[x265] [PATCH SCC 03/09] Modify reference picture list for IntrablockCopy mode

Anusuya Kumarasamy anusuya.kumarasamy at multicorewareinc.com
Wed Aug 7 17:20:33 UTC 2024


>From 21c8be0de09076b700db5eeb6336b95c2587e848 Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Thu, 18 Jul 2024 21:15:11 +0530
Subject: [PATCH 3/9] Modify reference picture list for IntrablockCopy mode

---
 source/common/cudata.cpp            |  7 +++++--
 source/common/piclist.h             |  2 +-
 source/common/slice.cpp             | 27 +++++++++++++++++++++++++--
 source/common/slice.h               |  1 +
 source/encoder/analysis.cpp         |  7 +++++--
 source/encoder/dpb.cpp              |  9 ++++++---
 source/encoder/encoder.cpp          |  9 ++++++---
 source/encoder/entropy.cpp          |  6 ++++++
 source/encoder/frameencoder.cpp     |  8 ++++++++
 source/encoder/ratecontrol.cpp      |  2 +-
 source/encoder/search.cpp           | 23 ++++++++++++++++++-----
 source/encoder/search.h             |  2 ++
 source/encoder/slicetype.cpp        |  2 +-
 source/encoder/weightPrediction.cpp |  6 +++++-
 14 files changed, 90 insertions(+), 21 deletions(-)

diff --git a/source/common/cudata.cpp b/source/common/cudata.cpp
index c0d68bc5f..ddee2b52b 100644
--- a/source/common/cudata.cpp
+++ b/source/common/cudata.cpp
@@ -1681,10 +1681,13 @@ uint32_t CUData::getInterMergeCandidates(uint32_t
absPartIdx, uint32_t puIdx, MV
             }
         }
     }
-    int numRefIdx = (isInterB) ? X265_MIN(m_slice->m_numRefIdx[0],
m_slice->m_numRefIdx[1]) : m_slice->m_numRefIdx[0];
+    int numRefIdx0 = m_slice->m_numRefIdx[0];
+    if (m_slice->m_param->bEnableSCC)
+        numRefIdx0--;
+    int numRefIdx = (isInterB) ? X265_MIN(numRefIdx0,
m_slice->m_numRefIdx[1]) : numRefIdx0;
     int r = 0;
     int refcnt = 0;
-    while (count < maxNumMergeCand)
+    while (numRefIdx && (count < maxNumMergeCand))
     {
         candDir[count] = 1;
         candMvField[count][0].mv.word = 0;
diff --git a/source/common/piclist.h b/source/common/piclist.h
index d270d0aec..dae253d8b 100644
--- a/source/common/piclist.h
+++ b/source/common/piclist.h
@@ -69,7 +69,7 @@ public:
     Frame* popFront();

     /** Find frame with specified POC */
-    Frame* getPOC(int poc, int sLayerId);
+    Frame* getPOC(int poc, int sLayerId = 0);
     /* Find next MCSTF frame with specified POC */
     Frame* getPOCMCSTF(int poc);

diff --git a/source/common/slice.cpp b/source/common/slice.cpp
index 7f62695ee..badcb7671 100644
--- a/source/common/slice.cpp
+++ b/source/common/slice.cpp
@@ -64,6 +64,15 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi
         return;
     }

+    /*Reset the number of references for I-slice marked as P-slice*/
+    if (m_param->bEnableSCC && m_sliceType != m_origSliceType)
+    {
+        memset(m_refFrameList, 0, sizeof(m_refFrameList));
+        memset(m_refReconPicList, 0, sizeof(m_refReconPicList));
+        memset(m_refPOCList, 0, sizeof(m_refPOCList));
+        m_numRefIdx[0] = 1;
+    }
+
     Frame* refPic = NULL;
     Frame* refPicSetStCurr0[MAX_NUM_REF];
     Frame* refPicSetStCurr1[MAX_NUM_REF];
@@ -75,7 +84,7 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi

     for (i = 0; i < m_rps.numberOfNegativePictures; i++)
     {
-        if (m_rps.bUsed[i])
+        if (m_rps.bUsed[i] && m_origSliceType != I_SLICE)
         {
             refPic = picList.getPOC(m_poc + m_rps.deltaPOC[i],
m_rps.deltaPOC[i] ? sLayerId : 0);
             refPicSetStCurr0[numPocStCurr0] = refPic;
@@ -85,7 +94,7 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi

     for (; i < m_rps.numberOfNegativePictures +
m_rps.numberOfPositivePictures; i++)
     {
-        if (m_rps.bUsed[i])
+        if (m_rps.bUsed[i] && m_origSliceType != I_SLICE)
         {
             refPic = picList.getPOC(m_poc + m_rps.deltaPOC[i],
m_rps.deltaPOC[i] ? sLayerId : 0);
             refPicSetStCurr1[numPocStCurr1] = refPic;
@@ -105,6 +114,9 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi
     int numPocTotalCurr = numPocStCurr0 + numPocStCurr1 + numPocLtCurr;
 #endif

+    if (m_param->bEnableSCC)
+        numPocTotalCurr++;
+
     int cIdx = 0;
     for (i = 0; i < numPocStCurr0; i++, cIdx++)
         rpsCurrList0[cIdx] = refPicSetStCurr0[i];
@@ -127,6 +139,9 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi
             rpsCurrList0[cIdx] = refPicSetInterLayer1.getPOC(m_poc, 0);
 #endif

+    if (m_param->bEnableSCC)
+        rpsCurrList0[cIdx++] = picList.getPOC(m_poc);
+
     X265_CHECK(cIdx == numPocTotalCurr, "RPS index check fail\n");

     if (m_sliceType == B_SLICE)
@@ -153,6 +168,9 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi
                 rpsCurrList1[cIdx] = refPicSetInterLayer0.getPOC(m_poc, 0);
 #endif

+        if (m_param->bEnableSCC)
+            rpsCurrList1[cIdx++] = picList.getPOC(m_poc);
+
         X265_CHECK(cIdx == numPocTotalCurr, "RPS index check fail\n");
     }

@@ -166,6 +184,11 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi
 #endif
     }

+    if (m_param->bEnableSCC && numPocTotalCurr > m_numRefIdx[0])
+    {
+        m_refFrameList[0][m_numRefIdx[0] - 1] = picList.getPOC(m_poc);
+    }
+
     if (m_sliceType != B_SLICE)
     {
         m_numRefIdx[1] = 0;
diff --git a/source/common/slice.h b/source/common/slice.h
index add5948f8..f03508660 100644
--- a/source/common/slice.h
+++ b/source/common/slice.h
@@ -376,6 +376,7 @@ public:

     NalUnitType m_nalUnitType;
     SliceType   m_sliceType;
+    SliceType   m_origSliceType;
     int         m_sliceQp;
     int         m_chromaQpOffset[2];
     int         m_poc;
diff --git a/source/encoder/analysis.cpp b/source/encoder/analysis.cpp
index 1f1984707..33bf9d9a9 100644
--- a/source/encoder/analysis.cpp
+++ b/source/encoder/analysis.cpp
@@ -223,7 +223,7 @@ Mode& Analysis::compressCTU(CUData& ctu, Frame& frame,
const CUGeom& cuGeom, con
     }
     ProfileCUScope(ctu, totalCTUTime, totalCTUs);

-    if (m_slice->m_sliceType == I_SLICE)
+    if (m_slice->m_sliceType == I_SLICE || (m_param->bEnableSCC &&
(m_slice->m_numRefIdx[0] == 1) && m_slice->m_refPOCList[0][0] ==
m_slice->m_poc))
     {
         x265_analysis_intra_data* intraDataCTU =
m_frame->m_analysisData.intraData;
         if (m_param->analysisLoadReuseLevel > 1)
@@ -3434,7 +3434,8 @@ uint32_t Analysis::topSkipMinDepth(const CUData&
parentCTU, const CUGeom& cuGeom
     uint32_t minDepth0 = 4, minDepth1 = 4;
     uint32_t sum = 0;
     int numRefs = 0;
-    if (m_slice->m_numRefIdx[0])
+    int refPresent = (!m_slice->m_param->bEnableSCC &&
m_slice->m_numRefIdx[0]) || ((!m_slice->m_param->bEnableSCC &&
(m_slice->m_numRefIdx[0] - 1)));
+    if (refPresent)
     {
         numRefs++;
         const CUData& cu =
*m_slice->m_refFrameList[0][0]->m_encData->getPicCTU(parentCTU.m_cuAddr);
@@ -3781,6 +3782,8 @@ int Analysis::findSameContentRefCount(const CUData&
parentCTU, const CUGeom& cuG
         for (int i = 0; i <
m_frame->m_encData->m_slice->m_numRefIdx[list]; i++)
         {
             int refPoc =
m_frame->m_encData->m_slice->m_refFrameList[list][i]->m_poc;
+            if (refPoc == m_curPoc)
+                continue;
             int refPrevChange =
m_frame->m_encData->m_slice->m_refFrameList[list][i]->m_addOnPrevChange[parentCTU.m_cuAddr][cuGeom.absPartIdx];
             if ((refPoc < prevChange && refPoc < m_curPoc) || (refPoc >
m_curPoc && prevChange < m_curPoc && refPrevChange > m_curPoc) || ((refPoc
== prevChange) && (m_additionalCtuInfo[cuGeom.absPartIdx] ==
CTU_INFO_CHANGE)))
                 sameContentRef++;    /* Content changed */
diff --git a/source/encoder/dpb.cpp b/source/encoder/dpb.cpp
index eafc9c91e..e488cebb8 100644
--- a/source/encoder/dpb.cpp
+++ b/source/encoder/dpb.cpp
@@ -150,7 +150,9 @@ void DPB::prepareEncode(Frame *newFrame)
     if (slice->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL ||
slice->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP)
         m_lastIDR = pocCurr;
     slice->m_lastIDR = m_lastIDR;
-    slice->m_sliceType = IS_X265_TYPE_B(type) ? B_SLICE : (type ==
X265_TYPE_P) ? P_SLICE : I_SLICE;
+    slice->m_origSliceType = slice->m_sliceType = IS_X265_TYPE_B(type) ?
B_SLICE : (type == X265_TYPE_P) ? P_SLICE : I_SLICE;
+    if (slice->m_param->bEnableSCC && IS_X265_TYPE_I(type))
+        slice->m_sliceType = P_SLICE;

     if (type == X265_TYPE_B)
     {
@@ -277,10 +279,11 @@ void DPB::prepareEncode(Frame *newFrame)
     if (newFrame->m_viewId)
         slice->createInterLayerReferencePictureSet(m_picList,
newFrame->refPicSetInterLayer0, newFrame->refPicSetInterLayer1);
 #endif
+    int numRef = slice->m_param->bEnableSCC ?
slice->m_rps.numberOfNegativePictures + 1 :
slice->m_rps.numberOfNegativePictures;
     if (slice->m_sliceType != I_SLICE)
-        slice->m_numRefIdx[0] = x265_clip3(1,
newFrame->m_param->maxNumReferences, slice->m_rps.numberOfNegativePictures
+ newFrame->refPicSetInterLayer0.size() +
newFrame->refPicSetInterLayer1.size());
+        slice->m_numRefIdx[0] = x265_clip3(1,
newFrame->m_param->maxNumReferences, numRef +
newFrame->refPicSetInterLayer0.size() +
newFrame->refPicSetInterLayer1.size());
     else
-        slice->m_numRefIdx[0] =
X265_MIN(newFrame->m_param->maxNumReferences,
slice->m_rps.numberOfNegativePictures); // Ensuring L0 contains just the
-ve POC
+        slice->m_numRefIdx[0] =
X265_MIN(newFrame->m_param->maxNumReferences, numRef); // Ensuring L0
contains just the -ve POC
     slice->m_numRefIdx[1] = X265_MIN(newFrame->m_param->bBPyramid ? 3 : 2,
slice->m_rps.numberOfPositivePictures +
newFrame->refPicSetInterLayer0.size() +
newFrame->refPicSetInterLayer1.size());
     slice->setRefPicList(m_picList, newFrame->refPicSetInterLayer0,
newFrame->refPicSetInterLayer1, layer);

diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 095009200..f4782f55d 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -629,8 +629,11 @@ int Encoder::getRefFrameList(PicYuv** l0, PicYuv** l1,
int sliceType, int poc, i
                     int l0POC =
framePtr->m_encData->m_slice->m_refFrameList[0][j]->m_poc;
                     pocL0[j] = l0POC;
                     Frame* l0Fp = m_dpb->m_picList.getPOC(l0POC, 0);
-                    while (l0Fp->m_reconRowFlag[l0Fp->m_numRows - 1].get()
== 0)
-                        l0Fp->m_reconRowFlag[l0Fp->m_numRows -
1].waitForChange(0); /* If recon is not ready, current frame encoder has to
wait. */
+                    if (l0POC != poc)
+                    {
+                        while (l0Fp->m_reconRowFlag[l0Fp->m_numRows -
1].get() == 0)
+                            l0Fp->m_reconRowFlag[l0Fp->m_numRows -
1].waitForChange(0); /* If recon is not ready, current frame encoder has to
wait. */
+                    }
                     l0[j] = l0Fp->m_reconPic;
                 }
             }
@@ -3700,7 +3703,7 @@ void Encoder::initPPS(PPS *pps)

     pps->bEntropyCodingSyncEnabled = m_param->bEnableWavefront;

-    pps->numRefIdxDefault[0] = 1;
+    pps->numRefIdxDefault[0] = 1 + !!m_param->bEnableSCC;;
     pps->numRefIdxDefault[1] = 1;
     pps->pps_extension_flag = false;
     pps->maxViews = 1;
diff --git a/source/encoder/entropy.cpp b/source/encoder/entropy.cpp
index 400a7dd8e..c79c3ea0d 100644
--- a/source/encoder/entropy.cpp
+++ b/source/encoder/entropy.cpp
@@ -1726,6 +1726,8 @@ void Entropy::codePredWeightTable(const Slice& slice)
         {
             for (int ref = 0; ref < slice.m_numRefIdx[list]; ref++)
             {
+                if (slice.m_poc == slice.m_refPOCList[list][ref])
+                    continue;
                 wp = slice.m_weightPredTable[list][ref];
                 if (!bDenomCoded)
                 {
@@ -1746,6 +1748,8 @@ void Entropy::codePredWeightTable(const Slice& slice)
             {
                 for (int ref = 0; ref < slice.m_numRefIdx[list]; ref++)
                 {
+                    if (slice.m_poc == slice.m_refPOCList[list][ref])
+                        continue;
                     wp = slice.m_weightPredTable[list][ref];
                     WRITE_FLAG(!!wp[1].wtPresent, "chroma_weight_lX_flag");
                     totalSignalledWeightFlags += 2 * wp[1].wtPresent;
@@ -1754,6 +1758,8 @@ void Entropy::codePredWeightTable(const Slice& slice)

             for (int ref = 0; ref < slice.m_numRefIdx[list]; ref++)
             {
+                if (slice.m_poc == slice.m_refPOCList[list][ref])
+                    continue;
                 wp = slice.m_weightPredTable[list][ref];
                 if (wp[0].wtPresent)
                 {
diff --git a/source/encoder/frameencoder.cpp
b/source/encoder/frameencoder.cpp
index c5175f538..0ee3e9a2e 100644
--- a/source/encoder/frameencoder.cpp
+++ b/source/encoder/frameencoder.cpp
@@ -911,6 +911,10 @@ void FrameEncoder::compressFrame(int layer)
                     {
                         Frame *refpic = slice->m_refFrameList[l][ref];

+                        /*Exempt the current pic as reference*/
+                        if (m_param->bEnableSCC && refpic->m_poc ==
m_frame[layer]->m_poc)
+                            continue;
+
                         // NOTE: we unnecessary wait row that beyond
current slice boundary
                         const int rowIdx = X265_MIN(sliceEndRow, (row +
m_refLagRows));

@@ -953,6 +957,10 @@ void FrameEncoder::compressFrame(int layer)
                     {
                         Frame *refpic = slice->m_refFrameList[list][ref];

+                        /*Exempt the current pic as reference*/
+                        if (m_param->bEnableSCC && refpic->m_poc ==
m_frame[layer]->m_poc)
+                            continue;
+
                         const int rowIdx = X265_MIN(m_numRows - 1, (i +
m_refLagRows));
                         while (refpic->m_reconRowFlag[rowIdx].get() == 0)

 refpic->m_reconRowFlag[rowIdx].waitForChange(0);
diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp
index d46fb9a1e..25cb7318e 100644
--- a/source/encoder/ratecontrol.cpp
+++ b/source/encoder/ratecontrol.cpp
@@ -1348,7 +1348,7 @@ int RateControl::rateControlStart(Frame* curFrame,
RateControlEntry* rce, Encode

     FrameData& curEncData = *curFrame->m_encData;
     m_curSlice = curEncData.m_slice;
-    m_sliceType = m_curSlice->m_sliceType;
+    m_sliceType = m_curSlice->m_origSliceType;
     rce->sliceType = m_sliceType;
     if (!m_2pass)
         rce->keptAsRef = IS_REFERENCED(curFrame);
diff --git a/source/encoder/search.cpp b/source/encoder/search.cpp
index 954ec54d2..79af0b350 100644
--- a/source/encoder/search.cpp
+++ b/source/encoder/search.cpp
@@ -76,6 +76,7 @@ bool Search::initSearch(const x265_param& param,
ScalingList& scalingList)
     m_param = ¶m;
     m_bFrameParallel = param.frameNumThreads > 1;
     m_numLayers = g_log2Size[param.maxCUSize] - 2;
+    m_ibcEnabled = param.bEnableSCC;

     m_rdCost.setPsyRdScale(param.psyRd);
     m_rdCost.setSsimRd(param.bSsimRd);
@@ -2086,7 +2087,10 @@ void Search::processPME(PME& pme, Search& slave)
 void Search::singleMotionEstimation(Search& master, Mode& interMode, const
PredictionUnit& pu, int part, int list, int ref)
 {
     uint32_t bits = master.m_listSelBits[list] + MVP_IDX_BITS;
-    bits += getTUBits(ref, m_slice->m_numRefIdx[list]);
+    int numIdx = m_slice->m_numRefIdx[list];
+    if (!list && m_ibcEnabled)
+        numIdx--;
+    bits += getTUBits(ref, numIdx);

     MotionData* bestME = interMode.bestME[part];

@@ -2246,7 +2250,10 @@ void Search::predInterSearch(Mode& interMode, const
CUGeom& cuGeom, bool bChroma
                     continue;
                 }
                 uint32_t bits = m_listSelBits[list] + MVP_IDX_BITS;
-                bits += getTUBits(ref, numRefIdx[list]);
+                int numIdx = m_slice->m_numRefIdx[list];
+                if (!list && m_ibcEnabled)
+                    numIdx--;
+                bits += getTUBits(ref, numIdx);

                 int numMvc = cu.getPMV(interMode.interNeighbours, list,
ref, interMode.amvpCand[list][ref], mvc, puIdx, pu.puAbsPartIdx);
                 const MV* amvp = interMode.amvpCand[list][ref];
@@ -2354,7 +2361,10 @@ void Search::predInterSearch(Mode& interMode, const
CUGeom& cuGeom, bool bChroma
             for (int list = 0; list < numPredDir; list++)
             {
                 int idx = 0;
-                for (int ref = 0; ref < numRefIdx[list]; ref++)
+                int numIdx = numRefIdx[list];
+                if (!list && m_ibcEnabled)
+                    numIdx--;
+                for (int ref = 0; ref < numIdx; ref++)
                 {
                     if (!(refMask & (1 << ref)))
                         continue;
@@ -2393,7 +2403,10 @@ void Search::predInterSearch(Mode& interMode, const
CUGeom& cuGeom, bool bChroma

             for (int list = 0; list < numPredDir; list++)
             {
-                for (int ref = 0; ref < numRefIdx[list]; ref++)
+                int numIdx = numRefIdx[list];
+                if (!list && m_ibcEnabled)
+                    numIdx--;
+                for (int ref = 0; ref < numIdx; ref++)
                 {
                     ProfileCounter(interMode.cu,
totalMotionReferences[cuGeom.depth]);

@@ -2404,7 +2417,7 @@ void Search::predInterSearch(Mode& interMode, const
CUGeom& cuGeom, bool bChroma
                     }

                     uint32_t bits = m_listSelBits[list] + MVP_IDX_BITS;
-                    bits += getTUBits(ref, numRefIdx[list]);
+                    bits += getTUBits(ref, numIdx);

                     int numMvc = cu.getPMV(interMode.interNeighbours,
list, ref, interMode.amvpCand[list][ref], mvc, puIdx, pu.puAbsPartIdx);

diff --git a/source/encoder/search.h b/source/encoder/search.h
index ea3fae02f..e90964619 100644
--- a/source/encoder/search.h
+++ b/source/encoder/search.h
@@ -288,6 +288,8 @@ public:

     bool            m_vertRestriction;

+    int             m_ibcEnabled;
+
 #if DETAILED_CU_STATS
     /* Accumulate CU statistics separately for each frame encoder */
     CUStats         m_stats[X265_MAX_FRAME_THREADS];
diff --git a/source/encoder/slicetype.cpp b/source/encoder/slicetype.cpp
index 46c6dd4d5..8bbac8244 100644
--- a/source/encoder/slicetype.cpp
+++ b/source/encoder/slicetype.cpp
@@ -1324,7 +1324,7 @@ void Lookahead::getEstimatedPictureCost(Frame
*curFrame)
     int l0poc = slice->m_rps.numberOfNegativePictures ?
slice->m_refPOCList[0][0] : -1;
     int l1poc = slice->m_refPOCList[1][0];

-    switch (slice->m_sliceType)
+    switch (slice->m_origSliceType)
     {
     case I_SLICE:
         frames[p0] = &curFrame->m_lowres;
diff --git a/source/encoder/weightPrediction.cpp
b/source/encoder/weightPrediction.cpp
index 9568afb12..724757429 100644
--- a/source/encoder/weightPrediction.cpp
+++ b/source/encoder/weightPrediction.cpp
@@ -491,8 +491,12 @@ void weightAnalyse(Slice& slice, Frame& frame,
x265_param& param)
         lumaDenom = weights[0].log2WeightDenom;
         chromaDenom = weights[1].log2WeightDenom;

+        int numIdx = slice.m_numRefIdx[list];
+        if (!list && param.bEnableSCC)
+            numIdx--;
+
         /* reset weight states */
-        for (int ref = 1; ref < slice.m_numRefIdx[list]; ref++)
+        for (int ref = 1; ref < numIdx; ref++)
         {
             SET_WEIGHT(wp[list][ref][0], false, 1 << lumaDenom, lumaDenom,
0);
             SET_WEIGHT(wp[list][ref][1], false, 1 << chromaDenom,
chromaDenom, 0);
-- 
2.36.0.windows.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240807/41103607/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0003-Modify-reference-picture-list-for-IntrablockCopy-mod.patch
Type: application/octet-stream
Size: 19609 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240807/41103607/attachment-0001.obj>


More information about the x265-devel mailing list