x265代码分析scanPosLast_c函数

static int scanPosLast_c(const uint16_t *scan, const coeff_t *coeff, uint16_t *coeffSign, uint16_t *coeffFlag, uint8_t *coeffNum, int numSig, const uint16_t* /*scanCG4x4*/, const int /*trSize*/)
{
    memset(coeffNum, 0, MLS_GRP_NUM * sizeof(*coeffNum));
    memset(coeffFlag, 0, MLS_GRP_NUM * sizeof(*coeffFlag));
    memset(coeffSign, 0, MLS_GRP_NUM * sizeof(*coeffSign));

    int scanPosLast = 0;
    do
    {
        const uint32_t cgIdx = (uint32_t)scanPosLast >> MLS_CG_SIZE;

        const uint32_t posLast = scan[scanPosLast++];

        const int curCoeff = coeff[posLast];
        const uint32_t isNZCoeff = (curCoeff != 0); //是否为非零系数
        // get L1 sig map
        // NOTE: the new algorithm is complicated, so I keep reference code here
        //uint32_t posy   = posLast >> log2TrSize;
        //uint32_t posx   = posLast - (posy << log2TrSize);
        //uint32_t blkIdx0 = ((posy >> MLS_CG_LOG2_SIZE) << codingParameters.log2TrSizeCG) + (posx >> MLS_CG_LOG2_SIZE);
        //const uint32_t blkIdx = ((posLast >> (2 * MLS_CG_LOG2_SIZE)) & ~maskPosXY) + ((posLast >> MLS_CG_LOG2_SIZE) & maskPosXY);
        //sigCoeffGroupFlag64 |= ((uint64_t)isNZCoeff << blkIdx);
        numSig -= isNZCoeff; //非零系数减1

        // TODO: optimize by instruction BTS
        coeffSign[cgIdx] += (uint16_t)(((uint32_t)curCoeff >> 31) << coeffNum[cgIdx]); //
        coeffFlag[cgIdx] = (coeffFlag[cgIdx] << 1) + (uint16_t)isNZCoeff;//
        coeffNum[cgIdx] += (uint8_t)isNZCoeff; //非零系数个数
    }
    while (numSig > 0);
    return scanPosLast - 1;
}

前三个语句初始化了三个数组,

该函数遍历CG系数组从第一个非零系数到最后一个非零系数,同时统计了TB块中的sig_coeff_flag语法元素(表示当前位置上的系数是否为0),coeff_sign_flag语法元素(用于表示非零系数是正值还是负值)和非零系数的数目,分别记录在coeffFlag, coeffSign, coeffNum数组中。

通过这个函数可以推断出x265对系数位置的表示,以对角扫描威力,首先因为它是从CG系数组中的最后一恶搞系数开始统计的,所以scanPosLast = 0表示的位置就是左上角的位置。

在看之前提到的scan参量,该数组所存储的对于8x8对焦萨摩顺序的数据为。

{ 0, 8, 1, 16, 9, 2, 24, 17, 10, 3, 25, 18, 11, 26, 19, 27, 32, 40, 33, 48, 41, 34, 56, 49, 42, 35, 57, 50, 43, 58, 51, 59, 4, 12, 5, 20, 13, 6, 28, 21, 14, 7, 29, 22, 15, 30, 23, 31, 36, 44, 37, 52, 45, 38, 60, 53, 46, 39, 61, 54, 47, 62, 55, 63 }

因此,未扫描钱, TB中的变换系数是从左上角开始,向右,逐行向下进行标序的。scanPosLast也是对CG中系数位置的特殊表述。

回到函数中,do循环就是遍历的过程,scanPosLast >> MLS_CG_SIZE 4,除16,表示当前系数所在的CG块,

根据前面所述,posLast变量就表示扫描当前系数在TB中的位置,curCoeff就存储该系数的值,

isNZCoeff = (curCoeff != 0) 判断该系数是否为非零系数,numSig 存储的是剩余非零系数个数。

coeffSign[cgIdx] += (uint16_t)((uint32_t)curCoeff >> 31) << coeffNum[cgIdx];

先将curCoeff右移31位,取出符号位,再左移当前所记录的非零系数数目,添加进数组中,可见数组中的一个数表示一个CG,其中有16位数,分别表示cg中16个数的coeff_sign_flag值,TB中位置靠前的再低位。

coeffFlag[cgIdx] = (coeffFlag[cgIdx] << 1) + (uint16_t)isNZCoeff;

采用同样的存储方法,但是在该数组中,TB中位置靠前的在高位,coeffNum就不用说了,最后scanPosLast - 1对应循环中的scanPosLast++, 返回正确值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值