11-NAL unit解碼

在完成了參數配置文件的解析之後,主函數中調用cTAppDecTop.decode()開始正式的解碼過程。這個函數中首先調用xCreateDecLib();xInitDecLib();建立和初始化解碼器的對象。下面的byteStreamNALUnit (bytestream, nalUnit, stats);函數進行NAL的解碼過程,進入該函數,發現實際進行操作的是_byteStreamNALUnit(bs, nalUnit, stats);這個函數,看來關鍵就在這裏。
爲了更加清晰地與實驗結果進行對照,用ultraedit打開之前編碼生成的碼流文件str.bin,查看其二進制碼流結構,我們之前生成的碼流數據如下圖所示:
【HEVC學習與研究】13.NAL <wbr>unit解碼
程序在運行中變量的變化值會同ultraedit中顯示的值進行對照,以輔助我們的理解。下圖是別人的博客中的截圖,說明的是NAL層的語法結構,此處借用一下
【HEVC學習與研究】13.NAL <wbr>unit解碼
_byteStreamNALUnit(bs, nalUnit, stats)中,while ((bs.eofBeforeNBytes(24/8)||bs.peekBytes(24/8) != 0x000001)&&(bs.eofBeforeNBytes(32/8) || bs.peekBytes(32/8) != 0x00000001))的這個循環尋找第一個3或4字節長度,值爲1的元素,並丟棄之前的0。
if (bs.peekBytes(24/8) != 0x000001)部分的作用是找出並丟棄zero_byte字段。
uint32_t start_code_prefix_one_3bytes = bs.readBytes(24/8);將提取並捨棄start_code_prefix_one字段。
while (bs.eofBeforeNBytes(24/8) || bs.peekBytes(24/8) > 2){nalUnit.push_back(bs.readByte());}的作用是正式讀取nal單元的數據。在本例中,前四個字節“00 00 00 01”都將被捨棄,正式讀取的數據時從那個0x40(64)開始讀取,一直讀到文件末尾,或者遇到後面三個字節爲0或1爲止。
while ((bs.eofBeforeNBytes(24/8) || bs.peekBytes(24/8) != 0x000001)&&(bs.eofBeforeNBytes(32/8) || bs.peekBytes(32/8) != 0x00000001))將會捨棄末尾的trailing_zero_8bits字段。
在本例中,NAL分析讀取完成後,nalUnit中將包含從value=64開始的24個元素,並在read(nalu, nalUnit);函數中進行下一步處理。
read(nalu, nalUnit)這個函數調用convertPayloadToRBSP函數,將nalUnit中的元素轉化爲nal的參數數據。(該函數爲什麼會捨棄元素3?我沒太弄明白)完成後,nalUnit的buf中共20個元素。之後調用readNalUnitHeader函數,解析nal頭數據。文獻“Overview of HEVC High-Level Syntax and Reference Picture Management”中講述了NAL的頭數據結構,也就是下圖所示:
【HEVC學習與研究】13.NAL <wbr>unit解碼
這樣readNalUnitHeader函數的功能便很明朗了,其主要目的就是獲取nal type和temporal_id這兩部分信息。
PS:更多的關於NAL解碼的信息可以參考一下該博客:
http://blog.csdn.net/hevc_cjl/article/details/8461660
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章