Search::encodeResAndCalcRd[Skip/Inter]CU()

Search::encodeResAndCalcRdSkipCU()

/* Note: this function overwrites the RD cost variables of interMode, but leaves the sa8d cost unharmed 
   计算interMode为skip mode时的rdcost

   过程:
		1.计算luma+chroma的distiortion
		2.计算skipFlag+mergeIdx的bits开销,skip模式无残差bits开销。
		3.更新energe和rdcost
		4.保存熵编码上下文
*/
void Search::encodeResAndCalcRdSkipCU(Mode& interMode)
{
	//取interMode的CUData
    CUData& cu = interMode.cu;
	//取interMode的reconYUV、fencYUV、predYUV
    Yuv* reconYuv = &interMode.reconYuv;
    const Yuv* fencYuv = interMode.fencYuv;
    Yuv* predYuv = &interMode.predYuv;
    X265_CHECK(!cu.isIntra(0), "intra CU not expected\n");
	//得到当前CU的深度
    uint32_t depth  = cu.m_cuDepth[0];

    // No residual coding : SKIP mode

	//设置CU为skip
    cu.setPredModeSubParts(MODE_SKIP);
	//清空cbf
    cu.clearCbf();
    //设置TU深度
	cu.setTUDepthSubParts(0, 0, depth);
	//将interMode的预测YUV拷贝给recon
    reconYuv->copyFromYuv(interMode.predYuv);

    // 计算Luma的distortion
    int part = partitionFromLog2Size(cu.m_log2CUSize[0]);
    interMode.lumaDistortion = primitives.cu[part].sse_pp(fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size);
    interMode.distortion = interMode.lumaDistortion;
    // 若有色度,则累加上Chroma的distortion
    if (m_csp != X265_CSP_I400 && m_frame->m_fencPic->m_picCsp != X265_CSP_I400)
    {
        interMode.chromaDistortion = m_rdCost.scaleChromaDist(1, primitives.chroma[m_csp].cu[part].sse_pp(fencYuv->m_buf[1], fencYuv->m_csize, reconYuv->m_buf[1], reconYuv->m_csize));
        interMode.chromaDistortion += m_rdCost.scaleChromaDist(2, primitives.chroma[m_csp].cu[part].sse_pp(fencYuv->m_buf[2], fencYuv->m_csize, reconYuv->m_buf[2], reconYuv->m_csize));
        interMode.distortion += interMode.chromaDistortion;
    }
    cu.m_distortion[0] = interMode.distortion;
    
	//加载熵编码上下文
	m_entropyCoder.load(m_rqt[depth].cur);
	//重置bits
    m_entropyCoder.resetBits();
    if (m_slice->m_pps->bTransquantBypassEnabled)
        m_entropyCoder.codeCUTransquantBypassFlag(cu.m_tqBypass[0]);
	//编码skipFlag
    m_entropyCoder.codeSkipFlag(cu, 0);
	//得到skipFlag的bits开销
    int skipFlagBits = m_entropyCoder.getNumberOfWrittenBits();
	//编码merge备选集索引
    m_entropyCoder.codeMergeIndex(cu, 0);
	//得到merge备选集索引开销
    interMode.mvBits = m_entropyCoder.getNumberOfWrittenBits() - skipFlagBits;
	//skip无系数开销
    interMode.coeffBits = 0;
	//总开销 = mv开销 + merge备选集索引开销
    interMode.totalBits = interMode.mvBits + skipFlagBits;
	//更新psy/ssim能量
    if (m_rdCost.m_psyRd)
        interMode.psyEnergy = m_rdCost.psyCost(part, fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size);
    else if(m_rdCost.m_ssimRd)
        interMode.ssimEnergy = m_quant.ssimDistortion(cu, fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size, cu.m_log2CUSize[0], TEXT_LUMA, 0);
	//更新残差能量
    interMode.resEnergy = primitives.cu[part].sse_pp(fencYuv->m_buf[0], fencYuv->m_size, predYuv->m_buf[0], predYuv->m_size);
    //更新rdcost
	updateModeCost(interMode);
	//保持上下文
    m_entropyCoder.store(interMode.contexts);
}

Search::encodeResAndCalcRdInterCU()

/* encode residual and calculate rate-distortion for a CU block.
 * Note: this function overwrites the RD cost variables of interMode, but leaves the sa8d cost unharmed 
 * 为CU编码残差并计算rdcost。该函数可能重写rdcost,但不会改变sa8d cost 
  
	过程:
		1.取interMode的CUData、reconYUV、fencYUV、predYUV、resiYUV以及当前CU深度depth
		2.根据fencYUV和predYUV计算resiYUV,即resiYUV = fencYUV - predYUV
		3.加载熵编码上下文
		4.对残差resiYUV进行编码并得到cost
		5.若不允许transform-quantization旁路,则计算cbf = 0时候的rdcost
			1.计算cbf = 0时候的distortion
			2.计算cbf = 0时候的bits
			3.根据distortion和bits得到cbf = 0时候的rdcost
			4.若cbf = 0时的rdcost<有残差时候的rdcost,则设置cbf = 0
		6.若cbf != 0,也就是有残差,则保存残差数据
		7.编码TransquantBypassFlag
		8.计算bits
			·若是skip,则bits = SkipFlag + MergeIndex
			·若非skip,则bits = SkipFlag + PredMode + PartSize + PredInfo + Coeff
		9.恢复reconYUV,即reconYUV = predYUV + resiYUV
		10.更新interMode的distortion
		11.更新interMode的energy、bits、rdcost
 */
void Search::encodeResAndCalcRdInterCU(Mode& interMode, const CUGeom& cuGeom)
{
    ProfileCUScope(interMode.cu, interRDOElapsedTime[cuGeom.depth], countInterRDO[cuGeom.depth]);

	//取interMode的cu
    CUData& cu = interMode.cu;
	//取interMode的recon、pred、enc YUV
    Yuv* reconYuv = &interMode.reconYuv;
    Yuv* predYuv = &interMode.predYuv;
	const Yuv* fencYuv = interMode.fencYuv;
	//取当前CU的depth
    uint32_t depth = cuGeom.depth;
	//取残差YUV
    ShortYuv* resiYuv = &m_rqt[depth].tmpResiYuv;

    X265_CHECK(!cu.isIntra(0), "intra CU not expected\n");

    uint32_t log2CUSize = cuGeom.log2CUSize;
    int sizeIdx = log2CUSize - 2;

	//计算残差YUV,即resiYuv = fencYuv - predYuv
    resiYuv->subtract(*fencYuv, *predYuv, log2CUSize, m_frame->m_fencPic->m_picCsp);

    uint32_t tuDepthRange[2];
    cu.getInterTUQtDepthRange(tuDepthRange, 0);

	//加载熵编码上下文
    m_entropyCoder.load(m_rqt[depth].cur);

    if ((m_limitTU & X265_TU_LIMIT_DFS) && !(m_limitTU & X265_TU_LIMIT_NEIGH))
        m_maxTUDepth = -1;
    else if (m_limitTU & X265_TU_LIMIT_BFS)
        memset(&m_cacheTU, 0, sizeof(TUInfoCache));

	/*
		计算残差值并得到cost
	*/
    Cost costs;
    if (m_limitTU & X265_TU_LIMIT_NEIGH)
    {
        /* Save and reload maxTUDepth to avoid changing of maxTUDepth between modes */
        int32_t tempDepth = m_maxTUDepth;
        if (m_maxTUDepth != -1)
        {
            uint32_t splitFlag = interMode.cu.m_partSize[0] != SIZE_2Nx2N;
            uint32_t minSize = tuDepthRange[0];
            uint32_t maxSize = tuDepthRange[1];
            maxSize = X265_MIN(maxSize, cuGeom.log2CUSize - splitFlag);
            m_maxTUDepth = x265_clip3(cuGeom.log2CUSize - maxSize, cuGeom.log2CUSize - minSize, (uint32_t)m_maxTUDepth);
        }
        estimateResidualQT(interMode, cuGeom, 0, 0, *resiYuv, costs, tuDepthRange);
        m_maxTUDepth = tempDepth;
    }
    else
        estimateResidualQT(interMode, cuGeom, 0, 0, *resiYuv, costs, tuDepthRange);

	//是否旁路transform和quantization,即无损编码
    uint32_t tqBypass = cu.m_tqBypass[0];
	//若不旁路,则有损
    if (!tqBypass)
    {
		/*
			计算cbf = 0时候的distortion
		*/
        sse_t cbf0Dist = primitives.cu[sizeIdx].sse_pp(fencYuv->m_buf[0], fencYuv->m_size, predYuv->m_buf[0], predYuv->m_size);
        //若有色度,则累加chroma的失真
		if (m_csp != X265_CSP_I400 && m_frame->m_fencPic->m_picCsp != X265_CSP_I400)
        {
            cbf0Dist += m_rdCost.scaleChromaDist(1, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[1], predYuv->m_csize, predYuv->m_buf[1], predYuv->m_csize));
            cbf0Dist += m_rdCost.scaleChromaDist(2, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[2], predYuv->m_csize, predYuv->m_buf[2], predYuv->m_csize));
        }

        /* Consider the RD cost of not signaling any residual 
			计算cbf = 0时候的bits开销	*/
		//加载熵编码上下文
        m_entropyCoder.load(m_rqt[depth].cur);
		//重置bits
        m_entropyCoder.resetBits();
		//cbf为0时,进行编码
        m_entropyCoder.codeQtRootCbfZero();
		//得到cbf为0时的bits开销
        uint32_t cbf0Bits = m_entropyCoder.getNumberOfWrittenBits();

		/*
			根据distortion和bits计算energy和rdcost
		*/
        uint32_t cbf0Energy; uint64_t cbf0Cost;
        if (m_rdCost.m_psyRd)
        {
            cbf0Energy = m_rdCost.psyCost(log2CUSize - 2, fencYuv->m_buf[0], fencYuv->m_size, predYuv->m_buf[0], predYuv->m_size);
            cbf0Cost = m_rdCost.calcPsyRdCost(cbf0Dist, cbf0Bits, cbf0Energy);
        }
        else if(m_rdCost.m_ssimRd)
        {
            cbf0Energy = m_quant.ssimDistortion(cu, fencYuv->m_buf[0], fencYuv->m_size, predYuv->m_buf[0], predYuv->m_size, log2CUSize, TEXT_LUMA, 0);
            cbf0Cost = m_rdCost.calcSsimRdCost(cbf0Dist, cbf0Bits, cbf0Energy);
        }
        else
            cbf0Cost = m_rdCost.calcRdCost(cbf0Dist, cbf0Bits);

		//若cbf = 0时候的rdcost < 有残差的rdcost,则cbf置0
        if (cbf0Cost < costs.rdcost)
        {
            cu.clearCbf();
            cu.setTUDepthSubParts(0, 0, depth);
        }
    }

	//若cbf!=0,则保存残差数据
    if (cu.getQtRootCbf(0))
        saveResidualQTData(cu, *resiYuv, 0, 0);

    /* calculate signal bits for inter/merge/skip coded CU */
	//加载熵编码上下文
    m_entropyCoder.load(m_rqt[depth].cur);
	//重置bits
    m_entropyCoder.resetBits();
    if (m_slice->m_pps->bTransquantBypassEnabled)
        m_entropyCoder.codeCUTransquantBypassFlag(tqBypass);

	/*
		计算bits
	*/
    uint32_t coeffBits, bits, mvBits;
	//若是merge,且2Nx2N,且CBF = 0,则是skip模式
    if (cu.m_mergeFlag[0] && cu.m_partSize[0] == SIZE_2Nx2N && !cu.getQtRootCbf(0))
    {
		//设置为skip模式
        cu.setPredModeSubParts(MODE_SKIP);

        /* Merge/Skip */
        coeffBits = mvBits = 0;
		//编码skipFlag
        m_entropyCoder.codeSkipFlag(cu, 0);
        //得到skipFlag的bits开销
		int skipFlagBits = m_entropyCoder.getNumberOfWrittenBits();
        //编码mergeIdx
		m_entropyCoder.codeMergeIndex(cu, 0);
        //得到mergeIdx的bits开销
		mvBits = m_entropyCoder.getNumberOfWrittenBits() - skipFlagBits;
		//总计skip模式下的bits总开销
        bits = mvBits + skipFlagBits;
    }
	//若非skip模式下
    else
    {
		//编码skipFlag
        m_entropyCoder.codeSkipFlag(cu, 0);
        //得到skipFlag的bits开销
		int skipFlagBits = m_entropyCoder.getNumberOfWrittenBits();
		//编码PredMode
        m_entropyCoder.codePredMode(cu.m_predMode[0]);
        //编码partSize
		m_entropyCoder.codePartSize(cu, 0, cuGeom.depth);
		//编码PredInfo
        m_entropyCoder.codePredInfo(cu, 0);
		//得到PredMode/partSize/PredInfo的bits总开销
        mvBits = m_entropyCoder.getNumberOfWrittenBits() - skipFlagBits;

		//是否DQP
        bool bCodeDQP = m_slice->m_pps->bUseDQP;
		//编码coeff
        m_entropyCoder.codeCoeff(cu, 0, bCodeDQP, tuDepthRange);
        //得到coeff的bits开销
		bits = m_entropyCoder.getNumberOfWrittenBits();
        coeffBits = bits - mvBits - skipFlagBits;
    }
	//保存熵编码上下文
    m_entropyCoder.store(interMode.contexts);

	/*
		得到reconYUV,用于后续计算distortion
	*/
    if (cu.getQtRootCbf(0)) //若有cbf,则reconYUV = predYUV+resiYUV
        reconYuv->addClip(*predYuv, *resiYuv, log2CUSize, m_frame->m_fencPic->m_picCsp);
    else //若无cbf,则reconYUV = predYUV
        reconYuv->copyFromYuv(*predYuv);

    /* 
	   update with clipped distortion and cost (qp estimation loop uses unclipped values)
       记录luma和chroma的distortion
	 */
	//记录interMode的Luma最优distortion
	sse_t bestLumaDist = primitives.cu[sizeIdx].sse_pp(fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size);
    interMode.distortion = bestLumaDist;
    //若有色度,则记录interMode的chroma最优distortion
	if (m_csp != X265_CSP_I400 && m_frame->m_fencPic->m_picCsp != X265_CSP_I400)
    {
        sse_t bestChromaDist = m_rdCost.scaleChromaDist(1, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[1], fencYuv->m_csize, reconYuv->m_buf[1], reconYuv->m_csize));
        bestChromaDist += m_rdCost.scaleChromaDist(2, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[2], fencYuv->m_csize, reconYuv->m_buf[2], reconYuv->m_csize));
        interMode.chromaDistortion = bestChromaDist;
        interMode.distortion += bestChromaDist;
    }

	//记录energy
    if (m_rdCost.m_psyRd)
        interMode.psyEnergy = m_rdCost.psyCost(sizeIdx, fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size);
    else if(m_rdCost.m_ssimRd)
        interMode.ssimEnergy = m_quant.ssimDistortion(cu, fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size, cu.m_log2CUSize[0], TEXT_LUMA, 0);
    interMode.resEnergy = primitives.cu[sizeIdx].sse_pp(fencYuv->m_buf[0], fencYuv->m_size, predYuv->m_buf[0], predYuv->m_size);
    
	/*
		记录interMode的totalBits/lumaDistortion/coeffBits/mvBits/distortion
	*/
	interMode.totalBits = bits;
    interMode.lumaDistortion = bestLumaDist;
    interMode.coeffBits = coeffBits;
    interMode.mvBits = mvBits;
    cu.m_distortion[0] = interMode.distortion;

	//更新interMode的rdcost
    updateModeCost(interMode);
    checkDQP(interMode, cuGeom);
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值