媒體文件格式分析之FMP4


媒體文件格式分析之FMP4

MP4 中最基本的單元就是Box,它內部是通過一個一個獨立的Box拼接而成的。所以,這里,我們先從 Box 的講解開始,每個 Box 是由 Header 和 Data 組成的,FullBox 是 Box 的擴展,Box 結構的基礎上在 Header 中增加 8bits version 和 24bits flags

1. 名詞解釋

2. 最小單元Box

2.1 常見的mp4文件結構(簡化版)

 
normal_box_file.jpg

3. Mp4文件整體結構

這里,我們按照 MP4 box 的划分來進行相關的闡述。先看一張 MP4 給出的結構圖:

 
box_structure.png

一般來說,解析媒體文件,最關心的部分是視頻文件的寬高、時長、碼率、編碼格式、幀列表、關鍵幀列表,以及所對應的時戳和在文件中的位置,這些信息,在mp4中,是以特定的算法分開存放在stbl box下屬的幾個box中的,需要解析stbl下面所有的box,來還原媒體信息。下表是對於以上幾個重要的box存放信息的說明

 
majorbox.jpg

3.1 File Type Box (ftyp)

通常放在MP4文件的開頭,告訴解碼器基本的解碼版本和兼容格式。

  • 基本格式如下:
aligned(8) class FileTypeBox extends Box(‘ftyp’) { unsigned int(32) major_brand; unsigned int(32) minor_version; unsigned int(32) compatible_brands[]; } 
  • 字段說明:
字段 長度 說明 默認值
major_brand 4 推薦兼容性的版本 iso6
minor_version 4 最低兼容性的版本 1
compatible_brands 列表值 所有的兼容性的版本 'iso6' 'isom' 'dash'
  • Nginx模塊實現
ngx_int_t
ngx_rtmp_mp4_write_ftyp(ngx_buf_t *b) { u_char *pos; pos = ngx_rtmp_mp4_start_box(b, "ftyp"); /* major brand */ ngx_rtmp_mp4_box(b, "iso6"); /* minor version */ ngx_rtmp_mp4_field_32(b, 1); /* compatible brands */ ngx_rtmp_mp4_box(b, "isom"); ngx_rtmp_mp4_box(b, "iso6"); ngx_rtmp_mp4_box(b, "dash"); ngx_rtmp_mp4_update_box_size(b, pos); return NGX_OK; } 

3.2 Movie Box (moov)

作為容器盒子,存放相關的trak及meta信息.

  • 基本格式如下:
aligned(8) class MovieExtendsBox extends Box(‘mvex’){ } 

3.2.1 Movie Header Box (mvhd)

mvhd 是 moov 下的第一個 box,用來描述 media 的相關信息:

  • 基本格式如下:
aligned(8) class MovieHeaderBox extends FullBox(‘mvhd’, version, 0) { if (version==1) { unsigned int(64) creation_time; unsigned int(64) modification_time; unsigned int(32) timescale; unsigned int(64) duration; } else { // version==0 unsigned int(32) creation_time; unsigned int(32) modification_time; unsigned int(32) timescale; unsigned int(32) duration; } template int(32) rate = 0x00010000; // typically 1.0 template int(16) volume = 0x0100; // typically, full volume const bit(16) reserved = 0; const unsigned int(32)[2] reserved = 0; template int(32)[9] matrix = { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 }; // Unity matrix bit(32)[6] pre_defined = 0; unsigned int(32) next_track_ID; } 
  • 字段說明:
字段 長度 說明 默認值
version 4 版本 0 or 1s
creation_time 4 創建的UTC時間。從1904年開始算起, 用秒來表示
modification_time 4 最后一次修改時間
timescale 4 文件媒體在1秒時間內的刻度值,可以理解為1秒長度的時間單元數
duration 4 該track的時間長度,用duration和time scale值可以計算track時長s 實際時間為:duration/timescale = xx 秒
rate 4 推薦播放速率 0x00010000
volume 2 音量大小 0x0100 為最大值
reserved 10 保留字段 0
matrixs 4 * 9 視頻變換矩陣 {0x00010000,0,0,0,0x0001s0000,0,0,0,0x40000000}
next_track_ID 4 下一個track使用的id號  
  • Nginx模塊實現
static ngx_int_t ngx_rtmp_mp4_write_mvhd(ngx_buf_t *b) { u_char *pos; pos = ngx_rtmp_mp4_start_box(b, "mvhd"); /* version */ ngx_rtmp_mp4_field_32(b, 0); /* creation time */ ngx_rtmp_mp4_field_32(b, 0); /* modification time */ ngx_rtmp_mp4_field_32(b, 0); /* timescale */ ngx_rtmp_mp4_field_32(b, 1000); /* duration */ ngx_rtmp_mp4_field_32(b, 0); /* reserved */ ngx_rtmp_mp4_field_32(b, 0x00010000); ngx_rtmp_mp4_field_16(b, 0x0100); ngx_rtmp_mp4_field_16(b, 0); ngx_rtmp_mp4_field_32(b, 0); ngx_rtmp_mp4_field_32(b, 0); ngx_rtmp_mp4_write_matrix(b, 1, 0, 0, 1, 0, 0); /* reserved */ ngx_rtmp_mp4_field_32(b, 0); ngx_rtmp_mp4_field_32(b, 0); ngx_rtmp_mp4_field_32(b, 0); ngx_rtmp_mp4_field_32(b, 0); ngx_rtmp_mp4_field_32(b, 0); ngx_rtmp_mp4_field_32(b, 0); /* next track id */ ngx_rtmp_mp4_field_32(b, 1); ngx_rtmp_mp4_update_box_size(b, pos); return NGX_OK; } 

3.2.2 Movie Extends Box (mvex)(fMP4專有)

mvex 是 fMP4 的標准盒子。它的作用是告訴解碼器這是一個fMP4的文件,具體的 samples 信息內容不再放到 trak 里面,而是在每一個 moof 中。基本格式為:


aligned(8) class MovieExtendsHeaderBox extends FullBox(‘mehd’, version, 0) { if (version==1) { unsigned int(64) fragment_duration; } else { // version==0 unsigned int(32) fragment_duration; } } 
3.2.2.1 Track Extends Box (trex)(fMP4專有)

trex 是 mvex 的子一級 box 用來給 fMP4 的 sample 設置默認值。基本內容為

aligned(8) class TrackExtendsBox extends FullBox(‘trex’, 0, 0){ unsigned int(32) track_ID; unsigned int(32) default_sample_description_index; unsigned int(32) default_sample_duration; unsigned int(32) default_sample_size; unsigned int(32) default_sample_flags } 

3.2.3 Track Box (trak)

trak box 就是主要存放相關 media stream 的內容。

3.2.3.1 Track Header Box (tkhd)

tkhd 是 trak box 的子一級 box 的內容。主要是用來描述該特定 trak 的相關內容信息。其主要內容為:

  • 基本格式如下:

aligned(8) class TrackHeaderBox extends FullBox(‘tkhd’, version, flags){ if (version==1) { unsigned int(64) creation_time; unsigned int(64) modification_time; unsigned int(32) track_ID; const unsigned int(32) reserved = 0; unsigned int(64) duration; } else { // version==0 unsigned int(32) creation_time; unsigned int(32) modification_time; unsigned int(32) track_ID; const unsigned int(32) reserved = 0; unsigned int(32) duration; } const unsigned int(32)[2] reserved = 0; template int(16) layer = 0; template int(16) alternate_group = 0; template int(16) volume = {if track_is_audio 0x0100 else 0}; const unsigned int(16) reserved = 0; template int(32)[9] matrix= { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 }; // unity matrix unsigned int(32) width; unsigned int(32) height; } 
  • 字段說明:
字段 長度 說明 默認值
version 4 版本  
creation_time 4 創建時間,非必須 0
modification_time 4 修改時間,非必須 0
track_ID 4 指明當前描述的 track ID 1
reserved 4 保留 0
duration 4 當前 track 內容持續的時間。通常結合 timescale 進行相關計算 0
reserved 12 保留字段 0
reserved 2 保留字段 0
alternate_group 2 保留字段 0
volume 2 保留字段 if track_is_audio 0x0100 else 0
reserved 2 保留字段 0
matrix 9 * 4 matrix b, 1, 0, 0, 1, 0, 0 , width , height
3.2.3.2 Media Box (media)

mdia 主要用來包裹相關的 media 信息。

(1) Media Header Box (mdhd)
  • 基本格式如下:
aligned(8) class MediaHeaderBox extends FullBox(‘mdhd’, version, 0) { if (version==1) { unsigned int(64) creation_time; unsigned int(64) modification_time; unsigned int(32) timescale; unsigned int(64) duration; } else { // version==0 unsigned int(32) creation_time; unsigned int(32) modification_time; unsigned int(32) timescale; unsigned int(32) duration; } bit(1) pad = 0; unsigned int(5)[3] language; // ISO-639-2/T language code unsigned int(16) pre_defined = 0; } 
  • 字段說明:
字段 長度 說明 默認值
version 4 版本  
creation_time 4 創建時間,非必須 0
modification_time 4 修改時間,非必須 0
timescale 4 文件媒體在1秒時間內的刻度值,可以理解為1秒長度的時間單元數
duration 4 當前 track 內容持續的時間。通常結合 timescale 進行相關計算 0
lanuage 4s 表明當前 trak 的語言。因為該字段總長為 15bit,通常是和 pad 組合成為 2B 的長度。 -
(2) Handler Reference Box(hdlr)
  • 基本格式如下:

aligned(8) class HandlerBox extends FullBox(‘hdlr’, version = 0, 0) { unsigned int(32) pre_defined = 0; unsigned int(32) handler_type; const unsigned int(32)[3] reserved = 0; string name; } 
  • 字段說明:
字段 長度 說明 默認值
version 4 版本  
pre_defined 4 版本 0
handler_type 4 是代指具體 trak 的處理類型 0
reserved 4 * 3 reserved 0
data string reserved "VideoHandler" or "SoundHandler"
  • handler_type 類型如下:
    vide : Video track
    soun : Audio track
    hint : Hint track
    meta : Timed Metadata track
    auxv : Auxiliary Video track

3.2.3.3 Media Information Box (minf)

minf 是子屬內容中,重要的容器 box,用來存放當前 track 的基本描述信息。

(1) Video Media Header Box(vmhd)
  • 基本格式如下:
aligned(8) class VideoMediaHeaderBox extends FullBox(‘vmhd’, version = 0, 1) { template unsigned int(16) graphicsmode = 0; // copy, see below template unsigned int(16)[3] opcolor = {0, 0, 0}; } 
(2) Sound Media Header Box(smhd)
  • 基本格式如下:
aligned(8) class SoundMediaHeaderBox extends FullBox(‘smhd’, version = 0, 0) { template int(16) balance = 0; const unsigned int(16) reserved = 0; } 
(3) Data Information Box(dinf)

dinf 是用來說明在 trak 中,media 描述信息的位置。其實本身就是一個容器,沒啥內容:

  • 基本格式如下:
aligned(8) class SoundMediaHeaderBox extends FullBox(‘smhd’, version = 0, 0) { template int(16) balance = 0; const unsigned int(16) reserved = 0; } 
(4) Data Reference Box(dref)

dref 是用來設置當前Box描述信息的 data_entry。

  • 基本格式如下:
aligned(8) class DataReferenceBox extends FullBox(‘dref’, version = 0, 0) { unsigned int(32) entry_count; for (i=1; i <= entry_count; i++) { DataEntryBox(entry_version, entry_flags) data_entry; } } 
  • 字段說明:
字段 長度 說明 默認值
version 4 版本 0
entry_count 4 入口數 1
entry_version 4 入口數 0
entry_flags 3 入口數 0

3.3 Moof Box

3.4 Sidxs Box



作者:lo踏風
鏈接:https://www.jianshu.com/p/dee55d54fd54
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM