用JavaCV改写“100行代码实现最简单的基于FFMPEG+SDL的视频播放器 ”
FFMPEG的文档少,JavaCV的文档就更少了。从网上找到这篇100行代码实现最简单的基于FFMPEG+SDL的视频播放器。地址是http://blog.csdn.net/leixiaohua1020/article/details/8652605。
用JavaCV重新实现并使用opencv_highgui进行显示。
import com.googlecode.javacpp.IntPointer;
import com.googlecode.javacpp.Pointer;
import com.googlecode.javacv.cpp.avcodec;
import com.googlecode.javacv.cpp.avcodec.AVPacket;
import com.googlecode.javacv.cpp.avcodec.AVPicture;
import com.googlecode.javacv.cpp.avformat;
import com.googlecode.javacv.cpp.avutil;
import com.googlecode.javacv.cpp.avutil.AVDictionary;
import com.googlecode.javacv.cpp.opencv_core;
import static com.googlecode.javacv.cpp.opencv_core.IPL_DEPTH_8U;
import com.googlecode.javacv.cpp.opencv_core.IplImage;
import static com.googlecode.javacv.cpp.opencv_core.cvSize;
import com.googlecode.javacv.cpp.opencv_highgui;
import static com.googlecode.javacv.cpp.opencv_highgui.cvDestroyWindow;
import static com.googlecode.javacv.cpp.opencv_highgui.cvNamedWindow;
import com.googlecode.javacv.cpp.swscale;
import com.googlecode.javacv.cpp.swscale.SwsContext; /**
*
* @author cuizhenfu@gmail.com
*/
public class DecodingH264 { public static void main(String[] args) {
String filePath = "Images/butterfly.h264"; // Register all formats and codes
avformat.av_register_all();
avcodec.avcodec_register_all(); // Open video file
avformat.AVFormatContext formatCtx = avformat.avformat_alloc_context();
if (avformat.avformat_open_input(formatCtx, filePath, null, null) != 0) {
System.out.println("无法打开文件\n");
return;
} if (avformat.avformat_find_stream_info(formatCtx, (AVDictionary) null) < 0) {
System.out.println("Couldn't find stream information.\n");
return;
}
int videoIndex = -1;
for (int i = 0; i < formatCtx.nb_streams(); i++) {
if (formatCtx.streams(i).codec().codec_type() == avutil.AVMEDIA_TYPE_VIDEO) {
videoIndex = i;
break;
}
} if (videoIndex == -1) {
System.out.println("Didn't find a video stream.\n");
return;
} avcodec.AVCodecContext codecCtx = formatCtx.streams(videoIndex).codec();
avcodec.AVCodec codec = avcodec.avcodec_find_decoder(codecCtx.codec_id());
if (codec == null) {
System.out.println("Codec not found.\n");
return;
} if (avcodec.avcodec_open2(codecCtx, codec, (AVDictionary) null) < 0) {
System.out.println("Could not open codec.\n");
} avutil.AVFrame frame = avcodec.avcodec_alloc_frame();
avutil.AVFrame frameRGB = avcodec.avcodec_alloc_frame(); // 注意AVPicture的构造方法,参考http://blog.csdn.net/wahrlr/article/details/21970755
// 注意avutil.av_malloc的返回值(用Pointer代替uint8_t*)
int nunBytes = avcodec.avpicture_get_size(avutil.AV_PIX_FMT_RGB24, codecCtx.width(), codecCtx.height());
Pointer outBuffer = avutil.av_malloc(nunBytes);
avcodec.avpicture_fill(new AVPicture(frameRGB), outBuffer.asByteBuffer(), avutil.AV_PIX_FMT_RGB24, codecCtx.width(), codecCtx.height()); avformat.av_dump_format(formatCtx, 0, filePath, 0); SwsContext img_convert_ctx = swscale.sws_getContext(codecCtx.width(), codecCtx.height(), codecCtx.pix_fmt(), codecCtx.width(), codecCtx.height(), avutil.AV_PIX_FMT_RGB24, swscale.SWS_BICUBIC, null, null, (double[])null); AVPacket packet = new AVPacket();
int y_size = codecCtx.width() * codecCtx.height();
avcodec.av_new_packet(packet, y_size);
cvNamedWindow("butterfly.h264");
IplImage showImage = opencv_core.cvCreateImage(cvSize(codecCtx.width(),codecCtx.height()), IPL_DEPTH_8U, 3);
while(avformat.av_read_frame(formatCtx, packet) >= 0) {
if(packet.stream_index() == videoIndex) {
IntPointer ip = new IntPointer();
int ret = avcodec.avcodec_decode_video2(codecCtx, frame, ip, packet);
if(ret < 0) {
System.out.println("解码错误");
return;
}
if(ip.get() != 0) {
swscale.sws_scale(img_convert_ctx, frame.data(), frame.linesize(), 0, codecCtx.height(), frameRGB.data(), frameRGB.linesize()); showImage.imageData(frameRGB.data(0));
showImage.widthStep(frameRGB.linesize().get(0)); opencv_highgui.cvShowImage("butterfly.h264", showImage);
opencv_highgui.cvWaitKey(25);
}
}
avcodec.av_free_packet(packet);
} showImage.release();
cvDestroyWindow("butterfly.h264");
avutil.av_free(frameRGB);
avcodec.avcodec_close(codecCtx);
avformat.avformat_close_input(formatCtx);
} }
用JavaCV改写“100行代码实现最简单的基于FFMPEG+SDL的视频播放器 ”的更多相关文章
- 100行代码实现最简单的基于FFMPEG+SDL的视频播放器(SDL1.x)【转】
转自:http://blog.csdn.net/leixiaohua1020/article/details/8652605 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] ...
- 【转】100行代码实现最简单的基于FFMPEG+SDL的视频播放器
FFMPEG工程浩大,可以参考的书籍又不是很多,因此很多刚学习FFMPEG的人常常感觉到无从下手.我刚接触FFMPEG的时候也感觉不知从何学起. 因此我把自己做项目过程中实现的一个非常简单的视频播放器 ...
- 100行代码实现现代版Router
原文:http://www.html-js.com/article/JavaScript-version-100-lines-of-code-to-achieve-a-modern-version ...
- 100行代码让您学会JavaScript原生的Proxy设计模式
面向对象设计里的设计模式之Proxy(代理)模式,相信很多朋友已经很熟悉了.比如我之前写过代理模式在Java中实现的两篇文章: Java代理设计模式(Proxy)的四种具体实现:静态代理和动态代理 J ...
- GuiLite 1.2 发布(希望通过这100+行代码来揭示:GuiLite的初始化,界面元素Layout,及消息映射的过程)
经过开发群的长期验证,我们发现:即使代码只有5千多行,也不意味着能够轻松弄懂代码意图.痛定思痛,我们发现:虽然每个函数都很简单(平均长度约为30行),可以逐个击破:但各个函数之间如何协作,却很难说明清 ...
- 【编程教室】PONG - 100行代码写一个弹球游戏
大家好,欢迎来到 Crossin的编程教室 ! 今天跟大家讲一讲:如何做游戏 游戏的主题是弹球游戏<PONG>,它是史上第一款街机游戏.因此选它作为我这个游戏开发系列的第一期主题. 游戏引 ...
- 100行代码实现HarmonyOS“画图”应用,eTS开发走起!
本期我们给大家带来的是"画图"应用开发者Rick的分享,希望能给你的HarmonyOS开发之旅带来启发~ 介绍 2021年的华为开发者大会(HDC2021)上,HarmonyOS ...
- 100 行代码实现的 JavaScript MVC 样式框架
介绍 使用过 JavaScript框架(如 AngularJS, Backbone 或者Ember)的人都很熟悉在UI(用户界面,前端)中mvc的工作机理.这些框架实现了MVC,使得在一个单页面中实现 ...
- 100行代码搞定抖音短视频App,终于可以和美女合唱了。
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由视频咖 发表于云+社区专栏 本文作者,shengcui,腾讯云高级开发工程师,负责移动客户端开发 最近抖音最近又带了一波合唱的节奏,老 ...
随机推荐
- Spring框架学习(9)AOP技术理解与使用
内容源自:AOP技术理解与使用 一.什么是AOP? aop技术是面向切面编程思想,作为OOP(面向对象编程)的延续思想添加到企业开发中,用于弥补OOP开发过程中的缺陷而提出的编程思想. AOP底层也是 ...
- 读书笔记--MapReduce 适用场景 及 常见应用
原文:http://blog.csdn.net/smile0198/article/details/20578389 1.MR解决的问题的特点 MR是应大数据的背景产生,其解决的问题的共性为:大问 ...
- sdut 3-7 类的友元函数的应用
3-7 类的友元函数的应用 Time Limit: 1000MS Memory limit: 65536K 题目描写叙述 通过本题目的练习能够掌握类的友元函数的定义和使用方法 要求设计一个点类Poin ...
- [Functional Programming Monad] Refactor Stateful Code To Use A State Monad
When we start to accumulate functions that all work on a given datatype, we end up creating a bunch ...
- C# 和 Java的区别积累
1.类的继承 A.C#用 ":"符号: B.Java用关键字 extends: 2.接口的实现 A.C#用 ":"符号: B.Java用关键字 implemen ...
- 两种方法连接MySql数据库
.用MySQLDriverCS连接MySQL数据库 先下载和安装MySQLDriverCS,在安装文件夹下面找到MySQLDriver.dll,然后将MySQLDriver.dll添加引用到项目中. ...
- ant font 本地化
要解决的问题1.antd默认iconfont指向的是阿里在公网CDN上部署的url 2.项目需要在本地进行部署,使用的是本地文件的访问方式,希望能内网/离线使用 在ant-design-pro中的配置 ...
- android与服务端通讯时使用到的GZIP压缩及解压
为了减小android项目与服务端进行通讯时的数据流量,我们可以使用GZIP对服务端传输的数据进行压缩,在android客户端解压.或在客户端压缩,在服务端解压.代码如下: android客户端的GZ ...
- 理解Linux系统中的load average
理解Linux系统中的load average(图文版) 博客分类: Linux linux load nagios 一.什么是load average? linux系统中的Load对当前CPU工作 ...
- javascript常量的定义
例如可以使用 const PI = 3.14159265; 一般不推荐使用 const 关键字,因为它不是 ECMAScript 语法的一部分.当需要常量的时候一般是以命名习惯来约束的,亦即使用大写字 ...