用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,腾讯云高级开发工程师,负责移动客户端开发 最近抖音最近又带了一波合唱的节奏,老 ...
随机推荐
- (转)nio 连网和异步 I/O
连网和异步 I/O 概述 连网是学习异步 I/O 的很好基础,而异步 I/O 对于在 Java 语言中执行任何输入/输出过程的人来说,无疑都是必须具备的知识.NIO 中的连网与 NIO 中的其他任何操 ...
- 加加减减(你真的懂++--吗) C#
目录 TOC \o "1-3" \h \z \u 自增量. PAGEREF _Toc456268662 \h 1 08D0C9EA79F9BACE118C8200AA004BA9 ...
- [Android] SQLite数据库之增删改查基础操作
在编程中常常会遇到数据库的操作,而Android系统内置了SQLite,它是一款轻型数据库,遵守事务ACID的关系型数据库管理系统,它占用的资源非常低,可以支持Windows/Linux/Un ...
- 【php】在php代码嵌入HTML代码(适用于公众号开发)
核心:HTML的双引号["]一定要转义,不废话: $link = "<a href=\"http://www.baidu.com\">最新活动链接& ...
- 《转》oracle—flashback
FLASHBACK介绍 在介绍flashback之前先介绍下undo_retention相关参数 undo_retention:表示undo数据的过期时间.系统默认这个时间设置为900即15分钟.但要 ...
- canvas学习笔记(中篇) -- canvas入门教程-- 颜色/透明度/渐变色/线宽/线条样式/虚线/文本/阴影/图片/像素处理
[中篇] -- 建议学习时间4小时 课程共(上中下)三篇 此笔记是我初次接触canvas的时候的学习笔记,这次特意整理为博客供大家入门学习,几乎涵盖了canvas所有的基础知识,并且有众多练习案例, ...
- 使用httpModules做一些事
httpmodules是http管道处理程序 可以重写接口进行一些在请求到达api接口前做全局处理 这是一个过滤关键词的例子 using System; using System.Collection ...
- 自制MVC框架的插件与拦截器基础
上篇谈到我自己写的MVC框架,接下来讲讲插件及拦截器! 在处理一些通用的逻辑最好把它封装一个插件或者拦截器,以便日后可以直接拿过来直接使用.在我的框架中可以通过继承以下抽象类来实现插件或者拦截器. 1 ...
- python selenium --处理下拉框
下拉框是我们最常见的一种页面元素,对于一般的元素,我们只需要一次就定位,但下拉框里的内容需要进行两次定位,先定位到下拉框,再定位到下拉框内里的选项. drop_down.html <html&g ...
- python 高级语法
#coding:utf-8 #定义一个装饰器函数 def doc_func(func): #包裹函数(闭包) def warpfunc(): #做一些额外的事情 print "%s call ...