[x265] [PATCH 1 of 2] level: plumb in support for Main12 and *-Intra profiles

Steve Borho steve at borho.org
Thu Jul 2 21:43:38 CEST 2015


# HG changeset patch
# User Steve Borho <steve at borho.org>
# Date 1435866171 18000
#      Thu Jul 02 14:42:51 2015 -0500
# Node ID c2fcd2315b664f7e547d691f27aefaeef616944c
# Parent  a632a7b1b90e8d8a6eccfc72317c4e34ea1935a2
level: plumb in support for Main12 and *-Intra profiles

the encoder will now signal Main-Intra if MainStillPicture is requested but
multiple frames are intended to be encoded.

diff -r a632a7b1b90e -r c2fcd2315b66 doc/reST/cli.rst
--- a/doc/reST/cli.rst	Mon Jun 29 16:17:01 2015 -0700
+++ b/doc/reST/cli.rst	Thu Jul 02 14:42:51 2015 -0500
@@ -444,13 +444,20 @@
 	profile.  May abort the encode if the specified profile is
 	impossible to be supported by the compile options chosen for the
 	encoder (a high bit depth encoder will be unable to output
-	bitstreams compliant with Main or Mainstillpicture).
+	bitstreams compliant with Main or Mains-Still-Picture).
+
+	Note: Main12 presets are extremely unstable, do not use them yet.
+	      And Main16 is not supported at all.
 
 	API users must use x265_param_apply_profile() after configuring
 	their param structure. Any changes made to the param structure after
 	this call might make the encode non-compliant.
 
-	**Values:** main, main10, mainstillpicture, main422-8, main422-10, main444-8, main444-10
+	**Values:** main, main10, mainstillpicture, msp
+				main-intra main10-intra main444-8 main444-intra main444-stillpicture
+				main422-10 main422-10-intra main444-10 main444-10-intra main12 main12-intra
+				main422-12 main422-12-intra main444-12 main444-12-intra
+				main444-16-intra main444-16-stillpicture
 
 	**CLI ONLY**
 
diff -r a632a7b1b90e -r c2fcd2315b66 source/common/param.cpp
--- a/source/common/param.cpp	Mon Jun 29 16:17:01 2015 -0700
+++ b/source/common/param.cpp	Thu Jul 02 14:42:51 2015 -0500
@@ -1010,15 +1010,8 @@
     uint32_t tuQTMaxLog2Size = X265_MIN(maxLog2CUSize, 5);
     uint32_t tuQTMinLog2Size = 2; //log2(4)
 
-    /* These checks might be temporary */
-#if HIGH_BIT_DEPTH
-    CHECK(param->internalBitDepth != 10,
-          "x265 was compiled for 10bit encodes, only 10bit internal depth supported");
-#else
-    CHECK(param->internalBitDepth != 8,
-          "x265 was compiled for 8bit encodes, only 8bit internal depth supported");
-#endif
-
+    CHECK(param->internalBitDepth != X265_DEPTH,
+          "internalBitDepth must match compiled bit depth");
     CHECK(param->minCUSize != 64 && param->minCUSize != 32 && param->minCUSize != 16 && param->minCUSize != 8,
           "minimim CU size must be 8, 16, 32, or 64");
     CHECK(param->minCUSize > param->maxCUSize,
diff -r a632a7b1b90e -r c2fcd2315b66 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Mon Jun 29 16:17:01 2015 -0700
+++ b/source/encoder/encoder.cpp	Thu Jul 02 14:42:51 2015 -0500
@@ -1389,9 +1389,23 @@
     }
     else if (p->keyframeMax <= 1)
     {
+        p->keyframeMax = 1;
+
         // disable lookahead for all-intra encodes
         p->bFrameAdaptive = 0;
         p->bframes = 0;
+        p->bOpenGOP = 0;
+        p->bRepeatHeaders = 1;
+        p->lookaheadDepth = 0;
+        p->bframes = 0;
+        p->scenecutThreshold = 0;
+        p->bFrameAdaptive = 0;
+        p->rc.cuTree = 0;
+        p->bEnableWeightedPred = 0;
+        p->bEnableWeightedBiPred = 0;
+
+        /* SPSs shall have sps_max_dec_pic_buffering_minus1[ sps_max_sub_layers_minus1 ] equal to 0 only */
+        p->maxNumReferences = 1;
     }
     if (!p->keyframeMin)
     {
diff -r a632a7b1b90e -r c2fcd2315b66 source/encoder/level.cpp
--- a/source/encoder/level.cpp	Mon Jun 29 16:17:01 2015 -0700
+++ b/source/encoder/level.cpp	Thu Jul 02 14:42:51 2015 -0500
@@ -62,12 +62,17 @@
 void determineLevel(const x265_param &param, VPS& vps)
 {
     vps.maxTempSubLayers = param.bEnableTemporalSubLayers ? 2 : 1;
-    if (param.internalCsp == X265_CSP_I420)
+    if (param.internalCsp == X265_CSP_I420 && param.internalBitDepth <= 10)
     {
         if (param.internalBitDepth == 8)
         {
             if (param.keyframeMax == 1 && param.maxNumReferences == 1)
-                vps.ptl.profileIdc = Profile::MAINSTILLPICTURE;
+            {
+                if (param.totalFrames == 1)
+                    vps.ptl.profileIdc = Profile::MAINSTILLPICTURE;
+                else
+                    vps.ptl.profileIdc = Profile::MAINREXT; /* Main Intra */
+            }
             else 
                 vps.ptl.profileIdc = Profile::MAIN;
         }
@@ -186,7 +191,7 @@
         break;
     }
 
-    vps.ptl.intraConstraintFlag = false;
+    vps.ptl.intraConstraintFlag = param.keyframeMax == 1;
     vps.ptl.lowerBitRateConstraintFlag = true;
     vps.ptl.bitDepthConstraint = param.internalBitDepth;
     vps.ptl.chromaFormatConstraint = param.internalCsp;
@@ -194,21 +199,56 @@
     static const char *profiles[] = { "None", "Main", "Main 10", "Main Still Picture", "RExt" };
     static const char *tiers[]    = { "Main", "High" };
 
-    const char *profile = profiles[vps.ptl.profileIdc];
+    char profbuf[64];
+    strcpy(profbuf, profiles[vps.ptl.profileIdc]);
+
+    bool bStillPicture = false;
     if (vps.ptl.profileIdc == Profile::MAINREXT)
     {
         if (param.internalCsp == X265_CSP_I422)
-            profile = "Main 4:2:2 10";
-        if (param.internalCsp == X265_CSP_I444)
+        {
+            if (param.internalBitDepth <= 10)
+                strcpy(profbuf, "Main 4:2:2 10");
+            else if (vps.ptl.bitDepthConstraint <= 12)
+                strcpy(profbuf, "Main 4:2:2 12");
+        }
+        else if (param.internalCsp == X265_CSP_I444)
         {
             if (vps.ptl.bitDepthConstraint <= 8)
-                profile = "Main 4:4:4 8";
+            {
+                if (vps.ptl.intraConstraintFlag && param.totalFrames == 1)
+                {
+                    strcpy(profbuf, "Main 4:4:4 Still Picture");
+                    bStillPicture = true;
+                }
+                else
+                    strcpy(profbuf, "Main 4:4:4 8");
+            }
             else if (vps.ptl.bitDepthConstraint <= 10)
-                profile = "Main 4:4:4 10";
+                strcpy(profbuf, "Main 4:4:4 10");
+            else if (vps.ptl.bitDepthConstraint <= 12)
+                strcpy(profbuf, "Main 4:4:4 12");
+            else
+            {
+                if (vps.ptl.intraConstraintFlag && param.totalFrames == 1)
+                {
+                    strcpy(profbuf, "Main 4:4:4 16 Still Picture");
+                    bStillPicture = true;
+                }
+                else
+                    strcpy(profbuf, "Main 4:4:4 16");
+            }
         }
+        else if (vps.ptl.bitDepthConstraint <= 12)
+            strcpy(profbuf, "Main 12");
+        else
+            strcpy(profbuf, "Unknown");
+
+        if (vps.ptl.intraConstraintFlag && !bStillPicture)
+            strcat(profbuf, " Intra");
     }
     x265_log(&param, X265_LOG_INFO, "%s profile, Level-%s (%s tier)\n",
-             profile, levels[i].name, tiers[vps.ptl.tierFlag]);
+             profbuf, levels[i].name, tiers[vps.ptl.tierFlag]);
 }
 
 /* enforce a maximum decoder level requirement, in other words assure that a
@@ -362,73 +402,68 @@
     if (!param || !profile)
         return 0;
 
-#if HIGH_BIT_DEPTH
-    if (!strcmp(profile, "main") || !strcmp(profile, "mainstillpicture") || !strcmp(profile, "msp") || !strcmp(profile, "main444-8"))
+    /* Check if profile bit-depth requirement is exceeded by internal bit depth */
+    bool bInvalidDepth = false;
+#if X265_DEPTH > 8
+    if (!strcmp(profile, "main") || !strcmp(profile, "mainstillpicture") || !strcmp(profile, "msp") ||
+        !strcmp(profile, "main444-8") || !strcmp(profile, "main-intra") ||
+        !strcmp(profile, "main444-intra") || !strcmp(profile, "main444-stillpicture"))
+        bInvalidDepth = true;
+#endif
+#if X265_DEPTH > 10
+    if (!strcmp(profile, "main10") || !strcmp(profile, "main422-10") || !strcmp(profile, "main444-10") ||
+        !strcmp(profile, "main10-intra") || !strcmp(profile, "main422-10-intra") || !strcmp(profile, "main444-10-intra"))
+        bInvalidDepth = true;
+#endif
+#if X265_DEPTH > 12
+    if (!strcmp(profile, "main12") || !strcmp(profile, "main422-12") || !strcmp(profile, "main444-12") ||
+        !strcmp(profile, "main12-intra") || !strcmp(profile, "main422-12-intra") || !strcmp(profile, "main444-12-intra"))
+        bInvalidDepth = true;
+#endif
+
+    if (bInvalidDepth)
     {
-        x265_log(param, X265_LOG_ERROR, "%s profile not supported, compiled for Main10.\n", profile);
+        x265_log(param, X265_LOG_ERROR, "%s profile not supported, internal bit depth %d.\n", profile, X265_DEPTH);
         return -1;
     }
-#else
-    if (!strcmp(profile, "main10") || !strcmp(profile, "main422-10") || !strcmp(profile, "main444-10"))
+
+    size_t l = strlen(profile);
+    bool bBoolIntra = (l > 6 && !strcmp(profile + l - 6, "-intra")) ||
+                      !strcmp(profile, "mainstillpicture") || !strcmp(profile, "msp");
+    if (bBoolIntra)
     {
-        x265_log(param, X265_LOG_ERROR, "%s profile not supported, compiled for Main.\n", profile);
-        return -1;
+        /* The profile may be detected as still picture if param->totalFrames is 1 */
+        param->keyframeMax = 1;
     }
-#endif
     
-    if (!strcmp(profile, "main"))
+    /* check that input color space is supported by 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"))
     {
-        if (!(param->internalCsp & X265_CSP_I420))
+        if (param->internalCsp != X265_CSP_I420)
         {
             x265_log(param, X265_LOG_ERROR, "%s profile not compatible with %s input color space.\n",
                      profile, x265_source_csp_names[param->internalCsp]);
             return -1;
         }
     }
-    else if (!strcmp(profile, "mainstillpicture") || !strcmp(profile, "msp"))
+    else if (!strcmp(profile, "main422-10") || !strcmp(profile, "main422-10-intra") ||
+             !strcmp(profile, "main422-12") || !strcmp(profile, "main422-12-intra"))
     {
-        if (!(param->internalCsp & X265_CSP_I420))
-        {
-            x265_log(param, X265_LOG_ERROR, "%s profile not compatible with %s input color space.\n",
-                     profile, x265_source_csp_names[param->internalCsp]);
-            return -1;
-        }
-
-        /* SPSs shall have sps_max_dec_pic_buffering_minus1[ sps_max_sub_layers_minus1 ] equal to 0 only */
-        param->maxNumReferences = 1;
-
-        /* The bitstream shall contain only one picture (we do not enforce this) */
-        /* just in case the user gives us more than one picture: */
-        param->keyframeMax = 1;
-        param->bOpenGOP = 0;
-        param->bRepeatHeaders = 1;
-        param->lookaheadDepth = 0;
-        param->bframes = 0;
-        param->scenecutThreshold = 0;
-        param->bFrameAdaptive = 0;
-        param->rc.cuTree = 0;
-        param->bEnableWeightedPred = 0;
-        param->bEnableWeightedBiPred = 0;
-    }
-    else if (!strcmp(profile, "main10"))
-    {
-        if (!(param->internalCsp & X265_CSP_I420))
+        if (param->internalCsp != X265_CSP_I420 && param->internalCsp != X265_CSP_I422)
         {
             x265_log(param, X265_LOG_ERROR, "%s profile not compatible with %s input color space.\n",
                      profile, x265_source_csp_names[param->internalCsp]);
             return -1;
         }
     }
-    else if (!strcmp(profile, "main422-10"))
-    {
-        if (!(param->internalCsp & (X265_CSP_I420 | X265_CSP_I422)))
-        {
-            x265_log(param, X265_LOG_ERROR, "%s profile not compatible with %s input color space.\n",
-                     profile, x265_source_csp_names[param->internalCsp]);
-            return -1;
-        }
-    }
-    else if (!strcmp(profile, "main444-8") || !strcmp(profile, "main444-10"))
+    else if (!strcmp(profile, "main444-8") ||
+             !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"))
     {
         /* any color space allowed */
     }
diff -r a632a7b1b90e -r c2fcd2315b66 source/x265.h
--- a/source/x265.h	Mon Jun 29 16:17:01 2015 -0700
+++ b/source/x265.h	Thu Jul 02 14:42:51 2015 -0500
@@ -1182,11 +1182,31 @@
 #define X265_PARAM_BAD_VALUE (-2)
 int x265_param_parse(x265_param *p, const char *name, const char *value);
 
+static const char * const x265_profile_names[] = {
+    /* HEVC v1 */
+    "main", "main10", "mainstillpicture", /* alias */ "msp",
+
+    /* HEVC v2 (Range Extensions) */
+    "main-intra", "main10-intra",
+    "main444-8",  "main444-intra", "main444-stillpicture",
+
+    "main422-10", "main422-10-intra",
+    "main444-10", "main444-10-intra",
+
+    "main12",     "main12-intra",                  /* Highly Experimental */
+    "main422-12", "main422-12-intra",
+    "main444-12", "main444-12-intra",
+
+    "main444-16-intra", "main444-16-stillpicture", /* Not Supported! */
+    0
+};
+
 /* x265_param_apply_profile:
- *      Applies the restrictions of the given profile. (one of below) */
-static const char * const x265_profile_names[] = { "main", "main10", "mainstillpicture", 0 };
-
-/*      (can be NULL, in which case the function will do nothing)
+ *      Applies the restrictions of the given profile. (one of x265_profile_names)
+ *      (can be NULL, in which case the function will do nothing)
+ *      Note: the detected profile can be lower than the one specified to this
+ *      function. This function will force the encoder parameters to fit within
+ *      the specified profile, or fail if that is impossible.
  *      returns 0 on success, negative on failure (e.g. invalid profile name). */
 int x265_param_apply_profile(x265_param *, const char *profile);
 


More information about the x265-devel mailing list