CABAC之手把手教你編碼

首先要說明的是CABAC的生命期是SLICE,因此本篇所講的也是一個SLICE里CABAC的流程,其次對于我們來說場模式幾乎用不到,所以本文的編碼流程只使用幀模式,因此實際上用到的表只有277個, 當然如果我寫成399, 不是說里面所有表都用到的. 這里只是聲明一下這個問題, 如果大家實際操作的時候發現模型表序號始終不過276那是很正常的. 本文參考了T264的代碼, 應此一幀里只有一個SLICE. 而本文用的變量則采用標準里的變量.本文不會講CABAC的原理, 想要了解原理請參考FTP上的<<Context-based adaptive binary arithmetic coding in the H.264AVC video compression standard>>

?????? 注意:我用的標準是BS的正式標準,可能里面的序號和大家的不一樣,但是內容應該是一樣.大家對照著就可以了

片級: 即以下步驟在片期間只做1次

?????? 1, 在一幀的開始的時候, 先看是否字節對齊, 沒有對齊則補1, 直到字節對齊

?????? 2, 先根據SliceQP算出399個模型表里的pStateIdx和valMPS, 構成一張初始表,根據標準9.3.1.1里的公式, 同時可以參考T264_cabac_context_init函數. 這張表不要和模型表弄混,雖然都是399維的, 但我們宏塊級編碼過程中實際用的只是這張表, 而不是標準里的那張模型表Table 9-23, 9-23這張表是用來算由pStateIdx和valMPS構成的初始表的.

?????? 3, 然后就是初始化CABAC的初值, 下界指針,區間范圍 (0x1FE)等等,可參考T264_cabac_encode_init函數.

宏塊級: 以下則是每個宏塊都要做一次的, 這一級中會處理很多的語法元素, 這里我只用前2個語法元素做為例子: mb_skip_flag, mb_type

??????? 4, 重整區間, 確保在區間在28-29內.這里的區間概念來自BAC,如果不明白先google算術編碼,然后再看上面那個參考文獻.

??????? 5, 首先mb_skip_flag標志進行CABAC編碼, 由于這個元素本身就是2值的,所以直接就可以進行上下文模型選擇了:

??????????????? 1. 由標準Table 9-24知道, P幀(這里要注意是slice_type==P, 不是mb_type)的這個元素用11號表, B幀用24號表. 可以參考T264中的T264_cabac_mb_skip函數.

??????????????? 2. 由于這個元素只有1個bit, 因此只要算第一個bit的ctxIdxInc就可以了, 參考標準Table 9-29, 可以看到表中11 和 24號表確實只有第一個bit是可用的, 根據9.3.3.1.1子條款可以知道這一位的ctxIdxInc可能是0, 1, 2中的一個, 在T264中簡單的說就是看左邊和上邊宏塊是否是Skip模式, 有一個是skip模式ctxIdxInc就加1. 也就是全不是skip為0, 有一個skip則ctxIdxInc就是1,全是skip則ctxIdxInc就是2.

??????????????? 3. 下來就是算術編碼部分了, 簡單提一下基本原理: 在CABAC中為了減少RLPS = R*pLPS 這個區間變換公式的開銷, 用128個有限狀態(實際可用的為126)代替pLPS , 用rangeTab這張表代替了RLPS, 見標準Table 9-33. 可以參考T264中的T264_cabac_encode_decision函數, 看一下具體流程:

????????? 獲得當前bin的pStateIdx和valMPS(來自片級計算的那張初始表)

????????? 根據標準9.3.3.2.1子條款, 求得qCodIRangeIdx用來索引表rangeTab, 即可以求得變換后的區間了.

????????? 修正區間codIRange = codIRange – codIRangeLPS

????????? 判斷當前的bin是否為最有可能的值, 如果不是(binVal!= valMPS),則更新區間下邊界codILow = codILow + codIRange, 同時修正區間codIRange = codIRangeLPS;然后判斷當前狀態, 如果已經達到狀態0, 是則把valMPS的值取反(即0,1互換), 如果還有沒達到0, 則進行LPS的狀態遷移,具體參看標準Table 9-34的狀態遷移表中的transIdxLPS

????????? 如果當前的binVal值等于valMPS, 就比較簡單了, 直接進行狀態遷移, MPS的狀態遷移也很簡單, 直接數據+1就可以了(最大63),具體參考標準Table 9-34的狀態遷移表中的transIdxMPS, 狀態的轉移其實就是修改了399個模型的初始表.

????????? 區間重整, 如果區間過小則輸出一些bit, 這樣可以不用把數據全部編碼完再輸出, 可以編一部分輸出一些.

????????? 已編碼的2進制值bin總數+1, 即SymCnt+1, 這個值用于字節填充, 可以參考標準9.3.4.6, 其中的BinCountsInNALunits就是指這個值,至此算術編碼部分就結束了.

??????? 6, 下面就是開始編碼第二個語法元素了: mb_type

????????????????? 1)???? 不同于上一個語法元素mb_skip_flag, mb_type這個語法元素本身并不是二值化的, 因此編碼的第一步是進行二值化, 查閱標準Table 9-24可知mb_type的二值化方法需要參考9.3.2.5子條款, 由該條款可知mb_type的二值化相對簡單, 可以直接參考表得到, 例如I片中某宏塊mb_type為I_16x16時則二值化后bin0=1, 且非I_PCM則bin1=0, 亮度AC無非0系數則bin2=0, 色度有非0系數則bin3=1, 色度DC,AC都無非0系數時,bin4=0, 幀內預測模式為0時則bin5=0, bin6=0, 因此我們就得到了標準中I_16x16_0_1_0的二值化串為1001000

???????????????? 2)???? 下來是上下文模型選擇, 由Table 9-24可知 I的mb_type元素起始表是3號表, 然后參考標準表Table 9-29, 計算bin串中每個bin的ctxIdxInc值,由表可知bin0要參考9.3.3.1.1.3才能確定ctxIdxInc值, 簡單的說就是如果上邊和左邊的塊模式有一個不是I_4x4則ctxIdxInc++, 這樣就有0,1,2這3種可能的結果了; bin1的ctxIdx固定是276, 直接就調用了encoder_terminal模塊, 即標準Figure 9-11的右分支;bin2的ctxIdxInc是3;bin3的ctxIdxInc是4,; bin4和bin5要參考9.3.3.1.2子條款, 由該條款可知如果bin3是1則bin4的ctxIdxInc=5,bin5的ctxIdxInc=6,如果bin3=0則bin4的ctxIdxInc =6,bin5的ctxIdxInc =7,由于I_16x16_0_1_0的二值化串為1001000, 其中bin3=1, 由此可知此時bin4的ctxIdxInc =5, bin5的ctxIdxInc =6; 最后由表9-29 中bin6的ctxIdxInc為7.至此二進制串所有位的表號可以用3+的ctxIdxInc來得到了.

??????????????? 3)???? 下來就是算術編碼部分,這個部分于mb_skip_flag的算術編碼部分步驟一樣.這里要提的是, 第一步獲得當前bin的pStateIdx和valMPS的模型表已經被更新了(是表被更新,但不一定是當前表), 還記得么? 是在上一個語法元素的狀態轉移的時候更新的.

??????? 7, 下面的語法元素就是按照標準7.3.5的語法一一編碼的, 其過程和上面2個語法元素的編碼過程大同小異,就不一一細述了.

?

……如此做完所有的宏塊里的語法元素

又回到片級:

?????? 8, 寫入end_of_slice_flag的標志,即完成標準Figure 9-11的左分支, 然后調用T264_cabac_encode_flush函數, 輸出bit

?????? 9, 進行byte stuffing, 參考標準9.3.4.6 Byte stuffing process里的公式可以求得k, 在碼流中填充k次的0x000003

?????? 10, 最后是模型更新,更換模型表(更改PB幀所用的模型表,而I幀所用的不變)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455736.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455736.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455736.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python網絡攻擊代碼_Python-python網絡編程寫arp攻擊代碼

from scapy.all import ARP,send,arping import sys,re,random,time stdoutsys.stdout ip IPADDR"192.168.1.102" 網關 gateway_ip"192.168.1.1" tmp[] 偽造網關mac地址 for i in range(0,6): tmp.append(str("%02x"%random.randint(0x01,0xfe))…

Kubernetes初步學習

今天分享如題&#xff1a; Kubernetes 本篇內容源于工作項目需要自學 但K8s確實現在十分的主流so推薦給大家 最近更新緩慢由于工作太忙惹&#xff0c;忙里偷閑整理愿分享能與君共勉&#x1f4aa; 大家新年快樂&#x1f389; &#x1f508;言歸正題&#xff0c;相信很多朋友…

手機界面常見的的九宮格

手機界面常見的的九宮格 手機界面常見的的九宮格 首先布局的話需要用到一個mainactivity和一個item的布局目前用得最多也最熟悉的還是LinearLayout布局所以&#xff0c;一下也是&#xff0c;按套路就不過多贅述了。 <GridView android:layout_width"wrap_content"…

JavaScript中的運算符

js運算符 算 字 賦 比 邏 位 它算術運算符 - * / --字符串連接 賦值運算 - %比較運算符 < > > < ! !邏輯運算符 && || !位運算 ^ & | << >>其它運算符 ? : 三元運算符 delete&#xff1…

CABAC編碼

H&#xff0e;264&#xff0f;AVC標準采用了很多新技術和新方法&#xff0c;大大提高了視頻編碼效率&#xff0c;其中CABAC便是H&#xff0e;264&#xff0f;AVC采用的新型熵編碼方法之一。CABAC采用了高效的算術編碼思想&#xff0c;同時充分考慮了視頻流相關統計特性&#xf…

【教程分享】Jmeter入門教程

好&#xff01;回歸學長每周的教程分享&#xff01; PART2 >今天又來分享Jmter 因為最近好像有相關工作內容 提前準備資修一下 分享僅供參考- JMeter的作用對軟件做壓力測試 1.能夠對HTTP和FTP服務器進行壓力和性能測試&#xff0c; 也可以對任何數據庫進行同樣的測試&…

linux 特殊shell變量

特殊變量 環境變量&#xff1a; 系統本身運行需要由linux系統提前創建好的一類變量 主要用于用戶的工作環境&#xff0c;包括&#xff08;用戶的宿主目錄&#xff0c;命令的查找路徑&#xff0c;用戶的當前目錄&#xff0c;登錄的終端等&#xff09;環境變量的值由操作系統本身…

JavaScript中的循環

js循環 程序中進行有規律的重復性操作&#xff0c;需要用到循環語句。 break 和 continue 語句對循環中的代碼執行提供了更嚴格的控制。 for循環 for(var i0;i<len;i){...... }while循環 var i0;while(i<8){......i;}for-in 語句 for-in 語句是嚴格的迭代語句&…

快速傅里葉變換python_FFT快速傅里葉變換的python實現過程解析

FFT是DFT的高效算法&#xff0c;能夠將時域信號轉化到頻域上&#xff0c;下面記錄下一段用python實現的FFT代碼。 # encodingutf-8 import numpy as np import pylab as pl # 導入和matplotlib同時安裝的作圖庫pylab sampling_rate 8000 # 采樣頻率8000Hz fft_size 512 # 采樣…

rabbitmq的安裝全過程

2019獨角獸企業重金招聘Python工程師標準>>> 1 首先下載安裝依賴elang 添加yum支持 cd /usr/local/src/ mkdir rabbitmq cd rabbitmq wget http://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm rpm -Uvh erlang-solutions-1.0-1.noarch.rpm rp…

【框架學習分享】HttpRunner

今天文章分為兩部分 :) PART1 HttpRunner內容分享/ PART2 關于后廠村兒 10 Minutes HttpRunner: PART 1 首先感謝作者開源&#x1f44d; 因為最近工作需要用到HttpRunner&#xff0c; 于是便趁著周末學了下這個測試框架&#xff0c;感覺還可以~ 所以分享一下今天的學習記…

x264 移植到 ARM的方法

1。Linux下編譯X264&#xff1a; 其實在windows下使用vc已經編譯過了&#xff0c;不過聽到有人說在linux下編好了&#xff0c;我也就嘗試做一下&#xff0c;況且x264源代碼的makefile已經做好了&#xff0c;我只需要做的就是把文件copy一下&#xff0c;然后make 一下就可以了。…

JavaScript中的元素獲取與操作

js元素獲取與操作 可以使用內置對象document上的getElementById方法來獲取頁面上設置了id屬性的元素&#xff0c;獲取到的是一個html對象&#xff0c;然后將它賦值給一個變量&#xff0c;比如&#xff1a; <script type"text/javascript">var oDiv document…

VUE2第五天學習---自定義指令

閱讀目錄 1.理解VUE中的自定義指令回到頂部1.理解VUE中的自定義指令 默認核心指令有 (v-model 和 v-show), 但是有時候我們需要用到自定義指令&#xff0c;在vue中&#xff0c;代碼復用主要形式和抽象是組件&#xff0c;但是在有的情況下&#xff0c;我們仍然需要對DOM元素進行…

python報名_2019年少兒Python創意編程比賽報名時間

2019年Python創意編程比賽時間及相關規定&#xff1a;參賽對象 Python創意編程比賽設初中組和高中組。 全國各地初中、高中(含中等職業學校)在校學生均以個人名義報名參加。 參賽步驟 Python創意編程比賽分初評、復評和終評三個階段&#xff0c;初評和復評以線上形式開展&#…

【分享】后廠村鮮為人知的另一面

好&#xff01;回歸學長每周的雜談分享&#xff01; 有人說“后廠村”像一座孤島&#xff0c; 這里遠離喧囂&#xff0c;沒有生活氣息。 而剛剛到廠的學長&#xff0c; 卻想和你分享他鮮為人知的另一面。 內容整理源于網絡看客原創侵刪 說起后廠村&#xff0c;也許是老北京人…

windows 下安裝rabbitmq

2019獨角獸企業重金招聘Python工程師標準>>> 1、下載 下載地址&#xff1a;http://www.rabbitmq.com/download.html 2、Windows上安裝 2.1 安裝安裝Erlang 下載erlang&#xff1a;http://www.erlang.org/download/otp_win64_17.3.exe 安裝&#xff1a; erlang安裝完…

【Kubernetes】k8s 的基本使用指令

今天分享如題&#xff1a; Kubernetes 最近更新緩慢由于工作太忙惹&#xff0c;忙里偷閑整理愿能與君共勉&#x1f4aa; K8S對我來說是個新的技術棧&#xff0c;程序員就是需要一直充電&#x1f50b; 加油&#xff0c;一起進步&#x1f4aa; 結構模型 k8s 是經典的一對多模…

php是如何工作的

a:前提條件: apache服務器啟動正常工作 b:客戶端瀏覽器在地址欄輸入一個程序地欄 按回車發送請求 {請求}http://127.0.0.1/day03/1.php c:apache接收請求&#xff0c;并且負責查找相應資源1.php d:如果apache沒有找到相應的資源,返回錯誤消息給客戶端瀏覽器404 NOT FOUND e:如果…

c語言 malloc_C語言快速入門——動態內存分配

在前面一系列的字符串操作中&#xff0c;我們都是先定義一個固定大小的字符數組&#xff0c;然后根據所需&#xff0c;或拷貝、或連接、或格式化來為這個數組提供內容。固定大小的數組意味著在程序運行期間&#xff0c;數組所占用的內存是確定的(即劃分了固定數量的內存)&#…