<div dir="ltr">From 4101dcf0f15686578b0c981de3df296d91a3ae8f 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, 19 Jul 2024 16:52:58 +0530<br>Subject: [PATCH 5/9] Added sao, deblock and temporal-mvp support and disable<br> weight prediction<br><br>---<br> source/common/cudata.cpp        |  8 ++---<br> source/common/deblock.cpp       |  4 +--<br> source/common/frame.cpp         | 55 ++++++++++++++++++++-------------<br> source/common/frame.h           |  2 +-<br> source/common/framedata.h       |  2 +-<br> source/common/param.cpp         |  7 ++++-<br> source/common/predict.cpp       | 50 +++++++++++++++++++++++-------<br> source/common/slice.h           |  2 ++<br> source/encoder/analysis.cpp     | 24 ++++++++------<br> source/encoder/dpb.cpp          | 19 +++++++++---<br> source/encoder/encoder.cpp      | 20 ++++++------<br> source/encoder/entropy.cpp      |  4 +--<br> source/encoder/frameencoder.cpp |  8 ++---<br> source/encoder/framefilter.cpp  | 14 ++++-----<br> source/encoder/level.cpp        |  9 +++---<br> source/encoder/sao.cpp          | 10 +++---<br> source/encoder/search.cpp       | 39 ++++++++++++++---------<br> 17 files changed, 173 insertions(+), 104 deletions(-)<br><br>diff --git a/source/common/cudata.cpp b/source/common/cudata.cpp<br>index a671df113..23f95288e 100644<br>--- a/source/common/cudata.cpp<br>+++ b/source/common/cudata.cpp<br>@@ -1595,7 +1595,7 @@ uint32_t CUData::getInterMergeCandidates(uint32_t absPartIdx, uint32_t puIdx, MV<br>                 return maxNumMergeCand;<br>         }<br>     }<br>-    if (m_slice->m_sps->bTemporalMVPEnabled)<br>+    if (m_slice->m_bTemporalMvp)<br>     {<br>         uint32_t partIdxRB = deriveRightBottomIdx(puIdx);<br>         MV colmv;<br>@@ -1822,9 +1822,9 @@ int CUData::getPMV(InterNeighbourMV* neighbours, uint32_t picList, uint32_t refI<br>     // Get the collocated candidate. At this step, either the first candidate<br>     // was found or its value is 0.<br> #if ENABLE_MULTIVIEW<br>-    if (m_slice->m_param->numViews > 1)<br>+    if (m_slice->m_param->numViews > 1 || !!m_slice->m_param->bEnableSCC)<br>     {<br>-        if (m_slice->m_sps->bTemporalMVPEnabled && num < 2)<br>+        if (m_slice->m_bTemporalMvp && num < 2)<br>         {<br>             int refId = refIdx;<br>             uint32_t absPartAddr = m_absIdxInCTU + absPartIdx;<br>@@ -1915,7 +1915,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 && !(m_slice->m_param->numViews > 1))<br>+    if (m_slice->m_bTemporalMvp && !(!!m_slice->m_param->bEnableSCC || m_slice->m_param->numViews > 1))<br>     {<br>         uint32_t absPartAddr = m_absIdxInCTU + absPartIdx;<br>         uint32_t partIdxRB = deriveRightBottomIdx(puIdx);<br>diff --git a/source/common/deblock.cpp b/source/common/deblock.cpp<br>index 15ca361b2..0f9bc02dd 100644<br>--- a/source/common/deblock.cpp<br>+++ b/source/common/deblock.cpp<br>@@ -316,7 +316,7 @@ static inline void pelFilterLuma(pixel* src, intptr_t srcStep, intptr_t offset,<br> <br> void Deblock::edgeFilterLuma(const CUData* cuQ, uint32_t absPartIdx, uint32_t depth, int32_t dir, int32_t edge, const uint8_t blockStrength[])<br> {<br>-    PicYuv* reconPic = cuQ->m_encData->m_reconPic;<br>+    PicYuv* reconPic = cuQ->m_encData->m_reconPic[0];<br>     pixel* src = reconPic->getLumaAddr(cuQ->m_cuAddr, absPartIdx);<br>     intptr_t stride = reconPic->m_stride;<br>     const PPS* pps = cuQ->m_slice->m_pps;<br>@@ -429,7 +429,7 @@ void Deblock::edgeFilterChroma(const CUData* cuQ, uint32_t absPartIdx, uint32_t<br>                 : ((g_zscanToPelY[absPartIdx] + edge * UNIT_SIZE) >> cuQ->m_vChromaShift)) % DEBLOCK_SMALLEST_BLOCK == 0,<br>                "invalid edge\n");<br> <br>-    PicYuv* reconPic = cuQ->m_encData->m_reconPic;<br>+    PicYuv* reconPic = cuQ->m_encData->m_reconPic[0];<br>     intptr_t stride = reconPic->m_strideC;<br>     intptr_t srcOffset = reconPic->getChromaAddrOffset(cuQ->m_cuAddr, absPartIdx);<br>     bool bCheckNoFilter = pps->bTransquantBypassEnabled;<br>diff --git a/source/common/frame.cpp b/source/common/frame.cpp<br>index c40093dba..6140021aa 100644<br>--- a/source/common/frame.cpp<br>+++ b/source/common/frame.cpp<br>@@ -37,7 +37,8 @@ Frame::Frame()<br>     m_reconColCount = NULL;<br>     m_countRefEncoders = 0;<br>     m_encData = NULL;<br>-    m_reconPic = NULL;<br>+    for (int i = 0; i < 2; i++)<br>+        m_reconPic[i] = NULL;<br>     m_quantOffsets = NULL;<br>     m_next = NULL;<br>     m_prev = NULL;<br>@@ -204,29 +205,35 @@ fail:<br> bool Frame::allocEncodeData(x265_param *param, const SPS& sps)<br> {<br>     m_encData = new FrameData;<br>-    m_reconPic = new PicYuv;<br>     m_param = param;<br>-    m_encData->m_reconPic = m_reconPic;<br>-    bool ok = m_encData->create(*param, sps, m_fencPic->m_picCsp) && m_reconPic->create(param);<br>+    for (int i = 0; i < !!m_param->bEnableSCC + 1; i++)<br>+    {<br>+        m_reconPic[i] = new PicYuv;<br>+        m_encData->m_reconPic[i] = m_reconPic[i];<br>+    }<br>+    bool ok = m_encData->create(*param, sps, m_fencPic->m_picCsp) && m_reconPic[0]->create(param) && (!!param->bEnableSCC ? (!!param->bEnableSCC && m_reconPic[1]->create(param)) : 1);<br>     if (ok)<br>     {<br>-        /* initialize right border of m_reconpicYuv as SAO may read beyond the<br>+        /* initialize right border of m_reconPicYuv as SAO may read beyond the<br>          * end of the picture accessing uninitialized pixels */<br>         int maxHeight = sps.numCuInHeight * param->maxCUSize;<br>-        memset(m_reconPic->m_picOrg[0], 0, sizeof(pixel)* m_reconPic->m_stride * maxHeight);<br>-<br>-        /* use pre-calculated cu/pu offsets cached in the SPS structure */<br>-        m_reconPic->m_cuOffsetY = sps.cuOffsetY;<br>-        m_reconPic->m_buOffsetY = sps.buOffsetY;<br>+        memset(m_reconPic[0]->m_picOrg[0], 0, sizeof(pixel)* m_reconPic[0]->m_stride * maxHeight);<br> <br>-        if (param->internalCsp != X265_CSP_I400)<br>+        for (int i = 0; i < !!m_param->bEnableSCC + 1; i++)<br>         {<br>-            memset(m_reconPic->m_picOrg[1], 0, sizeof(pixel) * m_reconPic->m_strideC * (maxHeight >> m_reconPic->m_vChromaShift));<br>-            memset(m_reconPic->m_picOrg[2], 0, sizeof(pixel) * m_reconPic->m_strideC * (maxHeight >> m_reconPic->m_vChromaShift));<br>-<br>             /* use pre-calculated cu/pu offsets cached in the SPS structure */<br>-            m_reconPic->m_cuOffsetC = sps.cuOffsetC;<br>-            m_reconPic->m_buOffsetC = sps.buOffsetC;<br>+            m_reconPic[i]->m_cuOffsetY = sps.cuOffsetY;<br>+            m_reconPic[i]->m_buOffsetY = sps.buOffsetY;<br>+<br>+            if (param->internalCsp != X265_CSP_I400)<br>+            {<br>+                memset(m_reconPic[i]->m_picOrg[1], 0, sizeof(pixel) * m_reconPic[i]->m_strideC * (maxHeight >> m_reconPic[i]->m_vChromaShift));<br>+                memset(m_reconPic[i]->m_picOrg[2], 0, sizeof(pixel) * m_reconPic[i]->m_strideC * (maxHeight >> m_reconPic[i]->m_vChromaShift));<br>+<br>+                /* use pre-calculated cu/pu offsets cached in the SPS structure */<br>+                m_reconPic[i]->m_cuOffsetC = sps.cuOffsetC;<br>+                m_reconPic[i]->m_buOffsetC = sps.buOffsetC;<br>+            }<br>         }<br>     }<br>     return ok;<br>@@ -236,7 +243,9 @@ bool Frame::allocEncodeData(x265_param *param, const SPS& sps)<br> void Frame::reinit(const SPS& sps)<br> {<br>     m_bChromaExtended = false;<br>-    m_reconPic = m_encData->m_reconPic;<br>+    m_reconPic[0] = m_encData->m_reconPic[0];<br>+    if (!!m_param->bEnableSCC)<br>+        m_reconPic[1] = m_encData->m_reconPic[1];<br>     m_encData->reinit(sps);<br> }<br> <br>@@ -306,11 +315,15 @@ void Frame::destroy()<br>         X265_FREE(m_isSubSampled);<br>     }<br> <br>-    if (m_reconPic)<br>+    int numVersion = !!m_param->bEnableSCC ? 2 : 1;<br>+    for (int i = 0; i < numVersion; i++)<br>     {<br>-        m_reconPic->destroy();<br>-        delete m_reconPic;<br>-        m_reconPic = NULL;<br>+        if (m_reconPic[i])<br>+        {<br>+            m_reconPic[i]->destroy();<br>+            delete m_reconPic[i];<br>+            m_reconPic[i] = NULL;<br>+        }<br>     }<br> <br>     if (m_reconRowFlag)<br>diff --git a/source/common/frame.h b/source/common/frame.h<br>index 4ddd8bd46..4e6a4beed 100644<br>--- a/source/common/frame.h<br>+++ b/source/common/frame.h<br>@@ -81,7 +81,7 @@ public:<br>     /* These two items will be NULL until the Frame begins to be encoded, at which point<br>      * it will be assigned a FrameData instance, which comes with a reconstructed image PicYuv */<br>     FrameData*             m_encData;<br>-    PicYuv*                m_reconPic;<br>+    PicYuv*                m_reconPic[2];<br> <br>     /* Data associated with x265_picture */<br>     PicYuv*                m_fencPic;<br>diff --git a/source/common/framedata.h b/source/common/framedata.h<br>index 611664ca5..66a00696c 100644<br>--- a/source/common/framedata.h<br>+++ b/source/common/framedata.h<br>@@ -115,7 +115,7 @@ public:<br>     const x265_param* m_param;<br> <br>     FrameData*     m_freeListNext;<br>-    PicYuv*        m_reconPic;<br>+    PicYuv*        m_reconPic[2];<br>     bool           m_bHasReferences;   /* used during DPB/RPS updates */<br>     int            m_frameEncoderID;   /* the ID of the FrameEncoder encoding this frame */<br>     JobProvider*   m_jobProvider;<br>diff --git a/source/common/param.cpp b/source/common/param.cpp<br>index 2f4f8084d..bbf33dae9 100755<br>--- a/source/common/param.cpp<br>+++ b/source/common/param.cpp<br>@@ -1476,7 +1476,12 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)<br>             p->numViews = atoi(value);<br>         }<br> #endif<br>-        OPT("scc") p->bEnableSCC = atoi(value);<br>+        OPT("scc")<br>+        {<br>+            p->bEnableSCC = atoi(value);<br>+            if (p->bEnableSCC)<br>+                p->bEnableWeightedPred = false;<br>+        }<br>         else<br>             return X265_PARAM_BAD_NAME;<br>     }<br>diff --git a/source/common/predict.cpp b/source/common/predict.cpp<br>index a32bd05f7..e6fc478e3 100644<br>--- a/source/common/predict.cpp<br>+++ b/source/common/predict.cpp<br>@@ -112,10 +112,20 @@ void Predict::motionCompensation(const CUData& cu, const PredictionUnit& pu, Yuv<br>         }<br>         else<br>         {<br>-            if (bLuma)<br>-                predInterLumaPixel(pu, predYuv, *cu.m_slice->m_refReconPicList[0][refIdx0], mv0);<br>-            if (bChroma)<br>-                predInterChromaPixel(pu, predYuv, *cu.m_slice->m_refReconPicList[0][refIdx0], mv0);<br>+            if (!!cu.m_slice->m_param->bEnableSCC && refIdx0 == (cu.m_slice->m_numRefIdx[0] - 1))<br>+            {<br>+                if (bLuma)<br>+                    predInterLumaPixel(pu, predYuv, *cu.m_slice->m_refFrameList[0][refIdx0]->m_reconPic[1], mv0);<br>+                if (bChroma)<br>+                    predInterChromaPixel(pu, predYuv, *cu.m_slice->m_refFrameList[0][refIdx0]->m_reconPic[1], mv0);<br>+            }<br>+            else<br>+            {<br>+                if (bLuma)<br>+                    predInterLumaPixel(pu, predYuv, *cu.m_slice->m_refReconPicList[0][refIdx0], mv0);<br>+                if (bChroma)<br>+                    predInterChromaPixel(pu, predYuv, *cu.m_slice->m_refReconPicList[0][refIdx0], mv0);<br>+            }<br>         }<br>     }<br>     else<br>@@ -174,12 +184,18 @@ void Predict::motionCompensation(const CUData& cu, const PredictionUnit& pu, Yuv<br> <br>             if (bLuma)<br>             {<br>-                predInterLumaShort(pu, m_predShortYuv[0], *cu.m_slice->m_refReconPicList[0][refIdx0], mv0);<br>+                if (!!cu.m_slice->m_param->bEnableSCC && refIdx0 == (cu.m_slice->m_numRefIdx[0] - 1))<br>+                    predInterLumaShort(pu, m_predShortYuv[0], *cu.m_slice->m_refFrameList[0][refIdx0]->m_reconPic[1], mv0);<br>+                else<br>+                    predInterLumaShort(pu, m_predShortYuv[0], *cu.m_slice->m_refReconPicList[0][refIdx0], mv0);<br>                 predInterLumaShort(pu, m_predShortYuv[1], *cu.m_slice->m_refReconPicList[1][refIdx1], mv1);<br>             }<br>             if (bChroma)<br>             {<br>-                predInterChromaShort(pu, m_predShortYuv[0], *cu.m_slice->m_refReconPicList[0][refIdx0], mv0);<br>+                if (!!cu.m_slice->m_param->bEnableSCC && refIdx0 == (cu.m_slice->m_numRefIdx[0] - 1))<br>+                    predInterChromaShort(pu, m_predShortYuv[0], *cu.m_slice->m_refFrameList[0][refIdx0]->m_reconPic[1], mv0);<br>+                else<br>+                    predInterChromaShort(pu, m_predShortYuv[0], *cu.m_slice->m_refReconPicList[0][refIdx0], mv0);<br>                 predInterChromaShort(pu, m_predShortYuv[1], *cu.m_slice->m_refReconPicList[1][refIdx1], mv1);<br>             }<br> <br>@@ -206,10 +222,20 @@ void Predict::motionCompensation(const CUData& cu, const PredictionUnit& pu, Yuv<br>             }<br>             else<br>             {<br>-                if (bLuma)<br>-                    predInterLumaPixel(pu, predYuv, *cu.m_slice->m_refReconPicList[0][refIdx0], mv0);<br>-                if (bChroma)<br>-                    predInterChromaPixel(pu, predYuv, *cu.m_slice->m_refReconPicList[0][refIdx0], mv0);<br>+                if (!!cu.m_slice->m_param->bEnableSCC && refIdx0 == (cu.m_slice->m_numRefIdx[0] - 1))<br>+                {<br>+                    if (bLuma)<br>+                        predInterLumaPixel(pu, predYuv, *cu.m_slice->m_refFrameList[0][refIdx0]->m_reconPic[1], mv0);<br>+                    if (bChroma)<br>+                        predInterChromaPixel(pu, predYuv, *cu.m_slice->m_refFrameList[0][refIdx0]->m_reconPic[1], mv0);<br>+                }<br>+                else<br>+                {<br>+                    if (bLuma)<br>+                        predInterLumaPixel(pu, predYuv, *cu.m_slice->m_refReconPicList[0][refIdx0], mv0);<br>+                    if (bChroma)<br>+                        predInterChromaPixel(pu, predYuv, *cu.m_slice->m_refReconPicList[0][refIdx0], mv0);<br>+                }<br>             }<br>         }<br>         else<br>@@ -602,7 +628,7 @@ void Predict::initAdiPattern(const CUData& cu, const CUGeom& cuGeom, uint32_t pu<br>     int tuSize = 1 << intraNeighbors.log2TrSize;<br>     int tuSize2 = tuSize << 1;<br> <br>-    PicYuv* reconPic = cu.m_encData->m_reconPic;<br>+    PicYuv* reconPic = cu.m_encData->m_reconPic[0];<br>     pixel* adiOrigin = reconPic->getLumaAddr(cu.m_cuAddr, cuGeom.absPartIdx + puAbsPartIdx);<br>     intptr_t picStride = reconPic->m_stride;<br> <br>@@ -651,7 +677,7 @@ void Predict::initAdiPattern(const CUData& cu, const CUGeom& cuGeom, uint32_t pu<br> <br> void Predict::initAdiPatternChroma(const CUData& cu, const CUGeom& cuGeom, uint32_t puAbsPartIdx, const IntraNeighbors& intraNeighbors, uint32_t chromaId)<br> {<br>-    PicYuv* reconPic = cu.m_encData->m_reconPic;<br>+    PicYuv* reconPic = cu.m_encData->m_reconPic[0];<br>     const pixel* adiOrigin = reconPic->getChromaAddr(chromaId, cu.m_cuAddr, cuGeom.absPartIdx + puAbsPartIdx);<br>     intptr_t picStride = reconPic->m_strideC;<br> <br>diff --git a/source/common/slice.h b/source/common/slice.h<br>index 2f8872473..57ef1afee 100644<br>--- a/source/common/slice.h<br>+++ b/source/common/slice.h<br>@@ -405,6 +405,7 @@ public:<br> <br>     Frame*      m_lastEncPic;<br>     bool        m_bLMvdL1Zero;<br>+    bool        m_bTemporalMvp;<br> <br>     Slice()<br>     {<br>@@ -421,6 +422,7 @@ public:<br>         m_rpsIdx = -1;<br>         m_chromaQpOffset[0] = m_chromaQpOffset[1] = 0;<br>         m_fieldNum = 0;<br>+        m_bTemporalMvp = false;<br>     }<br> <br>     void disableWeights();<br>diff --git a/source/encoder/analysis.cpp b/source/encoder/analysis.cpp<br>index 4bbfcbfe3..789069c4c 100644<br>--- a/source/encoder/analysis.cpp<br>+++ b/source/encoder/analysis.cpp<br>@@ -271,7 +271,7 @@ Mode& Analysis::compressCTU(CUData& ctu, Frame& frame, const CUGeom& cuGeom, con<br>         {<br>             /* In RD Level 0/1, copy source pixels into the reconstructed block so<br>              * they are available for intra predictions */<br>-            m_modeDepth[0].fencYuv.copyToPicYuv(*m_frame->m_reconPic, ctu.m_cuAddr, 0);<br>+            m_modeDepth[0].fencYuv.copyToPicYuv(*m_frame->m_reconPic[0], ctu.m_cuAddr, 0);<br> <br>             compressInterCU_rd0_4(ctu, cuGeom, qp);<br> <br>@@ -508,7 +508,7 @@ void Analysis::qprdRefine(const CUData& parentCTU, const CUGeom& cuGeom, int32_t<br> <br>     /* Copy best data to encData CTU and recon */<br>     md.bestMode->cu.copyToPic(depth);<br>-    md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic, parentCTU.m_cuAddr, cuGeom.absPartIdx);<br>+    md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic[0], parentCTU.m_cuAddr, cuGeom.absPartIdx);<br> }<br> <br> uint64_t Analysis::compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp)<br>@@ -816,7 +816,10 @@ uint64_t Analysis::compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom<br>     /* Copy best data to encData CTU and recon */<br>     md.bestMode->cu.copyToPic(depth);<br>     if (md.bestMode != &md.pred[PRED_SPLIT])<br>-        md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic, parentCTU.m_cuAddr, cuGeom.absPartIdx);<br>+    {<br>+        for (int i = 0; i < !!m_param->bEnableSCC + 1; i++)<br>+            md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic[i], parentCTU.m_cuAddr, cuGeom.absPartIdx);<br>+    }<br> <br>     return md.bestMode->rdCost;<br> }<br>@@ -1292,7 +1295,7 @@ uint32_t Analysis::compressInterCU_dist(const CUData& parentCTU, const CUGeom& c<br> <br>     /* Copy best data to encData CTU and recon */<br>     md.bestMode->cu.copyToPic(depth);<br>-    md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic, cuAddr, cuGeom.absPartIdx);<br>+    md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic[0], cuAddr, cuGeom.absPartIdx);<br> <br>     return refMask;<br> }<br>@@ -1310,14 +1313,14 @@ SplitData Analysis::compressInterCU_rd0_4(const CUData& parentCTU, const CUGeom&<br>     if (m_param->searchMethod == X265_SEA)<br>     {<br>         int numPredDir = m_slice->isInterP() ? 1 : 2;<br>-        int offset = (int)(m_frame->m_reconPic->m_cuOffsetY[parentCTU.m_cuAddr] + m_frame->m_reconPic->m_buOffsetY[cuGeom.absPartIdx]);<br>+        int offset = (int)(m_frame->m_reconPic[0]->m_cuOffsetY[parentCTU.m_cuAddr] + m_frame->m_reconPic[0]->m_buOffsetY[cuGeom.absPartIdx]);<br>         for (int list = 0; list < numPredDir; list++)<br>             for (int i = 0; i < m_frame->m_encData->m_slice->m_numRefIdx[list]; i++)<br>                 for (int planes = 0; planes < INTEGRAL_PLANE_NUM; planes++)<br>                     m_modeDepth[depth].fencYuv.m_integral[list][i][planes] = m_frame->m_encData->m_slice->m_refFrameList[list][i]->m_encData->m_meIntegral[planes] + offset;<br>     }<br> <br>-    PicYuv& reconPic = *m_frame->m_reconPic;<br>+    PicYuv& reconPic = *m_frame->m_reconPic[0];<br>     SplitData splitCUData;<br> <br>     bool bHEVCBlockAnalysis = (m_param->bAnalysisType == AVC_INFO && cuGeom.numPartitions > 16);<br>@@ -2026,7 +2029,7 @@ SplitData Analysis::compressInterCU_rd5_6(const CUData& parentCTU, const CUGeom&<br>     if (m_param->searchMethod == X265_SEA)<br>     {<br>         int numPredDir = m_slice->isInterP() ? 1 : 2;<br>-        int offset = (int)(m_frame->m_reconPic->m_cuOffsetY[parentCTU.m_cuAddr] + m_frame->m_reconPic->m_buOffsetY[cuGeom.absPartIdx]);<br>+        int offset = (int)(m_frame->m_reconPic[0]->m_cuOffsetY[parentCTU.m_cuAddr] + m_frame->m_reconPic[0]->m_buOffsetY[cuGeom.absPartIdx]);<br>         for (int list = 0; list < numPredDir; list++)<br>             for (int i = 0; i < m_frame->m_encData->m_slice->m_numRefIdx[list]; i++)<br>                 for (int planes = 0; planes < INTEGRAL_PLANE_NUM; planes++)<br>@@ -2708,7 +2711,8 @@ SplitData Analysis::compressInterCU_rd5_6(const CUData& parentCTU, const CUGeom&<br> <br>         /* Copy best data to encData CTU and recon */<br>         md.bestMode->cu.copyToPic(depth);<br>-        md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic, parentCTU.m_cuAddr, cuGeom.absPartIdx);<br>+        for (int i = 0; i < !!m_param->bEnableSCC + 1; i++)<br>+            md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic[i], parentCTU.m_cuAddr, cuGeom.absPartIdx);<br>     }<br>     else<br>     {<br>@@ -2994,7 +2998,7 @@ void Analysis::recodeCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t q<br> <br>         /* Copy best data to encData CTU and recon */<br>         md.bestMode->cu.copyToPic(depth);<br>-        md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic, parentCTU.m_cuAddr, cuGeom.absPartIdx);<br>+        md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic[0], parentCTU.m_cuAddr, cuGeom.absPartIdx);<br>     }<br>     if (m_param->bDynamicRefine && bDecidedDepth)<br>         trainCU(parentCTU, cuGeom, *md.bestMode, td);<br>@@ -3580,7 +3584,7 @@ void Analysis::checkBidir2Nx2N(Mode& inter2Nx2N, Mode& bidir2Nx2N, const CUGeom&<br> {<br>     CUData& cu = bidir2Nx2N.cu;<br> <br>-    if (cu.isBipredRestriction() || inter2Nx2N.bestME[0][0].cost == MAX_UINT || inter2Nx2N.bestME[0][1].cost == MAX_UINT)<br>+    if ((cu.is8x8BipredRestriction(inter2Nx2N.bestME[0][0].mv, inter2Nx2N.bestME[0][1].mv, inter2Nx2N.bestME[0][0].ref, inter2Nx2N.bestME[0][1].ref) ? (cu.m_cuDepth[0] == 3) : cu.isBipredRestriction()) || inter2Nx2N.bestME[0][0].cost == MAX_UINT || inter2Nx2N.bestME[0][1].cost == MAX_UINT)<br>     {<br>         bidir2Nx2N.sa8dCost = MAX_INT64;<br>         bidir2Nx2N.rdCost = MAX_INT64;<br>diff --git a/source/encoder/dpb.cpp b/source/encoder/dpb.cpp<br>index d957008eb..8ef1f7abe 100644<br>--- a/source/encoder/dpb.cpp<br>+++ b/source/encoder/dpb.cpp<br>@@ -53,8 +53,8 @@ DPB::~DPB()<br>         FrameData* next = m_frameDataFreeList->m_freeListNext;<br>         m_frameDataFreeList->destroy();<br> <br>-        m_frameDataFreeList->m_reconPic->destroy();<br>-        delete m_frameDataFreeList->m_reconPic;<br>+        m_frameDataFreeList->m_reconPic[0]->destroy();<br>+        delete m_frameDataFreeList->m_reconPic[0];<br> <br>         delete m_frameDataFreeList;<br>         m_frameDataFreeList = next;<br>@@ -132,7 +132,8 @@ void DPB::recycleUnreferenced()<br>                 curFrame->m_prevCtuInfoChange = NULL;<br>             }<br>             curFrame->m_encData = NULL;<br>-            curFrame->m_reconPic = NULL;<br>+            for (int i = 0; i < !!curFrame->m_param->bEnableSCC + 1; i++)<br>+                curFrame->m_reconPic[i] = NULL;<br>         }<br>     }<br> }<br>@@ -206,7 +207,8 @@ void DPB::prepareEncode(Frame *newFrame)<br>     // Do decoding refresh marking if any<br>     decodingRefreshMarking(pocCurr, slice->m_nalUnitType, layer);<br> <br>-    computeRPS(pocCurr, newFrame->m_tempLayer, slice->isIRAP(), &slice->m_rps, slice->m_sps->maxDecPicBuffering[newFrame->m_tempLayer], layer);<br>+    uint32_t maxDecBuffer = (slice->m_sps->maxDecPicBuffering[newFrame->m_tempLayer] >= 8 && slice->m_param->bEnableSCC) ? 7 : slice->m_sps->maxDecPicBuffering[newFrame->m_tempLayer];<br>+    computeRPS(pocCurr, newFrame->m_tempLayer, slice->isIRAP(), &slice->m_rps, maxDecBuffer, layer);<br>     bool isTSAPic = ((slice->m_nalUnitType == 2) || (slice->m_nalUnitType == 3)) ? true : false;<br>     // Mark pictures in m_piclist as unreferenced if they are not included in RPS<br>     applyReferencePictureSet(&slice->m_rps, pocCurr, newFrame->m_tempLayer, isTSAPic, layer);<br>@@ -367,6 +369,15 @@ void DPB::prepareEncode(Frame *newFrame)<br>         slice->m_bLMvdL1Zero = false;<br>     }<br> <br>+    if (!slice->isIntra() && slice->m_param->bEnableTemporalMvp)<br>+    {<br>+        const Frame* colPic = slice->m_refFrameList[slice->isInterB() && !slice->m_colFromL0Flag][slice->m_colRefIdx];<br>+        if (colPic->m_poc == slice->m_poc)<br>+            slice->m_bTemporalMvp = false;<br>+        else<br>+            slice->m_bTemporalMvp = true;<br>+    }<br>+<br>     // Disable Loopfilter in bound area, because we will do slice-parallelism in future<br>     slice->m_sLFaseFlag = (newFrame->m_param->maxSlices > 1) ? false : ((SLFASE_CONSTANT & (1 << (pocCurr % 31))) > 0);<br> <br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index f4782f55d..4043342c1 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -624,7 +624,7 @@ int Encoder::getRefFrameList(PicYuv** l0, PicYuv** l1, int sliceType, int poc, i<br>         {<br>             for (int j = 0; j < framePtr->m_encData->m_slice->m_numRefIdx[0]; j++)    // check only for --ref=n number of frames.<br>             {<br>-                if (framePtr->m_encData->m_slice->m_refFrameList[0][j] && framePtr->m_encData->m_slice->m_refFrameList[0][j]->m_reconPic != NULL)<br>+                if (framePtr->m_encData->m_slice->m_refFrameList[0][j] && framePtr->m_encData->m_slice->m_refFrameList[0][j]->m_reconPic[0] != NULL)<br>                 {<br>                     int l0POC = framePtr->m_encData->m_slice->m_refFrameList[0][j]->m_poc;<br>                     pocL0[j] = l0POC;<br>@@ -634,19 +634,19 @@ int Encoder::getRefFrameList(PicYuv** l0, PicYuv** l1, int sliceType, int poc, i<br>                         while (l0Fp->m_reconRowFlag[l0Fp->m_numRows - 1].get() == 0)<br>                             l0Fp->m_reconRowFlag[l0Fp->m_numRows - 1].waitForChange(0); /* If recon is not ready, current frame encoder has to wait. */<br>                     }<br>-                    l0[j] = l0Fp->m_reconPic;<br>+                    l0[j] = l0Fp->m_reconPic[0];<br>                 }<br>             }<br>             for (int j = 0; j < framePtr->m_encData->m_slice->m_numRefIdx[1]; j++)    // check only for --ref=n number of frames.<br>             {<br>-                if (framePtr->m_encData->m_slice->m_refFrameList[1][j] && framePtr->m_encData->m_slice->m_refFrameList[1][j]->m_reconPic != NULL)<br>+                if (framePtr->m_encData->m_slice->m_refFrameList[1][j] && framePtr->m_encData->m_slice->m_refFrameList[1][j]->m_reconPic[0] != NULL)<br>                 {<br>                     int l1POC = framePtr->m_encData->m_slice->m_refFrameList[1][j]->m_poc;<br>                     pocL1[j] = l1POC;<br>                     Frame* l1Fp = m_dpb->m_picList.getPOC(l1POC, 0);<br>                     while (l1Fp->m_reconRowFlag[l1Fp->m_numRows - 1].get() == 0)<br>                         l1Fp->m_reconRowFlag[l1Fp->m_numRows - 1].waitForChange(0); /* If recon is not ready, current frame encoder has to wait. */<br>-                    l1[j] = l1Fp->m_reconPic;<br>+                    l1[j] = l1Fp->m_reconPic[0];<br>                 }<br>             }<br>         }<br>@@ -1974,7 +1974,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture** pic_out)<br>                     x265_free_analysis_data(m_param, &outFrame->m_analysisData);<br>                 if (pic_out[sLayer])<br>                 {<br>-                    PicYuv* recpic = outFrame->m_reconPic;<br>+                    PicYuv* recpic = outFrame->m_reconPic[0];<br>                     pic_out[sLayer]->poc = slice->m_poc;<br>                     pic_out[sLayer]->bitDepth = X265_DEPTH;<br>                     pic_out[sLayer]->userData = outFrame->m_userData;<br>@@ -2330,15 +2330,15 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture** pic_out)<br>             {<br>                 int padX = m_param->maxCUSize + 32;<br>                 int padY = m_param->maxCUSize + 16;<br>-                uint32_t numCuInHeight = (frameEnc[0]->m_encData->m_reconPic->m_picHeight + m_param->maxCUSize - 1) / m_param->maxCUSize;<br>+                uint32_t numCuInHeight = (frameEnc[0]->m_encData->m_reconPic[0]->m_picHeight + m_param->maxCUSize - 1) / m_param->maxCUSize;<br>                 int maxHeight = numCuInHeight * m_param->maxCUSize;<br>                 for (int i = 0; i < INTEGRAL_PLANE_NUM; i++)<br>                 {<br>-                    frameEnc[0]->m_encData->m_meBuffer[i] = X265_MALLOC(uint32_t, frameEnc[0]->m_reconPic->m_stride * (maxHeight + (2 * padY)));<br>+                    frameEnc[0]->m_encData->m_meBuffer[i] = X265_MALLOC(uint32_t, frameEnc[0]->m_reconPic[0]->m_stride * (maxHeight + (2 * padY)));<br>                     if (frameEnc[0]->m_encData->m_meBuffer[i])<br>                     {<br>-                        memset(frameEnc[0]->m_encData->m_meBuffer[i], 0, sizeof(uint32_t)* frameEnc[0]->m_reconPic->m_stride * (maxHeight + (2 * padY)));<br>-                        frameEnc[0]->m_encData->m_meIntegral[i] = frameEnc[0]->m_encData->m_meBuffer[i] + frameEnc[0]->m_encData->m_reconPic->m_stride * padY + padX;<br>+                        memset(frameEnc[0]->m_encData->m_meBuffer[i], 0, sizeof(uint32_t)* frameEnc[0]->m_reconPic[0]->m_stride * (maxHeight + (2 * padY)));<br>+                        frameEnc[0]->m_encData->m_meIntegral[i] = frameEnc[0]->m_encData->m_meBuffer[i] + frameEnc[0]->m_encData->m_reconPic[0]->m_stride * padY + padX;<br>                     }<br>                     else<br>                         x265_log(m_param, X265_LOG_ERROR, "SEA motion search: POC %d Integral buffer[%d] unallocated\n", frameEnc[0]->m_poc, i);<br>@@ -3072,7 +3072,7 @@ void Encoder::fetchStats(x265_stats *stats, size_t statsSizeBytes, int layer)<br> <br> void Encoder::finishFrameStats(Frame* curFrame, FrameEncoder *curEncoder, x265_frame_stats* frameStats, int inPoc, int layer)<br> {<br>-    PicYuv* reconPic = curFrame->m_reconPic;<br>+    PicYuv* reconPic = curFrame->m_reconPic[0];<br>     uint64_t bits = curEncoder->m_accessUnitBits[layer];<br> <br>     //===== calculate PSNR =====<br>diff --git a/source/encoder/entropy.cpp b/source/encoder/entropy.cpp<br>index 2ec93ab6a..22408e6f3 100644<br>--- a/source/encoder/entropy.cpp<br>+++ b/source/encoder/entropy.cpp<br>@@ -997,7 +997,7 @@ void Entropy::codeSliceHeader(const Slice& slice, FrameData& encData, uint32_t s<br>         }<br> <br>         if (slice.m_sps->bTemporalMVPEnabled)<br>-            WRITE_FLAG(1, "slice_temporal_mvp_enable_flag");<br>+            WRITE_FLAG(slice.m_bTemporalMvp, "slice_temporal_mvp_enable_flag");<br>     }<br>     const SAOParam *saoParam = encData.m_saoParam;<br>     if (slice.m_bUseSao)<br>@@ -1039,7 +1039,7 @@ void Entropy::codeSliceHeader(const Slice& slice, FrameData& encData, uint32_t s<br>     if (slice.isInterB())<br>         WRITE_FLAG(slice.m_bLMvdL1Zero, "mvd_l1_zero_flag");<br> <br>-    if (slice.m_sps->bTemporalMVPEnabled)<br>+    if (slice.m_bTemporalMvp)<br>     {<br>         if (slice.m_sliceType == B_SLICE)<br>             WRITE_FLAG(slice.m_colFromL0Flag, "collocated_from_l0_flag");<br>diff --git a/source/encoder/frameencoder.cpp b/source/encoder/frameencoder.cpp<br>index 0ee3e9a2e..286eb520a 100644<br>--- a/source/encoder/frameencoder.cpp<br>+++ b/source/encoder/frameencoder.cpp<br>@@ -591,7 +591,7 @@ void FrameEncoder::compressFrame(int layer)<br>             WeightParam *w = NULL;<br>             if ((bUseWeightP || bUseWeightB) && slice->m_weightPredTable[l][ref][0].wtPresent)<br>                 w = slice->m_weightPredTable[l][ref];<br>-            slice->m_refReconPicList[l][ref] = slice->m_refFrameList[l][ref]->m_reconPic;<br>+            slice->m_refReconPicList[l][ref] = slice->m_refFrameList[l][ref]->m_reconPic[0];<br>             m_mref[l][ref].init(slice->m_refReconPicList[l][ref], w, *m_param);<br>         }<br>         if (m_param->analysisSave && (bUseWeightP || bUseWeightB))<br>@@ -988,7 +988,7 @@ void FrameEncoder::compressFrame(int layer)<br> <br>     if (m_param->maxSlices > 1)<br>     {<br>-        PicYuv *reconPic = m_frame[layer]->m_reconPic;<br>+        PicYuv *reconPic = m_frame[layer]->m_reconPic[0];<br>         uint32_t height = reconPic->m_picHeight;<br>         initDecodedPictureHashSEI(0, 0, height, layer);<br>     } <br>@@ -1252,7 +1252,7 @@ void FrameEncoder::compressFrame(int layer)<br> <br> void FrameEncoder::initDecodedPictureHashSEI(int row, int cuAddr, int height, int layer)<br> {<br>-    PicYuv *reconPic = m_frame[layer]->m_reconPic;<br>+    PicYuv *reconPic = m_frame[layer]->m_reconPic[0];<br>     uint32_t width = reconPic->m_picWidth;    <br>     intptr_t stride = reconPic->m_stride;<br>     uint32_t maxCUHeight = m_param->maxCUSize;<br>@@ -2263,7 +2263,7 @@ void FrameEncoder::readModel(FilmGrainCharacteristics* m_filmGrain, FILE* filmgr<br> void FrameEncoder::vmafFrameLevelScore()<br> {<br>     PicYuv *fenc = m_frame->m_fencPic;<br>-    PicYuv *recon = m_frame->m_reconPic;<br>+    PicYuv *recon = m_frame->m_reconPic[0];<br> <br>     x265_vmaf_framedata *vmafframedata = (x265_vmaf_framedata*)x265_malloc(sizeof(x265_vmaf_framedata));<br>     if (!vmafframedata)<br>diff --git a/source/encoder/framefilter.cpp b/source/encoder/framefilter.cpp<br>index da01d0ceb..344ac738d 100644<br>--- a/source/encoder/framefilter.cpp<br>+++ b/source/encoder/framefilter.cpp<br>@@ -256,7 +256,7 @@ static void restoreOrigLosslessYuv(const CUData* cu, Frame& frame, uint32_t absP<br>     const int size = cu->m_log2CUSize[absPartIdx] - 2;<br>     const uint32_t cuAddr = cu->m_cuAddr;<br> <br>-    PicYuv* reconPic = frame.m_reconPic;<br>+    PicYuv* reconPic = frame.m_reconPic[0];<br>     PicYuv* fencPic  = frame.m_fencPic;<br> <br>     pixel* dst = reconPic->getLumaAddr(cuAddr, absPartIdx);<br>@@ -337,7 +337,7 @@ void FrameFilter::ParallelFilter::processSaoCTU(SAOParam *saoParam, int col)<br> <br>         uint32_t cuAddr = m_rowAddr + col;<br>         const CUData* ctu = m_encData->getPicCTU(cuAddr);<br>-        assert(m_frameFilter->m_frame->m_reconPic == m_encData->m_reconPic);<br>+        assert(m_frameFilter->m_frame->m_reconPic[0] == m_encData->m_reconPic[0]);<br>         origCUSampleRestoration(ctu, cuGeoms[ctuGeomMap[cuAddr]], *m_frameFilter->m_frame);<br>     }<br> }<br>@@ -352,7 +352,7 @@ void FrameFilter::ParallelFilter::processPostCu(int col) const<br>     if ((col != 0) & (col != m_frameFilter->m_numCols - 1) & (m_row != 0) & (m_row != m_frameFilter->m_numRows - 1))<br>         return;<br> <br>-    PicYuv *reconPic = m_frameFilter->m_frame->m_reconPic;<br>+    PicYuv *reconPic = m_frameFilter->m_frame->m_reconPic[0];<br>     const uint32_t lineStartCUAddr = m_rowAddr + col;<br>     const int realH = getCUHeight();<br>     const int realW = m_frameFilter->getCUWidth(col);<br>@@ -441,7 +441,7 @@ void FrameFilter::ParallelFilter::processTasks(int /*workerThreadId*/)<br>     SAOParam* saoParam = m_encData->m_saoParam;<br>     const CUGeom* cuGeoms = m_frameFilter->m_frameEncoder->m_cuGeoms;<br>     const uint32_t* ctuGeomMap = m_frameFilter->m_frameEncoder->m_ctuGeomMap;<br>-    PicYuv* reconPic = m_encData->m_reconPic;<br>+    PicYuv* reconPic = m_encData->m_reconPic[0];<br>     const int colStart = m_lastCol.get();<br>     const int numCols = m_frameFilter->m_numCols;<br>     // TODO: Waiting previous row finish or simple clip on it?<br>@@ -653,7 +653,7 @@ void FrameFilter::processRow(int row, int layer)<br> <br> void FrameFilter::processPostRow(int row, int layer)<br> {<br>-    PicYuv *reconPic = m_frame->m_reconPic;<br>+    PicYuv *reconPic = m_frame->m_reconPic[0];<br>     const uint32_t numCols = m_frame->m_encData->m_slice->m_sps->numCuInWidth;<br>     const uint32_t lineStartCUAddr = row * numCols;<br> <br>@@ -737,7 +737,7 @@ void FrameFilter::computeMEIntegral(int row)<br>             }<br>         }<br> <br>-        int stride = (int)m_frame->m_reconPic->m_stride;<br>+        int stride = (int)m_frame->m_reconPic[0]->m_stride;<br>         int padX = m_param->maxCUSize + 32;<br>         int padY = m_param->maxCUSize + 16;<br>         int numCuInHeight = m_frame->m_encData->m_slice->m_sps->numCuInHeight;<br>@@ -763,7 +763,7 @@ void FrameFilter::computeMEIntegral(int row)<br> <br>         for (int y = startRow; y < height; y++)<br>         {<br>-            pixel    *pix = m_frame->m_reconPic->m_picOrg[0] + y * stride - padX;<br>+            pixel    *pix = m_frame->m_reconPic[0]->m_picOrg[0] + y * stride - padX;<br>             uint32_t *sum32x32 = m_frame->m_encData->m_meIntegral[0] + (y + 1) * stride - padX;<br>             uint32_t *sum32x24 = m_frame->m_encData->m_meIntegral[1] + (y + 1) * stride - padX;<br>             uint32_t *sum32x8 = m_frame->m_encData->m_meIntegral[2] + (y + 1) * stride - padX;<br>diff --git a/source/encoder/level.cpp b/source/encoder/level.cpp<br>index b5af25b4f..84f407702 100644<br>--- a/source/encoder/level.cpp<br>+++ b/source/encoder/level.cpp<br>@@ -178,7 +178,7 @@ void determineLevel(const x265_param &param, VPS& vps)<br>     uint32_t samplesPerSec = (uint32_t)(lumaSamples * ((double)param.fpsNum / param.fpsDenom));<br>     uint32_t bitrate = param.rc.vbvMaxBitrate ? param.rc.vbvMaxBitrate : param.rc.bitrate;<br> <br>-    const uint32_t MaxDpbPicBuf = 6;<br>+    const uint32_t MaxDpbPicBuf = !!param.bEnableSCC ? 7 : 6;<br>     vps.ptl.levelIdc = Level::NONE;<br>     vps.ptl.tierFlag = Level::MAIN;<br> <br>@@ -388,7 +388,7 @@ bool enforceLevel(x265_param& param, VPS& vps)<br>     for (uint32_t i = 0; i < vps.maxTempSubLayers; i++)<br>     {<br>         vps.numReorderPics[i] = (i == 0) ? ((param.bBPyramid && param.bframes > 1) ? 2 : !!param.bframes) : i;<br>-        vps.maxDecPicBuffering[i] = X265_MIN(MAX_NUM_REF, X265_MAX(vps.numReorderPics[i] + 2, (uint32_t)param.maxNumReferences) + 1);<br>+        vps.maxDecPicBuffering[i] = X265_MIN(MAX_NUM_REF, X265_MAX(vps.numReorderPics[i] + 2, (uint32_t)param.maxNumReferences) + 1) + !!param.bEnableSCC;<br>     }<br> <br>     if (!!param.bEnableTemporalSubLayers)<br>@@ -504,7 +504,7 @@ bool enforceLevel(x265_param& param, VPS& vps)<br>     }<br> <br>     /* The value of sps_max_dec_pic_buffering_minus1[ HighestTid ] + 1 shall be less than or equal to MaxDpbSize */<br>-    const uint32_t MaxDpbPicBuf = 6;<br>+    const uint32_t MaxDpbPicBuf = !!param.bEnableSCC ? 7 : 6;<br>     uint32_t maxDpbSize = MaxDpbPicBuf;<br>     if (!param.uhdBluray) /* Do not change MaxDpbPicBuf for UHD-Bluray */<br>     {<br>@@ -519,8 +519,7 @@ bool enforceLevel(x265_param& param, VPS& vps)<br>     int savedRefCount = param.maxNumReferences;<br>     while (vps.maxDecPicBuffering[vps.maxTempSubLayers - 1] > maxDpbSize && param.maxNumReferences > 1)<br>     {<br>-        param.maxNumReferences--;<br>-        vps.maxDecPicBuffering[vps.maxTempSubLayers - 1] = X265_MIN(MAX_NUM_REF, X265_MAX(vps.numReorderPics[vps.maxTempSubLayers - 1] + 1, (uint32_t)param.maxNumReferences) + 1);<br>+        vps.maxDecPicBuffering[vps.maxTempSubLayers - 1] = X265_MIN(MAX_NUM_REF, X265_MAX(vps.numReorderPics[vps.maxTempSubLayers - 1] + 1, (uint32_t)param.maxNumReferences) + 1 + !!param.bEnableSCC);<br>     }<br>     if (param.maxNumReferences != savedRefCount)<br>         x265_log(&param, X265_LOG_WARNING, "Lowering max references to %d to meet level requirement\n", param.maxNumReferences);<br>diff --git a/source/encoder/sao.cpp b/source/encoder/sao.cpp<br>index 105ec79de..329f36ccf 100644<br>--- a/source/encoder/sao.cpp<br>+++ b/source/encoder/sao.cpp<br>@@ -267,7 +267,7 @@ void SAO::startSlice(Frame* frame, Entropy& initState)<br> // CTU-based SAO process without slice granularity<br> void SAO::applyPixelOffsets(int addr, int typeIdx, int plane)<br> {<br>-    PicYuv* reconPic = m_frame->m_reconPic;<br>+    PicYuv* reconPic = m_frame->m_reconPic[0];<br>     pixel* rec = reconPic->getPlaneAddr(plane, addr);<br>     intptr_t stride = plane ? reconPic->m_strideC : reconPic->m_stride;<br>     uint32_t picWidth  = m_param->sourceWidth;<br>@@ -565,7 +565,7 @@ void SAO::applyPixelOffsets(int addr, int typeIdx, int plane)<br> /* Process SAO unit */<br> void SAO::generateLumaOffsets(SaoCtuParam* ctuParam, int idxY, int idxX)<br> {<br>-    PicYuv* reconPic = m_frame->m_reconPic;<br>+    PicYuv* reconPic = m_frame->m_reconPic[0];<br>     intptr_t stride = reconPic->m_stride;<br>     int ctuWidth = m_param->maxCUSize;<br>     int ctuHeight = m_param->maxCUSize;<br>@@ -625,7 +625,7 @@ void SAO::generateLumaOffsets(SaoCtuParam* ctuParam, int idxY, int idxX)<br> /* Process SAO unit (Chroma only) */<br> void SAO::generateChromaOffsets(SaoCtuParam* ctuParam[3], int idxY, int idxX)<br> {<br>-    PicYuv* reconPic = m_frame->m_reconPic;<br>+    PicYuv* reconPic = m_frame->m_reconPic[0];<br>     intptr_t stride = reconPic->m_strideC;<br>     int ctuWidth  = m_param->maxCUSize;<br>     int ctuHeight = m_param->maxCUSize;<br>@@ -729,7 +729,7 @@ void SAO::generateChromaOffsets(SaoCtuParam* ctuParam[3], int idxY, int idxX)<br> void SAO::calcSaoStatsCTU(int addr, int plane)<br> {<br>     Slice* slice = m_frame->m_encData->m_slice;<br>-    const PicYuv* reconPic = m_frame->m_reconPic;<br>+    const PicYuv* reconPic = m_frame->m_reconPic[0];<br>     const CUData* cu = m_frame->m_encData->getPicCTU(addr);<br>     const pixel* fenc0 = m_frame->m_fencPic->getPlaneAddr(plane, addr);<br>     const pixel* rec0  = reconPic->getPlaneAddr(plane, addr);<br>@@ -916,7 +916,7 @@ void SAO::calcSaoStatsCu_BeforeDblk(Frame* frame, int idxX, int idxY)<br> <br>     int x, y;<br>     const CUData* cu = frame->m_encData->getPicCTU(addr);<br>-    const PicYuv* reconPic = m_frame->m_reconPic;<br>+    const PicYuv* reconPic = m_frame->m_reconPic[0];<br>     const pixel* fenc;<br>     const pixel* rec;<br>     intptr_t stride = reconPic->m_stride;<br>diff --git a/source/encoder/search.cpp b/source/encoder/search.cpp<br>index ba220eaa6..3a5c54ffa 100644<br>--- a/source/encoder/search.cpp<br>+++ b/source/encoder/search.cpp<br>@@ -497,7 +497,7 @@ void Search::codeIntraLumaQT(Mode& mode, const CUGeom& cuGeom, uint32_t tuDepth,<br>     }<br> <br>     // set reconstruction for next intra prediction blocks if full TU prediction won<br>-    PicYuv*  reconPic = m_frame->m_reconPic;<br>+    PicYuv*  reconPic = m_frame->m_reconPic[0];<br>     pixel*   picReconY = reconPic->getLumaAddr(cu.m_cuAddr, cuGeom.absPartIdx + absPartIdx);<br>     intptr_t picStride = reconPic->m_stride;<br>     <a href="http://primitives.cu" target="_blank">primitives.cu</a>[sizeIdx].copy_pp(picReconY, picStride, reconQt, reconQtStride);<br>@@ -673,7 +673,7 @@ void Search::codeIntraLumaTSkip(Mode& mode, const CUGeom& cuGeom, uint32_t tuDep<br>     }<br> <br>     // set reconstruction for next intra prediction blocks<br>-    PicYuv*  reconPic = m_frame->m_reconPic;<br>+    PicYuv*  reconPic = m_frame->m_reconPic[0];<br>     pixel*   picReconY = reconPic->getLumaAddr(cu.m_cuAddr, cuGeom.absPartIdx + absPartIdx);<br>     intptr_t picStride = reconPic->m_stride;<br>     <a href="http://primitives.cu" target="_blank">primitives.cu</a>[sizeIdx].copy_pp(picReconY, picStride, reconQt, reconQtStride);<br>@@ -724,7 +724,7 @@ void Search::residualTransformQuantIntra(Mode& mode, const CUGeom& cuGeom, uint3<br>         uint32_t sizeIdx   = log2TrSize - 2;<br>         <a href="http://primitives.cu" target="_blank">primitives.cu</a>[sizeIdx].calcresidual[stride % 64 == 0](fenc, pred, residual, stride);<br> <br>-        PicYuv*  reconPic = m_frame->m_reconPic;<br>+        PicYuv*  reconPic = m_frame->m_reconPic[0];<br>         pixel*   picReconY = reconPic->getLumaAddr(cu.m_cuAddr, cuGeom.absPartIdx + absPartIdx);<br>         intptr_t picStride = reconPic->m_stride;<br> <br>@@ -888,7 +888,7 @@ void Search::codeIntraChromaQt(Mode& mode, const CUGeom& cuGeom, uint32_t tuDept<br>             coeff_t* coeffC        = m_rqt[qtLayer].coeffRQT[chromaId] + coeffOffsetC;<br>             pixel*   reconQt       = m_rqt[qtLayer].reconQtYuv.getChromaAddr(chromaId, absPartIdxC);<br>             uint32_t reconQtStride = m_rqt[qtLayer].reconQtYuv.m_csize;<br>-            PicYuv*  reconPic = m_frame->m_reconPic;<br>+            PicYuv*  reconPic = m_frame->m_reconPic[0];<br>             pixel*   picReconC = reconPic->getChromaAddr(chromaId, cu.m_cuAddr, cuGeom.absPartIdx + absPartIdxC);<br>             intptr_t picStride = reconPic->m_strideC;<br> <br>@@ -1079,7 +1079,7 @@ void Search::codeIntraChromaTSkip(Mode& mode, const CUGeom& cuGeom, uint32_t tuD<br>             cu.setCbfPartRange(bCbf << tuDepth, ttype, absPartIdxC, tuIterator.absPartIdxStep);<br>             cu.setTransformSkipPartRange(bTSkip, ttype, absPartIdxC, tuIterator.absPartIdxStep);<br> <br>-            PicYuv*  reconPic = m_frame->m_reconPic;<br>+            PicYuv*  reconPic = m_frame->m_reconPic[0];<br>             pixel*   reconPicC = reconPic->getChromaAddr(chromaId, cu.m_cuAddr, cuGeom.absPartIdx + absPartIdxC);<br>             intptr_t picStride = reconPic->m_strideC;<br>             <a href="http://primitives.cu" target="_blank">primitives.cu</a>[sizeIdxC].copy_pp(reconPicC, picStride, reconQt, reconQtStride);<br>@@ -1186,7 +1186,7 @@ void Search::residualQTIntraChroma(Mode& mode, const CUGeom& cuGeom, uint32_t ab<br>             int16_t* residual = resiYuv.getChromaAddr(chromaId, absPartIdxC);<br>             uint32_t coeffOffsetC  = absPartIdxC << (LOG2_UNIT_SIZE * 2 - (m_hChromaShift + m_vChromaShift));<br>             coeff_t* coeffC        = cu.m_trCoeff[ttype] + coeffOffsetC;<br>-            PicYuv*  reconPic = m_frame->m_reconPic;<br>+            PicYuv*  reconPic = m_frame->m_reconPic[0];<br>             pixel*   picReconC = reconPic->getChromaAddr(chromaId, cu.m_cuAddr, cuGeom.absPartIdx + absPartIdxC);<br>             intptr_t picStride = reconPic->m_strideC;<br> <br>@@ -1285,6 +1285,9 @@ void Search::checkIntra(Mode& intraMode, const CUGeom& cuGeom, PartSize partSize<br> <br>     updateModeCost(intraMode);<br>     checkDQP(intraMode, cuGeom);<br>+<br>+    if (!!m_param->bEnableSCC)<br>+        intraMode.reconYuv.copyToPicYuv(*m_frame->m_reconPic[1], cu.m_cuAddr, cuGeom.absPartIdx);<br> }<br> <br> /* Note that this function does not save the best intra prediction, it must<br>@@ -1672,7 +1675,7 @@ sse_t Search::estIntraPredQT(Mode &intraMode, const CUGeom& cuGeom, const uint32<br>              * output recon picture, so it cannot proceed in parallel with anything else when doing INTRA_NXN. Also<br>              * it is not updating m_rdContexts[depth].cur for the later PUs which I suspect is slightly wrong. I think<br>              * that the contexts should be tracked through each PU */<br>-            PicYuv*  reconPic = m_frame->m_reconPic;<br>+            PicYuv*  reconPic = m_frame->m_reconPic[0];<br>             pixel*   dst       = reconPic->getLumaAddr(cu.m_cuAddr, cuGeom.absPartIdx + absPartIdx);<br>             uint32_t dststride = reconPic->m_stride;<br>             const pixel*   src = reconYuv->getLumaAddr(absPartIdx);<br>@@ -1845,7 +1848,7 @@ sse_t Search::estIntraPredChromaQT(Mode &intraMode, const CUGeom& cuGeom)<br>         if (!tuIterator.isLastSection())<br>         {<br>             uint32_t zorder    = cuGeom.absPartIdx + absPartIdxC;<br>-            PicYuv*  reconPic  = m_frame->m_reconPic;<br>+            PicYuv*  reconPic  = m_frame->m_reconPic[0];<br>             uint32_t dststride = reconPic->m_strideC;<br>             const pixel* src;<br>             pixel* dst;<br>@@ -2008,7 +2011,10 @@ int Search::selectMVP(const CUData& cu, const PredictionUnit& pu, const MV amvp[<br>                 continue;<br>         }<br>         cu.clipMv(mvCand);<br>-        predInterLumaPixel(pu, tmpPredYuv, *m_slice->m_refReconPicList[list][ref], mvCand);<br>+        if (!!m_slice->m_param->bEnableSCC && !list && ref == m_slice->m_numRefIdx[0] - 1)<br>+            predInterLumaPixel(pu, tmpPredYuv, *m_slice->m_refFrameList[list][ref]->m_reconPic[1], mvCand);<br>+        else<br>+            predInterLumaPixel(pu, tmpPredYuv, *m_slice->m_refReconPicList[list][ref], mvCand);<br>         costs[i] = m_me.bufSAD(tmpPredYuv.getLumaAddr(pu.puAbsPartIdx), tmpPredYuv.m_size);<br>     }<br> <br>@@ -2263,7 +2269,7 @@ void Search::predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChroma<br>                     int puX = puIdx & 1;<br>                     int puY = puIdx >> 1;<br>                     for (int planes = 0; planes < INTEGRAL_PLANE_NUM; planes++)<br>-                        m_me.integral[planes] = interMode.fencYuv->m_integral[list][ref][planes] + puX * pu.width + puY * pu.height * m_slice->m_refFrameList[list][ref]->m_reconPic->m_stride;<br>+                        m_me.integral[planes] = interMode.fencYuv->m_integral[list][ref][planes] + puX * pu.width + puY * pu.height * m_slice->m_refFrameList[list][ref]->m_reconPic[0]->m_stride;<br>                 }<br>                 setSearchRange(cu, mvp, m_param->searchRange, mvmin, mvmax);<br>                 MV mvpIn = mvp;<br>@@ -2432,7 +2438,7 @@ void Search::predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChroma<br>                         int puX = puIdx & 1;<br>                         int puY = puIdx >> 1;<br>                         for (int planes = 0; planes < INTEGRAL_PLANE_NUM; planes++)<br>-                            m_me.integral[planes] = interMode.fencYuv->m_integral[list][ref][planes] + puX * pu.width + puY * pu.height * m_slice->m_refFrameList[list][ref]->m_reconPic->m_stride;<br>+                            m_me.integral[planes] = interMode.fencYuv->m_integral[list][ref][planes] + puX * pu.width + puY * pu.height * m_slice->m_refFrameList[list][ref]->m_reconPic[0]->m_stride;<br>                     }<br>                     m_vertRestriction = cu.m_slice->m_refPOCList[list][ref] == cu.m_slice->m_poc;<br>                     setSearchRange(cu, mvp, m_param->searchRange, mvmin, mvmax);<br>@@ -2731,12 +2737,12 @@ int Search::intraBCSearchMVChromaRefine(Mode& intraBCMode,<br> <br>         for (uint32_t ch = TEXT_CHROMA_U; ch < MAX_NUM_COMPONENT; ch++)<br>         {<br>-            ref = m_slice->m_refFrameList[0][m_slice->m_numRefIdx[0] - 1]->m_reconPic->getChromaAddr(ch, cu.m_cuAddr, cu.m_absIdxInCTU + partOffset);<br>+            ref = m_slice->m_refFrameList[0][m_slice->m_numRefIdx[0] - 1]->m_reconPic[1]->getChromaAddr(ch, cu.m_cuAddr, cu.m_absIdxInCTU + partOffset);<br> <br>             picOrg = intraBCMode.fencYuv->getChromaAddr(ch, partOffset);<br>             orgStride = intraBCMode.fencYuv->m_csize;<br> <br>-            refStride = m_frame->m_reconPic->m_strideC;<br>+            refStride = m_frame->m_reconPic[1]->m_strideC;<br> <br>             width = roiWidth >> m_hChromaShift;<br>             height = roiHeight >> m_vChromaShift;<br>@@ -3545,8 +3551,8 @@ void Search::intraBlockCopyEstimate(Mode& intraBCMode, const CUGeom& cuGeom, int<br>     assert(nPSH == roiHeight);<br> <br>     int ref = m_slice->m_numRefIdx[0] - 1;<br>-    pixel* refY = m_slice->m_refFrameList[0][ref]->m_reconPic->getLumaAddr(cu.m_cuAddr, cu.m_absIdxInCTU + partAddr);<br>-    int  strideY = m_slice->m_refFrameList[0][ref]->m_reconPic->m_stride;<br>+    pixel* refY = m_slice->m_refFrameList[0][ref]->m_reconPic[1]->getLumaAddr(cu.m_cuAddr, cu.m_absIdxInCTU + partAddr);<br>+    int  strideY = m_slice->m_refFrameList[0][ref]->m_reconPic[1]->m_stride;<br> <br>     setIntraSearchRange(intraBCMode, mvPred, puIdx, roiWidth, roiHeight, searchRangeLT, searchRangeRB);<br> <br>@@ -4769,6 +4775,9 @@ void Search::encodeResAndCalcRdInterCU(Mode& interMode, const CUGeom& cuGeom)<br>     cu.m_distortion[0] = interMode.distortion;<br>     updateModeCost(interMode);<br>     checkDQP(interMode, cuGeom);<br>+<br>+    if (!!m_param->bEnableSCC)<br>+        interMode.reconYuv.copyToPicYuv(*m_frame->m_reconPic[1], cu.m_cuAddr, cuGeom.absPartIdx);<br> }<br> <br> void Search::residualTransformQuantInter(Mode& mode, const CUGeom& cuGeom, uint32_t absPartIdx, uint32_t tuDepth, const uint32_t depthRange[2])<br>-- <br>2.36.0.windows.1<br><br></div>