AVIOContext和邊合成邊上傳

基礎(chǔ)知識

AVFormatContext->pb是一個AVIOContext結(jié)構(gòu)體,負(fù)責(zé)IO操作。
一般情況下,我們通過avio_open函數(shù)創(chuàng)建并初始化AVFormatContext->pb;通過avio_closep函數(shù)關(guān)閉AVFormatContext->pb。

1.  // 創(chuàng)建AVIOContext,用于讀寫url標(biāo)識的文件
2.  int avio_open(AVIOContext  **s,  const  char  *url,  int flags);
3.  // 關(guān)閉AVIOContext資源
4.  int avio_closep(AVIOContext  **s);

Mux流程:

  1. avio_open(打開AVIOContext)
  2. avformat_write_header(寫封裝格式頭信息)
  3. av_interleaved_write_frame(寫入AVPacket)
  4. av_write_trailer(寫封裝格式尾信息)
  5. avio_closep(關(guān)閉AVIOContext)

邊合成邊上傳

所謂邊合成邊上傳,就是在寫文件的同時,通過回調(diào)向外拋出一份Buffer數(shù)據(jù),業(yè)務(wù)側(cè)可以基于Buffer數(shù)據(jù)同步做文件上傳。

核心邏輯就是創(chuàng)建自定義AVIOContext,接管文件IO。

1.  // 創(chuàng)建Buffer
2.  uint8_t  *avio_buffer =  (uint8_t*)av_malloc(avio_ctx_buffer_size);
3.  // 創(chuàng)建AVIOContext,read_packet函數(shù)負(fù)責(zé)讀buffer,write_packet負(fù)責(zé)寫buffer,seek_user負(fù)責(zé)seek
4.  AVIOContext io = avio_alloc_context(avio_buffer, avio_ctx_buffer_size,  1, opaque,  &read_packet,  &write_packet,  &seek_user);
5.  io->seekable = AVIO_SEEKABLE_NORMAL;

7.  AVFormatContext->pb = io;

Mux時,AVIOContext->write_packet收到Buffer數(shù)據(jù),可以一邊寫文件,一邊向外回調(diào)Buffer,業(yè)務(wù)側(cè)進(jìn)行同步上傳。

下面的48字節(jié),一開始就會輸出,其中ftyp和free box是固定的40字節(jié),最后8字節(jié)表示mdat box header,在所有AVPacket輸出完之后(只有所有AVPacket都輸出完了,才知道m(xù)dat box size),會更新40~43字節(jié)的mdat box size。

1.  `ftyp box header`
2.  `0,  0,  0,  20,  // ftyp box 共32字節(jié)`
3.  `66,  74,  79,  70,`
4.  `69,  73,  6f,  6d,` 
5.  `0,  0,  2,  0,` 
6.  `69,  73,  6f,  6d,` 
7.  `69,  73,  6f,  32,` 
8.  `61,  76,  63,  31,` 
9.  `6d,  70,  34,  31,` 

11.  `free box header` 
12.  `0,  0,  0,  8,  // free box 共8字節(jié)`
13.  `66,  72,  65,  65,` 

15.  `mdat box header` 
16.  `0, d, a1, af,` 
17.  `6d,  64,  61,  74,` 

最后生成的Mp4文件,正好可以與前48字節(jié)對應(yīng)起來:


ftyp

輸出完所有AVPacket之后,調(diào)用av_write_trailer輸出尾部數(shù)據(jù),例如:Mp4的moov box。

調(diào)用av_write_trailer之后,AVIOContext->write_packet首先重寫mdat box size(40~43字節(jié)),然后輸出moov數(shù)據(jù)。

1.  `moov box header` 
2.  `0,  0,  10,  2d,  // moov box size`
3.  `6d,  6f,  6f,  76,` 

5.  `// 后續(xù)為moov具體內(nèi)容`
6.  `0,  0,  0,  6c,` 
7.  `6d,  76,  68,  64`
8.  `............`

最終生成的Mp4文件,正好與尾部數(shù)據(jù)一致:


moov

總結(jié)

AVIOContext->write_packet函數(shù)首先輸出48字節(jié),包含ftyp box、free box、mdat box header,然后輸出所有的AVPacket,最后調(diào)用av_write_trailer函數(shù)后,AVIOContext->write_packet函數(shù)先調(diào)整40~43字節(jié)的mdat size,然后輸出moov box。

在邊合成邊上傳場景中,可以先緩存48字節(jié)的文件頭和MOOV文件尾,等到所有AVPacket向外回調(diào)之后,再單獨(dú)回調(diào)文件頭Buffer和文件尾Buffer。

因?yàn)闀嬖谛薷囊焉蟼鲾?shù)據(jù)(40~43)的情況,并且上傳SDK并不支持這種操作,所以才分為文件主內(nèi)容(AVPacket)、文件頭和文件尾三部分向外回調(diào)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容