<div dir="ltr">From a407ed7bdf3b1975ba28f910425c7123e6e99d80 Mon Sep 17 00:00:00 2001<br>From: Niranjan Kumar <<a href="mailto:niranjan@multicorewareinc.com" target="_blank">niranjan@multicorewareinc.com</a>><br>Date: Mon, 31 Oct 2022 11:48:32 +0530<br>Subject: [PATCH] Add config file for BBAQ<br><br>---<br> source/abrEncApp.h             |   1 +<br> source/common/param.cpp        | 185 ++++++++++++++++++++-------------<br> source/common/param.h          |   1 +<br> source/encoder/api.cpp         |   1 +<br> source/encoder/ratecontrol.cpp |  26 ++++-<br> source/encoder/ratecontrol.h   |   7 +-<br> source/x265.cpp                |  10 ++<br> source/x265.h                  |   3 +<br> source/x265cli.cpp             | 129 +++++++++++++++++++++++<br> source/x265cli.h               |   5 +<br> 10 files changed, 288 insertions(+), 80 deletions(-)<br><br>diff --git a/source/abrEncApp.h b/source/abrEncApp.h<br>index 73b4052b3..f7ff6d96d 100644<br>--- a/source/abrEncApp.h<br>+++ b/source/abrEncApp.h<br>@@ -91,6 +91,7 @@ namespace X265_NS {<br>         FILE*    m_qpfile;<br>         FILE*    m_zoneFile;<br>         FILE*    m_dolbyVisionRpu;/* File containing Dolby Vision BL RPU metadata */<br>+        FILE*    m_scenecutAwareQpConfig;<br> <br>         int m_ret;<br> <br>diff --git a/source/common/param.cpp b/source/common/param.cpp<br>index 5de4361af..ccadcd2cc 100755<br>--- a/source/common/param.cpp<br>+++ b/source/common/param.cpp<br>@@ -678,6 +678,109 @@ static int parseName(const char* arg, const char* const* names, bool& bError)<br> #define atof(str) x265_atof(str, bError)<br> #define atobool(str) (x265_atobool(str, bError))<br> <br>+int x265_scenecut_aware_qp_param_parse(x265_param* p, const char* name, const char* value)<br>+{<br>+    bool bError = false;<br>+    char nameBuf[64];<br>+    if (!name)<br>+        return X265_PARAM_BAD_NAME;<br>+    // skip -- prefix if provided<br>+    if (name[0] == '-' && name[1] == '-')<br>+        name += 2;<br>+    // s/_/-/g<br>+    if (strlen(name) + 1 < sizeof(nameBuf) && strchr(name, '_'))<br>+    {<br>+        char *c;<br>+        strcpy(nameBuf, name);<br>+        while ((c = strchr(nameBuf, '_')) != 0)<br>+            *c = '-';<br>+        name = nameBuf;<br>+    }<br>+    if (!value)<br>+        value = "true";<br>+    else if (value[0] == '=')<br>+        value++;<br>+#define OPT(STR) else if (!strcmp(name, STR))<br>+    if (0);<br>+    OPT("scenecut-aware-qp") p->bEnableSceneCutAwareQp = x265_atoi(value, bError);<br>+    OPT("masking-strength")<br>+    {<br>+        int window1;<br>+        double refQpDelta1, nonRefQpDelta1;<br>+        if (p->bEnableSceneCutAwareQp == FORWARD)<br>+        {<br>+            if (3 == sscanf(value, "%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1))<br>+            {<br>+                if (window1 > 0)<br>+                    p->fwdScenecutWindow = window1;<br>+                if (refQpDelta1 > 0)<br>+                    p->fwdRefQpDelta = refQpDelta1;<br>+                if (nonRefQpDelta1 > 0)<br>+                    p->fwdNonRefQpDelta = nonRefQpDelta1;<br>+            }<br>+            else<br>+            {<br>+                x265_log(NULL, X265_LOG_ERROR, "Specify all the necessary offsets for masking-strength \n");<br>+                bError = true;<br>+            }<br>+        }<br>+        else if (p->bEnableSceneCutAwareQp == BACKWARD)<br>+        {<br>+            if (3 == sscanf(value, "%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1))<br>+            {<br>+                if (window1 > 0)<br>+                    p->bwdScenecutWindow = window1;<br>+                if (refQpDelta1 > 0)<br>+                    p->bwdRefQpDelta = refQpDelta1;<br>+                if (nonRefQpDelta1 > 0)<br>+                    p->bwdNonRefQpDelta = nonRefQpDelta1;<br>+            }<br>+            else<br>+            {<br>+                x265_log(NULL, X265_LOG_ERROR, "Specify all the necessary offsets for masking-strength \n");<br>+                bError = true;<br>+            }<br>+        }<br>+        else if (p->bEnableSceneCutAwareQp == BI_DIRECTIONAL)<br>+        {<br>+            int window2;<br>+            double refQpDelta2, nonRefQpDelta2;<br>+            if (6 == sscanf(value, "%d,%lf,%lf,%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1, &window2, &refQpDelta2, &nonRefQpDelta2))<br>+            {<br>+                if (window1 > 0)<br>+                    p->fwdScenecutWindow = window1;<br>+                if (refQpDelta1 > 0)<br>+                    p->fwdRefQpDelta = refQpDelta1;<br>+                if (nonRefQpDelta1 > 0)<br>+                    p->fwdNonRefQpDelta = nonRefQpDelta1;<br>+                if (window2 > 0)<br>+                    p->bwdScenecutWindow = window2;<br>+                if (refQpDelta2 > 0)<br>+                    p->bwdRefQpDelta = refQpDelta2;<br>+                if (nonRefQpDelta2 > 0)<br>+                    p->bwdNonRefQpDelta = nonRefQpDelta2;<br>+            }<br>+            else<br>+            {<br>+                x265_log(NULL, X265_LOG_ERROR, "Specify all the necessary offsets for masking-strength \n");<br>+                bError = true;<br>+            }<br>+        }<br>+    }<br>+    else<br>+        return X265_PARAM_BAD_NAME;<br>+#undef OPT<br>+    return bError ? X265_PARAM_BAD_VALUE : 0;<br>+}<br>+<br>+<br>+/* internal versions of string-to-int with additional error checking */<br>+#undef atoi<br>+#undef atof<br>+#define atoi(str) x265_atoi(str, bError)<br>+#define atof(str) x265_atof(str, bError)<br>+#define atobool(str) (x265_atobool(str, bError))<br>+<br> int x265_zone_param_parse(x265_param* p, const char* name, const char* value)<br> {<br>     bool bError = false;<br>@@ -1346,72 +1449,6 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)<br>             p->selectiveSAO = atoi(value);<br>         }<br>         OPT("fades") p->bEnableFades = atobool(value);<br>-        OPT("scenecut-aware-qp") p->bEnableSceneCutAwareQp = atoi(value);<br>-        OPT("masking-strength")<br>-        {<br>-            int window1;<br>-            double refQpDelta1, nonRefQpDelta1;<br>-<br>-            if (p->bEnableSceneCutAwareQp == FORWARD)<br>-            {<br>-                if (3 == sscanf(value, "%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1))<br>-                {<br>-                    if (window1 > 0)<br>-                        p->fwdScenecutWindow = window1;<br>-                    if (refQpDelta1 > 0)<br>-                        p->fwdRefQpDelta = refQpDelta1;<br>-                    if (nonRefQpDelta1 > 0)<br>-                        p->fwdNonRefQpDelta = nonRefQpDelta1;<br>-                }<br>-                else<br>-                {<br>-                    x265_log(NULL, X265_LOG_ERROR, "Specify all the necessary offsets for masking-strength \n");<br>-                    bError = true;<br>-                }<br>-            }<br>-            else if (p->bEnableSceneCutAwareQp == BACKWARD)<br>-            {<br>-                if (3 == sscanf(value, "%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1))<br>-                {<br>-                    if (window1 > 0)<br>-                        p->bwdScenecutWindow = window1;<br>-                    if (refQpDelta1 > 0)<br>-                        p->bwdRefQpDelta = refQpDelta1;<br>-                    if (nonRefQpDelta1 > 0)<br>-                        p->bwdNonRefQpDelta = nonRefQpDelta1;<br>-                }<br>-                else<br>-                {<br>-                    x265_log(NULL, X265_LOG_ERROR, "Specify all the necessary offsets for masking-strength \n");<br>-                    bError = true;<br>-                }<br>-            }<br>-            else if (p->bEnableSceneCutAwareQp == BI_DIRECTIONAL)<br>-            {<br>-                int window2;<br>-                double refQpDelta2, nonRefQpDelta2;<br>-                if (6 == sscanf(value, "%d,%lf,%lf,%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1, &window2, &refQpDelta2, &nonRefQpDelta2))<br>-                {<br>-                    if (window1 > 0)<br>-                        p->fwdScenecutWindow = window1;<br>-                    if (refQpDelta1 > 0)<br>-                        p->fwdRefQpDelta = refQpDelta1;<br>-                    if (nonRefQpDelta1 > 0)<br>-                        p->fwdNonRefQpDelta = nonRefQpDelta1;<br>-                    if (window2 > 0)<br>-                        p->bwdScenecutWindow = window2;<br>-                    if (refQpDelta2 > 0)<br>-                        p->bwdRefQpDelta = refQpDelta2;<br>-                    if (nonRefQpDelta2 > 0)<br>-                        p->bwdNonRefQpDelta = nonRefQpDelta2;<br>-                }<br>-                else<br>-                {<br>-                    x265_log(NULL, X265_LOG_ERROR, "Specify all the necessary offsets for masking-strength \n");<br>-                    bError = true;<br>-                }<br>-            }<br>-        }<br>         OPT("field") p->bField = atobool( value );<br>         OPT("cll") p->bEmitCLL = atobool(value);<br>         OPT("frame-dup") p->bEnableFrameDuplication = atobool(value);<br>@@ -1859,17 +1896,17 @@ int x265_check_params(x265_param* param)<br>             "Invalid masking direction. Value must be between 0 and 3(inclusive)");<br>             CHECK(param->fwdScenecutWindow < 0 || param->fwdScenecutWindow > 1000,<br>             "Invalid forward scenecut Window duration. Value must be between 0 and 1000(inclusive)");<br>-            CHECK(param->fwdRefQpDelta < 0 || param->fwdRefQpDelta > 10,<br>-            "Invalid fwdRefQpDelta value. Value must be between 0 and 10 (inclusive)");<br>-            CHECK(param->fwdNonRefQpDelta < 0 || param->fwdNonRefQpDelta > 10,<br>-            "Invalid fwdNonRefQpDelta value. Value must be between 0 and 10 (inclusive)");<br>+            CHECK(param->fwdRefQpDelta < 0 || param->fwdRefQpDelta > 20,<br>+            "Invalid fwdRefQpDelta value. Value must be between 0 and 20 (inclusive)");<br>+            CHECK(param->fwdNonRefQpDelta < 0 || param->fwdNonRefQpDelta > 20,<br>+            "Invalid fwdNonRefQpDelta value. Value must be between 0 and 20 (inclusive)");<br> <br>             CHECK(param->bwdScenecutWindow < 0 || param->bwdScenecutWindow > 1000,<br>                 "Invalid backward scenecut Window duration. Value must be between 0 and 1000(inclusive)");<br>-            CHECK(param->bwdRefQpDelta < -1 || param->bwdRefQpDelta > 10,<br>-                "Invalid bwdRefQpDelta value. Value must be between 0 and 10 (inclusive)");<br>-            CHECK(param->bwdNonRefQpDelta < -1 || param->bwdNonRefQpDelta > 10,<br>-                "Invalid bwdNonRefQpDelta value. Value must be between 0 and 10 (inclusive)");<br>+            CHECK(param->bwdRefQpDelta < -1 || param->bwdRefQpDelta > 20,<br>+                "Invalid bwdRefQpDelta value. Value must be between 0 and 20 (inclusive)");<br>+            CHECK(param->bwdNonRefQpDelta < -1 || param->bwdNonRefQpDelta > 20,<br>+                "Invalid bwdNonRefQpDelta value. Value must be between 0 and 20 (inclusive)");<br>         }<br>     }<br>     if (param->bEnableHME)<br>diff --git a/source/common/param.h b/source/common/param.h<br>index 8ccd1f4a6..7808947f6 100644<br>--- a/source/common/param.h<br>+++ b/source/common/param.h<br>@@ -52,6 +52,7 @@ void x265_param_default(x265_param *param);<br> int x265_param_default_preset(x265_param *, const char *preset, const char *tune);<br> int x265_param_apply_profile(x265_param *, const char *profile);<br> int x265_param_parse(x265_param *p, const char *name, const char *value);<br>+int x265_scenecut_aware_qp_param_parse(x265_param* p, const char* name, const char* value);<br> int x265_zone_param_parse(x265_param* p, const char* name, const char* value);<br> #define PARAM_NS X265_NS<br> #endif<br>diff --git a/source/encoder/api.cpp b/source/encoder/api.cpp<br>index 66f26e37e..482ab9b8e 100644<br>--- a/source/encoder/api.cpp<br>+++ b/source/encoder/api.cpp<br>@@ -1050,6 +1050,7 @@ static const x265_api libapi =<br>     &PARAM_NS::x265_param_free,<br>     &PARAM_NS::x265_param_default,<br>     &PARAM_NS::x265_param_parse,<br>+    &PARAM_NS::x265_scenecut_aware_qp_param_parse,<br>     &PARAM_NS::x265_param_apply_profile,<br>     &PARAM_NS::x265_param_default_preset,<br>     &x265_picture_alloc,<br>diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp<br>index d0bd9762e..7e0dfe054 100644<br>--- a/source/encoder/ratecontrol.cpp<br>+++ b/source/encoder/ratecontrol.cpp<br>@@ -3335,7 +3335,7 @@ double RateControl::forwardMasking(Frame* curFrame, double q)<br> {<br>     double qp = x265_qScale2qp(q);<br>     uint32_t maxWindowSize = uint32_t((m_param->fwdScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5);<br>-    uint32_t windowSize = maxWindowSize / 3;<br>+    uint32_t windowSize = maxWindowSize / 6;<br>     int lastScenecut = m_top->m_rateControl->m_lastScenecut;<br>     int lastIFrame = m_top->m_rateControl->m_lastScenecutAwareIFrame;<br>     double fwdRefQpDelta = double(m_param->fwdRefQpDelta);<br>@@ -3361,8 +3361,14 @@ double RateControl::forwardMasking(Frame* curFrame, double q)<br>                     qp += WINDOW1_DELTA * (fwdRefQpDelta - sliceTypeDelta);<br>                 else if (((curFrame->m_poc) > (lastScenecut + int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 2 * int(windowSize))))<br>                     qp += WINDOW2_DELTA * (fwdRefQpDelta - sliceTypeDelta);<br>-                else if (curFrame->m_poc > lastScenecut + 2 * int(windowSize))<br>+                else if (((curFrame->m_poc) > (lastScenecut + 2 * int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 3 * int(windowSize))))<br>                     qp += WINDOW3_DELTA * (fwdRefQpDelta - sliceTypeDelta);<br>+                else if (((curFrame->m_poc) > (lastScenecut + 3 * int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 4 * int(windowSize))))<br>+                    qp += WINDOW4_DELTA * (fwdRefQpDelta - sliceTypeDelta);<br>+                else if (((curFrame->m_poc) > (lastScenecut + 4 * int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 5 * int(windowSize))))<br>+                    qp += WINDOW5_DELTA * (fwdRefQpDelta - sliceTypeDelta);<br>+                else if (curFrame->m_poc > lastScenecut + 5 * int(windowSize))<br>+                    qp += WINDOW6_DELTA * (fwdRefQpDelta - sliceTypeDelta);<br>             }<br>         }<br>         else if (curFrame->m_lowres.sliceType == X265_TYPE_BREF)<br>@@ -3375,8 +3381,14 @@ double RateControl::forwardMasking(Frame* curFrame, double q)<br>                     qp += WINDOW1_DELTA * fwdRefQpDelta;<br>                 else if (((curFrame->m_poc) > (lastScenecut + int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 2 * int(windowSize))))<br>                     qp += WINDOW2_DELTA * fwdRefQpDelta;<br>-                else if (curFrame->m_poc > lastScenecut + 2 * int(windowSize))<br>+                else if (((curFrame->m_poc) > (lastScenecut + 2 * int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 3 * int(windowSize))))<br>                     qp += WINDOW3_DELTA * fwdRefQpDelta;<br>+                else if (((curFrame->m_poc) > (lastScenecut + 3 * int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 4 * int(windowSize))))<br>+                    qp += WINDOW4_DELTA * fwdRefQpDelta;<br>+                else if (((curFrame->m_poc) > (lastScenecut + 4 * int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 5 * int(windowSize))))<br>+                    qp += WINDOW5_DELTA * fwdRefQpDelta;<br>+                else if (curFrame->m_poc > lastScenecut + 5 * int(windowSize))<br>+                    qp += WINDOW6_DELTA * fwdRefQpDelta;<br>             }<br>         }<br>         else if (curFrame->m_lowres.sliceType == X265_TYPE_B)<br>@@ -3389,8 +3401,14 @@ double RateControl::forwardMasking(Frame* curFrame, double q)<br>                     qp += WINDOW1_DELTA * fwdNonRefQpDelta;<br>                 else if (((curFrame->m_poc) > (lastScenecut + int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 2 * int(windowSize))))<br>                     qp += WINDOW2_DELTA * fwdNonRefQpDelta;<br>-                else if (curFrame->m_poc > lastScenecut + 2 * int(windowSize))<br>+                else if (((curFrame->m_poc) > (lastScenecut + 2 * int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 3 * int(windowSize))))<br>                     qp += WINDOW3_DELTA * fwdNonRefQpDelta;<br>+                else if (((curFrame->m_poc) > (lastScenecut + 3 * int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 4 * int(windowSize))))<br>+                    qp += WINDOW4_DELTA * fwdNonRefQpDelta;<br>+                else if (((curFrame->m_poc) > (lastScenecut + 4 * int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 5 * int(windowSize))))<br>+                    qp += WINDOW5_DELTA * fwdNonRefQpDelta;<br>+                else if (curFrame->m_poc > lastScenecut + 5 * int(windowSize))<br>+                    qp += WINDOW6_DELTA * fwdNonRefQpDelta;<br>             }<br>         }<br>     }<br>diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h<br>index 10dfc268d..d1734f8ff 100644<br>--- a/source/encoder/ratecontrol.h<br>+++ b/source/encoder/ratecontrol.h<br>@@ -49,8 +49,11 @@ struct SPS;<br> <br> /*Scenecut Aware QP*/<br> #define WINDOW1_DELTA           1.0 /* The offset for the frames coming in the window-1*/<br>-#define WINDOW2_DELTA           0.7 /* The offset for the frames coming in the window-2*/<br>-#define WINDOW3_DELTA           0.4 /* The offset for the frames coming in the window-3*/<br>+#define WINDOW2_DELTA           0.85 /* The offset for the frames coming in the window-2*/<br>+#define WINDOW3_DELTA           0.7 /* The offset for the frames coming in the window-3*/<br>+#define WINDOW4_DELTA           0.55 /* The offset for the frames coming in the window-4*/<br>+#define WINDOW5_DELTA           0.4 /* The offset for the frames coming in the window-5*/<br>+#define WINDOW6_DELTA           0.25 /* The offset for the frames coming in the window-6*/<br> <br> struct Predictor<br> {<br>diff --git a/source/x265.cpp b/source/x265.cpp<br>index ae3803b49..31a627d87 100644<br>--- a/source/x265.cpp<br>+++ b/source/x265.cpp<br>@@ -296,6 +296,16 @@ int main(int argc, char **argv)<br> <br>     int ret = 0;<br> <br>+    if (cliopt[0].scenecutAwareQpConfig)<br>+    {<br>+        if (!cliopt[0].parseScenecutAwareQpConfig())<br>+        {<br>+            x265_log(NULL, X265_LOG_ERROR, "Unable to parse scenecut aware qp config file \n");<br>+            fclose(cliopt[0].scenecutAwareQpConfig);<br>+            cliopt[0].scenecutAwareQpConfig = NULL;<br>+        }<br>+    }<br>+<br>     AbrEncoder* abrEnc = new AbrEncoder(cliopt, numEncodes, ret);<br>     int threadsActive = abrEnc->m_numActiveEncodes.get();<br>     while (threadsActive)<br>diff --git a/source/x265.h b/source/x265.h<br>index 4f1c52d56..25efb17f1 100644<br>--- a/source/x265.h<br>+++ b/source/x265.h<br>@@ -2024,6 +2024,8 @@ void x265_zone_free(x265_param *param);<br> <br> int x265_zone_param_parse(x265_param* p, const char* name, const char* value);<br> <br>+int x265_scenecut_aware_qp_param_parse(x265_param* p, const char* name, const char* value);<br>+<br> static const char * const x265_profile_names[] = {<br>     /* HEVC v1 */<br>     "main", "main10", "mainstillpicture", /* alias */ "msp",<br>@@ -2293,6 +2295,7 @@ typedef struct x265_api<br>     void          (*param_free)(x265_param*);<br>     void          (*param_default)(x265_param*);<br>     int           (*param_parse)(x265_param*, const char*, const char*);<br>+    int           (*scenecut_aware_qp_param_parse)(x265_param*, const char*, const char*);<br>     int           (*param_apply_profile)(x265_param*, const char*);<br>     int           (*param_default_preset)(x265_param*, const char*, const char *);<br>     x265_picture* (*picture_alloc)(void);<br>diff --git a/source/x265cli.cpp b/source/x265cli.cpp<br>index 54479ef2f..53e04fa6b 100755<br>--- a/source/x265cli.cpp<br>+++ b/source/x265cli.cpp<br>@@ -181,6 +181,7 @@ namespace X265_NS {<br>         H1("                                 2 - Backward masking\n");<br>         H1("                                 3 - Bidirectional masking\n");<br>         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");<br>+        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");<br>         H0("   --radl <integer>              Number of RADL pictures allowed in front of IDR. Default %d\n", param->radl);<br>         H0("   --intra-refresh               Use Periodic Intra Refresh instead of IDR frames\n");<br>         H0("   --rc-lookahead <integer>      Number of frames for frame-type lookahead (determines encoder latency) Default %d\n", param->lookaheadDepth);<br>@@ -738,6 +739,12 @@ namespace X265_NS {<br>                         return true;<br>                     }<br>                 }<br>+                OPT("scenecut-qp-config")<br>+                {<br>+                    this->scenecutAwareQpConfig = x265_fopen(optarg, "rb");<br>+                    if (!this->scenecutAwareQpConfig)<br>+                        x265_log_file(param, X265_LOG_ERROR, "%s scenecut aware qp config file not found or error in opening config file\n", optarg);<br>+                }<br>                 OPT("zonefile")<br>                 {<br>                     this->zoneFile = x265_fopen(optarg, "rb");<br>@@ -1092,6 +1099,128 @@ namespace X265_NS {<br>         return 0;<br>     }<br> <br>+    bool CLIOptions::parseScenecutAwareQpConfig()<br>+    {<br>+        char line[256];<br>+        char* argLine;<br>+        rewind(scenecutAwareQpConfig);<br>+        while (fgets(line, sizeof(line), scenecutAwareQpConfig))<br>+        {<br>+            if (*line == '#' || (strcmp(line, "\r\n") == 0))<br>+                continue;<br>+            int index = (int)strcspn(line, "\r\n");<br>+            line[index] = '\0';<br>+            argLine = line;<br>+            while (isspace((unsigned char)*argLine)) argLine++;<br>+            char* start = strchr(argLine, '-');<br>+            int argCount = 0;<br>+            char **args = (char**)malloc(256 * sizeof(char *));<br>+            //Adding a dummy string to avoid file parsing error<br>+            args[argCount++] = (char *)"x265";<br>+            char* token = strtok(start, " ");<br>+            while (token)<br>+            {<br>+                args[argCount++] = token;<br>+                token = strtok(NULL, " ");<br>+            }<br>+            args[argCount] = NULL;<br>+            CLIOptions cliopt;<br>+            if (cliopt.parseScenecutAwareQpParam(argCount, args, param))<br>+            {<br>+                cliopt.destroy();<br>+                if (cliopt.api)<br>+                    cliopt.api->param_free(cliopt.param);<br>+                exit(1);<br>+            }<br>+            break;<br>+        }<br>+        return 1;<br>+    }<br>+    bool CLIOptions::parseScenecutAwareQpParam(int argc, char **argv, x265_param* globalParam)<br>+    {<br>+        bool bError = false;<br>+        int bShowHelp = false;<br>+        int outputBitDepth = 0;<br>+        const char *profile = NULL;<br>+        /* Presets are applied before all other options. */<br>+        for (optind = 0;;)<br>+        {<br>+            int c = getopt_long(argc, argv, short_options, long_options, NULL);<br>+            if (c == -1)<br>+                break;<br>+            else if (c == 'D')<br>+                outputBitDepth = atoi(optarg);<br>+            else if (c == 'P')<br>+                profile = optarg;<br>+            else if (c == '?')<br>+                bShowHelp = true;<br>+        }<br>+        if (!outputBitDepth && profile)<br>+        {<br>+            /*try to derive the output bit depth from the requested profile*/<br>+            if (strstr(profile, "10"))<br>+                outputBitDepth = 10;<br>+            else if (strstr(profile, "12"))<br>+                outputBitDepth = 12;<br>+            else<br>+                outputBitDepth = 8;<br>+        }<br>+        api = x265_api_get(outputBitDepth);<br>+        if (!api)<br>+        {<br>+            x265_log(NULL, X265_LOG_WARNING, "falling back to default bit-depth\n");<br>+            api = x265_api_get(0);<br>+        }<br>+        if (bShowHelp)<br>+        {<br>+            printVersion(globalParam, api);<br>+            showHelp(globalParam);<br>+        }<br>+        for (optind = 0;;)<br>+        {<br>+            int long_options_index = -1;<br>+            int c = getopt_long(argc, argv, short_options, long_options, &long_options_index);<br>+            if (c == -1)<br>+                break;<br>+            if (long_options_index < 0 && c > 0)<br>+            {<br>+                for (size_t i = 0; i < sizeof(long_options) / sizeof(long_options[0]); i++)<br>+                {<br>+                    if (long_options[i].val == c)<br>+                    {<br>+                        long_options_index = (int)i;<br>+                        break;<br>+                    }<br>+                }<br>+                if (long_options_index < 0)<br>+                {<br>+                    /* getopt_long might have already printed an error message */<br>+                    if (c != 63)<br>+                        x265_log(NULL, X265_LOG_WARNING, "internal error: short option '%c' has no long option\n", c);<br>+                    return true;<br>+                }<br>+            }<br>+            if (long_options_index < 0)<br>+            {<br>+                x265_log(NULL, X265_LOG_WARNING, "short option '%c' unrecognized\n", c);<br>+                return true;<br>+            }<br>+            bError |= !!api->scenecut_aware_qp_param_parse(globalParam, long_options[long_options_index].name, optarg);<br>+            if (bError)<br>+            {<br>+                const char *name = long_options_index > 0 ? long_options[long_options_index].name : argv[optind - 2];<br>+                x265_log(NULL, X265_LOG_ERROR, "invalid argument: %s = %s\n", name, optarg);<br>+                return true;<br>+            }<br>+        }<br>+        if (optind < argc)<br>+        {<br>+            x265_log(param, X265_LOG_WARNING, "extra unused command arguments given <%s>\n", argv[optind]);<br>+            return true;<br>+        }<br>+        return false;<br>+    }<br>+<br> #ifdef __cplusplus<br> }<br> #endif<br>\ No newline at end of file<br>diff --git a/source/x265cli.h b/source/x265cli.h<br>index eea47f168..f4e748787 100644<br>--- a/source/x265cli.h<br>+++ b/source/x265cli.h<br>@@ -381,6 +381,7 @@ static const struct option long_options[] =<br>     { "abr-ladder", required_argument, NULL, 0 },<br>     { "min-vbv-fullness", required_argument, NULL, 0 },<br>     { "max-vbv-fullness", required_argument, NULL, 0 },<br>+    { "scenecut-qp-config", required_argument, NULL, 0 },<br>     { "film-grain", required_argument, NULL, 0 },<br>     { 0, 0, 0, 0 },<br>     { 0, 0, 0, 0 },<br>@@ -397,6 +398,7 @@ static const struct option long_options[] =<br>         FILE*       qpfile;<br>         FILE*       zoneFile;<br>         FILE*    dolbyVisionRpu;    /* File containing Dolby Vision BL RPU metadata */<br>+        FILE*    scenecutAwareQpConfig; /* File containing scenecut aware frame quantization related CLI options */<br>         const char* reconPlayCmd;<br>         const x265_api* api;<br>         x265_param* param;<br>@@ -434,6 +436,7 @@ static const struct option long_options[] =<br>             qpfile = NULL;<br>             zoneFile = NULL;<br>             dolbyVisionRpu = NULL;<br>+            scenecutAwareQpConfig = NULL;<br>             reconPlayCmd = NULL;<br>             api = NULL;<br>             param = NULL;<br>@@ -464,6 +467,8 @@ static const struct option long_options[] =<br>         bool parseQPFile(x265_picture &pic_org);<br>         bool parseZoneFile();<br>         int rpuParser(x265_picture * pic);<br>+        bool parseScenecutAwareQpConfig();<br>+        bool parseScenecutAwareQpParam(int argc, char **argv, x265_param* globalParam);<br>     };<br> #ifdef __cplusplus<br> }<br>-- <br>2.18.0.windows.1<br><br><div><br></div>-- <br><div dir="ltr" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div dir="ltr"><font color="#0c343d" face="verdana, sans-serif"><br></font></div><div dir="ltr"><font color="#0c343d" face="verdana, sans-serif">Thanks & Regards</font><div><font color="#0c343d" face="verdana, sans-serif"><b>Niranjan Kumar B</b></font></div><div><font size="1" color="#0c343d" face="verdana, sans-serif">Video Codec Engineer </font></div><div><font size="1" color="#0c343d" face="verdana, sans-serif">Media & AI Analytics</font></div><div><font face="trebuchet ms, sans-serif" color="#0c343d">+91 958 511 1449</font></div><div><a href="https://multicorewareinc.com/" style="color:rgb(17,85,204)" target="_blank"><img src="https://docs.google.com/uc?export=download&id=1kc3RJu9M8bnIf6Xa5rUw2d-eEVUsPBE5&revid=0B7tw9XJBmynaemR1VUpQUi9DVytRVW5SVkRwVTFjb1hBMUcwPQ"></a></div></div></div></div></div></div></div></div>