原文:https://blog.csdn.net/uyy203/article/details/79283087
視頻封裝格式是指視頻數據如何存儲的,視頻編碼格式是指原始視頻數據如何編碼為二進制數據碼流。編碼后的視頻數據最終通過視頻封裝格式存儲為視頻文件。
本文對視頻封裝格式MP4做一些介紹。主要介紹了Atom結構和Atom中數據的意義。
一、MP4封裝格式
ISO/IEC 14496-12(MPEG-4 Part 12 ISO base media file format)定義了一種通用的數字媒體文件格式標准,其基礎是2001年版的Apple QuickTime文件格式。
ISO/IEC 14496-14標准中定義了ISO/IEC 14496-12的一種多媒體容器格式實現,即我們現在熟知的MP4(MPEG-4 Part 14),它屬於MPEG-4的一部分。
MP4文件由若干稱為Atom(或稱為box)的數據對象組成,每個Atom的起首為四個字節的數據長度(Big Endian)和四個字節的類型標識,數據長度和類型標志都可以擴展。Atom可以嵌套,即其數據域可以由若干其它Atom組成,從而實現結構化的數據。
MP4是一種描述較為全面的容器格式,被認為可以在其中嵌入任何形式的數據,包括各種編碼的視頻、音頻,我們常見的大部分的MP4文件存放的AVC(H.264)或MPEG-4(Part 2)編碼的視頻和AAC編碼的音頻。
MP4格式的官方文件后綴名是“.mp4”,還有其他的以mp4為基礎進行的擴展或者是縮水版本的格式,包括:M4V, 3GP, F4V等。
說明:
QuickTime影片格式是Apple公司開發的一種音頻、視頻文件格式,用於存儲常用數字媒體類型。其擴展名為.mov。
二、MP4文件結構
MP4是由Atom嵌套來存放媒體信息。Atom的基本結構是:
[4bytes atom length] [4bytes atom name] [8bytes largesize, if size ==1] [contents of the atom, if any]
結構如圖:

SIZE表示整個Atom所占用的大小,包括header部分。如果Atom很大,超過了uint32的最大數值(例如存放具體視頻數據的mdat),size就被設置為1,並用接下來的LARGESIZE來存放數據大小。
TYPE表示這個Atom的類型,主要有ftyp、moov、mdat等。
LARGESIZE,如果SIZE==1,則使用8bytes uint64來存儲該Atom大小。
DATA是實際的數據。
MP4文件含有很多Atom,主要的Atom和嵌套結構如圖。

三、一個典型的MP4文件實例
MP4文件需要有ftyp、moov、mdat,它們都是頂級Atom,不能被其他Atom嵌套。
ftyp標示了MP4文件,必須出現在第一個。
moov保存了視頻的基本信息,mdat保存視頻和音頻數據。這兩個Atom順序不固定。
一個moov在mdat之后的MP4文件的Atom結構:

由於moov中保存了視頻數據的索引,對於在線播放的場景,需要moov在mdat之前,才能流式讀取視頻數據。
部分攝像設備生成的MP4文件中,moov在mdat之前,兩者之間可能還存在一個Atom free,即moov-free-mdat。
free中為全0,只是用於占位。
一個moov在mdat之前的MP4文件的Atom結構:

四、ATOM說明
1、FTYP
ftyp是整個文件的第一個Atom,通過判斷該Atom來確定文件的類型。該Atom有且只有1個,並且只能被包含在文件層,而不能被其他Atom包含。該Atom應該被放在文件的最開始,指示文件的相關信息。
文件的最開始的四個字節就是“ftyp”Atom的大小,然后是該Atom的類型。 “ftyp”的body依次包括1個32位的major brand(4個字符),1個32位的minor version(整數)和1個以32位(4個字符)為單位元素的數組compatible brands。這些都是用來指示文件應用級別的信息。以一個MP4文件的“ftyp”Atom為例,如下所示:
0000000: 0000 0018 6674 7970 6d70 3432 0000 0000 ....ftypmp42....
0000010: 6d70 3432 6d70 3431 0528 834f 6d64 6174 mp42mp41.(.Omdat
其中,
(1)0x00 00 00 18是“ftyp”Atom的大小,為24個字節,這在一般情況下為一個固定值。
(2)0x66 74 79 70是“ftyp”四個字符的ASCII值,也就是該Atom的類型。
(3)0x6D 70 34 32是major brand,這里為“mp42”,對於不同的文件,該值可能是不一樣的。
(4)0x00 00 00 00是minor version。
(5)0x6D 70 34 32和0x6D 70 34 31是compatible brands,”mp42”和“mp41”
FTYP到底是什么呢?
ftyp就是一個由四個字符組成的碼字,用來標識編碼類型、兼容性或者媒體文件的用途。它存在於MP4文件和MOV文件中,當然,也存在於3GP文件中。
雖然MP4文件、MOV文件和3GP文件采用了相同的封裝標准,但由於是由不同的廠商合成,因此還是存在差別的。即使是同一種媒體文件,比如MP4文件,由不同developers開發的MP4也是存在差別的。ftyp簡單的說就是為了標識它的developer是誰,兼容哪些標准等。
比如上面的例子,“mp42”表示它的major brand是MP4 v2 [ISO 14496-14],而“mp42”和“mp41”則表示它的compatible brands是MP4 v2 [ISO 14496-14]和MP4 v1 [ISO 14496-1:ch13]。
2、FREE
free是可選的,如果存在,則通常出現在moov與mdat之間,即moov-free-mdat。
free中的數據通常為全0,其作用相當於占位符,在實時拍攝視頻,moov數據增多時分配給moov使用。
因為設備錄制視頻時並不能預先知道視頻數據大小,如果moov在mdat之前,隨着拍攝mdat的數據會增加,moov數據也會增多,如果沒有free預留的空間,則要不停的向后移動mdat數據以騰出moov空間。
3、MOOV
moov中主要保存了媒體的時間信息、trak信息和媒體索引等。
3.1 媒體時間信息
moov-mvhd中有一個time scale,以1/n秒的形式給出一個總的時間粒度,moov-trak-tkhd中以此時間粒度給出各個track的duration;
3.2 trak信息
moov中通常包含兩個trak,一個視頻索引,一個音頻索引。
3.2.1 trak類型
trak的類型在moov-trak-mdia-hdlr中給出,包括’vide’, ‘soun’和’hint’三種。
3.2.2 trak的時間
moov-trak-mdia-mdhd中以1/n秒的形式給出各個媒體的時間粒度以及以此時間粒度為單位的duration。
moov-trak-mdia-minf-stbl-stts中有媒體幀之間的時間間隔,單位是moov-trak-tkhd中的時間粒度。
3.2.3 索引信息
moov-trak-mdia-minf-stbl比較重要,其中保存了解碼器需要的信息和索引信息,以下Atom都是stbl Atom的孩子。
stsd中保存了解碼器需要的媒體描述信息。

stss, Sync Sample Atom
標識了媒體流中的關鍵幀,提供了隨機訪問點。每個entry標識了一個關鍵幀。
關鍵幀號是按照增長順序排列的。如果該Atom不存在,表示所有幀都是關鍵幀。

Sync Sample Table的布局
stts, Time-To-Sample Atoms
stts給出每個數據幀之間的時間間隔,單位是moov-trak-tkhd中的時間粒度。
Atom的每個entry給出了具有相同時間間隔的連續幀的個數,這些幀的時間間隔值,結構如圖。

Time-To-Sample的table entry布局
如果連續的幀有相同的時長,他們會被放在同一個entry中。如果所有的幀具有相同的時長,那么Atom中就只有一個entry。
stts實例
下圖通過3個entries來描述9個幀。需要說明的是,這里的entry和chunk不是對應的。例如,4、5、6幀可以在同一個chunk中,但是,由於它們的時長不同,4幀的時長為3,而5、6幀的時長為1,因此,保存在不同的entry中。

stco/co64, Chunk Offset Atom
stco/co64給出每個數據Chunk在文件中的偏移。Chunk Offset Atom的每個entry給出了每個chunk在文件中的偏移。
如果Chunk Offset Atom的類型為stco,則保存的偏移量是32位;如果是co64,則保存的偏移量是64位的。布局如圖。

chunk offset table的布局
需要注意的是,該Atom中只給出了每個chunk的偏移量,並沒有給出每個sample的偏移量。因此,如果要獲得每個sample的偏移量,還需要用到Sample Size Table和Sample-To-Chunk Table。
stsc, Sample-To-Chunk Atom
stsc給出各個數據Chunk中包含的數據幀。一個chunk可能會包含一個或者幾個幀。每個chunk會有不同的size,每個chunk中的幀也會有不同的size。
entry中保存了第一個chunk號、每個chunk包含的幀數、幀描述ID。

Sample-To-Chunk Atom的table entry布局
每個entry包含一組chunk,其中每個chunk的幀數相同。而且,這些chunk中的每個幀都必須使用相同的幀描述。
如果chunk中的幀數或者幀描述改變,必須創建一個新的entry。
如果所有的chunk包含的幀數和幀描述相同,那么只有一個entry。
stsc實例
圖中表示至少有5個chunk,第1、2個chunk分別包含3個幀,幀描述ID是23;第3、4個chunk分別包含1個幀,幀描述ID是23;第5個及以后的chunk,包含1個幀,幀描述ID是24。
對於最后一個entry需要特殊的處理,因為無法判斷什么時候結束。

stsz, Sample Size Atom

sample size table的布局
3.3 用戶定義數據
udta中保存了用戶定義數據,例如iTune使用的meta數據就保存在udta中。
3.4 用戶擴展數據
Atom的擴展通過uuid實現。用戶可以使用類型為’uuid’的Atom,以16個特定的字節作為標識,定義自己的數據格式。
4、MDAT
所有媒體數據統一存放在mdat中,沒有同步字,沒有分隔符,只能根據索引進行訪問。
mdat的位置比較靈活,可以位於moov之前,也可以位於moov之后,但必須和stbl中的信息保持一致。
另外,在寫mp4文件的時候,對於mdat這個Atom,一般是先將Atom size填寫0,待數據寫完之后,再回過來填入具體大小。
5、其他ATOM
5.1、THMB
Atom moov @ 13840405 of size: 355190, ends @ 14195595
…….
Atom udta @ 14146330 of size: 49265, ends @ 14195595
Atom thmb @ 14146338 of size: 49197, ends @ 14195535
Atom cprt [zho] @ 14195535 of size: 30, ends @ 14195565
Atom perf [zho] @ 14195565 of size: 30, ends @ 14195595
thmb 結構:
atom size (49197)
atom type (thmb)
thmb size (0)
thmb type (jpeg)
thmb data
五、實際應用場景
1、把文件尾部的moov移到文件頭
對於流媒體播放,如果mdat的位置在moov之前,通過流的方式播放文件會出現問題,因為沒有辦法在一開始就獲得文件的媒體信息和索引。
這種情況需要對視頻做預處理,把moov移動到文件頭。通過遍歷Atom可以很容易找到moov Atom。
需要注意的是,移動moov到文件頭,同時需要修改moov中的stco/co64。因為這里保存了chunk數據的偏移量,移動moov后,需要根據moov的新位置更新stco/co64 。
stco/co64的結構如下:

可參考 python開源庫 qtfaststart。
2、分割MP4文件
在視頻點播服務中,需要將MP4文件分割為多個分片,此時需要獲取關鍵幀、切割時間軸、更新moov和生成各個分片文件。
可參考 http://www.cnblogs.com/haibindev/archive/2011/10/17/2214518.html
附 查看Atom相關工具
Windows:mp4info,解析和用樹形顯示文件的atom
Linux:AtomicParsley,C++編寫,解析文件的atom
附錄: ISO/IEC 14496 MPEG的協議標准
ISO/IEC 14496是MPEG專家組制定的MPEG-4標准於1998年10月公布第1版,1999年1月成為國際標准,1999年12月公布了第2版,2000年初成為國際標准。
全文分為27個部分:
(1)ISO/IEC 14496-1系統部分,描述視頻和音頻數據流的控制、同步以及混合方式(即混流 Multiplexing,簡寫為MUX)。
(2)ISO/IEC 14496-2視頻部分,定義了一個對各種視覺信息(包括自然視頻、靜止紋理、計算機合成圖形等等)的編解碼器。(例如XviD編碼就屬於MPEG-4 Part 2)。
(3)ISO/IEC 14496-3音頻部分,定義了一個對各種音頻信號進行編碼的編解碼器的集合。包括高級音頻編碼(Advanced Audio Coding,縮寫為AAC)的若干變形和其他一些音頻/語音編碼工具。
(4)ISO/IEC 14496-4一致性部分,定義了比特流和設備的一致性條件,用來測試MPEG-4的實現。
(5)ISO/IEC 14496-5參考軟件,提供了用於演示功能和說明本標准其他部分功能的軟件。
(6)ISO/IEC 14496-6多媒體傳送整體框架DMIF,這是MPEG-4應用層與傳輸網絡的接口,定義了通信協議,使MPEG-4系統的數據流能進入各種傳輸網絡。還包含一個存儲格式MP4,用於存儲編碼的場景。
(7) ISO/IEC 14496-7優化的參考軟件,提供了對實現進行優化的例子(這里的實現指的是第五部分)。
(8)ISO/IEC 14496-8在IP網絡上傳輸,定義了在IP網絡上傳輸MPEG-4內容的方式。
(9)ISO/IEC 14496-9參考硬件描述,提供了用於演示怎樣在硬件上實現本標准其他部分功能的硬件設計方案
(10)ISO/IEC 14496-10高級視頻編碼AVC,定義了一個視頻編解碼器(codec)。AVC和XviD都屬於MPEG-4編碼,但由於AVC屬於MPEG-4 Part 10,在技術特性上比屬於MPEG-4 Part2的XviD要先進。另外,它和ITU-T H.264標准是一致的,故又稱為H.264。
(11)ISO/IEC 14496-11場景描述和應用引擎。
(12)ISO/IEC 14496-12ISO媒體文件格式,定義了一個存儲媒體內容的文件格式。
(13)ISO/IEC 14496-13知識產權管理和保護(IPMP:Intellectual Property Management and Protection)擴展。
(14)ISO/IEC 14496-14MP4文件格式,定義了基於第十二部分的用於存儲MPEG-4內容的容器文件格式。
(15)ISO/IEC 14496-15AVC文件格式,定義了基於第十二部分的用於存儲第十部分的視頻內容的文件格式。
(16)ISO/IEC 14496-16動畫框架擴展AFX(Animation Framework eXtension)。
(17)ISO/IEC 14496-17同步文本字幕格式。
(18)ISO/IEC 14496-18字體壓縮和流式傳輸(針對公開字體格式)。
(19)ISO/IEC 14496-19合成材質流(Synthesized Texture Stream)。
(20)ISO/IEC 14496-20簡單場景表示(LASeR for Lightweight Scene Representation)。
(21)ISO/IEC 14496-21用於描繪(Rendering)的MPEG-J拓展。
(22)ISO/IEC 14496-22開放字體格式(Open Font Format)。
(23)ISO/IEC 14496-2符號化音樂表示(Symbolic Music Representation)。
(24)ISO/IEC 14496-24音頻與系統交互作用(Audio and systems interaction)。
(25)ISO/IEC 14496-253D圖形壓縮模型(3D Graphics Compression Model)。
(26)ISO/IEC 14496-26音頻一致性檢查:定義了測試音頻數據與ISO/IEC 14496-3是否一致的方法(Audio conformance)。
(27)ISO/IEC 14496-273D圖形一致性檢查:定義了測試3D圖形數據與ISO/IEC 14496-11:2005, ISO/IEC 14496-16:2006, ISO/IEC 14496-21:2006, 和 ISO/IEC 14496-25:2009是否一致的方法(3D Graphics conformance)。
參考
http://blog.csdn.net/yu_yuan_1314/article/details/9406587
http://m.blog.chinaunix.net/uid-26009923-id-5702652.html
視頻格式說明
http://www.zhihu.com/question/20997688
atom說明
http://wiki.multimedia.cx/?title=QuickTime_container
http://atomicparsley.sourceforge.net/mpeg-4files.html
http://www.ftyps.com/what.html
http://blog.csdn.net/yu_yuan_1314/article/details/9366703
http://blog.csdn.net/yu_yuan_1314/article/details/9078287
開源庫
qtfaststart python編寫的,如果moov在文件尾部,移動到文件頭部
https://github.com/danielgtaylor/qtfaststart.git
from:https://www.jianshu.com/p/dd6b8aa625d4