mp4文件格式解析

目錄

概述

mp4文件基本信息

封裝格式重要概念

重要box介紹

其他box介紹

實(shí)用技術(shù)

開(kāi)源軟件

參考

[1]ISO/IEC 14496-12:2015

[2]wikipedia/MPEG-4

[3]wikipedia/ISO base media file format

[4]wikipedia/MPEG-4 Part 14

[5]Tocy/多媒體文件格式之MP4

[6]Phil Cluff/What's in the box_!

[7]github.com/gpac/mp4box.js

[8]tao/Android音視頻系列:視頻容器操作篇 -- mp4容器打包實(shí)現(xiàn)

[9]LiaoJunXiong/使用gpac封裝mp4

[10]Jameson Steiner/Fun with Container Formats? – Part 2

1. 概述

mp4或稱(chēng)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)文檔把編碼和容器格式的說(shuō)明分開(kāi)持际。

MPEG-4 Part12沃琅,定義了容器格式通用的box結(jié)構(gòu),即ISO媒體文件格式(ISO base media file format, ISOBMFF)蜘欲。

MPEG-4 Part14益眉,基于Part12進(jìn)行了細(xì)化,定義了用于存儲(chǔ)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)上這部分是付費(fèi)的澈歉。

MP4文件由許多box組成朱庆,每個(gè)box包含不同的信息, 這些box以樹(shù)形結(jié)構(gòu)的方式組織闷祥。以下是主要box的簡(jiǎn)要說(shuō)明:

圖2 主要box說(shuō)明

根節(jié)點(diǎn)之下,主要包含三個(gè)節(jié)點(diǎn):ftyp傲诵、moov凯砍、mdat。

ftyp:文件類(lèi)型拴竹。描述遵從的規(guī)范的版本悟衩。

moov box:媒體的metadata信息。

mdat:具體的媒體數(shù)據(jù)栓拜。

說(shuō)明:在 mp4 中默認(rèn)寫(xiě)入字節(jié)序是 Big-Endian的座泳。

2. mp4文件基本信息

分析mp4文件的工具:

mp4box.js:一個(gè)在線(xiàn)解析mp4的工具惠昔。

bento4:包含mp4dump、mp4edit挑势、mp4encrypt等工具镇防。

MP4Box:類(lèi)似于bento4,包含很全面的工具潮饱。

mp4info.exe: windows平臺(tái)圖形界面展示mp4基本信息的工具来氧。

下圖為使用mp4info.exe打開(kāi)mp4文件的界面:

圖3 mp4info.PNG

mp4文件基本信息

audio信息:

smplrate:sample rate(采樣率)。

channel:通道個(gè)數(shù)香拉。

bitrate:比特率啦扬。

audiosamplenum:音頻sample的個(gè)數(shù)。

video信息:

width凫碌、height:視頻的寬/高扑毡。

bitrate:比特率(碼率),秒為單位盛险。等于視頻總的大小/時(shí)長(zhǎng)瞄摊。

frames:視頻幀數(shù)。

fps:幀率(frame per second)枉层。

total_time:時(shí)間長(zhǎng)度泉褐,ms為單位。等于duration/timescale鸟蜡。

timescale:時(shí)間的粒度膜赃,1000表示1000個(gè)單位為1s。

duration:時(shí)間粒度的個(gè)數(shù)揉忘。

videosamplenum:視頻sample的個(gè)數(shù)跳座。

3. 封裝格式重要概念

3.1 box

mp4文件由若干個(gè)box組成。下面是box結(jié)構(gòu)的一個(gè)示意圖泣矛。

圖4 mp4_box.png

box由header和body組成疲眷,header指明box的size和type。size是包含box header的整個(gè)box的大小您朽。

box type狂丝,通常是4個(gè)ASCII碼的字符如“ftyp”、“moov”等哗总,這些box type都是已經(jīng)預(yù)定義好的几颜,表示固定的含義。如果是“uuid”讯屈,表示該box為用戶(hù)自定義擴(kuò)展類(lèi)型蛋哭,如果box type是未定義的,應(yīng)該將其忽略涮母。

如果header中的size為1谆趾,則表示box長(zhǎng)度需要更多的bits位來(lái)描述躁愿,在后面會(huì)有一個(gè)64bits位的largesize用來(lái)描述box的長(zhǎng)度。如果size為0沪蓬,表示該box為文件的最后一個(gè)box彤钟,文件結(jié)尾(同樣只存在于“mdat”類(lèi)型的box中)。

box中可以包含box怜跑,這種box稱(chēng)為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的集合辫樱,對(duì)于媒體數(shù)據(jù)來(lái)說(shuō),track表示一個(gè)視頻或者音頻序列俊庇。

3.3 sample

video sample即為一幀或者一組連續(xù)視頻幀狮暑,audio sample即為一段連續(xù)的音頻。

3.4. sample table

指明sample時(shí)序和物理布局的表辉饱。

3.5. chunk

一個(gè)track的幾個(gè)sample組成的單元搬男。

mp4文件中,媒體內(nèi)容在moov的box中彭沼。一個(gè)moov包含多個(gè)track缔逛。每個(gè)track就是一個(gè)隨時(shí)間變化的媒體序列,track里的每個(gè)時(shí)間單位是一個(gè)sample姓惑,sample按照時(shí)間順序排列褐奴。注意,一幀音頻可以分解成多個(gè)音頻sample于毙,所以音頻一般用sample作為單位敦冬,而不用幀。

4. 重要box介紹

4.1 Sample Table Box(stbl)

“stbl”是mp4文件中最復(fù)雜的一個(gè)box了唯沮,也是解開(kāi)mp4文件格式的主干脖旱。

stbl :sample table是一個(gè)container box。

語(yǔ)法:

classSampleTableBoxextendsBox(‘stbl’){}

其子box包括:

stsd:sample description box介蛉,樣本的描述信息夯缺。

stts:time to sample box,sample解碼時(shí)間的壓縮表甘耿。

ctts:composition time to sample box,sample的CTS與DTS的時(shí)間差的壓縮表竿滨。

stss:sync sample box佳恬,針對(duì)視頻捏境,關(guān)鍵幀的序號(hào)。

stsz/stz2:sample size box毁葱,每個(gè)sample的字節(jié)大小垫言。

stsc:sample to chunk box,sample-chunk映射表倾剿。

stco/co64:chunk offset box筷频,chunk在文件中的偏移。

sample是媒體數(shù)據(jù)存儲(chǔ)的單位前痘,存儲(chǔ)在media的chunk中凛捏,chunk和sample的長(zhǎng)度均可互不相同,如下圖所示芹缔。

圖5 sample.jpg

4.2 Sample Description Box(stsd)

存儲(chǔ)了編碼類(lèi)型和初始化解碼器需要的信息坯癣。

有與特定的track-type相關(guān)的信息,相同的track-type也會(huì)存在不同信息的情況如使用不一樣的編碼標(biāo)準(zhǔn)最欠。

語(yǔ)法:

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;}}}}

主要字段說(shuō)明:

entry count:entry的個(gè)數(shù)示罗。

handler_type:類(lèi)型信息如“vide”、“soud”等芝硬,不同類(lèi)型會(huì)提供不同的信息蚜点。

對(duì)于audio track,使用“AudioSampleEntry”類(lèi)型信息拌阴。

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:利用這個(gè)索引可以檢索與當(dāng)前sample description關(guān)聯(lián)的數(shù)據(jù)脯倒。數(shù)據(jù)引用存儲(chǔ)在data reference box。

channelcount:通道個(gè)數(shù)捺氢。

samplesize:采樣位數(shù)藻丢。默認(rèn)是16比特。

samplerate:采樣率摄乒。[16.16]格式的數(shù)據(jù)悠反。

對(duì)于video track,使用“VisualSampleEntry”類(lèi)型信息馍佑。

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:每個(gè)sample中的視頻幀數(shù)舅世,默認(rèn)是1旦委∑嫱剑可以是一個(gè)sample中有多幀數(shù)據(jù)。

4.3 Decoding Time to Sample Box(stts)

包含了一個(gè)壓縮版本的表缨硝,通過(guò)這個(gè)表可以從解碼時(shí)間映射到sample序號(hào)摩钙。表中的每一項(xiàng)是連續(xù)相同的編碼時(shí)間增量(Decode Delta)的個(gè)數(shù)和編碼時(shí)間增量。通過(guò)把時(shí)間增量累加就可以建立一個(gè)完整的time to sample表查辩。

以下是Decoding Timing和Decode delta關(guān)系的一個(gè)圖示:

圖6 STTS_sample.PNG

DT(decoding time):編碼時(shí)間胖笛。

CT(composition time):創(chuàng)作時(shí)間。

Decode Delta:編碼時(shí)間增量宜岛。

Composition offset:顯示時(shí)間同解碼時(shí)間的差值长踊,等于CT - DT。

計(jì)算方式:

DT(n+1)=DT(n)+STTS(n)whereSTTS(n)注:這里的STTS(n)是未壓縮的DecodeDelta表谬返。DT(i)=SUM(forj=0to i-1ofdelta(j))

語(yǔ)法:

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;}}

重要字段說(shuō)明:

entry_count:表中條目的個(gè)數(shù)之斯。

sample_count: 連續(xù)相同時(shí)間長(zhǎng)度的sample個(gè)數(shù)。

sample_delta:以timescale為單位的時(shí)間長(zhǎng)度遣铝。

4.4 composition time to sample box(ctts)

這個(gè)box提供了decoding time到composition time的offset的表佑刷,用于計(jì)算pts。

這個(gè)表在Decoding time和composition time不一樣的情況下時(shí)必須的酿炸。

如果box的version等于0瘫絮,decoding time必須小于等于composition time,因而差值用一個(gè)無(wú)符號(hào)的數(shù)字表示填硕。

有以下公式:

注:CTTS(n)是未壓縮的表的第n個(gè)sample對(duì)應(yīng)的offset麦萤。

語(yǔ)法:

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;}}}

主要字段說(shuō)明:

sample_count:連續(xù)相同的offset的個(gè)數(shù)。

sample_offset:CT和DT之間的offset扁眯。

4.5 sync sample box(stss)

它包含media中的關(guān)鍵幀的sample表壮莹。如果此表不存在,說(shuō)明每一個(gè)sample都是一個(gè)關(guān)鍵幀姻檀。

語(yǔ)法:

classSyncSampleBoxextendsFullBox(‘stss’,version=0,0){unsignedint(32)entry_count;int i;for(i=0;i<entry_count;i++){unsignedint(32)sample_number;}}

主要字段說(shuō)明:

sample_number:媒體流中同步sample的序號(hào)命满。

4.6 Sample Size Box(stsz/stz2)

包含sample的數(shù)量和每個(gè)sample的字節(jié)大小,這個(gè)box相對(duì)來(lái)說(shuō)體積比較大的绣版。

語(yǔ)法:

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;}}}

主要字段說(shuō)明:

sample_size:指定默認(rèn)的sample字節(jié)大小胶台,如果所有sample的大小不一樣,這個(gè)字段為0杂抽。

sample_count:track中sample的數(shù)量诈唬。

entry_size:每個(gè)sample的字節(jié)大小。

Compact Sample SizeBox(stz2):一種壓縮的sample大小存儲(chǔ)方式缩麸。

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愚屁,則每個(gè)字節(jié)存儲(chǔ)兩個(gè)sample的大小:

entry[i] << 4 + entry[i + 1]济竹。

(2) 如果大小沒(méi)有填充滿(mǎn)整數(shù)個(gè)字節(jié),則用最后一個(gè)字節(jié)未使用部分填充0霎槐。

sample_count是一個(gè)整數(shù),它給出了下表中的條目數(shù)梦谜。

entry_size是一個(gè)整數(shù)丘跌,它指定一個(gè)sample的大小,并根據(jù)其編號(hào)進(jìn)行索引唁桩。

4.7 Sample To Chunk Box(stsc)

media中的sample被分為組成chunk闭树。chunk可以有不同的大小,chunk內(nèi)的sample可以有不同的大小荒澡。

通過(guò)stsc中的sample-chunk映射表可以找到包含指定sample的chunk报辱,從而找到這個(gè)sample。結(jié)構(gòu)相同的chunk可以聚集在一起形成一個(gè)entry单山,這個(gè)entry就是stsc映射表的表項(xiàng)碍现。

語(yǔ)法:

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;}}

主要字段說(shuō)明:

first_chunk:一組chunk的第一個(gè)chunk的序號(hào)。

chunk的編號(hào)從1開(kāi)始米奸。

samples_per_chunk:每個(gè)chunk有多少個(gè)sample昼接。

sample_desc_idx:stsd 中sample desc信息的索引。

把一組相同結(jié)構(gòu)的chunk放在一起進(jìn)行管理悴晰,是為了壓縮文件大小慢睡。

mp4box.js查看的stsc box的信息如下:

image.png

第一組chunk的first_chunk序號(hào)為1,每個(gè)chunk的sample個(gè)數(shù)為1铡溪,因?yàn)榈诙Mchunk的first_chunk序號(hào)為2漂辐,可知第一組chunk中只有一個(gè)chunk。

第二組chunk的first_chunk序號(hào)為2棕硫,每個(gè)chunk的sample個(gè)數(shù)為2髓涯,因?yàn)榈谌Mchunk的first_chunk序號(hào)為24,可知第二組chunk中有22個(gè)chunk饲帅,有44個(gè)sample复凳。

4.8 Chunk Offset Box(stco/co64)

Chunk Offset表存儲(chǔ)了每個(gè)chunk在文件中的位置,這樣就可以直接在文件中找到媒體數(shù)據(jù)灶泵,而不用解析box育八。

需要注意的是一旦前面的box有了任何改變,這張表都要重新建立赦邻。

語(yǔ)法:

classChunkOffsetBoxextendsFullBox(‘stco’,version=0,0){unsignedint(32)entry_count;for(i=1;i<=entry_count;i++){unsignedint(32)chunk_offset;}}

主要字段說(shuō)明:

chunk_offset:chunk在文件中的位置髓棋。

stco 有兩種形式,如果你的視頻過(guò)大的話(huà),就有可能造成 chunkoffset 超過(guò) 32bit 的限制按声。所以膳犹,這里針對(duì)大 Video 額外創(chuàng)建了一個(gè) co64 的 Box。它的功效等價(jià)于 stco签则,也是用來(lái)表示 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一般在文件的開(kāi)頭豺旬,用來(lái)指示該 mp4文件使用的標(biāo)準(zhǔn)規(guī)范。為了早期規(guī)范版本兼容柒凉,允許不包含ftyp box族阅。

語(yǔ)法:

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}

沒(méi)有ftyp box的文件應(yīng)該處理成ftyp的major_brand為'mp41',minor_version為0膝捞,compatible_brands只包含一個(gè)'mp41'坦刀。

5.2 Movie Box(moov)

Movie Box包含了文件媒體的metadata信息,“moov”是一個(gè)container box蔬咬,具體內(nèi)容信息在其子box中鲤遥。一般情況下,“moov”會(huì)緊隨著“ftyp”计盒。

“moov”中包含1個(gè)“mvhd”和若干個(gè)“trak”渴频。其中“mvhd”是header box,一般作為“moov”的第一個(gè)子box出現(xiàn)北启〔防剩“trak”包含了一個(gè)track的相關(guān)信息,是一個(gè)container box咕村。

語(yǔ)法:

classMovieBoxextendsBox(‘moov’){}

5.3 Movie Header Box(mvhd)

語(yǔ)法:

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)建時(shí)間(相對(duì)于UTC時(shí)間1904-01-01零點(diǎn)的秒數(shù))逛万。

modification time : 修改時(shí)間 。

timescale : 文件媒體在1秒時(shí)間內(nèi)的刻度值批钠,可理解為1秒長(zhǎng)度的時(shí)間單元數(shù)宇植。

duration : 該track的時(shí)間長(zhǎng)度,用duration和time scale值可以計(jì)算track時(shí)長(zhǎng)埋心,比如audio track的time scale = 8000, duration = 560128指郁,時(shí)長(zhǎng)為70.016,video track的time scale = 600, duration = 42000拷呆,時(shí)長(zhǎng)為70闲坎。

rate : 推薦播放速率疫粥,高16位和低16位分別為小數(shù)點(diǎn)整數(shù)部分和小數(shù)部分,即[16.16] 格式腰懂,該值為1.0(0x00010000)表示正常前向播放梗逮。

volume : 推薦播放音量,[8.8] 格式绣溜,1.0(0x0100)表示最大音量慷彤。

5.4 Track Box(trak)

Track Box是一個(gè)container box,其子box包含了該track的媒體數(shù)據(jù)引用和描述(hint track除外)怖喻。一個(gè)mp4文件可以包含多個(gè)track瞬欧,且至少有一個(gè)track,track之間是獨(dú)立罢防,有自己的時(shí)間和空間信息“χ叮“trak”必須包含一個(gè)“tkhd”和一個(gè)“mdia”咒吐,此外還有很多可選的box。其中“tkhd”為track header box属划,“mdia”為media box恬叹,該box是一個(gè)包含一些track媒體數(shù)據(jù)信息box的container box。

語(yǔ)法:

classTrackBoxextendsBox(‘trak’){}

5.5 Track Header Box(tkhd)

語(yǔ)法:

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ù)覽時(shí)被使用的妖。

track id : track id號(hào),不能重復(fù)且不能為0足陨。

duration : track的時(shí)間長(zhǎng)度嫂粟,計(jì)量單位timescale在mvhd中。

volume : [8.8] 格式钠右,如果為音頻track赋元,1.0(0x0100)表示最大音量;否則為0。

width : 寬搁凸,[16.16] 格式值媚值。

height : 高,[16.16] 格式值护糖,不必與sample的像素尺寸一致褥芒,用于播放時(shí)的展示寬高。

5.6 Media Box(mdia)

Media Box也是個(gè)container box嫡良。

語(yǔ)法:

classMediaBoxextendsBox(‘mdia’){}

其子box的結(jié)構(gòu)和種類(lèi)還是比較復(fù)雜的锰扶。

“mdia”定義了track媒體類(lèi)型以及sample數(shù)據(jù),描述sample信息寝受。

一個(gè)“mdia”必須包含如下容器:

一個(gè)Media Header Atom(mdhd)

一個(gè)Handler Reference(hdlr)

一個(gè)media information(minf)和User Data

下面依次看一下這幾個(gè)box的結(jié)構(gòu)坷牛。

5.7 Media Header Box(mdhd)

mdhd 和 tkhd ,內(nèi)容大致都是一樣的很澄。不過(guò)tkhd 通常是對(duì)指定的 track 設(shè)定相關(guān)屬性和內(nèi)容京闰。而 mdhd 是針對(duì)于獨(dú)立的 media 來(lái)設(shè)置的。不過(guò)兩者一般都是一樣的甩苛。

語(yǔ)法:

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的時(shí)間長(zhǎng)度。

language: 媒體語(yǔ)言碼墨林。最高位為0赁酝,后面15位為3個(gè)字符(見(jiàn)ISO 639-2/T標(biāo)準(zhǔn)中定義)。

5.8 Handler Reference Box(hdlr)

“hdlr”解釋了媒體的播放過(guò)程信息萌丈,該box也可以被包含在meta box(meta)中赞哗。

語(yǔ)法:

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個(gè)字符辆雾,會(huì)有以下取值:

‘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”存儲(chǔ)了解釋track媒體數(shù)據(jù)的handler-specific信息,media handler用這些信息將媒體時(shí)間映射到媒體數(shù)據(jù)并進(jìn)行處理惭墓√沉海“minf”是一個(gè)container box,其實(shí)際內(nèi)容由子box說(shuō)明腊凶。

語(yǔ)法:

classMediaInformationBoxextendsBox(‘minf’){}

“minf”中的信息格式和內(nèi)容與媒體類(lèi)型以及解釋媒體數(shù)據(jù)的media handler密切相關(guān)划咐,其他media handler不知道如何解釋這些信息拴念。

一般情況下,“minf”包含一個(gè)header box褐缠,一個(gè)“dinf”和一個(gè)“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這兩個(gè)box在解析時(shí)状婶,非不可或缺的(有時(shí)候得看播放器),缺了的話(huà)馅巷,有可能會(huì)被認(rèn)為格式不正確。

Video Media Header Box(vmhd)

語(yǔ)法:

classVideoMediaHeaderBoxextendsFullBox(‘vmhd’,version=0,1){template unsignedint(16)graphicsmode=0;// copy, see belowtemplate unsignedint(16)[3]opcolor={0,0,0};}

主要字段含義:

graphics mode:視頻合成模式草姻,為0時(shí)拷貝原始圖像钓猬,否則與opcolor進(jìn)行合成。

opcolor: 一組(red撩独,green敞曹,blue),graphics modes使用综膀。

Sound Media Header Box(smhd)

語(yǔ)法:

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”解釋如何定位媒體信息拢锹,是一個(gè)container box。

語(yǔ)法:

classDataInformationBoxextendsBox(‘dinf’){}

“dinf”一般包含一個(gè)“dref”(data reference box)萄喳。

“dref”下會(huì)包含若干個(gè)“url”或“urn”卒稳,這些box組成一個(gè)表,用來(lái)定位track數(shù)據(jù)他巨。簡(jiǎn)單的說(shuō)充坑,track可以被分成若干段减江,每一段都可以根據(jù)“url”或“urn”指向的地址來(lái)獲取數(shù)據(jù),sample描述中會(huì)用這些片段的序號(hào)將這些片段組成一個(gè)完整的track捻爷。一般情況下辈灼,當(dāng)數(shù)據(jù)被完全包含在文件中時(shí),“url”或“urn”中的定位字符串是空的役衡。

“dref”的語(yǔ)法:

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”表的元素個(gè)數(shù)茵休。

entry_version:entry格式的版本。

entry_flags:當(dāng)“url”或“urn”的box flag為1時(shí)手蝎,表示數(shù)據(jù)在該文件的Moov

Box中榕莺。

“url”或“urn”都是box,“url”的內(nèi)容為location字符串棵介,“urn”的內(nèi)容為名稱(chēng)字符串和location字符串钉鸯。

6. 實(shí)用技術(shù)

6.1 moov移到mdat前面

ffmpeg默認(rèn)情況下生成moov是在mdat寫(xiě)完成之后再寫(xiě)入,所以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 如何實(shí)現(xiàn)seek

stbl.png

例如,我們需要seek到30s吨述。

需要做如下工作:

使用timescale將目標(biāo)時(shí)間標(biāo)準(zhǔn)化岩睁。timescale為90000,30*90000=2700000揣云。

通過(guò)time-to-sample box找到指定track的給定時(shí)間之前的第一個(gè)sample number捕儒。2700000/3000 = 900。

通過(guò)sync sample table查詢(xún)sample number之前的第一個(gè)sync sample邓夕。對(duì)應(yīng)為795的sample刘莹。

通過(guò)sample-to-chunk table查找到對(duì)應(yīng)的chunk number。

對(duì)應(yīng)的chunk號(hào)假設(shè)是400焚刚。

通過(guò)chunk offset box查找到對(duì)應(yīng)chunk在文件中的起始偏移量点弯。第14個(gè)chunk的offset是3481072。

最后使用sample-to-chunk box和sample size box的信息計(jì)算出該chunk中需要讀取的sample在文件中的起始偏移量矿咕,即完成seek抢肛。

7. 開(kāi)源軟件

gpac:開(kāi)源的多媒體工具包,包括用于MP4打包的mp4box等碳柱。

mp4v2:提供了API來(lái)創(chuàng)建和修改mp4文件雌团。

注意:window下用Binary Viewer查看二進(jìn)制文件

鏈接:http://www.reibang.com/p/529c3729f357

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市士聪,隨后出現(xiàn)的幾起案子锦援,更是在濱河造成了極大的恐慌,老刑警劉巖剥悟,帶你破解...
    沈念sama閱讀 216,744評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灵寺,死亡現(xiàn)場(chǎng)離奇詭異曼库,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)略板,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)毁枯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人叮称,你說(shuō)我怎么就攤上這事种玛。” “怎么了瓤檐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,105評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵赂韵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我挠蛉,道長(zhǎng)祭示,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,242評(píng)論 1 292
  • 正文 為了忘掉前任谴古,我火速辦了婚禮质涛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掰担。我一直安慰自己汇陆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評(píng)論 6 389
  • 文/花漫 我一把揭開(kāi)白布带饱。 她就那樣靜靜地躺著瞬测,像睡著了一般。 火紅的嫁衣襯著肌膚如雪纠炮。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,215評(píng)論 1 299
  • 那天灯蝴,我揣著相機(jī)與錄音恢口,去河邊找鬼。 笑死穷躁,一個(gè)胖子當(dāng)著我的面吹牛耕肩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播问潭,決...
    沈念sama閱讀 40,096評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼猿诸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了狡忙?” 一聲冷哼從身側(cè)響起梳虽,我...
    開(kāi)封第一講書(shū)人閱讀 38,939評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎灾茁,沒(méi)想到半個(gè)月后窜觉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體谷炸,經(jīng)...
    沈念sama閱讀 45,354評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評(píng)論 2 333
  • 正文 我和宋清朗相戀三年禀挫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了旬陡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,745評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡语婴,死狀恐怖描孟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情砰左,我是刑警寧澤匿醒,帶...
    沈念sama閱讀 35,448評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站菜职,受9級(jí)特大地震影響青抛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜酬核,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評(píng)論 3 327
  • 文/蒙蒙 一蜜另、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嫡意,春花似錦此迅、人聲如沸旧巾。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,683評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鲁猩。三九已至坎怪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間廓握,已是汗流浹背搅窿。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,838評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留隙券,地道東北人男应。 一個(gè)月前我還...
    沈念sama閱讀 47,776評(píng)論 2 369
  • 正文 我出身青樓沐飘,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親牲迫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子薪铜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容