Analysis::checkInter_rd[0_4/5_6]()

Analysis::checkInter_rd0_4()和Analysis::checkInter_rd5_6()函数高度相似,唯一的不同在其确定了CU中每个PU的最优预测后,计算当前CU的rdcost的方式

  • Analysis::checkInter_rd0_4()的计算方式是
  1. 计算fencYUV和predYUV计算distortion
  2. 计算interMode的bits = block_mode_bits + mvp_idx_bits + refIdx_bits + mvd_bits
  3. 通过distortion和bits计算rdcost
  • Analysis::checkInter_rd5_6()的计算方式是通过调用encodeResAndCalcRdInterCU()函数计算得到的
  1. 得到resiYUV = fencYUV - predYUV ,初始化上下文,并对残差进行变换、量化、编码,以及反量化、反变换来重建编码帧
  2. 计算bits = SkipFlag_bits + MergeIndex_bits
    或bits = SkipFlag_bits + PredMode_bits + PartSize_bits + PredInfo_bits + Coeff_bits
  3. 得到reconYUV,计算reconYUV和fencYUV的distortion
  4. 通过distortion和bits计算rdcost

也就是说,rdlevel5-6相比0-4,在计算distortion和bits上更加严谨,rdlevel0-4是的distortion和bits只是一个估算,而rdlevel5-6将所有的编码流程全部走完了,包括上下文初始化、对残差的编码、重建编码帧,严谨的计算distortion和bits

Analysis::checkInter_rd0_4()

/*
	计算rdlevel0~4下,当前CU在partSize划分下的最优预测(即每个PU的帧间预测信息),及其rdcost

	过程:
		1.初始化该预测模式下的cost
		2.设置partSize、设置predMode
		3.得到预测的方向个数
		4.若analysisLoad,则从m_reuseRef中载入refIdx
		5.若analysisMultiPassRefine,则从m_reuseRef、m_reuseMv及m_reuseMvpIdx中载入refIdx、MV及mvpIdx
		6.针对CU下的每个PU,得到其最佳帧间预测,即mergeFlag,mvpIdx,refIdx,mvd以及bits信息
		7.取原始YUV即预测的YUV,计算其distortion
		8.根据6中得到的bits和7中得到的distortion,计算其rdcost
		9.若analysisSave,则将6中得到的ref存储回m_reuseRef
*/
void Analysis::checkInter_rd0_4(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, uint32_t refMask[2])
{
	//初始化interMode的cost
    interMode.initCosts();
	//设置partSize
    interMode.cu.setPartSizeSubParts(partSize);
	//设置pred mode
    interMode.cu.setPredModeSubParts(MODE_INTER);
	//单向预测 双向预测?
    int numPredDir = m_slice->isInterP() ? 1 : 2;

	//若analysisLoad && m_reuseInterDataCTU && analysisReuseLevel > 1 && analysisReuseLevel != 10,则从m_reuseRef载入ref
    if (m_param->analysisLoad && m_reuseInterDataCTU && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10)
    {
		//计算当前CU的ref在m_reuseRef存储的偏移量
        int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2;
        int index = 0;

		//得到当前CU的PU个数
        uint32_t numPU = interMode.cu.getNumPartInter(0);
		//针对每一个PU的每一个预测方向,载入其ref
        for (uint32_t part = 0; part < numPU; part++)
        {
            MotionData* bestME = interMode.bestME[part];
            for (int32_t i = 0; i < numPredDir; i++)
                bestME[i].ref = m_reuseRef[refOffset + index++];
        }
    }

	//若analysisMultiPassRefine && bStatRead && m_reuseInterDataCTU
    if (m_param->analysisMultiPassRefine && m_param->rc.bStatRead && m_reuseInterDataCTU)
    {
		//得到PU个数
        uint32_t numPU = interMode.cu.getNumPartInter(0);
		//针对每一个PU
        for (uint32_t part = 0; part < numPU; part++)
        {
            MotionData* bestME = interMode.bestME[part];
			//针对每个预测方向,载入ref,mv,mvpIdx到bestME中
            for (int32_t i = 0; i < numPredDir; i++)
            {
                int* ref = &m_reuseRef[i * m_frame->m_analysisData.numPartitions * m_frame->m_analysisData.numCUsInFrame];
          
				bestME[i].ref = ref[cuGeom.absPartIdx];
                bestME[i].mv = m_reuseMv[i][cuGeom.absPartIdx].word;
                bestME[i].mvpIdx = m_reuseMvpIdx[i][cuGeom.absPartIdx];
            }
        }
    }

	//对CU的每一个PU都进行最优帧间预测决定,得到每个PU的mergeFlag,mvpIdx,refIdx,mvd等,并累加上其bits
    predInterSearch(interMode, cuGeom, m_bChromaSa8d && (m_csp != X265_CSP_I400 && m_frame->m_fencPic->m_picCsp != X265_CSP_I400), refMask);

    /* predInterSearch sets interMode.sa8dBits */

	//取原始的YUV和预测的YUV
    const Yuv& fencYuv = *interMode.fencYuv;
    Yuv& predYuv = interMode.predYuv;

    int part = partitionFromLog2Size(cuGeom.log2CUSize);
    //计算luma的distortion
	interMode.distortion = primitives.cu[part].sa8d(fencYuv.m_buf[0], fencYuv.m_size, predYuv.m_buf[0], predYuv.m_size);
    //若有色度且m_bChromaSa8d,则累加chroma的distortion
	if (m_bChromaSa8d && (m_csp != X265_CSP_I400 && m_frame->m_fencPic->m_picCsp != X265_CSP_I400))
    {
        interMode.distortion += primitives.chroma[m_csp].cu[part].sa8d(fencYuv.m_buf[1], fencYuv.m_csize, predYuv.m_buf[1], predYuv.m_csize);
        interMode.distortion += primitives.chroma[m_csp].cu[part].sa8d(fencYuv.m_buf[2], fencYuv.m_csize, predYuv.m_buf[2], predYuv.m_csize);
    }
	//根据distortion和bits计算rdcost
    interMode.sa8dCost = m_rdCost.calcRdSADCost((uint32_t)interMode.distortion, interMode.sa8dBits);

	//若analysisSave && m_reuseInterDataCTU && analysisReuseLevel>1,则将计算得到的ref存储到m_reuseRef中
    if (m_param->analysisSave && m_reuseInterDataCTU && m_param->analysisReuseLevel > 1)
    {
		//找到当前CU在m_reuseRef中的偏移量
        int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2;
        int index = 0;
		//取CU的PU个数
        uint32_t numPU = interMode.cu.getNumPartInter(0);
		//针对每一个PU的每一个预测方向,将其ref存储回m_reuseRef中
        for (uint32_t puIdx = 0; puIdx < numPU; puIdx++)
        {
            MotionData* bestME = interMode.bestME[puIdx];
            for (int32_t i = 0; i < numPredDir; i++)
                m_reuseRef[refOffset + index++] = bestME[i].ref;
        }
    }
}

Analysis::checkInter_rd5_6()

/*
	计算rdlevel5~6下,当前CU在partSize划分下的最优预测(即每个PU的帧间预测信息),及其rdcost

	过程:
		1.初始化该预测模式下的cost
		2.设置partSize、设置predMode
		3.得到预测的方向个数
		4.若analysisLoad,则从m_reuseRef中载入refIdx
		5.若analysisMultiPassRefine,则从m_reuseRef、m_reuseMv及m_reuseMvpIdx中载入refIdx、MV及mvpIdx
		6.针对CU下的每个PU,得到其最佳帧间预测,即mergeFlag,mvpIdx,refIdx,mvd以及bits信息
		7.为当前CU进行残差编码,并计算rdcost
		8.若analysisSave,则将6中得到的ref存储回m_reuseRef
*/
void Analysis::checkInter_rd5_6(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, uint32_t refMask[2])
{
	//初始化cost
    interMode.initCosts();
    //设置partSize
	interMode.cu.setPartSizeSubParts(partSize);
    //设置predMode
	interMode.cu.setPredModeSubParts(MODE_INTER);
	//得到预测方向的个数
    int numPredDir = m_slice->isInterP() ? 1 : 2;

	//若analysisLoad && m_reuseInterDataCTU && analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10,则从m_reuseRef载入ref
    if (m_param->analysisLoad && m_reuseInterDataCTU && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10)
    {
		//计算当前CU的ref在m_reuseRef存储的偏移量
        int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2;
        int index = 0;

		//得到当前CU的PU个数
        uint32_t numPU = interMode.cu.getNumPartInter(0);
		//针对每一个PU的每一个预测方向,载入其ref
        for (uint32_t puIdx = 0; puIdx < numPU; puIdx++)
        {
            MotionData* bestME = interMode.bestME[puIdx];
            for (int32_t i = 0; i < numPredDir; i++)
                bestME[i].ref = m_reuseRef[refOffset + index++];
        }
    }

	//若analysisMultiPassRefine && bStatRead && m_reuseInterDataCTU
    if (m_param->analysisMultiPassRefine && m_param->rc.bStatRead && m_reuseInterDataCTU)
    {
		//得到PU个数
        uint32_t numPU = interMode.cu.getNumPartInter(0);
		//针对每一个PU
        for (uint32_t part = 0; part < numPU; part++)
        {
            MotionData* bestME = interMode.bestME[part];
			//针对每个预测方向,载入ref,mv,mvpIdx到bestME中
            for (int32_t i = 0; i < numPredDir; i++)
            {
                int* ref = &m_reuseRef[i * m_frame->m_analysisData.numPartitions * m_frame->m_analysisData.numCUsInFrame];
                bestME[i].ref = ref[cuGeom.absPartIdx];
                bestME[i].mv = m_reuseMv[i][cuGeom.absPartIdx].word;
                bestME[i].mvpIdx = m_reuseMvpIdx[i][cuGeom.absPartIdx];
            }
        }
    }

	对CU的每一个PU都进行最优帧间预测决定,得到每个PU的mergeFlag,mvpIdx,refIdx,mvd等,并累加上其bits
    predInterSearch(interMode, cuGeom, m_csp != X265_CSP_I400 && m_frame->m_fencPic->m_picCsp != X265_CSP_I400, refMask);

    /* predInterSearch sets interMode.sa8dBits, but this is ignored */
	//为当前CU进行残差编码,并计算rdcost
    encodeResAndCalcRdInterCU(interMode, cuGeom);

	//若analysisSave && m_reuseInterDataCTU && analysisReuseLevel>1,则将计算得到的ref存储到m_reuseRef中
    if (m_param->analysisSave && m_reuseInterDataCTU && m_param->analysisReuseLevel > 1)
    {
		//找到当前CU在m_reuseRef中的偏移量
        int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2;
        int index = 0;
		//取CU的PU个数
        uint32_t numPU = interMode.cu.getNumPartInter(0);
		//针对每一个PU的每一个预测方向,将其ref存储回m_reuseRef中
        for (uint32_t puIdx = 0; puIdx < numPU; puIdx++)
        {
            MotionData* bestME = interMode.bestME[puIdx];
            for (int32_t i = 0; i < numPredDir; i++)
                m_reuseRef[refOffset + index++] = bestME[i].ref;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值