正所謂工欲善其事呜呐,必先利其器就斤;我們下面要解析vps,sps蘑辑,pps洋机,少不了的會(huì)有兩點(diǎn):1、對(duì)照spec看語(yǔ)法元素洋魂;2根據(jù)描述解析語(yǔ)法元素绷旗;那么這里我要總結(jié)的是,如何解析這些語(yǔ)法元素副砍;因?yàn)関ps衔肢,sps,pps的信息豁翎,單獨(dú)看每個(gè)有啥含義角骤,在這里看是沒(méi)有太多用處的;目前我們只能說(shuō)了解個(gè)大概谨垃;因?yàn)檫@些信息是為了后面的解碼服務(wù)的启搂;所以這里我們要看具體是怎么解析的;
首先這里我要粘貼一下書(shū)上的描述子的描述(這里有點(diǎn)繞刘陶。。牢撼。但是沒(méi)錯(cuò)):
那么這里面就出現(xiàn)了幾個(gè)概念需要理解:
1匙隔、基于上下文的自適應(yīng)的二元算數(shù)編碼:ae(v)這里指的是可以理解為對(duì)于265就是cabac編碼
2、其他的就是哥倫布編碼以及其他等等熏版;
所以纷责,這節(jié)最主要的還是要看熵編碼這一塊的知識(shí)捍掺,就知道如何進(jìn)行熵解碼
一、
首先我們應(yīng)該先看看普通的變長(zhǎng)編碼(非定長(zhǎng)的再膳,VLC挺勿,看一下首字母就知道怎么回事了)是怎么編碼的;來(lái)引出我們的概念:
常見(jiàn)的就是哈夫曼編碼喂柒,說(shuō)道哈夫曼編碼不瓶,其實(shí)在這里了解一下即可;說(shuō)道哈夫曼編碼就離不開(kāi)哈夫曼樹(shù)灾杰,直接舉例蚊丐,會(huì)比較好理解一些:
假設(shè)ABCD,加權(quán)是0.2,0.3艳吠,0.1,0.4麦备,那么我們?cè)趺串嫻蚵鼧?shù)呢;首先我們找最小的兩個(gè)昭娩;也就是A凛篙,C。
小概率的放到左邊栏渺,大概率的放到右邊鞋诗,那么就會(huì)合成一個(gè)E,E就是0.3迈嘹,然后E再和B對(duì)比削彬,然后組成F,F(xiàn)是0.6秀仲,然后再和D對(duì)比那么D放到左邊融痛,F(xiàn)放到右邊,所以就會(huì)有下圖:
畫的太丑了神僵,但是很明顯就是編碼后雁刷,A是111,C是110保礼,B是10沛励,D是0,所以比較簡(jiǎn)單炮障;
舉例如果是ACBA目派,那么編碼出來(lái)的就是11111010111
二、
上面是代表的是變長(zhǎng)編碼胁赢;但是算數(shù)編碼是不一樣的企蹭;變長(zhǎng)編碼,如哈夫曼編碼,那么會(huì)是要對(duì)每個(gè)碼字都要進(jìn)行率先給一個(gè)碼字谅摄;如A是111徒河,C是110,那么每個(gè)字符送漠,至少也得分配一個(gè)碼字顽照;但是算數(shù)編碼不是的;他是要對(duì)整個(gè)碼率進(jìn)行編碼闽寡;這就出現(xiàn)了概率空間的概念了舉個(gè)例子代兵,比如AA,我可能用1一個(gè)bit就代替了下隧,那么如果使用邊長(zhǎng)編碼的話奢人,那么就會(huì)出現(xiàn)1111116個(gè)bit,這樣是不是感覺(jué)算數(shù)編碼很節(jié)氏骸何乎?
上面說(shuō)了這么多,其實(shí)沒(méi)啥用土辩,如果不舉例支救,其實(shí)什么都看不懂;我們還是按照上面的概率拷淘,上面ACBA舉例各墨;那么如果是算數(shù)編碼,那么應(yīng)該是怎么樣的呢启涯?
如下圖:
1贬堵、首先我們說(shuō),第一個(gè)碼字是A结洼,那么就是落在的概率區(qū)間就是[0,0.2]
2黎做、然后第二個(gè)碼字是C,那么C是在A的基礎(chǔ)之上的松忍,所以C落在[0.1~0.12],C過(guò)后蒸殿,概率區(qū)間只有0.02大小了
3、然后是B鸣峭,那么B是在0.02x0.2以后宏所,所以結(jié)合前面就是0.104~0.11之間;此時(shí)摊溶,概率區(qū)間只有0.006大小了
4爬骤、最后是A,那么A又是從0開(kāi)始的更扁,所以輸出的碼率下限就是0.104盖腕,那么我們輸出0.104赫冬,就能代表是ACBA這個(gè)碼字了
我們整理為公式的話輸出的就是0+0.2x0.5+0.2x0.1x0.2 = 0.104
那比如如果我們現(xiàn)在有了一個(gè)小數(shù)浓镜,能否解碼出來(lái)呢溃列?答案是必須且唯一的;要不學(xué)習(xí)算數(shù)編碼膛薛,無(wú)法解碼有什么用呢听隐?
假設(shè)是一個(gè)0.105,那么0.105在0~0.2之間哄啄,也就是說(shuō)第一個(gè)是A
然后我們現(xiàn)在看編碼的這個(gè)公式0+0.2x0.5+0.2x0.1x0.2 = 0.104
說(shuō)明什么呢雅任?說(shuō)明下一步主要看第二加的內(nèi)容區(qū)間。所以為(0.105-0)/0.2 = 0.525咨跌,是C
以此類推沪么,(0.525-0.5)/0.1 = 0.25,是B
(0.25-0.2)/0.3是0.166,是A
也就是最終為ACBA;
那么我們上面編碼不是0.104嘛锌半,為啥0.105也是ACBA呢禽车?
因?yàn)锳CBA最后一個(gè)是落在0.006x0.2 = 0.0012也就是說(shuō),在0.104~0.1052之間的任意數(shù)都是0可以的刊殉;
三殉摔、
下面要看一下哥倫布指數(shù)編碼;哥倫布指數(shù)編碼记焊,屬于變長(zhǎng)編碼的范疇逸月;那么我們從上面可以看出我們學(xué)習(xí)了變長(zhǎng)編碼,算數(shù)編碼遍膜;為什么碗硬,我們要回過(guò)頭來(lái),看哥倫布指數(shù)編碼呢瓢颅?
首先恩尾,我們要看哥倫布指數(shù)編碼在265中的作用:
1、slice以上大多會(huì)用到哥倫布指數(shù)編碼(sps惜索,vps特笋,pps,ue(v)巾兆,se(v))
2猎物、在slice層,有一個(gè)參數(shù)要用1階哥倫布指數(shù)編碼去二值化
這兩點(diǎn)是不是很暈角塑?其實(shí)還好蔫磨,我大體描述一下是什么意思:
對(duì)于那些sps,vps這些圃伶,我們需要哥倫布編碼的方式編碼堤如;就是這些值用哥倫布指數(shù)編碼編成0101的碼字即可蒲列;
但是對(duì)于slice編碼的話,就像上面描述的搀罢;用變長(zhǎng)編碼是不是用的碼字特別多蝗岖?是不是需要用算數(shù)編碼?但是算數(shù)編碼需要三步:1榔至、二值化抵赢;2、建立概率模型唧取;3铅鲤、算數(shù)編碼;此時(shí)枫弟,變長(zhǎng)編碼邢享。也就是1階哥倫布指數(shù)編碼就會(huì)用到了
但是這里我得說(shuō)一句,一階哥倫布指數(shù)編碼去二值化淡诗,情況很少骇塘,大部分我們不用這種方式;slice層只有一個(gè)地方會(huì)用到袜漩;所以了解即可绪爸;
終于要進(jìn)入正題了;就是如何進(jìn)行哥倫布指數(shù)編碼:
首先要看一下宙攻,無(wú)符號(hào)0階哥倫布指數(shù)編碼:
這里我是在不想寫那么多了奠货,但是我只是總結(jié)一下;其中座掘,圖片中codenum指的是要編碼的語(yǔ)法元素递惋;如果要進(jìn)行哥倫布指數(shù)編碼,那么有兩部分組成:
1溢陪、前綴0萍虽,前綴0的話,計(jì)算就是M那個(gè)公式形真;
2杉编、實(shí)際的碼字,就是codenum+1對(duì)應(yīng)的二進(jìn)制咆霜;
如果編程的話邓馒,沒(méi)有以2為底的函數(shù)的話,可以用兩個(gè)以10為底的log相除
是不是很簡(jiǎn)單蛾坯,下面還有表格光酣,都是例子;
然后再看有符號(hào)的哥倫布指數(shù)編碼
其中V是指的要編碼的語(yǔ)法元素脉课;是不是很巧妙救军?通過(guò)奇偶就能區(qū)分了正負(fù)财异;可以看出,正數(shù)都是變成了奇數(shù)后再去編碼唱遭,負(fù)數(shù)和0變成了偶數(shù)去編碼戳寸;
最后看一下1階哥倫布指數(shù)編碼,再?gòu)?qiáng)調(diào)一點(diǎn)胆萧,這個(gè)只是為了二值化庆揩,所以會(huì)用1階哥倫布指數(shù)編碼
這里貼了一段程序俐东,如下:
代碼是不是很容易就可以看懂跌穗?
其中synval代表的是要編碼的語(yǔ)法元素;要首先求一個(gè)絕對(duì)值虏辫;然后定義個(gè)結(jié)束的標(biāo)志位蚌吸;然后k初始化為1,因?yàn)槭?階哥倫布指數(shù)編碼砌庄;然后循環(huán)輸出0和1羹唠,然后輸出幾個(gè)0,或者幾個(gè)1娄昆,最終結(jié)束佩微;
舉例14,按照上述的邏輯輸出為11100000萌焰,也就是224
講到這里哺眯,我們其實(shí)自適應(yīng)的二元算數(shù)編碼還沒(méi)有接觸。但是起碼扒俯;sps這些你能解析了奶卓;因?yàn)樗麄兇蟛糠质歉鐐惒季幋a;這節(jié)寫的有點(diǎn)多撼玄,所以后面再寫cabac