av1编码--位于图像边界的超级块划分
目录3.2 位于图像边界的超级块划分3.2 位于图像边界的超级块划分在实际的视频编码过程中图像的宽度和高度可能不是 128 或 64 的整数倍这会导致图像的右侧和底部的超级块可能会超出图像的实际边界。为了解决这个问题当超级块的任何部分超出图像的底部或右侧边界时这些超级块被强制进行划分直到所有的编码像素块完全包含在图像的边界之内。在图 3-2 的示例中由于该图片的分辨率是 832×480因此当超级块大小是 128×128 时右侧和底部的超级块都超出了图像边界而当超级块大小是 64×64 时仅底部超级块超出了图像边界。对于这些超出图像边界的超级块AV1 标准会使用四叉树划分模式PARTITION_SPLIT或者长宽比为 1:2 的水平划分模式PARTITION_HORZ或者长宽比是 2:1 的垂直划分模式PARTITION_VERT强制对这些超级块进行划分。在超级块强制划分过程中如果生成的四叉树节点仍存在一部分区域位于图像边界之外那么该四叉树节点将继续被强制划分直到每个编码块的所有像素都位于图像边界内部。AV1 使用语法元素split_or_horz和split_or_vert表示每个四叉树节点的划分模式。具体来讲如果当前四叉树节点的左上角四叉树子节点超出了图像的底部边界那么 AV1 使用语法元素split_or_horz表示其划分模式。此时split_or_horz等于 0 表示使用划分模式PARTITION_HORZ划分当前节点否则表示使用划分模式PARTITION_SPLIT划分当前节点。如果当前四叉树节点的左上角四叉树子节点超出了图像的右侧边界那么 AV1 使用语法元素split_or_vert表示其划分模式。split_or_vert等于 0 表示使用PARTITION_VERT划分当前节点否则使用PARTITION_SPLIT划分当前节点。如果当前四叉树节点的左上角四叉树子节点既超出了图像的右侧边界又超出了图像的底部边界那么 AV1 使用划分模式PARTITION_SPLIT对该四叉树节点进行划分。此时不需要编码任何语法元素。假设变量r和c分别表示当前四叉树节点的行坐标和列坐标r和c均以 4 亮度像素为基本单位变量bSize表示四叉树节点的大小函数parse(symbol)是解析语法元素symbol的函数。那么 AV1 标准文档定义的编码块划分流程decode_partition如下所示根据 AV1 标准文档定义的编码块划分流程decode_partition如果当前四叉树节点仅仅超出了图像的底部边界但是没有超出图像的右侧边界那么当前节点的split_or_vert似乎在任何条件下都能被赋值为PARTITION_VERT而与当前节点所在图像内部区域的大小无关。但是根据笔者观察只有当四叉树节点所在图片内部区域正好可以通过划分模式PARTITION_VERT产生时该节点的split_or_vert才能被赋值为PARTITION_VERT否则该节点不能被正确解码。同理对于超出图像的右侧边界但是没有超出图像底部边界的超级块只有当四叉树节点所在图片内部区域正好可以通过划分模式PARTITION_HORZ产生时其split_or_horz才能被赋值为PARTITION_HORZ。图 3-7 为图像边界处的超级块划分示意图。在图 3-7 中图片分辨率是 832×480超级块的尺寸是 128×128。对于图 3-7 中的超级块 A/B/C/D 中的节点 1/2/3/4按照编码块划分函数decode_partition()的执行流程对应的语法元素取值可描述如下图3-7 图像边界处的超级块划分示意图对于图像底部边界处的超级块 A其所在图片内部区域的大小是 128×96。此时变量hasRows和hasCols均为 true所以编码器将使用语法元素partition来表示超级块 A 的划分状态。在这种情况下超级块 A 的语法元素partition只能等于PARTITION_SPLIT。这是因为如果语法元素partition等于其他值如PARTITION_HORZ超级块 A 的下方编码块所在图片内部区域的大小是 128×32而 AV1 解码器无法编码这种尺寸的编码块。当使用partitionPARTITION_SPLIT方式分割超级块 A 之后对于新生成的左下角四叉树节点 N变量hasCols均为 true而变量hasRows为 false所以编码器使用语法元素split_or_horz表示它的划分状态。由于其所在图片内部区域的大小是 64×32该区域可以通过PARTITION_HORZ来生成。因此节点 N 的split_or_horz可以被设置为PARTITION_HORZ也可以被设置为PARTITION_SPLIT。在这个示例中编码器把节点 N 的split_or_horz设置为PARTITION_HORZ生成了编码块 1。编码块 1 完全包含在图片内部并且不再进行划分。对于既超出图像底部边界又超出右侧边界的超级块 B其所在图片内部区域的大小是 64×96。此时变量hasCols均为 false而变量hasRows为 true。所以编码器使用语法元素split_or_vert表示超级块 B 的划分状态。由于 B 所在图片内部区域的大小是 64×96这个尺寸的区域无法通过划分模式PARTITION_VERT得到所以超级块 B 的语法元素split_or_vert只能等于PARTITION_SPLIT。对于新生成的左下角四叉树节点 M变量hasCols均为 true而变量hasRows为 false所以编码器使用语法元素split_or_horz表示它的划分状态。在这个示例中节点 M 的split_or_horz被设置为PARTITION_SPLIT进而得到节点 2。由于节点 2 完全包含在图片内部所以节点 2 将按照正常节点继续编码即使用语法元素partition来表示其划分模式。对于图像右侧边界处的超级块 C其所在图片内部区域的大小是 64×128。此时变量hasCols均为 false而变量hasRows为 true。所以编码器使用语法元素split_or_vert表示超级块 C 的划分状态。由于 C 所在图片内部区域的大小是 64×128这个尺寸的区域可以通过划分模式PARTITION_VERT得到所以超级块 C 的语法元素split_or_vert可以被设置为PARTITION_VERT也可以被设置为PARTITION_SPLIT。在这个示例中编码器把节点 C 的split_or_vert设置为PARTITION_VERT生成了编码块 3。编码块 3 完全包含在图片内部并且不再进行划分。对于图像底部和右侧边界处的超级块 D其所在图片内部区域的大小是 64×128。与超级块C类似变量hasCols均为false而变量hasRows均为 ture所以编码器将使用语法元素split_or_vert来表示超级块 D 的划分状态。在这个示例中超级块D的split_or_vert被设置为PARTITION_SPLIT从而得到节点4。由于节点4完全包含在图片内部所以节点4将按照正常节点继续编码即使用语法元素partition来表示其划分模式。