x265對語法元素cu qp delta

2021-08-17 03:18:48 字數 4790 閱讀 1860

hevc所使用的熵編碼方法為cabac(基於上下文的自適應二進位制算術編碼),大致分為三個步驟:

1、二值化

2、上下文建模(模型初始化、更新)

3、二進位制算術編碼    

對該語法元素的編碼是在codedeltaqp函式中完成的。

void entropy::codedeltaqp(const cudata& cu, uint32_t abspartidx)

}

一、二值化

根據hevc的標準,cu_qp_delta_abs語法元素的字首部分的值為:prefixval=min(cu_qp_delta_abs,5)。並且對prefixval的編碼使用截斷萊斯二進位製化方法(tr),tr方法的兩個引數cmax=5、criceparam = 0。x265中將cu_dqp_tu_cmax(cmax)和tuvalue(prefixval)兩個引數傳遞給writeunarymaxsymbol函式並在其中完成二值化,該函式也同時對其進行編碼,這之後會講。

void entropy::writeunarymaxsymbol(uint32_t symbol, uint8_t* scmmodel, int offset, uint32_t maxsymbol)

該函式中symbol為語法元素值,maxsymbol為門限值cmax,萊斯引數r(criceparam)=0,其他引數先不管。tr分為字首碼和字尾碼,兩者分開求取。

字首值p=v>>r,所以p=symbol,第一種情況:若p小於值(cmax>>r)=maxsymbol,則字首碼由p個『1』和乙個『0』組成,當symbol為0時,p等於0,所以字首就只有乙個0,而p不等於0時,字首碼的第乙個值就為1,所以對第一位進行編碼的encodebin函式的第乙個引數就可以確定,剩餘的『1』在while迴圈中編碼完成,因為迴圈條件為(--symbol)所以會編碼symbol-1個『1』。到此也就完成了p個『1』的編碼,且symbol第二種情況:p大於等於值(cmax>>r)時,字首碼由maxsymbol個『1』組成,由第乙個編碼函式加上while中的編碼函式完成。

字尾值s=v-(p二、上下文模型

1、初始化

codedeltaqp傳遞給writeunarymaxsymbol的兩個引數:

&entropy->m_contextstate[off_delta_qp_ctx](最大概率符號mps、概率狀態索引)和1(初始化型別)

確定了對該語法元素編碼的上下文模型。下面講解對上下文的初始化:

首先先給出標準中對該步驟的描述

inittype01

2initvariable

0..1

2..3

4..5

initvariable

initvalue

我們最終所要的就是initvalue,初始化的函式為:

initbuffer(&m_contextstate[off_delta_qp_ctx], slicetype, qp, (uint8_t*)init_dqp, num_delta_qp_ctx);

static void initbuffer(uint8_t* contextmodel, slicetype slicetype, int qp, uint8_t* ctxmodel, int size)

先看initbuffer函式的引數列表,size=num_delta_qp_ctx=3,表示上下文模型個數,根據上面的**可知,實際上該語法元素需要6個上下模型,但因為initvalue的值都相同,初始化出來的模型也都相同,也就不需要initvariable的中轉,可以直接與inittype對應。slicetype就代表inittype

typedef enum slicetype

slicetype;

init_dqp=ctxmodel儲存initvalue
static const uint8_t init_dqp[3][num_delta_qp_ctx] =

, ,,};

contextmodel就是儲存位址,qp為片層亮度量化引數,初始化演算法中會使用。將initvalue和qp傳給sbacinit實現初始化。

uint8_t sbacinit(int qp, int initvalue)

初始變數計算方法(標準中已給出),mpstate?(initstate-64):(63-initstate)得到概率狀態索引,mpstate為最大概率符號,最後將概率狀態索引左移一位,末尾賦值最大概率符號,state同時儲存兩個引數。

contextmodel=m_contextstate陣列內儲存的就是state,也就是上下文模型。

2、更新

writeunarymaxsymbol函式中的encodebin函式就是實現對二進位制值得編碼,第乙個引數就是二進位制值,第二個引數就是所使用的上下文模型,其引數offset表示在確定inittype中的偏移量,第乙個二進位制位比較特殊需要與後幾位想區分,使用第乙個上下文模型,而後幾位就使用offset所確定的上下文模型。

void entropy::encodebin(uint32_t binvalue, uint8_t &ctxmodel)

uint32_t range = m_range;

uint32_t state = sbacgetstate(mstate);

uint32_t lps = g_lpstable[state][((uint8_t)range >> 6)];

range -= lps;

x265_check(lps >= 2, "lps is too small\n");

int numbits = (uint32_t)(range - 256) >> 31;

uint32_t low = m_low;

// note: mps must be lowest bit in mstate

x265_check((uint32_t)((binvalue ^ mstate) & 1) == (uint32_t)(binvalue != sbacgetmps(mstate)), "binvalue failure\n");

if ((binvalue ^ mstate) & 1)

m_low = (low << numbits);

m_range = (range << numbits);

m_bitsleft += numbits;

if (m_bitsleft >= 0)

writeout();

}

函式中是使用sbacnext通過查表的方法對模型進行更新的。實際上就是標準中所給的概率更新表,只是根據x265中的實際情況進行改寫,就是考慮到mstate最後一位為mps。
const uint8_t g_nextstate[128][2] =

, , , , , , , ,

, , , , , , , ,

, , , , , , , ,

, , , , , , , ,

, , , , , , , ,

, , , , , , , ,

, , , , , , , ,

, , , , , , , ,

, , , , , , , ,

, , , , , , , ,

, , , , , , , ,

, , , , , , , ,

, , , , , , , ,

, , , , , , , ,

, , , , , , , ,

, , , , , , ,

};

三、二進位制算術編碼

encodebin後續完成的就是算術編碼,取出當前的編碼區間m_range和區間下限m_low,sbacgetstate函式將mstate右移一位得到state概率狀態索引,通過取出m_range的後8位(unit8)&3得到計算索引值,與state仍通過查編碼區間索引表的方法確定出當前的最小概率符號區間lps,x265中直接計算range=range-lps得到最大概率區間。

變數numbits表示的是重歸一化過程中輸出的碼元數。重歸一化流程圖如圖所示

numbits第一次被賦的值為(range - 256) >> 31,range為32位,取出符號位,也就得到range是否大於256,。該numbits是在當前二進位制值等於mps的情況下使用的,而其取值為什麼只能為『0』和『1』,是因為在

編碼區間索引表中相鄰概率狀態索引值所對應的lps取值相近,表明當前m_range減去lps若小於256,只要左移一位就可以使其值大於256。

函式的最後根據所得的numbits,實現部分的歸一化操作,並將numbits存入全域性變數中。

if語句中實現的是二進位制值等於(最小概率符號)lps的情況,if中的條件就是binvalue和mstate最後一位的值不相同時執行。

clz函式得到lps二進位制串最高位『1』的位置。

int clz(unsigned int a)

}m_numbufferedbytes = 1;

m_bufferedbyte = (uint8_t)leadbyte;}}

該函式實現流程圖中根據不同情況對l進行調整的步驟,並根據l的值決定輸出的是『0』還是『1』。但這裡使用的是相當複雜的演算法,最終以位元組為單位將編碼下限m_low中的高位作為碼流輸出。到此就完成了熵編碼一條支線上的全過程。

感謝閱讀!!上述都是個人的理解,如果有什麼原則性的錯誤還請提出!!

x265探索與研究(二) x265使用基本方法

參考 第一步 進入 x265 1.8 build vc10 x86 雙擊 build all.bat 則進行編譯。資料夾中的內容變化如下兩圖所示。第二步 用vs開啟上一步中生成的 x265.sln 其具體位置在 x265 1.8 build vc10 x86 如下圖,根據平台選擇 開啟後,vs出現如...

x265各個preset對比

x265編碼器中設定了一系列的preset,包括ultrafast,supe st,veryfast,faster,fast,medium,slow,slower,veryslow和placebo。現在對這幾種preset的引數值進行乙個簡單的對比。其中藍色區域是default的值,medium就是...

x265多執行緒 鎖

對互斥量的一層包裝 class lock 銷毀互斥量 lock 對互斥量加鎖 void acquire 釋放互斥量 void release protected pthread mutex t handle 互斥量 模擬lock guard,建立時自動加鎖 超出scopedlock的作用域,被析構 ...