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