H264的coded_block_pattern编码块模式
1 词汇约定
CodedBlockPatternLuma:一个宏块的亮度分量的coded_block_pattern
CodedBlockPatternChroma:一个宏块的色度分量的coded_block_pattern,Cb、Cr的CodedBlockPatternChroma相同。
宏块:一个 16X16 的亮度象素块和两个对应的色差象素块。
块:一个 MxN的象素数组(M列,N 行),或者一个 MxN 变换系数数组。
子宏块:一个宏块的1/4采样大小,即:对于有三个采样数组(即一个亮度分量两个色度分量比如YCbCr)的图像来说,
一个8x8的亮度块与两个的相应色度块,他们分别的一个角位于宏块的一个角,或者对于单色图像或每个分量单独编码的有
三个采样数组的图像(比如XYZ色彩格式)其一个8x8亮度块的一个角位于宏块的一个宏块的一个角。
2 coded_block_pattern
规定了一个宏块的4个8x8亮度子宏块(对于I_16x16是针对16个4x4块)与相关联的色度块中的哪些会包含非0变换系数。
3 chroma_format_idc
a)在单色采样中,仅存在一个采样阵列,其通常被认为是亮度阵列,没有色度阵列。
b)在4:2:0采样时,两个色度阵列中每一个的高度与宽度都是亮度阵列的一半,举例对于CIF:352x288,
其亮色阵列为352*288而两个色度阵列中的第一个都为176*144。
c) 在4:2:2采样时,两个色度阵列中每一个的高度等于亮度阵列的高度,其宽度等于亮度阵列的一半,
举例对于CIF:352x288,其亮色阵列为352*288而两个色度阵列中的第一个都为176*288。
d) 在4:4:4采样时,若separate_colour_plance_flag等于0表示色度阵列与亮度阵列的宽高是一样的,
否则也就是separate_colour_plance_flag等于1表示亮度陈列与两个色度阵列就像单色图像哪样分别单独编码,
即Y、Cb、Cr阵列都当成单色图像的采样阵列,然后按单色图像哪样编码。
e) chroma_format_idc如果在码流中不出现,其默认值为1即(4:2:0),separate_colour_plance_flag如果在码流中不出现默认值为0
5) ChromaArrayType
if (separate_colour_plance_flag == 0) ChromaArrayType = chroma_format_idc else ChromaArrayType = 1;
6) CodedBlockPatternLuma与CodedBlockPatternChroma
if (宏块预测模式为P_Skip、B_Skip、I_PCM) ;//不存在CodedBlockPatternLuma与CodedBlockPatternChroma else if (宏块预测模式为Intra_16x16) ;//CodedBlockPatternLuma与CodedBlockPatternChroma的值隐藏在宏块类型中, ;//举例对于I条带的宏块类型7,其名称为I_16x16_0_c_l,其中c表示CodedBlockPatternChroma,l表示CodedBlockPatternLuma。 else { //码流中会出现coded_block_pattern,这样: CodedBlockPatternLuma = coded_block_pattern % 16; CodedBlockPatternChroma = coded_block_pattern / 16; }
7 CodedBlockPatternLuma的语义
if (宏块预测模为Intra_16x16) { if (ChromaArrayType != 3) { if (CodedBlockPatternLuma == 0) { ;//一个宏块的亮度分量的AC变换系数都为0,即对于一个16x16的亮度块其16个4x4块亮度分量的AC变换系数都为0, ;//不需要传送给解码器,解码器将这个宏块的亮度分量的AC变换系统全用默认值0代替。 } else { ;//一个宏块的亮度分量至少有一个AC变换系数不为0,这时对这个16x16的亮度块的16个4x4块(的亮度分量的)AC变换系数 ;//都要被扫描,意味着AC变换系数需要编码进码流传送给解码器。 } } else //ChromaArrayType == 3 { if (CodedBlockPatternLuma == 0) { ;//一个宏块的亮度分量、两个色度分量的AC变换系数都为0,即对于一个16x16的亮度块、Cb色度块、Cr色度块 ;//其相应的16个4x4块亮度分量、Cb色度分量、Cr色度分量的AC变换系数都为0, ;//不需要传送给解码器,解码器将这个宏块的相应分量的AC变换系统全用默认值0代替。 } else { ;//一个宏块的亮度分量、两个色度分量至少有一个AC变换系数不为0,这时 ;//对这个16x16的亮度块、Cb色度块、Cr色度块的16个4x4块(相应的亮度分量或色度分量的) ;//AC变换系数都要被扫描,意味着AC变换系数需要编码进码流传送给解码器。 } } } else { if (ChromaArrayType != 3) { ;// CodedBlockPatternLuma低4位的每位按如下方式确定一个宏块的4个8x8块中的一个块的(编码模式) if (CodedBlockPatternLuma的低4位的某位等于0) { ;//相应8x8块的亮度变换块的所有变换系数都为0,不需要编码进码流,即不需要发送给解码器 } else { ;//相应8x8块的一个或多个亮度变换块(比如8x4)的一个或多个变换系数不为0,这时这个8x8块的所有亮度变换块的变换系数 ;//都要被扫描,需要编码进码流传送给解码器 } } else//ChromaArrayType ==3) { ;// CodedBlockPatternLuma低4位的每位按如下方式确定一个宏块的4个8x8块中的一个块的(编码模式) if (CodedBlockPatternLuma的低4位的某位等于0) { ;//相应8x8块的亮度、色度Cb、色度Cr变换块(比如8x4)的所有变换系数都为0,不需要编码进码流,即不需要发送给解码器 } else { ;//相应8x8块的一个或多个亮度、色度Cb、色度Cr变换块(比如8x4)的一个或多个变换系数不为0,这时这个8x8块的所有亮度、色度Cb、色度Cr变换块的变换系数 ;//都要被扫描,需要编码进码流传送给解码器 } } }
8 CodedBlockPatternChroma的语义
if (ChromaArrayType != 0 & ChromaArrayType != 3) { switch (CodedBlockPatternChroma) { case 0: ;//表示所有色度变换系统都等于0,不需要传送给解码器,解码器按协议将这些系数赋为0 break; case 1: ;//表示一个或多个色度DC变换系数不为0,而所有的色度AC变换系数都为0,需向解码器传送色度DC变换系数,不而传送色度AC变换系数 break; case 2: ;//表示零个或多个色度DC变换系数不为0,一个或多个DC变换系数不为0,需向解码器传送色度DC与AC变换系数 } } else //ChromaArrayType == 0 或 ChromaArrayType == 3 { ;//码流中不存在色度分量的编码模式表示,ChromaArrayType==0(单色图像或含有三个颜色分量的图像每个分量都按照单色图像这样独立编码)时,压跟没有颜色分量, ;// ChromaArrayType == 3 ,亮度编码模式的含义已经包括了色度分量的编码模式,见这里1,这里2,这样对于非Intra_16x16、I_PCM、P_Skip、B_Skip时传送 ;//的CodedBlockPattern由于不需要包括CodedBlockPatternChroma所以只需要4位范围的数即可表达,参见标准的me(v)解码过程 }