H.264协议CABAC熵编码学习(四)

目录:
H.264协议CABAC熵编码学习(一)
H.264协议CABAC熵编码学习(二)
H.264协议CABAC熵编码学习(三)
H.264协议CABAC熵编码学习(四)
H.264协议CABAC熵编码学习(五)

先列出计算ctxIdx的公式:

  • (1)ctxIdx=ctxIdxOffset+ctxIdxInc(ctxIdxOffset,binIdx)

  • (2)ctxIdx=ctxIdxOffset+ctxIdxInc(ctxBlockCat)+ctxIdxBlockCatOffset(ctxBlockCat)

特殊语法元素ctxInc推导过程

再次说明,若无介绍到,则该语法元素使用式1进行推导,而式1的ctxIdxOffset和ctxIdxInc可以通过查阅Table 9-34获取。

mb_type

mb_type是一个比较复杂的语法元素,其包含的值较多,这里首先介绍下其值的意义,在介绍如何推导ctxInc。

mb_type的值

该语法元素表示的宏块类型。接下来笔者将详细的介绍下该语法元素的值。

一个宏块可以是I、P、B、SKIP、PCM这5种类型中的一种。每种类型根据子宏块的划分方式以及预测模式,又分别有多种类型。

首先介绍下I块的类型:

H.264协议CABAC熵编码学习(四)

表格中,左边是I块类型值,右边是该值二值化后的结果。第一个I_NxN表示的是继续进行子宏块划分,可以是4x4和8x8,根据transform_size_8x8_flag进行判定。最后一个I_PCM表示的是使用PCM模式。

其他值可以总结为I_16x16_a_b_c,其中16x16表示是16x16划分,而a表示的是16x16的帧内预测模式,b表示chroma的CBP(coded_block_pattern),c表示的是luma的CBP。

对于P块,其类型如下:

H.264协议CABAC熵编码学习(四)

  • P_L0_16x16:16x16宏块的参考帧在L0中

  • P_L0_L0_16x8:两个16x8子宏块的参考帧在L0中,并且索引可能一致或者不一致

  • P_L0_L0_8x16:两个8x16子宏块的参考帧在L0中,并且索引可能一致或者不一致

  • P_8x8:四个8x8子宏块的参考帧在L0中,并且索引不全都一样

  • P_8x8ref0:四个子宏块8x8的参考帧在L0中,并且索引一致

对于B块,其类型如下:

H.264协议CABAC熵编码学习(四)

  • B_Direct/L0/L1/Bi_16x16:16x16宏块采用Direct预测模式或者参考帧在L0/L1/L0和L1中

  • B_L0/L1/Bi_L0/L1/Bi_16x8/8x16

  • B_8x8

对于P和B块,其都可以继续划分子宏块,子宏块的类型如下:

H.264协议CABAC熵编码学习(四)

其含义与之前介绍的相同。

协议中根据mb_type,还回推导出一些中间变量,这些变量用于协议中其他语法元素值得推导,这里列出这些中间变量得表格。

H.264协议CABAC熵编码学习(四)
H.264协议CABAC熵编码学习(四)
H.264协议CABAC熵编码学习(四)
H.264协议CABAC熵编码学习(四)

mb_type的ctxInc推导

使用式1计算ctxIdx。

  • 满足以下条件之一,condTermFlagN为0

    • mbAddrN不存在

    • ctxIdxOffset为0,并且mbAddrN的mb_type为SI

    • ctxIdxOffset为3,并且mbAddrN的mb_type为I_NxN

    • ctxIdxOffset为27,并且mbAddrN的mb_type为B_Skip或者B_Direct_16x16

  • 否则,condTermFlagN为1

ctxIdxInc可通过如下算式计算:

ctxIdxInc=condTermFlagA+condTermFlagB

ref_idx_l0/l1

使用式1计算ctxIdx。

笔者介绍的都是帧模式的情况,因此

refIdxZeroFlagN=((refidxlX[mbPartIdxN]>0)?0:1)

ref_idx_l0/l1的ctxIdxInc的推导还需要利用到变量predModeEqualFlagN,该变量的推导过程如下:

  • 若mbAddrN为B_Direct_16x16或者B_Skip,predModeEqualFlagN为0

  • 否则,若mbAddrN为P_8x8或B_8x8,则:

    • 若SubMbPredMode(sub_mb_type[mbPartIdxN])不为Pred_LX,并且不为BiPred,则predModeEqualFlagN为0

    • 否则,predModeEqualFlagN为1

  • 否则:

    • 若MbPartPredMode(mb_type, mbPartIdxN)不为Pred_LX,并且不为BiPred,则predModeEqualFlagN为0

    • 否则,predModeEqualFlagN为1

condTermFlagN的推导过程如下:

  • 若如下任一条件为真,则condTermFlagN为0:

    • mbAddrN不可用

    • mbAddrN为P_Skip或者B_Skip

    • mbAddrN为帧内预测模式

    • predModeEqualFlagN为0

    • refIdxZeroFlagN为1

  • 否则,condTermFlagN为1

ctxIdxInc的计算公式如下:

ctxIdxInc=condTermFlagA+2condTermFlagB

mvd_l0/l1

使用式1计算ctxIdx。

该语法元素ctxIdxInc的推导,需要使用到中间变量predModeEqualFlagN,compIdx,absMvdCompN。

predModeEqualFlagN跟前面的推到方式一致,compIdx的推到方式如下:

  • 若ctxIdxOffset为40,compIdx为0

  • 否则,compIdx为1

absMvdCompN的推到方式如下:

  • 若以下任一条件为真,absMvdCompN为0:

    • mbAddrN为0

    • mbAddrN为P_Skip和B_Skip

    • mbAddrN为帧内预测模式

    • predModeEqualFlagN为0

  • 否则:

    • absMvdCompN=abs(mvd_lX[mbPartIdxN][subMbPartIdxN][compIdx])

ctxIdxInc的计算公式如下:

  • 若absMvdCompA + absMvdCompB小于3,则ctxIdxInc为0

  • 若absMvdCompA + absMvdCompB大于32,则ctxIdxInc为2

  • 否则,则ctxIdxInc为1

可以看出ref_idx_l0/1和mvd_l0/1的ctxIdxInc推导较为负责,这是因为H.264中P帧和B帧的分块、预测模式较为复杂导致的。通过前人大量的统计,总结出这样的上下文划分方式比较有利于压缩。下一节笔者将介绍残差的CABAC熵编码。