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等。
一個mp4檔案有可能包含非常多的box(全部大約70多個),在很大程度上增加了解析的複雜性。如果要全部解析必要性不是很大。大部分mp4檔案沒有那麼多的box型別,下圖就是一個簡化了的,常見的mp4檔案結構:
下圖是節點box詳細說明:
下面我們將對以上主要box的解析進行詳細說明:
1. 一級box
一級box主要包含ftyp、moov、free、mdat等等。
1.1 ftyp box
結構:
/******************************************************************************************** ** File Type Box (ftyp) ** -------------------------------------------------------------------------------------------- ** 欄位名稱 | 長度(bytes) | 有關描述 -------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 4 | box的型別 ** major_brand | 4 | ** minor_version | 4 | 版本號 ** compatible_brands | 4 * N | 本檔案遵從的多種協議(ismo, iso2, mp41) ********************************************************************************************/
執行結果:
1.2 moov box
結構:
/******************************************************************************************** ** 欄位名稱 | 長度(bytes) | 有關描述 -------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 4 | box的型別 ********************************************************************************************/
1.3 free box
結構:
/******************************************************************************************** ** 欄位名稱 | 長度(bytes) | 有關描述 -------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 4 | box的型別 ********************************************************************************************/
1.4 mdat box
結構:
/******************************************************************************************** ** 欄位名稱 | 長度(bytes) | 有關描述 -------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 4 | box的型別 ** | 後面全是真實資料 ********************************************************************************************/
執行結果:
2. 二級box
本節所說的二級box皆為moov的子box,主要包含mvhd、trak、udat等等。
2.1 mvhd box
結構:
/************************************************************************************************************ ** mvhd ** -------------------------------------------------------------------------------------------- ** 欄位名稱 | 長度(bytes) | 有關描述 -------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 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時長 ** 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號 ************************************************************************************************************/
執行結果:
2.2 trak box
結構:
/******************************************************************************************** ** 欄位名稱 | 長度(bytes) | 有關描述 -------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 4 | box的型別 ********************************************************************************************/
2.3 udat box
結構:
/************************************************************************************************************ ** udat ** -------------------------------------------------------------------------------------------- ** 欄位名稱 | 長度(bytes) | 有關描述 -------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 4 | box的型別 ** | 使用者自定義資料解析 ************************************************************************************************************/
執行結果:
3. 三級box
本節所說的三級box皆為trak的子box,主要包含tkhd、mdia等。
3.1 tkhd box
結構:
/************************************************************************************************************ ** tkhd ** ------------------------------------------------------------------------------------------------------------- ** 欄位名稱 | 長度(bytes) | 有關描述 ------------------------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 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描述中的實際畫面大小比值,用於播放時的展示寬高 ************************************************************************************************************/
執行結果:
3.2 mdia box
結構:
/******************************************************************************************** ** 欄位名稱 | 長度(bytes) | 有關描述 -------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 4 | box的型別 ********************************************************************************************/
4. 四級box
本節所說的四級box皆為mdia的子box,主要包含mdhd、hdlr、minf等。
4.1 mdhd box
結構:
/************************************************************************************************************ ** tkhd ** ------------------------------------------------------------------------------------------------------------- ** 欄位名稱 | 長度(bytes) | 有關描述 ------------------------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 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 | 保留位 ************************************************************************************************************/
結果:
4.2 hdlr box
結構:
/************************************************************************************************************ ** hdlr ** ------------------------------------------------------------------------------------------------------------- ** 欄位名稱 | 長度(bytes) | 有關描述 ------------------------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 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’結尾的字串 ************************************************************************************************************/
結果:
4.3 minf box
結構:
/******************************************************************************************** ** 欄位名稱 | 長度(bytes) | 有關描述 -------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 4 | box的型別 ********************************************************************************************/
5. 五級box
本節所說的五級box皆為minf的子box,主要包含header box(vmhd/smhd/hmld/nmld)、stbl等。
5.1 header box
本處的headerbox會根據前面的handler type數值選擇哪個box。
"vide"—vmhd 視訊
"soun"— smhd 音訊
"hint"—hmhd 忽略
vmhd結構:
/************************************************************************************************************ ** vmhd ** ------------------------------------------------------------------------------------------------------------- ** 欄位名稱 | 長度(bytes) | 有關描述 ------------------------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 4 | box的型別 ** version | 1 | box版本0或1 一般為0 (以下位元組數均按version=0) ** flags | 3 | ** graphics_mode | 4 | 視訊合成模式,為0時拷貝原始影象,否則與opcolor進行合成 ** opcolor | 2 ×3 | {red,green,blue} ************************************************************************************************************/
結果:
5.2 stbl box
結構:
/******************************************************************************************** ** 欄位名稱 | 長度(bytes) | 有關描述 -------------------------------------------------------------------------------------------- ** boxsize | 4 | box的長度 ** boxtype | 4 | box的型別 ********************************************************************************************/
6. 六級box
本節所說的六級box皆為stbl的子box,主要包含stsd、stts、stsz、stsc、stss、stco等,這些也是mp4檔案設計的精髓所在,主要控制chunk、sample、mdat之間的對映關係。
6.1 stsd box
stsd: Sample Description Box,解析stsd可獲得coding型別、視訊寬高、音訊samplesize、channelcount這些和解碼器有關資訊。
6.2 stts box
stts: Decoding Time to Sample Box,時間戳和Sample對映表
上圖是一個video trak,說明該視訊包含87幀資料,每幀包含512個取樣。
總共512*87=44544個取樣,和我們前面mdhd box的Duration完全一致。
Duration / TimeScale = 44544 / 12288 = 3.625秒 正是我們的視訊播放長度。
12288 / 512 = 24 p/s (幀率)。
6.3 stsz box
stsz, stz2: Sample Size Boxes,每個Sample大小的表
一共87幀 每幀的位元組大小。
6.4 stsc box
stsc: Sample to chunk 的對映表。
前面說了一共87幀資料,放在83個chunk中。1~82個chunk每個裡面放1幀,第83個chunk放了5幀。
6.5 stss box
stss: 關鍵幀索引表。
第1、13、25、37、49、61、73、85.... 這些幀都是關鍵幀。
每12幀就有一個關鍵幀, 前面我們計算得知fps是24。由此可知該視訊關鍵幀間隔為0.5秒。
6.6 stco box
'stco','co64': Chunk位置偏移表
一共83個chunk,記錄在mdat真實資料中的位元組偏移量。
下圖為第三方MP4檔案解析結果:
MP4檔案格式解析原始碼:https://github.com/kingsunc/AVFileParse
MP4分割實現原始碼:https://github.com/kingsunc/AVFileParse/tree/master/Mp4_Segment