JEM學習:candidateSearch

這個函數是幀間進行KL變換之前,在插值圖像中找到當前塊的預測塊的相似塊 

關鍵函數

candidateSearch()函數調用了searchCandidateFromOnePicInteger();

searchCandidateFromOnePicInteger()調用了xSetSearchRange();

下面依次註釋:

candidateSearch()

Void TComTrQuant::candidateSearch(TComDataCU *pcCU, UInt uiPartAddr, UInt uiBlkSize, UInt uiTempSize)
{
    ComponentID compID = COMPONENT_Y;
    UInt uiPatchSize = uiBlkSize + uiTempSize;
    UInt uiTarDepth = g_aucConvertToBit[uiBlkSize];
    Pel **tarPatch = m_pppTarPatch[uiTarDepth];
    Int      iRefIdx[2] = { -1, -1 };
#if !VCEG_AZ08_INTER_KLT_MV_BUGFIXED
    TComMv      cMvs[2];
#endif
    UInt uiTargetCandiNum = g_uiDepth2MaxCandiNum[uiTarDepth];
    const Int channelBitDepth = pcCU->getSlice()->getSPS()->getBitDepth(toChannelType(compID));
    //Initialize the library for saving the best candidates
    m_tempLibFast.initDiff(uiPatchSize, channelBitDepth, uiTargetCandiNum);
    Short setId = -1; //to record the reference picture.

    Int iCurrPOC = pcCU->getPic()->getPOC();
    Int iRefPOC = 0;
    TComMv cMvRef;

    Int iRefPOCs[2] = { 0, 0 };
    TComMv      cMvRefs[2];
    cMvRefs[0].setZero();
    cMvRefs[1].setZero();
    Int filledNum = 0;
    for (Int iRefList = 0; iRefList < 2; iRefList++)
    {
        RefPicList eRefPicList = (iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
        iRefIdx[eRefPicList] = pcCU->getCUMvField(eRefPicList)->getRefIdx(uiPartAddr);
        if (iRefIdx[eRefPicList] >= 0)
        {
#if VCEG_AZ08_INTER_KLT_MV_BUGFIXED
            cMvRefs[filledNum] = pcCU->getCUMvField(eRefPicList)->getMv(uiPartAddr);
#else
            cMvRefs[filledNum] = cMvs[eRefPicList];
#endif
            iRefPOCs[filledNum] = pcCU->getSlice()->getRefPic(eRefPicList, iRefIdx[eRefPicList])->getPOC();
            filledNum++;
        }
    }

    //for other reference frames not related with prediction
    for (Int iRefList = 0; iRefList < 2; iRefList++)
    {
        RefPicList eRefPicList = (iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
        for (Int iRefIdxTemp = 0; iRefIdxTemp < pcCU->getSlice()->getNumRefIdx(eRefPicList); iRefIdxTemp++)
        {
            TComMv   cMv;
            Int iTargetPOC = pcCU->getSlice()->getRefPic(eRefPicList, iRefIdxTemp)->getPOC();
            Int minDistancePOC = MAX_INT;
            Int distance;
            //use the reference frame (having mvs) with nearest distacne from the current iTargetPOC 
            for (Int filledId = 0; filledId < filledNum; filledId++)
            {
                distance = abs(iRefPOCs[filledId] - iTargetPOC);
                if (distance < minDistancePOC)
                {
                    minDistancePOC = distance;
                    iRefPOC = iRefPOCs[filledId];
                    cMvRef = cMvRefs[filledId];
                }
            }

            Double dScale = ((Double)(iCurrPOC - iTargetPOC) / (Double)(iCurrPOC - iRefPOC));
            cMv.set((Short)(cMvRef.getHor()*dScale + 0.5), (Short)(cMvRef.getVer()*dScale + 0.5));
            if (eRefPicList == REF_PIC_LIST_1)
            {
                //check whether the reference frames in list1 had appeared in list0, if so, will not use it to find candidates.
                bool bSimilarSearchRegion = false;
                for (Int iRefIdxList0 = 0; iRefIdxList0 < pcCU->getSlice()->getNumRefIdx(REF_PIC_LIST_0); iRefIdxList0++)
                {
                    UInt prevPicPOCList0 = pcCU->getSlice()->getRefPic(eRefPicList, iRefIdxList0)->getPOC();
                    if (prevPicPOCList0 == iTargetPOC)
                    {
                        bSimilarSearchRegion = true;
                        break; //had appeared in list0 for this reference in list1
                    }
                }
                if (bSimilarSearchRegion)
                {
                    continue;
                }
            }
/***************************************************************************************/
            //get參考幀首地址*refPic
            TComPic* refPic = pcCU->getSlice()->getRefPic(eRefPicList, iRefIdxTemp);
            UInt uiRow = 0;
            UInt uiCol = 0;

            //get重建參考幀
            //uiRow = 0uiCol = 0表示重建參考幀;
            //uiRow = 1,0uiCol = 0表示水平方向進行1/4插值後的參考幀
            //uiRow = 0,0uiCol = 1表示水平方向進行1/4插值後的參考幀,以此類推
            TComPicYuv *refPicRec = refPic->getPicQuaYuvRec(uiRow, uiCol);

            //get當前塊在當前幀位置,並找出同樣位置在參考幀中的地址
            //即找出當前幀和參考幀同位PU的位置
            Pel *ref = refPicRec->getAddr(compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiPartAddr);

            setId++;
            setRefPicUsed(setId, ref); //to facilitate the access of each candidate point 
            setRefPicBuf(setId, refPic);
            setStride(refPicRec->getStride(compID));
            searchCandidateFromOnePicInteger(pcCU, uiPartAddr, refPicRec, cMv, tarPatch, uiPatchSize, uiTempSize, setId);
        }
    }

    Short setIdFraStart = setId + 1;
    RecordPosition(uiTargetCandiNum);
    searchCandidateFraBasedOnInteger(pcCU, tarPatch, uiPatchSize, uiTempSize, uiPartAddr, setIdFraStart);
}

 searchCandidateFromOnePicInteger()

Void TComTrQuant::searchCandidateFromOnePicInteger(TComDataCU *pcCU, UInt uiPartAddr, TComPicYuv *refPic, TComMv  cMv, Pel **tarPatch, UInt uiPatchSize, UInt uiTempSize, UInt setId)
{
    const ComponentID compID = COMPONENT_Y;
    UInt uiBlkSize = uiPatchSize - uiTempSize;
    UInt uiTarDepth = g_aucConvertToBit[uiBlkSize];
    UInt uiTargetCandiNum = g_uiDepth2MaxCandiNum[uiTarDepth];
    UInt  uiLibSizeMinusOne = uiTargetCandiNum - 1;
    m_uiPartLibSize = uiTargetCandiNum;

    Int *pX = m_tempLibFast.getX();
    Int *pY = m_tempLibFast.getY();
    DistType *pDiff = m_tempLibFast.getDiff();
    Short *pId = m_tempLibFast.getId();

    Int  refStride = refPic->getStride(compID);        
    //同位PU
    Pel  *ref = refPic->getAddr(compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiPartAddr);

    Int      iSrchRng = SEARCHRANGE;
    TComMv  cMvSrchRngLT;
    TComMv  cMvSrchRngRB;
    //設置加上搜索範圍之後,當前塊和預測值,在當前幀和未插值的參考幀中的整數位移
    xSetSearchRange(pcCU, cMv, iSrchRng, cMvSrchRngLT, cMvSrchRngRB);

    Int mvYMin = cMvSrchRngLT.getVer();
    Int mvYMax = cMvSrchRngRB.getVer();

    Int mvXMin = cMvSrchRngLT.getHor();
    Int mvXMax = cMvSrchRngRB.getHor();

    //search
    //在未插值參考幀中的搜索起點*refMove
    Pel *refMove = ref + mvYMin*refStride + mvXMin;
    DistType *pDiffEnd = &pDiff[uiLibSizeMinusOne];

    DistType diff;
    for (Int iYOffset = mvYMin; iYOffset <= mvYMax; iYOffset++)
    {
        Pel *refCurr = refMove;
        for (Int iXOffset = mvXMin; iXOffset <= mvXMax; iXOffset++)
        {
            //The position of the leftup pixel within this block: refCurr = ref + iYOffset*refStride + iXOffset;
            diff = calcPatchDiff(refCurr, refStride, tarPatch, uiPatchSize, uiTempSize, *pDiffEnd);
            refCurr++;
            if (diff > 0 && diff < (*pDiffEnd))//when residual is zero, may not contribute to the distribution.
            {
                insertNode(diff, iXOffset, iYOffset, pDiff, pX, pY, pId, uiLibSizeMinusOne, setId);
            }
        }
        refMove += refStride;
    }
}

xSetSearchRange()

Void TComTrQuant::xSetSearchRange(TComDataCU* pcCU, TComMv& cMvPred, Int iSrchRng, TComMv& rcMvSrchRngLT, TComMv& rcMvSrchRngRB)
{
    Int  iMvShift = 2;
#if VCEG_AZ08_INTER_KLT_MV_BUGFIXED
#if VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE
    iMvShift += VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE;
#endif
#endif
    
    //需要注意的是,cTmpMvPred對應1/4插值後的運動向量
    TComMv cTmpMvPred = cMvPred;
    pcCU->clipMv(cTmpMvPred);

    //iSrchRng對應1/4插值之後範圍
    rcMvSrchRngLT.setHor(cTmpMvPred.getHor() - (iSrchRng << iMvShift));
    rcMvSrchRngLT.setVer(cTmpMvPred.getVer() - (iSrchRng << iMvShift));

    rcMvSrchRngRB.setHor(cTmpMvPred.getHor() + (iSrchRng << iMvShift));
    rcMvSrchRngRB.setVer(cTmpMvPred.getVer() + (iSrchRng << iMvShift));
    pcCU->clipMv(rcMvSrchRngLT);
    pcCU->clipMv(rcMvSrchRngRB);
        
    //運動矢量值向右移動2位,即保留除4後的整數部分。
    //此時的運動矢量爲當前塊和預測塊,在當前幀和未插值的參考幀中的整數位移
    rcMvSrchRngLT >>= iMvShift;
    rcMvSrchRngRB >>= iMvShift;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章