FFmpeg中AVPacket和AVFrame关系

Posted Ven_J

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FFmpeg中AVPacket和AVFrame关系相关的知识,希望对你有一定的参考价值。

        最近在研究ffplay3.2.4的源码,ffplay中有两个队列一个PacketQueue, 一个FrameQueue,对这两个队列之间的关系不是很清楚。于是对这两个结构仔细研究一下。

1、数据结构含义

AVPacket

        用于存储压缩的数据,分别包括有音频压缩数据,视频压缩数据和字幕压缩数据。它通常在解复用操作后存储压缩数据,然后作为输入传给解码器。或者由编码器输出然后传递给复用器。

        对于视频压缩数据,一个AVPacket通常包括一个视频帧。对于音频压缩数据,可能包括几个压缩的音频帧。

AVFrame

         用于存储解码后的音频或者视频数据。AVFrame必须通过av_frame_alloc进行分配,通过av_frame_free释放。

两者之间的关系

        av_read_frame得到压缩的数据包AVPacket,一般有三种压缩的数据包(视频、音频和字幕),都用AVPacket表示。然后调用avcodec_decode_video2对AVPacket进行解码得到AVFrame。

2、队列关系

        ffplay中有三种PacketQueue,分别为视频包队列(videoq)、音频包队列(audioq)和字幕包队列(subtitleq)。相应地,也有三种FrameQueue,视频帧队列(pictq)、音频帧队列(sampq)和字幕帧队列(subpq)。         队列的初始化工作是在stream_open函数中进行,分别通过packet_queue_init和frame_queue_init执行初始化操作。需要注意的是,初始化中PacketQueue没有手动分配AVPacket结构,而是直接使用解码过程中的AVPacket。FrameQueue中则是通过av_frame_alloc手动分配了AVFrame结构。

        在read_thread函数中,通过av_read_frame函数读取数据包,然后调用packet_queue_put将AVPacket添加到PacketQueue中。

        在video_thread函数中,通过get_video_frame函数读取数据帧,然后调用queue_picture将AVFrame添加到FrameQueue中。

        那么两个队列是怎么联系起来的呢?让我们分析read_thread函数。read_thread函数的主要工作:首先,创建解复用和解码所需要的数据结构。其次,分别通过stream_component_open函数打开三种数据流。最后,通过av_read_frame将解复用后的数据包分别添加到对应的PacketQueue中。在stream_component_open函数主要负责解码工作,ffplay中为解码工作专门设置了一个数据结构Decoder,Decoder结构中有一个成员queue,这个queue就是指的输入的PacketQueue,通过decoder_init函数来指定PacketQueue。这个工作就是在stream_component_open中执行的。指定PacketQueue之后通过get_video_frame函数从PacketQueue中解码出AVFrame结构,最后通过queue_picture函数将解码得到的帧添加到FrameQueue。

以上是关于FFmpeg中AVPacket和AVFrame关系的主要内容,如果未能解决你的问题,请参考以下文章

ffmpeg中AVPacket与AVFrame中数据的传递与释放

ffmpeg中AVPacket与AVFrame中数据的传递与释放

ffmpeg中AVPacket与AVFrame中数据的传递与释放

ffmpeg中AVPacket与AVFrame中数据的传递与释放

FFmpeg从AVPacket中提取出AVFrame帧数据后怎么显示出来

4.FFMPEG-AVFrame