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了。

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