干貨 | H.265編碼SAO算法優(yōu)化

作者:姜生剃斧,PP云高級技術經(jīng)理鉴象,10余年視頻編解碼算法設計優(yōu)化慕的,流媒體應用等領域開發(fā)經(jīng)驗叠殷。

一 SAO 技術介紹

  SAO 的全稱是 Sample adaptiveoffset堕伪,對應的中文意思是采樣自適應補償揖庄。SAO 是H.265編碼規(guī)范中一項重要的壓縮技術,該技術的思想源于Samsung提案JCTVC-A124欠雌。實驗測試結果顯示 SAO 能夠帶來的壓縮增益遠超過Deblock和ALF蹄梢。

SAO 模塊在編碼器的結構圖一中所處的位置如下(紅色的部分):

  圖一 SAO在編碼器中的位置

SAO 在解碼器的結構圖二中所處的位置如下(紅色的部分):

  圖二 SAO在解碼器中的位置

  從流程圖中可以看出,SAO和ALF是loop內(nèi)的操作富俄,接在Deblock的后面禁炒,輸入包括原始的YUV圖像和Deblock的輸出,生成的參數(shù)需要進行entropy編碼霍比。參考圖三:

  圖三 SAO 的算法概圖

二 SAO 算法介紹

  圖像經(jīng)過壓縮和解壓后幕袱,精度會損失。通過psnr計算公式可以看出悠瞬,重構數(shù)據(jù)和原始數(shù)據(jù)YUV之間差值的平方和決定了psnr们豌。SAO 通過分析原始數(shù)據(jù)和重構后的數(shù)據(jù)涯捻,對deblock之后的進行offset補償操作,使得盡量接近原始的像素值望迎,達到提高psnr 的目的障癌。

  均方誤差:

  峰值信噪比:

  如何具體運算來提高PSNR值呢,一個直接的想法是把deblock的重構數(shù)據(jù)和原始的YUV 中每一個相同位置的pixel做差值擂煞,把這個差值傳給decoder混弥,這樣可以完全恢復YUV。實際上对省,這樣做會導致碼率非常高蝗拿,達不到壓縮的效果。

  為了能夠提高psnr蒿涎,同時只會增加極少量的碼率哀托,H.265 在碼率和psnr之間做了一個tradeoff。下面看一下是怎么做的劳秋。

  H.265是基于CTB來做SAO的仓手,通過分析原始數(shù)據(jù)和deblock后的重構數(shù)據(jù),將pixel 分成三種SAO模式:

  SaoTypeIdx[cIdx][rx][ry]

  SAO type

  Not applied

  1

  Band Offset(BO)

  2

  Edge Offset(EO)

由上表可以看出玻淑,SAO 有三種模式:不做嗽冒,BandOffset, Edge Offset, 后面兩種模式分別介紹如下:

EdgeOffset Mode:(邊界補償模式)

  在這種模式下补履,SAO 需要為CTB 選擇一種梯度模式添坊,水平/垂直/45度角/135度角。這四個類別用sao_eo_class 語法元素表示箫锤,如圖四:

  圖四 edgeoffset 梯度四種模式

  為當前的CTB選擇好一種梯度模式后贬蛙,開始計算該CTB中每一個像素和相鄰兩個像素的大小關系,這個大小關系分成5類:

  EdgeIdx

  Condition

  Meaning

  P = n0 and p = n1

  Flat area

  1

  P < n0 and p < n1

  Local min

  2

  P < n0 and p = n1 or P = n0 and p < n1

  Edge

  3

  P > n0 and p = n1 or P = n0 and p > n1

  Edge

  4

  P > n0 and p > n1

  Local max

  圖五 EdgeIdx 四種類型

  對CTB而言谚攒,EO(Edge Offset)的梯度模式在碼流里面被包含了阳准,但是對于每一個像素而言,EdgeIdx 是通過計算得來的馏臭,編碼器和解碼器所使用的計算方法一樣野蝇,所以得到的結果一樣,碼流里面不需要編碼EdgeIdx信息括儒,這樣節(jié)省了碼率浪耘,付出的代價是增加了CPU 的運算量。

對于EdgeIdx 為0的flat area塑崖,可以不需要做任何操作。對于其余四類痛倚,SAO為每一類分配了一個Offset 整數(shù)補償值规婆,這個Offset會add到被重構的每一對應類像素中。同時H.265規(guī)定,EdgeIdx=1抒蚜,2 這兩類掘鄙,offset 值必須為正數(shù),EdgeIdx=3嗡髓,4必須為負數(shù)操漠,這樣符號位不需要編碼,節(jié)省碼率饿这。

Band Offset Mode:

  YUV 像素值的取值范圍通常是 0~255浊伙,平均分成32個band,每一個band包含的橫跨的范圍是8.通過一定的算法來選擇連續(xù)的4個band進行補償长捧,當CTB的YUV 像素值處于選定的4個band中時嚣鄙,需要對這個sample補償。

  圖六 BandOffset 補償模式

Band Offset 的原理是:在編碼器端串结,對32個band分別做像素值的直方圖統(tǒng)計哑子,求每一個band像素值的平均值。下面是一個例子:

假設對于原始的CTB肌割,其中有一個band卧蜓,位于[28,35], 有三個pixel,像素值分別是:32把敞,35弥奸, 35,這樣可以知道該band 的像素平均值是(32 + 35+35)/3 = 34; 而對應的deblock之后的band先巴,包含三個像素其爵,分別是30,32伸蚯,34摩渺,平均值是(30 + 32 + 34) / 3 = 32, 可見,在該band上剂邮,原始的像素值平均值比重構的大 34-32=2摇幻,因此,可以分配offset=+2給這個band挥萌,在decoder 端為這個band 的每一個像素值加2.這樣保證在該band上出現(xiàn)的重構pixel和原始的平均值相等绰姻。對32個都做這種處理,最后選擇連續(xù)的4個引瀑。

對于Band OffsetModeEdge Offset Mode而言狂芋,如果當前的CTB的SAO 參數(shù)與左邊或上邊CTB的SAO 參數(shù)相同,這時不需要為當前的CTB傳輸SAO參數(shù)憨栽,而是直接使用左邊或上邊CTB的SAO 參數(shù)帜矾。

三 SAO 算法的優(yōu)化

1. 優(yōu)化之前的常用算法:

  對于CTB 內(nèi)的每一個像素而言翼虫,需要計算:

  1. 先要計算出原始像素值和重構像素值的差值,每個像素的差值用變量offset_value 表示屡萤;

  2. 需要根據(jù)重構的像素值珍剑,分別計算每個像素BO,EO0, EO1, EO2, EO3 這五種類型內(nèi)的每一種子類型值,這個類型之命名為 sao_class死陆,這樣 64*64的CTB 方陣招拙,要遍歷5次,訪問次數(shù)大約為:5*64*64

  3. 然后對CTB的64*64的方陣措译,一共4096個像素統(tǒng)計每一個類型的offset_value之和别凤,以及每個類型像素個數(shù) cnt_of_class。

2. 優(yōu)化后的算法:

  該算法的特點是瞳遍,把每個像素的 offset_value 向左偏移 12位闻妓,一個32位的整數(shù),高20位放offset_value 值掠械,低12位放像素個數(shù). 對于每一個像素而言由缆,低12位初始化為1. 64*64 的CTB 塊,同一個SAO 的子類型猾蒂,最多只有 2^12 個像素均唉,所以用低12位保存子類型個數(shù)剛剛好不會溢出,如下圖:

  12 ~ 31 bit (offset_value)

  0 ~ 11 (cnt_of_class)

  圖七 復合數(shù)據(jù)格式

  這樣把offset_value 和 cnt_of_class 合并到一個 32 位整型數(shù)內(nèi)肚菠,可以讓兩個數(shù)據(jù)同時累加運行舔箭,運算量減少一半。

  假設 64*64的CTB 塊蚊逢,offset值定義為下面的數(shù)組:

Offset_value[64][64] = { … …} ; 其中的每個數(shù)據(jù)格式都是符合數(shù)據(jù)格式

Rec_pixel_value[64][64] = { … …} ; 重構像素值 0 ~ 255

BO_class[64][64] = { … …} ; 取值范圍 0 ~ 31

EO0_class[64][64] = { … …} ; 取值范圍 0 ~ 4

EO1_class[64][64] = { … …} ; 取值范圍 0 ~ 4

EO2_class[64][64] = { … …} ; 取值范圍 0 ~ 4

EO3_class[64][64] = { … …} ; 取值范圍 0 ~ 4

  定義一個數(shù)組:

Int BO_Class[32] = {0} ;

For(int i = 0; i < 64; i++)

For(intj = 0; j < 64; j++)

{

Int Rec_pixel_value[i][j] >> 3;

BO_Class[class]+= Offset_value[i][j];

}

  上面運算完成后层扶,可以從BO_Class中分離出每一個子類的:

For(int i = 0; i < 32; i++)

{

offset_value = BO_Class[i] >> 12;

cnt_of_ BO_Class[i] & 0xFFF;

}

  Edge Offset Mode:

  1. 把 EO0, EO1 和并到一個數(shù)組中:EO0, EO1 都包含了 5個子類 0 ~ 4, 需要3bit,為了把兩個子類合并起來烙荷,需要建立一個二維數(shù)組镜会,兩個下標分別代表兩個類型的子類索引。假設左邊的下標代表 EO1 的子類索引终抽,右邊的下標代表 EO0 的子類索引:

EO_01[8][8]

  2. 按照上面的方法把 EO2, EO3合并到一個數(shù)組中:

EO_23[8][8]

  3. 完成下面的運算:

{

Intclass_0 = EO0_class[i][j];

Int class_1 = EO1_class[i][j];

Int offset = Offset_value[i][j];

EO_01[class_1][class_0] += offset

EO_23[class_3][class_2] += offset;

  4. 分離出 EO0, EO1, EO2, EO3:

Int EO0[5] = {0};

Int EO1[5] = {0};

Int EO2[5] = {0};

Int EO3[5] = {0};

For(int i = 0; i < 5; i++)

For(int J =0; J < 5; J++)

EO0[j] += EO_01[i][j];

EO1[i]+= EO_01[i][j];

EO2[j]+= EO_23[i][j];

  最后把每一類的 offset 和 count 分離出來戳表。

四 總結

  優(yōu)化后,SAO 中 offset 統(tǒng)計部分的計算量減少到原來的 25%左右昼伴。整個 SAO 模塊 90%的運算時間被統(tǒng)計部分消耗掉匾旭,所以這個算法的優(yōu)化在C 層面比較明顯。在匯編層面圃郊,有一定效果价涝,但不太明顯,因為在運算的中間加了一個 8*8的數(shù)組持舆,這個數(shù)組不利于用多媒體指令集并行方式來實現(xiàn)飒泻。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鞭光,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子泞遗,更是在濱河造成了極大的恐慌,老刑警劉巖席覆,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件史辙,死亡現(xiàn)場離奇詭異,居然都是意外死亡佩伤,警方通過查閱死者的電腦和手機聊倔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來生巡,“玉大人耙蔑,你說我怎么就攤上這事」氯伲” “怎么了甸陌?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長盐股。 經(jīng)常有香客問我钱豁,道長,這世上最難降的妖魔是什么疯汁? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任牲尺,我火速辦了婚禮,結果婚禮上幌蚊,老公的妹妹穿的比我還像新娘谤碳。我一直安慰自己,他們只是感情好溢豆,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布蜒简。 她就那樣靜靜地躺著,像睡著了一般沫换。 火紅的嫁衣襯著肌膚如雪臭蚁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天讯赏,我揣著相機與錄音垮兑,去河邊找鬼。 笑死漱挎,一個胖子當著我的面吹牛系枪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播磕谅,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼私爷,長吁一口氣:“原來是場噩夢啊……” “哼雾棺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起衬浑,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤捌浩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后工秩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尸饺,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年助币,在試婚紗的時候發(fā)現(xiàn)自己被綠了浪听。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡眉菱,死狀恐怖迹栓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情俭缓,我是刑警寧澤克伊,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站尔崔,受9級特大地震影響答毫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜季春,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一洗搂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧载弄,春花似錦耘拇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至逞刷,卻和暖如春嘉涌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背夸浅。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工仑最, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人帆喇。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓警医,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子预皇,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結尾創(chuàng)建: 董瀟偉侈玄,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,718評論 0 9
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些閱讀 2,031評論 0 2
  • 方塊效應產(chǎn)生的原因:1.變換、量化 的誤差2.幀間預測的運動補償過程為了消除或減輕塊效應吟温,我們可以用環(huán)路濾波器(L...
    Persistently閱讀 3,324評論 0 0
  • 我算個渣渣級別的序仙,經(jīng)常不在線地忘記自己前面寫了什么,等想起來的時候溯街,想去睡覺诱桂,想去吃飯,一遍一遍地回不到主線呈昔,然后...
    蘇小牙_d5d9閱讀 206評論 0 0
  • 我和心雨結緣,首先要感謝我的同班同學楊振璽友绝。是他把我介紹給了校友會的學長們堤尾,讓我找到了組織,他是我的入會介...
    克驤閱讀 802評論 0 0