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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章