最近用ffmpeg解码H264裸码流文件,发现解码总是少几帧。上网查了些资料,解决了。

当使用avcodec_decode_video2时,如果第三个参数的值为1,则表示完成一帧的解码,如果为0,表示没有解码完成。此时需要计算未解码的帧数,以便再次调用avcodec_decode_video2函数。如下getFrame函数,当解码成功一帧时返回,如果没有解码,则累加。另外实现getSkippedFrame函数,将之前未解码的数据再次解码。

代码如下:

int CH264Decoder::getFrame(unsigned char** yuvBuffer, unsigned char** rgbBuffer, int* size, int* width, int* height)
{int got_picture = 0;    // 找到帧标志int len = 0;AVPacket avpkt;av_init_packet(&avpkt);//int frame = 0;// av_read_fram返回下一帧,发生错误或文件结束返回<0while (av_read_frame(m_fmtctx, &avpkt) >= 0){// 解码视频流if (avpkt.stream_index == m_videoStream){len = avcodec_decode_video2(m_avctx, m_picture, &got_picture, &avpkt);if (len < 0){debug("error while decoding frame.\n");return -1;}if (got_picture){m_picWidth  = m_avctx->width;m_picHeight = m_avctx->height;// 传出原始数据指针,由于内部已经申请了,不用再开辟数据if (yuvBuffer != NULL){*yuvBuffer = m_picture->data[0];if (size != NULL){*size = len; // to check}}if (rgbBuffer != NULL){*rgbBuffer = convertToRgb();if (size != NULL){*size = m_picWidth * m_picHeight * 3; // 上面指定了rgb24,所以是w*h*3}}//printf("frame fmt: %d\n", m_picture->format);if (width != NULL){*width = m_picWidth;}if (height != NULL){*height = m_picHeight;}//printf("bit_rate: %d width: %d height:%d\n", m_avctx->bit_rate, m_avctx->width, m_avctx->height);return 1;} // end of got pictureelse{m_skippedFrame++;//debug("skipped count: %d\n", m_skippedFrame);}} // end of video streamav_free_packet(&avpkt);} // end of read framereturn 0;
}

上面的函数已经统计了缓存起来的帧总数,下面根据m_skippedFrame的值再调用avcodec_decode_video2解码。

int CH264Decoder::getSkippedFrame(unsigned char** yuvBuffer, unsigned char** rgbBuffer, int* size, int* width, int* height)
{int got_picture = 0;    // 找到帧标志int len = 0;AVPacket avpkt;memset(&avpkt, '\0', sizeof(AVPacket));av_init_packet(&avpkt);// 是否还有缓存的帧while (m_skippedFrame-- > 0){// 注:avpkt要清空data和size,否则无法解码avpkt.data = NULL;avpkt.size = 0;// 解码视频流len = avcodec_decode_video2(m_avctx, m_picture, &got_picture, &avpkt);if (len < 0){debug("error while decoding frame.\n");return -1;}if (got_picture){// 传出原始数据指针,由于内部已经申请了,不用再开辟数据if (yuvBuffer != NULL){*yuvBuffer = m_picture->data[0];}if (rgbBuffer != NULL){*rgbBuffer = convertToRgb();}//printf("frame fmt: %d\n", m_picture->format);if (size != NULL){*size = len;}m_picWidth  = m_avctx->width;m_picHeight = m_avctx->height;if (width != NULL){*width = m_picWidth;}if (height != NULL){*height = m_picHeight;}//printf("bit_rate: %d width: %d height:%d\n", m_avctx->bit_rate, m_avctx->width, m_avctx->height);return 1;} // end of got pictureav_packet_unref(&avpkt);} // end of read framereturn 0;
}

2016.4.23 周日的补充:

注意,在调用avcodec_decode_video2对缓存的帧解码时,一定要将avpkt.data置为NULL,并将avpkt.size置为0,否则会解码不成功。在调用av_init_packet前,也要手工对AVPacket结构体进行清零操作。直到最后在VS环境使用该类时才发现这个问题。在解码函数avcodec_decode_video2注释中有如下说明:

* @note Codecs which have the CODEC_CAP_DELAY capability set have a delay
 * between input and output, these need to be fed with avpkt->data=NULL,
 * avpkt->size=0 at the end to return the remaining frames.

李迟 2015.12.12 中午

ffmpeg解码H264缺少帧的解决办法相关推荐

  1. (转)FFMPEG解码H264拼帧简解

    http://blog.csdn.net/ikevin/article/details/7649095 H264的I帧通常 0x00 0x00 0x00 0x01 0x67 开始,到下一个帧头开始之前 ...

  2. ffmpeg 切片花屏_利用ffmpeg解码H264,花屏,该如何解决

    利用ffmpeg解码H264,花屏 UINT CMP4File::VideoCap_Thread_Fun(void* pParam) { CMP4File  *pMP4File=(CMP4File*) ...

  3. python2发送http不编码_[转]Python 2.x中常见字符编码和解码方面的错误及其解决办法...

    Python 2.x中的字符编码,设计的的确不好,导致初学者,甚至是即使用Python很长时间的人,都会经常遇到字符编解码方面的错误. 下面就把一些常见情,尽量的都整理出来,并给出相应的解决办法. 看 ...

  4. linux安装之后缺少命令,CentOS7安装成功后缺少命令的解决办法

    CentOS 是一个基于Red Hat Linux 提供的可自由使用源代码的企业级Linux发行版本.每个版本的 CentOS都会获得十年的支持(通过安全更新方式).接下来是小编为大家收集的CentO ...

  5. win11右键菜单缺少“新建“选项解决办法“

    亲测这个是最好用的,那个修改..docx的什么操作尝试了八百遍都不行 原文链接 (4条消息) win11右键菜单缺少"新建"选项解决办法_Hrrington的博客-CSDN博客

  6. 计算机中丢失openal32.dll无法启动游戏,缺少openal32period;dll 解决办法 | 手游网游页游攻略大全...

    发布时间:2015-10-09 文明太空玩家将扮演成为探索某星球的第一人,在这段奇妙的旅程中我们能看见很多没有见过的美景和各种神迹,各位玩家是否已经忍不住要去探索了呢. 今天我们一起来看一下文明太空缺 ...

  7. apex服务器不稳定,apex英雄掉帧不稳定怎么办-apex英雄掉帧不稳定解决办法_牛游戏网...

    apex英雄中出现掉帧不稳定的情况要怎么办,很多的小伙伴可能都不太了解,下面牛游戏小编就为你们带来了<apex英雄>掉帧不稳定解决办法,想了解的小伙伴就一起来了解一下吧,说不定正好是对你们 ...

  8. Mac - eclipse中缺少project facets解决办法

    Mac - eclipse中缺少project facets解决办法 在2021新版的eclipse中,缺少Project Facets 选项,需要我们手动进行相关插件的安装 解决方法 1.在Help ...

  9. FFmpeg解码H264裸流并转换成opencv Mat

    感谢雷霄骅博士的在中文视频编解码的付出,http://blog.csdn.net/leixiaohua1020 最近要搞一些视频推流的事情,要解析H264裸流并且获取opencv格式的Mat数据给算法 ...

最新文章

  1. ROS nodelet的使用
  2. 精美图文讲解Java AQS 共享式获取同步状态以及Semaphore的应用
  3. java基础(5)----面向对象
  4. Indy10中IdMappedPortTCP的用法
  5. BitcoinCore JSONRPC Java使用,创建账号,获取余额,转账等等...
  6. Opportunity workflow debug
  7. Android---什么是3G
  8. 【前沿】PurdueUCLA提出梯度Boosting网络,效果远好于XGBoost模型!
  9. ASP.NET MVC3 RenderPartial 传入空Model时出现字典类型错误
  10. 多元统计分析假设检验
  11. 欧姆龙nj与nx哪个高端_没想到还有比三菱更垃圾的PLC,欧姆龙隆重登场
  12. C#中SqlParameter的作用与用法
  13. AutoRunner检查点之校验属性
  14. 网站运行原理及开发流程
  15. Python线图点图--matplotlib.pyplot.plot
  16. 一名普通医护人员的抗疫日志
  17. Python爬取股票数据存入mysql数据库,获取股票(最新、最高、今开、成交量、成交额、量比、换手率、涨幅等)支持多线程+数据库连接池
  18. Linux Centos7 搭建简易堡垒机安装jailkit实现chroot
  19. Keycloak实现手机验证码登录
  20. Mysql查询当年去年当月上月

热门文章

  1. 创业要有创意--应当注意的八大细节
  2. 情景喜剧消亡史:人人都爱,没人敢拍
  3. 智商税?苹果1.8米连接线卖949元、3米的1169元被吐槽:高攀不起
  4. 国庆假期带动新能源汽车消费热潮
  5. TikTok全球月活突破10亿
  6. “滴血验癌”?昔日“女乔布斯”被控诈骗!身价估值从290亿元直降为0!或面临20年刑期...
  7. 饿了么上架iPhone 12:最快花呗10分钟拿到手
  8. 做中国女人难,做中国女装更难
  9. B站发布2020年一季度财报:月活用户达1.72亿,日活用户突破5000万
  10. 前魅族副总裁李楠上手魅族17:颜值提升了