多媒體檔案格式(一):MP4 格式
在網際網路常見的格式中,跨平臺最好的應該就屬MP4檔案了。因為MP4檔案既可以在PC平臺的Flashplayer中播放,又可以在移動平臺的Android、iOS等平臺中進行播放,而且使用系統預設的播放器即可以播放。
MP4格式是最常見的多媒體檔案格式。
一、MP4 格式標準介紹
MP4格式標準為ISO-14496 Part 12、ISO-14496 Part 14,標準內容不是很多,下面我們來介紹一下格式標準中一些重要的資訊。
MP4是一種描述較為全面的容器格式,被認為可以在其中嵌入任何形式的資料,各種編碼的視訊、音訊等都不在話下,常見的大部分的MP4檔案存放的AVC(H.264)或MPEG-4(Part 2)編碼的視訊和AAC編碼的音訊。MP4格式的官方檔案字尾名是“.mp4”,還有其他的以mp4為基礎進行的擴充套件或者是閹割版的格式,如:M4V, 3GP, F4V等。
MP4是由一個個“Box”組成的,大Box中存放小Box,一級巢狀一級來存放媒體資訊。下面我們來楚關於Box的幾個概念:
- MP4檔案由許多個Box與FullBox組成。
- 每個Box由Header和Data兩部分組成。
- FullBox是Box的擴充套件,其在Box結構的基礎上,在Header中增加8位version標誌和24的flags標誌。
- Header包含了整個Box的長度的大小(size)和型別(type),當size等於0時,代表這個Box是檔案的最後一個Box。當size等於1時,說明Box長度需要更多的位來描述,在後面會自定義一個64位的largesize用來描述Box的長度。當type等於uuid時,說明這個Box中的資料是使用者自定義擴充套件型別。
- Data為Box的實際資料,可以是純資料,也可以是更多的子Box。
- 當一個Box中Data是一系列的子Box時,這個Box又可以稱為Container(容器)Box。
下圖是我整理的 MP4常用參考標準Box排列方式 :
(圖內容有點多,看不清楚的,可以儲存圖片到本地後放大檢視)
也可以到本人的github上下載原圖: https://github.com/renhui/Thinking-in-AV/tree/master/多媒體格式/MP4
介紹了MP4的格式標準後,下面我們來介紹是三個MP4分析工具,為後續理解MP4檔案一些關鍵資訊做輔助工具。
二、MP4分析工具
可以用來分析MP4封裝格式的工具比較多,除了FFmpeg、FFprobe之外,還有一些常用的工具,如Elecard StreamEye、mp4box、mp4info等;下面簡單介紹一下這幾款常用的工具:
1. Elecard StreamEye
Elecard StreamEye是一款非常強大的視訊資訊檢視工具,能夠檢視幀的排列資訊,將I幀、P幀、B幀以不同顏色的柱狀展現出來,而且柱的長短將根據幀的大小展示。還能夠通過Elecard StreamEye分析MP4的封裝的內容資訊,包括流資訊、巨集塊的資訊、檔案頭頂額資訊、影象的資訊以及檔案的資訊等。還能根據每一幀的順序逐幀檢視,可以看到每一幀的詳細資訊與狀態。
示例如圖:
2. mp4box
mp4box 是GPAC專案中的一個元件,可以通過mp4box針對媒體檔案進行合成、拆解等操作。
官網地址: https://gpac.wp.imt.fr/mp4box/ 。
其使用時的常用命令如下:
1) mp4box -h 檢視mp4box中的所有幫助資訊 2) mp4box -h general 檢視mp4box中的通用幫助資訊 3) mp4box -info test.mp4 檢視test.mp4檔案是否有問題 4) mp4box-addtest.mp4test-new.mp4 修復test.mp4檔案格式不標準的問題,並把新檔案儲存在test-new.mp4中 5) mp4box-inter10000 test-new.mp4 解決開始播放test-new.mp4卡一下的問題,為HTTP下載快速播放有效,10000ms 6) mp4box -add file.avi new_file.mp4 把avi檔案轉換為mp4檔案 7) mp4box -hint file.mp4 為RTP準備,此指令將為檔案建立RTP提示跟蹤資訊。這使得經典的流媒體伺服器像darwinstreamingserver或QuickTime的流媒體伺服器通過RTSP/RTP傳輸檔案 8) mp4box -cat test1.mp4 -cat test2.mp4 -new test.mp4 把test1.mp4和test2.mp4合併到一個新的檔案test.mp4中,要求編碼引數一致 9) mp4box -force-cat test1.mp4 -force-cat test2.mp4 -new test.mp4 把test1.mp4和test2.mp4強制合併到一個新的檔案test.mp4中,有可能不能播放 10) mp4box -add video1.264 -cat video2.264 -cat video3.264 -add audio1.aac -cat audio2.aac -cat audio3.aac -new muxed.mp4 -fps 24 合併多段音視訊並保持同步 11) mp4box -split *time_sec* test.mp4 切取test.mp4中的前面time_sec秒的視訊檔案 12) mp4box -split-size *size *test.mp4 切取前面大小為size KB的視訊檔案 13) mp4box -split-chunk *S:E* test.mp4 切取起始為S少,結束為E秒的視訊檔案 14) mp4box -add 1.mp4#video -add 2.mp4#audio -new test.mp4 test.mp4由1.mp4中的視訊與2.mp4中的音訊合併生成
而通過mp4box也可以檢視mp4的資訊,其輸出內容格式非常類似ffprobe檢視的資訊,不過想對ffprobe更完善。
3. mp4info
mp4info是一個不錯的MP4分析工具,而且是視覺化的工具,可以將MP4中的各個Box解析出來,並將其中的資料展現出來。分析MP4檔案內容時使用mp4info將會更方便。
結合著此工具,理解MP4的Box會更方便,更直觀。
三、MP4格式重要Box
1. ftyp( File Type Box )
該Box有且只有1個,並且只能被包含在檔案層,而不能被其他Box包含。該Box應該被放在檔案的最開始,指示該MP4檔案應用的相關資訊。
“ftyp” body依次包括1個32位的major brand(4個字元),1個32位的minor version(整數)和1個以32位(4個字元)為單位元素的陣列Compatible Brands。
2. moov(Movie Box)
該box包含了檔案媒體的metadata資訊,“moov”是一個container box,具體內容資訊由子box詮釋。同File Type Box一樣,該box有且只有一個,且只被包含在檔案層。一般情況下,“moov”會緊隨“ftyp”出現。
moov定義了一個MP4檔案中的資料資訊,型別是moov,是一個容器Atom,其至少必須包含一下三種Atom中的一種:mvhd標籤、cmov標籤、rmra標籤。
- mvhd標籤:Movie Header Atom,存放未壓縮過的影片資訊的頭容器。
- cmov標籤:Compressed Movie Atom,壓縮鬼哦的電影資訊容器,此容器不常用。
- rmra標籤:Reference Movie Atom,參考電影資訊容器,此容器不常用。
一般情況下,“moov”中會包含1個“mvhd”和若干個“trak”。其中“mvhd”為Header Box,一般作為“moov”的第一個子Box出現(對於其他Container Box來說,Header Box都應作為首個子box出現)。“trak”包含了一個track的相關資訊,是一個Container Box。
3. trak( Track Box )
“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。
4. mdat( Meida Data Box)
該box包含於檔案層,可以有多個,也可以沒有(當媒體資料全部為外部檔案引用時),用來儲存媒體資料。資料直接跟在box type欄位後面,具體資料結構的意義需要參考metadata(主要在sample table中描述)。
5. free或 skip( Free Space Box )
“ free”中的內容是無關緊要的,可以被忽略。該 box被刪除後,不會對播放產生任何影響。
6. stbl(Sample Table Box)
“ stbl”幾乎是普通的 MP4檔案中最複雜的一個 box了,首先需要回憶一下 sample的概念。 sample是媒體資料儲存的單位,儲存在 media的 chunk中, chunk和 sample的長度均可互不相同,如下圖所示。
普通MP4檔案的結構重要的部分就講完了,理解起來可能比較亂,下面這張圖是常見的box的樹結構圖,可以用來大致瞭解MP4檔案的構造。
在MP4檔案中,Box的結構與上圖中所描述的一般沒太大的差別。
四、MP4格式 與 FFmpeg實戰
1. 在FFmpeg中的輸出MP4的Demuxer資訊
使用命令列 ffmpeg -h demuxder=mp4 檢視MP4檔案的Demuxer資訊:
Demuxer mov,mp4,m4a,3gp,3g2,mj2 [QuickTime / MOV]: Common extensions: mov,mp4,m4a,3gp,3g2,mj2.
2. 通過FFmepg faststart引數的使用,來理解mdat和moov的順序的意義
正常情況下,ffmpeg生成的moov是在mdat寫完成後再寫入的。
下面是一個例子:
ffmpeg -i 好漢歌.flv -c copy -f mp4 好漢歌.mp4
使用mp4info檢視容器出現的順序,如圖:
可以看出moov box是在mdat的下面。這時,我們可以使用faststart將上圖的moov移動到mdat前面。
使用如下命令列:
ffmpeg -i 好漢歌.flv -c copy -f mp4 -movflags faststart 好漢歌.mp4
然後使用mp4info檢視MP4的容器順序,就可以看到moov被移動到mdat前面了。如下圖所示:
因為MP4的標準中描述的moov與mdat的存放位置前後並沒有強制要求,所有有些時候moov這個Box在mdat的後面,有時候在mdat的前面。
在網際網路的視訊點播中,如果希望MP4檔案被快速開啟,則需要moov存放在mdat的前面;如果放在後面,則需要將MP4檔案下載完成後才可以進行播放。