【H.264/AVC视频编解码技术具体解释】十三、熵编码算法(4):H.264使用CAVLC解析宏块的残差数据...
《H.264/AVC視頻編解碼技術(shù)具體解釋》視頻教程已經(jīng)在“CSDN學(xué)院”上線,視頻中詳述了H.264的背景、標準協(xié)議和實現(xiàn),并通過一個實戰(zhàn)project的形式對H.264的標準進行解析和實現(xiàn),歡迎觀看!
“紙上得來終覺淺。絕知此事要躬行”。僅僅有自己依照標準文檔以代碼的形式操作一遍,才干對視頻壓縮編碼標準的思想和方法有足夠深刻的理解和體會。
鏈接地址:H.264/AVC視頻編解碼技術(shù)具體解釋
GitHub代碼地址:點擊這里
1. H.264的CAVLC解析宏塊殘差數(shù)據(jù)的流程
在H.264的解碼器在解析宏塊的殘差數(shù)據(jù)時。其流程相似于上文提到的CAVLC編碼的逆過程。
在解析一個宏塊殘差的時候。首先解析的是殘差矩陣的非零系數(shù)以及拖尾系數(shù)的個數(shù)numCoeff和trailingOnes。隨后是每個拖尾系數(shù)的符號trailingSigns。而后是每個非拖尾非零系數(shù)level的值。然后解析的是最高頻非零系數(shù)前面的零的總個數(shù)totalZeros。最后是每個非零系數(shù)前連續(xù)零的個數(shù)runBefore。
2. 計算CAVLC解析殘差的上下文參數(shù)
CAVLC編解碼過程中的上下文即為當前塊值numberCurrent。該值與當前像素塊的左側(cè)鄰塊和上方鄰塊中非零系數(shù)的個數(shù)有關(guān)。
以尺寸為4×4宏塊切割方式為例。當前像素塊同左側(cè)和上方鄰塊的相對位置關(guān)系例如以下圖:
對于當前像素塊。若其上方和左側(cè)相鄰塊都不可見(unavailable),那么當前像素塊的numberCurrent值為0;若上方或左側(cè),有且僅有一個相鄰塊是可見的。那么當前像素塊的numberCurrent值即為這個鄰塊中非零系數(shù)的個數(shù)numCoeff;若兩個鄰塊都是可見的,那么當前像素塊的numberCurrent值為兩個鄰塊numCoeff的四舍五入平均值。
3. 解析非零系數(shù)總個數(shù)和拖尾系數(shù)個數(shù)
在CAVLC的解析過程中。非零系數(shù)總個數(shù)numCoeff和拖尾系數(shù)個數(shù)trailingOnes兩個值是一起解析出來的。
解析這兩個值依據(jù)的是標準文檔中的表9-5,例如以下表即是表9-5的部分:
依據(jù)之前解析出來的numberCurrent值,在這個表格中選擇一列作為解碼數(shù)據(jù)的參考。此后,從碼流中讀取對應(yīng)長度的二進制碼流。與表格中的值相比較。當碼流與表格中的值匹配時,表格的前兩列作為數(shù)組的下標。其值即等于希望解析出來的numCoeff和trailingOnes的值。
4. 解析拖尾系數(shù)的符號
我們知道變換系數(shù)矩陣中最高頻的幾個絕對值為1的非零系數(shù)稱之為拖尾系數(shù),其個數(shù)范圍為0~3個。
表示每個拖尾系數(shù)的符號能夠一個bit的trailing_ones_sign_flag表示:
- 當trailing_ones_sign_flag為1,拖尾系數(shù)符號為-。
- 當trailing_ones_sign_flag為0,拖尾系數(shù)符號為+;
5. 解析非零系數(shù)的幅值
非拖尾的非零系數(shù)的幅值通常表示為levels。
Levels的解析相對較為復(fù)雜。該部分是從最高頻開始解析到最低頻的非零系數(shù)為止。也就是說,levels部分是按頻率倒序解析的。
在解析每個level的時候。每個值都會依照前綴(prefix)和后綴(suffix)兩部分進行解析。
5.1 解析level_prefix部分:
Level_prefix部分即level的前綴部分,該部分的解析較為簡單,以偽代碼表示如:
leadingZeroBits = ?1 for( b = 0; !b; leadingZeroBits++ )b = read_bits( 1 ) level_prefix = leadingZeroBits結(jié)合標準文檔中的表9-6的表述可知。level的前綴值即為當前碼流的下一個比特1之前連續(xù)的比特0的個數(shù)。
5.2 解析level_suffix部分:
Level_suffix部分的解析比prefix部分復(fù)雜,整體上能夠分為下面幾個步驟:
5.3 由level_prefix和level_suffix部分組合成為levelCode
在解析完畢level_prefix和level_suffix之后,將二者組合生成levelCode。
計算方法為:levelCode=(Min(15,level_prefix)<
5.3 由levelCode計算level
依據(jù)計算得到的levelCode的奇偶性。推斷l(xiāng)evel的符號:
- 若levelCode是偶數(shù),返回level值為(levelCode + 2)>>1;
- 若levelCode為奇數(shù),返回level值為(?levelCode?1)>>1;
5.4 更新suffixLength的值
在解析過程中更新suffixLength體現(xiàn)了上下文自適應(yīng)的思想。
- 當suffixLength = 0時。suffixLength更新為1;
- 當suffixLength小于6。且剛剛解析出來的level值大于閾值threshold時,suffixLength自增1;閾值threshold定義為( 3 << ( suffixLength ? 1 ) );
6. 解析零系數(shù)信息
變換系數(shù)矩陣中的零系數(shù)也是重要的信息。CAVLC解析的零系數(shù)信息主要分兩類:
- totalZeros:每個矩陣一個值,表示最高頻非零系數(shù)前零系數(shù)的總個數(shù);
- runBefore:每個非零系數(shù)一個值,表示該非零系數(shù)前連續(xù)0的總個數(shù)。
解析totalZeros的過程與解析numCoeff和trailingOnes相似,都是從一個二維表格中查找某列表格,在從碼流中查找與表格中匹配的值。然后索引便是所求的totalZeros值。解析totalZeros的表格為標準文檔中的表9-7。下圖是表9-7的局部:
在解析totalZeros的過程中。選擇表格的索引值等于當前矩陣塊的非零系數(shù)個數(shù)numCoeff。
解析每個非零系數(shù)的runBefore時,也是依照從高頻到低頻逆序處理的。每次解析的runBefore也是依照相似上述的解析方法。從碼流中讀取對應(yīng)長度的碼流并與表格中的值比對,匹配后返回索引值作為解析的值。解析runBefore參考標準文檔的表9-10:
每次解析出一個runBefore后,totalZeros都要減去該值,然后進行下一次處理。若有n個非零系數(shù)。則總共須要解析n-1個runBefore。最低頻率的非零系數(shù)前的runBefore不須要寫在碼流中,由于能夠通過上述信息推算出。
以上就是解析一個宏塊的4×4殘差系數(shù)矩陣對應(yīng)語法元素的主要思想和過程。當然實際的解析過程比此要復(fù)雜得多,更具體的情況可到CSDN學(xué)院的課程:H.264/AVC視頻編解碼技術(shù)具體解釋中觀看。
轉(zhuǎn)載于:https://www.cnblogs.com/lxjshuju/p/7296094.html
總結(jié)
以上是生活随笔為你收集整理的【H.264/AVC视频编解码技术具体解释】十三、熵编码算法(4):H.264使用CAVLC解析宏块的残差数据...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 技术面试的时候应该了解公司点什么
- 下一篇: springmvc 的 @PathVa