Search::checkIntra()

/*
	計算CU在partSize下的最優幀內預測,得到其rdcost
	
	過程:
		1.設置partSize和predMode
		2.計算TUsize的上下限tuDepthRange[2]
		3.初始化cost
		4.分析當前CU的最優幀內預測模式,並累計當前CU的total_distortion = luma_distortion + chroma_distortion
		5.重置bits
		6.若旁路trans和quan,則編碼TransquantBypassFlag
		7.若非Islice,則編碼skipFlag和predMode
		8.編碼partSize和predInfo
		9.得到編碼幀內預測信息的mv_bits = predMode + partSize + predInfo
		10.編碼殘差係數
		11.保存熵編碼上下文
		12.得到編碼CU的總bits開銷all_bits
		13.計算energy
		14.計算rdcost = total_distortion + lambda * all_bits
*/
void Search::checkIntra(Mode& intraMode, const CUGeom& cuGeom, PartSize partSize)
{
    CUData& cu = intraMode.cu;

	//設置partSize
    cu.setPartSizeSubParts(partSize);
	//設置predMode爲intra
	cu.setPredModeSubParts(MODE_INTRA);

	//得到TU的深度範圍[tuDepthRange[0],tuDepthRange[1]]
    uint32_t tuDepthRange[2];
    cu.getIntraTUQtDepthRange(tuDepthRange, 0);

	//初始化cost
    intraMode.initCosts();
	//計算當前CU的最優幀內預測模式,並累計其distortion
    intraMode.lumaDistortion += estIntraPredQT(intraMode, cuGeom, tuDepthRange);

	//若有色度,則計算CU色度的最優幀內預測模式,並累加上色度的distortion
    if (m_csp != X265_CSP_I400)
    {
        intraMode.chromaDistortion += estIntraPredChromaQT(intraMode, cuGeom);
        intraMode.distortion += intraMode.lumaDistortion + intraMode.chromaDistortion;
    }
	//若無色度則只算上luma的distortion
    else
        intraMode.distortion += intraMode.lumaDistortion;

    cu.m_distortion[0] = intraMode.distortion;

	//重置bits
    m_entropyCoder.resetBits();

	//若旁路trans和quan,則編碼其flag
    if (m_slice->m_pps->bTransquantBypassEnabled)
        m_entropyCoder.codeCUTransquantBypassFlag(cu.m_tqBypass[0]);

    int skipFlagBits = 0;
	//若非Islice
    if (!m_slice->isIntra())
    {
		//編碼skipFlag
        m_entropyCoder.codeSkipFlag(cu, 0);
        //得到編碼skipFlag的bits開銷
		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開銷
    intraMode.mvBits = m_entropyCoder.getNumberOfWrittenBits() - skipFlagBits;

    bool bCodeDQP = m_slice->m_pps->bUseDQP;
	//編碼殘差係數
    m_entropyCoder.codeCoeff(cu, 0, bCodeDQP, tuDepthRange);
    //保存熵編碼上下文
	m_entropyCoder.store(intraMode.contexts);
	//得到編碼當前CU的總bits開銷
    intraMode.totalBits = m_entropyCoder.getNumberOfWrittenBits();
    //得到編碼當前CU係數的總bits開銷
	intraMode.coeffBits = intraMode.totalBits - intraMode.mvBits - skipFlagBits;
    const Yuv* fencYuv = intraMode.fencYuv;

	//計算energy
    if (m_rdCost.m_psyRd)
        intraMode.psyEnergy = m_rdCost.psyCost(cuGeom.log2CUSize - 2, fencYuv->m_buf[0], fencYuv->m_size, intraMode.reconYuv.m_buf[0], intraMode.reconYuv.m_size);
    else if(m_rdCost.m_ssimRd)
        intraMode.ssimEnergy = m_quant.ssimDistortion(cu, fencYuv->m_buf[0], fencYuv->m_size, intraMode.reconYuv.m_buf[0], intraMode.reconYuv.m_size, cuGeom.log2CUSize, TEXT_LUMA, 0);

	//計算殘差energy
    intraMode.resEnergy = primitives.cu[cuGeom.log2CUSize - 2].sse_pp(intraMode.fencYuv->m_buf[0], intraMode.fencYuv->m_size, intraMode.predYuv.m_buf[0], intraMode.predYuv.m_size);
	
	//計算intraMode的rdcost = distortion(fenc, recon) + lambda * all_bits
    updateModeCost(intraMode);
    checkDQP(intraMode, cuGeom);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章