如果我在FFmpeg中使用av_read_frame,则会丢失多个帧

pon*_*ish 4 c ffmpeg

我有一个3500帧的HEVC序列,我正在写一个解码器来读取它(逐帧读取并转储到yuv).在我的main()中,我有一个for循环调用一个解码器()3500次(我假设在这个阶段main()知道有多少帧).

因此,对于每次调用decoder(),我都需要返回一个完整的帧.这就是解码器()的样子.

bool decode(pFormatCtx, pCodecCtx)
{
    int gotaFrame=0;

    while (gotaFrame==0) {

        printf("1\t");

        if ( !av_read_frame(pFormatCtx, &packet) ) { 
            if(packet.stream_index==videoStreamIndex) {

                // try decoding
                avcodec_decode_video2(pCodecCtx, pFrame, &gotaFrame, &packet);

                if (gotaFrame) {  // decode success.

                    printf("2\t");

                    // dump to yuv ... not shown here. 

                    // cleanup
                    av_frame_unref(pFrame);
                    av_frame_free(&pFrame);
                    av_free_packet(&packet);

                    return true;
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

行为是这样的:1 1 1 1 1 1 1 1 1 1 1 1 2 1 2 1 2 ......在解码之前看起来好像读了几帧?第一帧是I帧,所以不应该立即解码?

使用此代码,我最终失去了几帧(由1系列表示).有人可以帮帮我吗?我的代码中有什么问题吗?

更新:测试片段仅限视频.没有音频.

sza*_*ary 9

你所看到的是正确的行为.解码器提供几帧以实现多线程效率.并且它可能需要几帧来"灌注泵".基本上,为了使您的程序保持响应,avcodec_decode_video2将帧排队等待解码,然后返回.这可以防止程序长时间阻塞.在B帧的情况下也绝对需要延迟解码,其中解码顺序可能与显示顺序不同.

那么,如何不丢失这些帧?在av_read_frame停止返回新帧之后,您必须通过使用空数据包调用avcodec_decode_video2来刷新解码器,直到不再重新调整帧为止.