目前MP4的概念被炒得很火,也很亂。最開始MP4指的是音頻(MP3的升級版),即MPEG-2 AAC標準。隨後MP4概念被轉移到視頻上,對應的是MPEG-4標準。而如今咱們流行的叫法,多半是指能播放MPEG-4標準編碼格式視頻的播放器。可是這篇文章介紹的內容跟上面這些都無關,咱們要討論的是MP4文件封裝格式,對應的標準爲ISO/IEC 14496-12,即信息技術 視聽對象編碼的第12部分:ISO 基本媒體文件格式(Information technology Coding of audio-visual objects Part 12: ISO base media file format)。ISO/IEC組織指定的標準通常用數字表示,ISO/IEC 14496即MPEG-4標準。html
MP4視頻文件封裝格式是基於QuickTime容器格式定義的,所以參考QuickTime的格式定義對理解MP4文件格式頗有幫助。MP4文件格式是一個十分開放的容器,幾乎能夠用來描述全部的媒體結構,MP4文件中的媒體描述與媒體數據是分開的,而且媒體數據的組織也很自由,不必定要按照時間順序排列,甚至媒體數據能夠直接引用其餘文件。同時,MP4也支持流媒體。MP4目前被普遍用於封裝h.264視頻和AAC音頻,是高清視頻的表明。數組
如今咱們就來看看MP4文件格式究竟是什麼樣的。網絡
一、概述數據結構
MP4文件中的全部數據都裝在box(QuickTime中爲atom)中,也就是說MP4文件由若干個box組成,每一個box有類型和長度,能夠將box理解爲一個數據對象塊。box中能夠包含另外一個box,這種box稱爲container box。一個MP4文件首先會有且只有一個「ftyp」類型的box,做爲MP4格式的標誌幷包含關於文件的一些信息;以後會有且只有一個「moov」類型的box(Movie Box),它是一種container box,子box包含了媒體的metadata信息;MP4文件的媒體數據包含在「mdat」類型的box(Midia Data Box)中,該類型的box也是container box,能夠有多個,也能夠沒有(當媒體數據所有引用其餘文件時),媒體數據的結構由metadata進行描述。ide
下面是一些概念:佈局
track 表示一些sample的集合,對於媒體數據來講,track表示一個視頻或音頻序列。優化
hint track 這個特殊的track並不包含媒體數據,而是包含了一些將其餘數據track打包成流媒體的指示信息。ui
sample 對於非hint track來講,video sample即爲一幀視頻,或一組連續視頻幀,audio sample即爲一段連續的壓縮音頻,它們統稱sample。對於hint track,sample定義一個或多個流媒體包的格式。編碼
sample table 指明sampe時序和物理佈局的表。atom
chunk 一個track的幾個sample組成的單元。
在本文中,咱們不討論涉及hint的內容,只關注包含媒體數據的本地MP4文件。下圖爲一個典型的MP4文件的結構樹。
二、Box
首先須要說明的是,box中的字節序爲網絡字節序,也就是大端字節序(Big-Endian),簡單的說,就是一個32位的4字節整數存儲方式爲高位字節在內存的低端。Box由header和body組成,其中header統一指明box的大小和類型,body根據類型有不一樣的意義和格式。
標準的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是未定義的,應該將其忽略。
三、File Type Box(ftyp)
該box有且只有1個,而且只能被包含在文件層,而不能被其餘box包含。該box應該被放在文件的最開始,指示該MP4文件應用的相關信息。
「ftyp」 body依次包括1個32位的major brand(4個字符),1個32位的minor version(整數)和1個以32位(4個字符)爲單位元素的數組compatible brands。這些都是用來指示文件應用級別的信息。該box的字節實例以下:
四、Movie Box(moov)
該box包含了文件媒體的metadata信息,「moov」是一個container box,具體內容信息由子box詮釋。同File Type Box同樣,該box有且只有一個,且只被包含在文件層。通常狀況下,「moov」會緊隨「ftyp」出現。
通常狀況下(限於篇幅,本文只講解常見的MP4文件結構),「moov」中會包含1個「mvhd」和若干個「trak」。其中「mvhd」爲header box,通常做爲「moov」的第一個子box出現(對於其餘container box來講,header box都應做爲首個子box出現)。「trak」包含了一個track的相關信息,是一個container box。下圖爲部分「moov」的字節實例,其中紅色部分爲box header,綠色爲「mvhd」,黃色爲一部分「trak」。
4.1 Movie Header Box(mvhd)
「mvhd」結構以下表。
字段 |
字節數 |
意義 |
box size |
4 |
box大小 |
box type |
4 |
box類型 |
version |
1 |
box版本,0或1,通常爲0。(如下字節數均按version=0) |
flags |
3 |
|
creation time |
4 |
建立時間(相對於UTC時間1904-01-01零點的秒數) |
modification time |
4 |
修改時間 |
time scale |
4 |
文件媒體在1秒時間內的刻度值,能夠理解爲1秒長度的時間單元數 |
duration |
4 |
該track的時間長度,用duration和time scale值能夠計算track時長,好比audio track的time scale = 8000, duration = 560128,時長爲70.016,video track的time scale = 600, duration = 42000,時長爲70 |
rate |
4 |
推薦播放速率,高16位和低16位分別爲小數點整數部分和小數部分,即[16.16] 格式,該值爲1.0(0x00010000)表示正常前向播放 |
volume |
2 |
與rate相似,[8.8] 格式,1.0(0x0100)表示最大音量 |
reserved |
10 |
保留位 |
matrix |
36 |
視頻變換矩陣 |
pre-defined |
24 |
|
next track id |
4 |
下一個track使用的id號 |
「mvhd」的字節實例以下圖,各字段已經用顏色區分開:
4.2 Track Box(trak)
「trak」也是一個container box,其子box包含了該track的媒體數據引用和描述(hint track除外)。一個MP4文件中的媒體能夠包含多個track,且至少有一個track,這些track之間彼此獨立,有本身的時間和空間信息。「trak」必須包含一個「tkhd」和一個「mdia」,此外還有不少可選的box(略)。其中「tkhd」爲track header box,「mdia」爲media box,該box是一個包含一些track媒體數據信息box的container box。
「trak」的部分字節實例以下圖,其中黃色爲「trak」box的頭,綠色爲「tkhd」,藍色爲「edts」(一個可選box),紅色爲一部分「mdia」。
4.2.1 Track Header Box(tkhd)
「tkhd」結構以下表。
字段 |
字節數 |
意義 |
box size |
4 |
box大小 |
box type |
4 |
box類型 |
version |
1 |
box版本,0或1,通常爲0。(如下字節數均按version=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均設置了這兩項;對於hint track,該值爲0 |
creation time |
4 |
建立時間(相對於UTC時間1904-01-01零點的秒數) |
modification time |
4 |
修改時間 |
track id |
4 |
id號,不能重複且不能爲0 |
reserved |
4 |
保留位 |
duration |
4 |
track的時間長度 |
reserved |
8 |
保留位 |
layer |
2 |
視頻層,默認爲0,值小的在上層 |
alternate group |
2 |
track分組信息,默認爲0表示該track未與其餘track有羣組關係 |
volume |
2 |
[8.8] 格式,若是爲音頻track,1.0(0x0100)表示最大音量;不然爲0 |
reserved |
2 |
保留位 |
matrix |
36 |
視頻變換矩陣 |
width |
4 |
寬 |
height |
4 |
高,均爲 [16.16] 格式值,與sample描述中的實際畫面大小比值,用於播放時的展現寬高 |
「tkhd」的字節實例以下圖,各字段已經用顏色區分開:
4.2.2 Media Box(mdia)
「mdia」也是個container box,其子box的結構和種類仍是比較複雜的。先來看一個「mdia」的實例結構樹圖。
整體來講,「mdia」定義了track媒體類型以及sample數據,描述sample信息。通常「mdia」包含一個「mdhd」,一個「hdlr」和一個「minf」,其中「mdhd」爲media header box,「hdlr」爲handler reference box,「minf」爲media information box。下面依次看一下這幾個box的結構。
4.2.2.1 Media Header Box(mdhd)
「mdhd」結構以下表。
字段 |
字節數 |
意義 |
box size |
4 |
box大小 |
box type |
4 |
box類型 |
version |
1 |
box版本,0或1,通常爲0。(如下字節數均按version=0) |
flags |
3 |
|
creation time |
4 |
建立時間(相對於UTC時間1904-01-01零點的秒數) |
modification time |
4 |
修改時間 |
time scale |
4 |
同前表 |
duration |
4 |
track的時間長度 |
language |
2 |
媒體語言碼。最高位爲0,後面15位爲3個字符(見ISO 639-2/T標準中定義) |
pre-defined |
2 |
|
「mdhd」的字節實例以下圖,各字段已經用顏色區分開:
4.2.2.2 Handler Reference Box(hdlr)
「hdlr」解釋了媒體的播放過程信息,該box也能夠被包含在meta box(meta)中。「hdlr」結構以下表。
字段 |
字節數 |
意義 |
box size |
4 |
box大小 |
box type |
4 |
box類型 |
version |
1 |
box版本,0或1,通常爲0。(如下字節數均按version=0) |
flags |
3 |
|
pre-defined |
4 |
|
handler type |
4 |
在media box中,該值爲4個字符: 「vide」— video track 「soun」— audio track 「hint」— hint track |
reserved |
12 |
|
name |
不定 |
track type name,以‘\0’結尾的字符串 |
「hdlr」的字節實例以下圖,各字段已經用顏色區分開:
4.2.2.3 Media Information Box(minf)
「minf」存儲瞭解釋track媒體數據的handler-specific信息,media handler用這些信息將媒體時間映射到媒體數據並進行處理。「minf」中的信息格式和內容與媒體類型以及解釋媒體數據的media handler密切相關,其餘media handler不知道如何解釋這些信息。「minf」是一個container box,其實際內容由子box說明。
通常狀況下,「minf」包含一個header box,一個「dinf」和一個「stbl」,其中,header box根據track type(即media handler type)分爲「vmhd」、「smhd」、「hmhd」和「nmhd」,「dinf」爲data information box,「stbl」爲sample table box。下面分別介紹。
下圖爲「minf」部分字節實例,其中紅色爲box header,藍色爲「smhd」,綠色爲「dinf」,黃色爲一部分「stbl」。
4.2.2.3.1 Media Information Header Box(vmhd、smhd、hmhd、nmhd)
Video Media Header Box(vmhd)
字段 |
字節數 |
意義 |
box size |
4 |
box大小 |
box type |
4 |
box類型 |
version |
1 |
box版本,0或1,通常爲0。(如下字節數均按version=0) |
flags |
3 |
|
graphics mode |
4 |
視頻合成模式,爲0時拷貝原始圖像,不然與opcolor進行合成 |
opcolor |
2×3 |
{red,green,blue} |
Sound Media Header Box(smhd)
字段 |
字節數 |
意義 |
box size |
4 |
box大小 |
box type |
4 |
box類型 |
version |
1 |
box版本,0或1,通常爲0。(如下字節數均按version=0) |
flags |
3 |
|
balance |
2 |
立體聲平衡,[8.8] 格式值,通常爲0,-1.0表示所有左聲道,1.0表示所有右聲道 |
reserved |
2 |
|
Hint Media Header Box(hmhd)
略
Null Media Header Box(nmhd)
非視音頻媒體使用該box,略。
4.2.2.3.2 Data Information Box(dinf)
「dinf」解釋如何定位媒體信息,是一個container box。「dinf」通常包含一個「dref」,即data reference box;「dref」下會包含若干個「url」或「urn」,這些box組成一個表,用來定位track數據。簡單的說,track能夠被分紅若干段,每一段均可以根據「url」或「urn」指向的地址來獲取數據,sample描述中會用這些片斷的序號將這些片斷組成一個完整的track。通常狀況下,當數據被徹底包含在文件中時,「url」或「urn」中的定位字符串是空的。
「dref」的字節結構以下表。
字段 |
字節數 |
意義 |
box size |
4 |
box大小 |
box type |
4 |
box類型 |
version |
1 |
box版本,0或1,通常爲0。(如下字節數均按version=0) |
flags |
3 |
|
entry count |
4 |
「url」或「urn」表的元素個數 |
「url」或「urn」列表 |
不定 |
|
「url」或「urn」都是box,「url」的內容爲字符串(location string),「urn」的內容爲一對字符串(name string and location string)。當「url」或「urn」的box flag爲1時,字符串均爲空。
下面是一個「dinf」的字節實例圖。其中黃色爲「dinf」的box header,由紅色部分咱們知道包含的「url」或「urn」個數爲1,紅色後面爲「url」box的內容。紫色爲「url」的box header(根據box type咱們知道是個「url」),綠色爲box flag,值爲1,說明「url」中的字符串爲空,表示track數據已包含在文件中。
4.2.2.3.3 Sample Table Box(stbl)
「stbl」幾乎是普通的MP4文件中最複雜的一個box了,首先須要回憶一下sample的概念。sample是媒體數據存儲的單位,存儲在media的chunk中,chunk和sample的長度都可互不相同,以下圖所示。
「stbl」包含了關於track中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」包含了編碼的信息,其存儲的信息隨媒體類型不一樣而不一樣。
Sample Description Box(stsd)
box header和version字段後會有一個entry count字段,根據entry的個數,每一個entry會有type信息,如「vide」、「sund」等,根據type不一樣sample description會提供不一樣的信息,例如對於video track,會有「VisualSampleEntry」類型信息,對於audio track會有「AudioSampleEntry」類型信息。
視頻的編碼類型、寬高、長度,音頻的聲道、採樣等信息都會出如今這個box中。
Time To Sample Box(stts)
「stts」存儲了sample的duration,描述了sample時序的映射方法,咱們經過它能夠找到任什麼時候間的sample。「stts」能夠包含一個壓縮的表來映射時間和sample序號,用其餘的表來提供每一個sample的長度和指針。表中每一個條目提供了在同一個時間偏移量裏面連續的sample序號,以及samples的偏移量。遞增這些偏移量,就能夠創建一個完整的time to sample表。
Sample Size Box(stsz)
「stsz」 定義了每一個sample的大小,包含了媒體中所有sample的數目和一張給出每一個sample大小的表。這個box相對來講體積是比較大的。
Sample To Chunk Box(stsc)
用chunk組織sample能夠方便優化數據獲取,一個thunk包含一個或多個sample。「stsc」中用一個表描述了sample與chunk的映射關係,查看這張表就能夠找到包含指定sample的thunk,從而找到這個sample。
Sync Sample Box(stss)
「stss」肯定media中的關鍵幀。對於壓縮媒體數據,關鍵幀是一系列壓縮序列的開始幀,其解壓縮時不依賴之前的幀,然後續幀的解壓縮將依賴於這個關鍵幀。「stss」能夠很是緊湊的標記媒體內的隨機存取點,它包含一個sample序號表,表內的每一項嚴格按照sample的序號排列,說明了媒體中的哪個sample是關鍵幀。若是此表不存在,說明每個sample都是一個關鍵幀,是一個隨機存取點。
Chunk Offset Box(stco)
「stco」定義了每一個thunk在媒體流中的位置。位置有兩種可能,32位的和64位的,後者對很是大的電影頗有用。在一個表中只會有一種可能,這個位置是在整個文件中的,而不是在任何box中的,這樣作就能夠直接在文件中找到媒體數據,而不用解釋box。須要注意的是一旦前面的box有了任何改變,這張表都要從新創建,由於位置信息已經改變了。
五、Free Space Box(free或skip)
「free」中的內容是可有可無的,能夠被忽略。該box被刪除後,不會對播放產生任何影響。
六、Meida Data Box(mdat)
該box包含於文件層,能夠有多個,也能夠沒有(當媒體數據所有爲外部文件引用時),用來存儲媒體數據。數據直接跟在box type字段後面,具體數據結構的意義須要參考metadata(主要在sample table中描述)。
普通MP4文件的結構就講完了,可能會比較亂,下面這張圖是常見的box的樹結構圖,能夠用來大體瞭解MP4文件的構造。
這篇文章主要面向一些對MP4文件結構沒有太多瞭解的初學者,算是篇比較初級的文章,本人也是參考了一些資料寫出來的,對於MP4文件中涉及的一些概念沒有太深刻的瞭解,所以其中應該是有一些錯誤理解,但願你們抱着批判的眼光讀這篇文章。若是有錯誤的地方,還請你們不吝賜教。
該文主要參考了標準和網友wqyuwss的blog系列文章:mp4文件格式