7

我使用此循环从 FFMPEG 中的视频流中读取帧:

while(av_read_frame(pFormatCtx, &packet)>=0) {
        // Is this a packet from the video stream?
        if(packet.stream_index==videoStream) {
            // Decode video frame
            avcodec_decode_video2(pCodecCtx,pFrame,&frameFinished,&packet);

            // Did we get a video frame?
            if(frameFinished) {


                sws_scale(img_convert_context ,pFrame->data,pFrame->linesize,0,
                     pCodecCtx->height, pFrameRGBA->data, pFrameRGBA->linesize);
                printf("%s\n","Frame read finished ");

                                       ExportFrame(pFrameRGBA->data[0]);
                    break;
                }
            }
            // Save the frame to disk

        }
            printf("%s\n","Read next frame ");

        // Free the packet that was allocated by av_read_frame
        av_free_packet(&packet);
    }

所以以这种方式顺序读取流。我想要的是随机访问帧以能够读取特定帧(按帧号)。它是如何完成的?

4

2 回答 2

7

你可能想看看

int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp,
                  int flags);

上面的 api 将在给定时间戳处寻找关键帧。寻找后,您可以阅读框架。下面的教程还解释了位置和时间戳之间的转换。

http://dranger.com/ffmpeg/tutorial07.html

于 2013-04-23T07:44:05.410 回答
3

由于视频中的大多数帧都依赖于前一帧和下一帧,因此通常访问视频中的随机帧并不简单。但是,某些帧独立于任何其他帧进行编码,并且在整个视频中定期出现。这些帧称为 I 帧。通过查找可以直接访问这些帧。

如果您想“随机”访问视频中的任何帧,那么您必须:

  1. 寻找上一个 I 帧
  2. 逐帧阅读,直到获得所需的帧号

你已经得到了第二点的代码,所以你需要做的就是处理第一点,你就完成了。这是人们经常参考的 Dranger 教程的更新版本——它可能会有所帮助。

于 2013-04-23T07:48:36.510 回答