MP4簡介
MP4(MPEG-4 Part 14)是一種常見的多媒體容器格式,它是在“ISO/IEC 14496-14”標準文件中定義的,屬于MPEG-4的一部分,是“ISO/IEC 14496-12(MPEG-4 Part 12 ISO base media file format)”標準中所定義的媒體格式的一種實現,后者定義了一種通用的媒體文件結構標準。
MP4是一種描述較為全面的容器格式,被認為可以在其中嵌入任何形式的數據,各種編碼的視頻、音頻等都不在話下,不過我們常見的大部分的MP4文件存放的AVC(H.264)或MPEG-4(Part 2)編碼的視頻和AAC編碼的音頻。
MP4格式的官方文件后綴名是“.mp4”,還有其他的以mp4為基礎進行的擴展或者是縮水版本的格式,包括:M4V, 3GP, F4V等。
Box
MP4文件中的所有數據都裝在box(QuickTime中為atom)中,也就是說MP4文件由若干個box組成,每個box有類型和長度,可以將box理解為一個數據對象塊。
box中可以包含另一個box。
一個MP4文件首先會有且只有一個“ftyp”類型的box,作為MP4格式的標志并包含關于文件的一些信息;之后會有且只有一個“moov”類型的box(Movie Box),它是一種容器 box,里面包含了各種子box,子box包含了媒體的metadata信息。
MP4文件的媒體數據包含在“mdat”類型的box(Midia Data Box)中,該類型的box也是容器box,可以有多個,也可以沒有(當媒體數據全部引用其他文件時)。
標準的box開頭的4個字節(32位)為box size,該大小包括box header和box body整個box的大小,這樣我們就可以在文件中定位各個box。如果size為1,則表示這個box的大小為large size,真正的size值要在largesize域上得到。(實際上只有“mdat”類型的box才有可能用到large size。)如果size為0,表示該box為文件的最后一個box,文件結尾即為該box結尾。(同樣只存在于“mdat”類型的box中。)size后面緊跟的32位為box type,一般是4個字符,如“ftyp”、“moov”等,這些box type都是已經預定義好的,分別表示固定的意義。如果是“uuid”,表示該box為用戶擴展類型。如果box type是未定義的,應該將其忽略。
box根據header部分包含的信息的不同可以分為box和full box。
box和full box的區別如圖所示:
1、 File Type Box(ftyp)
該box有且只有一個,并且不能包含其他box,一般放在文件的最開始位置,包含一些該MP4文件的基本信息。
ftyp box包含一個32位的major brand(4個字符),一個32位的minor version和一個以32位為單位的compatible數組。
這些都是用來指示文件應用級別的信息。
下面來分析一個示例文件:
00 00 00 18 66 74 79 70 6D 70 34 32 00 00 00 00 6D 70 34 32 00 00 00 00 ...
box的類型為ftyp box大小為24個字節,其中major_brand和minor_version都是mp42。
2、 Movie Box(moov)
該box包含了文件媒體的metadata信息,“moov”是一個容器 box,具體內容信息由子box詮釋。
該box也是有且只有一個,且只被包含在文件層。
有時輸出的格式拿到網絡上后發現需要完整下載后才能開始播放,而不能像網上的很多視頻那樣一開始就能播放,造成這個問題的原因是一些描述mp4文件信息的moov box元數據放置在了視頻文件的最后,而所有的播放器都需要這些信息來正確構建播放(比如視頻分辨率到底是多少,視頻到底有多長......),因此需要把這些信息想辦法移動到mp4文件的前部,這樣讀取到這些信息后客戶端播放器就可以搭起播放環境,后續只需要播放數據即可。
2.1、 Movie Header Box(mvhd)
由上圖MP4文件結構圖可以看出“moov”中會包含1個“mvhd box”和若干個“trak box”。
其中“mvhd”為header box,一般作為“moov”的第一個子box出現(對于其他容器 box來說,header box都應作為首個子box出現)。
mvhd 定義了整個 movie 的特性,例如 time scale 和 duration。具體字段的表結構如圖:
2.2、 Track Box(trak)
一個mp4文件可以包含一個或多個 tracks,它們之間相互獨立,各自有各自的時間和空間信息。
每個track box都有與之關聯的media box。trak box 要求必須有一個 trak header box (‘tkhd’) 和一個 media box(‘mdia’)。
其中tkhd box包含了該track的特性和總體信息,如時長,寬高等。tkhd box的字段結構如下表:
字段 | 字節長度(多少個字節) | 含義 |
---|---|---|
box size | 4 | box大小 |
box type | 4 | box類型 |
version | 1 | box版本,0或1,一般是0 |
flags | 3 | 按位或操作結果值,預定義如下:0X000001 track_enabled,否則該track不被播放;0X000002 track_in_movie 表示該track在播放中被引用;0X000004 track_in_preview 表示該track在預覽時被引用;一般情況下該值為7,如果一個媒體的所有track均沒有設置track_in_movie和track_in_preview,將被理解為所有track均被設置了這兩項 |
creation_time | 4 | 指定創建時間(相對于UTC時間1904-01-01零點的秒數) |
modification_time | 4 | 指定修改時間 |
track_ID | 4 | 指定track的id號,不能重復且不能為0 |
reserved | 4 | 保留位 |
duration | 4 | 指定track的時長 |
reserved | 8 | 保留位 |
layer | 2 | 指定視頻層,默認為0,值小的在上層 |
alternate_group | 2 | 指定rack分組信息,默認為0表示該track未與其他track有群組關系 |
volume | 2 | 指定[8.8] 格式的音量信息,如果為音頻track,1.0(0x0100)表示最大音量;否則為0 |
reserved | 2 | 保留位 |
matrix | 36 | 指定視頻變換矩陣 |
width | 4 | 寬,為 [16.16] 格式值,與sample描述中的實際畫面大小比值,用于播放時的展示寬高 |
height | 4 | 高 |
而mdia box是一個包含一些track媒體數據信息的容器 box。
mdia的子 box 的結構和種類還是比較復雜的。總體來說,“mdia”定義了 trak 媒體類型以及 sample 數據,描述 sample 信息。
一般“mdia”包含一個“mdhd”, 一個“hdlr”和一個“minf”,其中“mdhd”為 media header box,“hdlr” 為 handler reference box,“minf”為 media information box。
2.2.1、 mdhd box
mdhd(Media header box):包含了了該track的總體信息,mdhd 和 tkhd 內容大致都是一樣的。tkhd 通常是對指定的 track 設定相關屬性和內容,而 mdhd 是針對于獨立的 media 來設置的。
2.2.2、 hdlr box
hdlr(handler reference box) 解釋了媒體流的播放過程。例如,一個視頻 handler 處理一個 video track。
2.2.3、 ninf box
minf box介紹 “minf”存儲了解釋 trak 媒體數據的 handler-specific 信息,media handler用這些信息將媒體時間映射到媒體數據并進行處理。
“minf”中的信息格式和內容與媒體類型以及解釋媒體數據的 media handler密切相關,其他 media handler 不知道如何解釋這些信息。
“minf”是一個 container box,其實際內容由子 box說明。
minf的子box 一般情況下,“minf”包含一個 header box,一個“dinf”和一個“stbl”。
header box 根據track type(即 media handler type)分為“vmhd”、“smhd”,
“dinf”為 data information box,“stbl”為 sample table box。
2.2.3.1、 vmhd box
vmhd:用在視頻track中,包含當前track的視頻描述信息(如視頻編碼等信息)。除了box header之外還包含graphicsmode和opcolor兩個字段。
其中graphicsmode: 視頻合成模式,占4個字節。為0時拷貝原始圖像,否則與opcolor進行合成。
而opcolor:{red,green,blue},占2X3字節。
2.2.3.2、 smhd box
smhd:用在音頻track中,包含當前track的音頻描述信息(如編碼格式等信息)。其中有一個balance字段;
balance:立體聲平衡,占2個字節,[8.8] 格式值,一般為0,-1.0表示全部左聲道,1.0表示全部右聲道。
2.2.3.3、 stbl box
“stbl”包含了關于 trak 中 sample 所有時間和位置的信息,以及 sample 的編解碼等信息。
利用這個表,可以解釋sample 的時序、類型、大小以及在各自存儲容器中的位置。
“stbl”是一個 container box,其子 box 包括:sample description box(stsd)、time to sample box(stts)、sample size box(stsz 或stz2)、sample to chunk box(stsc)、chunk offset box (stco 或co64)、composition time to sample box(ctts)、sync sample box(stss)等。
“stsd”必不可少,且至少包含一個條目,該box包含了data reference box進行sample數據檢索的信息。沒有“stsd”就無法計算media sample的存儲位置。
stsd:box header和version字段后會有一個entry count字段,根據entry的個數,每個entry會有type信息,如“vide”、“sund”等,根據type不同sample description會提供不同的信息,例如對于video track,會有“VisualSampleEntry”類型信息,對于audio track會有“AudioSampleEntry”類型信息。視頻的編碼類型、寬高、長度,音頻的聲道、采樣等信息都會出現在這個box中。
stts:stts box存儲了sample的duration,描述了sample時序的映射方法,我們通過它可以找到任何時間的sample。stts box可以包含一個壓縮的表來映射時間和sample序號,用其他的表來提供每個sample的長度和指針。表中每個條目提供了在同一個時間偏移量里面連續的sample序號,以及samples的偏移量。遞增這些偏移量,就可以建立一個完整的time to sample表(時間戳到sample序號的映射表)。
stsz:“stsz” 定義了每個sample的大小,包含了媒體中全部sample的數目和一張給出每個sample大小的表。這個box相對來說體積是比較大的。
stsc: 用chunk組織sample可以方便優化數據獲取,一個thunk包含一個或多個sample。“stsc”中用一個表描述了sample與chunk的映射關系,查看這張表就可以找到包含指定sample的thunk,從而找到這個sample。
stss:“stss”確定media中的關鍵幀。對于壓縮媒體數據,關鍵幀是一系列壓縮序列的開始幀,其解壓縮時不依賴以前的幀,而后續幀的解壓縮將依賴于這個關鍵幀。“stss”可以非常緊湊的標記媒體內的隨機存取點,它包含一個sample序號表,表內的每一項嚴格按照sample的序號排列,說明了媒體中的哪一個sample是關鍵幀。如果此表不存在,說明每一個sample都是一個關鍵幀,是一個隨機存取點。
stco:“stco”定義了每個thunk在媒體流中的位置,sample的偏移可以根據其他box推算出來。位置有兩種可能,32位的和64位的,后者對非常大的電影很有用。在一個表中只會有一種可能,這個位置是在整個文件中的,而不是在任何box中的,這樣做就可以直接在文件中找到媒體數據,而不用解釋box。需要注意的是一旦前面的box有了任何改變,這張表都要重新建立,因為位置信息已經改變了。
2.2.3.4、 dinf box
介紹:“dinf”解釋如何定位媒體信息,是一個 container box。“dinf”一般包含一個“dref”,即 data reference box;“dref”下會包含若干個“url”或“urn”,這些 box 組成一個表,用來定位 trak 數據。簡單的說,trak可以被分成若干段, 每一段都可以根據“url”或“urn”指向的地址來獲取數據,sample 描述中會用這些片段的序號將這些片段組成一個完整的 trak。一般情況下,當數據被完全包含在文件中時,“url”或“urn”中的定位字符串是空的。
dref中包含entry_version和entry_flags字段:
entry_version: 用來指明當前 entry 的格式。
entry_flags: 其值不是固定的,但是有一個特殊的值, 0x000001 用來表示當前 media 的數據和 moov 包含的數據一致。
3、 Mdat Box
MP4的媒體信息和數據是分開存放的。就是你想獲得數據之前必須要解析出每個幀數據所在的位置。mp4存放這個幀信息的是放在stbl這個box里。而真實的數據放在mdat中。
4、 free Box
free box中的內容是無關緊要的,可以被忽略。該box被刪除后,不會對播放產生任何影響,它的type域可以是free或skip。
如果你對音視頻開發感興趣可以關注公號:思想覺悟