AV1视频编码位于图像边界的超级块划分

一 位于图像边界的超级块划分

在实际视频编码过程中给你图像宽度高度可能不是12864整数倍这会导致图像的右侧底部超级可能会超出图像实际边界为了解决这个问题超级任何部分超出图像底部右侧边界时这些超级强制进行划分直到所有编码像素块完全包含在图像边界之内在图3-2示例该图片分辨率832x480因此超级大小128x128右侧底部超级都超出图像边界超级大小64x64仅仅底部超级超出图像边界

这些超出图像边界超级AV1标准会使用四叉树划分模式PARTITION_SPLIT 或者长宽1:2水平划分模式PARTITION_HORZ或者长宽比2:1垂直划分模式PARTITION_VERT强制这些超级进行划分在超级强制划分过程中如果生四叉树节点存在一部分区域位于图像边界之外那么该四叉树节点继续强制划分直到每个编码块所有像素都位于图像边界内部AV1使用语法元素split_or_horzsplit_or_vert表示每个四叉树节点划分模式

1 如果当前四叉树节点左上角四叉树节点超出图像底部边界那么AV1使用语法元素split_or_horz 表示划分模式此时split_or_horz 等于0表示使用划分模式 PARTITION_HORZ划分当前节点否则表示使用划分模式PARTITION_SPLIT划分当前节点

2 如果当前四叉树节点左上角四叉树子节点超出图像右侧边界那么AV1使用于法元素split_or_vert 表示划分模式split_or_vert等于0表示使用PARTITION_VERT划分当前节点否则使用PARTITION_SPLIT划分当前节点

3 如果当前四叉树节点左上角四叉树子节点超出了图像右侧边界超出了图像底部边界那么AV1使用划分模式PARTITION_SPLIT对该四叉树节点进行划分此时不需要编码任何语法元素

假设变量rc分别表示当前四叉树节点坐标坐标rc4亮度像素基本单位变量bSize表示四叉树节点大小函数parse symbol 解析语法元素symbol函数那么AV1标准文档定义编码划分流程decode_partition如下所示

decode_partition(r, c, bSize) {
//如果当前四叉树节点起始行坐标r坐标c超过图片边界退出
    if (r >= MiRows || c >= MiCols)
        return 0;
    AvailU = is_inside(r - 1, c)
    AvailL = is_inside(r, c - 1)
    
    //根据当前四叉树节点尺寸bSize获取节点宽度
    num4x4 = Num_4x4_Blocks_Wide[bSize]
    //halfBlock4x4当前四叉树节点宽度一半quarterBlock4x4 宽度1/4
    halfBlock4x4 = num4x4 >> 1
    quarterBLock4x4 = halBlock4x4>>1
    //hasRowshasCols分别表示四叉树节点左上角四叉树子节点是否超过底部边界
    //右侧边界hasRowshasCols取值false表示超过图像边界
    hasRows = (r + halfBlock4x4) < MiRows
    hasCols = (c + halfBlock4x4) < MiCols
    if (bSize < BLOCK_8x8) {
    //尺寸bSize,小于8x8不需要继续分割
            partition = PARTITION_NONE
    } else if (hasRows && hasCols) {
    //左上角四叉树子节点位于图像内部解析语法元素parition
        parse(partition)
    } else if (hasCols) {
    //左上角四叉树子节点超过图像底部边界解析语法元素split_or_horz
    //据此partition进行赋值
        parse(split_or_horz)
        partition = split_or_horz ? PARTITION_SPLIT: PARTITION_HORZ
    } else if (hasRows) {
    //左上角四叉树子节点超过图像右侧边界解析语法元素split_or_horz
    //据此partition进行赋值
        parse(split_or_vert)
        partition = split_or_vert ? PARTITION_SPLIT: PARTITION_VERT
    } else {
    //左上角四叉树子节点同时超过图像底部右侧边界partition
    //赋值为PARTITION_SPLIT
        partition = PARTITION_SPLIT
    }
    subSize = Partition_SUbSize[partition][bSize]
    splitSize = Partition_Subsize[PARTITION_SPLIT][bSize]
    
    if (partition == PARTITION_NONE) {
    //当节点不再继续划分解码重构当前节点
        decode_block(r, c, subSize)
    } else if (partition == PARTITION_HORZ) {
    //解码重构上方编码块
        decode_block(r, c, subSize)
        //当下编码块位于图像内部解码重构下方编码
        if (hasRows) {
            decode_block(r + halfBlock4x4, c, subSize)
        }
    } else if (partition == PARTITION_VERT) {
    //解码重构左侧编码块
        decode_block(r, c, subSize)
        //右侧编码块位于图像内部解码重构右侧编码
        if (hasCols)
            decode_block(r, c + halfBlock4x4, subSize)
    } else if (partition == PARTITION_SPLIT) {
    //按照四叉树划分模式递归解码子节点
        decode_partition(r, c, subSize)
        decode_partition(r, c + halfBlock4x4, subSize)
        decode_partition(r + halfBlock4x4, c, subSize)
        decode_partition(r + halfBLock4x4, c + halfBlock4x4, subSize)
    } else if (partition == PARTITION_HORZ_A) {
    //解码重构上方两个方形编码块
        decode_block(r, c, splitSize)
        decode_block(r, c + halfBlock4x4, splitSize)
        //解码重构下方一个矩形编码块
        decode_block(r + halfBlock4x4, c, subSize)
    } else if (partition == PARTITION_HORZ_B) {
    //解码重构上方一个矩形编码
        decode_block(r, c, subSize)
        //解码下方两个方向编码块
        decode_block(r + halfBLock4x4, c, splitSize)
        decode_block(r + halfBLock4x4, c + halfBlock4x4, splitSize)
    } else if (partition == PARTITION_VERT_A) {
    //解码左侧两个方形编码块
        decode_block(r, c, splitSize)
        decode_block(r + halfBLock4x4, c, splitSize)
        //解码右侧一个矩形编码块
        decode_block(r, c + halfBlock4x4, subSize)
    } else if (partition == PARTITION_VERT_B) {
    //解码左侧一个方形编码
        decode_block(r, c, subSize)
        //解码右侧两个方形编码块
        decode_block(r, c + halfBlock4x4, splitSize)
        decode_block(r + halfBlock4x4, c + halfBlock4x4, splitSIze)
    } else if (partition == PARTITION_HORZ_4) {
        decode_block(r + quarterBlock4x4 * 0, c, subSize)
        decode_block(r + quarterBlock4x4 * 1, c, subSize)
        decode_block(r + quarterBlock4x4 * 2, c, subSize)
        //当最后一个编码块位于图像内部解码重构最后一个编码块
        if (r + quarterBlock4x4 * 3 < MiRows)
            decode_block(r + quarterBlock4x4 * 3, c, subSize)
    } else {
        decode_block(r + quarterBlock4x4 * 0, c, subSize)
        decode_block(r + quarterBlock4x4 * 1, c, subSize)
        decode_block(r + quarterBlock4x4 * 2, c, subSize)
        //当最后一个编码块位于内部时解码重构最后一个编码块
        if (c + quarterBlock4x4 * 3 < MiCols)
            decode_block(r, c + quarterBlock4x4 * 3, subSize)
    }
}

根据AV1标准文档定义编码块划分流程decode_partition, 如果当前四叉树节点仅仅超出了图像底部边界但是没有超出图像右侧边界那么当前节点split_or_vert似乎任何条件都能赋值PARTITION_VERT当前所有节点在图像内部区域大小无关只有四叉树节点所在图片内部正好可以通过划分模式

PARTITION_VERT产生节点split_or_vert才能赋值PARTITION_VERT否则节点不能被正确解码对于超出图像的右侧边界但是没有超出图像底部边界超级只有四叉树节点所在图片内部区域正好可以通过划分模式PARTITION_HORZ产生时split_or_horz才能被赋值PARTITION_HORZ 3-7图像边界超级划分示意图

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值