H265_HEVC编解码系列(2):CTB的四叉树分割语法

H265/HEVC编解码系列(2):CTB的四叉树分割语法

一、CTB产生以及四叉树分割

1、CTB的产成

  上篇大致看了一下CTU是如何一步步划分的。下面我们说说,CTU具体是怎样得到的。上面这个图,我们现在只需要看红框里的部分,图中的第①部就是接下来要讲的。如果是yuv420采样,CTU可以分为luma CTBchroma CTB,我们就统一按照CTB来分析吧,对两种CTB处理上都是一样的。首先一幅图片会被分割成许多个大小一样的CTB块,但是CTB的size实在是没有找到是依据什么来确定的,可能是图片复杂度吧(肯定不是分辨率),知道的大佬可以指点一下,只在书上看到这句话:

  编码模块来确定CTB的size,并且大小只能为16x16、32x32、64x64。那么,sps里面是如何体现这个size的呢?看下图,图中黑体的就是sps中的参数,log2_min_luma_coding_block_size_minus3是把最小CTB size减去3再取以2为底的对数,log2_diff_max_min_luma_coding_block_size就是最大和最小CTB size的差值再取以2为底的对数。

  那么,下面的公式就很容易理解了,log2_min_luma_coding_block_size_minus3 + 3就得到了最小CB size(当然,是带log2的),MinCbLog2SizeY + log2_diff_max_min_luma_coding_block_size就是最大的CB size(也就是CTB size,带log2),第三个公式1 << MinCbLog2SizeY,相当于求2的次幂了,比如MinCbLog2SizeY=3时,MinCbSizeY就等于8CbSizeY就是我们想知道的每个CTB的size了,如图,同样也是求2的次幂。

2、四叉树分割

  H265 spec里面首次出现四叉树句法的地方是在描述slice segment句法的位置,如下图。coding_tree_unit就是四叉树分割的句法了。先看看片段的数据句法吧,首先一个大的while循环,前面说过,SS可以包含整数个CTB,这个循环用来遍历所有包含的CTB。进入循环,首先就是往下分割成更小的CB块,这个下面再说。end_of_slice_segment_flag是每个CTB块附加的判断结束位,end_of_subset_one_bit是slice segment subset(SS继续往下划分就是slice segment subset,每个slice segment subset都会被单独编码成CABAC码流)的结束位,最后加上一个对齐,一大堆判断懒得看了。。

  进入重点:coding_tree_unit,看下图,首先计算出了当前CTB块的起始像素(最左上方的那个像素),注意xCtbyCtb的单位是像素,所以在算出CTB块序号后又左移了CtbLog2SizeY位。下面进入了一个判断,进行sao(Sample adaptive offset)样点自适应补偿,对局部做信息补偿,这里不做讨论。

  下面这幅图就开始做四叉树的分割了,split_cu_flag决定了CB块需不需要做四叉树分割,这个flag是由编码器决定的,如果编码器没有指定,就会走图中的判断,若当前CB块区域不超出图像范围并且当前CB size要大于minimum CB size,这一块的split_cu_flag就会被置1,这一块CB就会被分割为四块,一旦split_cu_flag被置1了,接下来就会对分割出来的4块区域再进行递归调用coding_quadtree,继续向更小的CB块分割,直到CB分到8x8为止。若split_cu_flag为0,那么就会调用到coding_unit,CTB的划分到此就结束了,下面就是对CB块进行处理了。

  coding_unit就是对划分好的CB块进行处理,这些CB块的大小可能是8x8、16x16、32x32、64x64。cu_transquant_bypass_flag用来决定当前CB需不需要做缩放和变换;若当前slice不是I slice,cu_skip_flag就决定了当前CB是否可以不依赖其他参数就可以单独解码;nCbS是当前CB的size,如果cu_skip_flag为1,那么就直接进行PU的处理prediction_unit,不需要附加额外参数。如果cu_skip_flag为0,会进入else分支,pred_mode_flag为0说明当前CB是帧间预测模式,为1代表帧内预测模式。palette_mode_flag决定是否启用palette mode,该模式用于当CB块色彩由几种主要颜色构成时,我们的重点是看else分支。

  part_mode是用来表示当前CB块使用的预测分块模式,最下方的图片(Table 9-45)展示了不同分割模式bit流内容,可以自行研究一下。CuPredMode如果等于MODE_INTRA(帧内预测),那么part_mode等于0或者1;若CuPredMode等于MODE_INTER(帧间预测),①log2CbSize大于MinCbLog2SizeY,并且amp_enabled_flag等于1,part_mode取值范围[0, 2]或者[4, 7];②log2CbSize大于MinCbLog2SizeY,并且amp_enabled_flag等于0,part_mode取值范围[0, 2];③log2CbSize等于3,part_mode取值范围[0, 2];④log2CbSize大于3,且log2CbSize等于MinCbLog2SizeYpart_mode取值范围[0, 3]。

  紧接着就是帧内预测的处理,pcm_flag决定是否使用pcm(脉冲编码调制 pulse code modulation),这种方式就比较粗暴,跳过了预测、变换、量化、熵编码的过程,解码端同样也一律bypass,这种方式只有在分割模式为PART_2Nx2N(不分割)时才可以应用,具体的这里就不介绍了,继续往下看。下面判断了PartMode 是否为 PART_NxN(四等分),来决定预测块的size。对于luma样点的预测,编码器会选出三种当前luma样点最有可能使用的帧内预测模式(hevc 总共有35中预测模式),mpm_idx就是选择这三种模式的一种,rem_intra_luma_pred_mode就是除去最可能的3种后剩下的32种中的一个。

  继续往下,出现了一个ChromaArrayType元素,当separate_colour_plane_flag = 0时,ChromaArrayType = chroma_format_idc,可以看一下倒数第二张图片(Table-6-1),如果这里ChromaArrayType = 3,则chroma array size和luma array size相同;否则走else if的分支,这里没有看明白为什么只处理一个chroma sample?

  最后就是各种不同分割的帧间预测了,后面还有个小尾巴是关于transform_tree的句法的,rqt_root_cbf用来表示是否用到变换单元。这些放到下一篇具体来看看。

参考

  • [1] [新一代高效视频编码H.265/HEVC原理、标准与实现]
  • [2] [High Efficiency Video Coding(Hevc) Algorithms and Architectures]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

solanin0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值