`

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

 
阅读更多

使用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);
    }
}


原文地址:http://blog.yikuyiku.com/?p=3486

分享到:
评论

相关推荐

    avcodec_sample.rar_DEMO

    5. **读取/写入数据**:在解码过程中,使用`av_read_frame`从输入文件中读取一帧数据,然后调用`avcodec_decode_video2`或`avcodec_decode_audio4`进行解码。在编码过程中,将原始数据送入`avcodec_encode_video2`或...

    ffmpeg视频转换截图源码

    - 解码后的帧通过 `avcodec_encode_video2` 使用编码器编码为新的格式,最后 `av_interleaved_write_frame` 将编码后的数据写入输出文件。 3. **视频截图**: - 截图功能主要涉及解码视频帧。可以使用 `av_read_...

    android FFmpeg视频解码为YUV像素数据视频文件以及获取视频基本参数信息

    1. **旧API**:使用`avcodec_decode_video2`进行解码,需要先发送编码数据包到解码器,然后通过此函数接收解码后的AVFrame。解码后的AVFrame包含了视频帧的数据,可以是YUV、RGB等格式。 2. **新API**:在新API中,...

    内存H264+PCM发布rtmp.rar

    使用FFmpeg API可以简化多媒体处理的复杂性,比如使用`avcodec_decode_video2()`解码H264数据,`avcodec_encode_audio2()`编码PCM数据,`avformat_write_header()`和`av_interleaved_write_frame()`写入FLV容器。...

    ffmpeg使用dxva2硬解码DEMO(vs2010)

    在你的Win32Project1工程中,你需要找到视频解码的部分,通常是通过调用`avcodec_open2()`函数初始化解码器,并使用`avcodec_decode_video2()`函数进行解码。为了启用DXVA2硬件加速,你需要在调用`avcodec_open2()`...

    FFmpeg视频解码为逐帧数据

    然后调用`avcodec_decode_video2`函数进行解码,此函数会返回解码后的数据是否成功。如果成功,`pFrame`参数会指向解码出的AVFrame结构体,包含了解码后的像素数据。 解码后的每一帧可能包括多个颜色平面(如YUV420...

    用Ffmpeg进行h265编解码的实例

    调用`avcodec_open2()`初始化解码器,之后可以使用`avcodec_decode_video2()`对解码后的像素数据进行解包。 3. **Encoding(编码)**:如果需要重新编码,过程与解码类似,但这里使用的是编码器。`avcodec_find_...

    FFmpeg_08_解码及逐帧编码

    一旦准备就绪,可以使用`avcodec_decode_video2()`或`avcodec_decode_audio4()`函数进行实际的解码操作,将字节流解码为`AVFrame`结构,其中包含了视频帧的数据。 逐帧编码,顾名思义,是指对视频的每一帧进行独立...

    FFmpeg如何同步音视频的解决方案

    例如,我们可以使用avcodec_decode_video()函数来解码视频帧,并使用av_read_frame()函数来读取音频帧。 FFmpeg提供了一个强大的解决方案来实现音视频同步。在Android客户端中,我们可以使用FFmpeg来实现音视频同步...

    FFMPEG_apiexample.c_随机

    接着,使用 `avcodec_decode_video2()` 函数解码 NAL 单元,获取到解码后的 YUV 帧。解码完成后,关闭解码器。 在 `FFMPEG_apiexample.c` 示例中,源代码可能保持了 FFmpeg API 的基本结构,没有进行大规模修改,...

    ios-集成ffmpeg解码视频.zip

    接着,使用`avcodec_decode_video2`解码每一帧数据。 4. 图像渲染:解码后的数据是YUV格式,可以使用OpenGL ES或Metal进行渲染。 四、音频解码 1. 类似视频解码,首先找到音频流,然后获取解码器。 2. 创建解码器上...

    ff_test_stream.rar_C ffmpeg h264_ffmpeg_ffmpeg解码h264流_h264流 解码

    4. 解码NAL单元:调用`avcodec_decode_video2()`或`avcodec_send_packet()`和`avcodec_receive_frame()`这两个函数交替进行,将NAL单元送入解码器并接收解码后的帧。 5. 处理解码结果:解码成功后,`AVFrame`结构体...

    ffmpeg制作的超精简视频播放器(含超详细注释) 在6410上可用

    在循环中,调用av_read_frame()读取一帧数据,avcodec_decode_video2()解码视频帧,然后显示到屏幕上。 4. 解码与渲染:FFmpeg的avcodec_decode_video2()函数将编码后的数据解码为原始像素数据。解码后的帧可能是...

    avcodec-58.zip

    在使用avcodec-58.dll时,开发者需要熟悉FFmpeg的API接口,如avcodec_find_decoder()来寻找解码器,avcodec_open2()来初始化解码器,并通过avcodec_decode_video2()或avcodec_decode_audio4()进行解码操作。...

    简单的FFmpeg解码,OpenCV显示

    这通常通过读取AVPacket(封装了音视频数据的结构体)并调用`avcodec_decode_video2()`函数实现。 ```c++ AVPacket pkt; av_init_packet(&pkt); while (av_read_frame(fmt_ctx, &pkt) >= 0) { if (pkt.stream_...

    output_example.rar_FFmpeg解码_ffmpeg_ffmpeg 编译_output exmple_outpu

    5. **解码数据**:循环读取输入流的packet(`av_read_frame()`),然后使用`avcodec_decode_video2()`或`avcodec_decode_audio4()`进行解码。 6. **处理解码后的数据**:解码成功后,会返回解码后的AVFrame,从中...

    ffmpeg的tutorial中文版完美版+源码

    - avcodec_decode_audio4或avcodec_decode_video2:对数据包进行解码。 - av_frame_free:释放不再需要的AVFrame资源。 4. **教程04.c**: - 音视频帧处理:讲解如何处理解码后的音视频帧,包括显示、播放或...

    FFmpeg_04_视频流解码

    解码过程由`avcodec_decode_video2()`函数完成,它会将编码的视频帧解码成AVFrame结构体。需要注意的是,解码并不总是成功,因此需要检查返回值并处理解码错误。 解码后的AVFrame包含了原始的像素数据,可以进一步...

    simplest_ffmpeg_decoder.zip_FFmpeg解码_ffmpeg_ffmpeg visual c_ffmp

    解码过程由`avcodec_decode_video2`或`avcodec_send_packet/avcodec_receive_frame`完成。前者是旧版接口,后者是新版本的异步解码方式。在解码过程中,需要不断向解码器发送编码的`AVPacket`,并接收解码后的`...

    C++源码 使用Ffmpeg 获取 视频流中的关键帧

    4. 解码关键帧:使用`avcodec_decode_video2`进行解码,得到解码后的像素数据。 5. 渲染或保存:根据需求,可以将解码后的关键帧显示在屏幕上或者保存为图片文件。 6. 清理:使用`avcodec_close`关闭解码器,`...

Global site tag (gtag.js) - Google Analytics