目錄
概述
mp4文件基本信息
封裝格式重要概念
重要box介紹
其他box介紹
實用技術(shù)
開源軟件
參考
[3]wikipedia/ISO base media file format
[6]Phil Cluff/What's in the box_!
[8]tao/Android音視頻系列:視頻容器操作篇 -- mp4容器打包實現(xiàn)
[10]Jameson Steiner/Fun with Container Formats? – Part 2
1. 概述
mp4或稱MPEG-4 Part 14,是一種多媒體容器格式,擴(kuò)展名為.mp4。
歷史[6]:
2001年,apple的QuickTime格式,.qt和.mov的后綴名。
2001年,MPEG-4 Part1,把基于QuickTime的box布局的容器格式添加到了MPEG-4標(biāo)準(zhǔn)。
2004年,標(biāo)準(zhǔn)文檔把編碼和容器格式的說明分開。
MPEG-4 Part12,定義了容器格式通用的box結(jié)構(gòu),即ISO媒體文件格式(ISO base media file format, ISOBMFF)。
MPEG-4 Part14,基于Part12進(jìn)行了細(xì)化,定義了用于存儲MPEG-4內(nèi)容的容器格式,即.mp4格式。

圖1 MP4 File Format.png
以下是各標(biāo)準(zhǔn)文檔的鏈接:
QuickTime:QuickTime/QTFF
MPEG-4 Part12:ISO/IEC 14496-12:2015
MPEG-4 Part14:ISO/IEC 14496-14:2018,官網(wǎng)上這部分是付費的。
MP4文件由許多box組成,每個box包含不同的信息, 這些box以樹形結(jié)構(gòu)的方式組織。以下是主要box的簡要說明:

圖2 主要box說明
根節(jié)點之下,主要包含三個節(jié)點:ftyp、moov、mdat。
ftyp:文件類型。描述遵從的規(guī)范的版本。
moov box:媒體的metadata信息。
mdat:具體的媒體數(shù)據(jù)。
說明:在 mp4 中默認(rèn)寫入字節(jié)序是 Big-Endian的。
2. mp4文件基本信息
分析mp4文件的工具:
mp4box.js:一個在線解析mp4的工具。
bento4:包含mp4dump、mp4edit、mp4encrypt等工具。
MP4Box:類似于bento4,包含很全面的工具。
mp4info.exe: windows平臺圖形界面展示mp4基本信息的工具。
下圖為使用mp4info.exe打開mp4文件的界面:
圖3 mp4info.PNG
mp4文件基本信息
audio信息:
smplrate:sample rate(采樣率)。
channel:通道個數(shù)。
bitrate:比特率。
audiosamplenum:音頻sample的個數(shù)。
video信息:
width、height:視頻的寬/高。
bitrate:比特率(碼率),秒為單位。等于視頻總的大小/時長。
frames:視頻幀數(shù)。
fps:幀率(frame per second)。
total_time:時間長度,ms為單位。等于duration/timescale。
timescale:時間的粒度,1000表示1000個單位為1s。
duration:時間粒度的個數(shù)。
videosamplenum:視頻sample的個數(shù)。
3. 封裝格式重要概念
3.1 box
mp4文件由若干個box組成。下面是box結(jié)構(gòu)的一個示意圖。

圖4 mp4_box.png
box由header和body組成,header指明box的size和type。size是包含box header的整個box的大小。
box type,通常是4個ASCII碼的字符如“ftyp”、“moov”等,這些box type都是已經(jīng)預(yù)定義好的,表示固定的含義。如果是“uuid”,表示該box為用戶自定義擴(kuò)展類型,如果box type是未定義的,應(yīng)該將其忽略。
如果header中的size為1,則表示box長度需要更多的bits位來描述,在后面會有一個64bits位的largesize用來描述box的長度。如果size為0,表示該box為文件的最后一個box,文件結(jié)尾(同樣只存在于“mdat”類型的box中)。
box中可以包含box,這種box稱為container box。
box分為兩種,Box和Fullbox。FullBox 是 Box 的擴(kuò)展,Header 中增加了version 和 flags字段,分別定義如下:
aligned(8)classBox(unsignedint(32)boxtype,optionalunsignedint(8)[16]extended_type){unsignedint(32)size;unsignedint(32)type=boxtype;if(size==1){unsignedint(64)largesize;}elseif(size==0){// box extends to end of file}if(boxtype==‘uuid’){unsignedint(8)[16]usertype=extended_type;}}
FullBox有version和flags字段,
aligned(8)classFullBox(unsignedint(32)boxtype,unsignedint(8)v,bit(24)f)extendsBox(boxtype){unsignedint(8)version=v;bit(24)flags=f;}
3.2 track
一些sample的集合,對于媒體數(shù)據(jù)來說,track表示一個視頻或者音頻序列。
3.3 sample
video sample即為一幀或者一組連續(xù)視頻幀,audio sample即為一段連續(xù)的音頻。
3.4. sample table
指明sample時序和物理布局的表。
3.5. chunk
一個track的幾個sample組成的單元。
mp4文件中,媒體內(nèi)容在moov的box中。一個moov包含多個track。每個track就是一個隨時間變化的媒體序列,track里的每個時間單位是一個sample,sample按照時間順序排列。注意,一幀音頻可以分解成多個音頻sample,所以音頻一般用sample作為單位,而不用幀。
4. 重要box介紹
4.1 Sample Table Box(stbl)
“stbl”是mp4文件中最復(fù)雜的一個box了,也是解開mp4文件格式的主干。
stbl :sample table是一個container box。
語法:
classSampleTableBoxextendsBox(‘stbl’){}
其子box包括:
stsd:sample description box,樣本的描述信息。
stts:time to sample box,sample解碼時間的壓縮表。
ctts:composition time to sample box,sample的CTS與DTS的時間差的壓縮表。
stss:sync sample box,針對視頻,關(guān)鍵幀的序號。
stsz/stz2:sample size box,每個sample的字節(jié)大小。
stsc:sample to chunk box,sample-chunk映射表。
stco/co64:chunk offset box,chunk在文件中的偏移。
sample是媒體數(shù)據(jù)存儲的單位,存儲在media的chunk中,chunk和sample的長度均可互不相同,如下圖所示。

圖5 sample.jpg
4.2 Sample Description Box(stsd)
存儲了編碼類型和初始化解碼器需要的信息。
有與特定的track-type相關(guān)的信息,相同的track-type也會存在不同信息的情況如使用不一樣的編碼標(biāo)準(zhǔn)。
語法:
classSampleDescriptionBox(unsignedint(32)handler_type)extendsFullBox('stsd',0,0){int i;unsignedint(32)entry_count;for(i=1;i<=entry_count;i++){switch(handler_type){case‘soun’:// for audio tracksAudioSampleEntry();break;case‘vide’:// for video tracksVisualSampleEntry();break;case‘hint’:// Hint trackHintSampleEntry();break;case‘meta’:// Metadata trackMetadataSampleEntry();break;}}}}
主要字段說明:
entry count:entry的個數(shù)。
handler_type:類型信息如“vide”、“soud”等,不同類型會提供不同的信息。
對于audio track,使用“AudioSampleEntry”類型信息。
abstract class SampleEntry(unsignedint(32)format)extendsBox(format){constunsignedint(8)[6]reserved=0;unsignedint(16)data_reference_index;}classAudioSampleEntry(codingname)extends SampleEntry(codingname){constunsignedint(32)[2]reserved=0;templateunsignedint(16)channelcount=2;templateunsignedint(16)samplesize=16;unsignedint(16)pre_defined=0;constunsignedint(16)reserved=0;templateunsignedint(32)samplerate={defaultsamplerate of media}<<16;}
format:視頻或者音頻的編碼格式。
比如aac音頻的format值為mp4a。
AVC-1/H.264視頻的format值為avc1。
data_reference_index:利用這個索引可以檢索與當(dāng)前sample description關(guān)聯(lián)的數(shù)據(jù)。數(shù)據(jù)引用存儲在data reference box。
channelcount:通道個數(shù)。
samplesize:采樣位數(shù)。默認(rèn)是16比特。
samplerate:采樣率。[16.16]格式的數(shù)據(jù)。
對于video track,使用“VisualSampleEntry”類型信息。
classVisualSampleEntry(codingname)extends SampleEntry(codingname){unsignedint(16)pre_defined=0;constunsignedint(16)reserved=0;unsignedint(32)[3]pre_defined=0;unsignedint(16)width;unsignedint(16)height;templateunsignedint(32)horizresolution=0x00480000;// 72 dpitemplateunsignedint(32)vertresolution=0x00480000;// 72 dpiconstunsignedint(32)reserved=0;templateunsignedint(16)frame_count=1;string[32]compressorname;templateunsignedint(16)depth=0x0018;int(16)pre_defined=-1;// other boxes from derived specificationsCleanApertureBox clap;// optionalPixelAspectRatioBox pasp;// optional}
width、height:像素寬高。
horizresolution、vertresolution:每英寸的像素值(dpi),[16.16]格式的數(shù)據(jù)。
frame_count:每個sample中的視頻幀數(shù),默認(rèn)是1??梢允且粋€sample中有多幀數(shù)據(jù)。
4.3 Decoding Time to Sample Box(stts)
包含了一個壓縮版本的表,通過這個表可以從解碼時間映射到sample序號。表中的每一項是連續(xù)相同的編碼時間增量(Decode Delta)的個數(shù)和編碼時間增量。通過把時間增量累加就可以建立一個完整的time to sample表。
以下是Decoding Timing和Decode delta關(guān)系的一個圖示:
圖6 STTS_sample.PNG
DT(decoding time):編碼時間。
CT(composition time):創(chuàng)作時間。
Decode Delta:編碼時間增量。
Composition offset:顯示時間同解碼時間的差值,等于CT - DT。
計算方式:
DT(n+1)=DT(n)+STTS(n)whereSTTS(n)注:這里的STTS(n)是未壓縮的DecodeDelta表。DT(i)=SUM(forj=0to i-1ofdelta(j))
語法:
classTimeToSampleBoxextendsFullBox(’stts’,version=0,0){unsignedint(32)entry_count;inti;for(i=0;i<entry_count;i++){unsignedint(32)sample_count;unsignedint(32)sample_delta;}}
重要字段說明:
entry_count:表中條目的個數(shù)。
sample_count: 連續(xù)相同時間長度的sample個數(shù)。
sample_delta:以timescale為單位的時間長度。
4.4 composition time to sample box(ctts)
這個box提供了decoding time到composition time的offset的表,用于計算pts。
這個表在Decoding time和composition time不一樣的情況下時必須的。
如果box的version等于0,decoding time必須小于等于composition time,因而差值用一個無符號的數(shù)字表示。
有以下公式:
注:CTTS(n)是未壓縮的表的第n個sample對應(yīng)的offset。
語法:
classCompositionOffsetBoxextendsFullBox(‘ctts’,version=0,0){unsignedint(32)entry_count;inti;if(version==0){for(i=0;i<entry_count;i++){unsignedint(32)sample_count;unsignedint(32)sample_offset;}}elseif(version==1){for(i=0;i<entry_count;i++){unsignedint(32)sample_count;signedint(32)sample_offset;}}}
主要字段說明:
sample_count:連續(xù)相同的offset的個數(shù)。
sample_offset:CT和DT之間的offset。
4.5 sync sample box(stss)
它包含media中的關(guān)鍵幀的sample表。如果此表不存在,說明每一個sample都是一個關(guān)鍵幀。
語法:
classSyncSampleBoxextendsFullBox(‘stss’,version=0,0){unsignedint(32)entry_count;int i;for(i=0;i<entry_count;i++){unsignedint(32)sample_number;}}
主要字段說明:
sample_number:媒體流中同步sample的序號。
4.6 Sample Size Box(stsz/stz2)
包含sample的數(shù)量和每個sample的字節(jié)大小,這個box相對來說體積比較大的。
語法:
classSampleSizeBoxextendsFullBox(‘stsz’,version=0,0){unsignedint(32)sample_size;unsignedint(32)sample_count;if(sample_size==0){for(i=1;i<=sample_count;i++){unsignedint(32)entry_size;}}}
主要字段說明:
sample_size:指定默認(rèn)的sample字節(jié)大小,如果所有sample的大小不一樣,這個字段為0。
sample_count:track中sample的數(shù)量。
entry_size:每個sample的字節(jié)大小。
Compact Sample SizeBox(stz2):一種壓縮的sample大小存儲方式。
classCompactSampleSizeBoxextendsFullBox(‘stz2’,version=0,0){unsignedint(24)reserved=0;unisgnedint(8)field_size;unsignedint(32)sample_count;for(i=1;i<=sample_count;i++){unsignedint(field_size)entry_size;}}
field_size:指定表中條目的比特大小,取值為4、8或16。
(1) 如果使用值4,則每個字節(jié)存儲兩個sample的大小:
entry[i] << 4 + entry[i + 1]。
(2) 如果大小沒有填充滿整數(shù)個字節(jié),則用最后一個字節(jié)未使用部分填充0。
sample_count是一個整數(shù),它給出了下表中的條目數(shù)。
entry_size是一個整數(shù),它指定一個sample的大小,并根據(jù)其編號進(jìn)行索引。
4.7 Sample To Chunk Box(stsc)
media中的sample被分為組成chunk。chunk可以有不同的大小,chunk內(nèi)的sample可以有不同的大小。
通過stsc中的sample-chunk映射表可以找到包含指定sample的chunk,從而找到這個sample。結(jié)構(gòu)相同的chunk可以聚集在一起形成一個entry,這個entry就是stsc映射表的表項。
語法:
classSampleToChunkBoxextendsFullBox(‘stsc’,version=0,0){unsignedint(32)entry_count;for(i=1;i<=entry_count;i++){unsignedint(32)first_chunk;unsignedint(32)samples_per_chunk;unsignedint(32)sample_description_index;}}
主要字段說明:
first_chunk:一組chunk的第一個chunk的序號。
chunk的編號從1開始。
samples_per_chunk:每個chunk有多少個sample。
sample_desc_idx:stsd 中sample desc信息的索引。
把一組相同結(jié)構(gòu)的chunk放在一起進(jìn)行管理,是為了壓縮文件大小。
用mp4box.js查看的stsc box的信息如下:

image.png
第一組chunk的first_chunk序號為1,每個chunk的sample個數(shù)為1,因為第二組chunk的first_chunk序號為2,可知第一組chunk中只有一個chunk。
第二組chunk的first_chunk序號為2,每個chunk的sample個數(shù)為2,因為第三組chunk的first_chunk序號為24,可知第二組chunk中有22個chunk,有44個sample。
4.8 Chunk Offset Box(stco/co64)
Chunk Offset表存儲了每個chunk在文件中的位置,這樣就可以直接在文件中找到媒體數(shù)據(jù),而不用解析box。
需要注意的是一旦前面的box有了任何改變,這張表都要重新建立。
語法:
classChunkOffsetBoxextendsFullBox(‘stco’,version=0,0){unsignedint(32)entry_count;for(i=1;i<=entry_count;i++){unsignedint(32)chunk_offset;}}
主要字段說明:
chunk_offset:chunk在文件中的位置。
stco 有兩種形式,如果你的視頻過大的話,就有可能造成 chunkoffset 超過 32bit 的限制。所以,這里針對大 Video 額外創(chuàng)建了一個 co64 的 Box。它的功效等價于 stco,也是用來表示 sample 在 mdat box 中的位置。只是,里面 chunk_offset 是 64bit 的。
aligned(8)classChunkLargeOffsetBoxextendsFullBox(‘co64’,version=0,0){unsignedint(32)entry_count;for(i=1;i<=entry_count;i++){unsignedint(64)chunk_offset;}}
5. 其他box介紹
以下是ISO/IEC 14496-12:2015文檔給出的box的描述圖:

box.png
5.1 File Type Box(ftyp)
File Type Box一般在文件的開頭,用來指示該 mp4文件使用的標(biāo)準(zhǔn)規(guī)范。為了早期規(guī)范版本兼容,允許不包含ftyp box。
語法:
classFileTypeBoxextendsBox(‘ftyp’){unsignedint(32)major_brand;// is a brand identifierunsignedint(32)minor_version;// is an informative integer for the minor version of the major brandunsignedint(32)compatible_brands[];//is a list, to the end of the box, of brands}
沒有ftyp box的文件應(yīng)該處理成ftyp的major_brand為'mp41',minor_version為0,compatible_brands只包含一個'mp41'。
5.2 Movie Box(moov)
Movie Box包含了文件媒體的metadata信息,“moov”是一個container box,具體內(nèi)容信息在其子box中。一般情況下,“moov”會緊隨著“ftyp”。
“moov”中包含1個“mvhd”和若干個“trak”。其中“mvhd”是header box,一般作為“moov”的第一個子box出現(xiàn)?!皌rak”包含了一個track的相關(guān)信息,是一個container box。
語法:
classMovieBoxextendsBox(‘moov’){}
5.3 Movie Header Box(mvhd)
語法:
class MovieHeaderBox extendsFullBox(‘mvhd’,version,0){if(version==1){unsignedint(64)creation_time;unsignedint(64)modification_time;unsignedint(32)timescale;unsignedint(64)duration;}else{// version==0unsignedint(32)creation_time;unsignedint(32)modification_time;unsignedint(32)timescale;unsignedint(32)duration;}templateint(32)rate=0x00010000;// typically 1.0templateint(16)volume=0x0100;// typically, full volumeconstbit(16)reserved=0;constunsignedint(32)[2]reserved=0;templateint(32)[9]matrix={0x00010000,0,0,0,0x00010000,0,0,0,0x40000000};// Unity matrixbit(32)[6]pre_defined=0;unsignedint(32)next_track_ID;}
主要字段含義:
version : box版本,0或1,一般為0。
creation time : 創(chuàng)建時間(相對于UTC時間1904-01-01零點的秒數(shù))。
modification time : 修改時間 。
timescale : 文件媒體在1秒時間內(nèi)的刻度值,可理解為1秒長度的時間單元數(shù)。
duration : 該track的時間長度,用duration和time scale值可以計算track時長,比如audio track的time scale = 8000, duration = 560128,時長為70.016,video track的time scale = 600, duration = 42000,時長為70。
rate : 推薦播放速率,高16位和低16位分別為小數(shù)點整數(shù)部分和小數(shù)部分,即[16.16] 格式,該值為1.0(0x00010000)表示正常前向播放。
volume : 推薦播放音量,[8.8] 格式,1.0(0x0100)表示最大音量。
5.4 Track Box(trak)
Track Box是一個container box,其子box包含了該track的媒體數(shù)據(jù)引用和描述(hint track除外)。一個mp4文件可以包含多個track,且至少有一個track,track之間是獨立,有自己的時間和空間信息?!皌rak”必須包含一個“tkhd”和一個“mdia”,此外還有很多可選的box。其中“tkhd”為track header box,“mdia”為media box,該box是一個包含一些track媒體數(shù)據(jù)信息box的container box。
語法:
classTrackBoxextendsBox(‘trak’){}
5.5 Track Header Box(tkhd)
語法:
class TrackHeaderBox? ? extendsFullBox(‘tkhd’,version,flags){if(version==1){unsignedint(64)creation_time;unsignedint(64)modification_time;unsignedint(32)track_ID;constunsignedint(32)reserved=0;unsignedint(64)duration;}else{// version==0unsignedint(32)creation_time;unsignedint(32)modification_time;unsignedint(32)track_ID;constunsignedint(32)reserved=0;unsignedint(32)duration;}constunsignedint(32)[2]reserved=0;templateint(16)layer=0;templateint(16)alternate_group=0;templateint(16)volume={iftrack_is_audio0x0100else0};constunsignedint(16)reserved=0;templateint(32)[9]matrix={0x00010000,0,0,0,0x00010000,0,0,0,0x40000000};// unity matrixunsignedint(32)width;unsignedint(32)height;}
主要字段含義:
version : box版本,0或1,一般為0。
flags : 24-bit整數(shù),按位或操作結(jié)果值,預(yù)定義的值(0x000001 ,track_enabled,表示track是有效的)、(0x000002,track_in_movie,表示該track在播放中被使用)、(0x000004,track_in_preview,表示track在預(yù)覽時被使用。
track id : track id號,不能重復(fù)且不能為0。
duration : track的時間長度,計量單位timescale在mvhd中。
volume : [8.8] 格式,如果為音頻track,1.0(0x0100)表示最大音量;否則為0。
width : 寬,[16.16] 格式值。
height : 高,[16.16] 格式值,不必與sample的像素尺寸一致,用于播放時的展示寬高。
5.6 Media Box(mdia)
Media Box也是個container box。
語法:
classMediaBoxextendsBox(‘mdia’){}
其子box的結(jié)構(gòu)和種類還是比較復(fù)雜的。
“mdia”定義了track媒體類型以及sample數(shù)據(jù),描述sample信息。
一個“mdia”必須包含如下容器:
一個Media Header Atom(mdhd)
一個Handler Reference(hdlr)
一個media information(minf)和User Data
下面依次看一下這幾個box的結(jié)構(gòu)。
5.7 Media Header Box(mdhd)
mdhd 和 tkhd ,內(nèi)容大致都是一樣的。不過tkhd 通常是對指定的 track 設(shè)定相關(guān)屬性和內(nèi)容。而 mdhd 是針對于獨立的 media 來設(shè)置的。不過兩者一般都是一樣的。
語法:
class MediaHeaderBox extendsFullBox(‘mdhd’,version,0){if(version==1){unsignedint(64)creation_time;unsignedint(64)modification_time;unsignedint(32)timescale;unsignedint(64)duration;}else{// version==0unsignedint(32)creation_time;unsignedint(32)modification_time;unsignedint(32)timescale;unsignedint(32)duration;}bit(1)pad=0;unsignedint(5)[3]language;// ISO-639-2/T language codeunsignedint(16)pre_defined=0;}
主要字段含義:
version: box版本,0或1,一般為0。
timescale: 同mvhd中的timescale。
duration: track的時間長度。
language: 媒體語言碼。最高位為0,后面15位為3個字符(見ISO 639-2/T標(biāo)準(zhǔn)中定義)。
5.8 Handler Reference Box(hdlr)
“hdlr”解釋了媒體的播放過程信息,該box也可以被包含在meta box(meta)中。
語法:
classHandlerBoxextendsFullBox(‘hdlr’,version=0,0){unsignedint(32)pre_defined=0;unsignedint(32)handler_type;constunsignedint(32)[3]reserved=0;string name;}
主要字段含義:
handler type: 在media box中,該值為4個字符,會有以下取值:
‘vide’ Video track‘soun’ Audio track‘hint’ Hint track‘meta’ Timed Metadata track‘a(chǎn)uxv’ Auxiliary Video track
name:? human-readable name for the track
type,以‘\0’結(jié)尾的 UTF-8 字符串。用于調(diào)試后者檢查的目的。
5.9 Media Information Box(minf)
重要的容器 box,“minf”存儲了解釋track媒體數(shù)據(jù)的handler-specific信息,media handler用這些信息將媒體時間映射到媒體數(shù)據(jù)并進(jìn)行處理?!癿inf”是一個container box,其實際內(nèi)容由子box說明。
語法:
classMediaInformationBoxextendsBox(‘minf’){}
“minf”中的信息格式和內(nèi)容與媒體類型以及解釋媒體數(shù)據(jù)的media handler密切相關(guān),其他media handler不知道如何解釋這些信息。
一般情況下,“minf”包含一個header box,一個“dinf”和一個“stbl”,其中,header box根據(jù)track type(即media handler type)分為“vmhd”、“smhd”、“hmhd”和“nmhd”,“dinf”為data information box,“stbl”為sample table box。下面分別介紹。
5.10 Media Information Header Box(vmhd、smhd、hmhd、nmhd)
vmhd、smhd這兩個box在解析時,非不可或缺的(有時候得看播放器),缺了的話,有可能會被認(rèn)為格式不正確。
Video Media Header Box(vmhd)
語法:
classVideoMediaHeaderBoxextendsFullBox(‘vmhd’,version=0,1){template unsignedint(16)graphicsmode=0;// copy, see belowtemplate unsignedint(16)[3]opcolor={0,0,0};}
主要字段含義:
graphics mode:視頻合成模式,為0時拷貝原始圖像,否則與opcolor進(jìn)行合成。
opcolor: 一組(red,green,blue),graphics modes使用。
Sound Media Header Box(smhd)
語法:
classSoundMediaHeaderBoxextendsFullBox(‘smhd’,version=0,0){templateint(16)balance=0;constunsignedint(16)reserved=0;}
主要字段含義:
balance:立體聲平衡,[8.8] 格式值,一般為0表示中間,-1.0表示全部左聲道,1.0表示全部右聲道。
Hint Media Header Box(hmhd)
Null Media Header Box(nmhd)
非視音頻媒體使用該box。
5.11 Data Information Box(dinf)
“dinf”解釋如何定位媒體信息,是一個container box。
語法:
classDataInformationBoxextendsBox(‘dinf’){}
“dinf”一般包含一個“dref”(data reference box)。
“dref”下會包含若干個“url”或“urn”,這些box組成一個表,用來定位track數(shù)據(jù)。簡單的說,track可以被分成若干段,每一段都可以根據(jù)“url”或“urn”指向的地址來獲取數(shù)據(jù),sample描述中會用這些片段的序號將這些片段組成一個完整的track。一般情況下,當(dāng)數(shù)據(jù)被完全包含在文件中時,“url”或“urn”中的定位字符串是空的。
“dref”的語法:
classDataEntryUrlBox(bit(24)flags)extendsFullBox(‘url ’,version=0,flags){string location;}classDataEntryUrnBox(bit(24)flags)extendsFullBox(‘urn ’,version=0,flags){string name;string location;}classDataReferenceBoxextendsFullBox(‘dref’,version=0,0){unsignedint(32)entry_count;for(i=1;i<=entry_count;i++){DataEntryBox(entry_version,entry_flags)data_entry;}}
主要字段含義:
entry count:“url”或“urn”表的元素個數(shù)。
entry_version:entry格式的版本。
entry_flags:當(dāng)“url”或“urn”的box flag為1時,表示數(shù)據(jù)在該文件的Moov
Box中。
“url”或“urn”都是box,“url”的內(nèi)容為location字符串,“urn”的內(nèi)容為名稱字符串和location字符串。
6. 實用技術(shù)
6.1 moov移到mdat前面
ffmpeg默認(rèn)情況下生成moov是在mdat寫完成之后再寫入,所以moov是在mdat的后面,使用faststart參數(shù)可以將moov移到mdat前面。
./ffmpeg-i demo.flv-ccopyoutput.mp4
moov在mdat后面

image.png
使用faststart參數(shù)
ffmpeg -i out.flv -c copy -movflags faststart out2.mp4
moov在mdat前面

image.png
6.2 如何實現(xiàn)seek

stbl.png
例如,我們需要seek到30s。
需要做如下工作:
使用timescale將目標(biāo)時間標(biāo)準(zhǔn)化。timescale為90000,30*90000=2700000。
通過time-to-sample box找到指定track的給定時間之前的第一個sample number。2700000/3000 = 900。
通過sync sample table查詢sample number之前的第一個sync sample。對應(yīng)為795的sample。
通過sample-to-chunk table查找到對應(yīng)的chunk number。
對應(yīng)的chunk號假設(shè)是400。
通過chunk offset box查找到對應(yīng)chunk在文件中的起始偏移量。第14個chunk的offset是3481072。
最后使用sample-to-chunk box和sample size box的信息計算出該chunk中需要讀取的sample在文件中的起始偏移量,即完成seek。
7. 開源軟件
gpac:開源的多媒體工具包,包括用于MP4打包的mp4box等。
mp4v2:提供了API來創(chuàng)建和修改mp4文件。
注意:window下用Binary Viewer查看二進(jìn)制文件
鏈接:http://www.itdecent.cn/p/529c3729f357