使用libav转码视频时发现一个问题:使用下面这段代码解码视频时,视频尾巴上会丢掉几帧。
while(av_read_frame(ifmt_ctx,&packet) >= 0){ ret = avcodec_decode_video2(video_dec_ctx, vframe, &got_frame, &packet); if (got_frame) { packet.pts = av_rescale_q(packet.pts,video_dec_st->time_base,video_enc_st->time_base); write_video_frame(ofmt_ctx,video_enc_st,vframe); } }
这是因为源视频中PTS与DTS的不同造成的。
av_read_frame()按照PTS顺序读帧的时候,如果此帧需要参考后面的帧,那么此时avcodec_decode_video2()是没有能力解码此帧的,表现为got_frame返回0。
比如说遇上如下EFGH四帧:
ID :E F G H
KIND:I B P P
PTS : 1 2 3 4
DTS : 1 4 2 3
那么顺序读到F时,由于F需要参考G帧,而此时我们还没读到G帧,我们是没有解码F的能力的,got_frame就返回0了。如果我们对此事不做处理,那么我们就会丢掉一个帧(但丢掉的未必是F,因为av_read_frame()和avcodec_decode_video2()是1:1调用的)。
所以我们需要在while(av_read_frame())读完整个视频后,继续调用avcodec_decode_video2()把之前那些没有成功解码的帧都解出来。调用的次数就是之前got_frame返回0的次数。
按照上述思路变更代码为以下,成功找回丢失的帧。
int skipped_frame = 0; while(av_read_frame(ifmt_ctx,&packet) >= 0){ ret = avcodec_decode_video2(video_dec_ctx, vframe, &got_frame, &packet); if (got_frame) { packet.pts = av_rescale_q(packet.pts,video_dec_st->time_base,video_enc_st->time_base); write_video_frame(ofmt_ctx,video_enc_st,vframe); } else { skipped_frame++; } } for(int i=skipped_frame; i>0; i--) { ret = avcodec_decode_video2(video_dec_ctx, vframe, &got_frame, &packet); if (got_frame) { packet.pts = av_rescale_q(packet.pts,video_dec_st->time_base,video_enc_st->time_base); write_video_frame(ofmt_ctx,video_enc_st,vframe); } }
相关推荐
一个Ffmpeg库打开视频文件的例子,基本包含开发所需要的步骤,并详细说明其作用
ffmpeg例子.FFmpeg是一个集录制、转换、音/视频编码解码功能为一体的完整的开源解决方案。FFmpeg的开发是基于Linux操作系统,但是可以在大多数操作系统中编译和使用。
ffmpeg中使用libavcodec的一个例程,对开发ffmpeg的有帮助
(7) avcodec_decode_video() (8) av_free_packet() (9) av_free() 4. 文件操作: (1) avnew_steam() (2) av_read_frame() (3) av_write_frame() (4) dump_format() 5. 其他函数: (1) avpicture_deinterlace() (2) ...
(7) avcodec_decode_video() (8) av_free_packet() (9) av_free() 4. 文件操作: (1) avnew_steam() (2) av_read_frame() (3) av_write_frame() (4) dump_format() 5. 其他函数: (1) avpicture_deinterlace() (2) ...
VC6调用FFMPEG进行H264视频编码,代码大体流程: avcodec_init(); avcodec_register_all(); avcodec_find_encoder(CODEC_ID_H264); avcodec_alloc_context(); avcodec_alloc_frame(); avcodec_encode_video(c, outbuf,...
VS2010编译好的avcodec_sample.cpp,使用ffmpeg
利用ffmpeg 来读取视频,解压缩为一个个frame, 再利用ffmpeg 将frame 压缩成jpeg 格式存成图片. 对ffmpeg 的主要调用接口如下: 1. 打开一个文件进行解码的过程: //初始化 avformat_open_input() avformat_find_...
AV_SAMPLE_FMT_FLTP转为AV_SAMPLE_FMT_S16P(ffmpeg),在使用ffmpeg解码aac的时候,如果使用avcodec_decode_audio4函数解码,那么解码出来的会是AV_SAMPLE_FMT_FLTP 格式的数据( float, 4bit , planar), 如果我们希望...
avcodec 一个简单demo,可以支持本地文件的编解码
libavformat和libavcodec的简单应用
h263 codec, mpeg4, vc-1, h264. video decoder.
C:\MinGW\msys\1.0\home\Administrator\h264
2、兼容性问题已经验证,编码后的视频ffmpeg和各系统播放器都能正常解码;也不会出现首帧异常的情况; 3、在顺带验证mediacodec的硬解码过程中发现不少坑,计划后续将mediacodec硬解码方式从jni的方式改为直接native...
在工程中需要把所有的video修改成对应的解码文件Camer,缺少的库自行在ffmypeg下载。
Video_2016-10-26_094654附加源码调试失败案例
ffmpeg 在Mac下编译Android中需要的配置文件,注意配置文件中路径。编译前把configure,build_andriod_mac.sh替换即可,编译完成后在把Android.mk复制到Android目录下即可
avcodec-58.dll,有需要的自然懂,你不需要你就不用下载,这个资源不要钱,你要是觉得过意不去,帮我的博客点个赞就好了
c#对ffmpeg的封装,非常好用的多媒体编解码框架
一个简单的通过c++接口调用ffmpeg实现了读取一段视频并通过opencv显示出来,以及写入文档文件中