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

转载地址:
AVPacketList是代表链表的一种节点类型,每一个节点内存放的是该链表的内容(一个AVPacket)和一个用于串接链表的指针(看起来是一个单链表)
[cpp] view plain copy
typedef struct AVPacketList {
AVPacket pkt;
struct AVPacketList *next;
} AVPacketList;

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

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

[cpp] view plain copy
/*******************************************************
* 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了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章