其实最初不是为了解决这个问题而来的,是Peter兄给我的提示解决另一个问题却让我误打误撞解决了另外一个问题之后也把这个隐藏了很久的bug找到(之前总是有一些特别短的视频产生不知所措还以为是视频素材本身有问题呢),今天真是收获颇丰啊,对libav的理解更深。

一直以来我的程序架构是让读一帧av_read_frame,然后去尝试根据packet的type类型分别去decode video或者audio,然而这样总是在视频的结尾会有许多帧丢失的问题,我找过avplay代码中似乎没找到我想象中的那种读packet完毕后特殊处理的代码。

一下log是我设置将其avcodec_decode_video2函数调用前后输出的pts、dts值(注:Frame:为decode之后,测试视频为纯视频无音频的文件),从图中可以看出来,开头为了顺序正确,libav暂存了9个packet,读packet完毕后,我当然不能就直接不管了,还是要将libav暂存的那些帧取出来才行。


    综上几点我认为是在调用avcodec_decode_video2函数的时候,函数内会去发现这个packet尚不足以解码下一帧的时候就会暂存packet在内部队列中(我自己给他们取的名字,望能理解),这样问题就来了,等到整个视频文件都读取完了,剩下libav内部存的packet还有一大堆没处理,我的架构又是要求函数直接向视频索取一帧,因此就需要在读新packet完毕后还 单独调用decode video函数或者decode audio函数来取出剩余的AVFrame。

为了这些bug我破例无耻的使用了goto语句:

首先定义了类成员变量,初始化都为false:

bool            _no_packet;   //代表是否还有packet
bool _end_video_frame; //代表是否video中的队列取出完毕
bool _end_audio_frame; //代表是否audio中的队列取出完毕
AVPacket packet = {};
while(true)
{
auto auto_releaser = std::shared_ptr<AVPacket>(&packet, [](AVPacket* p) { av_free_packet(p); });
int ret = av_read_frame(_context.get(), &packet);
if ( ret != )
{
_no_packet = true;
if(!_end_video_frame)
goto loop_end_video;
if(!_end_audio_frame)
goto loop_end_audio;
if(_end_video_frame && _end_audio_frame)
return false;
}
if(packet.stream_index == vstream_index)
{
loop_end_video:
int frame_finished = true;
if(avcodec_decode_video2(_vcodec, _decoded_frame, &frame_finished, &packet) < )
{
// 。。。。do something。。。
}
if(frame_finished)
{
//。。。。do something。。。
}
else
{
if(_no_packet)
_end_video_frame = true;
}
}
else if (packet.stream_index == astream_index && (type & MEDIA_AUDIO) != )
{
loop_end_audio:
int frame_finished;
if (avcodec_decode_audio4(_acodec, _decoded_frame, &frame_finished, &packet) < )
{
// 。。。。do something。。。
}
if(frame_finished)
{
//。。。。do something。。。
}
else
{
if(_no_packet)
_end_audio_frame = true;
}
}
}

有了这些跳转,就能完美的在read_frame完之后还继续decode为我所用。希望能帮助到与我遇到了相同问题的人。

再次感谢Peter~

关于ffmpeg(libav)解码视频最后丢帧的问题的更多相关文章

  1. avcodec_decode_video2()解码视频后丢帧的问题解决

    使用libav转码视频时发现一个问题:使用下面这段代码解码视频时,视频尾巴上会丢掉几帧. while(av_read_frame(ifmt_ctx,&packet) >= 0){ ret ...

  2. 学习FFmpeg API – 解码视频

    本文转载 视频播放过程 首先简单介绍以下视频文件的相关知识.我们平时看到的视频文件有许多格式,比如 avi, mkv, rmvb, mov, mp4等等,这些被称为容器(Container), 不同的 ...

  3. ffmpeg编解码视频导致噪声增大的一种解决方法

    一.前言 ffmpeg在视音频编解码领域算是一个比较成熟的解决方案了.公司的一款视频编辑软件正是基于ffmpeg做了二次封装,并在此基础上进行音视频的编解码处理.然而,在观察编码后的视频质量时,发现图 ...

  4. 【转】学习FFmpeg API – 解码视频

    ffmpeg是编解码的利器,用了很久,以前看过dranger 的教程,非常精彩,受益颇多,是学习ffmpeg api很好的材料.可惜的是其针对的ffmpeg版本已经比较老了,而ffmpeg的更新又很快 ...

  5. 【学习ffmpeg】打开视频文件,帧分析,并bmp保存关键帧

    http://www.tuicool.com/articles/jiUzua   http://blog.csdn.net/code_future/article/details/8646717 主题 ...

  6. FFMPEG学习----解码视频

    基础概念 我们平时看到的视频文件有许多格式,比如 avi, mkv, rmvb, mov, mp4等等,这些被称为容器(Container), 不同的容器格式规定了其中音视频数据的组织方式(也包括其他 ...

  7. FFmpeg解码视频帧为jpg图片保存到本地

    FFmpeg解码视频帧为jpg图片保存到本地 - CSDN博客 https://blog.csdn.net/qq_28284547/article/details/78151635

  8. Android 音视频深入 九 FFmpeg解码视频生成yuv文件(附源码下载)

    项目地址,求star https://github.com/979451341/Audio-and-video-learning-materials/tree/master/FFmpeg(MP4%E8 ...

  9. 视频编解码---x264用于编码,ffmpeg用于解码

    项目要用到视频编解码,最近半个月都在搞,说实话真是走了很多弯路,浪费了很多时间.将自己的最终成果记录于此,期望会给其他人提供些许帮助. 参考教程: http://ffmpeg.org/trac/ffm ...

随机推荐

  1. The Largest Generation (25)(BFS)(PAT甲级)

    #include<bits/stdc++.h>using namespace std;int n,m,l,t;int a[1307][137][67];int vis[1307][137] ...

  2. Trie[字典树] 数据结构及基本操作集

    #include <iostream> #include <stdio.h> #include <cstring> #include <algorithm&g ...

  3. rlwrap: command not found和解决linux下sqlplus 提供浏览历史命令行的功能

    rlwrap工具可以解决linux下sqlplus 提供浏览历史命令行的功能,和删除先前输入错误的字母等问题 1.安装 需要readline包 这个安装光盘就有 [root@asm RedHat]# ...

  4. Java基础--正则表达式的规则

    注意:正则表达式只关注格式是否正确,不关注内容是否有效. 一.字符集合, []表示一个字符. 1.[abc] :指a,b,c中的任意一个字符. 2.[^abc]:指除了a,b,c外的任意字符. 3.[ ...

  5. kuangbin专题十二 HDU1029 Ignatius and the Princess IV (水题)

    Ignatius and the Princess IV Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32767 K ( ...

  6. CF616D Longest k-Good Segment

    题目描述 给定一个包含\(n\)个整数的序列\(a\),\(0\le a_i \le 10^6\),询问不重复数字个数\(\le k\)的最长区间的左右端点.如果有多解输出任意一组. 输入输出格式 输 ...

  7. QT的学习

    背景 最近正忙着做一个项目,由于之前对面向对象编程了解的非常少,所以导致项目的代码有很多不太清楚:看到代码的时候整个人是懵的.所以在国庆期间,结合着大神的博客看了一下面向对象编程,并学习了开发GUI应 ...

  8. rsyslog服务器同步其他服务器上面应用日志(如mysql审计日志 、nginx日志)

    **环境说明**系统:ubuntu 14.04 (CentOS可以参考http://www.cnblogs.com/hanyifeng/p/5463338.html) rsyslog版本 :8.16. ...

  9. 插入po得到主键,插入sql得到主键

    import com.yd.common.data.CIPPageInfo; import com.yd.common.data.CIPReqCondition; import com.yd.comm ...

  10. 转 安装EBS前期检查工具 - RDA - Health Check / Validation Engine Guide

    http://blog.itpub.net/35489/viewspace-1295028/ 参考文档        RDA - Health Check / Validation Engine Gu ...