AVFormatContext中的三个AVPacketList类型的缓冲的浅显分析

来源:互联网 发布:反映数据稳定性的指标 编辑:程序博客网 时间:2024/06/05 22:24


AVPacketList是代表链表的一种节点类型,每一个节点内存放的是该链表的内容(一个AVPacket)和一个用于串接链表的指针(看起来是一个单链表)

typedef struct AVPacketList {    AVPacket pkt;    struct AVPacketList *next;} AVPacketList;

因此,见到AVPacketList,应该首先相当这是一个链表的节点。



AVFormatContex中有好几个链表,链表是可以用一个节点来代表的:

  

    /*****************************************************************     * All fields below this line are not part of the public API. They     * may not be used outside of libavformat and can be changed and     * removed at will.     * New public fields should be added right above.     *****************************************************************     */    /**     * This buffer is only needed when packets were already buffered but     * not decoded, for example to get the codec parameters in MPEG     * streams.     */    struct AVPacketList *packet_buffer;    struct AVPacketList *packet_buffer_end;    /* av_seek_frame() support */    int64_t data_offset; /**< offset of the first packet */    /**     * Raw packets from the demuxer, prior to parsing and decoding.     * This buffer is used for buffering packets until the codec can     * be identified, as parsing cannot be done without knowing the     * codec.     */    struct AVPacketList *raw_packet_buffer;    struct AVPacketList *raw_packet_buffer_end;    /**     * Packets split by the parser get queued here.     */    struct AVPacketList *parse_queue;    struct AVPacketList *parse_queue_end;    /**     * Remaining size available for raw_packet_buffer, in bytes.     */#define RAW_PACKET_BUFFER_SIZE 2500000    int raw_packet_buffer_remaining_size;



ffmpeg的缓冲用的链表喜欢带有“能指定链表的头和尾的节点的指针的”。

可以看到,居然有在分析Format的时候,可能会用到三个缓冲,他们的出现时间和使用目的,可能有不同。



(1)

翻译过来是:这是用来在解码之前缓冲用的,比如需要从某些包里头获取codec的参数信息(可以看MPEG的处理),就用这个缓冲来做:

    struct AVPacketList *packet_buffer;
    struct AVPacketList *packet_buffer_end;


个人理解,

由于寻找codec的时候,并没有开始真正的demuxer parser decoder的处理,只是为了find info一下,所以这个缓冲,应该是最先是被使用的。

当然,codec的信息,可能在就解码的过程也会读取到,这个缓冲也可以在这个时候用?

我对MPEG的处理,不太了解,不敢妄作论断。


有人http://hi.baidu.com/ccqi0000/item/d3aaa79b3f9540dab72531bd认为这个packet_buffer是用来拼接给decoder的一个frame的,因此这个packet_buffer里头是从raw packet的buffer里头得到的用来拼接完整一帧的各个包,也就是说, 这个packet是parser用的???而且这个缓冲,是av_read_frame读取数据用的, av_read_frame里头有调用parser组装一帧的函数av_parser_parse2,因此这个packet_buffer,真的很有可能是用来从raw buffer中读取packet,用来拼接一帧用的临时缓冲,与我所猜测的用来find info的缓冲不是一回事。



(2)

从demuxer中得到的数据叫做raw packet (原始数据),这个时候的raw也是被压缩了的数据吧。

这些从demuxer中得到的包会用这个缓冲来存储下,等着找到了codec,就可以从这里分析(parse)和解码(decode)了。

parse和decode应该是两个不同的过程。raw的数据,经过parse后,得到的数据,才会送给解码器处理的。


    struct AVPacketList *raw_packet_buffer;
    struct AVPacketList *raw_packet_buffer_end;


个人理解,当demuxer过程开始,源源不断的数据从容器格式里头分离开来,等待处理(parse和decode),等待处理的数据应该要放在一个缓冲中,就是这个啦。


(3)

看到parse 从raw_packet_buffer中取数据,然后parse处理,之后将数据存放于缓冲parse_queue中,解码器中parse_queue中取出数据。

    /**
     * Packets split by the parser get queued here.
     */
    struct AVPacketList *parse_queue;
    struct AVPacketList *parse_queue_end;


个人理解,看来parse的过程应该是要从raw_packet_buffer中读取数据了。

parse之后的数据包,如果来不及送给解码器,那么也要缓冲起来,等待解码器慢慢取,这个缓冲就是这个parse_queue了。