概述
-
問:音視頻處理主要以解碼、特效、音視頻合成等為主,為什么先介紹編碼?
答:只有對(duì)編碼原理和碼流理解得足夠徹底,才能做好開發(fā)工作,視頻的開發(fā)不是簡單地調(diào)用api,理解不透徹的話,遇到問題可能會(huì)毫無頭緒,很可能連api都不知道怎么用,編碼可以直接理解為壓縮,將原始的yuv數(shù)據(jù)壓縮為體積更小的數(shù)據(jù) -
問:什么是H264?
答:提到視頻編碼,不得不提到大名鼎鼎的H.264。目前常見的編碼標(biāo)準(zhǔn)有H264、H265、VP8、VP9 和 AV1,而其中用的最普遍的視頻編碼就是H.264(所以本文主要就來詳細(xì)介紹一下它)。H264和H265都是國際標(biāo)準(zhǔn)化組織(ISO)和國際電信聯(lián)盟(ITU)開發(fā)的編碼標(biāo)準(zhǔn),而VP8、VP9 和 AV1是谷歌開發(fā)的編碼標(biāo)準(zhǔn)
編碼的思路
大家都知道編碼的目的是壓縮原始數(shù)據(jù),方便保存和傳輸,如何壓縮?大體可以從一下3個(gè)方面來著手
- 幀內(nèi)預(yù)測(cè)壓縮,一張圖像相鄰的兩個(gè)像素顏色可能很相似,那么它們的數(shù)據(jù)也就很相似,那么就產(chǎn)生了冗余數(shù)據(jù),幀內(nèi)壓縮主要解決這部分冗余問題
- 幀間預(yù)測(cè)壓縮,相鄰的兩幀圖像往往很相似,同理,這里也產(chǎn)生了冗余數(shù)據(jù),幀間壓縮主要解決這部分冗余問題
- 整數(shù)離散余弦變換(DCT),將空間上的相關(guān)性變?yōu)轭l域上無關(guān)的數(shù)據(jù)然后進(jìn)行量化,圖像中人眼不敏感的信息會(huì)產(chǎn)生一些視覺上的冗余數(shù)據(jù),DCT主要解決視覺冗余問題
- 熵編碼,真正的編碼開始了,將上面三部分得到的數(shù)據(jù),進(jìn)行編碼算法的到最終的碼流
預(yù)測(cè)編碼
預(yù)測(cè)編碼(Predictive Coding)是統(tǒng)計(jì)冗余數(shù)據(jù)壓縮理論三個(gè)重要分支之一,它的理論基礎(chǔ)是現(xiàn)代統(tǒng)計(jì)學(xué)和控制論,用預(yù)測(cè)編碼可以減少數(shù)據(jù)時(shí)間和空間的相關(guān)性,它廣泛地用于時(shí)間序列圖像數(shù)據(jù)和語音數(shù)據(jù)的壓縮編碼。預(yù)測(cè)編碼的方法是從相鄰象素之間有較強(qiáng)的相關(guān)性特點(diǎn)考慮,比如當(dāng)前象素的灰度或顏色信號(hào),數(shù)值上與其相鄰象素總是比較接近,除非處于邊界狀態(tài),那么,當(dāng)前象素的灰度或顏色信號(hào)的數(shù)值,可用前面已出現(xiàn)的象素的值進(jìn)行預(yù)測(cè)(估計(jì)),得到一個(gè)預(yù)測(cè)值(估計(jì)值),將實(shí)際值與預(yù)測(cè)值求差,對(duì)這個(gè)差值信號(hào)進(jìn)行編碼、傳送,這種編碼方法稱為預(yù)測(cè)編碼方法。預(yù)測(cè)編碼方分線性預(yù)測(cè)和非線性預(yù)測(cè)編碼兩種。
幀內(nèi)預(yù)測(cè)
一幀圖像中相鄰像素的亮度和色度信息是比較接近的,并且亮度和色度信息也是逐漸變化的,不太會(huì)出現(xiàn)突變。也就是說,圖像具有空間相關(guān)性。 利用這種相關(guān)性,視頻壓縮就可以去除空間冗余信息。 幀內(nèi)預(yù)測(cè),通過已編碼的像素來預(yù)測(cè)待編碼的像素值,最后達(dá)到減少空間冗余的目的,具體思路詳看上述預(yù)測(cè)編碼章節(jié),具體步驟如下:
- 劃分
宏塊
為了通過已編碼的像素來預(yù)測(cè)尚未編碼的像素,需要將一幀圖像劃分為若干個(gè)區(qū)域, 每個(gè)區(qū)域叫做宏塊,宏塊是編碼標(biāo)準(zhǔn)的基本處理單元,通常它的大小為 16x16 像素(H264 默認(rèn)是使用 16X16 大小的區(qū)域作為一個(gè)宏塊,也可以劃分成 8X8 大小的宏塊)
- 劃分
- 劃分子塊(圖像中細(xì)節(jié)復(fù)雜的地方)
16X16 的宏塊上可以劃分出更小的子塊。子塊的大小可以是 8X16? 16X8? 8X8? 4X8? 8X4? 4X4。
- 劃分子塊(圖像中細(xì)節(jié)復(fù)雜的地方)
- 對(duì)每個(gè)宏塊進(jìn)行預(yù)測(cè)
預(yù)測(cè)模式多達(dá)九種,預(yù)測(cè)模式就不在本文詳解了,預(yù)測(cè)后找出與原圖最接近的一種模式,然后計(jì)算差值(殘差值),將差值和預(yù)測(cè)模式一起保存下來,就可以還原原始圖像了
- 對(duì)每個(gè)宏塊進(jìn)行預(yù)測(cè)
幀間預(yù)測(cè)
- 幀分組
對(duì)于視頻數(shù)據(jù)主要有兩類數(shù)據(jù)冗余,一類是時(shí)間上的數(shù)據(jù)冗余,另一類是空間上的數(shù)據(jù)冗余。.其中時(shí)間上的數(shù)據(jù)冗余是最大的。下面我們就先來說說視頻數(shù)據(jù)時(shí)間上的冗余問題。
為什么說時(shí)間上的冗余是最大的呢?假設(shè)攝像頭每秒抓取30幀,這30幀的數(shù)據(jù)大部分情況下都是相關(guān)聯(lián)的。也有可能不止30幀的的數(shù)據(jù),可能幾十幀,上百幀的數(shù)據(jù)都是關(guān)聯(lián)特別密切的。
對(duì)于這些關(guān)聯(lián)特別密切的幀,其實(shí)我們只需要保存一幀的數(shù)據(jù),其它幀都可以通過這一幀再按某種規(guī)則預(yù)測(cè)出來,所以說視頻數(shù)據(jù)在時(shí)間上的冗余是最多的。
為了達(dá)到相關(guān)幀通過預(yù)測(cè)的方法來壓縮數(shù)據(jù),就需要將視頻幀進(jìn)行分組。那么如何判定某些幀關(guān)系密切,可以劃為一組呢?
分組即 H264 中的 序列(GOP)。其算法是:在相鄰幾幅圖像畫面中,一般有差別的像素只有 10% 以內(nèi)的點(diǎn),亮度差值變化不超過 2%,而色度差值的變化只有 1% 以內(nèi),我們認(rèn)為這樣的圖可以分到一組,在這樣一組幀中,經(jīng)過編碼后,我們只保留第一帖的完整數(shù)據(jù),其它幀都通過參考上一幀計(jì)算出來。我們稱第一幀為 IDR/I幀,其它幀我們稱為 P/B幀,這樣編碼后的數(shù)據(jù)幀組我們稱為 GOP。
所以如果場(chǎng)景一直沒什么變化,則一系列視頻幀中 I 幀的數(shù)量會(huì)很少。如果場(chǎng)景變換很復(fù)雜,一直在場(chǎng)景變換大的場(chǎng)景切換時(shí)就會(huì)有 I 幀出現(xiàn)。
- 幀分組
- 幀間預(yù)測(cè)(運(yùn)動(dòng)估計(jì)與運(yùn)動(dòng)補(bǔ)償)
H264 編碼器先按順序從編碼緩沖區(qū)取出兩幀圖像數(shù)據(jù),然后進(jìn)行宏塊掃描。當(dāng)發(fā)現(xiàn)其中一幀圖像中有物體時(shí),就在另一幀的鄰近位置進(jìn)行匹配。如果此時(shí)在另一幀圖像中匹配了該物體,那么就可以計(jì)算出物體的運(yùn)動(dòng)矢量了,運(yùn)動(dòng)矢量計(jì)算出來以后,將兩幀圖像相同部分的數(shù)據(jù)減掉,就得到了補(bǔ)償數(shù)據(jù),通過補(bǔ)償數(shù)據(jù)即可還原圖像了
我們把運(yùn)動(dòng)矢量與補(bǔ)償稱為幀間壓縮技術(shù),它解決的是視頻幀在時(shí)間上的數(shù)據(jù)冗余。在這一步我們獲取了 P/B 幀
- 幀間預(yù)測(cè)(運(yùn)動(dòng)估計(jì)與運(yùn)動(dòng)補(bǔ)償)
DCT(離散余弦變換)
- 首先說說圖像頻率是什么。圖像可以看做是一個(gè)定義為二維平面上的信號(hào),該信號(hào)的幅值對(duì)應(yīng)于像素的灰度值(對(duì)于彩色圖像則是RGB三個(gè)分量),如果我們僅僅考慮圖像上某一行像素,則可以將之視為一個(gè)定義在一維空間上的信號(hào),這個(gè)信號(hào)在形式上與傳統(tǒng)的信號(hào)處理領(lǐng)域的時(shí)變信號(hào)是相似的,時(shí)變信號(hào)是有一定頻率成分的,圖像的頻率又稱為空間頻率,它反映了圖像的像素灰度在空間中變化的情況。
- 一般圖片的高頻信息多但是幅值比較小。高頻信息主要描述圖片的邊緣或者細(xì)節(jié)信息,對(duì)于快速空間變化的圖像來說,比如充滿溝壑的山脈,其高頻成分會(huì)相對(duì)較強(qiáng),低頻則較弱。而低頻主要是圖像的整體輪廓信息。由于人眼的視覺敏感度是有限的,有的時(shí)候我們?nèi)コ艘徊糠指哳l信息之后,人眼看上去感覺區(qū)別并不大。這就是去除視覺冗余。
- 因此,我們可以先將圖片通過 DCT(離散余弦變換) 變換到頻域,然后再去除一些高頻信息。這樣我們就可以減少信息量,從而達(dá)到壓縮的目的
熵編碼
- 主要去除信息熵冗余。而前面說的去除空間、時(shí)間、視覺冗余,其實(shí)都是為這一步做準(zhǔn)備的。
- 前面的幀內(nèi)幀間預(yù)測(cè)得到的殘差以及后面的變換量化,都是將數(shù)據(jù)盡量轉(zhuǎn)換為連續(xù)的0更多的表現(xiàn)形式,然后再利用合理的編碼算法去編碼形成最終的碼流。
- 視頻內(nèi)容部分使用的是內(nèi)容自適應(yīng)的(CABAC或CAVLC)算術(shù)編碼。具體編碼算法這里就不深入了,不過核心思想都是利用了連續(xù)的‘0’盡可能去進(jìn)行壓縮
不喜勿噴
視頻編解碼技術(shù)太過復(fù)雜,本人也在學(xué)習(xí)中,本文寫的很淺顯,內(nèi)容也大部分參考網(wǎng)上內(nèi)容,有錯(cuò)誤的地方還請(qǐng)指正,不喜勿噴,謝謝!