[x265] [PATCH SCC 08/09] Add compile-time flag for scc

Anusuya Kumarasamy anusuya.kumarasamy at multicorewareinc.com
Wed Aug 7 17:24:11 UTC 2024


>From 4bf3e68331547af4565c0a96cb537b8cd5d22b89 Mon Sep 17 00:00:00 2001
From: AnusuyaKumarasamy <anusuya.kumarasamy at multicorewareinc.com>
Date: Fri, 26 Jul 2024 21:16:22 +0530
Subject: [PATCH 8/9] Add compile-time flag for scc

---
 doc/reST/cli.rst                    | 16 ++++++++++
 source/CMakeLists.txt               |  5 ++++
 source/common/cudata.cpp            | 27 ++++++++++++-----
 source/common/cudata.h              |  6 ++++
 source/common/frame.cpp             |  9 +++---
 source/common/frame.h               |  2 +-
 source/common/framedata.h           |  2 +-
 source/common/param.cpp             |  9 ++++++
 source/common/predict.cpp           | 16 +++++++---
 source/common/slice.cpp             | 14 +++++++++
 source/common/slice.h               | 12 ++++++--
 source/encoder/analysis.cpp         | 32 +++++++++++++++++++-
 source/encoder/analysis.h           |  6 +++-
 source/encoder/dpb.cpp              |  4 ++-
 source/encoder/encoder.cpp          |  4 +++
 source/encoder/entropy.cpp          | 22 ++++++++++++++
 source/encoder/frameencoder.cpp     |  4 +++
 source/encoder/level.cpp            | 25 +++++++++++-----
 source/encoder/search.cpp           | 45 +++++++++++++++++++++++++++--
 source/encoder/search.h             |  5 ++++
 source/encoder/weightPrediction.cpp |  2 ++
 source/x265.h                       |  7 +++++
 source/x265cli.cpp                  |  2 ++
 source/x265cli.h                    |  2 ++
 24 files changed, 243 insertions(+), 35 deletions(-)

diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
index 298ee334a..f1aca5320 100755
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -2923,4 +2923,20 @@ Multiview Encode Options

 **CLI_ONLY**

+
+Screen Content Coding Options
+===================
+.. option:: --scc <integer>
+
+    Enable screen content coding support in x265. Default disabled.
+    This option can be enabled only when ENABLE_SCC_EXT is set during the
make of x265.
+    SCC enables intrablockcopy in CTU analysis which can be enabled in two
modes [1-2].
+    Mode 1- Does limited search,faster than mode 2
+    Mode 2- Does full and exhaustive search
+
+    Note : Enabling SCC will disable weight prediction.
+           Enabling SCC expects rd-level of 6.
+
+    **CLI_ONLY**
+
 .. vim: noet
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index 9abf607d4..140625181 100755
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -605,6 +605,11 @@ if(ENABLE_MULTIVIEW)
     add_definitions(-DENABLE_MULTIVIEW)
 endif()

+option(ENABLE_SCC_EXT "Enable screen content coding extension in HEVC" OFF)
+if(ENABLE_SCC_EXT)
+    add_definitions(-DENABLE_SCC_EXT)
+endif()
+
 add_subdirectory(encoder)
 add_subdirectory(common)

diff --git a/source/common/cudata.cpp b/source/common/cudata.cpp
index e95f4830d..23ceeaeaf 100644
--- a/source/common/cudata.cpp
+++ b/source/common/cudata.cpp
@@ -290,8 +290,10 @@ void CUData::initCTU(const Frame& frame, uint32_t
cuAddr, int qp, uint32_t first
     m_bFirstRowInSlice = (uint8_t)firstRowInSlice;
     m_bLastRowInSlice  = (uint8_t)lastRowInSlice;
     m_bLastCuInSlice   = (uint8_t)lastCuInSlice;
+#if ENABLE_SCC_EXT
     m_lastIntraBCMv[0].set(0, 0);
     m_lastIntraBCMv[1].set(0, 0);
+#endif

     /* sequential memsets */
     m_partSet((uint8_t*)m_qp, (uint8_t)qp);
@@ -363,11 +365,13 @@ void CUData::initSubCU(const CUData& ctu, const
CUGeom& cuGeom, int qp, MV lastI
     memset(m_predMode, 0, (ctu.m_chromaFormat == X265_CSP_I400 ?
BytesPerPartition - 13 : BytesPerPartition - 9) * m_numPartitions);
     memset(m_distortion, 0, m_numPartitions * sizeof(sse_t));

+#if ENABLE_SCC_EXT
     if (lastIntraBCMv)
     {
         for (int i = 0; i < 2; i++)
             m_lastIntraBCMv[i] = lastIntraBCMv[i];
     }
+#endif
 }

 /* Copy the results of a sub-part (split) CU to the parent CU */
@@ -423,8 +427,10 @@ void CUData::copyPartFrom(const CUData& subCU, const
CUGeom& childGeom, uint32_t
         memcpy(m_trCoeff[1] + tmpC2, subCU.m_trCoeff[1], sizeof(coeff_t) *
tmpC);
         memcpy(m_trCoeff[2] + tmpC2, subCU.m_trCoeff[2], sizeof(coeff_t) *
tmpC);
     }
+#if ENABLE_SCC_EXT
     for (int i = 0; i < 2; i++)
         m_lastIntraBCMv[i] = subCU.m_lastIntraBCMv[i];
+#endif
 }

 /* If a sub-CU part is not present (off the edge of the picture) its depth
and
@@ -1601,7 +1607,11 @@ uint32_t CUData::getInterMergeCandidates(uint32_t
absPartIdx, uint32_t puIdx, MV
                 return maxNumMergeCand;
         }
     }
+#if ENABLE_SCC_EXT
     if (m_slice->m_bTemporalMvp)
+#else
+    if (m_slice->m_sps->bTemporalMVPEnabled)
+#endif
     {
         uint32_t partIdxRB = deriveRightBottomIdx(puIdx);
         MV colmv;
@@ -1692,8 +1702,10 @@ uint32_t CUData::getInterMergeCandidates(uint32_t
absPartIdx, uint32_t puIdx, MV
         }
     }
     int numRefIdx0 = m_slice->m_numRefIdx[0];
+#if ENABLE_SCC_EXT
     if (m_slice->m_param->bEnableSCC)
         numRefIdx0--;
+#endif
     int numRefIdx = (isInterB) ? X265_MIN(numRefIdx0,
m_slice->m_numRefIdx[1]) : numRefIdx0;
     int r = 0;
     int refcnt = 0;
@@ -1732,7 +1744,7 @@ int CUData::getPMV(InterNeighbourMV* neighbours,
uint32_t picList, uint32_t refI
     bool validDirect[MD_ABOVE_LEFT + 1];
     bool validIndirect[MD_ABOVE_LEFT + 1];

-#if ENABLE_MULTIVIEW
+#if (ENABLE_MULTIVIEW || ENABLE_SCC_EXT)
     if (m_slice->m_param->numViews > 1 || m_slice->m_param->bEnableSCC)
     {
         // Left candidate.
@@ -1827,8 +1839,8 @@ int CUData::getPMV(InterNeighbourMV* neighbours,
uint32_t picList, uint32_t refI

     // Get the collocated candidate. At this step, either the first
candidate
     // was found or its value is 0.
-#if ENABLE_MULTIVIEW
-    if (m_slice->m_param->numViews > 1 || !!m_slice->m_param->bEnableSCC)
+#if ENABLE_MULTIVIEW || ENABLE_SCC_EXT
+    if (m_slice->m_param->numViews > 1 || m_slice->m_param->bEnableSCC)
     {
         if (m_slice->m_bTemporalMvp && num < 2)
         {
@@ -1921,7 +1933,7 @@ void CUData::getNeighbourMV(uint32_t puIdx, uint32_t
absPartIdx, InterNeighbourM
     getInterNeighbourMV(neighbours + MD_ABOVE,      partIdxRT, MD_ABOVE);
     getInterNeighbourMV(neighbours + MD_ABOVE_LEFT, partIdxLT,
MD_ABOVE_LEFT);

-    if (m_slice->m_bTemporalMvp && !(!!m_slice->m_param->bEnableSCC ||
m_slice->m_param->numViews > 1))
+    if (m_slice->m_bTemporalMvp && !(m_slice->m_param->bEnableSCC ||
m_slice->m_param->numViews > 1))
     {
         uint32_t absPartAddr = m_absIdxInCTU + absPartIdx;
         uint32_t partIdxRB = deriveRightBottomIdx(puIdx);
@@ -2059,7 +2071,7 @@ bool CUData::getIndirectPMV(MV& outMV,
InterNeighbourMV *neighbours, uint32_t pi
             int neibRefPOC = m_slice->m_refPOCList[picList][partRefIdx];
             MV mvp = neighbours->mv[picList];

-#if ENABLE_MULTIVIEW
+#if ENABLE_MULTIVIEW || ENABLE_SCC_EXT
             if ((curRefPOC == curPOC) == (neibRefPOC == curPOC))
             {
                 if (curRefPOC == curPOC)
@@ -2107,7 +2119,7 @@ bool CUData::getColMVP(MV& outMV, int& outRefIdx, int
picList, int cuAddr, int p
     int curRefPOC = m_slice->m_refPOCList[picList][outRefIdx];
     int curPOC = m_slice->m_poc;

-#if ENABLE_MULTIVIEW
+#if ENABLE_MULTIVIEW || ENABLE_SCC_EXT
     if ((colPOC == colRefPOC) != (curPOC == curRefPOC))
         return false;
     else if (curRefPOC == curPOC)
@@ -2268,7 +2280,7 @@ void CUData::calcCTUGeoms(uint32_t ctuWidth, uint32_t
ctuHeight, uint32_t maxCUS
     }
 }

-
+#if ENABLE_SCC_EXT
 bool CUData::getDerivedBV(uint32_t absPartIdx, const MV& currentMv, MV&
derivedMv, uint32_t width, uint32_t height)
 {
     const int   ctuWidth = m_slice->m_param->maxCUSize;
@@ -2564,3 +2576,4 @@ bool CUData::is8x8BipredRestriction(MV mvL0, MV mvL1,
int iRefIdxL0, int iRefIdx
     }
     return b8x8BiPredRestricted;
 }
+#endif
diff --git a/source/common/cudata.h b/source/common/cudata.h
index 69cfb4947..2b669a802 100644
--- a/source/common/cudata.h
+++ b/source/common/cudata.h
@@ -37,7 +37,9 @@ class FrameData;
 class Slice;
 struct TUEntropyCodingParameters;
 struct CUDataMemPool;
+#if ENABLE_SCC_EXT
 struct IBC;
+#endif

 enum PartSize
 {
@@ -241,7 +243,9 @@ public:
     uint32_t*       m_collectCUVariance;
     uint32_t*       m_collectCUCount;

+#if ENABLE_SCC_EXT
     MV              m_lastIntraBCMv[2];
+#endif

     CUData();

@@ -322,12 +326,14 @@ public:
     const CUData* getPUAboveRightAdi(uint32_t& arPartUnitIdx, uint32_t
curPartUnitIdx, uint32_t partUnitOffset) const;
     const CUData* getPUBelowLeftAdi(uint32_t& blPartUnitIdx, uint32_t
curPartUnitIdx, uint32_t partUnitOffset) const;

+#if ENABLE_SCC_EXT
     void getIntraBCMVPsEncOnly(uint32_t absPartIdx, MV* MvPred, int&
nbPred, int puIdx);
     bool getDerivedBV(uint32_t absPartIdx, const MV& currentMv, MV&
derivedMv, uint32_t width, uint32_t height);
     bool isIntraBC(const CUData* cu, uint32_t absPartIdx) const;
     bool getColMVPIBC(int ctuRsAddr, int partUnitIdx, MV& rcMv);
     void roundMergeCandidates(MVField(*candMvField)[2], int iCount) const;
     bool is8x8BipredRestriction(MV mvL0, MV mvL1, int iRefIdxL0, int
iRefIdxL1) const;
+#endif

 protected:

diff --git a/source/common/frame.cpp b/source/common/frame.cpp
index b561a67b1..4c800e94e 100644
--- a/source/common/frame.cpp
+++ b/source/common/frame.cpp
@@ -37,7 +37,7 @@ Frame::Frame()
     m_reconColCount = NULL;
     m_countRefEncoders = 0;
     m_encData = NULL;
-    for (int i = 0; i < 2; i++)
+    for (int i = 0; i < NUM_RECON_VERSION; i++)
         m_reconPic[i] = NULL;
     m_quantOffsets = NULL;
     m_next = NULL;
@@ -211,7 +211,7 @@ bool Frame::allocEncodeData(x265_param *param, const
SPS& sps)
         m_reconPic[i] = new PicYuv;
         m_encData->m_reconPic[i] = m_reconPic[i];
     }
-    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);
+    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);
     if (ok)
     {
         /* initialize right border of m_reconPicYuv as SAO may read beyond
the
@@ -243,9 +243,8 @@ bool Frame::allocEncodeData(x265_param *param, const
SPS& sps)
 void Frame::reinit(const SPS& sps)
 {
     m_bChromaExtended = false;
-    m_reconPic[0] = m_encData->m_reconPic[0];
-    if (!!m_param->bEnableSCC)
-        m_reconPic[1] = m_encData->m_reconPic[1];
+    for (int i = 0; i < !!m_param->bEnableSCC + 1; i++)
+        m_reconPic[i] = m_encData->m_reconPic[i];
     m_encData->reinit(sps);
 }

diff --git a/source/common/frame.h b/source/common/frame.h
index 4e6a4beed..4fa90ef54 100644
--- a/source/common/frame.h
+++ b/source/common/frame.h
@@ -81,7 +81,7 @@ public:
     /* These two items will be NULL until the Frame begins to be encoded,
at which point
      * it will be assigned a FrameData instance, which comes with a
reconstructed image PicYuv */
     FrameData*             m_encData;
-    PicYuv*                m_reconPic[2];
+    PicYuv*                m_reconPic[NUM_RECON_VERSION];

     /* Data associated with x265_picture */
     PicYuv*                m_fencPic;
diff --git a/source/common/framedata.h b/source/common/framedata.h
index 66a00696c..6b9bde09a 100644
--- a/source/common/framedata.h
+++ b/source/common/framedata.h
@@ -115,7 +115,7 @@ public:
     const x265_param* m_param;

     FrameData*     m_freeListNext;
-    PicYuv*        m_reconPic[2];
+    PicYuv*        m_reconPic[NUM_RECON_VERSION];
     bool           m_bHasReferences;   /* used during DPB/RPS updates */
     int            m_frameEncoderID;   /* the ID of the FrameEncoder
encoding this frame */
     JobProvider*   m_jobProvider;
diff --git a/source/common/param.cpp b/source/common/param.cpp
index bbf33dae9..5288bf453 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -1476,12 +1476,14 @@ int x265_param_parse(x265_param* p, const char*
name, const char* value)
             p->numViews = atoi(value);
         }
 #endif
+#if ENABLE_SCC_EXT
         OPT("scc")
         {
             p->bEnableSCC = atoi(value);
             if (p->bEnableSCC)
                 p->bEnableWeightedPred = false;
         }
+#endif
         else
             return X265_PARAM_BAD_NAME;
     }
@@ -1964,6 +1966,9 @@ int x265_check_params(x265_param* param)
     CHECK((param->numViews > 2), "Multi-View Encoding currently support
only 2 views");
     CHECK((param->numViews > 1) && (param->internalBitDepth != 8),
"BitDepthConstraint must be 8 for Multiview main profile");
     CHECK((param->numViews > 1 && param->rc.rateControlMode !=
X265_RC_CQP), "Multiview encode supported only with CQP mode");
+#endif
+#if ENABLE_SCC_EXT
+    CHECK(!!param->bEnableSCC&& param->rdLevel != 6, "Enabling scc
extension in x265 requires rdlevel of 6 ");
 #endif
     return check_failed;
 }
@@ -2406,7 +2411,9 @@ char *x265_param2string(x265_param* p, int padx, int
pady)
     s += sprintf(s, " num-views=%d", p->numViews);
     s += sprintf(s, " format=%d", p->format);
 #endif
+#if ENABLE_SCC_EXT
     s += sprintf(s, "scc=%d", p->bEnableSCC);
+#endif
     BOOL(p->bEnableSBRC, "sbrc");
 #undef BOOL
     return buf;
@@ -2937,7 +2944,9 @@ void x265_copy_params(x265_param* dst, x265_param*
src)
     dst->format = src->format;
 #endif
     dst->numLayers = src->numLayers;
+#if ENABLE_SCC_EXT
     dst->bEnableSCC = src->bEnableSCC;
+#endif

     if (src->videoSignalTypePreset) dst->videoSignalTypePreset =
strdup(src->videoSignalTypePreset);
     else dst->videoSignalTypePreset = NULL;
diff --git a/source/common/predict.cpp b/source/common/predict.cpp
index e6fc478e3..8e9c32d23 100644
--- a/source/common/predict.cpp
+++ b/source/common/predict.cpp
@@ -112,7 +112,8 @@ void Predict::motionCompensation(const CUData& cu,
const PredictionUnit& pu, Yuv
         }
         else
         {
-            if (!!cu.m_slice->m_param->bEnableSCC && refIdx0 ==
(cu.m_slice->m_numRefIdx[0] - 1))
+#if ENABLE_SCC_EXT
+            if (cu.m_slice->m_param->bEnableSCC && refIdx0 ==
(cu.m_slice->m_numRefIdx[0] - 1))
             {
                 if (bLuma)
                     predInterLumaPixel(pu, predYuv,
*cu.m_slice->m_refFrameList[0][refIdx0]->m_reconPic[1], mv0);
@@ -120,6 +121,7 @@ void Predict::motionCompensation(const CUData& cu,
const PredictionUnit& pu, Yuv
                     predInterChromaPixel(pu, predYuv,
*cu.m_slice->m_refFrameList[0][refIdx0]->m_reconPic[1], mv0);
             }
             else
+#endif
             {
                 if (bLuma)
                     predInterLumaPixel(pu, predYuv,
*cu.m_slice->m_refReconPicList[0][refIdx0], mv0);
@@ -184,17 +186,21 @@ void Predict::motionCompensation(const CUData& cu,
const PredictionUnit& pu, Yuv

             if (bLuma)
             {
-                if (!!cu.m_slice->m_param->bEnableSCC && refIdx0 ==
(cu.m_slice->m_numRefIdx[0] - 1))
+#if ENABLE_SCC_EXT
+                if (cu.m_slice->m_param->bEnableSCC && refIdx0 ==
(cu.m_slice->m_numRefIdx[0] - 1))
                     predInterLumaShort(pu, m_predShortYuv[0],
*cu.m_slice->m_refFrameList[0][refIdx0]->m_reconPic[1], mv0);
                 else
+#endif
                     predInterLumaShort(pu, m_predShortYuv[0],
*cu.m_slice->m_refReconPicList[0][refIdx0], mv0);
                 predInterLumaShort(pu, m_predShortYuv[1],
*cu.m_slice->m_refReconPicList[1][refIdx1], mv1);
             }
             if (bChroma)
             {
-                if (!!cu.m_slice->m_param->bEnableSCC && refIdx0 ==
(cu.m_slice->m_numRefIdx[0] - 1))
+#if ENABLE_SCC_EXT
+                if (cu.m_slice->m_param->bEnableSCC && refIdx0 ==
(cu.m_slice->m_numRefIdx[0] - 1))
                     predInterChromaShort(pu, m_predShortYuv[0],
*cu.m_slice->m_refFrameList[0][refIdx0]->m_reconPic[1], mv0);
                 else
+#endif
                     predInterChromaShort(pu, m_predShortYuv[0],
*cu.m_slice->m_refReconPicList[0][refIdx0], mv0);
                 predInterChromaShort(pu, m_predShortYuv[1],
*cu.m_slice->m_refReconPicList[1][refIdx1], mv1);
             }
@@ -222,7 +228,8 @@ void Predict::motionCompensation(const CUData& cu,
const PredictionUnit& pu, Yuv
             }
             else
             {
-                if (!!cu.m_slice->m_param->bEnableSCC && refIdx0 ==
(cu.m_slice->m_numRefIdx[0] - 1))
+#if ENABLE_SCC_EXT
+                if (cu.m_slice->m_param->bEnableSCC && refIdx0 ==
(cu.m_slice->m_numRefIdx[0] - 1))
                 {
                     if (bLuma)
                         predInterLumaPixel(pu, predYuv,
*cu.m_slice->m_refFrameList[0][refIdx0]->m_reconPic[1], mv0);
@@ -230,6 +237,7 @@ void Predict::motionCompensation(const CUData& cu,
const PredictionUnit& pu, Yuv
                         predInterChromaPixel(pu, predYuv,
*cu.m_slice->m_refFrameList[0][refIdx0]->m_reconPic[1], mv0);
                 }
                 else
+#endif
                 {
                     if (bLuma)
                         predInterLumaPixel(pu, predYuv,
*cu.m_slice->m_refReconPicList[0][refIdx0], mv0);
diff --git a/source/common/slice.cpp b/source/common/slice.cpp
index d67aaae0b..24ccff933 100644
--- a/source/common/slice.cpp
+++ b/source/common/slice.cpp
@@ -63,6 +63,7 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi
         memset(m_refPOCList, 0, sizeof(m_refPOCList));
         m_numRefIdx[1] = m_numRefIdx[0] = 0;

+#if ENABLE_SCC_EXT
         if (!checkNumPocTotalCurr)
         {
             if (m_rps.numberOfPictures == 0)
@@ -76,10 +77,12 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi
             }
             return;
         }
+#endif

         return;
     }

+#if ENABLE_SCC_EXT
     /*Reset the number of references for I-slice marked as P-slice*/
     if (m_param->bEnableSCC && m_sliceType != m_origSliceType)
     {
@@ -99,6 +102,7 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi
         }
         m_lastEncPic = prevPic;
     }
+#endif

     Frame* refPic = NULL;
     Frame* refPicSetStCurr0[MAX_NUM_REF];
@@ -141,8 +145,10 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi
     int numPocTotalCurr = numPocStCurr0 + numPocStCurr1 + numPocLtCurr;
 #endif

+#if ENABLE_SCC_EXT
     if (m_param->bEnableSCC)
         numPocTotalCurr++;
+#endif

     int cIdx = 0;
     for (i = 0; i < numPocStCurr0; i++, cIdx++)
@@ -166,8 +172,10 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi
             rpsCurrList0[cIdx] = refPicSetInterLayer1.getPOC(m_poc, 0);
 #endif

+#if ENABLE_SCC_EXT
     if (m_param->bEnableSCC)
         rpsCurrList0[cIdx++] = picList.getPOC(m_poc);
+#endif

     X265_CHECK(cIdx == numPocTotalCurr, "RPS index check fail\n");

@@ -195,8 +203,10 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi
                 rpsCurrList1[cIdx] = refPicSetInterLayer0.getPOC(m_poc, 0);
 #endif

+#if  ENABLE_SCC_EXT
         if (m_param->bEnableSCC)
             rpsCurrList1[cIdx++] = picList.getPOC(m_poc);
+#endif

         X265_CHECK(cIdx == numPocTotalCurr, "RPS index check fail\n");
     }
@@ -211,10 +221,12 @@ void Slice::setRefPicList(PicList& picList, PicList&
refPicSetInterLayer0, PicLi
 #endif
     }

+#if  ENABLE_SCC_EXT
     if (m_param->bEnableSCC && numPocTotalCurr > m_numRefIdx[0])
     {
         m_refFrameList[0][m_numRefIdx[0] - 1] = picList.getPOC(m_poc);
     }
+#endif

     if (m_sliceType != B_SLICE)
     {
@@ -253,6 +265,7 @@ void Slice::disableWeights()
             }
 }

+#if  ENABLE_SCC_EXT
 bool Slice::isOnlyCurrentPictureAsReference() const
 {
     if (m_sliceType == I_SLICE)
@@ -278,6 +291,7 @@ bool Slice::isOnlyCurrentPictureAsReference() const

     return true;
 }
+#endif

 /* Sorts the deltaPOC and Used by current values in the RPS based on the
  * deltaPOC values.  deltaPOC values are sorted with -ve values before the
+ve
diff --git a/source/common/slice.h b/source/common/slice.h
index b5be561fd..d23479778 100644
--- a/source/common/slice.h
+++ b/source/common/slice.h
@@ -403,10 +403,12 @@ public:
     int         m_fieldNum;
     Frame*      m_mcstfRefFrameList[2][MAX_MCSTF_TEMPORAL_WINDOW_LENGTH];

-    Frame* m_lastEncPic;
+#if  ENABLE_SCC_EXT
+    Frame*      m_lastEncPic;
     bool        m_bLMvdL1Zero;
-    bool        m_bTemporalMvp;
     bool        m_useIntegerMv;
+#endif
+    bool        m_bTemporalMvp;

     Slice()
     {
@@ -423,9 +425,11 @@ public:
         m_rpsIdx = -1;
         m_chromaQpOffset[0] = m_chromaQpOffset[1] = 0;
         m_fieldNum = 0;
-        m_bTemporalMvp = false;
+#if  ENABLE_SCC_EXT
         m_lastEncPic = NULL;
         m_useIntegerMv = false;
+#endif
+        m_bTemporalMvp = false;
     }

     void disableWeights();
@@ -435,7 +439,9 @@ public:
     void createInterLayerReferencePictureSet(PicList& picList, PicList&
refPicSetInterLayer0, PicList& refPicSetInterLayer1);
 #endif

+#if  ENABLE_SCC_EXT
     bool isOnlyCurrentPictureAsReference() const;
+#endif

     bool getRapPicFlag() const
     {
diff --git a/source/encoder/analysis.cpp b/source/encoder/analysis.cpp
index 7a910cbb9..4ff6a69f6 100644
--- a/source/encoder/analysis.cpp
+++ b/source/encoder/analysis.cpp
@@ -223,9 +223,11 @@ Mode& Analysis::compressCTU(CUData& ctu, Frame& frame,
const CUGeom& cuGeom, con
     }
     ProfileCUScope(ctu, totalCTUTime, totalCTUs);

+#if  ENABLE_SCC_EXT
     memset(m_ibc.m_BVs, 0, sizeof(m_ibc.m_BVs));
     memset(m_ibc.m_lastIntraBCMv, 0, sizeof(m_ibc.m_lastIntraBCMv));
     m_ibc.m_numBV16s = 0; m_ibc.m_numBVs = 0;
+#endif
     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;
@@ -573,6 +575,7 @@ uint64_t Analysis::compressIntraCU(const CUData&
parentCTU, const CUGeom& cuGeom
             checkBestMode(md.pred[PRED_INTRA_NxN], depth);
         }

+#if ENABLE_SCC_EXT
         bool intraBlockCopyFastSearch = (m_param->bEnableSCC == 1) ? true
: false, bUse1DSearchFor8x8 = false;
         if (m_param->bEnableSCC)
         {
@@ -607,6 +610,7 @@ uint64_t Analysis::compressIntraCU(const CUData&
parentCTU, const CUGeom& cuGeom
                 checkBestMode(md.pred[PRED_IBC_Nx2N], depth);
             }
         }
+#endif

         if (m_bTryLossless)
             tryLossless(cuGeom);
@@ -615,6 +619,7 @@ uint64_t Analysis::compressIntraCU(const CUData&
parentCTU, const CUGeom& cuGeom
             addSplitFlagCost(*md.bestMode, cuGeom.depth);
     }

+#if ENABLE_SCC_EXT
     // If Intra BC keep last coded Mv
     if (md.bestMode && md.bestMode->cu.isInter(0))
     {
@@ -697,6 +702,7 @@ uint64_t Analysis::compressIntraCU(const CUData&
parentCTU, const CUGeom& cuGeom
             }
         }
     } // is inter
+#endif

     // stop recursion if we reach the depth of previous analysis decision
     mightSplit &= !(bAlreadyDecided && bDecidedDepth) || split;
@@ -739,6 +745,7 @@ uint64_t Analysis::compressIntraCU(const CUData&
parentCTU, const CUGeom& cuGeom
                 else
                     compressIntraCU(parentCTU, childGeom, nextQP, ibc);

+#if ENABLE_SCC_EXT
                 if (nd.bestMode->cu.m_lastIntraBCMv[0].x != 0 ||
nd.bestMode->cu.m_lastIntraBCMv[0].y != 0)
                 {
                     for (int i = 0; i < 2; i++)
@@ -746,6 +753,7 @@ uint64_t Analysis::compressIntraCU(const CUData&
parentCTU, const CUGeom& cuGeom
                         ibc.m_lastIntraBCMv[i] =
nd.bestMode->cu.m_lastIntraBCMv[i];
                     }
                 }
+#endif

                 // Save best CU and pred data for this sub CU
                 splitCU->copyPartFrom(nd.bestMode->cu, childGeom,
subPartIdx);
@@ -2163,12 +2171,14 @@ SplitData Analysis::compressInterCU_rd5_6(const
CUData& parentCTU, const CUGeom&
             checkInter_rd5_6(md.pred[PRED_2Nx2N], cuGeom, SIZE_2Nx2N,
refMasks);
             checkBestMode(md.pred[PRED_2Nx2N], cuGeom.depth);

+#if ENABLE_SCC_EXT
             interBest = md.bestMode;
             if (m_param->bEnableSCC)
             {
                 md.pred[PRED_MERGE_IBC].cu.initSubCU(parentCTU, cuGeom,
qp, ibc.m_lastIntraBCMv);
                 checkRDCostIntraBCMerge2Nx2N(md.pred[PRED_MERGE_IBC],
cuGeom);
             }
+#endif

             if (m_param->recursionSkipMode == RDCOST_BASED_RSKIP && depth
&& m_modeDepth[depth - 1].bestMode)
                 skipRecursion = md.bestMode &&
!md.bestMode->cu.getQtRootCbf(0);
@@ -2208,11 +2218,13 @@ SplitData Analysis::compressInterCU_rd5_6(const
CUData& parentCTU, const CUGeom&

                     splitData[subPartIdx] =
compressInterCU_rd5_6(parentCTU, childGeom, nextQP, ibc);

+#if ENABLE_SCC_EXT
                     if (nd.bestMode->cu.m_lastIntraBCMv[0].x != 0 ||
nd.bestMode->cu.m_lastIntraBCMv[0].y != 0)
                     {
                         for (int i = 0; i < 2; i++)
                             ibc.m_lastIntraBCMv[i] =
nd.bestMode->cu.m_lastIntraBCMv[i];
                     }
+#endif

                     // Save best CU and pred data for this sub CU
                     splitIntra |= nd.bestMode->cu.isIntra(0);
@@ -2447,6 +2459,7 @@ SplitData Analysis::compressInterCU_rd5_6(const
CUData& parentCTU, const CUGeom&
                     }
                 }

+#if ENABLE_SCC_EXT
                 if (m_param->bEnableSCC)
                 {
                     bool intraBlockCopyFastSearch = (m_param->bEnableSCC
== 1) ? true : false, bUse1DSearchFor8x8 = false, bValid;
@@ -2494,6 +2507,7 @@ SplitData Analysis::compressInterCU_rd5_6(const
CUData& parentCTU, const CUGeom&
                         checkBestMode(md.pred[PRED_IBC_Nx2N], depth);
                     }
                 }
+#endif

                 if ((m_slice->m_sliceType != B_SLICE ||
m_param->bIntraInBFrames) && (cuGeom.log2CUSize != MAX_LOG2_CU_SIZE) &&
!((m_param->bCTUInfo & 4) && bCtuInfoCheck))
                 {
@@ -2518,6 +2532,7 @@ SplitData Analysis::compressInterCU_rd5_6(const
CUData& parentCTU, const CUGeom&
                 }
             }

+#if ENABLE_SCC_EXT
             // If Intra BC keep last coded Mv
             if (md.bestMode->cu.isInter(0))
             {
@@ -2600,6 +2615,7 @@ SplitData Analysis::compressInterCU_rd5_6(const
CUData& parentCTU, const CUGeom&
                     }
                 }
             } // is inter
+#endif

             if ((md.bestMode->cu.isInter(0) &&
!(md.bestMode->cu.m_mergeFlag[0] && md.bestMode->cu.m_partSize[0] ==
SIZE_2Nx2N)) && (m_frame->m_fencPic->m_picCsp == X265_CSP_I400 && m_csp !=
X265_CSP_I400))
             {
@@ -2650,7 +2666,7 @@ SplitData Analysis::compressInterCU_rd5_6(const
CUData& parentCTU, const CUGeom&
             else
             {
                 /* use best merge/inter mode, in case of intra use 2Nx2N
inter references */
-                CUData& cu = md.bestMode->cu.isIntra(0) ?
md.pred[PRED_2Nx2N].cu : interBest->cu;
+                CUData& cu = md.bestMode->cu.isIntra(0) ?
md.pred[PRED_2Nx2N].cu : (m_param->bEnableSCC ? interBest->cu :
md.bestMode->cu);
                 uint32_t numPU = cu.getNumPartInter(0);
                 for (uint32_t puIdx = 0, subPartIdx = 0; puIdx < numPU;
puIdx++, subPartIdx += cu.getPUOffset(puIdx, 0))
                     splitCUData.splitRefs |= cu.getBestRefIdx(subPartIdx);
@@ -3196,7 +3212,9 @@ void Analysis::checkMerge2Nx2N_rd5_6(Mode& skip,
Mode& merge, const CUGeom& cuGe
     MVField candMvField[MRG_MAX_NUM_CANDS][2]; // double length for mv of
both lists
     uint8_t candDir[MRG_MAX_NUM_CANDS];
     uint32_t numMergeCand = merge.cu.getInterMergeCandidates(0, 0,
candMvField, candDir);
+#if ENABLE_SCC_EXT
     restrictBipredMergeCand(&merge.cu, 0, candMvField, candDir,
numMergeCand);
+#endif

     PredictionUnit pu(merge.cu, cuGeom, 0);

@@ -3252,10 +3270,12 @@ void Analysis::checkMerge2Nx2N_rd5_6(Mode& skip,
Mode& merge, const CUGeom& cuGe
             candMvField[i][0].mv.x > maxSafeMv)
             // skip merge candidates which reference beyond safe reference
area
             continue;
+#if ENABLE_SCC_EXT
         if ((candDir[i] == 1 || candDir[i] == 3) &&
(m_slice->m_refPOCList[0][candMvField[i][0].refIdx] == m_slice->m_poc))
         {
             continue;
         }
+#endif
         tempPred->cu.m_mvpIdx[0][0] = (uint8_t)i;    /* merge candidate ID
is stored in L0 MVP idx */
         tempPred->cu.m_interDir[0] = candDir[i];
         tempPred->cu.m_mv[0][0] = candMvField[i][0].mv;
@@ -3320,6 +3340,7 @@ void Analysis::checkMerge2Nx2N_rd5_6(Mode& skip,
Mode& merge, const CUGeom& cuGe
     }
 }

+#if ENABLE_SCC_EXT
 void Analysis::checkRDCostIntraBCMerge2Nx2N(Mode& mergeIBC, const CUGeom&
cuGeom)
 {
     mergeIBC.initCosts();
@@ -3386,6 +3407,7 @@ void Analysis::checkRDCostIntraBCMerge2Nx2N(Mode&
mergeIBC, const CUGeom& cuGeom
     checkBestMode(mergeIBC, depth);
     checkDQP(mergeIBC, cuGeom);
 }
+#endif

 void Analysis::checkInter_rd0_4(Mode& interMode, const CUGeom& cuGeom,
PartSize partSize, uint32_t refMask[2])
 {
@@ -3509,6 +3531,7 @@ void Analysis::checkInter_rd5_6(Mode& interMode,
const CUGeom& cuGeom, PartSize
     }
 }

+#if ENABLE_SCC_EXT
 void Analysis::checkIntraBC_rd5_6(Mode& intraBCMode, const CUGeom& cuGeom,
PartSize ePartSize, bool testOnlyPred, bool bUse1DSearchFor8x8, IBC& ibc,
MV* iMVCandList)
 {
     intraBCMode.initCosts();
@@ -3534,12 +3557,17 @@ void Analysis::checkIntraBC_rd5_6(Mode&
intraBCMode, const CUGeom& cuGeom, PartS
         iMVCandList[1] = intraBCMode.cu.m_mv[0][partAddr];
     }
 }
+#endif

 void Analysis::checkBidir2Nx2N(Mode& inter2Nx2N, Mode& bidir2Nx2N, const
CUGeom& cuGeom)
 {
     CUData& cu = bidir2Nx2N.cu;

+#if ENABLE_SCC_EXT
     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)
+#else
+    if (cu.isBipredRestriction() || inter2Nx2N.bestME[0][0].cost ==
MAX_UINT || inter2Nx2N.bestME[0][1].cost == MAX_UINT)
+#endif
     {
         bidir2Nx2N.sa8dCost = MAX_INT64;
         bidir2Nx2N.rdCost = MAX_INT64;
@@ -4175,8 +4203,10 @@ 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 ENABLE_SCC_EXT
             if (refPoc == m_curPoc)
                 continue;
+#endif
             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/analysis.h b/source/encoder/analysis.h
index 7f4f1c988..ad1ef6b63 100644
--- a/source/encoder/analysis.h
+++ b/source/encoder/analysis.h
@@ -75,12 +75,14 @@ public:
         PRED_nRx2N,
         PRED_INTRA_NxN, /* 4x4 intra PU blocks for 8x8 CU */
         PRED_LOSSLESS,  /* lossless encode of best mode */
+#if ENABLE_SCC_EXT
         PRED_IBC_2Nx2N,
         PRED_IBC_Nx2N,
         PRED_IBC_2NxN,
         PRED_MIXED_IBC_NX2N,
         PRED_MIXED_IBC_2NXN,
         PRED_MERGE_IBC,
+#endif
         MAX_PRED_TYPES
     };

@@ -170,7 +172,7 @@ protected:
     void qprdRefine(const CUData& parentCTU, const CUGeom& cuGeom, int32_t
qp, int32_t lqp);

     /* full analysis for an I-slice CU */
-    uint64_t compressIntraCU(const CUData& parentCTU, const CUGeom&
cuGeom, int32_t qp, IBC &ibc);
+    uint64_t compressIntraCU(const CUData& parentCTU, const CUGeom&
cuGeom, int32_t qp, IBC& ibc);

     /* full analysis for a P or B slice CU */
     uint32_t compressInterCU_dist(const CUData& parentCTU, const CUGeom&
cuGeom, int32_t qp);
@@ -189,8 +191,10 @@ protected:

     void checkBidir2Nx2N(Mode& inter2Nx2N, Mode& bidir2Nx2N, const CUGeom&
cuGeom);

+#if ENABLE_SCC_EXT
     void checkRDCostIntraBCMerge2Nx2N(Mode& merge, const CUGeom& cuGeom);
     void checkIntraBC_rd5_6(Mode& intraBCMode, const CUGeom& cuGeom,
PartSize ePartSize, bool testOnlyPred, bool bUse1DSearchFor8x8, IBC& ibc,
MV* iMVCandList = NULL);
+#endif

     /* encode current bestMode losslessly, pick best RD cost */
     void tryLossless(const CUGeom& cuGeom);
diff --git a/source/encoder/dpb.cpp b/source/encoder/dpb.cpp
index 8ef1f7abe..498d62c1a 100644
--- a/source/encoder/dpb.cpp
+++ b/source/encoder/dpb.cpp
@@ -327,7 +327,8 @@ void DPB::prepareEncode(Frame *newFrame)
         slice->m_colRefIdx = 0;
     }

-
+    slice->m_bTemporalMvp = slice->m_sps->bTemporalMVPEnabled;
+#if ENABLE_SCC_EXT
     bool bGPBcheck = false;
     if (slice->m_sliceType == B_SLICE)
     {
@@ -377,6 +378,7 @@ void DPB::prepareEncode(Frame *newFrame)
         else
             slice->m_bTemporalMvp = true;
     }
+#endif

     // Disable Loopfilter in bound area, because we will do
slice-parallelism in future
     slice->m_sLFaseFlag = (newFrame->m_param->maxSlices > 1) ? false :
((SLFASE_CONSTANT & (1 << (pocCurr % 31))) > 0);
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 4043342c1..1a16f039d 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -629,7 +629,9 @@ 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);
+#if ENABLE_SCC_EXT
                     if (l0POC != poc)
+#endif
                     {
                         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. */
@@ -3716,11 +3718,13 @@ void Encoder::initPPS(PPS *pps)
     }
 #endif

+#if ENABLE_SCC_EXT
     if (m_param->bEnableSCC)
     {
         pps->profileIdc = Profile::MAINSCC;
         pps->pps_extension_flag = true;
     }
+#endif
 }

 void Encoder::configureZone(x265_param *p, x265_param *zone)
diff --git a/source/encoder/entropy.cpp b/source/encoder/entropy.cpp
index 22408e6f3..12cfc3ef7 100644
--- a/source/encoder/entropy.cpp
+++ b/source/encoder/entropy.cpp
@@ -599,6 +599,7 @@ void Entropy::codeSPS(const SPS& sps, const
ScalingList& scalingList, const Prof
     }
 #endif

+#if ENABLE_SCC_EXT
     if (ptl.profileIdc[0] == Profile::MAINSCC)
     {
         bool sps_extension_flags[NUM_EXTENSION_FLAGS] = { false };
@@ -610,6 +611,7 @@ void Entropy::codeSPS(const SPS& sps, const
ScalingList& scalingList, const Prof
         WRITE_CODE(0, 2, "motion_vector_resolution_control_idc");
         WRITE_FLAG(0, "intra_boundary_filter_disabled_flag");
     }
+#endif
 }

 void Entropy::codePPS( const PPS& pps, bool filerAcross, int
iPPSInitQpMinus26, int layer)
@@ -680,6 +682,7 @@ void Entropy::codePPS( const PPS& pps, bool
filerAcross, int iPPSInitQpMinus26,
 #endif


+#if ENABLE_SCC_EXT
     if (pps.profileIdc == Profile::MAINSCC)
     {
         bool pps_extension_flags[NUM_EXTENSION_FLAGS] = { false };
@@ -690,6 +693,7 @@ void Entropy::codePPS( const PPS& pps, bool
filerAcross, int iPPSInitQpMinus26,
         WRITE_FLAG(0, "adaptive_colour_trans_flag");
         WRITE_FLAG(0, "palette_predictor_initializer_flag");
     }
+#endif
 }

 void Entropy::codeProfileTier(const ProfileTierLevel& ptl, int
maxTempSubLayers, int layer)
@@ -997,7 +1001,11 @@ void Entropy::codeSliceHeader(const Slice& slice,
FrameData& encData, uint32_t s
         }

         if (slice.m_sps->bTemporalMVPEnabled)
+#if ENABLE_SCC_EXT
             WRITE_FLAG(slice.m_bTemporalMvp,
"slice_temporal_mvp_enable_flag");
+#else
+            WRITE_FLAG(1, "slice_temporal_mvp_enable_flag");
+#endif
     }
     const SAOParam *saoParam = encData.m_saoParam;
     if (slice.m_bUseSao)
@@ -1037,9 +1045,17 @@ void Entropy::codeSliceHeader(const Slice& slice,
FrameData& encData, uint32_t s
     }

     if (slice.isInterB())
+#if ENABLE_SCC_EXT
         WRITE_FLAG(slice.m_bLMvdL1Zero, "mvd_l1_zero_flag");
+#else
+        WRITE_FLAG(0, "mvd_l1_zero_flag");
+#endif

+#if ENABLE_SCC_EXT
     if (slice.m_bTemporalMvp)
+#else
+    if (slice.m_sps->bTemporalMVPEnabled)
+#endif
     {
         if (slice.m_sliceType == B_SLICE)
             WRITE_FLAG(slice.m_colFromL0Flag, "collocated_from_l0_flag");
@@ -1726,8 +1742,10 @@ void Entropy::codePredWeightTable(const Slice& slice)
         {
             for (int ref = 0; ref < slice.m_numRefIdx[list]; ref++)
             {
+#if ENABLE_SCC_EXT
                 if (slice.m_poc == slice.m_refPOCList[list][ref])
                     continue;
+#endif
                 wp = slice.m_weightPredTable[list][ref];
                 if (!bDenomCoded)
                 {
@@ -1748,8 +1766,10 @@ void Entropy::codePredWeightTable(const Slice& slice)
             {
                 for (int ref = 0; ref < slice.m_numRefIdx[list]; ref++)
                 {
+#if ENABLE_SCC_EXT
                     if (slice.m_poc == slice.m_refPOCList[list][ref])
                         continue;
+#endif
                     wp = slice.m_weightPredTable[list][ref];
                     WRITE_FLAG(!!wp[1].wtPresent, "chroma_weight_lX_flag");
                     totalSignalledWeightFlags += 2 * wp[1].wtPresent;
@@ -1758,8 +1778,10 @@ void Entropy::codePredWeightTable(const Slice& slice)

             for (int ref = 0; ref < slice.m_numRefIdx[list]; ref++)
             {
+#if ENABLE_SCC_EXT
                 if (slice.m_poc == slice.m_refPOCList[list][ref])
                     continue;
+#endif
                 wp = slice.m_weightPredTable[list][ref];
                 if (wp[0].wtPresent)
                 {
diff --git a/source/encoder/frameencoder.cpp
b/source/encoder/frameencoder.cpp
index 286eb520a..7d02d0d96 100644
--- a/source/encoder/frameencoder.cpp
+++ b/source/encoder/frameencoder.cpp
@@ -911,9 +911,11 @@ void FrameEncoder::compressFrame(int layer)
                     {
                         Frame *refpic = slice->m_refFrameList[l][ref];

+#if ENABLE_SCC_EXT
                         /*Exempt the current pic as reference*/
                         if (m_param->bEnableSCC && refpic->m_poc ==
m_frame[layer]->m_poc)
                             continue;
+#endif

                         // NOTE: we unnecessary wait row that beyond
current slice boundary
                         const int rowIdx = X265_MIN(sliceEndRow, (row +
m_refLagRows));
@@ -957,9 +959,11 @@ void FrameEncoder::compressFrame(int layer)
                     {
                         Frame *refpic = slice->m_refFrameList[list][ref];

+#if ENABLE_SCC_EXT
                         /*Exempt the current pic as reference*/
                         if (m_param->bEnableSCC && refpic->m_poc ==
m_frame[layer]->m_poc)
                             continue;
+#endif

                         const int rowIdx = X265_MIN(m_numRows - 1, (i +
m_refLagRows));
                         while (refpic->m_reconRowFlag[rowIdx].get() == 0)
diff --git a/source/encoder/level.cpp b/source/encoder/level.cpp
index 84f407702..a87b49d90 100644
--- a/source/encoder/level.cpp
+++ b/source/encoder/level.cpp
@@ -60,6 +60,7 @@ LevelSpec levels[] =
     { MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, 1,
Level::LEVEL8_5, "8.5", 85 },
 };

+#if ENABLE_SCC_EXT
 enum SCCProfileName
 {
     NONE = 0,
@@ -84,6 +85,7 @@ static const SCCProfileName validSCCProfileNames[1][4/*
bit depth constraint 8=0
         { NONE,         NONE,          NONE,      NONE
        }  // 16-bit intra for 400, 420, 422 and 444
     },
 };
+#endif

 static inline int _confirm(x265_param* param, bool bflag, const char*
message)
 {
@@ -113,9 +115,7 @@ void determineLevel(const x265_param &param, VPS& vps)
         /* Probably an HEVC v1 profile, but must check to be sure */
         if (param.internalBitDepth <= 8)
         {
-            if (param.bEnableSCC)
-                vps.ptl.profileIdc[0] = Profile::MAINSCC;
-            else if (vps.ptl.onePictureOnlyConstraintFlag)
+            if (vps.ptl.onePictureOnlyConstraintFlag)
                 vps.ptl.profileIdc[0] = Profile::MAINSTILLPICTURE;
             else if (vps.ptl.intraConstraintFlag)
                 vps.ptl.profileIdc[0] = Profile::MAINREXT; /* Main Intra */
@@ -130,9 +130,7 @@ void determineLevel(const x265_param &param, VPS& vps)
         else if (param.internalBitDepth <= 10)
         {
             /* note there is no 10bit still picture profile */
-            if (param.bEnableSCC)
-                vps.ptl.profileIdc[0] = Profile::MAINSCC;
-            else if (vps.ptl.intraConstraintFlag)
+            if (vps.ptl.intraConstraintFlag)
                 vps.ptl.profileIdc[0] = Profile::MAINREXT; /* Main10 Intra
*/
             else
                 vps.ptl.profileIdc[0] = Profile::MAIN10;
@@ -151,12 +149,17 @@ void determineLevel(const x265_param &param, VPS& vps)
         vps.ptl.profileIdc[1] = Profile::MULTIVIEWMAIN;
 #endif

+#if ENABLE_SCC_EXT
+    if (param.bEnableSCC)
+        vps.ptl.profileIdc[0] = Profile::MAINSCC;
+
     /* determine which profiles are compatible with this stream */
     if (vps.ptl.profileIdc[0] == Profile::MAINSCC)
     {
         vps.ptl.onePictureOnlyConstraintFlag = false;
         vps.ptl.intraConstraintFlag = param.keyframeMax <= 1 ||
vps.ptl.onePictureOnlyConstraintFlag;
     }
+#endif

     memset(vps.ptl.profileCompatibilityFlag, 0,
sizeof(vps.ptl.profileCompatibilityFlag));
     vps.ptl.profileCompatibilityFlag[vps.ptl.profileIdc[0]] = true;
@@ -171,14 +174,16 @@ void determineLevel(const x265_param &param, VPS& vps)
     }
     else if (vps.ptl.profileIdc[0] == Profile::MAINREXT)
         vps.ptl.profileCompatibilityFlag[Profile::MAINREXT] = true;
+#if ENABLE_SCC_EXT
     else if (vps.ptl.profileIdc[0] == Profile::MAINSCC)
         vps.ptl.profileCompatibilityFlag[Profile::MAINSCC] = true;
+#endif

     uint32_t lumaSamples = param.sourceWidth * param.sourceHeight;
     uint32_t samplesPerSec = (uint32_t)(lumaSamples *
((double)param.fpsNum / param.fpsDenom));
     uint32_t bitrate = param.rc.vbvMaxBitrate ? param.rc.vbvMaxBitrate :
param.rc.bitrate;

-    const uint32_t MaxDpbPicBuf = !!param.bEnableSCC ? 7 : 6;
+    const uint32_t MaxDpbPicBuf = param.bEnableSCC ? 7 : 6;
     vps.ptl.levelIdc = Level::NONE;
     vps.ptl.tierFlag = Level::MAIN;

@@ -277,6 +282,7 @@ void determineLevel(const x265_param &param, VPS& vps)
         break;
     }

+#if ENABLE_SCC_EXT
     x265_param m_param = param;
 #define CHECK(expr, msg) check_failed |= _confirm(&m_param, expr, msg)
     int check_failed = 0; /* abort if there is a fatal configuration
problem */
@@ -292,6 +298,7 @@ void determineLevel(const x265_param &param, VPS& vps)
         const bool bValidProfile = (bitDepthIdx > 2 || chromaFormatIdx >
3) ? false : (validSCCProfileNames[0][bitDepthIdx][chromaFormatIdx] !=
NONE);
         CHECK(!bValidProfile, "Invalid intra constraint flag, bit depth
constraint flag and chroma format constraint flag combination for a RExt
profile");
     }
+#endif

     static const char* profiles[] = { "None", "Main", "Main 10", "Main
Still Picture", "RExt", "", "", "", "", "Main Scc" };
     static const char *tiers[]    = { "Main", "High" };
@@ -354,6 +361,7 @@ void determineLevel(const x265_param &param, VPS& vps)
             strcat(profbuf, " Intra");
     }

+#if ENABLE_SCC_EXT
     if (vps.ptl.profileIdc[0] == Profile::MAINSCC)
     {
         if (param.internalCsp == X265_CSP_I420)
@@ -371,6 +379,7 @@ void determineLevel(const x265_param &param, VPS& vps)
                 strcpy(profbuf, "Main 4:4:4 10 Scc");
         }
     }
+#endif

     x265_log(&param, X265_LOG_INFO, "%s profile, Level-%s (%s tier)\n",
              profbuf, levels[i].name, tiers[vps.ptl.tierFlag]);
@@ -504,7 +513,7 @@ bool enforceLevel(x265_param& param, VPS& vps)
     }

     /* The value of sps_max_dec_pic_buffering_minus1[ HighestTid ] + 1
shall be less than or equal to MaxDpbSize */
-    const uint32_t MaxDpbPicBuf = !!param.bEnableSCC ? 7 : 6;
+    const uint32_t MaxDpbPicBuf = param.bEnableSCC ? 7 : 6;
     uint32_t maxDpbSize = MaxDpbPicBuf;
     if (!param.uhdBluray) /* Do not change MaxDpbPicBuf for UHD-Bluray */
     {
diff --git a/source/encoder/search.cpp b/source/encoder/search.cpp
index 4fd3b21b1..71a52a1cd 100644
--- a/source/encoder/search.cpp
+++ b/source/encoder/search.cpp
@@ -76,7 +76,9 @@ bool Search::initSearch(const x265_param& param,
ScalingList& scalingList)
     m_param = ¶m;
     m_bFrameParallel = param.frameNumThreads > 1;
     m_numLayers = g_log2Size[param.maxCUSize] - 2;
+#if ENABLE_SCC_EXT
     m_ibcEnabled = param.bEnableSCC;
+#endif

     m_rdCost.setPsyRdScale(param.psyRd);
     m_rdCost.setSsimRd(param.bSsimRd);
@@ -172,8 +174,10 @@ bool Search::initSearch(const x265_param& param,
ScalingList& scalingList)
     CHECKED_MALLOC(m_tsResidual, int16_t, MAX_TS_SIZE * MAX_TS_SIZE);
     CHECKED_MALLOC(m_tsRecon,    pixel,   MAX_TS_SIZE * MAX_TS_SIZE);

+#if ENABLE_SCC_EXT
     m_numBVs = 0;
     m_numBV16s = 0;
+#endif

     return ok;

@@ -1289,8 +1293,10 @@ void Search::checkIntra(Mode& intraMode, const
CUGeom& cuGeom, PartSize partSize
     updateModeCost(intraMode);
     checkDQP(intraMode, cuGeom);

-    if (!!m_param->bEnableSCC)
+#if ENABLE_SCC_EXT
+    if (m_param->bEnableSCC)
         intraMode.reconYuv.copyToPicYuv(*m_frame->m_reconPic[1],
cu.m_cuAddr, cuGeom.absPartIdx);
+#endif
 }

 /* Note that this function does not save the best intra prediction, it must
@@ -1902,7 +1908,22 @@ uint32_t Search::mergeEstimation(CUData& cu, const
CUGeom& cuGeom, const Predict
     MVField  candMvField[MRG_MAX_NUM_CANDS][2];
     uint8_t  candDir[MRG_MAX_NUM_CANDS];
     uint32_t numMergeCand = cu.getInterMergeCandidates(pu.puAbsPartIdx,
puIdx, candMvField, candDir);
+#if ENABLE_SCC_EXT
     restrictBipredMergeCand(&cu, 0, candMvField, candDir, numMergeCand);
+#else
+    if (cu.isBipredRestriction())
+    {
+        /* do not allow bidir merge candidates if PU is smaller than 8x8,
drop L1 reference */
+        for (uint32_t mergeCand = 0; mergeCand < numMergeCand; ++mergeCand)
+        {
+            if (candDir[mergeCand] == 3)
+            {
+                candDir[mergeCand] = 1;
+                candMvField[mergeCand][1].refIdx = REF_NOT_VALID;
+            }
+        }
+    }
+#endif

     Yuv& tempYuv = m_rqt[cuGeom.depth].tmpPredYuv;

@@ -1931,10 +1952,12 @@ uint32_t Search::mergeEstimation(CUData& cu, const
CUGeom& cuGeom, const Predict
                 continue;
         }

+#if ENABLE_SCC_EXT
         if ((candDir[mergeCand] == 1 || candDir[mergeCand] == 3) &&
(m_slice->m_refPOCList[0][candMvField[mergeCand][0].refIdx] ==
m_slice->m_poc))
         {
             continue;
         }
+#endif
         cu.m_mv[0][pu.puAbsPartIdx] = candMvField[mergeCand][0].mv;
         cu.m_refIdx[0][pu.puAbsPartIdx] =
(int8_t)candMvField[mergeCand][0].refIdx;
         cu.m_mv[1][pu.puAbsPartIdx] = candMvField[mergeCand][1].mv;
@@ -2014,9 +2037,11 @@ int Search::selectMVP(const CUData& cu, const
PredictionUnit& pu, const MV amvp[
                 continue;
         }
         cu.clipMv(mvCand);
-        if (!!m_slice->m_param->bEnableSCC && !list && ref ==
m_slice->m_numRefIdx[0] - 1)
+#if ENABLE_SCC_EXT
+        if (m_slice->m_param->bEnableSCC && !list && ref ==
m_slice->m_numRefIdx[0] - 1)
             predInterLumaPixel(pu, tmpPredYuv,
*m_slice->m_refFrameList[list][ref]->m_reconPic[1], mvCand);
         else
+#endif
             predInterLumaPixel(pu, tmpPredYuv,
*m_slice->m_refReconPicList[list][ref], mvCand);
         costs[i] = m_me.bufSAD(tmpPredYuv.getLumaAddr(pu.puAbsPartIdx),
tmpPredYuv.m_size);
     }
@@ -2089,8 +2114,10 @@ void Search::singleMotionEstimation(Search& master,
Mode& interMode, const Predi
 {
     uint32_t bits = master.m_listSelBits[list] + MVP_IDX_BITS;
     int numIdx = m_slice->m_numRefIdx[list];
+#if ENABLE_SCC_EXT
     if (!list && m_ibcEnabled)
         numIdx--;
+#endif
     bits += getTUBits(ref, numIdx);

     MotionData* bestME = interMode.bestME[part];
@@ -2252,8 +2279,10 @@ void Search::predInterSearch(Mode& interMode, const
CUGeom& cuGeom, bool bChroma
                 }
                 uint32_t bits = m_listSelBits[list] + MVP_IDX_BITS;
                 int numIdx = m_slice->m_numRefIdx[list];
+#if ENABLE_SCC_EXT
                 if (!list && m_ibcEnabled)
                     numIdx--;
+#endif
                 bits += getTUBits(ref, numIdx);

                 int numMvc = cu.getPMV(interMode.interNeighbours, list,
ref, interMode.amvpCand[list][ref], mvc, puIdx, pu.puAbsPartIdx);
@@ -2363,8 +2392,10 @@ void Search::predInterSearch(Mode& interMode, const
CUGeom& cuGeom, bool bChroma
             {
                 int idx = 0;
                 int numIdx = numRefIdx[list];
+#if ENABLE_SCC_EXT
                 if (!list && m_ibcEnabled)
                     numIdx--;
+#endif
                 for (int ref = 0; ref < numIdx; ref++)
                 {
                     if (!(refMask & (1 << ref)))
@@ -2405,8 +2436,10 @@ void Search::predInterSearch(Mode& interMode, const
CUGeom& cuGeom, bool bChroma
             for (int list = 0; list < numPredDir; list++)
             {
                 int numIdx = numRefIdx[list];
+#if ENABLE_SCC_EXT
                 if (!list && m_ibcEnabled)
                     numIdx--;
+#endif
                 for (int ref = 0; ref < numIdx; ref++)
                 {
                     ProfileCounter(interMode.cu,
totalMotionReferences[cuGeom.depth]);
@@ -2473,10 +2506,12 @@ void Search::predInterSearch(Mode& interMode, const
CUGeom& cuGeom, bool bChroma
                     /* Refine MVP selection, updates: mvpIdx, bits, cost */
                     mvp = checkBestMVP(amvp, outmv, mvpIdx, bits, cost);

+#if ENABLE_SCC_EXT
                     if (list <= 1 && ref <= 1 && (cu.m_partSize[0] ==
SIZE_2NxN || cu.m_partSize[0] == SIZE_Nx2N) && (1 << cu.m_log2CUSize[0]) <=
16)
                     {
                         iMVCandList[4 * list + 2 * ref + puIdx] = outmv;
                     }
+#endif

                     if (cost < bestME[list].cost)
                     {
@@ -2670,6 +2705,7 @@ void Search::predInterSearch(Mode& interMode, const
CUGeom& cuGeom, bool bChroma
     interMode.sa8dBits += totalmebits;
 }

+#if ENABLE_SCC_EXT
 uint32_t Search::getSAD(pixel* ref, int refStride, const pixel* curr, int
currStride, int width, int height)
 {
     uint32_t dist = 0;
@@ -4397,6 +4433,7 @@ bool Search::predMixedIntraBCInterSearch(Mode&
intraBCMixedMode, const CUGeom& c

     return true;
 }
+#endif

 void Search::getBlkBits(PartSize cuMode, bool bPSlice, int partIdx,
uint32_t lastMode, uint32_t blockBit[3])
 {
@@ -4734,8 +4771,10 @@ void Search::encodeResAndCalcRdInterCU(Mode&
interMode, const CUGeom& cuGeom)
     updateModeCost(interMode);
     checkDQP(interMode, cuGeom);

-    if (!!m_param->bEnableSCC)
+#if ENABLE_SCC_EXT
+    if (m_param->bEnableSCC)
         interMode.reconYuv.copyToPicYuv(*m_frame->m_reconPic[1],
cu.m_cuAddr, cuGeom.absPartIdx);
+#endif
 }

 void Search::residualTransformQuantInter(Mode& mode, const CUGeom& cuGeom,
uint32_t absPartIdx, uint32_t tuDepth, const uint32_t depthRange[2])
diff --git a/source/encoder/search.h b/source/encoder/search.h
index 3ae3655b1..f12ac02e0 100644
--- a/source/encoder/search.h
+++ b/source/encoder/search.h
@@ -288,11 +288,14 @@ public:

     bool            m_vertRestriction;

+#if ENABLE_SCC_EXT
     int             m_ibcEnabled;
     int             m_numBVs;
     int             m_numBV16s;
     MV              m_BVs[64];
     uint32_t        m_lastCandCost;
+#endif
+
 #if DETAILED_CU_STATS
     /* Accumulate CU statistics separately for each frame encoder */
     CUStats         m_stats[X265_MAX_FRAME_THREADS];
@@ -336,6 +339,7 @@ public:

     MV getLowresMV(const CUData& cu, const PredictionUnit& pu, int list,
int ref);

+#if ENABLE_SCC_EXT
     bool      predIntraBCSearch(Mode& intraBCMode, const CUGeom& cuGeom,
bool bChromaMC, PartSize ePartSize, bool testOnlyPred, bool
bUse1DSearchFor8x8, IBC& ibc);
     void      intraBlockCopyEstimate(Mode& intraBCMode, const CUGeom&
cuGeom, int puIdx, MV* pred, MV& mv, uint32_t& cost, bool testOnlyPred,
bool bUse1DSearchFor8x8, IBC& ibc);
     void      setIntraSearchRange(Mode& intraBCMode, MV& pred, int puIdx,
int roiWidth, int roiHeight, MV& searchRangeLT, MV& searchRangeRB);
@@ -352,6 +356,7 @@ public:
     uint32_t  getSAD(pixel* ref, int refStride, const pixel* curr, int
currStride, int width, int height);
     bool      predMixedIntraBCInterSearch(Mode& intraBCMode, const CUGeom&
cuGeom, bool bChromaMC, PartSize ePartSize, MV* iMVCandList);
     void      restrictBipredMergeCand(CUData* cu, uint32_t puIdx,
MVField(*mvFieldNeighbours)[2], uint8_t* interDirNeighbours, uint32_t
numValidMergeCand);
+#endif

     class PME : public BondedTaskGroup
     {
diff --git a/source/encoder/weightPrediction.cpp
b/source/encoder/weightPrediction.cpp
index 724757429..a4a34f826 100644
--- a/source/encoder/weightPrediction.cpp
+++ b/source/encoder/weightPrediction.cpp
@@ -492,8 +492,10 @@ void weightAnalyse(Slice& slice, Frame& frame,
x265_param& param)
         chromaDenom = weights[1].log2WeightDenom;

         int numIdx = slice.m_numRefIdx[list];
+#if ENABLE_SCC_EXT
         if (!list && param.bEnableSCC)
             numIdx--;
+#endif

         /* reset weight states */
         for (int ref = 1; ref < numIdx; ref++)
diff --git a/source/x265.h b/source/x265.h
index 889dda934..c8651c7dd 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -654,6 +654,7 @@ typedef enum
 #define MAX_LAYERS              1
 #endif

+#if ENABLE_SCC_EXT
 /* SCC Extension Options */
 #define SCC_EXT_IDX               3
 #define NUM_EXTENSION_FLAGS       8
@@ -661,6 +662,10 @@ typedef enum
 #define CHROMA_REFINEMENT_CANDIDATES  8
 #define SCM_S0067_IBC_FULL_1D_SEARCH_FOR_PU  2 ///< Do full
horizontal/vertical search for Nx2N
 #define SCM_S0067_MAX_CAND_SIZE  32 ///< 32 or 64, 16 by default
+#define NUM_RECON_VERSION          2
+#else
+#define NUM_RECON_VERSION          1
+#endif

 #define X265_IPRATIO_STRENGTH   1.43

@@ -2374,7 +2379,9 @@ static const char * const x265_profile_names[] = {

     "main444-16-intra", "main444-16-stillpicture", /* Not Supported! */

+#if ENABLE_SCC_EXT
     "main-scc", "main10-scc", "main444-scc", "main444-10-scc", /* Screen
content coding */
+#endif
     0
 };

diff --git a/source/x265cli.cpp b/source/x265cli.cpp
index 2e02b1e44..d4fe886cc 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -382,7 +382,9 @@ namespace X265_NS {
         H0("   --format                      Format of the input video 0 :
normal, 1 : side-by-side, 2 : over-under  Default %d\n", param->format);
         H0("   --multiview-config            Configuration file for
Multiview Encoding\n");
 #endif
+#if ENABLE_SCC_EXT
         H0("   --scc <integer>               Enable screen content coding.
0: Diabled, 1:Intrablockcopy fast search with 1x2 CTUs search range, 2:
Intrablockcopy Full search. Default %d\n", param->bEnableSCC);
+#endif
 #ifdef SVT_HEVC
         H0("   --[no]svt                     Enable SVT HEVC encoder
%s\n", OPT(param->bEnableSvtHevc));
         H0("   --[no-]svt-hme                Enable Hierarchial motion
estimation(HME) in SVT HEVC encoder \n");
diff --git a/source/x265cli.h b/source/x265cli.h
index 654356287..2ec48352d 100644
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -366,7 +366,9 @@ static const struct option long_options[] =
     { "multiview-config", required_argument, NULL, 0 },
     { "format", required_argument, NULL, 0 },
 #endif
+#if ENABLE_SCC_EXT
     { "scc",        required_argument, NULL, 0 },
+#endif
 #ifdef SVT_HEVC
     { "svt",     no_argument, NULL, 0 },
     { "no-svt",  no_argument, NULL, 0 },
-- 
2.36.0.windows.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240807/722d25a0/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0008-Add-compile-time-flag-for-scc.patch
Type: application/octet-stream
Size: 56505 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240807/722d25a0/attachment-0001.obj>


More information about the x265-devel mailing list