x265中compressIntraCU()分析(版本2.8)

一. 函数关系调用图: 

x265中compressIntraCU()分析(版本2.8)_第1张图片

二.  函数内容概括:

x265中compressIntraCU()分析(版本2.8)_第2张图片

三. 源码分析:

/*
 ========Analysed by:       yangxin
 ========Date:              2018.8
 ========Function:          compressItraCU()函数,帧内模式分析   full analysis for an I-slice CU
 ========    
*/
uint64_t Analysis::compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp)
{
    uint32_t depth = cuGeom.depth;//--CU的几何结构的深度,深度值范围[0,3]
    ModeDepth& md = m_modeDepth[depth];//--
    md.bestMode = NULL;

    bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);//----为ture非叶子节点,还需要继续分裂
    bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);//---为ture,!(CU split is mandatory if CU is inside frame and can be split)

    bool bAlreadyDecided = m_param->intraRefine != 4 && parentCTU.m_lumaIntraDir[cuGeom.absPartIdx] != (uint8_t)ALL_IDX;//--
    bool bDecidedDepth = m_param->intraRefine != 4 && parentCTU.m_cuDepth[cuGeom.absPartIdx] == depth;
    int split = 0;

    if (m_param->intraRefine && m_param->intraRefine != 4)//--帧内精细化且不等于4
    {
        split = m_param->scaleFactor && ((cuGeom.log2CUSize == (uint32_t)(g_log2Size[m_param->minCUSize] + 1)) && bDecidedDepth);
        if (cuGeom.log2CUSize == (uint32_t)(g_log2Size[m_param->minCUSize]) && !bDecidedDepth)
            bAlreadyDecided = false;
    }

    if (bAlreadyDecided)//--已经决策确定的模式
    {
        if (bDecidedDepth)//--已经确定的深度
        {
            Mode& mode = md.pred[0];
            md.bestMode = &mode;
            mode.cu.initSubCU(parentCTU, cuGeom, qp);//---initialize Sub partition
            bool reuseModes = !((m_param->intraRefine == 3) ||
                                (m_param->intraRefine == 2 && parentCTU.m_lumaIntraDir[cuGeom.absPartIdx] > DC_IDX));//--intraRefine=0/1
            if (reuseModes)
            {
                memcpy(mode.cu.m_lumaIntraDir, parentCTU.m_lumaIntraDir + cuGeom.absPartIdx, cuGeom.numPartitions);
                memcpy(mode.cu.m_chromaIntraDir, parentCTU.m_chromaIntraDir + cuGeom.absPartIdx, cuGeom.numPartitions);
            }
            checkIntra(mode, cuGeom, (PartSize)parentCTU.m_partSize[cuGeom.absPartIdx]);//-- full RD search of intra modes

            if (m_bTryLossless)
                tryLossless(cuGeom);//--无损编码

            if (mightSplit)
                addSplitFlagCost(*md.bestMode, cuGeom.depth);//--add the RD cost of coding a split flag (0 or 1) to the given mode
        }
    }
    else if (cuGeom.log2CUSize != MAX_LOG2_CU_SIZE && mightNotSplit)//---不需要再分裂,则不需要递归调用
    {
        md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);//---initialize Sub partition
        checkIntra(md.pred[PRED_INTRA], cuGeom, SIZE_2Nx2N);//===intra 2Nx2N模式
        checkBestMode(md.pred[PRED_INTRA], depth);

        if (cuGeom.log2CUSize == 3 && m_slice->m_sps->quadtreeTULog2MinSize < 3)//==CU的尺寸是8x8,即最小的CU对应的预测单元是NxN
        {
            md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom, qp);//---initialize Sub partition
            checkIntra(md.pred[PRED_INTRA_NxN], cuGeom, SIZE_NxN);//===intra NxN模式
            checkBestMode(md.pred[PRED_INTRA_NxN], depth);//---check whether current mode is the new best
        }

        if (m_bTryLossless)
            tryLossless(cuGeom);

        if (mightSplit)
            addSplitFlagCost(*md.bestMode, cuGeom.depth);
    }

    // stop recursion if we reach the depth of previous analysis decision//--达到先前分析决策的深度就停止递归
    mightSplit &= !(bAlreadyDecided && bDecidedDepth) || split; //--  a = a &(!(b&&c)||d)

    if (mightSplit)//继续分裂
    {
        Mode* splitPred = &md.pred[PRED_SPLIT];
        splitPred->initCosts();
        CUData* splitCU = &splitPred->cu;
        splitCU->initSubCU(parentCTU, cuGeom, qp);//--initialize Sub partition 4 x sub CU

        uint32_t nextDepth = depth + 1;
        ModeDepth& nd = m_modeDepth[nextDepth];
        invalidateContexts(nextDepth);
        Entropy* nextContext = &m_rqt[depth].cur;
        int32_t nextQP = qp;
        uint64_t curCost = 0;
        int skipSplitCheck = 0;

        for (uint32_t subPartIdx = 0; subPartIdx < 4; subPartIdx++)//---循环每个子CU,执行相同操作
        {
            const CUGeom& childGeom = *(&cuGeom + cuGeom.childOffset + subPartIdx);
            if (childGeom.flags & CUGeom::PRESENT)
            {
                m_modeDepth[0].fencYuv.copyPartToYuv(nd.fencYuv, childGeom.absPartIdx);
                m_rqt[nextDepth].cur.load(*nextContext);

                if (m_slice->m_pps->bUseDQP && nextDepth <= m_slice->m_pps->maxCuDQPDepth)
                    nextQP = setLambdaFromQP(parentCTU, calculateQpforCuSize(parentCTU, childGeom));

                if (m_param->bEnableSplitRdSkip)//--Enable skipping split RD analysis when sum of split CU rdCost larger than none split CU rdCost for Intra CU
                {
                    curCost += compressIntraCU(parentCTU, childGeom, nextQP);//==递归调用
                    if (m_modeDepth[depth].bestMode && curCost > m_modeDepth[depth].bestMode->rdCost)
                    {
                        skipSplitCheck = 1;
                        break;
                    }
                }
                else
                    compressIntraCU(parentCTU, childGeom, nextQP);//==递归调用

                // Save best CU and pred data for this sub CU //--对当前子CU保存最佳CU和预测数据
                splitCU->copyPartFrom(nd.bestMode->cu, childGeom, subPartIdx);//--Copy the results of a sub-part (split) CU to the parent CU 
                splitPred->addSubCosts(*nd.bestMode);//--
				//--Copy Small YUV buffer to the part of other Big YUV buffer
                nd.bestMode->reconYuv.copyToPartYuv(splitPred->reconYuv, childGeom.numPartitions * subPartIdx);
                nextContext = &nd.bestMode->contexts;
            }
            else
            {
                /* record the depth of this non-present sub-CU */
                splitCU->setEmptyPart(childGeom, subPartIdx);//--记录下这个非当前子CU的深度

                /* Set depth of non-present CU to 0 to ensure that correct CU is fetched as reference to code deltaQP */
                if (bAlreadyDecided)
                    memset(parentCTU.m_cuDepth + childGeom.absPartIdx, 0, childGeom.numPartitions);//--将非当前CU的所有4X4的深度都置0
            }
        }
        if (!skipSplitCheck)
        {
            nextContext->store(splitPred->contexts);
            if (mightNotSplit)
                addSplitFlagCost(*splitPred, cuGeom.depth);
            else
                updateModeCost(*splitPred);

            checkDQPForSplitPred(*splitPred, cuGeom);//---检测 deltas QP(残差QP)
            checkBestMode(*splitPred, depth);//---check whether current mode is the new best
        }
    }

    if (m_param->bEnableRdRefine && depth <= m_slice->m_pps->maxCuDQPDepth)//--只有在rd5\6才开启率失真精细化,默认关闭
    {
        int cuIdx = (cuGeom.childOffset - 1) / 3;
        cacheCost[cuIdx] = md.bestMode->rdCost;
    }

    if ((m_limitTU & X265_TU_LIMIT_NEIGH) && cuGeom.log2CUSize >= 4)//--log2CUSize范围是[3,6],对应的TU深度
    {
        CUData* ctu = md.bestMode->cu.m_encData->getPicCTU(parentCTU.m_cuAddr);//--
        int8_t maxTUDepth = -1;
        for (uint32_t i = 0; i < cuGeom.numPartitions; i++)
            maxTUDepth = X265_MAX(maxTUDepth, md.bestMode->cu.m_tuDepth[i]);
        ctu->m_refTuDepth[cuGeom.geomRecurId] = maxTUDepth;//--TU depth of CU at depths 0, 1 and 2
    }

    /* Copy best data to encData CTU and recon */
    md.bestMode->cu.copyToPic(depth);//--- Copy completed predicted CU to CTU in picture 
    if (md.bestMode != &md.pred[PRED_SPLIT])
        md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic, parentCTU.m_cuAddr, cuGeom.absPartIdx);//-- Copy YUV buffer to picture buffer

    return md.bestMode->rdCost;//--最好模式的cost作为返回值
}

 

你可能感兴趣的:(Audio,and,video)