用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,腾讯云高级开发工程师,负责移动客户端开发 最近抖音最近又带了一波合唱的节奏,老 ...
随机推荐
- JSP中的TAG文件和TLD文件小结
在jsp文件中,可以引用tag和tld文件. 1.对于tag文件 <%@ taglib prefix="ui" tagdir="/WEB-INF/tags" ...
- Android Studio 项目中集成百度地图SDK报Native method not found: com.baidu.platform.comjni.map.commonmemcache.JNICommonMemCache.Create:()I错误
Android Studio 项目中集成百度地图SDK报以下错误: java.lang.UnsatisfiedLinkError: Native method not found: com.baidu ...
- 浅析SQL Server中的执行计划缓存(上)
简介 我们平时所写的SQL语句本质只是获取数据的逻辑,而不是获取数据的物理路径.当我们写的SQL语句传到SQL Server的时候,查询分析器会将语句依次进行解析(Parse).绑定(Bind).查询 ...
- iOS UITapGestureRecognizer手势和UIButton 以及UITabelView点击事件冲突
一:在同一个view上加载,UITapGestureRecognizer手势,UIButton 行为,UITabelView点击事件冲突: 二:解决方式: 在UITapGesttureRecogniz ...
- windows print 自定义字体颜色【python】
windows print 自定义字体颜色 import ctypes STD_INPUT_HANDLE = -10 STD_OUTPUT_HANDLE= -11 STD_ERROR_HANDLE = ...
- Bootstrap学习 进度条
本文将介绍Bootstrap进度条,在本文中你将看到如何使用Bootstrap创建加载,重定向或动作状态的进度条 bootstrap进度条使用CSS3过渡和动画来获得该效果.Internet Expl ...
- android 中的 Handler 线程间通信
一. 在MainActivity中为什么只是类似的写一行如下代码就可以使用handler了呢? Handler handler = new Handler() { @Override public v ...
- Shell编程二
告警系统需求分析 1.(虽然之前我们学习了zabbix,但有时候也不能满足我们的需求,比如比较冷门的监控项目需要写自定义脚本,或者服务器网络有问题,没有办法将客户端的数据发送到服务端.) 程序架构: ...
- homebrew osx下面最优秀的包管理工具
官方网站:https://brew.sh/index_zh-cn 安装 /usr/bin/ruby -e "$(curl -fsSL https://raw.githubuserconten ...
- C 语言 ioctl
/* *@author cody *@date 2014-08-12 *@description */ /* #include <sys/ioctl.h> send control and ...