在循环中使用av_read_frame缓存AVFrames只获得最后几帧

Caching AVFrames using av_read_frame in a loop only get last couple of frames

本文关键字:最后 几帧 缓存 循环 av frame read AVFrames      更新时间:2023-10-16

我正在尝试使用opengl逐帧处理视频。我使用ffmpeg从视频文件中读取帧。

在开始处理帧之前,我想先读取一些帧并将其存储在内存中。因此,我尝试在while循环中使用av_read_frame,并将帧数据复制到数组中

但是,当我尝试显示这些帧时,我发现我只得到最后几帧。例如,如果我想缓存50帧,但我只能获得最后几帧(第45帧到第50帧)。

这是我用来缓存帧的代码:

void cacheFrames()
{
    AVPacket tempPacket;
    av_init_packet(&tempPacket);
    int i = 0;
    avcodec_flush_buffers(formatContext->streams[streamIndex] ->codec);
    codecContext = formatContext->streams[streamIndex] ->codec;
    while (av_read_frame(formatContext, &tempPacket) >= 0 && i <NUM_FRAMES)
    {
        int finished = 0;
        if (tempPacket.stream_index == streamIndex)
        {
            avcodec_decode_video2(
                                  codecContext,
                                  frame,
                                  &finished,
                                  &tempPacket);
            if (finished)
            {
                memcpy(datas[i].datas, frame->data, sizeof(frame->data)); // copy the frame data into an array
                i++;
            }
        }
    }
    av_free_packet(&tempPacket);
}

那么,我做错了什么?

data定义为

 uint8_t* AVFrame::data[AV_NUM_DATA_POINTERS]

操作

memcpy(datas[i].datas, frame->data, sizeof(frame->data)); // copy the frame data into an array

AV_NUM_DATA_POINTERS指针复制到data[i].datas中。这是不正确的,因为您只将引用复制到您自己尚未分配的帧缓冲区。另外,保证在avcodec_decode_video2之后只有最后一帧缓冲器可用。

只要需要克隆帧,就可以保留数据。

AVFrame* framearray[NUM_FRAMES];
...
if (finished)
{
     framearray[i] = av_frame_clone(frame);
     i++;
}