[x265] [PATCH] Add config file for BBAQ

Niranjan Bala niranjan at multicorewareinc.com
Sun Dec 11 16:11:37 UTC 2022


>From a407ed7bdf3b1975ba28f910425c7123e6e99d80 Mon Sep 17 00:00:00 2001
From: Niranjan Kumar <niranjan at multicorewareinc.com>
Date: Mon, 31 Oct 2022 11:48:32 +0530
Subject: [PATCH] Add config file for BBAQ

---
 source/abrEncApp.h             |   1 +
 source/common/param.cpp        | 185 ++++++++++++++++++++-------------
 source/common/param.h          |   1 +
 source/encoder/api.cpp         |   1 +
 source/encoder/ratecontrol.cpp |  26 ++++-
 source/encoder/ratecontrol.h   |   7 +-
 source/x265.cpp                |  10 ++
 source/x265.h                  |   3 +
 source/x265cli.cpp             | 129 +++++++++++++++++++++++
 source/x265cli.h               |   5 +
 10 files changed, 288 insertions(+), 80 deletions(-)

diff --git a/source/abrEncApp.h b/source/abrEncApp.h
index 73b4052b3..f7ff6d96d 100644
--- a/source/abrEncApp.h
+++ b/source/abrEncApp.h
@@ -91,6 +91,7 @@ namespace X265_NS {
         FILE*    m_qpfile;
         FILE*    m_zoneFile;
         FILE*    m_dolbyVisionRpu;/* File containing Dolby Vision BL RPU
metadata */
+        FILE*    m_scenecutAwareQpConfig;

         int m_ret;

diff --git a/source/common/param.cpp b/source/common/param.cpp
index 5de4361af..ccadcd2cc 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -678,6 +678,109 @@ static int parseName(const char* arg, const char*
const* names, bool& bError)
 #define atof(str) x265_atof(str, bError)
 #define atobool(str) (x265_atobool(str, bError))

+int x265_scenecut_aware_qp_param_parse(x265_param* p, const char* name,
const char* value)
+{
+    bool bError = false;
+    char nameBuf[64];
+    if (!name)
+        return X265_PARAM_BAD_NAME;
+    // skip -- prefix if provided
+    if (name[0] == '-' && name[1] == '-')
+        name += 2;
+    // s/_/-/g
+    if (strlen(name) + 1 < sizeof(nameBuf) && strchr(name, '_'))
+    {
+        char *c;
+        strcpy(nameBuf, name);
+        while ((c = strchr(nameBuf, '_')) != 0)
+            *c = '-';
+        name = nameBuf;
+    }
+    if (!value)
+        value = "true";
+    else if (value[0] == '=')
+        value++;
+#define OPT(STR) else if (!strcmp(name, STR))
+    if (0);
+    OPT("scenecut-aware-qp") p->bEnableSceneCutAwareQp = x265_atoi(value,
bError);
+    OPT("masking-strength")
+    {
+        int window1;
+        double refQpDelta1, nonRefQpDelta1;
+        if (p->bEnableSceneCutAwareQp == FORWARD)
+        {
+            if (3 == sscanf(value, "%d,%lf,%lf", &window1, &refQpDelta1,
&nonRefQpDelta1))
+            {
+                if (window1 > 0)
+                    p->fwdScenecutWindow = window1;
+                if (refQpDelta1 > 0)
+                    p->fwdRefQpDelta = refQpDelta1;
+                if (nonRefQpDelta1 > 0)
+                    p->fwdNonRefQpDelta = nonRefQpDelta1;
+            }
+            else
+            {
+                x265_log(NULL, X265_LOG_ERROR, "Specify all the necessary
offsets for masking-strength \n");
+                bError = true;
+            }
+        }
+        else if (p->bEnableSceneCutAwareQp == BACKWARD)
+        {
+            if (3 == sscanf(value, "%d,%lf,%lf", &window1, &refQpDelta1,
&nonRefQpDelta1))
+            {
+                if (window1 > 0)
+                    p->bwdScenecutWindow = window1;
+                if (refQpDelta1 > 0)
+                    p->bwdRefQpDelta = refQpDelta1;
+                if (nonRefQpDelta1 > 0)
+                    p->bwdNonRefQpDelta = nonRefQpDelta1;
+            }
+            else
+            {
+                x265_log(NULL, X265_LOG_ERROR, "Specify all the necessary
offsets for masking-strength \n");
+                bError = true;
+            }
+        }
+        else if (p->bEnableSceneCutAwareQp == BI_DIRECTIONAL)
+        {
+            int window2;
+            double refQpDelta2, nonRefQpDelta2;
+            if (6 == sscanf(value, "%d,%lf,%lf,%d,%lf,%lf", &window1,
&refQpDelta1, &nonRefQpDelta1, &window2, &refQpDelta2, &nonRefQpDelta2))
+            {
+                if (window1 > 0)
+                    p->fwdScenecutWindow = window1;
+                if (refQpDelta1 > 0)
+                    p->fwdRefQpDelta = refQpDelta1;
+                if (nonRefQpDelta1 > 0)
+                    p->fwdNonRefQpDelta = nonRefQpDelta1;
+                if (window2 > 0)
+                    p->bwdScenecutWindow = window2;
+                if (refQpDelta2 > 0)
+                    p->bwdRefQpDelta = refQpDelta2;
+                if (nonRefQpDelta2 > 0)
+                    p->bwdNonRefQpDelta = nonRefQpDelta2;
+            }
+            else
+            {
+                x265_log(NULL, X265_LOG_ERROR, "Specify all the necessary
offsets for masking-strength \n");
+                bError = true;
+            }
+        }
+    }
+    else
+        return X265_PARAM_BAD_NAME;
+#undef OPT
+    return bError ? X265_PARAM_BAD_VALUE : 0;
+}
+
+
+/* internal versions of string-to-int with additional error checking */
+#undef atoi
+#undef atof
+#define atoi(str) x265_atoi(str, bError)
+#define atof(str) x265_atof(str, bError)
+#define atobool(str) (x265_atobool(str, bError))
+
 int x265_zone_param_parse(x265_param* p, const char* name, const char*
value)
 {
     bool bError = false;
@@ -1346,72 +1449,6 @@ int x265_param_parse(x265_param* p, const char*
name, const char* value)
             p->selectiveSAO = atoi(value);
         }
         OPT("fades") p->bEnableFades = atobool(value);
-        OPT("scenecut-aware-qp") p->bEnableSceneCutAwareQp = atoi(value);
-        OPT("masking-strength")
-        {
-            int window1;
-            double refQpDelta1, nonRefQpDelta1;
-
-            if (p->bEnableSceneCutAwareQp == FORWARD)
-            {
-                if (3 == sscanf(value, "%d,%lf,%lf", &window1,
&refQpDelta1, &nonRefQpDelta1))
-                {
-                    if (window1 > 0)
-                        p->fwdScenecutWindow = window1;
-                    if (refQpDelta1 > 0)
-                        p->fwdRefQpDelta = refQpDelta1;
-                    if (nonRefQpDelta1 > 0)
-                        p->fwdNonRefQpDelta = nonRefQpDelta1;
-                }
-                else
-                {
-                    x265_log(NULL, X265_LOG_ERROR, "Specify all the
necessary offsets for masking-strength \n");
-                    bError = true;
-                }
-            }
-            else if (p->bEnableSceneCutAwareQp == BACKWARD)
-            {
-                if (3 == sscanf(value, "%d,%lf,%lf", &window1,
&refQpDelta1, &nonRefQpDelta1))
-                {
-                    if (window1 > 0)
-                        p->bwdScenecutWindow = window1;
-                    if (refQpDelta1 > 0)
-                        p->bwdRefQpDelta = refQpDelta1;
-                    if (nonRefQpDelta1 > 0)
-                        p->bwdNonRefQpDelta = nonRefQpDelta1;
-                }
-                else
-                {
-                    x265_log(NULL, X265_LOG_ERROR, "Specify all the
necessary offsets for masking-strength \n");
-                    bError = true;
-                }
-            }
-            else if (p->bEnableSceneCutAwareQp == BI_DIRECTIONAL)
-            {
-                int window2;
-                double refQpDelta2, nonRefQpDelta2;
-                if (6 == sscanf(value, "%d,%lf,%lf,%d,%lf,%lf", &window1,
&refQpDelta1, &nonRefQpDelta1, &window2, &refQpDelta2, &nonRefQpDelta2))
-                {
-                    if (window1 > 0)
-                        p->fwdScenecutWindow = window1;
-                    if (refQpDelta1 > 0)
-                        p->fwdRefQpDelta = refQpDelta1;
-                    if (nonRefQpDelta1 > 0)
-                        p->fwdNonRefQpDelta = nonRefQpDelta1;
-                    if (window2 > 0)
-                        p->bwdScenecutWindow = window2;
-                    if (refQpDelta2 > 0)
-                        p->bwdRefQpDelta = refQpDelta2;
-                    if (nonRefQpDelta2 > 0)
-                        p->bwdNonRefQpDelta = nonRefQpDelta2;
-                }
-                else
-                {
-                    x265_log(NULL, X265_LOG_ERROR, "Specify all the
necessary offsets for masking-strength \n");
-                    bError = true;
-                }
-            }
-        }
         OPT("field") p->bField = atobool( value );
         OPT("cll") p->bEmitCLL = atobool(value);
         OPT("frame-dup") p->bEnableFrameDuplication = atobool(value);
@@ -1859,17 +1896,17 @@ int x265_check_params(x265_param* param)
             "Invalid masking direction. Value must be between 0 and
3(inclusive)");
             CHECK(param->fwdScenecutWindow < 0 || param->fwdScenecutWindow
> 1000,
             "Invalid forward scenecut Window duration. Value must be
between 0 and 1000(inclusive)");
-            CHECK(param->fwdRefQpDelta < 0 || param->fwdRefQpDelta > 10,
-            "Invalid fwdRefQpDelta value. Value must be between 0 and 10
(inclusive)");
-            CHECK(param->fwdNonRefQpDelta < 0 || param->fwdNonRefQpDelta >
10,
-            "Invalid fwdNonRefQpDelta value. Value must be between 0 and
10 (inclusive)");
+            CHECK(param->fwdRefQpDelta < 0 || param->fwdRefQpDelta > 20,
+            "Invalid fwdRefQpDelta value. Value must be between 0 and 20
(inclusive)");
+            CHECK(param->fwdNonRefQpDelta < 0 || param->fwdNonRefQpDelta >
20,
+            "Invalid fwdNonRefQpDelta value. Value must be between 0 and
20 (inclusive)");

             CHECK(param->bwdScenecutWindow < 0 || param->bwdScenecutWindow
> 1000,
                 "Invalid backward scenecut Window duration. Value must be
between 0 and 1000(inclusive)");
-            CHECK(param->bwdRefQpDelta < -1 || param->bwdRefQpDelta > 10,
-                "Invalid bwdRefQpDelta value. Value must be between 0 and
10 (inclusive)");
-            CHECK(param->bwdNonRefQpDelta < -1 || param->bwdNonRefQpDelta
> 10,
-                "Invalid bwdNonRefQpDelta value. Value must be between 0
and 10 (inclusive)");
+            CHECK(param->bwdRefQpDelta < -1 || param->bwdRefQpDelta > 20,
+                "Invalid bwdRefQpDelta value. Value must be between 0 and
20 (inclusive)");
+            CHECK(param->bwdNonRefQpDelta < -1 || param->bwdNonRefQpDelta
> 20,
+                "Invalid bwdNonRefQpDelta value. Value must be between 0
and 20 (inclusive)");
         }
     }
     if (param->bEnableHME)
diff --git a/source/common/param.h b/source/common/param.h
index 8ccd1f4a6..7808947f6 100644
--- a/source/common/param.h
+++ b/source/common/param.h
@@ -52,6 +52,7 @@ void x265_param_default(x265_param *param);
 int x265_param_default_preset(x265_param *, const char *preset, const char
*tune);
 int x265_param_apply_profile(x265_param *, const char *profile);
 int x265_param_parse(x265_param *p, const char *name, const char *value);
+int x265_scenecut_aware_qp_param_parse(x265_param* p, const char* name,
const char* value);
 int x265_zone_param_parse(x265_param* p, const char* name, const char*
value);
 #define PARAM_NS X265_NS
 #endif
diff --git a/source/encoder/api.cpp b/source/encoder/api.cpp
index 66f26e37e..482ab9b8e 100644
--- a/source/encoder/api.cpp
+++ b/source/encoder/api.cpp
@@ -1050,6 +1050,7 @@ static const x265_api libapi =
     &PARAM_NS::x265_param_free,
     &PARAM_NS::x265_param_default,
     &PARAM_NS::x265_param_parse,
+    &PARAM_NS::x265_scenecut_aware_qp_param_parse,
     &PARAM_NS::x265_param_apply_profile,
     &PARAM_NS::x265_param_default_preset,
     &x265_picture_alloc,
diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp
index d0bd9762e..7e0dfe054 100644
--- a/source/encoder/ratecontrol.cpp
+++ b/source/encoder/ratecontrol.cpp
@@ -3335,7 +3335,7 @@ double RateControl::forwardMasking(Frame* curFrame,
double q)
 {
     double qp = x265_qScale2qp(q);
     uint32_t maxWindowSize = uint32_t((m_param->fwdScenecutWindow /
1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5);
-    uint32_t windowSize = maxWindowSize / 3;
+    uint32_t windowSize = maxWindowSize / 6;
     int lastScenecut = m_top->m_rateControl->m_lastScenecut;
     int lastIFrame = m_top->m_rateControl->m_lastScenecutAwareIFrame;
     double fwdRefQpDelta = double(m_param->fwdRefQpDelta);
@@ -3361,8 +3361,14 @@ double RateControl::forwardMasking(Frame* curFrame,
double q)
                     qp += WINDOW1_DELTA * (fwdRefQpDelta - sliceTypeDelta);
                 else if (((curFrame->m_poc) > (lastScenecut +
int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 2 *
int(windowSize))))
                     qp += WINDOW2_DELTA * (fwdRefQpDelta - sliceTypeDelta);
-                else if (curFrame->m_poc > lastScenecut + 2 *
int(windowSize))
+                else if (((curFrame->m_poc) > (lastScenecut + 2 *
int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 3 *
int(windowSize))))
                     qp += WINDOW3_DELTA * (fwdRefQpDelta - sliceTypeDelta);
+                else if (((curFrame->m_poc) > (lastScenecut + 3 *
int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 4 *
int(windowSize))))
+                    qp += WINDOW4_DELTA * (fwdRefQpDelta - sliceTypeDelta);
+                else if (((curFrame->m_poc) > (lastScenecut + 4 *
int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 5 *
int(windowSize))))
+                    qp += WINDOW5_DELTA * (fwdRefQpDelta - sliceTypeDelta);
+                else if (curFrame->m_poc > lastScenecut + 5 *
int(windowSize))
+                    qp += WINDOW6_DELTA * (fwdRefQpDelta - sliceTypeDelta);
             }
         }
         else if (curFrame->m_lowres.sliceType == X265_TYPE_BREF)
@@ -3375,8 +3381,14 @@ double RateControl::forwardMasking(Frame* curFrame,
double q)
                     qp += WINDOW1_DELTA * fwdRefQpDelta;
                 else if (((curFrame->m_poc) > (lastScenecut +
int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 2 *
int(windowSize))))
                     qp += WINDOW2_DELTA * fwdRefQpDelta;
-                else if (curFrame->m_poc > lastScenecut + 2 *
int(windowSize))
+                else if (((curFrame->m_poc) > (lastScenecut + 2 *
int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 3 *
int(windowSize))))
                     qp += WINDOW3_DELTA * fwdRefQpDelta;
+                else if (((curFrame->m_poc) > (lastScenecut + 3 *
int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 4 *
int(windowSize))))
+                    qp += WINDOW4_DELTA * fwdRefQpDelta;
+                else if (((curFrame->m_poc) > (lastScenecut + 4 *
int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 5 *
int(windowSize))))
+                    qp += WINDOW5_DELTA * fwdRefQpDelta;
+                else if (curFrame->m_poc > lastScenecut + 5 *
int(windowSize))
+                    qp += WINDOW6_DELTA * fwdRefQpDelta;
             }
         }
         else if (curFrame->m_lowres.sliceType == X265_TYPE_B)
@@ -3389,8 +3401,14 @@ double RateControl::forwardMasking(Frame* curFrame,
double q)
                     qp += WINDOW1_DELTA * fwdNonRefQpDelta;
                 else if (((curFrame->m_poc) > (lastScenecut +
int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 2 *
int(windowSize))))
                     qp += WINDOW2_DELTA * fwdNonRefQpDelta;
-                else if (curFrame->m_poc > lastScenecut + 2 *
int(windowSize))
+                else if (((curFrame->m_poc) > (lastScenecut + 2 *
int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 3 *
int(windowSize))))
                     qp += WINDOW3_DELTA * fwdNonRefQpDelta;
+                else if (((curFrame->m_poc) > (lastScenecut + 3 *
int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 4 *
int(windowSize))))
+                    qp += WINDOW4_DELTA * fwdNonRefQpDelta;
+                else if (((curFrame->m_poc) > (lastScenecut + 4 *
int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 5 *
int(windowSize))))
+                    qp += WINDOW5_DELTA * fwdNonRefQpDelta;
+                else if (curFrame->m_poc > lastScenecut + 5 *
int(windowSize))
+                    qp += WINDOW6_DELTA * fwdNonRefQpDelta;
             }
         }
     }
diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h
index 10dfc268d..d1734f8ff 100644
--- a/source/encoder/ratecontrol.h
+++ b/source/encoder/ratecontrol.h
@@ -49,8 +49,11 @@ struct SPS;

 /*Scenecut Aware QP*/
 #define WINDOW1_DELTA           1.0 /* The offset for the frames coming in
the window-1*/
-#define WINDOW2_DELTA           0.7 /* The offset for the frames coming in
the window-2*/
-#define WINDOW3_DELTA           0.4 /* The offset for the frames coming in
the window-3*/
+#define WINDOW2_DELTA           0.85 /* The offset for the frames coming
in the window-2*/
+#define WINDOW3_DELTA           0.7 /* The offset for the frames coming in
the window-3*/
+#define WINDOW4_DELTA           0.55 /* The offset for the frames coming
in the window-4*/
+#define WINDOW5_DELTA           0.4 /* The offset for the frames coming in
the window-5*/
+#define WINDOW6_DELTA           0.25 /* The offset for the frames coming
in the window-6*/

 struct Predictor
 {
diff --git a/source/x265.cpp b/source/x265.cpp
index ae3803b49..31a627d87 100644
--- a/source/x265.cpp
+++ b/source/x265.cpp
@@ -296,6 +296,16 @@ int main(int argc, char **argv)

     int ret = 0;

+    if (cliopt[0].scenecutAwareQpConfig)
+    {
+        if (!cliopt[0].parseScenecutAwareQpConfig())
+        {
+            x265_log(NULL, X265_LOG_ERROR, "Unable to parse scenecut aware
qp config file \n");
+            fclose(cliopt[0].scenecutAwareQpConfig);
+            cliopt[0].scenecutAwareQpConfig = NULL;
+        }
+    }
+
     AbrEncoder* abrEnc = new AbrEncoder(cliopt, numEncodes, ret);
     int threadsActive = abrEnc->m_numActiveEncodes.get();
     while (threadsActive)
diff --git a/source/x265.h b/source/x265.h
index 4f1c52d56..25efb17f1 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -2024,6 +2024,8 @@ void x265_zone_free(x265_param *param);

 int x265_zone_param_parse(x265_param* p, const char* name, const char*
value);

+int x265_scenecut_aware_qp_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",
@@ -2293,6 +2295,7 @@ typedef struct x265_api
     void          (*param_free)(x265_param*);
     void          (*param_default)(x265_param*);
     int           (*param_parse)(x265_param*, const char*, const char*);
+    int           (*scenecut_aware_qp_param_parse)(x265_param*, const
char*, const char*);
     int           (*param_apply_profile)(x265_param*, const char*);
     int           (*param_default_preset)(x265_param*, const char*, const
char *);
     x265_picture* (*picture_alloc)(void);
diff --git a/source/x265cli.cpp b/source/x265cli.cpp
index 54479ef2f..53e04fa6b 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -181,6 +181,7 @@ namespace X265_NS {
         H1("                                 2 - Backward masking\n");
         H1("                                 3 - Bidirectional masking\n");
         H1("   --masking-strength <string>   Comma separated values which
specify the duration and offset for the QP increment for inter-frames when
scenecut-aware-qp is enabled.\n");
+        H1("   --scenecut-qp-config <file>   File containing
scenecut-aware-qp mode, window duration and offsets settings required for
the masking. Works only with --pass 2\n");
         H0("   --radl <integer>              Number of RADL pictures
allowed in front of IDR. Default %d\n", param->radl);
         H0("   --intra-refresh               Use Periodic Intra Refresh
instead of IDR frames\n");
         H0("   --rc-lookahead <integer>      Number of frames for
frame-type lookahead (determines encoder latency) Default %d\n",
param->lookaheadDepth);
@@ -738,6 +739,12 @@ namespace X265_NS {
                         return true;
                     }
                 }
+                OPT("scenecut-qp-config")
+                {
+                    this->scenecutAwareQpConfig = x265_fopen(optarg, "rb");
+                    if (!this->scenecutAwareQpConfig)
+                        x265_log_file(param, X265_LOG_ERROR, "%s scenecut
aware qp config file not found or error in opening config file\n", optarg);
+                }
                 OPT("zonefile")
                 {
                     this->zoneFile = x265_fopen(optarg, "rb");
@@ -1092,6 +1099,128 @@ namespace X265_NS {
         return 0;
     }

+    bool CLIOptions::parseScenecutAwareQpConfig()
+    {
+        char line[256];
+        char* argLine;
+        rewind(scenecutAwareQpConfig);
+        while (fgets(line, sizeof(line), scenecutAwareQpConfig))
+        {
+            if (*line == '#' || (strcmp(line, "\r\n") == 0))
+                continue;
+            int index = (int)strcspn(line, "\r\n");
+            line[index] = '\0';
+            argLine = line;
+            while (isspace((unsigned char)*argLine)) argLine++;
+            char* start = strchr(argLine, '-');
+            int argCount = 0;
+            char **args = (char**)malloc(256 * sizeof(char *));
+            //Adding a dummy string to avoid file parsing error
+            args[argCount++] = (char *)"x265";
+            char* token = strtok(start, " ");
+            while (token)
+            {
+                args[argCount++] = token;
+                token = strtok(NULL, " ");
+            }
+            args[argCount] = NULL;
+            CLIOptions cliopt;
+            if (cliopt.parseScenecutAwareQpParam(argCount, args, param))
+            {
+                cliopt.destroy();
+                if (cliopt.api)
+                    cliopt.api->param_free(cliopt.param);
+                exit(1);
+            }
+            break;
+        }
+        return 1;
+    }
+    bool CLIOptions::parseScenecutAwareQpParam(int argc, char **argv,
x265_param* globalParam)
+    {
+        bool bError = false;
+        int bShowHelp = false;
+        int outputBitDepth = 0;
+        const char *profile = NULL;
+        /* Presets are applied before all other options. */
+        for (optind = 0;;)
+        {
+            int c = getopt_long(argc, argv, short_options, long_options,
NULL);
+            if (c == -1)
+                break;
+            else if (c == 'D')
+                outputBitDepth = atoi(optarg);
+            else if (c == 'P')
+                profile = optarg;
+            else if (c == '?')
+                bShowHelp = true;
+        }
+        if (!outputBitDepth && profile)
+        {
+            /*try to derive the output bit depth from the requested
profile*/
+            if (strstr(profile, "10"))
+                outputBitDepth = 10;
+            else if (strstr(profile, "12"))
+                outputBitDepth = 12;
+            else
+                outputBitDepth = 8;
+        }
+        api = x265_api_get(outputBitDepth);
+        if (!api)
+        {
+            x265_log(NULL, X265_LOG_WARNING, "falling back to default
bit-depth\n");
+            api = x265_api_get(0);
+        }
+        if (bShowHelp)
+        {
+            printVersion(globalParam, api);
+            showHelp(globalParam);
+        }
+        for (optind = 0;;)
+        {
+            int long_options_index = -1;
+            int c = getopt_long(argc, argv, short_options, long_options,
&long_options_index);
+            if (c == -1)
+                break;
+            if (long_options_index < 0 && c > 0)
+            {
+                for (size_t i = 0; i < sizeof(long_options) /
sizeof(long_options[0]); i++)
+                {
+                    if (long_options[i].val == c)
+                    {
+                        long_options_index = (int)i;
+                        break;
+                    }
+                }
+                if (long_options_index < 0)
+                {
+                    /* getopt_long might have already printed an error
message */
+                    if (c != 63)
+                        x265_log(NULL, X265_LOG_WARNING, "internal error:
short option '%c' has no long option\n", c);
+                    return true;
+                }
+            }
+            if (long_options_index < 0)
+            {
+                x265_log(NULL, X265_LOG_WARNING, "short option '%c'
unrecognized\n", c);
+                return true;
+            }
+            bError |= !!api->scenecut_aware_qp_param_parse(globalParam,
long_options[long_options_index].name, optarg);
+            if (bError)
+            {
+                const char *name = long_options_index > 0 ?
long_options[long_options_index].name : argv[optind - 2];
+                x265_log(NULL, X265_LOG_ERROR, "invalid argument: %s =
%s\n", name, optarg);
+                return true;
+            }
+        }
+        if (optind < argc)
+        {
+            x265_log(param, X265_LOG_WARNING, "extra unused command
arguments given <%s>\n", argv[optind]);
+            return true;
+        }
+        return false;
+    }
+
 #ifdef __cplusplus
 }
 #endif
\ No newline at end of file
diff --git a/source/x265cli.h b/source/x265cli.h
index eea47f168..f4e748787 100644
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -381,6 +381,7 @@ static const struct option long_options[] =
     { "abr-ladder", required_argument, NULL, 0 },
     { "min-vbv-fullness", required_argument, NULL, 0 },
     { "max-vbv-fullness", required_argument, NULL, 0 },
+    { "scenecut-qp-config", required_argument, NULL, 0 },
     { "film-grain", required_argument, NULL, 0 },
     { 0, 0, 0, 0 },
     { 0, 0, 0, 0 },
@@ -397,6 +398,7 @@ static const struct option long_options[] =
         FILE*       qpfile;
         FILE*       zoneFile;
         FILE*    dolbyVisionRpu;    /* File containing Dolby Vision BL RPU
metadata */
+        FILE*    scenecutAwareQpConfig; /* File containing scenecut aware
frame quantization related CLI options */
         const char* reconPlayCmd;
         const x265_api* api;
         x265_param* param;
@@ -434,6 +436,7 @@ static const struct option long_options[] =
             qpfile = NULL;
             zoneFile = NULL;
             dolbyVisionRpu = NULL;
+            scenecutAwareQpConfig = NULL;
             reconPlayCmd = NULL;
             api = NULL;
             param = NULL;
@@ -464,6 +467,8 @@ static const struct option long_options[] =
         bool parseQPFile(x265_picture &pic_org);
         bool parseZoneFile();
         int rpuParser(x265_picture * pic);
+        bool parseScenecutAwareQpConfig();
+        bool parseScenecutAwareQpParam(int argc, char **argv, x265_param*
globalParam);
     };
 #ifdef __cplusplus
 }
-- 
2.18.0.windows.1


-- 

Thanks & Regards
*Niranjan Kumar B*
Video Codec Engineer
Media & AI Analytics
+91 958 511 1449
<https://multicorewareinc.com/>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20221211/8b90c879/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: AddBBAQconfigFile.diff
Type: application/octet-stream
Size: 26709 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20221211/8b90c879/attachment-0001.obj>


More information about the x265-devel mailing list