前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android FFmpeg系列03--视频解码与渲染

Android FFmpeg系列03--视频解码与渲染

作者头像
雪月清
发布2022-09-21 14:53:27
8450
发布2022-09-21 14:53:27
举报
文章被收录于专栏:雪月清的随笔雪月清的随笔

在前面的文章中讲述了FFmpeg的编译&集成和音视频的一些基础概念

Android FFmpeg系列01--编译与集成

Android FFmpeg系列02--音视频基础

本文为FFmpeg系列的第三篇文章,主要内容为利用FFmpeg解码本地mp4文件的视频流并利用OpenGL进行上屏渲染

FFmpeg视频解码

一个音视频文件的播放流程大致需要经历解封装->解码->音视频同步->数据消费几个步骤,如下图所示

解封装并查找视频流

查找解码器并打开

循环解码

核心代码

代码语言:javascript
复制
// 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比系统时钟晚的情况等待

代码语言:javascript
复制
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可以参考之前的两篇文章,这里就不赘述~

如何使用OpenGL渲染YUV数据

Android中如何使用OpenGL播放视频

Demo

https://github.com/sifutang/ffmpeg-demo

点击屏幕左右滑动会将视频划分为gray处理和原视频

~~END~~

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-08-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 雪月清的随笔 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档