<div dir="ltr">From 9d58aa88fc522dede32a12cc5a66342a0c3ee298 Mon Sep 17 00:00:00 2001<br>From: AnusuyaKumarasamy <<a href="mailto:anusuya.kumarasamy@multicorewareinc.com" target="_blank">anusuya.kumarasamy@multicorewareinc.com</a>><br>Date: Fri, 12 Jul 2024 16:28:14 +0530<br>Subject: [PATCH] Fix hash mismatch and temporal mvp issue<br><br>---<br> source/common/cudata.cpp    | 165 +++++++++++++++++++++++++++++-------<br> source/common/cudata.h      |   4 +-<br> source/encoder/analysis.cpp |   2 +-<br> source/encoder/dpb.cpp      |  24 +++++-<br> source/encoder/search.cpp   |   6 +-<br> 5 files changed, 165 insertions(+), 36 deletions(-)<br><br>diff --git a/source/common/cudata.cpp b/source/common/cudata.cpp<br>index 19281dee2..baa9be476 100644<br>--- a/source/common/cudata.cpp<br>+++ b/source/common/cudata.cpp<br>@@ -1712,28 +1712,61 @@ uint32_t CUData::getInterMergeCandidates(uint32_t absPartIdx, uint32_t puIdx, MV<br> }<br> <br> // Create the PMV list. Called for each reference index.<br>-int CUData::getPMV(InterNeighbourMV *neighbours, uint32_t picList, uint32_t refIdx, MV* amvpCand, MV* pmv) const<br>+int CUData::getPMV(InterNeighbourMV* neighbours, uint32_t picList, uint32_t refIdx, MV* amvpCand, MV* pmv, uint32_t puIdx, uint32_t absPartIdx) const<br> {<br>     MV directMV[MD_ABOVE_LEFT + 1];<br>     MV indirectMV[MD_ABOVE_LEFT + 1];<br>     bool validDirect[MD_ABOVE_LEFT + 1];<br>     bool validIndirect[MD_ABOVE_LEFT + 1];<br> <br>-    // Left candidate.<br>-    validDirect[MD_BELOW_LEFT]  = getDirectPMV(directMV[MD_BELOW_LEFT], neighbours + MD_BELOW_LEFT, picList, refIdx);<br>-    validDirect[MD_LEFT]        = getDirectPMV(directMV[MD_LEFT], neighbours + MD_LEFT, picList, refIdx);<br>-    // Top candidate.<br>-    validDirect[MD_ABOVE_RIGHT] = getDirectPMV(directMV[MD_ABOVE_RIGHT], neighbours + MD_ABOVE_RIGHT, picList, refIdx);<br>-    validDirect[MD_ABOVE]       = getDirectPMV(directMV[MD_ABOVE], neighbours + MD_ABOVE, picList, refIdx);<br>-    validDirect[MD_ABOVE_LEFT]  = getDirectPMV(directMV[MD_ABOVE_LEFT], neighbours + MD_ABOVE_LEFT, picList, refIdx);<br>-<br>-    // Left candidate.<br>-    validIndirect[MD_BELOW_LEFT]  = getIndirectPMV(indirectMV[MD_BELOW_LEFT], neighbours + MD_BELOW_LEFT, picList, refIdx);<br>-    validIndirect[MD_LEFT]        = getIndirectPMV(indirectMV[MD_LEFT], neighbours + MD_LEFT, picList, refIdx);<br>-    // Top candidate.<br>-    validIndirect[MD_ABOVE_RIGHT] = getIndirectPMV(indirectMV[MD_ABOVE_RIGHT], neighbours + MD_ABOVE_RIGHT, picList, refIdx);<br>-    validIndirect[MD_ABOVE]       = getIndirectPMV(indirectMV[MD_ABOVE], neighbours + MD_ABOVE, picList, refIdx);<br>-    validIndirect[MD_ABOVE_LEFT]  = getIndirectPMV(indirectMV[MD_ABOVE_LEFT], neighbours + MD_ABOVE_LEFT, picList, refIdx);<br>+#if ENABLE_MULTIVIEW<br>+    if (m_slice->m_param->numViews > 1)<br>+    {<br>+        // Left candidate.<br>+        if ((neighbours + MD_BELOW_LEFT)->isAvailable || (neighbours + MD_LEFT)->isAvailable)<br>+        {<br>+            validIndirect[MD_ABOVE_RIGHT] = validIndirect[MD_ABOVE] = validIndirect[MD_ABOVE_LEFT] = false;<br>+<br>+            validDirect[MD_BELOW_LEFT] = getDirectPMV(directMV[MD_BELOW_LEFT], neighbours + MD_BELOW_LEFT, picList, refIdx);<br>+            validDirect[MD_LEFT] = getDirectPMV(directMV[MD_LEFT], neighbours + MD_LEFT, picList, refIdx);<br>+<br>+            validIndirect[MD_BELOW_LEFT] = getIndirectPMV(indirectMV[MD_BELOW_LEFT], neighbours + MD_BELOW_LEFT, picList, refIdx);<br>+            validIndirect[MD_LEFT] = getIndirectPMV(indirectMV[MD_LEFT], neighbours + MD_LEFT, picList, refIdx);<br>+        }<br>+<br>+        // Top candidate.<br>+        validDirect[MD_ABOVE_RIGHT] = getDirectPMV(directMV[MD_ABOVE_RIGHT], neighbours + MD_ABOVE_RIGHT, picList, refIdx);<br>+        validDirect[MD_ABOVE] = getDirectPMV(directMV[MD_ABOVE], neighbours + MD_ABOVE, picList, refIdx);<br>+        validDirect[MD_ABOVE_LEFT] = getDirectPMV(directMV[MD_ABOVE_LEFT], neighbours + MD_ABOVE_LEFT, picList, refIdx);<br>+<br>+        // Top candidate.<br>+        if (!((neighbours + MD_BELOW_LEFT)->isAvailable || (neighbours + MD_LEFT)->isAvailable))<br>+        {<br>+            validDirect[MD_BELOW_LEFT] = validDirect[MD_LEFT] = validIndirect[MD_BELOW_LEFT] = validIndirect[MD_LEFT] = false;<br>+            validIndirect[MD_ABOVE_RIGHT] = getIndirectPMV(indirectMV[MD_ABOVE_RIGHT], neighbours + MD_ABOVE_RIGHT, picList, refIdx);<br>+            validIndirect[MD_ABOVE] = getIndirectPMV(indirectMV[MD_ABOVE], neighbours + MD_ABOVE, picList, refIdx);<br>+            validIndirect[MD_ABOVE_LEFT] = getIndirectPMV(indirectMV[MD_ABOVE_LEFT], neighbours + MD_ABOVE_LEFT, picList, refIdx);<br>+        }<br>+    }<br>+    else<br>+#endif<br>+    {<br>+        // Left candidate.<br>+        validDirect[MD_BELOW_LEFT] = getDirectPMV(directMV[MD_BELOW_LEFT], neighbours + MD_BELOW_LEFT, picList, refIdx);<br>+        validDirect[MD_LEFT] = getDirectPMV(directMV[MD_LEFT], neighbours + MD_LEFT, picList, refIdx);<br>+        // Top candidate.<br>+        validDirect[MD_ABOVE_RIGHT] = getDirectPMV(directMV[MD_ABOVE_RIGHT], neighbours + MD_ABOVE_RIGHT, picList, refIdx);<br>+        validDirect[MD_ABOVE] = getDirectPMV(directMV[MD_ABOVE], neighbours + MD_ABOVE, picList, refIdx);<br>+        validDirect[MD_ABOVE_LEFT] = getDirectPMV(directMV[MD_ABOVE_LEFT], neighbours + MD_ABOVE_LEFT, picList, refIdx);<br>+<br>+        // Left candidate.<br>+        validIndirect[MD_BELOW_LEFT] = getIndirectPMV(indirectMV[MD_BELOW_LEFT], neighbours + MD_BELOW_LEFT, picList, refIdx);<br>+        validIndirect[MD_LEFT] = getIndirectPMV(indirectMV[MD_LEFT], neighbours + MD_LEFT, picList, refIdx);<br>+        // Top candidate.<br>+        validIndirect[MD_ABOVE_RIGHT] = getIndirectPMV(indirectMV[MD_ABOVE_RIGHT], neighbours + MD_ABOVE_RIGHT, picList, refIdx);<br>+        validIndirect[MD_ABOVE] = getIndirectPMV(indirectMV[MD_ABOVE], neighbours + MD_ABOVE, picList, refIdx);<br>+        validIndirect[MD_ABOVE_LEFT] = getIndirectPMV(indirectMV[MD_ABOVE_LEFT], neighbours + MD_ABOVE_LEFT, picList, refIdx);<br>+    }<br> <br>     int num = 0;<br>     // Left predictor search<br>@@ -1781,22 +1814,75 @@ int CUData::getPMV(InterNeighbourMV *neighbours, uint32_t picList, uint32_t refI<br> <br>     // Get the collocated candidate. At this step, either the first candidate<br>     // was found or its value is 0.<br>-    if (m_slice->m_sps->bTemporalMVPEnabled && num < 2)<br>+#if ENABLE_MULTIVIEW<br>+    if (m_slice->m_param->numViews > 1)<br>+    {<br>+        if (m_slice->m_sps->bTemporalMVPEnabled && num < 2)<br>+        {<br>+            int refId = refIdx;<br>+            uint32_t absPartAddr = m_absIdxInCTU + absPartIdx;<br>+            uint32_t partIdxRB = deriveRightBottomIdx(puIdx);<br>+            bool isValid;<br>+<br>+            // co-located RightBottom temporal predictor (H)<br>+            int ctuIdx = -1;<br>+<br>+            // image boundary check<br>+            if (m_encData->getPicCTU(m_cuAddr)->m_cuPelX + g_zscanToPelX[partIdxRB] + UNIT_SIZE < m_slice->m_sps->picWidthInLumaSamples &&<br>+                m_encData->getPicCTU(m_cuAddr)->m_cuPelY + g_zscanToPelY[partIdxRB] + UNIT_SIZE < m_slice->m_sps->picHeightInLumaSamples)<br>+            {<br>+                uint32_t absPartIdxRB = g_zscanToRaster[partIdxRB];<br>+                uint32_t numUnits = s_numPartInCUSize;<br>+                bool bNotLastCol = lessThanCol(absPartIdxRB, numUnits - 1); // is not at the last column of CTU<br>+                bool bNotLastRow = lessThanRow(absPartIdxRB, numUnits - 1); // is not at the last row    of CTU<br>+<br>+                if (bNotLastCol && bNotLastRow)<br>+                {<br>+                    absPartAddr = g_rasterToZscan[absPartIdxRB + RASTER_SIZE + 1];<br>+                    ctuIdx = m_cuAddr;<br>+                }<br>+                else if (bNotLastCol)<br>+                    absPartAddr = g_rasterToZscan[(absPartIdxRB + 1) & (numUnits - 1)];<br>+                else if (bNotLastRow)<br>+                {<br>+                    absPartAddr = g_rasterToZscan[absPartIdxRB + RASTER_SIZE - numUnits + 1];<br>+                    ctuIdx = m_cuAddr + 1;<br>+                }<br>+                else // is the right bottom corner of CTU<br>+                    absPartAddr = 0;<br>+            }<br>+            if (ctuIdx >= 0 && getColMVP(neighbours[MD_COLLOCATED].mv[picList], refId, picList, ctuIdx, absPartAddr))<br>+                pmv[numMvc++] = amvpCand[num++] = neighbours[MD_COLLOCATED].mv[picList];<br>+            else<br>+            {<br>+                uint32_t partIdxCenter = deriveCenterIdx(puIdx);<br>+                uint32_t curCTUIdx = m_cuAddr;<br>+                if (getColMVP(neighbours[MD_COLLOCATED].mv[picList], refId, picList, curCTUIdx, partIdxCenter))<br>+                    pmv[numMvc++] = amvpCand[num++] = neighbours[MD_COLLOCATED].mv[picList];<br>+            }<br>+        }<br>+    }<br>+    else<br>+#endif<br>     {<br>-        int tempRefIdx = neighbours[MD_COLLOCATED].refIdx[picList];<br>-        if (tempRefIdx != -1)<br>+        if (m_slice->m_sps->bTemporalMVPEnabled && num < 2)<br>         {<br>-            uint32_t cuAddr = neighbours[MD_COLLOCATED].cuAddr[picList];<br>-            const Frame* colPic = m_slice->m_refFrameList[m_slice->isInterB() && !m_slice->m_colFromL0Flag][m_slice->m_colRefIdx];<br>-            const CUData* colCU = colPic->m_encData->getPicCTU(cuAddr);<br>+            int tempRefIdx = neighbours[MD_COLLOCATED].refIdx[picList];<br>+            if (tempRefIdx != -1)<br>+            {<br>+                uint32_t cuAddr = neighbours[MD_COLLOCATED].cuAddr[picList];<br>+                const Frame* colPic = m_slice->m_refFrameList[m_slice->isInterB() && !m_slice->m_colFromL0Flag][m_slice->m_colRefIdx];<br>+                const CUData* colCU = colPic->m_encData->getPicCTU(cuAddr);<br> <br>-            // Scale the vector<br>-            int colRefPOC = colCU->m_slice->m_refPOCList[tempRefIdx >> 4][tempRefIdx & 0xf];<br>-            int colPOC = colCU->m_slice->m_poc;<br>+                // Scale the vector<br>+                int colRefPOC = colCU->m_slice->m_refPOCList[tempRefIdx >> 4][tempRefIdx & 0xf];<br>+                int colPOC = colCU->m_slice->m_poc;<br> <br>-            int curRefPOC = m_slice->m_refPOCList[picList][refIdx];<br>-            int curPOC = m_slice->m_poc;<br>-            pmv[numMvc++] = amvpCand[num++] = scaleMvByPOCDist(neighbours[MD_COLLOCATED].mv[picList], curPOC, curRefPOC, colPOC, colRefPOC);<br>+                int curRefPOC = m_slice->m_refPOCList[picList][refIdx];<br>+                int curPOC = m_slice->m_poc;<br>+<br>+                pmv[numMvc++] = amvpCand[num++] = scaleMvByPOCDist(neighbours[MD_COLLOCATED].mv[picList], curPOC, curRefPOC, colPOC, colRefPOC);<br>+            }<br>         }<br>     }<br> <br>@@ -1822,7 +1908,7 @@ void CUData::getNeighbourMV(uint32_t puIdx, uint32_t absPartIdx, InterNeighbourM<br>     getInterNeighbourMV(neighbours + MD_ABOVE,      partIdxRT, MD_ABOVE);<br>     getInterNeighbourMV(neighbours + MD_ABOVE_LEFT, partIdxLT, MD_ABOVE_LEFT);<br> <br>-    if (m_slice->m_sps->bTemporalMVPEnabled)<br>+    if (m_slice->m_sps->bTemporalMVPEnabled && !(m_slice->m_param->numViews > 1))<br>     {<br>         uint32_t absPartAddr = m_absIdxInCTU + absPartIdx;<br>         uint32_t partIdxRB = deriveRightBottomIdx(puIdx);<br>@@ -1895,6 +1981,7 @@ void CUData::getInterNeighbourMV(InterNeighbourMV *neighbour, uint32_t partUnitI<br>         // Mark the PMV as unavailable.<br>         for (int i = 0; i < 2; i++)<br>             neighbour->refIdx[i] = -1;<br>+        neighbour->isAvailable = (tmpCU != NULL) && (tmpCU->isInter(idx));<br>         return;<br>     }<br> <br>@@ -1905,6 +1992,7 @@ void CUData::getInterNeighbourMV(InterNeighbourMV *neighbour, uint32_t partUnitI<br> <br>         // Get the reference idx.<br>         neighbour->refIdx[i] = tmpCU->m_refIdx[i][idx];<br>+        neighbour->isAvailable = (tmpCU != NULL) && (tmpCU->isInter(idx));<br>     }<br> }<br> <br>@@ -1958,8 +2046,18 @@ bool CUData::getIndirectPMV(MV& outMV, InterNeighbourMV *neighbours, uint32_t pi<br>             int neibRefPOC = m_slice->m_refPOCList[picList][partRefIdx];<br>             MV mvp = neighbours->mv[picList];<br> <br>+#if ENABLE_MULTIVIEW<br>+            if ((curRefPOC == curPOC) == (neibRefPOC == curPOC))<br>+            {<br>+                if (curRefPOC == curPOC)<br>+                    outMV = mvp;<br>+                if (!(curRefPOC == curPOC))<br>+                    outMV = scaleMvByPOCDist(mvp, curPOC, curRefPOC, neibPOC, neibRefPOC);<br>+#else<br>             outMV = scaleMvByPOCDist(mvp, curPOC, curRefPOC, neibPOC, neibRefPOC);<br>+#endif<br>             return true;<br>+            }<br>         }<br>     }<br>     return false;<br>@@ -1995,7 +2093,16 @@ bool CUData::getColMVP(MV& outMV, int& outRefIdx, int picList, int cuAddr, int p<br>     int curRefPOC = m_slice->m_refPOCList[picList][outRefIdx];<br>     int curPOC = m_slice->m_poc;<br> <br>+#if ENABLE_MULTIVIEW<br>+    if ((colPOC == colRefPOC) != (curPOC == curRefPOC))<br>+        return false;<br>+    else if (curRefPOC == curPOC)<br>+        outMV = colmv;<br>+    else if (!(curRefPOC == curPOC))<br>+        outMV = scaleMvByPOCDist(colmv, curPOC, curRefPOC, colPOC, colRefPOC);<br>+#else<br>     outMV = scaleMvByPOCDist(colmv, curPOC, curRefPOC, colPOC, colRefPOC);<br>+#endif;<br>     return true;<br> }<br> <br>diff --git a/source/common/cudata.h b/source/common/cudata.h<br>index 8397f0568..404e95714 100644<br>--- a/source/common/cudata.h<br>+++ b/source/common/cudata.h<br>@@ -107,6 +107,8 @@ struct InterNeighbourMV<br>     // Collocated right bottom CU addr.<br>     uint32_t cuAddr[2];<br> <br>+    bool isAvailable;<br>+<br>     // For spatial prediction, this field contains the reference index<br>     // in each list (-1 if not available).<br>     //<br>@@ -272,7 +274,7 @@ public:<br>     int8_t   getRefQP(uint32_t currAbsIdxInCTU) const;<br>     uint32_t getInterMergeCandidates(uint32_t absPartIdx, uint32_t puIdx, MVField (*candMvField)[2], uint8_t* candDir) const;<br>     void     clipMv(MV& outMV) const;<br>-    int      getPMV(InterNeighbourMV *neighbours, uint32_t reference_list, uint32_t refIdx, MV* amvpCand, MV* pmv) const;<br>+    int      getPMV(InterNeighbourMV* neighbours, uint32_t reference_list, uint32_t refIdx, MV* amvpCand, MV* pmv, uint32_t puIdx = 0, uint32_t absPartIdx = 0) const;<br>     void     getNeighbourMV(uint32_t puIdx, uint32_t absPartIdx, InterNeighbourMV* neighbours) const;<br>     void     getIntraTUQtDepthRange(uint32_t tuDepthRange[2], uint32_t absPartIdx) const;<br>     void     getInterTUQtDepthRange(uint32_t tuDepthRange[2], uint32_t absPartIdx) const;<br>diff --git a/source/encoder/analysis.cpp b/source/encoder/analysis.cpp<br>index aabf386ca..1f1984707 100644<br>--- a/source/encoder/analysis.cpp<br>+++ b/source/encoder/analysis.cpp<br>@@ -2501,7 +2501,7 @@ void Analysis::recodeCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t q<br>                                 continue;<br>                             MV mvp;<br> <br>-                            int numMvc = mode.cu.getPMV(mode.interNeighbours, list, ref, mode.amvpCand[list][ref], mvc);<br>+                            int numMvc = mode.cu.getPMV(mode.interNeighbours, list, ref, mode.amvpCand[list][ref], mvc, part, pu.puAbsPartIdx);<br>                             mvp = mode.amvpCand[list][ref][mode.cu.m_mvpIdx[list][pu.puAbsPartIdx]];<br>                             if (m_param->interRefine == 1)<br>                             {<br>diff --git a/source/encoder/dpb.cpp b/source/encoder/dpb.cpp<br>index 3b4934df5..a187e6657 100644<br>--- a/source/encoder/dpb.cpp<br>+++ b/source/encoder/dpb.cpp<br>@@ -287,9 +287,29 @@ void DPB::prepareEncode(Frame *newFrame)<br>         /* TODO: the lookahead should be able to tell which reference picture<br>          * had the least motion residual.  We should be able to use that here to<br>          * select a colocation reference list and index */<br>-        slice->m_colFromL0Flag = false;<br>+<br>+        bool bLowDelay = true;<br>+        int  iCurrPOC = slice->m_poc;<br>+        int iRefIdx = 0;<br>+<br>+        for (iRefIdx = 0; iRefIdx < slice->m_numRefIdx[0] && bLowDelay; iRefIdx++)<br>+        {<br>+            if (slice->m_refPOCList[0][iRefIdx] > iCurrPOC)<br>+            {<br>+                bLowDelay = false;<br>+            }<br>+        }<br>+        for (iRefIdx = 0; iRefIdx < slice->m_numRefIdx[1] && bLowDelay; iRefIdx++)<br>+        {<br>+            if (slice->m_refPOCList[1][iRefIdx] > iCurrPOC)<br>+            {<br>+                bLowDelay = false;<br>+            }<br>+        }<br>+<br>+        slice->m_bCheckLDC = bLowDelay;<br>+        slice->m_colFromL0Flag = bLowDelay;<br>         slice->m_colRefIdx = 0;<br>-        slice->m_bCheckLDC = false;<br>     }<br>     else<br>     {<br>diff --git a/source/encoder/search.cpp b/source/encoder/search.cpp<br>index 3218f4a24..9dc5f90c5 100644<br>--- a/source/encoder/search.cpp<br>+++ b/source/encoder/search.cpp<br>@@ -2092,7 +2092,7 @@ void Search::singleMotionEstimation(Search& master, Mode& interMode, const Predi<br> <br>     // 12 mv candidates including lowresMV<br>     MV  mvc[(MD_ABOVE_LEFT + 1) * 2 + 2];<br>-    int numMvc = interMode.cu.getPMV(interMode.interNeighbours, list, ref, interMode.amvpCand[list][ref], mvc);<br>+    int numMvc = interMode.cu.getPMV(interMode.interNeighbours, list, ref, interMode.amvpCand[list][ref], mvc, 0, pu.puAbsPartIdx);<br> <br>     const MV* amvp = interMode.amvpCand[list][ref];<br>     int mvpIdx = selectMVP(interMode.cu, pu, amvp, list, ref);<br>@@ -2246,7 +2246,7 @@ void Search::predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChroma<br>                 uint32_t bits = m_listSelBits[list] + MVP_IDX_BITS;<br>                 bits += getTUBits(ref, numRefIdx[list]);<br> <br>-                int numMvc = cu.getPMV(interMode.interNeighbours, list, ref, interMode.amvpCand[list][ref], mvc);<br>+                int numMvc = cu.getPMV(interMode.interNeighbours, list, ref, interMode.amvpCand[list][ref], mvc, puIdx, pu.puAbsPartIdx);<br>                 const MV* amvp = interMode.amvpCand[list][ref];<br>                 int mvpIdx = selectMVP(cu, pu, amvp, list, ref);<br>                 MV mvmin, mvmax, outmv, mvp;<br>@@ -2404,7 +2404,7 @@ void Search::predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChroma<br>                     uint32_t bits = m_listSelBits[list] + MVP_IDX_BITS;<br>                     bits += getTUBits(ref, numRefIdx[list]);<br> <br>-                    int numMvc = cu.getPMV(interMode.interNeighbours, list, ref, interMode.amvpCand[list][ref], mvc);<br>+                    int numMvc = cu.getPMV(interMode.interNeighbours, list, ref, interMode.amvpCand[list][ref], mvc, puIdx, pu.puAbsPartIdx);<br> <br>                     const MV* amvp = interMode.amvpCand[list][ref];<br>                     int mvpIdx = selectMVP(cu, pu, amvp, list, ref);<br>-- <br>2.36.0.windows.1<br><br></div>