Search::checkIntraInInter()

/* Note that this function does not save the best intra prediction, it must
 * be generated later. It records the best mode in the cu 
	找到最优帧内预测方向,DC?PNANAR?angle2~34?并记录最优帧内预测方向的sa8d、bits和cost 

	过程:
		1.设置partSize为2Nx2N,predMode为intra
		2.加载neighbor可用参考信息
		3.对neighbor参考像素进行填充,并平滑滤波
		4.若TU大小为64x64,则将其收缩到32x32,为什么要这么做?
		5.进行DC预测计算,得到sa8d、bits、cost开销,初始化为最优帧内预测bestMode
		6.进行PLANAR预测计算,得到sa8d、bits、cost开销,更新最优帧内预测bestMode
		7.进行angle2~34预测计算
			·若开启快速帧内预测方向决定
				1.在5、10、15、20、25、30里面根据cost选择最优mode1
				2.在最优mode1的±2个角度之内选择最优mode2
				3.若最优mode2=33,则再计算下角度34,选择最优mode3
				4.更新最优帧内预测bestMode
			·否则,遍历angle2~34进行预测计算,更新最优帧内预测bestMode
		8.记录下最优帧内预测bestMode及其sa8d、bits和cost
 */
void Search::checkIntraInInter(Mode& intraMode, const CUGeom& cuGeom)
{
    ProfileCUScope(intraMode.cu, intraAnalysisElapsedTime, countIntraAnalysis);

    CUData& cu = intraMode.cu;
    uint32_t depth = cuGeom.depth;
	//设置partSize为2Nx2N
    cu.setPartSizeSubParts(SIZE_2Nx2N);
    //设置predMode为intra
	cu.setPredModeSubParts(MODE_INTRA);

    const uint32_t initTuDepth = 0;
    uint32_t log2TrSize = cuGeom.log2CUSize - initTuDepth;
    uint32_t tuSize = 1 << log2TrSize;
    const uint32_t absPartIdx = 0;

    // Reference sample smoothing 初始化向量宏块像素
    IntraNeighbors intraNeighbors;
	//得到相邻CU的可用信息
    initIntraNeighbors(cu, absPartIdx, initTuDepth, true, &intraNeighbors);
    //对相邻CU的参考像素进行平滑滤波预处理
	initAdiPattern(cu, cuGeom, absPartIdx, intraNeighbors, ALL_IDX);

	//原始YUV及其stride
    const pixel* fenc = intraMode.fencYuv->m_buf[0];
    uint32_t stride = intraMode.fencYuv->m_size;

    int sad, bsad;
    uint32_t bits, bbits, mode, bmode;
    uint64_t cost, bcost;

    // 33 Angle modes once
    int scaleTuSize = tuSize;
    int scaleStride = stride;
    int costShift = 0;
    int sizeIdx = log2TrSize - 2;

    if (tuSize > 32)	//若tu的大小为64x64
    {
        // CU is 64x64, we scale to 32x32 and adjust required parameters
		//将64x64伸缩成32x32
        primitives.scale2D_64to32(m_fencScaled, fenc, stride);
        fenc = m_fencScaled;

        pixel nScale[129];
		//将为filter的neighbor像素拷贝
        intraNeighbourBuf[1][0] = intraNeighbourBuf[0][0];
        primitives.scale1D_128to64[NONALIGNED](nScale + 1, intraNeighbourBuf[0] + 1);

        // we do not estimate filtering for downscaled samples
        memcpy(&intraNeighbourBuf[0][1], &nScale[1], 2 * 64 * sizeof(pixel));   // Top & Left pixels
        memcpy(&intraNeighbourBuf[1][1], &nScale[1], 2 * 64 * sizeof(pixel));

        scaleTuSize = 32;
        scaleStride = 32;
        costShift = 2;
        sizeIdx = 5 - 2; // log2(scaleTuSize) - 2
    }

    pixelcmp_t sa8d = primitives.cu[sizeIdx].sa8d;
    int predsize = scaleTuSize * scaleTuSize;

    m_entropyCoder.loadIntraDirModeLuma(m_rqt[depth].cur);

    /* there are three cost tiers for intra modes:
     *  pred[0]          - mode probable, least cost
     *  pred[1], pred[2] - less probable, slightly more cost
     *  non-mpm modes    - all cost the same (rbits) */
    uint64_t mpms;
    uint32_t mpmModes[3];
	//计算mpms映射和三个mpmModes,得到未命中mpm时候的bits开销
    uint32_t rbits = getIntraRemModeBits(cu, absPartIdx, mpmModes, mpms);

    /* 进行DC预测计算 */
	//DC预测,输出到m_intraPredAngs
    primitives.cu[sizeIdx].intra_pred[DC_IDX](m_intraPredAngs, scaleStride, intraNeighbourBuf[0], 0, (scaleTuSize <= 16));
    //计算sa8d
	bsad = sa8d(fenc, scaleStride, m_intraPredAngs, scaleStride) << costShift;
    //存储mode
	bmode = mode = DC_IDX;
    //计算bits
	bbits = (mpms & ((uint64_t)1 << mode)) ? m_entropyCoder.bitsIntraModeMPM(mpmModes, mode) : rbits;
    //计算rdcost = sa8d + lambda * mode_bits,计算的比较粗略
	bcost = m_rdCost.calcRdSADCost(bsad, bbits);

	/* 进行PLANAR预测计算 */
    pixel* planar = intraNeighbourBuf[0];
    if (tuSize & (8 | 16 | 32))
        planar = intraNeighbourBuf[1];
	//进行PLANAR预测
    primitives.cu[sizeIdx].intra_pred[PLANAR_IDX](m_intraPredAngs, scaleStride, planar, 0, 0);
    //计算sa8d
	sad = sa8d(fenc, scaleStride, m_intraPredAngs, scaleStride) << costShift;
    //存储mode
	mode = PLANAR_IDX;
    //计算bits
	bits = (mpms & ((uint64_t)1 << mode)) ? m_entropyCoder.bitsIntraModeMPM(mpmModes, mode) : rbits;
	//计算rdcost = sa8d + lambda * mode_bits,计算的比较粗略
	cost = m_rdCost.calcRdSADCost(sad, bits);

	/* 选择DC和PLANAR之间的较优,存储到bcost、bmode、bsad和bbits中 */
    COPY4_IF_LT(bcost, cost, bmode, mode, bsad, sad, bbits, bits);

    bool allangs = true;
	//若存在intra_pred_allangs函数,则通过其计算angle
    if (primitives.cu[sizeIdx].intra_pred_allangs)
    {
		//对CU进行转置
        primitives.cu[sizeIdx].transpose(m_fencTransposed, fenc, scaleStride);
		//进行33种angle预测计算,将它们输出到m_intraPredAngs中
        primitives.cu[sizeIdx].intra_pred_allangs(m_intraPredAngs, intraNeighbourBuf[0], intraNeighbourBuf[1], (scaleTuSize <= 16)); 
    }
    else
        allangs = false;

	/*
		定义angle预测计算函数 try_angle(angle)
	*/
#define TRY_ANGLE(angle) \
    if (allangs) { \
        if (angle < 18) \
            sad = sa8d(m_fencTransposed, scaleTuSize, &m_intraPredAngs[(angle - 2) * predsize], scaleTuSize) << costShift; \
        else \
            sad = sa8d(fenc, scaleStride, &m_intraPredAngs[(angle - 2) * predsize], scaleTuSize) << costShift; \
        bits = (mpms & ((uint64_t)1 << angle)) ? m_entropyCoder.bitsIntraModeMPM(mpmModes, angle) : rbits; \
        cost = m_rdCost.calcRdSADCost(sad, bits); \
    } else { \
        int filter = !!(g_intraFilterFlags[angle] & scaleTuSize); \
        primitives.cu[sizeIdx].intra_pred[angle](m_intraPredAngs, scaleTuSize, intraNeighbourBuf[filter], angle, scaleTuSize <= 16); \
        sad = sa8d(fenc, scaleStride, m_intraPredAngs, scaleTuSize) << costShift; \
        bits = (mpms & ((uint64_t)1 << angle)) ? m_entropyCoder.bitsIntraModeMPM(mpmModes, angle) : rbits; \
        cost = m_rdCost.calcRdSADCost(sad, bits); \
    }
	/*
		结束TRY_ANGLE(angle)函数定义
	*/

	//若使用intra快速决定
    if (m_param->bEnableFastIntra)
    {
        int asad = 0;
        uint32_t lowmode, highmode, amode = 5, abits = 0;
        uint64_t acost = MAX_INT64;

        /* pick the best angle, sampling at distance of 5 
			五个一跨度计算最优angle */
        for (mode = 5; mode < 35; mode += 5)
        {
            TRY_ANGLE(mode);
            COPY4_IF_LT(acost, cost, amode, mode, asad, sad, abits, bits);
        }

        /* refine best angle at distance 2, then distance 1 
			在之前五个一跨度计算的最优angle上下个计算两个angle,找到最优 */
        for (uint32_t dist = 2; dist >= 1; dist--)
        {
            lowmode = amode - dist;
            highmode = amode + dist;

			//下angle合法检查
            X265_CHECK(lowmode >= 2 && lowmode <= 34, "low intra mode out of range\n");
            //下angle预测计算
			TRY_ANGLE(lowmode);
            //更新最优
			COPY4_IF_LT(acost, cost, amode, lowmode, asad, sad, abits, bits);

			//上angle合法检查
            X265_CHECK(highmode >= 2 && highmode <= 34, "high intra mode out of range\n");
            //上angle预测计算
			TRY_ANGLE(highmode);
			//更新最优
            COPY4_IF_LT(acost, cost, amode, highmode, asad, sad, abits, bits);
        }

		//若最优angle为33,则尝试angle34。因为该算法无法到达angle34
        if (amode == 33)
        {
            TRY_ANGLE(34);
            COPY4_IF_LT(acost, cost, amode, 34, asad, sad, abits, bits);
        }

		//在DC、PLANR和angle间选择最优
        COPY4_IF_LT(bcost, acost, bmode, amode, bsad, asad, bbits, abits);
    }
	//若不使用intra快速决定,则所有angle全遍历
    else // calculate and search all intra prediction angles for lowest cost
    {
        for (mode = 2; mode < 35; mode++)
        {
            TRY_ANGLE(mode);
            COPY4_IF_LT(bcost, cost, bmode, mode, bsad, sad, bbits, bits);
        }
    }

	//记录最优预测方向
    cu.setLumaIntraDirSubParts((uint8_t)bmode, absPartIdx, depth + initTuDepth);
    //初始化intraMode的开销,并存储最优帧内预测方向的bits、sa8d以及cost
	intraMode.initCosts();
    intraMode.totalBits = bbits;
    intraMode.distortion = bsad;
    intraMode.sa8dCost = bcost;
    intraMode.sa8dBits = bbits;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值