Android FFmpeg系列03--视频解码与渲染
Android 视频 系列 -- 渲染 03 解码 FFMPEG
2023-06-13 09:13:01 时间
在前面的文章中讲述了FFmpeg的编译&集成和音视频的一些基础概念
本文为FFmpeg系列的第三篇文章,主要内容为利用FFmpeg解码本地mp4文件的视频流并利用OpenGL进行上屏渲染
FFmpeg视频解码
一个音视频文件的播放流程大致需要经历解封装->解码->音视频同步->数据消费几个步骤,如下图所示
解封装并查找视频流
查找解码器并打开
循环解码
核心代码
// step1: alloc format context
mFtx = avformat_alloc_context();
// step2: open input file
avformat_open_input(&mFtx, path.c_str(), nullptr, nullptr);
// step3: find video stream index
avformat_find_stream_info(mFtx, nullptr);
int videoIndex = -1;
for (int i = 0; i < mFtx->nb_streams; i++) {
if (mFtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoIndex = i;
break;
}
}
// step4: find decoder and open
mVideoCodec = avcodec_find_decoder(codecParameters->codec_id);
mVideoCodecContext = avcodec_alloc_context3(mVideoCodec);
avcodec_parameters_to_context(mVideoCodecContext, codecParameters);
avcodec_open2(mVideoCodecContext, mVideoCodec, nullptr);
// steop5: loop decode
while (true) {
av_read_frame(mFtx, avPacket);
// ....
avcodec_send_packet(mVideoCodecContext, avPacket);
// ....
avcodec_receive_frame(mVideoCodecContext, avFrame);
// ....
sws_scale(...);
// ....
// clock sync and doRender
// ....
}
时钟同步
每解码一帧就渲染上屏的话,可以发现视频播放就像按了快进键一样画面飞速闪过,要让画面正常速率显示的话就需要做时钟同步了,按照视频帧的pts来渲染这一帧
因为Demo只解码视频流上屏,所以时钟肯定就是参考系统时钟了,这里我们只是在pts比系统时钟晚的情况等待
auto pts = avFrame->best_effort_timestamp;
// s -> us
pts = pts * av_q2d(mFtx->streams[mVideoDecoder->getStreamIndex()]->time_base) * 1000 * 1000;
int64_t elapsedTime;
if (mStartTime < 0) {
mStartTime = av_gettime();
elapsedTime = 0;
} else {
elapsedTime = av_gettime() - mStartTime;
}
int64_t diff = pts - elapsedTime;
if (diff > 0) {
av_usleep(diff);
}
OpenGL渲染
解码出来的AVFrame经过sws context后统一转为YUV420P格式,然后抛到java层上传纹理并渲染
OpenGL如何渲染YUV buffer可以参考之前的两篇文章,这里就不赘述~
Demo
https://github.com/sifutang/ffmpeg-demo
点击屏幕左右滑动会将视频划分为gray处理和原视频
~~END~~
相关文章
- android开机动画多长时间_Android开机动画原理分析
- 代码加密 android,Android 开发怎样做代码加密或混淆「建议收藏」
- android开发笔记之 Android代码混淆打包
- android onresume函数,android – 在Activity中重新创建后未调用onResume
- android listview更新数据
- android 安装p12证书,如何在Android中使用p12证书(客户端证书)
- android vlc 中文字幕,解决Android版vlc中文乱码问题
- 【Android布局】在程序中设置android gravity 和 android layout Gravity属性
- android广播注册方式_安卓广播接收器
- Android四大组件Broadcast中注册广播registerReceiver流程源代码详解
- Android保存图片到相册(适配android 10以下及以上)
- Android 列表视频
- 【Android FFMPEG 开发】FFMPEG 音视频同步 ( 音视频同步方案 | 视频帧 FPS 控制 | H.264 编码 I / P / B 帧 | PTS | 音视频同步 )
- 【Android RTMP】RTMPDump 封装 RTMPPacket 数据包 ( 关键帧数据格式 | 非关键帧数据格式 | x264 编码后的数据处理 | 封装 H.264 视频数据帧 )
- APKHunt:一款功能强大的Android应用程序静态代码分析工具
- 【Android 逆向】逆向修改游戏应用 ( APK 解析工具 | 解包 -> 分析 -> 重打包 -> 签名 流程 )
- 【错误记录】编译 Android 版本的 ijkplayer 报错 ( You must define ANDROID_NDK before starting. | 下载指定版本 NDK )
- 【Android UI】贝塞尔曲线 ④ ( 使用 android.graphics.Path 提供的 cubicTo 方法绘制三阶贝塞尔曲线示例 )
- 【错误记录】Android Studio 集成 ARoute 编译报错 ( 兼容 support 库和 androidx 库 | add ‘tools:replace=“android:appCo )
- Android开发中遇到的问题(三)——eclipse创建android项目无法正常预览布局文件详解手机开发
- android插件化之路详解手机开发
- android 播放视频详解手机开发
- Android开发艺术探索(三)——View的事件体系详解手机开发
- Android系统中MySQL数据库连接实现(安卓mysql连接)
- Android实现PHP连接MySQL进行数据交互(android通过php连接mysql)
- Android 开发必备知识:我和 Gradle 有个约会
- javascript判断iphone/android手机横竖屏模式的函数
- Android列表实现(1)_数组列表实例介绍
- android版本检测Android程序的版本检测与更新实现介绍
- Android中使用pull解析器操作xml文件的解决办法
- Android的ImageButton当显示Drawable图片时就不显示文字
- Android提高之蓝牙传感应用实例