圖像編碼與 H264 基礎(chǔ)知識
RGB 顏色模型
圖像的采集可以通過攝像頭或者截取屏幕來獲取的圖像數(shù)據(jù)。一幅圖像可以看作為一個(gè)二維的矩陣,其中矩陣中的每一個(gè)點(diǎn)被稱為像素。像素的顏色可以通過紅、綠、藍(lán)來表示,也就是常說的 3 基色。如下圖所示:

每個(gè)像素可以用不同的數(shù)據(jù)位數(shù)來表示,常用的量化位數(shù)有 16 位、24 位、32 位等。
24 位最好理解,就是 RGB 的各個(gè)分量各占 8 位,取值范圍為 0 ~ 255;
32 位則是 24 位的基礎(chǔ)上增加了透明度的量化位數(shù),也是 8 位,用來表示當(dāng)前像素的透明度,根據(jù)透明的位置可以分為 RGBA 和 ARGB;
16 位可以分為 565 和 555 兩種模式,565 則表示綠色分量占 6 位,紅色和藍(lán)色各占 5 位,555 模式則丟棄一位不用,RGB 各個(gè)分量占 5 位。量化位數(shù)越多,所能表示顏色的層次也越多,顏色則越豐富。
在表示圖像的二維的矩陣中,寬和高兩個(gè)維度中像素的數(shù)量稱為分辨率,通常用 寬 x 高 來表示,例如下面分辨率為 4 x 4 的圖像。

圖像還有另一個(gè)屬性就是寬高比,例如常見的 16:9、4:3、21:9 等,這里通常指顯示寬高比(DAR),同樣像素也有不同的寬高比,稱之為像素長寬比(PAR)。


YUV 顏色模型與冗余刪除
一張 1280x720 分辨率的圖片,如果使用 RGB 顏色模型存儲話,24 位量化位數(shù)的情況下需要 1280 720 3(24bit) = 2.6M 空間來存儲一張圖片,如果是 32 位則需要 1280 720 4(24bit) = 3.5M 存儲空間,而我們的眼睛對于亮度相比于顏色更敏感,例如一下圖片:

區(qū)域 A 與區(qū)域 B,是相同的顏色,第一張很難區(qū)分出來,這跟我們?nèi)搜鄣臉?gòu)造相關(guān),人眼更加注意光線明亮度。
所以針對這一特點(diǎn)存在另一種顏色模型 YUV 顏色模型,YUV 顏色模型中,其中的 Y 分量表示的是明亮度(Luminance、Luma), U、V 表示的是色度 (Chrominance/Chroma),如下圖:

該模型下可以采用不同的量化位數(shù)來表示亮度以及色度,所以存在不同到模式:4:4:4、4:2:2、4:1:1、4:2:0、4:1:0 和 3:1:1 六種不同的模式。
在使用 4:2:0 模式時(shí),同樣的圖片相比 RGB 模式,所用的內(nèi)存減少一半。RGB 可以和 YUV(YCbCr)進(jìn)行轉(zhuǎn)換,公式如下:
#?第一步計(jì)算亮度
Y?=?0.299R?+?0.587G?+?0.114B
#?一旦有了亮度,可以分割顏色(色度藍(lán)色和紅色):
Cb?=?0.564(B?-?Y)
Cr?=?0.713(R?-?Y)
#?也可以通過使用?YCbCr?進(jìn)行轉(zhuǎn)換,甚至獲得?RGB
R?=?Y?+?1.402Cr
B?=?Y?+?1.772Cb
G?=?Y?-?0.344Cb?-?0.714Cr
采樣率、碼率、幀以及場的概念
圖像則是對模擬信號進(jìn)行采樣量化后獲得,而視頻則是由一系列的圖像組成,采集時(shí)圖像的分辨率及量化位數(shù)越高,所能表達(dá)的信息越多,畫面則越清晰。
視頻存在一個(gè)采樣頻率的屬性,即單位時(shí)間內(nèi)采樣的次數(shù)。視頻的采樣頻率也受人眼的限制,通常在每秒 20 ~ 30 幀之間。
當(dāng)采樣頻率在每秒 10~20 幀時(shí),對于快速運(yùn)動的圖像,人眼可以感覺到不流暢,而采樣頻率提高到 20~30 幀時(shí),人眼看起來比較流暢了。
如果將采樣頻率在提高,人眼是很難感覺這種差異的,這也是目前電影拍攝時(shí)使用 24 幀或者 30 幀采樣頻率的原因。
顯示視頻所需要的每秒位數(shù)稱作為比特率,也叫碼率。
計(jì)算公式為 比特率=寬 高 位深度 每秒幀數(shù) 例如,如果我們不采用任何類型的壓縮,每秒 30 幀,每像素 24 位,480x240 分辨率的視頻將需要 82,944,000 位/秒 或 82.944 Mbps(30x480x240x24)。
當(dāng)比特率幾乎恒定時(shí),稱為恒定比特率(CBR),但它也可以變化,然后稱為可變比特率(VBR)。
下圖顯示了一個(gè)受限的 VBR,在幀為黑色時(shí)不會花太多位。

視頻采樣中通過逐行掃描得到一幅完整的圖像稱之為一幀,通常幀頻率為 25 幀(PAL 制)、30 幀每秒(NTSC 制),而通過隔行掃描(奇、偶數(shù)行),那么一幀圖像就被分成兩場,通常場頻為 50Hz(PAL 制)、60Hz(NTSC 制)。
這是在早期,工程師們提出的一種技術(shù),能夠在不消耗額外的帶寬的情況下,使得顯示器的感知幀率倍增。這種技術(shù)稱為隔行視頻;它基本上在 1 幀中發(fā)送一半的屏幕,而在下一幀中發(fā)送另一半。

今天視頻的顯示主要使用逐行掃描技術(shù)。逐行是顯示、存儲或發(fā)送運(yùn)動圖像的方法,其中每幀的所有行被依次繪制。
H264 編碼
當(dāng)需要存儲視頻或者網(wǎng)絡(luò)傳輸時(shí),無論是使用 RGB 還是 YUV 格式,所需要的碼率和存儲空間都是非常大的,例如一個(gè)分辨率為 1280 x 720 ,24 位量化位數(shù),采樣頻率為每秒 30 幀,一個(gè)小時(shí)的視頻則需要 1280 x 720 x 3 x 30 x 60 x 60 = 278G 的空間來存儲該視頻。
而在顯示或網(wǎng)絡(luò)傳輸該視頻時(shí)所需要的碼率為 1280 x 720 x 24 x 30 = 632Mbps,這么大數(shù)據(jù)量很難實(shí)際應(yīng)用,因?yàn)榫W(wǎng)絡(luò)帶寬和硬盤存儲空間都是非常有限的。
針對以上問題則需要對視頻進(jìn)行編碼壓縮,而 H264 是其中一種編解碼標(biāo)準(zhǔn);
H264 由視頻編解碼器 H.261 發(fā)展而來的,它誕生于 1990 年(技術(shù)上為 1988 年),其設(shè)計(jì)工作的數(shù)據(jù)速率為 64 kbit / s。它已經(jīng)使用了色度子采樣,宏塊等方面的想法。在 1995 年,H.263 視頻編解碼器標(biāo)準(zhǔn)被公布,并持續(xù)延續(xù)至 2001 年。
2003 年,第一版 H.264/AVC 完成。同一年,一家名為 TrueMotion 的公司將其視頻編解碼器作為免版稅的有損視頻壓縮稱為 VP3。2008 年,Google 收購了該公司,同年發(fā)布了 VP8。2012 年 12 月,Google 發(fā)布了 VP9, 大約有 3/4 的瀏覽器市場(包括手機(jī))支持。
AV1 是一種新的視頻編解碼器,免版稅并且開放源代碼,由 AOMedia 聯(lián)盟設(shè)計(jì),該組織包括:谷歌,Mozilla,微軟,亞馬遜,Netflix,AMD,ARM,NVIDIA,英特爾,思科等等,編解碼器的第一個(gè)版本 0.1.0 于 2016 年 4 月 7 日發(fā)布。

H264 編解碼方法
去除數(shù)據(jù)統(tǒng)計(jì)冗余:H264 采用兩種熵編碼方式:CAVLC ( 基于上下文的可變字長編碼)和 CABAC(基于上下文的二進(jìn)制算數(shù)編碼),CAVLC 實(shí)現(xiàn)相對簡單,編碼效率高,但壓縮率要比 CABAC 低 15% 左右,CABAC 復(fù)雜度高,可以分場景采用不同的熵編碼,讓視頻壓縮后的平均碼長接近信源熵值。
去除空間冗余:去除空間冗余則僅考慮本幀的數(shù)據(jù)而不考慮相鄰幀之間的冗余信息,這實(shí)際上與靜態(tài)圖像壓縮類似。幀內(nèi)一般采用有損壓縮算法,由于幀內(nèi)壓縮是編碼一個(gè)完整的圖像,所以可以獨(dú)立的解碼、顯示。幀內(nèi)壓縮一般達(dá)不到很高的壓縮,跟編碼 jpeg 差不多。
除此以外,H264 采用變換編碼的方式,將殘差從空間域利用 DCT(離散余弦變換)變換到頻率域,結(jié)合差異量化編碼方式,更進(jìn)一步的去除空間冗余。
去除時(shí)間冗余:相鄰幾幀的數(shù)據(jù)有很大的相關(guān)性,或者說前后兩幀信息變化很小的特點(diǎn)。也即連續(xù)的視頻其相鄰幀之間具有冗余信息,根據(jù)這一特性,壓縮相鄰幀之間的冗余量就可以進(jìn)一步提高壓縮量,減小壓縮比。幀間壓縮也稱為時(shí)間壓縮(Temporal compression),它通過比較時(shí)間軸上不同幀之間的數(shù)據(jù)進(jìn)行壓縮。
幀間壓縮一般是無損的。幀差值(Frame differencing)算法是一種典型的時(shí)間壓縮法,它通過比較本幀與相鄰幀之間的差異,僅記錄本幀與其相鄰幀的差值,這樣可以大大減少數(shù)據(jù)量。
去除人眼視覺冗余:H264 編碼器的輸入圖像或視頻的色彩空間采樣格式一般為 YUV420,不同于 RGB 采樣,YUV420 利用人眼視覺對像素亮度分量更敏感,而色度分量沒那么敏感,進(jìn)一步將圖像或視頻的色度分量做 2:1 的采樣,4 個(gè)亮度分量,2 個(gè)色度分量。
另外,H264 采用量化編碼的有損編碼方式,也正是利用了人眼視覺對高頻細(xì)節(jié)部分不敏感的理論基礎(chǔ),將殘差系數(shù)低頻部分采用更細(xì)的量化參數(shù),而高頻部分則粗化量化,一般的視頻壓縮失真也正是這個(gè)階段產(chǎn)生。
除了以上是 H264 所使用的技術(shù),還使用了以下方法:
幀分組(GOP):在 H264 中圖像以序列為單位進(jìn)行組織,一個(gè)序列是一段圖像編碼后的數(shù)據(jù)流,以 I 幀開始,到下一個(gè) I 幀結(jié)束。當(dāng)運(yùn)動變化比較少時(shí),一個(gè)序列可以很長,因?yàn)檫\(yùn)動變化少就代表圖像畫面的內(nèi)容變動很小,所以就可以編一個(gè) I 幀,然后一直 P 幀、B 幀了,可以有效的降低碼率。
當(dāng)運(yùn)動變化多時(shí),一個(gè)序列就需要設(shè)置的比較小,比如就包含一個(gè) I 幀 和 3、4 個(gè) P 幀,這樣可以控制 P 幀和 B 幀的大小。
幀類型的定義:將每組內(nèi)各幀圖像定義為三種類型,即 I 幀(IDR)、B 幀和 P 幀;I 幀是幀內(nèi)編碼幀,I 幀表示關(guān)鍵幀,可以理解為這一幀畫面的完整保留, I 幀特點(diǎn):
它是一個(gè)全幀壓縮編碼幀。它將全幀圖像信息進(jìn)行 JPEG 壓縮編碼及傳輸; 解碼時(shí)僅用 I 幀的數(shù)據(jù)就可重構(gòu)完整圖像; I 幀描述了圖像背景和運(yùn)動主體的詳情; I 幀不需要參考其他畫面而生成; I 幀是 P 幀和 B 幀的參考幀,其質(zhì)量直接影響到同組中以后各幀的質(zhì)量; I 幀是幀組 GOP 的基礎(chǔ)幀(第一幀),在一組中只有一個(gè) I 幀; I 幀不需要考慮運(yùn)動矢量; I 幀所占數(shù)據(jù)的信息量比較大。
P 幀是前向預(yù)測編碼幀。P 幀表示的是這一幀跟之前的一個(gè)關(guān)鍵幀(或 P 幀)的差別,解碼時(shí)需要用之前緩存的畫面疊加上本幀定義的差別,生成最終畫面。P 幀是以 I 幀或 P 幀為參考幀,在參考幀中找出 P 幀的差異 P 幀特點(diǎn):
P 幀采用運(yùn)動補(bǔ)償?shù)姆椒▊魉退c前面的 I 或 P 幀的差值及運(yùn)動矢量(預(yù)測誤差); 解碼時(shí)必須將 I 幀中的預(yù)測值與預(yù)測誤差求和后才能重構(gòu)完整的 P 幀圖像; P 幀屬于前向預(yù)測的幀間編碼,它只參考前面最靠近它的 I 幀 或 P 幀; P 幀可以是其后面 P 幀的參考幀,也可以是其前后的 B 幀 的參考幀; 由于 P 幀是參考幀,它可能造成解碼錯(cuò)誤的擴(kuò)散; 由于是差值傳送,P 幀的壓縮比較高。
B 幀是雙向預(yù)測內(nèi)插編碼幀。B 幀是雙向差別幀,也就是 B 幀記錄的是本幀與前后幀的差別,換言之,要解碼 B 幀不僅要取得之前的緩存畫面,還要解碼之后的畫面,通過前后畫面的與本幀數(shù)據(jù)的疊加取得最終的畫面。B 幀以前面的 I 或 P 幀 和后面的 P 幀為參考幀,B 幀特點(diǎn):
B 幀是由前面的 I 或 P 幀和后面的 P 幀來進(jìn)行預(yù)測的; B 幀傳送的是它與前面的 I 或 P 幀和后面的 P 幀之間的預(yù)測誤差及運(yùn)動矢量; B 幀是雙向預(yù)測編碼幀; B 幀壓縮比最高,因?yàn)樗环从潮麉⒖紟g運(yùn)動主體的變化情況,預(yù)測比較準(zhǔn)確; B 幀不是參考幀,不會造成解碼錯(cuò)誤的擴(kuò)散。
I、P、B 各幀是根據(jù)壓縮算法的需要,是人為定義的,它們都是實(shí)實(shí)在在的物理幀。 一般來說,I 幀的壓縮率是 7(跟 JPG 差不多),P 幀是 20,B 幀可以達(dá)到 50。 B 幀的使用會導(dǎo)致解碼的延時(shí),因?yàn)樾枰獏⒖记昂髱?,同時(shí)也會增加 CPU 負(fù)擔(dān)。 P 幀和 B 幀不會越過 I 幀(IDR 圖像)去參考其他幀。
H264 的編碼參數(shù)
H264 的編碼的實(shí)現(xiàn)存在很多的控制參數(shù),不同的編碼器實(shí)現(xiàn)可能有一些特殊的參數(shù)可供設(shè)置,不同的控制參數(shù)得到不同的輸出結(jié)果,以便適應(yīng)不同的應(yīng)用場景,這里介紹一些通用的參數(shù),后續(xù)在介紹一些具體編碼器以及應(yīng)用時(shí),在對一些參數(shù)進(jìn)行詳細(xì)的說明。
H.264 Profiles:Profile 用于確定編碼過程中幀
間壓縮使用的算法,常見的 H264 編碼 Profile 有如下 3 種:
1、Baseline Profile (BP):只支持 I/P 幀,無交錯(cuò)(Progressive)和 CAVLC,主要用于計(jì)算能力有限的應(yīng)用環(huán)境,一般用于低階或需要額外容錯(cuò)的應(yīng)用,比如視頻通話、手機(jī)視頻等;優(yōu)勢:編解碼開銷較小,速度快,適用于視頻會議等延時(shí)敏感的場景或者解碼能力不夠的環(huán)境。不足:同等碼率下,Baseline 的畫質(zhì)最差。
2、Main Profile (MP):支持 I/P/B 幀,無交錯(cuò)(Progressive)和交錯(cuò)(Interlaced),同時(shí)提供對于 CAVLC 和 CABAC 的支持,用于主流消費(fèi)類電子產(chǎn)品規(guī)格如低解碼(相對而言)的 MP4、便攜的視頻播放器;
優(yōu)勢:CABAC 的支持和 B 幀的引入,相同碼率下畫質(zhì)相對 Baseline 有 15% 的提升。不足:運(yùn)算量上和畫質(zhì)相對于 HiP 沒有太大優(yōu)勢,絕大部份情況下已經(jīng)被 HiP 取代。
3、High Profile (HiP):在 Main 的基礎(chǔ)上增加了 8x8 內(nèi)部預(yù)測、自定義量化、無損視頻編碼和更多的 YUV 格式(如 4:4:4)用于廣播,高清電視及視頻碟片存儲(HiP 被采納為 HD DVD 和藍(lán)光的編碼標(biāo)準(zhǔn))。
優(yōu)勢:8x8 內(nèi)部預(yù)測的引入使得 HiP 能夠較好的編碼快速移動的場景、支持碼流之間有效的切換(SP 和 SI 片)、改進(jìn)誤碼性能。
CAVLC 和 CABAC 是兩種不同的熵編碼(一種無損,變長編碼數(shù)據(jù)壓縮方案)形式,CAVLC 效率高壓縮比低,CABAC 反之。
除此之外還存一下類別:
High 10 Profile (Hi10P):超越目前主流的消費(fèi)型產(chǎn)品能力,此 profile 建立在 High Profile 之上,多了支援 10 bit 的精度,色彩更精準(zhǔn)。以影片壓制而言,將 High Profile (8 bit) 影片重新編碼輸出為 H.264 High 10 Profile ,雖然色彩精度不會變,但至少壓縮率比輸出 High Profile (8 bit) 還要高。
High 4:2:2 Profile (Hi422P):針對專業(yè)領(lǐng)域應(yīng)用,此 profile 建立在 High 10 Profile 之上,多了支援 4:2:2 色彩取樣,位元深度達(dá) 10 bit。
High 4:4:4 Predictive Profile (Hi444PP):此 profile 建立在 High 4:2:2 Profile 之上,多了支援 4:4:4 色彩取樣,位元深度達(dá) 14 bit,并且支援高效率無損重新編碼,且每張畫面編碼為三個(gè)獨(dú)立的色彩平面。
H.264 Level:Level 是對視頻本身特性的一些描述(碼率,分辨率,fps 等),Level 越高,視頻的碼率、分辨率、fps 越高。Level 也表示了對播放設(shè)備的解碼性能要求,值越高,代表播放設(shè)備解碼性能要求越高,相對的輸出影片的壓縮率也越越高。
關(guān)于 Profile 和 Level 更詳細(xì)資料可參考 WiKi 百科的 H.264/MPEG-4 AVC 資料。
地址:https://en.wikipedia.org/wiki/Advanced_Video_Coding
GOP 長度:一個(gè) key frame (IDR) 到下一個(gè) key frame 的范圍。表示關(guān)鍵幀的間隔,一個(gè)序列的第一個(gè)圖像叫做 IDR 圖像(立即刷新圖像),IDR 圖像都是 I 幀 圖像。當(dāng)解碼器解碼到 IDR 圖像時(shí),立即將參考幀隊(duì)列清空,將已解碼的數(shù)據(jù)全部輸出或拋棄,重新查找參數(shù)集,開始一個(gè)新的序列。這樣,如果前一個(gè)序列出現(xiàn)重大錯(cuò)誤,在這里可以獲得重新同步的機(jī)會。IDR 圖像之后的圖像永遠(yuǎn)不會使用 IDR 之前的圖像的數(shù)據(jù)來解碼。
Constant Quantizer (QP):恒定量化值(Constant Quantizer)可以用來控制圖像編碼的品質(zhì)。編碼器中一般可以這是最大值和最小值。比較低的數(shù)值會得到比較高的品質(zhì)。
Maximun B-frame:當(dāng)設(shè)定 B 幀時(shí),重復(fù)部分比較多/變化較少的 Frames 會被編碼為 B 幀此值限制 B 幀的最大連續(xù)數(shù)量。
Reference frame (ref):設(shè)定一個(gè) P 幀所能參考的幀的數(shù)量,ref 會影響播放相容性。
碼率控制(Bitrate Control):CBR(恒定碼率)、VBR(動態(tài)碼率);碼率控制實(shí)際上是一種編碼的優(yōu)化算法,它用于實(shí)現(xiàn)對視頻流碼流大小的控制。
目的在于同樣的視頻編碼格式,碼流大,它包含的信息也就越多,那么對應(yīng)的圖像也就越清晰,反之亦然。
VBR 碼流控制方式可以降低圖像動態(tài)畫面少時(shí)候的帶寬占用,CBR 控制方式碼流穩(wěn)定,圖像狀態(tài)較穩(wěn)定。他們?yōu)榱私鉀Q的是不同需求下的不同應(yīng)用。
來源:http://www.enkichen.com/2017/11/26/image-h264-encode/
?

技術(shù)交流,歡迎加我微信:ezglumes ,拉你入技術(shù)交流群。
私信領(lǐng)取相關(guān)資料
推薦閱讀:
音視頻開發(fā)工作經(jīng)驗(yàn)分享 || 視頻版
開通專輯 | 細(xì)數(shù)那些年寫過的技術(shù)文章專輯
NDK 學(xué)習(xí)進(jìn)階免費(fèi)視頻來了
推薦幾個(gè)堪稱教科書級別的 Android 音視頻入門項(xiàng)目
覺得不錯(cuò),點(diǎn)個(gè)在看唄~

