Mp4格式詳解

????????Mp4是一種非常常見的一種音視頻封裝格式,因為兼容性強,所以被普遍使用。今天總結(jié)了一下Mp4格式。

Mp4格式是一種使用box為單元的格式,Mp4的box有很多種,見過的70多個吧,這里一共寫了必須的10多個,剩下的可以擴(kuò)展,有:fpyt,free,mdat,moov,mvhd,trak,tkhd,mdia,mdhd,hdlr,minf,vmhd,smhd,dinf,stbl,stsd,stts,stsc,stsz,stco,stss,ctts(可選),avc1,accC,mp4a,esds。

MP4文件封裝格式,對應(yīng)的標(biāo)準(zhǔn)為ISO/IEC 14496-12,即信息技術(shù) 視聽對象編碼的第12部分 ISO 基本媒體文件格式(Information technology Coding of audio-visual objects Part 12: ISO base media file format)

如果從整體上看,mp4所有的數(shù)據(jù)全部存放在 一個叫box的結(jié)構(gòu)中。

box,顧名思義,可以簡單的理解為一個箱子?里面可以放任何符合大小的東西,也可以繼續(xù)放箱子,箱子里面再放東西,這種箱子里面仍然放箱子的箱子稱為容器箱子(container box) 你可以想象你要搬家,把你的家具全部放在一個個的箱子里面,然后一個大箱子把小箱子一個個再裝箱。MP4中的 moov box 就是一種容器箱子。


box的字節(jié)序為網(wǎng)絡(luò)字節(jié)序,也就是大端字節(jié)序(Big-Endian)Box由header和body組成,其中header統(tǒng)一指明box的大小和類型,body根據(jù)類型有不同的意義和作用。


box size 有三種可能:

1、通常的box開頭的4個字節(jié)(32位)為box size,該大小包括box header和box body整個box的大小,這樣我們就可以在文件中定位各個box。

2、如果 box size為1,則表示這個box的大小為large size(“mdat”類型)。

3、如果box size為0,表示該box為文件的最后一個box,文件結(jié)尾即為該box結(jié)尾。(同樣只存在于“mdat”類型的box中。)

size后面緊跟的32位為box type,一般是4個字符,如“ftyp”、“moov”等,這些box type都是已經(jīng)預(yù)定義好的,分別表示固定的意義。如果是“uuid”,表示該box為用戶擴(kuò)展類型,如果box type是未定義的,應(yīng)該將其忽略。

14496-12標(biāo)準(zhǔn)中box的都有這些類型,這張表,也能從整體上了解完各類型box的說明:


MP4文件分析工具。

兩個在線的MP4 分析工具,下面內(nèi)容全部以此工具來分析一份demo

online-mp4-parser

online-mp4-parser-2

可以看到這份標(biāo)準(zhǔn)的mp4視頻根路徑上有四個box --?ftyp、moov、uuid、mdat

ftyp 指定了文件類型

moov 保存了音視頻數(shù)據(jù)的時空間信息

mdat 存放音視頻數(shù)據(jù)

下面依賴工具簡單依次分析一份普通mp4文件


ftyp box

該box有且只有1個,并且只能被包含在文件層,而不能被其他box包含。該box應(yīng)該被放在文件的最開始,指示該MP4文件應(yīng)用的相關(guān)信息。

“ftyp” body依次包括1個32位的major brand(4個字符),1個32位的minor version(整數(shù))和1個以32位(4個字符)為單位元素的數(shù)組compatible brands。這些都是用來指示文件應(yīng)用級別的信息。

moov box

moov box 是一個 container box 該box包含了文件媒體的元數(shù)據(jù)信息,具體內(nèi)容信息由子box詮釋。同F(xiàn)ile Type Box一樣,該box有且只有一個,且只被包含在文件層。一般情況下,“moov”會緊隨“ftyp”出現(xiàn)。

可以看到這個demo 中有 mvhd、trak、udta 三種 box 一般情況下 “moov”中會包含1個“mvhd”和若干個“trak”。其中“mvhd”為header box,一般作為“moov”的第一個子box出現(xiàn)?!皌rak”包含了一條音、視頻軌/流/track的相關(guān)信息,也是一個container box。

該box是解析MP4文件里面最重要的一個box,它包含了音視頻數(shù)據(jù)的編碼格式、音視頻數(shù)據(jù)樣本,chunks的大小、存儲位置也即偏移offset、時間戳單位、DTS,CTS(PTS),解碼時間、顯示時間等等...

moov box中記錄的每幀音視頻數(shù)據(jù)位置信息,實際上都在mdat box中,通過解析moov box來獲取到每幀音視頻數(shù)據(jù)具體位置后,使得播放器能方便的拖拉進(jìn)度條。

mvhd box (Movie Header Box)

mvhd 描述了與具體音頻或視頻流無關(guān)的文件整體信息,其中的duration/timescale的值即為單位為秒的媒體時長。

trak box (Track Box)

trak也是一個container box,其子box包含了該track的媒體數(shù)據(jù)引用和描述。一個MP4文件中的媒體可以包含多個track,且至少有一個track,這些track之間彼此獨立,有自己的時間和空間信息?!皌rak”必須包含一個“tkhd”和一個“mdia”,此外還有很多可選的box(略)。

tkhd(track header box)

tkhd 描述的該track的,如果是視頻會有寬、高信息、 還有文件創(chuàng)建時間、修改時間等。

mdia (Track Media Structure)

mdia box 描述了這條音視頻軌/流(trak)的媒體數(shù)據(jù)樣本的主要信息,對播放器來說是一個很重要的box..

mdhd (Media Header Box)

當(dāng)前音/視頻軌/流(trak)的總體信息, 該box中有duration字段和timescale字段,duration/timescale的值即為當(dāng)前流的時長。

hdlr box用來指定該流的類型

stsd box的子box用于保存該流的編碼類型

avcC box指定了該流的編碼類型為H264,儲了解碼所需的SPS、PPS信息。

stsc stsz stco三個box用于保存每幀視頻或音頻數(shù)據(jù)在文件中的保存位置。

stts stss ctts三個box用于保存媒體數(shù)據(jù)和時間戳的對應(yīng)關(guān)系。

在同級的stbl的樣本表box里面可以查到對應(yīng)的樣本 描述信息(stsd),時序信息(stts),樣本的大小信息(stsz),樣本到chunk的映射信息(stsc),chunk的位置信息(stco)等等

下面計算下PTS,來了解stbl box..

PTS和DTS的計算

I P B 幀的概念

在音視頻中,為了提高壓縮效率,會將每幀畫面壓縮為不同類型的視頻幀數(shù)據(jù)。

I幀表示關(guān)鍵幀,包含有一幀畫面的完整信息,解碼時只需要本幀數(shù)據(jù)就可以解碼出完整的一幀畫面。

P幀表示前向參考幀,它保存了本幀與上一幀的差異信息,它不能單獨解碼,需要根據(jù)上一幀的畫面加上本幀保存的差值來獲取本幀的完整畫面。

B幀為雙向參考幀,它解碼時需要依賴它之前和之后的幀來獲取最終的畫面

因為B幀需要依賴它后面的幀來進(jìn)行解碼,所以它的解碼順序就必然和顯示順序不能保持一致,這時就需要解碼時間戳(DTS)和顯示時間戳(PTS)來共同決定一幀視頻數(shù)據(jù)何時解碼,然后何時顯示了。

舉個例子

一小段視頻幀序列如下 :

type : I --- B --- B --- P --- B --- B --- P

PTS : 0.33 0.67 1.00 1.33 1.67 2.00 2.33

DTS : 0.00 0.67 1.00 0.33 1.67 2.00 1.33

PTS >= DTS

根據(jù)mp4 stts和ctts 可以得到DTS和PTS

stts(Decoding Time to Sample Box)

stts 可以計算出每個sample的dts,其中sample_delta為該sample的dts相對于上一個smaple的差值,

那么此樣本數(shù)據(jù)的dts為 :

0 1000200030004000···

ctts(Composition Time to Sample Box)

Composition Time 構(gòu)成時間目前我直接理解的PTS。。

ctts 有每個sample的構(gòu)成時間(Composition Time)和解碼時間(DTS)之間的差值(CTTS)即圖中的composition_offset。

如果不存在ctts,則代表該流不存在B幀,那么PTS就直接等于DTS。

timescale

最后就是關(guān)于單位,你可以看到圖中樣本的單位都是以1000為單位浮動,實際上真實DTS和PTS時間是需要除以mdia/mdhd中的timescale。這里是30000。

有了這些,我們就可以在ctts里面計算出pts了 :

elseif(box_type_equa(uint32_to_str(bh.type, sbuffer),"ctts")) {uint32_tversion =0;? ? ? ? read_net_bytes_to_host_uint32(&box[8], &version);if(version !=0) {? ? ? ? ? ? LOG_E("ctts unsupport version :%d ", version)return;? ? ? ? }uint32_tentry_cnt =0;? ? ? ? read_net_bytes_to_host_uint32(&box[12], &entry_cnt);charbuf[128] = {0};? ? ? ? tree_childs_insert_with_val(tree,"version", uint32_to_ascii(version, buf));? ? ? ? tree_childs_insert_with_val(tree,"entry_cnt", uint32_to_ascii(entry_cnt, buf));uint32_ti =0, j =0, num =0, pos =16;for(i =0; i < entry_cnt; i++) {uint32_tsample_cnt;? ? ? ? ? ? read_net_bytes_to_host_uint32(&box[pos], &sample_cnt);? ? ? ? ? ? pos +=4;uint32_tsample_offset;? ? ? ? ? ? read_net_bytes_to_host_uint32(&box[pos], &sample_offset);? ? ? ? ? ? pos +=4;for(j =0; j < sample_cnt; j++) {? ? ? ? ? ? ? ? PushBack_Array(pts_array, At_Array(dts_array, num++) + sample_offset);floatdt, pt =0.0;printf("dts : %9.3f ms | pts : %9.3f ms | \n", At_Array(dts_array, num -1) / (mdhd_time_scale *1.0), At_Array(pts_array, num -1) / (mdhd_time_scale *1.0));? ? ? ? ? ? }

stss (Sync Sample Box)

stss 里面存放了關(guān)鍵幀的序號(I幀),跳轉(zhuǎn)時,需要從關(guān)鍵幀開始解碼,否則會花屏。

stsz (Sample Size Boxes):

顧名思義,樣本大小.

stsc (Sample To Chunk Box):

媒體數(shù)據(jù)的樣本是被打包進(jìn)chunks(塊)的,chunks和樣本(samples)的大小不固定,該box用于說明chunks關(guān)聯(lián)樣本的信息。

first_chunk 該入口第一個chunks的索引(index).

samples_per_chunk 樣本數(shù)量/chunks.

stco (Chunk Offset Box)

描述每個chunks相對文件的偏移量。

如圖 第一個chunks即前10個樣本(此例), samples.1起始地址為 423257, samples.1的地址則為 423257 + 140798 = 564055, 依此類推...

有了這些即可計算出音視頻的時間和空間信息了

mdat box

Meida Data Box 媒體數(shù)據(jù)box 位于頂層,定義是一個字節(jié)數(shù)組,用來存儲媒體數(shù)據(jù)。該box數(shù)量可以為0個,也可以有多個(當(dāng)媒體數(shù)據(jù)全部為外部文件引用時),數(shù)據(jù)直接跟在box type字段后面,具體數(shù)據(jù)結(jié)構(gòu)的意義需要參考metadata(主要在sample table中描述)。

出處:http://www.cnblogs.com/ailumiyana/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容