前言
本節(jié)重點講解了 H.264 編碼以及 AAC 編碼,在對其進行講解前先介紹了視頻編碼的實現(xiàn)原理。
一、視頻編碼的實現(xiàn)原理
1、視頻編碼技術(shù)的基本原理
編碼就是為了壓縮。要實現(xiàn)壓縮,就要設(shè)計各種算法,將視頻數(shù)據(jù)中的冗余信息去除。
種類 | 內(nèi)容 | 壓縮方法 |
---|
空間冗余 | 像素間的相關(guān)性 | 變換編碼,預(yù)測編碼 | 時間冗余 | 時間方向上的相關(guān)性 | 幀間預(yù)測,運動補償 | 圖像構(gòu)造冗余 | 圖像本身的構(gòu)造 | 輪廓編碼,區(qū)域分割 | 知識冗余 | 收發(fā)兩端對人物的共有認識 | 基于知識的編碼 | 視覺冗余 | 人的視覺特性 | 非線性量化,位分配 | 其他 | 不確定因素 |
|
視頻編碼技術(shù)優(yōu)先消除的目標,就是空間冗余和時間冗余。
2、視頻編碼技術(shù)的實現(xiàn)方法
視頻是由不同的幀畫面連續(xù)播放形成的。這些幀,主要分為三類,分別是:
- I 幀
- 是自帶全部信息的獨立幀,是最完整的畫面(占用的空間最大),無需參考其它圖像便可獨立進行解碼。視頻序列中的第一個幀,始終都是 I 幀。
- B 幀
- “雙向預(yù)測編碼幀”,以前幀后幀作為參考幀。不僅參考前面,還參考后面的幀,所以,它的壓縮率最高,可以達到 200:1。不過,因為依賴后面的幀,所以不適合實時傳輸(例如視頻會議)。
- P 幀
- “幀間預(yù)測編碼幀”,需要參考前面的 I 幀和/或 P 幀的不同部分,才能進行編碼。P 幀對前面的 P 和 I 參考幀有依賴性。但是,P 幀壓縮率比較高,占用的空間較小。
通過對幀的分類處理,可以大幅壓縮視頻的大小。
畢竟,要處理的對象,大幅減少了(從整個圖像,變成圖像中的一個區(qū)域)。
3、運動估計和補償
①、塊(Block)與宏塊(MicroBlock)
如果總是按照像素來算,數(shù)據(jù)量會比較大,所以,一般都是把圖像切割為不同的“塊(Block)”或“宏塊(MacroBlock)”,對它們進行計算。
一個宏塊一般為 16 像素×16 像素。
②、I 幀、P 幀、B 幀的小結(jié)
- 對 I 幀的處理,是采用幀內(nèi)編碼方式,只利用本幀圖像內(nèi)的空間相關(guān)性。
- 對 P 幀的處理,采用幀間編碼(前向運動估計) ,同時利用空間和時間上的相關(guān)性。
簡單來說,采用運動補償(motion compensation)算法來去掉冗余信息。
③、I 幀(幀內(nèi)編碼)
需要特別注意,I 幀(幀內(nèi)編碼),雖然只有空間相關(guān)性,但整個編碼過程也不簡單。 如上圖所示,整個幀內(nèi)編碼,還要經(jīng)過 DCT(離散余弦變換)、量化、編碼等多個過程。
- RGB 轉(zhuǎn) YUV:固定公式
- 圖片宏塊切割:宏塊 16x16
- DCT:離散余弦變換
- 量化:取樣
- ZigZag 掃描:
- DPCM:差值脈沖編碼調(diào)制
- RLE:游程編碼
- 算數(shù)編碼:
④、如何衡量和評價編解碼的效果
一般來說,分為客觀評價和主觀評價??陀^評價,就是拿數(shù)字來說話。例如計算“信噪比/峰值信噪比”
一般來說,分為客觀評價和主觀評價。
- 客觀評價,就是拿數(shù)字來說話。例如計算“信噪比/峰值信噪比”。
- 主觀評價,就是用人的主觀感知直接測量。
二、H.264 編碼基礎(chǔ)
1、H.264 快速入門
從事視頻編碼算法的標準化組織主要有兩個,ITU-T 和 ISO。
- ITU-T,國際電信聯(lián)盟——電信標準分局,主要制定了 H.261/H263/H263+/H263++ 等標準
- ISO,國際標準化組織,主要制定了 MPEG-1/MPEG-4 等
比如 MPEG-2、 H.264/AVC 和 H.265/HEVC 等。不同標準組織制定的視頻編碼標準的發(fā)展如下圖所示:
②、視頻壓縮編碼的基本技術(shù)
視頻信息之所以存在大量可以被壓縮的空間, 是因為其中本身就存在大量的數(shù)據(jù)冗余。 其主要類型有:
- 時間冗余:視頻相鄰的兩幀之間內(nèi)容相似,存在運動關(guān)系
- 空間冗余:視頻的某一幀內(nèi)部的相鄰像素存在相似性
- 編碼冗余:視頻中不同數(shù)據(jù)出現(xiàn)的概率不同
- 視覺冗余: 觀眾的視覺系統(tǒng)對視頻中不同的部分敏感度不同
針對這些不同類型的冗余信息,在各種視頻編碼的標準算法中都有不同的技術(shù)專門應(yīng)對,以通過不同的角度提高壓縮的比率。
<1>、預(yù)測編碼
預(yù)測編碼可以用于處理視頻中的時間和空間域的冗余。
視頻處理中的預(yù)測編碼主要分為兩大類:幀內(nèi)預(yù)測和幀間預(yù)測。
- 幀內(nèi)預(yù)測:預(yù)測值與實際值位于同一幀內(nèi),用于消除圖像的空間冗余;幀內(nèi)預(yù)測的特點是壓縮率相對較低,然而可以獨立解碼,不依賴其他幀的數(shù)據(jù);通常視頻中的關(guān)鍵幀都采用幀內(nèi)預(yù)測。
- 幀間預(yù)測:幀間預(yù)測的實際值位于當(dāng)前幀,預(yù)測值位于參考幀,用于消除圖像的時間冗余;幀間預(yù)測的壓縮率高于幀內(nèi)預(yù)測,然而不能獨立解碼,必須在獲取參考幀數(shù)據(jù)之后才能重建當(dāng)前幀。
通常在視頻碼流中,I 幀全部使用幀內(nèi)編碼,P 幀/B 幀中的數(shù)據(jù)可能使用幀內(nèi)或者幀間編碼。
<2>、變換編碼
所謂變換編碼是指,將給定的圖象變換到另一個數(shù)據(jù)域如頻域上,使得大量的信息能用較少的數(shù)據(jù)來表示,從而達到壓縮的目的。
目前主流的視頻編碼算法均屬于有損編碼,通過對視頻造成有限而可以容忍的損失,獲取相對更高的編碼效率。
而造成信息損失的部分即在于變換量化這一部分。
在進行量化之前,首先需要將圖像信息從空間域通過變換編碼變換至頻域,并計算其變換系數(shù)供后續(xù)的編碼。
在視頻編碼算法中通常使用正交變換進行變換編碼,常用的正交變換方法有:離散余弦變換(DCT)、 離散正弦變換(DST)、K-L 變換等。
<3>、熵編碼
視頻編碼中的熵編碼方法主要用于消除視頻信息中的統(tǒng)計冗余。
由于信源中每一個符號出現(xiàn)的概率并不一致,這就導(dǎo)致使用同樣長度的碼字表示所有的符號會造成浪費。
通過熵編碼,針對不同的語法元素分配不同長度的碼元,可以有效消除視頻信息中由于符號概率導(dǎo)致的冗余。
在視頻編碼算法中常用的熵編碼方法有變長編碼和算術(shù)編碼等,具體來說主要有:
- UVLC(Universal Variable Length Coding):主要采用指數(shù)哥倫布編碼
- CAVLC(Context Adaptive Variable Length Coding):上下文自適應(yīng)的變長編碼
- CABAC(Context Adaptive Binary Arithmetic Coding):上下文自適應(yīng)的二進制算數(shù)編碼
根據(jù)不同的語法元素類型指定不同的編碼方式。 通過這兩種熵編碼方式達到一種編碼效率與 運算復(fù)雜度之間的平衡。
③、VCL NAL
視頻編碼中采用的如預(yù)測編碼、變化量化、熵編碼等編碼工具主要工作在 slice 層或以下,這一層通常被稱為“視頻編碼層”(Video Coding Layer, VCL)。
相對的,在 slice 以上所進行的數(shù)據(jù)和算法通常稱之為“網(wǎng)絡(luò)抽象層”(Network Abstraction Layer, NAL)。
設(shè)計定義 NAL 層的主要意義在于提升 H.264 格式的視頻對網(wǎng)絡(luò)傳輸和數(shù)據(jù)存儲的親和性。
④、檔次與級別
為了適應(yīng)不同的應(yīng)用場景,H.264 也定義了三種不同的檔次:
- 基準檔次(Baseline Profile):主要用于視頻會議、可視電話等低延時實時通信領(lǐng)域;支持 I 條帶和 P 條帶,熵編碼支持 CAVLC 算法。
- 主要檔次(Main Profile):主要用于數(shù)字電視廣播、數(shù)字視頻數(shù)據(jù)存儲等;支持視頻場編碼、B 條帶雙向預(yù)測和加權(quán)預(yù)測,熵編碼支持 CAVLC 和 CABAC 算法。
- 擴展檔次(Extended Profile):主要用于網(wǎng)絡(luò)視頻直播與點播等;支持基準檔次的所有特性,并支持 SI 和 SP 條帶,支持數(shù)據(jù)分割以改進誤碼性能,支持 B 條帶和加權(quán)預(yù)測,但不支持 CABAC 和場編碼。
CAVLC 支持所有的 H.264 profiles,CABAC 則不支援 Baseline 以及 Extended profiles。
⑤、常見編碼器
H.264 是一種視頻壓縮標準, 其只規(guī)定了符合標準的碼流的格式, 以及碼流中各個語法元素的解析方法。H.264 標準并未規(guī)定編碼器的實現(xiàn)或流程,這給了不同的廠商或組織在編碼實現(xiàn)方面極大的自由度, 并產(chǎn)生了一些比較著名的開源 H.264 編解碼器工程。
其中 H.264 編碼器中最著名的兩個當(dāng)屬 JM 和 X264, 這二者都屬于 H.264 編碼標準的一種實現(xiàn)形式。
JM encoder 實在太慢了,x264則相當(dāng)快.
2、H.264 編碼原理與實現(xiàn)
①、前言
H264 在視頻采集到輸出中屬于編解碼層次的數(shù)據(jù),如下圖所示,是在采集數(shù)據(jù)后做編碼壓縮時通過編碼標準編碼后所呈現(xiàn)的數(shù)據(jù)。
②、H264 相關(guān)概念
<1>、序列
H264 編碼標準中所遵循的理論依據(jù)個人理解成:參照一段時間內(nèi)相鄰的圖像中, 像素、 亮度與色溫的差別很小。
所以當(dāng)面對一段時間內(nèi)圖像我們沒必要去對每一幅圖像進行完整一幀的編碼,而是可以選取這段時間的第一幀圖像作為完整編碼,而下一幅圖像可以記錄與第一幀完整編碼圖像像素、亮度與色溫等的差別即可,以此類推循環(huán)下去。
什么叫序列呢?上述的這段時間內(nèi)圖像變化不大的圖像集我們就可以稱之為一個序列。 序列可以理解為有相同特點的一段數(shù)據(jù)。
<2>、幀類型
H264 結(jié)構(gòu)中,一個視頻圖像編碼后的數(shù)據(jù)叫做一幀,一幀由一個片(slice)或多個片組成,一個片由一個或多個宏塊(MB)組成,一個宏塊由 16x16 的 yuv 數(shù)據(jù)組成。宏塊作為 H264 編碼的基本單位。
在 H264 協(xié)議內(nèi)定義了三種幀,分別是 I 幀、B 幀與 P 幀。
<3>、GOP(畫面組,圖像組)
GOP 我個人也理解為跟序列差不多意思,就是一段時間內(nèi)變化不大的圖像集。
GOP 結(jié)構(gòu)一般有兩個數(shù)字,如 M=3,N=12。M 指定 I 幀和 P 幀之間的距離,N 指定兩個 I 幀之間的距離。
上面的 M=3,N=12,GOP 結(jié)構(gòu)為: IBBPBBPBBPBBI。
在一個 GOP 內(nèi) I frame 解碼不依賴任何的其它幀,p frame 解碼則依賴前面的 I frame 或 P frame,B frame 解碼依賴前最近的一個 I frame 或 P frame 及其后最近的一個 P frame。
<4>、IDR 幀(關(guān)鍵幀)
在編碼解碼中為了方便,將 GOP 中首個 I 幀要和其他 I 幀區(qū)別開,把第一個 I 幀叫 IDR,這樣方便控制編碼和解碼流程,所以 IDR 幀一定是 I 幀,但 I 幀不一定是 IDR 幀;IDR 幀的作用是立刻刷新,使錯誤不致傳播,從 IDR 幀開始算新的序列開始編碼。I 幀有被跨幀參考的可能,IDR 不會。
I 幀不用參考任何幀,但是之后的 P 幀和 B 幀是有可能參考這個 I 幀之前的幀的。
IDR 就不允許這樣, 例如:
IDR1 P4 B2 B3 P7 B5 B6 I10 B8 B9 P13 B11 B12 P16 B14 B15
這里的 B8 可以跨過 I10 去參考 P7
IDR1 P4 B2 B3 P7 B5 B6 IDR8 P11 B9 B10 P14 B11 B12
這里的 B9 就只能參照 IDR8 和 P11,不可以參考 IDR8 前面的幀
作用: H.264 引入 IDR 圖像是為了解碼的重同步,當(dāng)解碼器解碼到 IDR 圖像時,立即將參考幀隊列清空,將已解碼的數(shù)據(jù)全部輸出或拋棄,重新查找參數(shù)集, 開始一個新的序列。 這樣,如果前一個序列出現(xiàn)重大錯誤,在這里可以獲得重新同步的機會。IDR 圖像之后的圖像永遠不會使用 IDR 之前的圖像的數(shù)據(jù)來解碼。
③、H264 壓縮方式
H264 采用的核心算法是幀內(nèi)壓縮和幀間壓縮, 幀內(nèi)壓縮是生成 I 幀的算法, 幀間壓縮是生成 B 幀和 P 幀的算法。
- 幀內(nèi)(Intraframe)壓縮也稱為空間壓縮(Spatialcompression)。當(dāng)壓縮一幀圖像時,僅考慮本幀的數(shù)據(jù)而不考慮相鄰幀之間的冗余信息,這實際上與靜態(tài)圖像壓縮類似。幀內(nèi)一般采用有損壓縮算法,由于幀內(nèi)壓縮是編碼一個完整的圖像,所以可以獨立的解碼、顯示。幀內(nèi)壓縮一般達不到很高的壓縮,跟編碼 jpeg 差不多
- 幀間(Interframe)壓縮的原理是:相鄰幾幀的數(shù)據(jù)有很大的相關(guān)性,或者說前后兩幀信息變化很小的特點。也即連續(xù)的視頻其相鄰幀之間具有冗余信息,根據(jù)這一特性,壓縮相鄰幀之間的冗余量就可以進一步提高壓縮量,減小壓縮比。幀間壓縮也稱為時間壓縮(Temporalcompression),它通過比較時間軸上不同幀之間的數(shù)據(jù)進行壓縮。幀間壓縮一般是無損的。幀差值(Framedifferencing)算法是一種典型的時間壓縮法,它通過比較本幀與相鄰幀之間的差異,僅記錄本幀與其相鄰幀的差值,這樣可以大大減少數(shù)據(jù)量。
壓縮方式說明
- Step1:分組,也就是將一系列變換不大的圖像歸為一個組,也就是一個序列,也可以叫 GOP(畫面組) ;
- Step2:定義幀,將每組的圖像幀歸分為 I 幀、P 幀和 B 幀三種類型;
- Step3:預(yù)測幀,以 I 幀做為基礎(chǔ)幀,以 I 幀預(yù)測 P 幀,再由 I 幀和 P 幀預(yù)測 B 幀;
- Step4:數(shù)據(jù)傳輸,最后將 I 幀數(shù)據(jù)與預(yù)測的差值信息進行存儲和傳輸。
④、H264 分層結(jié)構(gòu)
H.264 原始碼流(裸流)是由一個接一個 NALU 組成,它的功能分為兩層,VCL(視頻編碼層)和 NAL(網(wǎng)絡(luò)提取層)
H264 的主要目標是為了有高的視頻壓縮比和良好的網(wǎng)絡(luò)親和性,為了達成這兩個目標,H264 的解決方案是將系統(tǒng)框架分為兩個層面,分別是視頻編碼層面(VCL) 和網(wǎng)絡(luò)抽象層面(NAL),如下圖;
- VCL 層(視頻編碼層)是對核心算法引擎、塊、宏塊及片的語法級別的定義,負責(zé)有效表示視頻數(shù)據(jù)的內(nèi)容,最終輸出編碼完的數(shù)據(jù) SODB
- NAL 層(視頻數(shù)據(jù)網(wǎng)絡(luò)抽象層)定義了片級以上的語法級別(如序列參數(shù)集參數(shù)集和圖像參數(shù)集,針對網(wǎng)絡(luò)傳輸,后面會描述到),負責(zé)以網(wǎng)絡(luò)所要求的恰當(dāng)方式去格式化數(shù)據(jù)并提供頭信息,以保證數(shù)據(jù)適合各種信道和存儲介質(zhì)上的傳輸。NAL 層將 SODB 打包成RBSP 然后加上 NAL 頭組成一個 NALU 單元。
- 因為 H264 最終還是要在網(wǎng)絡(luò)上進行傳輸,在傳輸?shù)臅r候,網(wǎng)絡(luò)包的最大傳輸單元是 1500 字節(jié),一個 H264 的幀往往是大于 1500 字節(jié)的,所以需要將一個幀拆成多個包進行傳輸。這些拆包、組包等工作都在 NAL 層去處理。
<1>、SODB 與 RBSP 的關(guān)聯(lián)
具體結(jié)構(gòu)如下圖所示:
- SODB:數(shù)據(jù)比特串,是編碼后的原始數(shù)據(jù);
- RBSP:原始字節(jié)序列載荷,是在原始編碼數(shù)據(jù)后面添加了結(jié)尾比特,一個 bit“1”和若干個比特“0”,用于字節(jié)對齊。
<2>、SODB RBSP EBSP 的區(qū)別
- SODB(String of Data Bits,數(shù)據(jù)比特串)
- 最原始, 未經(jīng)過處理的編碼數(shù)據(jù)
- 因為它是流的形式,所以長度不一定是 8 倍數(shù),它是由 VLC 層產(chǎn)生的。由于我們計算機是以 8 倍數(shù)去處理數(shù)據(jù)所以計算機在處理 H264 時,就需要 RBSP。
- RBSP(Raw Byte Sequence Payload,原始字節(jié)序列載荷)
- 在 SODB 的后面填加了結(jié)尾 bit(RBSP trailing bits 一個 bit '1’) 若干 bit '0’,以便字節(jié)對齊。
- 由于它是一個壓縮流,SODB 不知道是在何處結(jié)束,所以算法在 SODB 最后一位補一個 1,沒有按字節(jié)對齊的則補 0。
- EBSP(Encapsulated Byte Sequence Payload,擴展字節(jié)序列載荷)
- NALU 的起始碼為 0x000001 或 0x00000001(起始碼包括兩種:3 字節(jié)(0x000001)和 4 字節(jié)(0x00000001),在 SPS、PPS 和 Access Unit 的第一個 NALU 使用 4 字節(jié)起始碼,其余情況均使用 3 字節(jié)起始碼。)
- 在生成壓縮流之后,在每一幀的開頭加一個起始位,這個起始位一般是 00 00 00 01 或者是 00 00 01。所以在 h264 碼流中規(guī)定每有兩個連續(xù)的 00 00,就增加一個 0x03。
- 仿校驗字節(jié)(0x03)
- 同時 H264 規(guī)定,當(dāng)檢測到 0x000000 時,也可以表示當(dāng)前 NALU 的結(jié)束。那這樣就會產(chǎn)生一個問題,就是如果在 NALU 的內(nèi)部,出現(xiàn)了 0x000001 或 0x000000 時該怎么辦?
- 在 RBSP 基礎(chǔ)上填加了仿校驗字節(jié)(0x03)它的原因是:在 NALU 加到 Annexb 上時,需要填加每組 NALU 之前的開始碼 StartCodePrefix,如果該 NALU 對應(yīng)的 slice為一幀的開始則用 4 位字節(jié)表示,0x00000001,否則用 3 位字節(jié)表示 0x000001,為了使 NALU 主體中不包括與開始碼相沖突的,在編碼時,每遇到兩個字節(jié)連續(xù)為 0,就插入一個字節(jié)的 0x03。解碼時將 0x03 去掉。也稱為脫殼操作。
關(guān)系圖:
為什么要弄一個 EBSP 呢? EBSP 相較于 RBSP, 多了防止競爭的一個字節(jié): 0x03。 我們知道,NALU 的起始碼為 0x000001 或 0x00000001,同時 H264 規(guī)定,當(dāng)檢測到 0x000000 時,也可以表示當(dāng)前 NALU 的結(jié)束。那這樣就會產(chǎn)生一個問題,就是如果在 NALU 的內(nèi)部,出現(xiàn)了 0x000001 或 0x000000 時該怎么辦? 所以 H264 就提出了“防止競爭”這樣一種機制,當(dāng)編碼器編碼完一個 NAL 時,應(yīng)該檢測 NALU 內(nèi)部,是否出現(xiàn)如下左側(cè)的四個序列。當(dāng)檢測到它們存在時,編碼器就在最后一個字節(jié), 插入一個新的字節(jié):0x03。
⑤、H264 碼流結(jié)構(gòu)
在具體講述 NAL 單元前,十分有必要先了解一下 H264 的碼流結(jié)構(gòu);在經(jīng)過編碼后的 H264 的碼流如下圖所示,從圖中我們需要得到一個概念,H264 碼流是由一個個的 NAL 單元組成,其中 SPS、PPS、IDR 和 SLICE 是 NAL 單元某一類型的數(shù)據(jù)。
⑥、H264 的 NAL 單元
<1>、H264 的 NAL 結(jié)構(gòu)
在實際的網(wǎng)絡(luò)數(shù)據(jù)傳輸過程中 H264 的數(shù)據(jù)結(jié)構(gòu)是以 NALU(NAL 單元)進行傳輸?shù)?,傳輸?shù)據(jù)結(jié)構(gòu)組成為 [NALU Header]+[RBSP],如下圖所示: VCL 層編碼后的視頻幀數(shù)據(jù),幀有可能是 I/B/P 幀,這些幀也可能是屬于不同的序列之中,同一序列也還有相應(yīng)的序列參數(shù)集與圖片參數(shù)集;想要完成準確無誤視頻的解碼,除了需要 VCL 層編碼出來的視頻幀數(shù)據(jù),同時還需要傳輸 序列參數(shù)集和 圖像參數(shù)集等等。
上面知道 NAL 單元是作為實際視頻數(shù)據(jù)傳輸?shù)幕締卧?,NALU 頭是用來標識后面 RBSP 是什么類型的數(shù)據(jù),同時記錄 RBSP 數(shù)據(jù)是否會被其他幀參考以及網(wǎng)絡(luò)傳輸是否有錯誤。
<2>、NAL 頭
NAL 單元的頭部是由 forbidden_bit(1bit),nal_reference_bit(2bits)(優(yōu)先級),nal_unit_type(5bits)(類型)三個部分組成的, 組成如下圖所示:
- F(forbiden):禁止位,占用 NAL 頭的第一個位,當(dāng)禁止位值為 1 時表示語法錯誤
- NRl:參考級別,占用 NAL 頭的第二到第三個位;值越大, 該 NAL 越重要
- Type:Nal 單元數(shù)據(jù)類型,也就是標識該 NAL 單元的數(shù)據(jù)類型是哪種,占用 NAL 頭的第四到第 8 個位
<3>、NAL 單元數(shù)據(jù)類型
NAL 類型主要就是下面圖中這些類型每個類型都有特殊的作用; 在具體介紹 NAL 數(shù)據(jù)類型前, 有必要知道 NAL 分為 VCL 和非 VCL 的 NAL 單元。
而另外一個需要了解的概念就是參數(shù)集(Parameter sets) ,參數(shù)集是攜帶解碼參數(shù)的 NAL 單元,參數(shù)集對于正確解碼是非常重要的,在一個有損耗的傳輸場景中,傳輸過程中比特列或包可能丟失或損壞,在這種網(wǎng)絡(luò)環(huán)境下,參數(shù)集可以通過高質(zhì)量的服務(wù)來發(fā)送,比如向前糾錯機制或優(yōu)先級機制。
以上三種數(shù)據(jù)塊每種分割被單獨的存放在一個 NAL 單元中,因此可以被單獨傳輸
<4>、NAL Unit
一個 H264 的幀至少由一個切片組成,不能沒有切片,可以是一個到多個。
在網(wǎng)絡(luò)傳輸?shù)臅r候一個 H264 幀可能需要切開去傳,一個一次傳不完,這就按照切片來切。
每一個切片組成一個 NAL Unit。
<5>、切片與宏塊的關(guān)系
在切片數(shù)據(jù)中,包含若干個宏塊。 在一個宏塊中,又包含了宏塊類型、宏塊預(yù)測、殘差數(shù)據(jù)。
<6>、H264 的 NAL 單元與片、宏之間的聯(lián)系
- 1 幀(一幅圖像)= 1~N 個片(slice) //也可以說 1 到多個片為一個片組
- 1 個片 = 1~N 個宏塊(Marcroblock)
- 1 個宏塊 = 16X16 的 YUV 數(shù)據(jù)(原始視頻采集數(shù)據(jù))
從數(shù)據(jù)層次角度來說,一幅原始的圖片可以算作廣義上的一幀,幀包含片組和片,片組由片來組成,片由宏塊來組成,每個宏塊可以是 44、88、16*16 像素規(guī)模的大小,它們之間的聯(lián)系如圖所示。 同時有幾點需要說明一下,這樣能便于理解 NAL 單元:
- 如果不采用 FMO(靈活宏塊排序)機制,則一幅圖像只有一個片組;
- 如果不使用多個片,則一個片組只有一個片;
- 如果不采用 DP(數(shù)據(jù)分割)機制, 則一個片就是一個 NALU,一個 NALU 也就是一個片。否則,一個片的組成需要由 三個 NALU 組成,也就是上面說到的 A、 B、 C 類數(shù)據(jù)塊
這時候在看下面這幅碼流數(shù)據(jù)分層, 下圖就比較能理解整體的碼流結(jié)構(gòu)組成了 如我們所見,每個分片也包含著頭和數(shù)據(jù)兩部分;分片頭中包含著分片類型、分片中的宏塊類型、分片幀的數(shù)量以及對應(yīng)的幀的設(shè)置和參數(shù)等信息;而分片數(shù)據(jù)中則是宏塊,這里就是我們要找的存儲像素數(shù)據(jù)的地方,宏塊是視頻信息的主要承載者,因為它包含著每一個像素的亮度和色度信息。
視頻解碼最主要的工作則是提供高效的方式從碼流中獲得宏塊中的像素陣列。
宏塊數(shù)據(jù)的組成如下圖所示: 從上圖中,可以看到,宏塊中包含了宏塊類型、預(yù)測類型、Coded Block Pattern、Quantization Parameter、像素的亮度和色度數(shù)據(jù)集等等信息。
需要注意的幾點:
- H.264/AVC 標準對送到解碼器的 NAL 單元順序是有嚴格要求的,如果 NAL 單元的順序是混亂的,必須將其重新依照規(guī)范組織后送入解碼器,否則解碼器不能夠正確解碼。
- 序列參數(shù)集(sps)NAL 單元必須在傳送所有以此參數(shù)集為參考的其他 NAL 單元之前傳送,不過允許這些 NAL 單元中間出現(xiàn)重復(fù)的序列參數(shù)集 NAL 單元。所謂重復(fù)的詳細解釋為:序列參數(shù)集 NAL 單元都有其專門的標識,如果兩個序列參數(shù)集 NAL 單元的標識相同,就可以認為后一個只不過是前一個的拷貝,而非新的序列參數(shù)集。
- 圖像參數(shù)集(pps)NAL 單元 必須在所有以此參數(shù)集為參考的其他 NAL 單元之前傳送,不過允許這些 NAL 單元中間出現(xiàn)重復(fù)的圖像參數(shù)集 NAL 單元,這一點與上述的序列參數(shù)集NAL 單元是相同
三、AAC 編碼基礎(chǔ)
AAC 是高級音頻編碼(Advanced Audio Coding)的縮寫,AAC 是新一代的音頻有損壓縮技術(shù)
1、AAC 編碼的特點
- AAC 是一種高壓縮比的音頻壓縮算法,但它的壓縮比要遠超過較老的音頻壓縮算法,如 AC-3、MP3 等。并且其質(zhì)量可以同未壓縮的 CD 音質(zhì)相媲美。
- 同其他類似的音頻編碼算法一樣,AAC 也是采用了變換編碼算法,但 AAC 使用了分辨率更高的濾波器組,因此它可以達到更高的壓縮比。
- AAC 使用了臨時噪聲重整、后向自適應(yīng)線性預(yù)測、聯(lián)合立體聲技術(shù)和量化哈夫曼編碼等最新技術(shù),這些新技術(shù)的使用都使壓縮比得到進一步的提高。
- AAC 支持更多種采樣率和比特率、支持 1 個到 48 個音軌、支持多達 15 個低頻音軌、具有多種語言的兼容能力、還有多達 15 個內(nèi)嵌數(shù)據(jù)流。
- AAC 支持更寬的聲音頻率范圍,最高可達到 96kHz,最低可達 8KHz,遠寬于 MP3 的 16KHz-48kHz 的范圍。
- 不同于 MP3 及 WMA,AAC 幾乎不損失聲音頻率中的甚高、甚低頻率成分,并且比 WMA 在頻譜結(jié)構(gòu)上更接近于原始音頻,因而聲音的保真度更好。專業(yè)評測中表明,AAC 比 WMA 聲音更清晰,而且更接近原音
- AAC 采用優(yōu)化的算法達到了更高的解碼效率,解碼時只需較少的處理能力。
2、AAC 音頻文件格式
①、ACC 音頻文件格式類型
AAC 的音頻文件格式有:ADIF,ADTS
- ADIF:Audio Data Interchange Format 音頻數(shù)據(jù)交換格式。這種格式的特征是可以確定的找到這個音頻數(shù)據(jù)的開始,不需進行在音頻數(shù)據(jù)流中間開始的解碼,即它的解碼必須在明確定義的開始處進行。 故這種格式常用在磁盤文件中。
- ADTS:Audio Data Transport Stream 音頻數(shù)據(jù)傳輸流。這種格式的特征是它是一個有同步字的比特流,解碼可以在這個流中任何位置開始。它的特征類似于 mp3 數(shù)據(jù)流格式。
簡單說,ADTS 可以在任意幀解碼,也就是說它每一幀都有頭信息。ADIF 只有一個統(tǒng)一的頭,所以必須得到所有的數(shù)據(jù)后解碼。這兩種的 header 的格式也是不同的,一般編碼后的和抽取出的都是 ADTS 格式的音頻流。
AAC 的 ADIF 文件格式如下圖: AAC 的 ADTS 文件中一幀的格式如下圖:
②、ADIF 的 Header 結(jié)構(gòu)
ADIF 的頭信息如下圖: ADIF 頭信息位于 AAC 文件的起始處, 接下來就是連續(xù)的 Raw Data Blocks。
組成 ADIF 頭信息的各個域如下所示:
③、ADTS 的 Header 結(jié)構(gòu)
ADTS 的固定頭信息: ADTS 的可變頭信息:
- 幀同步目的在于找出幀頭在比特流中的位置,13818-7 規(guī)定,AAC ADTS 格式的幀頭同步字為 12 比特的“1111 1111 1111”。
- ADTS 的頭信息為兩部分組成,其一為固定頭信息,緊接著是可變頭信息。固定頭信息中的數(shù)據(jù)每一幀都相同,而可變頭信息則在幀與幀之間可變。
④、AAC 元素信息
在 AAC 中,原始數(shù)據(jù)塊的組成可能有六種不同的元素:
- SCE: Single Channel Element 單通道元素。單通道元素基本上只由一個 ICS 組成。一個原始數(shù)據(jù)塊最可能由 16 個 SCE 組成。
- CPE: Channel Pair Element 雙通道元素,由兩個可能共享邊信息的 ICS 和一些聯(lián)合立體聲編碼信息組成。一個原始數(shù)據(jù)塊最多可能由 16 個 SCE 組成。
- CCE: Coupling Channel Element 藕合通道元素。代表一個塊的多通道聯(lián)合立體聲信息或者多語種程序的對話信息。
- LFE: Low Frequency Element 低頻元素。包含了一個加強低采樣頻率的通道。
- DSE: Data Stream Element 數(shù)據(jù)流元素,包含了一些并不屬于音頻的附加信息。
- PCE: Program Config Element 程序配置元素。包含了聲道的配置信息。它可能出現(xiàn)在 ADIF 頭部信息中。
- FIL: Fill Element 填充元素。包含了一些擴展信息。如 SBR,動態(tài)范圍控制信息等。
⑤、AAC 文件處理流程
- (1)判斷文件格式, 確定為 ADIF 或 ADTS
- (2)若為 ADIF,解 ADIF 頭信息,跳至第 6 步
- (3)若為 ADTS,尋找同步頭
- (4)解 ADTS 幀頭信息
- (5)若有錯誤檢測,進行錯誤檢測
- (6)解塊信息
- (7)解元素信息
3、編碼算法處理流程
首先對輸入的 PCM 信號分段,每幀每聲道 1024 個樣本,采用 1/2 重疊,組合得到 2048 個樣本。
加窗后,進行離散余弦變化(MDCT),輸出 1024 個頻譜分量,依據(jù)不同采樣率和變換塊類型劃分成 10 個不同帶寬的比例因子頻帶。其中變化塊類型由 心理聲學(xué)模型 計算分析得到,該模型還將輸出 信掩比,用于后續(xù)模塊的處理。
AAC 還使用了一種新的稱為時域噪聲整形的技術(shù),簡稱為 TNS。TNS 的作用機理在于利用了時域和頻域信號的對偶性
量化和編碼使用一種兩層嵌套循環(huán)算法,以權(quán)衡碼率和失真之間的矛盾。
最后,進行比特流封裝,得到壓縮后的碼流。
|