<div dir="ltr">From 85c51ad5a99db52001e254296ae64335074e47a5 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: Thu, 18 Jul 2024 20:37:58 +0530<br>Subject: [PATCH 2/9] Add profiletier, sps, pps MainScc profile support for scc<br> extension<br><br>---<br> source/common/slice.h      |  5 ++-<br> source/encoder/encoder.cpp |  8 ++++<br> source/encoder/entropy.cpp | 48 +++++++++++++++++---<br> source/encoder/level.cpp   | 92 +++++++++++++++++++++++++++++++++++---<br> source/x265.h              |  6 +++<br> 5 files changed, 147 insertions(+), 12 deletions(-)<br><br>diff --git a/source/common/slice.h b/source/common/slice.h<br>index 0d6807952..add5948f8 100644<br>--- a/source/common/slice.h<br>+++ b/source/common/slice.h<br>@@ -76,7 +76,8 @@ namespace Profile {<br>         HIGHTHROUGHPUTREXT = 5,<br>         MULTIVIEWMAIN = 6,<br>         SCALABLEMAIN = 7,<br>-        SCALABLEMAIN10 = 8<br>+        SCALABLEMAIN10 = 8,<br>+        MAINSCC = 9<br>     };<br> }<br> <br>@@ -324,6 +325,8 @@ struct PPS<br> <br>     bool     pps_extension_flag;<br>     int      maxViews;<br>+<br>+    int      profileIdc;<br> };<br> <br> struct WeightParam<br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index ff8f53883..095009200 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -3656,6 +3656,8 @@ void Encoder::initSPS(SPS *sps)<br>     }<br> #endif<br> <br>+    sps->sps_extension_flag = m_param->bEnableSCC ? true : false;<br>+<br> }<br> <br> void Encoder::initPPS(PPS *pps)<br>@@ -3710,6 +3712,12 @@ void Encoder::initPPS(PPS *pps)<br>         pps->maxViews = m_param->numViews;<br>     }<br> #endif<br>+<br>+    if (m_param->bEnableSCC)<br>+    {<br>+        pps->profileIdc = Profile::MAINSCC;<br>+        pps->pps_extension_flag = true;<br>+    }<br> }<br> <br> void Encoder::configureZone(x265_param *p, x265_param *zone)<br>diff --git a/source/encoder/entropy.cpp b/source/encoder/entropy.cpp<br>index 0e45b4976..400a7dd8e 100644<br>--- a/source/encoder/entropy.cpp<br>+++ b/source/encoder/entropy.cpp<br>@@ -585,7 +585,7 @@ void Entropy::codeSPS(const SPS& sps, const ScalingList& scalingList, const Prof<br>     WRITE_FLAG(sps.sps_extension_flag, "sps_extension_flag");<br> <br> #if ENABLE_MULTIVIEW<br>-    if (sps.sps_extension_flag)<br>+    if (sps.sps_extension_flag && sps.maxViews > 1)<br>     {<br>         WRITE_FLAG(0, "sps_range_extensions_flag");<br>         WRITE_FLAG(sps.maxViews > 1, "sps_multilayer_extension_flag");<br>@@ -598,6 +598,18 @@ void Entropy::codeSPS(const SPS& sps, const ScalingList& scalingList, const Prof<br>             WRITE_FLAG(1, "inter_view_mv_vert_constraint_flag");<br>     }<br> #endif<br>+<br>+    if (ptl.profileIdc[0] == Profile::MAINSCC)<br>+    {<br>+        bool sps_extension_flags[NUM_EXTENSION_FLAGS] = { false };<br>+        sps_extension_flags[SCC_EXT_IDX] = true;<br>+        for (int i = 0; i < NUM_EXTENSION_FLAGS; i++)<br>+            WRITE_FLAG(sps_extension_flags[i], "sps_extension_flag");<br>+        WRITE_FLAG(1, "intra_block_copy_enabled_flag");<br>+        WRITE_FLAG(0, "palette_mode_enabled_flag");<br>+        WRITE_CODE(0, 2, "motion_vector_resolution_control_idc");<br>+        WRITE_FLAG(0, "intra_boundary_filter_disabled_flag");<br>+    }<br> }<br> <br> void Entropy::codePPS( const PPS& pps, bool filerAcross, int iPPSInitQpMinus26, int layer)<br>@@ -650,7 +662,7 @@ void Entropy::codePPS( const PPS& pps, bool filerAcross, int iPPSInitQpMinus26,<br>     WRITE_FLAG(pps.pps_extension_flag, "pps_extension_flag");<br> <br> #if ENABLE_MULTIVIEW<br>-    if (pps.pps_extension_flag)<br>+    if (pps.pps_extension_flag && pps.maxViews > 1)<br>     {<br>         WRITE_FLAG(0, "pps_range_extensions_flag");<br>         WRITE_FLAG(pps.maxViews > 1, "pps_multilayer_extension_flag");<br>@@ -666,6 +678,18 @@ void Entropy::codePPS( const PPS& pps, bool filerAcross, int iPPSInitQpMinus26,<br>         }<br>     }<br> #endif<br>+<br>+<br>+    if (pps.profileIdc == Profile::MAINSCC)<br>+    {<br>+        bool pps_extension_flags[NUM_EXTENSION_FLAGS] = { false };<br>+        pps_extension_flags[SCC_EXT_IDX] = true;<br>+        for (int i = 0; i < NUM_EXTENSION_FLAGS; i++)<br>+            WRITE_FLAG(pps_extension_flags[i], "pps_extension_flag");<br>+        WRITE_FLAG(1, "curr_pic_as_ref_enabled_pps_flag");<br>+        WRITE_FLAG(0, "adaptive_colour_trans_flag");<br>+        WRITE_FLAG(0, "palette_predictor_initializer_flag");<br>+    }<br> }<br> <br> void Entropy::codeProfileTier(const ProfileTierLevel& ptl, int maxTempSubLayers, int layer)<br>@@ -686,7 +710,7 @@ void Entropy::codeProfileTier(const ProfileTierLevel& ptl, int maxTempSubLayers,<br>     WRITE_FLAG(ptl.nonPackedConstraintFlag, "general_non_packed_constraint_flag");<br>     WRITE_FLAG(ptl.frameOnlyConstraintFlag, "general_frame_only_constraint_flag");<br> <br>-    if (ptl.profileIdc[layer] == Profile::MAINREXT || ptl.profileIdc[layer] == Profile::HIGHTHROUGHPUTREXT || ptl.profileIdc[layer] == Profile::SCALABLEMAIN || ptl.profileIdc[layer] == Profile::SCALABLEMAIN10 || ptl.profileIdc[layer] == Profile::MULTIVIEWMAIN)<br>+    if (ptl.profileIdc[layer] == Profile::MAINREXT || ptl.profileIdc[layer] == Profile::HIGHTHROUGHPUTREXT || ptl.profileIdc[layer] == Profile::SCALABLEMAIN || ptl.profileIdc[layer] == Profile::SCALABLEMAIN10 || ptl.profileIdc[layer] == Profile::MULTIVIEWMAIN || ptl.profileIdc[layer] == Profile::MAINSCC)<br>     {<br>         uint32_t bitDepthConstraint = ptl.bitDepthConstraint;<br>         int csp = ptl.chromaFormatConstraint;<br>@@ -699,9 +723,19 @@ void Entropy::codeProfileTier(const ProfileTierLevel& ptl, int maxTempSubLayers,<br>         WRITE_FLAG(ptl.intraConstraintFlag,        "general_intra_constraint_flag");<br>         WRITE_FLAG(ptl.onePictureOnlyConstraintFlag,"general_one_picture_only_constraint_flag");<br>         WRITE_FLAG(ptl.lowerBitRateConstraintFlag, "general_lower_bit_rate_constraint_flag");<br>-        WRITE_CODE(0 , 16, "XXX_reserved_zero_35bits[0..15]");<br>-        WRITE_CODE(0 , 16, "XXX_reserved_zero_35bits[16..31]");<br>-        WRITE_CODE(0 ,  3, "XXX_reserved_zero_35bits[32..34]");<br>+        if (ptl.profileIdc[layer] == Profile::MAINSCC)<br>+        {<br>+            WRITE_FLAG(bitDepthConstraint <= 14, "max_14bit_constraint_flag");<br>+            WRITE_CODE(0, 16, "reserved_zero_33bits[0..15]");<br>+            WRITE_CODE(0, 16, "reserved_zero_33bits[16..31]");<br>+            WRITE_FLAG(0, "reserved_zero_33bits[32]");<br>+        }<br>+        else<br>+        {<br>+            WRITE_CODE(0, 16, "XXX_reserved_zero_35bits[0..15]");<br>+            WRITE_CODE(0, 16, "XXX_reserved_zero_35bits[16..31]");<br>+            WRITE_CODE(0, 3, "XXX_reserved_zero_35bits[32..34]");<br>+        }<br>     }<br>     else<br>     {<br>@@ -709,6 +743,8 @@ void Entropy::codeProfileTier(const ProfileTierLevel& ptl, int maxTempSubLayers,<br>         WRITE_CODE(0, 16, "XXX_reserved_zero_44bits[16..31]");<br>         WRITE_CODE(0, 12, "XXX_reserved_zero_44bits[32..43]");<br>     }<br>+    if (ptl.profileIdc[layer] == Profile::MAINSCC)<br>+        WRITE_FLAG(false, "inbld_flag");<br> <br>     WRITE_CODE(ptl.levelIdc, 8, "general_level_idc");<br> <br>diff --git a/source/encoder/level.cpp b/source/encoder/level.cpp<br>index 12803baff..b5af25b4f 100644<br>--- a/source/encoder/level.cpp<br>+++ b/source/encoder/level.cpp<br>@@ -60,6 +60,40 @@ LevelSpec levels[] =<br>     { MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, 1, Level::LEVEL8_5, "8.5", 85 },<br> };<br> <br>+enum SCCProfileName<br>+{<br>+    NONE = 0,<br>+    // The following are SCC profiles, which would map to the MAINSCC profile idc.<br>+    // The enumeration indicates the bit-depth constraint in the bottom 2 digits<br>+    //                           the chroma format in the next digit<br>+    //                           the intra constraint in the next digit<br>+    //                           If it is a SCC profile there is a '2' for the next digit.<br>+    //                           If it is a highthroughput , there is a '2' for the top digit else '1' for the top digit<br>+    SCC_MAIN = 121108,<br>+    SCC_MAIN_10 = 121110,<br>+    SCC_MAIN_444 = 121308,<br>+    SCC_MAIN_444_10 = 121310,<br>+};<br>+<br>+static const SCCProfileName validSCCProfileNames[1][4/* bit depth constraint 8=0, 10=1, 12=2, 14=3*/][4/*chroma format*/] =<br>+{<br>+   {<br>+        { NONE,         SCC_MAIN,      NONE,      SCC_MAIN_444                     }, // 8-bit  intra for 400, 420, 422 and 444<br>+        { NONE,         SCC_MAIN_10,   NONE,      SCC_MAIN_444_10                  }, // 10-bit intra for 400, 420, 422 and 444<br>+        { NONE,         NONE,          NONE,      NONE                             }, // 12-bit intra for 400, 420, 422 and 444<br>+        { NONE,         NONE,          NONE,      NONE                             }  // 16-bit intra for 400, 420, 422 and 444<br>+    },<br>+};<br>+<br>+static inline int _confirm(x265_param* param, bool bflag, const char* message)<br>+{<br>+    if (!bflag)<br>+        return 0;<br>+<br>+    x265_log(param, X265_LOG_ERROR, "%s\n", message);<br>+    return 1;<br>+}<br>+<br> /* determine minimum decoder level required to decode the described video */<br> void determineLevel(const x265_param &param, VPS& vps)<br> {<br>@@ -79,7 +113,9 @@ void determineLevel(const x265_param &param, VPS& vps)<br>         /* Probably an HEVC v1 profile, but must check to be sure */<br>         if (param.internalBitDepth <= 8)<br>         {<br>-            if (vps.ptl.onePictureOnlyConstraintFlag)<br>+            if (param.bEnableSCC)<br>+                vps.ptl.profileIdc[0] = Profile::MAINSCC;<br>+            else if (vps.ptl.onePictureOnlyConstraintFlag)<br>                 vps.ptl.profileIdc[0] = Profile::MAINSTILLPICTURE;<br>             else if (vps.ptl.intraConstraintFlag)<br>                 vps.ptl.profileIdc[0] = Profile::MAINREXT; /* Main Intra */<br>@@ -94,7 +130,9 @@ void determineLevel(const x265_param &param, VPS& vps)<br>         else if (param.internalBitDepth <= 10)<br>         {<br>             /* note there is no 10bit still picture profile */<br>-            if (vps.ptl.intraConstraintFlag)<br>+            if (param.bEnableSCC)<br>+                vps.ptl.profileIdc[0] = Profile::MAINSCC;<br>+            else if (vps.ptl.intraConstraintFlag)<br>                 vps.ptl.profileIdc[0] = Profile::MAINREXT; /* Main10 Intra */<br>             else<br>                 vps.ptl.profileIdc[0] = Profile::MAIN10;<br>@@ -114,6 +152,11 @@ void determineLevel(const x265_param &param, VPS& vps)<br> #endif<br> <br>     /* determine which profiles are compatible with this stream */<br>+    if (vps.ptl.profileIdc[0] == Profile::MAINSCC)<br>+    {<br>+        vps.ptl.onePictureOnlyConstraintFlag = false;<br>+        vps.ptl.intraConstraintFlag = param.keyframeMax <= 1 || vps.ptl.onePictureOnlyConstraintFlag;<br>+    }<br> <br>     memset(vps.ptl.profileCompatibilityFlag, 0, sizeof(vps.ptl.profileCompatibilityFlag));<br>     vps.ptl.profileCompatibilityFlag[vps.ptl.profileIdc[0]] = true;<br>@@ -128,6 +171,8 @@ void determineLevel(const x265_param &param, VPS& vps)<br>     }<br>     else if (vps.ptl.profileIdc[0] == Profile::MAINREXT)<br>         vps.ptl.profileCompatibilityFlag[Profile::MAINREXT] = true;<br>+    else if (vps.ptl.profileIdc[0] == Profile::MAINSCC)<br>+        vps.ptl.profileCompatibilityFlag[Profile::MAINSCC] = true;<br> <br>     uint32_t lumaSamples = param.sourceWidth * param.sourceHeight;<br>     uint32_t samplesPerSec = (uint32_t)(lumaSamples * ((double)param.fpsNum / param.fpsDenom));<br>@@ -232,7 +277,23 @@ void determineLevel(const x265_param &param, VPS& vps)<br>         break;<br>     }<br> <br>-    static const char *profiles[] = { "None", "Main", "Main 10", "Main Still Picture", "RExt" };<br>+    x265_param m_param = param;<br>+#define CHECK(expr, msg) check_failed |= _confirm(&m_param, expr, msg)<br>+    int check_failed = 0; /* abort if there is a fatal configuration problem */<br>+<br>+    if (vps.ptl.profileIdc[0] == Profile::MAINSCC)<br>+    {<br>+        CHECK(vps.ptl.lowerBitRateConstraintFlag == false && vps.ptl.intraConstraintFlag == false, "The lowerBitRateConstraint flag cannot be false when intraConstraintFlag is false");<br>+        CHECK(param.bEnableSCC && !(vps.ptl.profileIdc[0] == Profile::MAINSCC), "UseIntraBlockCopy must not be enabled unless the SCC profile is being used.");<br>+        CHECK(vps.ptl.intraConstraintFlag, "intra constraint flag must be 0 for SCC profiles");<br>+        CHECK(vps.ptl.onePictureOnlyConstraintFlag, "one-picture-only constraint flag shall be 0 for SCC profiles");<br>+        const uint32_t bitDepthIdx = (vps.ptl.bitDepthConstraint == 8 ? 0 : (vps.ptl.bitDepthConstraint == 10 ? 1 : (vps.ptl.bitDepthConstraint == 12 ? 2 : (vps.ptl.bitDepthConstraint == 16 ? 3 : 4))));<br>+        const uint32_t chromaFormatIdx = uint32_t(vps.ptl.chromaFormatConstraint);<br>+        const bool bValidProfile = (bitDepthIdx > 2 || chromaFormatIdx > 3) ? false : (validSCCProfileNames[0][bitDepthIdx][chromaFormatIdx] != NONE);<br>+        CHECK(!bValidProfile, "Invalid intra constraint flag, bit depth constraint flag and chroma format constraint flag combination for a RExt profile");<br>+    }<br>+<br>+    static const char* profiles[] = { "None", "Main", "Main 10", "Main Still Picture", "RExt", "", "", "", "", "Main Scc" };<br>     static const char *tiers[]    = { "Main", "High" };<br> <br>     char profbuf[64];<br>@@ -292,6 +353,25 @@ void determineLevel(const x265_param &param, VPS& vps)<br>         if (vps.ptl.intraConstraintFlag && !bStillPicture)<br>             strcat(profbuf, " Intra");<br>     }<br>+<br>+    if (vps.ptl.profileIdc[0] == Profile::MAINSCC)<br>+    {<br>+        if (param.internalCsp == X265_CSP_I420)<br>+        {<br>+            if (vps.ptl.bitDepthConstraint <= 8)<br>+                strcpy(profbuf, "Main Scc");<br>+            else if (vps.ptl.bitDepthConstraint <= 10)<br>+                strcpy(profbuf, "Main 10 Scc");<br>+        }<br>+        else if (param.internalCsp == X265_CSP_I444)<br>+        {<br>+            if (vps.ptl.bitDepthConstraint <= 8)<br>+                strcpy(profbuf, "Main 4:4:4 Scc");<br>+            else if (vps.ptl.bitDepthConstraint <= 10)<br>+                strcpy(profbuf, "Main 4:4:4 10 Scc");<br>+        }<br>+    }<br>+<br>     x265_log(&param, X265_LOG_INFO, "%s profile, Level-%s (%s tier)\n",<br>              profbuf, levels[i].name, tiers[vps.ptl.tierFlag]);<br> }<br>@@ -535,7 +615,8 @@ int x265_param_apply_profile(x265_param *param, const char *profile)<br>     if (!strcmp(profile, "main") || !strcmp(profile, "main-intra") ||<br>         !strcmp(profile, "main10") || !strcmp(profile, "main10-intra") ||<br>         !strcmp(profile, "main12") || !strcmp(profile, "main12-intra") ||<br>-        !strcmp(profile, "mainstillpicture") || !strcmp(profile, "msp"))<br>+        !strcmp(profile, "mainstillpicture") || !strcmp(profile, "msp") ||<br>+        !strcmp(profile, "main-scc") || !strcmp(profile, "main10-scc"))<br>     {<br>         if (param->internalCsp != X265_CSP_I420)<br>         {<br>@@ -558,7 +639,8 @@ int x265_param_apply_profile(x265_param *param, const char *profile)<br>              !strcmp(profile, "main444-intra") || !strcmp(profile, "main444-stillpicture") ||<br>              !strcmp(profile, "main444-10") || !strcmp(profile, "main444-10-intra") ||<br>              !strcmp(profile, "main444-12") || !strcmp(profile, "main444-12-intra") ||<br>-             !strcmp(profile, "main444-16-intra") || !strcmp(profile, "main444-16-stillpicture"))<br>+             !strcmp(profile, "main444-16-intra") || !strcmp(profile, "main444-16-stillpicture") ||<br>+             !strcmp(profile, "main444-scc") || !strcmp(profile, "main444-10-scc"))<br>     {<br>         /* any color space allowed */<br>     }<br>diff --git a/source/x265.h b/source/x265.h<br>index 530ae4d81..abe3f16f0 100644<br>--- a/source/x265.h<br>+++ b/source/x265.h<br>@@ -654,6 +654,10 @@ typedef enum<br> #define MAX_LAYERS              1<br> #endif<br> <br>+/* SCC Extension Options */<br>+#define SCC_EXT_IDX               3<br>+#define NUM_EXTENSION_FLAGS       8<br>+<br> #define X265_IPRATIO_STRENGTH   1.43<br> <br> typedef struct x265_cli_csp<br>@@ -2365,6 +2369,8 @@ static const char * const x265_profile_names[] = {<br>     "main444-12", "main444-12-intra",<br> <br>     "main444-16-intra", "main444-16-stillpicture", /* Not Supported! */<br>+<br>+    "main-scc", "main10-scc", "main444-scc", "main444-10-scc", /* Screen content coding */<br>     0<br> };<br> <br>-- <br>2.36.0.windows.1<br><br></div>