談到視頻的編解碼,我們會(huì)自然地想到H.264、HEVC/H.265這些權(quán)威的視頻編解碼標(biāo)準(zhǔn);談到標(biāo)準(zhǔn),有人覺(jué)得這個(gè)是有專門機(jī)構(gòu)去研究的,我們關(guān)心應(yīng)用就好;即使有興趣讀了標(biāo)準(zhǔn)和相關(guān)技術(shù),面對(duì)更多的是各種數(shù)學(xué)公式和術(shù)語(yǔ),如協(xié)方差、傅立葉變換、高頻、濾波等等,需要花更多時(shí)間去理解。通常更為實(shí)際的做法是,我們只要調(diào)研如何應(yīng)用這些標(biāo)準(zhǔn),如何做好軟硬件編碼方案的選型,如何優(yōu)化技術(shù)參數(shù)以及如何調(diào)用API,也就基本能夠應(yīng)對(duì)日常的視頻業(yè)務(wù)了。因此,談到視頻的編解碼,往往帶有一絲神秘色彩。
本文的目標(biāo)是以非專業(yè)的視角來(lái)看待視頻編解碼原理,試圖將所謂高大上的專業(yè)術(shù)語(yǔ)或名詞轉(zhuǎn)換為普通IT業(yè)者略懂的話語(yǔ),從而使更多人了解視頻編解碼到底是怎么回事。
為什么要編碼?
原因很簡(jiǎn)單,不經(jīng)過(guò)編碼的源視頻數(shù)據(jù)量太大了。例如輸出一路1920×1080分辨率、24位色、每秒30幀的高清視頻,就這么一秒鐘的視頻,它的碼率達(dá)就到了1.5Gbps.因此需要編碼,盡最大可能將其壓縮至最低。下圖展示了編解碼標(biāo)準(zhǔn)的演進(jìn)歷程,經(jīng)過(guò)H.264編碼后,視頻碼率被壓縮到10Mbps,是源視頻數(shù)據(jù)量的1/150。
那么,什么時(shí)候我們不再關(guān)心編碼了?理想的狀態(tài)就是我們不再對(duì)存儲(chǔ)空間和網(wǎng)絡(luò)帶寬的限制有顧慮的時(shí)候,就不需要考慮編碼了,照單全收即可。
思考:N年以后,在 G網(wǎng)絡(luò)普及之后,視頻的編解碼技術(shù)和CDN的作用會(huì)不會(huì)越來(lái)越被淡化?
什么是編碼?
狹義但不全面的解釋:編碼最主要的工作就是壓縮。但壓縮是分步驟的,不是簡(jiǎn)單地把圖像中重復(fù)的0 聚在一起這么簡(jiǎn)單。依據(jù)方法論,可壓縮的內(nèi)容有以下幾種:
單幅圖像壓縮
一幅圖像,分成若干小塊,每塊8×8像素大小,如果這個(gè)小塊的每個(gè)像素的顏色都是白色,是不是就可以用一個(gè)點(diǎn)的值來(lái)代替這所有64個(gè)點(diǎn)的值? 這在編碼中的標(biāo)準(zhǔn)術(shù)語(yǔ)叫空間冗余,相應(yīng)的方法叫幀內(nèi)壓縮。
多幅圖像間壓縮
視頻中一個(gè)連續(xù)的動(dòng)作,比如畫(huà)面里的女主角在紅墻背景下閉上了眼睛,這一動(dòng)作的背后,是由一系列的多幅圖片組成,而每幅圖片的內(nèi)容基本上都是一樣的,唯一變化的部分就是女主角的眼睛所在圖像區(qū)域,眼睛緩慢由開(kāi)到閉,這塊區(qū)域的像素值發(fā)生了變化。對(duì)于絕大多數(shù)的背景區(qū)域,它是沒(méi)有變化的,那么除了含有閉眼動(dòng)作的這塊區(qū)域,是否可以只用一幅圖像來(lái)代替這么多個(gè)連續(xù)的圖像呢?這在編碼中的術(shù)語(yǔ)叫時(shí)間冗余,強(qiáng)調(diào)的是在一定時(shí)間段內(nèi)如何對(duì)連續(xù)多幅圖像的冗余部分進(jìn)行壓縮,術(shù)語(yǔ)叫幀間壓縮。
編碼的壓縮
圖像的空間冗余和時(shí)間冗余都被壓縮了,壓縮成一串字符串,對(duì)這段字符串的展現(xiàn)有沒(méi)有進(jìn)一步壓縮的可能性呢?是所謂的編碼冗余。
所有的視頻編碼技術(shù)和標(biāo)準(zhǔn)都是努力對(duì)上述三種冗余數(shù)據(jù)進(jìn)行壓縮,絞盡腦汁采用不同的算法和策略,產(chǎn)生了不同的結(jié)果,也就產(chǎn)生了不同的視頻編碼標(biāo)準(zhǔn)。
編碼的核心技術(shù)步驟主要分為預(yù)測(cè)、變換、量化、熵編碼,這幾步之后還有個(gè)可選步驟是濾波。是不是有點(diǎn)懵,現(xiàn)在解釋一下。
預(yù)測(cè)
一個(gè)視頻根據(jù)時(shí)間采樣被拆成N個(gè)圖像,為了壓縮和計(jì)算方便,每個(gè)圖像被分成多個(gè)小塊,比如每個(gè)小塊由8×8個(gè)像素構(gòu)成。如果不做壓縮,就需要把每個(gè)圖像的每個(gè)像素值都存儲(chǔ)起來(lái),一共存儲(chǔ)N幅圖像連接起來(lái),從而構(gòu)成一個(gè)完整的原始視頻。像素值的類型分為圖像的亮度值和色彩值。為了簡(jiǎn)化理解 ,本文通篇以亮度值舉例進(jìn)行講解。
壓縮的第一步是預(yù)測(cè)。對(duì)于一幅圖像的每個(gè)塊,根據(jù)某幾個(gè)相鄰的像素值,在指定的方向上對(duì)下一個(gè)像素點(diǎn)的值用一個(gè)公式做預(yù)測(cè),從而得到該點(diǎn)的預(yù)測(cè)的像素值,來(lái)構(gòu)造完整的圖像。
再比如:有連續(xù)兩幅運(yùn)動(dòng)圖像 ,對(duì)一幅圖像不做改變,保存本來(lái)的像素值,然后以此圖像的值為基礎(chǔ),對(duì)另一幅圖像使用公式計(jì)算來(lái)做運(yùn)動(dòng)預(yù)測(cè),即把第一幅圖像的某個(gè)像素的值,經(jīng)過(guò)公式計(jì)算后,預(yù)測(cè)出第二個(gè)圖像指定位置的像素值,以此類推,得到一幅完整的預(yù)測(cè)出來(lái)的圖像。
問(wèn)題來(lái)了,這世上哪有那么牛的算法能計(jì)算預(yù)測(cè)得這么完美?是的,沒(méi)有。那預(yù)測(cè)還有什么用?答案是為了獲取他們的差。差值有什么用?因?yàn)椴钪档慕^對(duì)值都很小。還是不明白?我們看下圖的三個(gè)像素值矩陣:

是不是感覺(jué)到了差值矩陣的數(shù)據(jù)存儲(chǔ)的絕對(duì)值比較???數(shù)值小,理論術(shù)語(yǔ)上是為了使包含的信息能量變低;是為了到編碼階段,使編碼壓縮的數(shù)據(jù)量更小,從而壓縮效率更高。這就是預(yù)測(cè)的作用。
我們有了原圖,又有了特定的預(yù)測(cè)公式算法,就不需要再去存儲(chǔ)第二幅至相關(guān)第N幅的像素原值,只需要存儲(chǔ)它們的差值就行了。如果要解碼,把數(shù)據(jù)拿來(lái),利用公式還原后再加上差值,就可以把那些被預(yù)測(cè)的圖像的真面目恢復(fù)了。
在一幅圖內(nèi)做預(yù)測(cè),就叫幀內(nèi)預(yù)測(cè);對(duì)一系列組圖如一段扣籃動(dòng)作的視頻做運(yùn)動(dòng)軌跡預(yù)測(cè),屬于幀間預(yù)測(cè)。
拿來(lái)做基準(zhǔn)參考的幀,叫I幀,是關(guān)鍵幀,它的信息量最大,只能做幀內(nèi)壓縮,通常壓縮率很低;而那些后續(xù)通過(guò)參考I幀的信息做預(yù)測(cè)獲取差值的圖像,存儲(chǔ)的根本不是原像素值,而是些原始圖像的殘差,叫預(yù)測(cè)幀。預(yù)測(cè)幀有時(shí)候會(huì)混合使用幀內(nèi)預(yù)測(cè)和幀間預(yù)測(cè),取決于該區(qū)塊對(duì)那種算法更適應(yīng)。
根據(jù)前一幅圖像來(lái)預(yù)測(cè)得到本幀圖像叫P幀;結(jié)合前面的圖像和后面的圖像進(jìn)行雙向預(yù)測(cè)計(jì)算得到的本幀圖像叫B幀?;谝环P(guān)鍵I幀圖像加上一系列相應(yīng)的預(yù)測(cè)圖像如B幀、P幀構(gòu)成的一組圖像叫GOP。

現(xiàn)在該明白別人常說(shuō)的I幀、B幀、P幀是什么意思了吧?I幀是圖像信息的關(guān)鍵;B幀或P幀才是主要被壓縮的地方。
思考:為了降低視頻的網(wǎng)絡(luò)傳輸延遲,在CDN上的HLS視頻數(shù)據(jù)分片是不是越細(xì)越好?
答案:不是。切片時(shí)要為每一個(gè)分片都提供至少一個(gè)I幀和一系列P幀、B幀。分得太細(xì),I幀數(shù)量反而會(huì)變多。I幀太多,就意味著壓縮率變低,網(wǎng)絡(luò)傳輸量不降反升。
變換
事情還遠(yuǎn)沒(méi)結(jié)束。雖然通過(guò)預(yù)測(cè)公式降低了眾多像素存儲(chǔ)的編碼信息量,但這還不是壓縮。于是引入了各種變換,如離散余弦變換DCT、小波變換等等。學(xué)術(shù)上,其目的是將圖像進(jìn)行從空域到頻域的變化,通過(guò)這些所謂的變換濾掉高頻信息,因?yàn)槿搜蹖?duì)高頻信息不敏感,濾掉一些也無(wú)所謂。經(jīng)典的DCT公式長(zhǎng)這樣:

是不是又懵了?好吧,翻譯一下 ,看下面這個(gè)圖。變換公式就如同是水果分揀機(jī)器,根據(jù)某種特點(diǎn)如按體積大小對(duì)水果進(jìn)行歸類,把個(gè)頭大的放一堆,個(gè)頭小的放一堆。經(jīng)過(guò)變換,實(shí)現(xiàn)了物以類聚,后續(xù)如果再有需求就可以很容易地進(jìn)行封箱打包的操作了。
對(duì)圖像的變換改變了原來(lái)像素信息的空間順序,取而代之的是依據(jù)頻率和幅度的存儲(chǔ)方式。但此時(shí)的變換,只是改變了隊(duì)形,沒(méi)有任何實(shí)際的壓縮動(dòng)作。
拿一個(gè)8×8的圖像塊舉例,原始圖像塊的像素值如下:

經(jīng)DCT變換的結(jié)果如下圖。

能看出點(diǎn)什么特征嗎?如果還不能,提醒一下:矩陣左上角的數(shù)值較大,而右下角的數(shù)值較小,且趨近于零值。這就是傳說(shuō)中的頻率劃分。經(jīng)過(guò)DCT變化,低頻的、幅值高的、重要的信息都被歸置在左上部;而人類不敏感的、高頻的、卻又低振幅的數(shù)據(jù)都放在了右下側(cè)。
這又有什么好處呢?在接下來(lái)的量化步驟,就可以對(duì)右下側(cè)的數(shù)據(jù)開(kāi)刀了。因此可以簡(jiǎn)單理解,不管是什么A變換還是B變換,不要被它的公式和名稱嚇倒,它只是為了改變隊(duì)形,為后續(xù)的編碼和壓縮做準(zhǔn)備。
量化
到現(xiàn)在為止,仍然沒(méi)有進(jìn)行實(shí)質(zhì)性的壓縮。萬(wàn)事俱備,只欠量化。它是壓縮前的最后一道工序。量化就好比對(duì)剛才站好隊(duì)的隊(duì)員的身高進(jìn)行分級(jí)打分,通過(guò)一個(gè)基準(zhǔn)步長(zhǎng)來(lái)計(jì)算出每個(gè)值的相對(duì)數(shù)值。又懵了吧? 如下圖:量化前左上角的值為236,步長(zhǎng)為8,則量化后它值為236/8 = 30;量化前第二行首元素的值為-22,則量化后為-22/ 8 = -3。

這樣一來(lái),經(jīng)過(guò)量化分級(jí),數(shù)據(jù)開(kāi)始變得簡(jiǎn)潔明了,但精度也有損失了,損失的大小由量化的步長(zhǎng)決定。圖像的失真就是由量化引起的。
回顧,經(jīng)過(guò)上面的DCT變換后以后,數(shù)據(jù)隊(duì)形已準(zhǔn)備好;再經(jīng)過(guò)量化,把很多高頻的右下角的數(shù)值變?yōu)?。對(duì)數(shù)值進(jìn)行Z字形掃描,就變成一串?dāng)?shù)字了 。

針對(duì)上面的變換后的值的量化結(jié)果為:
30, 0, -3, -1, -2, -2, -1, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
為什么要進(jìn)行Z字形掃描,因?yàn)榭梢愿奖愕匕? 都聚在一起;為什么0 都會(huì)排在右下角?因?yàn)榻?jīng)過(guò)了DCT變換改變了隊(duì)形。 為什么把0聚在一起?為了編碼壓縮??!
熵編碼
壓縮的第一道工序叫行程編碼。什么是行程編碼?忘掉這個(gè)名詞,就是把連續(xù)重復(fù)的數(shù)據(jù)的用重復(fù)的次數(shù)值來(lái)表示??蠢?,一個(gè)原始串:
aaaaaaabbbbccccdddeeddaa
對(duì)這個(gè)原始串進(jìn)行行程編碼后,把重復(fù)的字母用一個(gè)重復(fù)的數(shù)字來(lái)代替,變成了這樣:
7a4b4c3d2e2d2a
這就是行程編碼的思想。行程編碼思想雖然簡(jiǎn)單但用處很大,在PNG,GZIP等各種壓縮算法里都有它的影子。
這還不算完,只是壓縮的一小步,第二步就是要對(duì)行程編碼后的數(shù)據(jù)進(jìn)行變長(zhǎng)編碼,如Huffman編碼,這才是壓縮的重頭戲。Huffman編碼主要思路是將出現(xiàn)頻率最高的字符串用最短的碼來(lái)替換,從整體上減少了原始數(shù)據(jù)的長(zhǎng)度。網(wǎng)上的討論極多,這里不再詳述,感興趣的也可見(jiàn)我的文章《圖解DEFLATE編解碼》。

編解碼總結(jié)
再梳理一下視頻編碼的核心步驟:
? 先做幀內(nèi)預(yù)測(cè)和幀間預(yù)測(cè),根據(jù)關(guān)鍵幀來(lái)獲取每幅圖像的差值,從而減少存儲(chǔ)的編碼信息量;
? 對(duì)其進(jìn)行變換,完成隊(duì)形調(diào)整;
? 對(duì)數(shù)據(jù)進(jìn)行有損量化,將不重要的數(shù)據(jù)歸零;
? 對(duì)量化數(shù)據(jù)進(jìn)行特定方向的掃描,將二維數(shù)據(jù)轉(zhuǎn)為一維數(shù)據(jù);
? 最后進(jìn)行壓縮,即先進(jìn)行行程編碼,再使用壓縮編碼。
解碼的步驟只是反其道而行之。
絕大部分的視頻編解碼標(biāo)準(zhǔn)都無(wú)一例外地包含這些目標(biāo)。當(dāng)然有些標(biāo)準(zhǔn)還考慮了環(huán)路濾波,但它不是必選項(xiàng),這里不做解釋。
編解碼的標(biāo)準(zhǔn)
各大標(biāo)準(zhǔn)之間有什么區(qū)別?有了上面的基礎(chǔ)理解后,就比較好解釋了。不同的標(biāo)準(zhǔn),有的只用了變換,有的用了預(yù)測(cè)加變換的混合編碼;或者幀內(nèi)預(yù)測(cè)算法不一樣,預(yù)測(cè)方向不一樣,有的支持4個(gè)方向,有的支持8個(gè)方向;或者變換的算法不一樣,如有的是DCT變換,有的是小波變換;或者熵編碼算法也不一樣,有的是Huffman編碼,有的是算術(shù)編碼;等等等等……
具體一點(diǎn)如H.263及之前的編碼標(biāo)準(zhǔn),會(huì)對(duì)幀內(nèi)編碼塊直接進(jìn)行變換,到了H.264,它提供了基于9種方向的幀內(nèi)預(yù)測(cè);再如到了HEVC / H.265, 采用了基于四叉樹(shù)的分塊方式;對(duì)于幀間預(yù)測(cè)提供了8種預(yù)測(cè)單元的劃分類型,除了支持離散余弦變換DCT,還首次使用了離散正弦變換DST,更有效地實(shí)現(xiàn)了對(duì)殘差矩陣的變換。
越是最近新出的編碼標(biāo)準(zhǔn),算法越先進(jìn),也越復(fù)雜。
最后
以上就是視頻編解碼的基本原理,希望讀了以后能大體明白視頻編解碼原理的基本思路。但如果真想對(duì)視頻編解碼的標(biāo)準(zhǔn)和算法細(xì)節(jié)做深入了解,那就真得要下苦功夫了。文中每個(gè)主題,都可以寫(xiě)出幾本書(shū)來(lái)。請(qǐng)有理想有毅力的同學(xué)繼續(xù)前行,祝一切順利!
編輯:hfy
-
視頻編解碼
+關(guān)注
關(guān)注
2文章
54瀏覽量
12087
發(fā)布評(píng)論請(qǐng)先 登錄
請(qǐng)問(wèn)如何構(gòu)建和運(yùn)行視頻編解碼器示例應(yīng)用程序?
TLV320AIC1x系列單聲道編解碼器:特性、應(yīng)用與設(shè)計(jì)要點(diǎn)
TLV320AIC26:高性能低功耗音頻編解碼器的詳細(xì)解析
深入解析LM4546B AC '97多通道音頻編解碼器
瑞芯微RK3562平臺(tái)FFmpeg硬件編解碼移植及性能測(cè)試實(shí)戰(zhàn)攻略
音視頻編解碼封裝解封裝部件介紹
瑞芯微RK3588平臺(tái)FFmpeg硬件編解碼移植及性能測(cè)試實(shí)戰(zhàn)攻略
新唐科技推出低延遲音頻編解碼器NAU88L21C
瑞芯微RK3576平臺(tái)FFmpeg硬件編解碼移植及性能測(cè)試實(shí)戰(zhàn)攻略 觸覺(jué)智能RK3576開(kāi)發(fā)板演示
增強(qiáng)T-BOX設(shè)計(jì),新唐編解碼器的重要作用
基于RK3576的BASE64編解碼
5ms低延遲 視頻編解碼模塊迎來(lái)關(guān)鍵突破
新一代視頻編解碼標(biāo)準(zhǔn)H.266走向主流 頭部視頻平臺(tái)滲透率超70%
為什么要編碼?視頻編解碼原理及詳細(xì)步驟
評(píng)論