視頻基礎和MP4容器解封裝

最近在研究基於移動端平臺上使用視頻作動畫載體的方案,目前移動端平臺使用動畫的方案有:gif圖、apng、webp、lottie、svga等,各有各的優點,也有相應的劣勢,而使用視頻作動畫的目的,尋求的是完美還原設計師的設計特效外,同時性能達到極致。html

在這個過程當中,也積累了一些視頻相關的知識,藉此同你們分享下。web

第一部分 視頻相關基礎

1、視頻的編解碼方式

談到視頻,咱們常常會聽到視頻編解碼、H.264等諸如此類的內容。那麼視頻編解碼是什麼意思呢?算法

視頻編解碼,其實就是對視頻數據進行壓縮和解壓縮的過程,而在討論到編解碼時,又常常同H.264聯繫到一塊兒,那麼H.264又是什麼?windows

H.264是一種視頻壓縮標準,簡稱AVG,一種被普遍使用的高精度視頻的錄製、壓縮和發佈格式。該標準引入了一系列新的可以大大提升壓縮性能的技術,並可以同時在高碼率端和低碼率端大大超越之前的諸標準,能夠說是一種壓縮算法,但又不只僅止步於此。markdown

H.264H.26X系列中的一種,目前最新是H.265,簡稱HEVC,在一樣的畫面質量下,後者的壓縮率是前者兩倍(比特率減小50%),是將來發展趨勢,iOS上的Video ToolBox目前可支持H.265的編解碼。網絡

視頻編碼還有其餘的標準,好比AMVAVS等等,但主流基本是H.26X系列。ide

2、關於H.264

H.264是視頻的原始碼流,分爲兩層,分別是視頻編碼層(VCL)和網絡提取層(NAL),前者是H.264編碼/壓縮的核心,主要負責將視頻數據編碼/壓縮,再切分,後者負責格式化VCL數據並提供頭信息,以保證數據適合各類信道和存儲介質的傳輸,基本單位是NALUsvg

經過上圖能夠看到,一個視頻幀包含了一個或多個NALU,開頭通常是SPSPPS,這兩個主要是用於初始化解碼器所須要的參數信息,也是解碼的關鍵,接下去就是I/P/B幀等NALU數據,而NALU細分下去還有切片、宏等單位,這裏因爲篇幅緣由就不在展開述論。工具

3、視頻幀相關概念

在視頻的編解碼中,常常會討論到幾個很關鍵的名詞,如I幀、P幀、B幀等。接下來從編碼和解碼角度來理解它們。oop

從編碼角度上來講:

  1. I幀:幀內編碼幀, I幀一般是每一個GOP(MPEG所使用的一種視頻壓縮技術)的第一個幀,通過適度地壓縮,做爲隨機訪問的參考點,能夠當成靜態圖像,I幀壓縮掉視頻的空間冗餘信息;
  2. P幀:前向預測編碼幀,經過將圖像序列中前面已編碼幀的時間冗餘信息充分去除來壓縮傳輸數據量的編碼圖像;
  3. B幀:雙向預測內插編碼幀,既考慮源圖像序列前面的已編碼幀,又顧及源圖像序列後面的已編碼幀之間的時間冗餘信息,來壓縮傳輸數據量的編碼圖像。

從解碼角度上來講:

  1. I幀自身能夠經過視頻解壓算法解壓成一張單獨的完整視頻畫面,因此I幀去掉的是視頻幀在空間維度上的冗餘信息;
  2. P幀須要參考其前面的一個I幀或者P幀來解碼成一張完整的視頻畫面;
  3. B幀則須要參考其前一個I幀或者P幀及其後面的一個P幀來生成一張完整的視頻畫面,因此P幀與B幀去掉的是視頻幀在時間維度上的冗餘信息。

除次以外,還有PTSDTSGOP

PTS是用來描述視頻解碼階段的幀輸出順序,DTS用來描述視頻解碼階段的幀解碼順序,在無B幀的狀況下,PTS等於DTS,在有B幀的狀況下,輸出順序須要參考PTS

GOP,描述的是兩個I幀之間造成的一組圖片。

第二部分 MP4解封裝

1、MP4定義

MP4是咱們常見的視頻資源,但MP4的本質又是什麼呢?和H.264有什麼不可告人的祕密呢?

MP4也叫MPEG-4,是一種多媒體容器格式,後綴是.mp4,其容器格式借鑑了AppleQuickTime的組織方式,即以一系列BOX爲基本單位。

2、Box理解

MP4文件由若干個box組成,box的示意圖如上圖所示:

  1. boxheaderbody組成,header指明瞭boxsizetype
  2. size包含了boxheaderbody整個大小;若是size爲1,表示box的長度須要用更多的bits位來描述,能夠經過一個64bits位的largesize來描述box的長度,若是size爲0,表示該box爲文件的最後一個box
  3. type,一般使用4個ASCII碼的字符如"ftyp"、"moov"等表示,這些box type是已經預約義好的,表示固定的含義,若是是"uuid",表示該box爲用戶自定義拓展的類型,若是box type是未定義的,應將其忽略;
  4. box中能夠包含box,這種box叫作container box
  5. box分爲兩種,BoxFullboxFullBoxBox的拓展,header中增長了8位的version和24位的flags字段。

3、常見的MP4文件工具

  1. mp4box.js:一個在線解析mp4的工具。
  2. bento4:包含mp4dump、mp4edit、mp4encrypt等工具。
  3. MP4Box:相似於bento4,包含很全面的工具。
  4. mp4info.exe: windows平臺圖形界面展現mp4基本信息的工具。

咱們使用mp4box.js,能夠看到MP4文件由許多box組成,每一個box包含不一樣的信息,以樹形的方式組織,主要的box以下:

經過上表,咱們能夠看到有4個樹節點:

  1. ftyp:文件類型;
  2. moov box:媒體的metadata的描述和信息;
  3. mdat:具體的媒體數據;
  4. free:可有可無的內容。

4、基本Box介紹

File Type Box

ftyp簡單的說就是爲了標識它的developer是誰,兼容哪些標準等,如「mp42」表示它的major brand是MP4 v2,而「mp42」和「mp41」則表示它的compatible brands是MP4 v2和MP4 v1。

  • major_brand:推薦兼容性的版本;
  • minor_version:最低兼容性的版本;
  • compatible_brands[]:全部的兼容性的版本。

Movie Box(moov)

包含了文件媒體的metadata信息,是一個container box,通常在ftyp後面。moov包含1個mvhd和若干個trak,其中mvhd是header box,做爲第一個子box出現,trak包含一個trakc的相關信息,是一個container box。

Movie Header Box(mvhd)

mvhd(Movie Header Box),主要存放着視頻文件的meta data,其中的time scale和 duration對文件的播放有着重要做用

  • version:box的版本,0或者1,通常爲0;
  • creation time:建立時間(相對於UTC時間1904-01-01零點的秒數);
  • modification time:修改時間;
  • timescale:文件媒體在1秒時間內的刻度,可理解爲1s長度的時間單元數;
  • duration:該track的時間長度;
  • rate:推薦播放速率,高16位和低16位分別爲小數點整數部分和小數部分,[16.16]格式,該值爲1.0(0x00010000)表示正常向前播放;
  • volume:推薦播放音量,[8.8]格式,1.0(0x0100)表示最大音量。
  • martix:視頻變換矩陣
  • newxt track id:下一個track使用的id

Track Header Box(tkhd)

  • version:box版本,0或者1,通常爲0;
  • flags:24-bit整數,按位或操做結果值;
  • track id:track id號,不能重複且不能爲0;
  • duration:track的時間長度;
  • volume:[8.8]格式,若是爲音頻track,1.0(0x0100)表示最大音量,不然爲0;
  • width:寬度,[16.16]格式;
  • height:高度,[16.16]格式,沒必要與sample的像素尺寸一致,用於播放時顯示的寬高。

Media Box(mdia)

Media Boxyeshi 也是一個container box,其定義了track媒體類型以及smaple數據,描述sample的信息。 mdia包含:

  • 一個Media Header Atom,即mdhd;
  • 一個Handler Reference,即hdlr;
  • 一個media information,即minf,解碼的關鍵。

Media Header Box(mdhd)

mdhd和tkhd內容上大體一致,不過tkhd一般是指定的track設定的相關屬性和內容,而mdhd是針對獨立的media來設置的,字段包含

  • version:box的版本,0或者1,通常爲0;
  • timescale:比mvhd中的timescale精度更高;
  • duration:track的時間長度;
  • language:媒體語言碼,最高位爲0。

handler Reference Box(hdlr)

hdlr解釋了媒體的播放過程信息,可獲取track類型信息,主要是有字段handler_type(uint32_t)區分,具體含義以下:

  • handler type:該值爲4個字符,會有如下取值:
    • vide:視頻;
    • soun:音頻;
    • hint:這個特殊的track並不包含媒體數據,而是包含了一些將其餘數據track打包成流媒體的指示信息。

Media Information Box(minf)

重要的容器box,存儲瞭解釋track媒體數據的handler-specific信息,media handler用這些信息將媒體時間映射到媒體數據並行處理,minf是一個container box,其實際內容由子box說明。 通常狀況下,minf包含了一個header box,一個dinf和一個stbl,其中header box的數據類型有vmhd(視頻軌)、smhd(音軌)、hmhd(hint track)、nmhd(null track),dinf爲data information box,stbl爲sample table box。

5、重要Box

Sample Table Box(stbl)

stbl包含了關於track中sample全部時間和位置的信息,以及sample的編解碼等信息。利用這個表,能夠解釋sample的時序、類型、大小以及在各自存儲容器中的位置。stbl是MP4文件中最複雜的一個box了,也是解開MP4文件格式的主幹,是一個container box;

stbl包含:

  • stsd:sample description box,樣本的描述信息;
  • stts:time to sample box,sample解碼時間的壓縮表;
  • ctts:composition time to sample box,sample的CTS與DTS的時間差壓縮表;
  • stss:sync sample box,針對視頻,關鍵幀的序號;
  • stsz/stz2:sample size box,每一個smaple的字節大小;
  • stsc:sample to chunk box,sample-chunk映射表;
  • stco/co64:chunk offset box,chunk在文件中的偏移。

在mp4文件中,sample是一個媒體流的基本單元,例如視頻流的一個sample表明實際的nal數據。chunk是數據存儲的基本單位,它是一系列sample數據的集合,一個chunk中能夠包含一個或多的sample。

Sample Description Box(stsd)

存儲了編碼類型和初始化解碼器須要的信息。 stsd有多種類型的子box,具體取決於該track是視頻或是音頻或是其餘,對於視頻,如果經過使用了H.264編碼的,子box爲avc1,avc1的主要字段:

  • type:avc1;
  • width、height:視頻像素寬高;
  • horizresolution、vertresolution:每英寸的像素值,[16,16]格式的數據;
  • frame_count:每一個sample的視頻幀數,默認是1;
  • avcC:存放sps和pps內容。

Decoding Time to Sample Box(stts)

包含一個Sample編碼時序表,經過這個表能夠從解碼時間映射到sample序號,表中的每一項是連續相同的編碼時間增量(Decode Delta)的個數和編碼時間增量,經過把時間增量累加就能夠創建一個完整的time to sample表。

Composition time to sample box(ctts)

這個box提供了decoding time到composition time的offset的表,用於計算pts。

  • 這個表在Decoding time和composition time不同的狀況下是必須的。
  • 若是box的version等於0,decoding time必須小於等於composition time,於是差值用一個無符號的數字表示。
  • sample_count:連續相同的offset的個數;
  • sample_offset:CT和DT之間的offset。

  • DT(decoding time):編碼時間;
  • CT(composition offset):創做時間;
  • Decode Delta:編碼時間增量,經過前面提到的stts表可獲取;
  • Composition offset:顯示時間同解碼時間的差值,等於CT-DT,經過ctts獲取。

由此可知,經過sttsctts能夠方向推出解碼順序和視頻播放順序,當無B幀視頻時,ctts不存在,解碼順序和播放順序一致。

Sync Sample box(stss)

它包含media中的關鍵幀的sample表,若是此表不存在,則每一幀都是關鍵幀。

主要字段sample_number:媒體流中同步的sample序號。

Sample Size Box(stsz/stz2)

包含sample的數量和每一個sample的字節大小,box體積有點大,主要字段有:

  • sample_size:指定默認的sample的字節大小,若是smaple大小不同,則這個字段爲0;
  • sample_count:track中的sample的數量;
  • sample_sizes:每一個sample的字節大小。

Sample To Chunk Box(stsc)

meida中的sample被分組成chunk,chunk能夠有不一樣的大小,chunk內的sample能夠有不一樣的大小,經過stsc中的sample-chunk映射表能夠找到指定的smaple的chunk,從而找到這個sample。結構相同的chunk能夠彙集在一塊兒造成一個entry,這個entry就是一個stsc映射表的表項。

主要字段說明:

  • first_chunk:一組chunk的第一個chunk的序號;

chunk的編號從1開始。

  • samples_per_chunk:每一個chunk有多少個sample;
  • sample_desc_idx:stsd中的sample desc信息的索引。

Chunk Offset Box(stco/co64)

Chunk Offset表存儲了每一個thunk在文件中的位置,這樣就能夠找到媒體數據,而不用解析box了。

總結

感謝您閱讀到這裏,本次分享的內容只是視頻方面的基礎,過程有些枯燥,如如有什麼描述不對或不得當,歡迎指出。

相關文章
相關標籤/搜索