<div dir="ltr">From d6b6c195aca2037c0e141efda899f22368ec7555 Mon Sep 17 00:00:00 2001<br>From: Niranjan Kumar <<a href="mailto:niranjan@multicorewareinc.com">niranjan@multicorewareinc.com</a>><br>Date: Fri, 4 Nov 2022 14:56:35 +0530<br>Subject: [PATCH] Increase BBAQ windows and enable masking after I frames<br><br>---<br> doc/reST/cli.rst               |  66 ++++++++---<br> source/common/param.cpp        | 208 ++++++++++++++++++++++++---------<br> source/encoder/encoder.cpp     |   4 +-<br> source/encoder/ratecontrol.cpp | 184 ++++++++++++++++++-----------<br> source/encoder/ratecontrol.h   |   8 --<br> source/x265.h                  |  15 ++-<br> 6 files changed, 326 insertions(+), 159 deletions(-)<br><br>diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst<br>index 2437a09da..c7ff17ff8 100755<br>--- a/doc/reST/cli.rst<br>+++ b/doc/reST/cli.rst<br>@@ -1974,12 +1974,17 @@ Quality, rate control and rate distortion options<br>         <br>     **CLI ONLY**<br> <br>+.. option:: --scenecut-qp-config <filename><br>+ Specify a text file which contains the scenecut aware QP options.<br>+    The options include :option:`--scenecut-aware-qp` and :option:`--masking-strength`<br>+   **CLI ONLY**<br>+<br> .. option:: --scenecut-aware-qp <integer><br> <br>       It reduces the bits spent on the inter-frames within the scenecut window<br>     before and after a scenecut by increasing their QP in ratecontrol pass2 algorithm<br>-    without any deterioration in visual quality. If a scenecut falls within the window,<br>-  the QP of the inter-frames after this scenecut will not be modified.<br>+ without any deterioration in visual quality.<br>+ It is mentioned inside :option:`--scenecut-qp-config` file.<br>  :option:`--scenecut-aware-qp` works only with --pass 2. Default 0.<br> <br>       +-------+---------------------------------------------------------------+<br>@@ -2002,47 +2007,72 @@ Quality, rate control and rate distortion options<br> <br>     Comma separated list of values which specifies the duration and offset<br>       for the QP increment for inter-frames when :option:`--scenecut-aware-qp`<br>-     is enabled.<br>+  is enabled. It is mentioned inside :option:`--scenecut-qp-config` file.<br> <br>  When :option:`--scenecut-aware-qp` is::<br>      * 1 (Forward masking):<br>-       --masking-strength <fwdWindow,fwdRefQPDelta,fwdNonRefQPDelta><br>+  --masking-strength <fwdMaxWindow,fwdRefQPDelta,fwdNonRefQPDelta><br>+       or <br>+  --masking-strength <fwdWindow1,fwdRefQPDelta1,fwdNonRefQPDelta1,fwdWindow2,fwdRefQPDelta2,fwdNonRefQPDelta2,<br>+                                              fwdWindow3,fwdRefQPDelta3,fwdNonRefQPDelta3,fwdWindow4,fwdRefQPDelta4,fwdNonRefQPDelta4,<br>+                                             fwdWindow5,fwdRefQPDelta5,fwdNonRefQPDelta5,fwdWindow6,fwdRefQPDelta6,fwdNonRefQPDelta6><br>  * 2 (Backward masking):<br>-      --masking-strength <bwdWindow,bwdRefQPDelta,bwdNonRefQPDelta><br>+  --masking-strength <bwdMaxWindow,bwdRefQPDelta,bwdNonRefQPDelta><br>+       or <br>+  --masking-strength <bwdWindow1,bwdRefQPDelta1,bwdNonRefQPDelta1,bwdWindow2,bwdRefQPDelta2,bwdNonRefQPDelta2,<br>+                                              bwdWindow3,bwdRefQPDelta3,bwdNonRefQPDelta3,bwdWindow4,bwdRefQPDelta4,bwdNonRefQPDelta4,<br>+                                             bwdWindow5,bwdRefQPDelta5,bwdNonRefQPDelta5,bwdWindow6,bwdRefQPDelta6,bwdNonRefQPDelta6><br>  * 3 (Bi-directional masking):<br>-        --masking-strength <fwdWindow,fwdRefQPDelta,fwdNonRefQPDelta,bwdWindow,bwdRefQPDelta,bwdNonRefQPDelta><br>+ --masking-strength <fwdMaxWindow,fwdRefQPDelta,fwdNonRefQPDelta,bwdMaxWindow,bwdRefQPDelta,bwdNonRefQPDelta><br>+   or <br>+  --masking-strength <fwdWindow1,fwdRefQPDelta1,fwdNonRefQPDelta1,fwdWindow2,fwdRefQPDelta2,fwdNonRefQPDelta2,<br>+                                              fwdWindow3,fwdRefQPDelta3,fwdNonRefQPDelta3,fwdWindow4,fwdRefQPDelta4,fwdNonRefQPDelta4,<br>+                                             fwdWindow5,fwdRefQPDelta5,fwdNonRefQPDelta5,fwdWindow6,fwdRefQPDelta6,fwdNonRefQPDelta6,<br>+                                             bwdWindow1,bwdRefQPDelta1,bwdNonRefQPDelta1,bwdWindow2,bwdRefQPDelta2,bwdNonRefQPDelta2,<br>+                                             bwdWindow3,bwdRefQPDelta3,bwdNonRefQPDelta3,bwdWindow4,bwdRefQPDelta4,bwdNonRefQPDelta4,<br>+                                             bwdWindow5,bwdRefQPDelta5,bwdNonRefQPDelta5,bwdWindow6,bwdRefQPDelta6,bwdNonRefQPDelta6><br> <br>      +-----------------+---------------------------------------------------------------+<br>  | Parameter       | Description                                                   |<br>      +=================+===============================================================+<br>-  | fwdWindow       | The duration(in milliseconds) for which there is a reduction  |<br>-      |                 | in the bits spent on the inter-frames after a scenecut by     |<br>-        |                 | increasing their QP. Default 500ms.                           |<br>-     |                 | **Range of values:** 0 to 1000                                |<br>+  | fwdMaxWindow    | The maximum duration(in milliseconds) for which there is a    |<br>+      |                 | reduction in the bits spent on the inter-frames after a       |<br>+       |                 | scenecut by increasing their QP. Default 500ms.               |<br>+   |                 | **Range of values:** 0 to 2000                                |<br>+  +-----------------+---------------------------------------------------------------+<br>+  | fwdWindow       | The duration of a sub-window(in milliseconds) for which there |<br>+       |                 | is a reduction in the bits spent on the inter-frames after a  |<br>+ |                 | scenecut by increasing their QP. Default 500ms.               |<br>+   |                 | **Range of values:** 0 to 2000                                |<br>  +-----------------+---------------------------------------------------------------+<br>  | fwdRefQPDelta   | The offset by which QP is incremented for inter-frames        |<br>     |                 | after a scenecut. Default 5.                                  |<br>- |                 | **Range of values:** 0 to 10                                  |<br>+ |                 | **Range of values:** 0 to 20                                  |<br>         +-----------------+---------------------------------------------------------------+<br>  | fwdNonRefQPDelta| The offset by which QP is incremented for non-referenced      |<br>       |                 | inter-frames after a scenecut. The offset is computed from    |<br>        |                 | fwdRefQPDelta when it is not explicitly specified.            |<br>-    |                 | **Range of values:** 0 to 10                                  |<br>+ |                 | **Range of values:** 0 to 20                                  |<br>+ +-----------------+---------------------------------------------------------------+<br>+  | bwdMaxWindow    | The maximum duration(in milliseconds) for which there is a    |<br>+      |                 | reduction in the bits spent on the inter-frames before a      |<br>+       |                 | scenecut by increasing their QP. Default 100ms.               |<br>+   |                 | **Range of values:** 0 to 2000                                |<br>  +-----------------+---------------------------------------------------------------+<br>-  | bwdWindow       | The duration(in milliseconds) for which there is a reduction  |<br>-      |                 | in the bits spent on the inter-frames before a scenecut by    |<br>-        |                 | increasing their QP. Default 100ms.                           |<br>-     |                 | **Range of values:** 0 to 1000                                |<br>+  | bwdWindow       | The duration of a sub-window(in milliseconds) for which there |<br>+       |                 | is a reduction in the bits spent on the inter-frames before a |<br>+  |                 | scenecut by increasing their QP. Default 100ms.               |<br>+   |                 | **Range of values:** 0 to 2000                                |<br>  +-----------------+---------------------------------------------------------------+<br>  | bwdRefQPDelta   | The offset by which QP is incremented for inter-frames        |<br>     |                 | before a scenecut. The offset is computed from                |<br>  |                 | fwdRefQPDelta when it is not explicitly specified.            |<br>-    |                 | **Range of values:** 0 to 10                                  |<br>+ |                 | **Range of values:** 0 to 20                                  |<br>         +-----------------+---------------------------------------------------------------+<br>  | bwdNonRefQPDelta| The offset by which QP is incremented for non-referenced      |<br>       |                 | inter-frames before a scenecut. The offset is computed from   |<br>         |                 | bwdRefQPDelta when it is not explicitly specified.            |<br>-    |                 | **Range of values:** 0 to 10                                  |<br>+ |                 | **Range of values:** 0 to 20                                  |<br>         +-----------------+---------------------------------------------------------------+<br> <br>      **CLI ONLY**<br>diff --git a/source/common/param.cpp b/source/common/param.cpp<br>index ccadcd2cc..d44693e56 100755<br>--- a/source/common/param.cpp<br>+++ b/source/common/param.cpp<br>@@ -180,12 +180,20 @@ void x265_param_default(x265_param* param)<br>     param->bEnableHRDConcatFlag = 0;<br>     param->bEnableFades = 0;<br>     param->bEnableSceneCutAwareQp = 0;<br>-    param->fwdScenecutWindow = 500;<br>-    param->fwdRefQpDelta = 5;<br>-    param->fwdNonRefQpDelta = param->fwdRefQpDelta + (SLICE_TYPE_DELTA * param->fwdRefQpDelta);<br>-    param->bwdScenecutWindow = 100;<br>-    param->bwdRefQpDelta = -1;<br>-    param->bwdNonRefQpDelta = -1;<br>+    param->fwdMaxScenecutWindow = 1200;<br>+    param->bwdMaxScenecutWindow = 600;<br>+    for (int i = 0; i < 6; i++)<br>+    {<br>+        int deltas[6] = { 5, 4, 3, 2, 1, 0 };<br>+<br>+        param->fwdScenecutWindow[i] = 200;<br>+        param->fwdRefQpDelta[i] = deltas[i];<br>+        param->fwdNonRefQpDelta[i] = param->fwdRefQpDelta[i] + (SLICE_TYPE_DELTA * param->fwdRefQpDelta[i]);<br>+<br>+        param->bwdScenecutWindow[i] = 100;<br>+        param->bwdRefQpDelta[i] = -1;<br>+        param->bwdNonRefQpDelta[i] = -1;<br>+    }<br> <br>     /* Intra Coding Tools */<br>     param->bEnableConstrainedIntra = 0;<br>@@ -705,18 +713,40 @@ int x265_scenecut_aware_qp_param_parse(x265_param* p, const char* name, const ch<br>     OPT("scenecut-aware-qp") p->bEnableSceneCutAwareQp = x265_atoi(value, bError);<br>     OPT("masking-strength")<br>     {<br>-        int window1;<br>-        double refQpDelta1, nonRefQpDelta1;<br>+        int window1[6];<br>+        double refQpDelta1[6], nonRefQpDelta1[6];<br>         if (p->bEnableSceneCutAwareQp == FORWARD)<br>         {<br>-            if (3 == sscanf(value, "%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1))<br>+            if (3 == sscanf(value, "%d,%lf,%lf", &window1[0], &refQpDelta1[0], &nonRefQpDelta1[0]))<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 (window1[0] > 0)<br>+                    p->fwdMaxScenecutWindow = window1[0];<br>+                if (refQpDelta1[0] > 0)<br>+                    p->fwdRefQpDelta[0] = refQpDelta1[0];<br>+                if (nonRefQpDelta1[0] > 0)<br>+                    p->fwdNonRefQpDelta[0] = nonRefQpDelta1[0];<br>+<br>+                p->fwdScenecutWindow[0] = p->fwdMaxScenecutWindow / 6;<br>+                for (int i = 1; i < 6; i++)<br>+                {<br>+                    p->fwdScenecutWindow[i] = p->fwdMaxScenecutWindow / 6;<br>+                    p->fwdRefQpDelta[i] = p->fwdRefQpDelta[i - 1] - (0.15 * p->fwdRefQpDelta[i - 1]);<br>+                    p->fwdNonRefQpDelta[i] = p->fwdNonRefQpDelta[i - 1] - (0.15 * p->fwdNonRefQpDelta[i - 1]);<br>+                }<br>+            }<br>+            else if (18 == sscanf(value, "%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf"<br>+                , &window1[0], &refQpDelta1[0], &nonRefQpDelta1[0], &window1[1], &refQpDelta1[1], &nonRefQpDelta1[1]<br>+                , &window1[2], &refQpDelta1[2], &nonRefQpDelta1[2], &window1[3], &refQpDelta1[3], &nonRefQpDelta1[3]<br>+                , &window1[4], &refQpDelta1[4], &nonRefQpDelta1[4], &window1[5], &refQpDelta1[5], &nonRefQpDelta1[5]))<br>+            {<br>+                p->fwdMaxScenecutWindow = 0;<br>+                for (int i = 0; i < 6; i++)<br>+                {<br>+                    p->fwdScenecutWindow[i] = window1[i];<br>+                    p->fwdRefQpDelta[i] = refQpDelta1[i];<br>+                    p->fwdNonRefQpDelta[i] = nonRefQpDelta1[i];<br>+                    p->fwdMaxScenecutWindow += p->fwdScenecutWindow[i];<br>+                }<br>             }<br>             else<br>             {<br>@@ -726,14 +756,36 @@ int x265_scenecut_aware_qp_param_parse(x265_param* p, const char* name, const ch<br>         }<br>         else if (p->bEnableSceneCutAwareQp == BACKWARD)<br>         {<br>-            if (3 == sscanf(value, "%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1))<br>+            if (3 == sscanf(value, "%d,%lf,%lf", &window1[0], &refQpDelta1[0], &nonRefQpDelta1[0]))<br>+            {<br>+                if (window1[0] > 0)<br>+                    p->bwdMaxScenecutWindow = window1[0];<br>+                if (refQpDelta1[0] > 0)<br>+                    p->bwdRefQpDelta[0] = refQpDelta1[0];<br>+                if (nonRefQpDelta1[0] > 0)<br>+                    p->bwdNonRefQpDelta[0] = nonRefQpDelta1[0];<br>+<br>+                p->bwdScenecutWindow[0] = p->bwdMaxScenecutWindow / 6;<br>+                for (int i = 1; i < 6; i++)<br>+                {<br>+                    p->bwdScenecutWindow[i] = p->bwdMaxScenecutWindow / 6;<br>+                    p->bwdRefQpDelta[i] = p->bwdRefQpDelta[i - 1] - (0.15 * p->bwdRefQpDelta[i - 1]);<br>+                    p->bwdNonRefQpDelta[i] = p->bwdNonRefQpDelta[i - 1] - (0.15 * p->bwdNonRefQpDelta[i - 1]);<br>+                }<br>+            }<br>+            else if (18 == sscanf(value, "%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf"<br>+                , &window1[0], &refQpDelta1[0], &nonRefQpDelta1[0], &window1[1], &refQpDelta1[1], &nonRefQpDelta1[1]<br>+                , &window1[2], &refQpDelta1[2], &nonRefQpDelta1[2], &window1[3], &refQpDelta1[3], &nonRefQpDelta1[3]<br>+                , &window1[4], &refQpDelta1[4], &nonRefQpDelta1[4], &window1[5], &refQpDelta1[5], &nonRefQpDelta1[5]))<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>+                p->bwdMaxScenecutWindow = 0;<br>+                for (int i = 0; i < 6; i++)<br>+                {<br>+                    p->bwdScenecutWindow[i] = window1[i];<br>+                    p->bwdRefQpDelta[i] = refQpDelta1[i];<br>+                    p->bwdNonRefQpDelta[i] = nonRefQpDelta1[i];<br>+                    p->bwdMaxScenecutWindow += p->bwdScenecutWindow[i];<br>+                }<br>             }<br>             else<br>             {<br>@@ -743,22 +795,56 @@ int x265_scenecut_aware_qp_param_parse(x265_param* p, const char* name, const ch<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>+            int window2[6];<br>+            double refQpDelta2[6], nonRefQpDelta2[6];<br>+            if (6 == sscanf(value, "%d,%lf,%lf,%d,%lf,%lf", &window1[0], &refQpDelta1[0], &nonRefQpDelta1[0], &window2[0], &refQpDelta2[0], &nonRefQpDelta2[0]))<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>+                if (window1[0] > 0)<br>+                    p->fwdMaxScenecutWindow = window1[0];<br>+                if (refQpDelta1[0] > 0)<br>+                    p->fwdRefQpDelta[0] = refQpDelta1[0];<br>+                if (nonRefQpDelta1[0] > 0)<br>+                    p->fwdNonRefQpDelta[0] = nonRefQpDelta1[0];<br>+                if (window2[0] > 0)<br>+                    p->bwdMaxScenecutWindow = window2[0];<br>+                if (refQpDelta2[0] > 0)<br>+                    p->bwdRefQpDelta[0] = refQpDelta2[0];<br>+                if (nonRefQpDelta2[0] > 0)<br>+                    p->bwdNonRefQpDelta[0] = nonRefQpDelta2[0];<br>+<br>+                p->fwdScenecutWindow[0] = p->fwdMaxScenecutWindow / 6;<br>+                p->bwdScenecutWindow[0] = p->bwdMaxScenecutWindow / 6;<br>+                for (int i = 1; i < 6; i++)<br>+                {<br>+                    p->fwdScenecutWindow[i] = p->fwdMaxScenecutWindow / 6;<br>+                    p->bwdScenecutWindow[i] = p->bwdMaxScenecutWindow / 6;<br>+                    p->fwdRefQpDelta[i] = p->fwdRefQpDelta[i - 1] - (0.15 * p->fwdRefQpDelta[i - 1]);<br>+                    p->fwdNonRefQpDelta[i] = p->fwdNonRefQpDelta[i - 1] - (0.15 * p->fwdNonRefQpDelta[i - 1]);<br>+                    p->bwdRefQpDelta[i] = p->bwdRefQpDelta[i - 1] - (0.15 * p->bwdRefQpDelta[i - 1]);<br>+                    p->bwdNonRefQpDelta[i] = p->bwdNonRefQpDelta[i - 1] - (0.15 * p->bwdNonRefQpDelta[i - 1]);<br>+                }<br>+            }<br>+            else if (36 == sscanf(value, "%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf"<br>+                , &window1[0], &refQpDelta1[0], &nonRefQpDelta1[0], &window1[1], &refQpDelta1[1], &nonRefQpDelta1[1]<br>+                , &window1[2], &refQpDelta1[2], &nonRefQpDelta1[2], &window1[3], &refQpDelta1[3], &nonRefQpDelta1[3]<br>+                , &window1[4], &refQpDelta1[4], &nonRefQpDelta1[4], &window1[5], &refQpDelta1[5], &nonRefQpDelta1[5]<br>+                , &window2[0], &refQpDelta2[0], &nonRefQpDelta2[0], &window2[1], &refQpDelta2[1], &nonRefQpDelta2[1]<br>+                , &window2[2], &refQpDelta2[2], &nonRefQpDelta2[2], &window2[3], &refQpDelta2[3], &nonRefQpDelta2[3]<br>+                , &window2[4], &refQpDelta2[4], &nonRefQpDelta2[4], &window2[5], &refQpDelta2[5], &nonRefQpDelta2[5]))<br>+            {<br>+                p->fwdMaxScenecutWindow = 0;<br>+                p->bwdMaxScenecutWindow = 0;<br>+                for (int i = 0; i < 6; i++)<br>+                {<br>+                    p->fwdScenecutWindow[i] = window1[i];<br>+                    p->fwdRefQpDelta[i] = refQpDelta1[i];<br>+                    p->fwdNonRefQpDelta[i] = nonRefQpDelta1[i];<br>+                    p->bwdScenecutWindow[i] = window2[i];<br>+                    p->bwdRefQpDelta[i] = refQpDelta2[i];<br>+                    p->bwdNonRefQpDelta[i] = nonRefQpDelta2[i];<br>+                    p->fwdMaxScenecutWindow += p->fwdScenecutWindow[i];<br>+                    p->bwdMaxScenecutWindow += p->bwdScenecutWindow[i];<br>+                }<br>             }<br>             else<br>             {<br>@@ -1894,19 +1980,22 @@ int x265_check_params(x265_param* param)<br>         {<br>             CHECK(param->bEnableSceneCutAwareQp < 0 || param->bEnableSceneCutAwareQp > 3,<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 > 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 > 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>+            for (int i = 0; i < 6; i++)<br>+            {<br>+                CHECK(param->fwdScenecutWindow[i] < 0 || param->fwdScenecutWindow[i] > 1000,<br>+                    "Invalid forward scenecut Window duration. Value must be between 0 and 1000(inclusive)");<br>+                CHECK(param->fwdRefQpDelta[i] < 0 || param->fwdRefQpDelta[i] > 20,<br>+                    "Invalid fwdRefQpDelta value. Value must be between 0 and 20 (inclusive)");<br>+                CHECK(param->fwdNonRefQpDelta[i] < 0 || param->fwdNonRefQpDelta[i] > 20,<br>+                    "Invalid fwdNonRefQpDelta value. Value must be between 0 and 20 (inclusive)");<br>+<br>+                CHECK(param->bwdScenecutWindow[i] < 0 || param->bwdScenecutWindow[i] > 1000,<br>+                    "Invalid backward scenecut Window duration. Value must be between 0 and 1000(inclusive)");<br>+                CHECK(param->bwdRefQpDelta[i] < -1 || param->bwdRefQpDelta[i] > 20,<br>+                    "Invalid bwdRefQpDelta value. Value must be between 0 and 20 (inclusive)");<br>+                CHECK(param->bwdNonRefQpDelta[i] < -1 || param->bwdNonRefQpDelta[i] > 20,<br>+                    "Invalid bwdNonRefQpDelta value. Value must be between 0 and 20 (inclusive)");<br>+            }<br>         }<br>     }<br>     if (param->bEnableHME)<br>@@ -2380,7 +2469,7 @@ char *x265_param2string(x265_param* p, int padx, int pady)<br>     s += sprintf(s, " qp-adaptation-range=%.2f", p->rc.qpAdaptationRange);<br>     s += sprintf(s, " scenecut-aware-qp=%d", p->bEnableSceneCutAwareQp);<br>     if (p->bEnableSceneCutAwareQp)<br>-        s += sprintf(s, " fwd-scenecut-window=%d fwd-ref-qp-delta=%f fwd-nonref-qp-delta=%f bwd-scenecut-window=%d bwd-ref-qp-delta=%f bwd-nonref-qp-delta=%f", p->fwdScenecutWindow, p->fwdRefQpDelta, p->fwdNonRefQpDelta, p->bwdScenecutWindow, p->bwdRefQpDelta, p->bwdNonRefQpDelta);<br>+        s += sprintf(s, " fwd-scenecut-window=%d fwd-ref-qp-delta=%f fwd-nonref-qp-delta=%f bwd-scenecut-window=%d bwd-ref-qp-delta=%f bwd-nonref-qp-delta=%f", p->fwdMaxScenecutWindow, p->fwdRefQpDelta[0], p->fwdNonRefQpDelta[0], p->bwdMaxScenecutWindow, p->bwdRefQpDelta[0], p->bwdNonRefQpDelta[0]);<br>     s += sprintf(s, "conformance-window-offsets right=%d bottom=%d", p->confWinRightOffset, p->confWinBottomOffset);<br>     s += sprintf(s, " decoder-max-rate=%d", p->decoderVbvMaxRate);<br>     BOOL(p->bliveVBV2pass, "vbv-live-multi-pass");<br>@@ -2742,12 +2831,17 @@ void x265_copy_params(x265_param* dst, x265_param* src)<br>     dst->bEnableSvtHevc = src->bEnableSvtHevc;<br>     dst->bEnableFades = src->bEnableFades;<br>     dst->bEnableSceneCutAwareQp = src->bEnableSceneCutAwareQp;<br>-    dst->fwdScenecutWindow = src->fwdScenecutWindow;<br>-    dst->fwdRefQpDelta = src->fwdRefQpDelta;<br>-    dst->fwdNonRefQpDelta = src->fwdNonRefQpDelta;<br>-    dst->bwdScenecutWindow = src->bwdScenecutWindow;<br>-    dst->bwdRefQpDelta = src->bwdRefQpDelta;<br>-    dst->bwdNonRefQpDelta = src->bwdNonRefQpDelta;<br>+    dst->fwdMaxScenecutWindow = src->fwdMaxScenecutWindow;<br>+    dst->bwdMaxScenecutWindow = src->bwdMaxScenecutWindow;<br>+    for (int i = 0; i < 6; i++)<br>+    {<br>+        dst->fwdScenecutWindow[i] = src->fwdScenecutWindow[i];<br>+        dst->fwdRefQpDelta[i] = src->fwdRefQpDelta[i];<br>+        dst->fwdNonRefQpDelta[i] = src->fwdNonRefQpDelta[i];<br>+        dst->bwdScenecutWindow[i] = src->bwdScenecutWindow[i];<br>+        dst->bwdRefQpDelta[i] = src->bwdRefQpDelta[i];<br>+        dst->bwdNonRefQpDelta[i] = src->bwdNonRefQpDelta[i];<br>+    }<br>     dst->bField = src->bField;<br>     dst->bEnableTemporalFilter = src->bEnableTemporalFilter;<br>     dst->temporalFilterStrength = src->temporalFilterStrength;<br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index 0fea6553c..38e1e56eb 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -1652,7 +1652,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)<br>             rcEntry = &(m_rateControl->m_rce2Pass[inFrame->m_poc]);<br>             if(rcEntry->scenecut)<br>             {<br>-                int backwardWindow = X265_MIN(int((m_param->bwdScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom)), p->lookaheadDepth);<br>+                int backwardWindow = X265_MIN(int((m_param->bwdMaxScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom)), p->lookaheadDepth);<br>                 for (int i = 1; i <= backwardWindow; i++)<br>                 {<br>                     int frameNum = inFrame->m_poc - i;<br>@@ -2137,7 +2137,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)<br>                         m_rateControl->m_lastScenecut = frameEnc->m_poc;<br>                     else<br>                     {<br>-                        int maxWindowSize = int((m_param->fwdScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5);<br>+                        int maxWindowSize = int((m_param->fwdMaxScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5);<br>                         if (frameEnc->m_poc > (m_rateControl->m_lastScenecut + maxWindowSize))<br>                             m_rateControl->m_lastScenecut = frameEnc->m_poc;<br>                     }<br>diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp<br>index 3defaf8bf..17d8c1e0d 100644<br>--- a/source/encoder/ratecontrol.cpp<br>+++ b/source/encoder/ratecontrol.cpp<br>@@ -3344,13 +3344,21 @@ void RateControl::splitbUsed(char bused[], RateControlEntry *rce)<br> 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 / 6;<br>+    uint32_t maxWindowSize = uint32_t((m_param->fwdMaxScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5);<br>+    uint32_t windowSize[6], prevWindow = 0;<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>-    double fwdNonRefQpDelta = double(m_param->fwdNonRefQpDelta);<br>-    double sliceTypeDelta = SLICE_TYPE_DELTA * fwdRefQpDelta;<br>+<br>+    double fwdRefQpDelta[6], fwdNonRefQpDelta[6], sliceTypeDelta[6];<br>+    for (int i = 0; i < 6; i++)<br>+    {<br>+        windowSize[i] = prevWindow + (uint32_t((m_param->fwdScenecutWindow[i] / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5));<br>+        fwdRefQpDelta[i] = double(m_param->fwdRefQpDelta[i]);<br>+        fwdNonRefQpDelta[i] = double(m_param->fwdNonRefQpDelta[i]);<br>+        sliceTypeDelta[i] = SLICE_TYPE_DELTA * fwdRefQpDelta[i];<br>+        prevWindow = windowSize[i];<br>+    }<br>+<br> <br>     //Check whether the current frame is within the forward window<br>     if (curFrame->m_poc > lastScenecut && curFrame->m_poc <= (lastScenecut + int(maxWindowSize)))<br>@@ -3363,63 +3371,51 @@ double RateControl::forwardMasking(Frame* curFrame, double q)<br>         }<br>         else if (curFrame->m_lowres.sliceType == X265_TYPE_P)<br>         {<br>-            if (!(lastIFrame > lastScenecut && lastIFrame <= (lastScenecut + int(maxWindowSize))<br>-                && curFrame->m_poc >= lastIFrame))<br>-            {<br>-                //Add offsets corresponding to the window in which the P-frame occurs<br>-                if (curFrame->m_poc <= (lastScenecut + int(windowSize)))<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))) && ((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>+            //Add offsets corresponding to the window in which the P-frame occurs<br>+            if (curFrame->m_poc <= (lastScenecut + int(windowSize[0])))<br>+                qp += fwdRefQpDelta[0] - sliceTypeDelta[0];<br>+            else if (((curFrame->m_poc) > (lastScenecut + int(windowSize[0]))) && ((curFrame->m_poc) <= (lastScenecut + int(windowSize[1]))))<br>+                qp += fwdRefQpDelta[1] - sliceTypeDelta[1];<br>+            else if (((curFrame->m_poc) > (lastScenecut + int(windowSize[1]))) && ((curFrame->m_poc) <= (lastScenecut + int(windowSize[2]))))<br>+                qp += fwdRefQpDelta[2] - sliceTypeDelta[2];<br>+            else if (((curFrame->m_poc) > (lastScenecut + int(windowSize[2]))) && ((curFrame->m_poc) <= (lastScenecut + int(windowSize[3]))))<br>+                qp += fwdRefQpDelta[3] - sliceTypeDelta[3];<br>+            else if (((curFrame->m_poc) > (lastScenecut + int(windowSize[3]))) && ((curFrame->m_poc) <= (lastScenecut + int(windowSize[4]))))<br>+                qp += fwdRefQpDelta[4] - sliceTypeDelta[4];<br>+            else if (curFrame->m_poc > lastScenecut + int(windowSize[4]))<br>+                qp += fwdRefQpDelta[5] - sliceTypeDelta[5];<br>         }<br>         else if (curFrame->m_lowres.sliceType == X265_TYPE_BREF)<br>         {<br>-            if (!(lastIFrame > lastScenecut && lastIFrame <= (lastScenecut + int(maxWindowSize))<br>-                && curFrame->m_poc >= lastIFrame))<br>-            {<br>-                //Add offsets corresponding to the window in which the B-frame occurs<br>-                if (curFrame->m_poc <= (lastScenecut + int(windowSize)))<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))) && ((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>+            //Add offsets corresponding to the window in which the B-frame occurs<br>+            if (curFrame->m_poc <= (lastScenecut + int(windowSize[0])))<br>+                qp += fwdRefQpDelta[0];<br>+            else if (((curFrame->m_poc) > (lastScenecut + int(windowSize[0]))) && ((curFrame->m_poc) <= (lastScenecut + int(windowSize[1]))))<br>+                qp += fwdRefQpDelta[1];<br>+            else if (((curFrame->m_poc) > (lastScenecut + int(windowSize[1]))) && ((curFrame->m_poc) <= (lastScenecut + int(windowSize[2]))))<br>+                qp += fwdRefQpDelta[2];<br>+            else if (((curFrame->m_poc) > (lastScenecut + int(windowSize[2]))) && ((curFrame->m_poc) <= (lastScenecut + int(windowSize[3]))))<br>+                qp += fwdRefQpDelta[3];<br>+            else if (((curFrame->m_poc) > (lastScenecut + int(windowSize[3]))) && ((curFrame->m_poc) <= (lastScenecut + int(windowSize[4]))))<br>+                qp += fwdRefQpDelta[4];<br>+            else if (curFrame->m_poc > lastScenecut + int(windowSize[4]))<br>+                qp += fwdRefQpDelta[5];<br>         }<br>         else if (curFrame->m_lowres.sliceType == X265_TYPE_B)<br>         {<br>-            if (!(lastIFrame > lastScenecut && lastIFrame <= (lastScenecut + int(maxWindowSize))<br>-                && curFrame->m_poc >= lastIFrame))<br>-            {<br>-                //Add offsets corresponding to the window in which the b-frame occurs<br>-                if (curFrame->m_poc <= (lastScenecut + int(windowSize)))<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))) && ((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>+            //Add offsets corresponding to the window in which the b-frame occurs<br>+            if (curFrame->m_poc <= (lastScenecut + int(windowSize[0])))<br>+                qp += fwdNonRefQpDelta[0];<br>+            else if (((curFrame->m_poc) > (lastScenecut + int(windowSize[0]))) && ((curFrame->m_poc) <= (lastScenecut + int(windowSize[1]))))<br>+                qp += fwdNonRefQpDelta[1];<br>+            else if (((curFrame->m_poc) > (lastScenecut + int(windowSize[1]))) && ((curFrame->m_poc) <= (lastScenecut + int(windowSize[2]))))<br>+                qp += fwdNonRefQpDelta[2];<br>+            else if (((curFrame->m_poc) > (lastScenecut + int(windowSize[2]))) && ((curFrame->m_poc) <= (lastScenecut + int(windowSize[3]))))<br>+                qp += fwdNonRefQpDelta[3];<br>+            else if (((curFrame->m_poc) > (lastScenecut + int(windowSize[3]))) && ((curFrame->m_poc) <= (lastScenecut + int(windowSize[4]))))<br>+                qp += fwdNonRefQpDelta[4];<br>+            else if (curFrame->m_poc > lastScenecut + int(windowSize[4]))<br>+                qp += fwdNonRefQpDelta[5];<br>         }<br>     }<br> <br>@@ -3428,24 +3424,76 @@ double RateControl::forwardMasking(Frame* curFrame, double q)<br> double RateControl::backwardMasking(Frame* curFrame, double q)<br> {<br>     double qp = x265_qScale2qp(q);<br>-    double fwdRefQpDelta = double(m_param->fwdRefQpDelta);<br>-    double bwdRefQpDelta = double(m_param->bwdRefQpDelta);<br>-    double bwdNonRefQpDelta = double(m_param->bwdNonRefQpDelta);<br>+    uint32_t maxWindowSize = uint32_t((m_param->bwdMaxScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5);<br>+    uint32_t windowSize[6], prevWindow = 0;<br>+    int lastScenecut = m_top->m_rateControl->m_lastScenecut;<br> <br>-    if (curFrame->m_isInsideWindow == BACKWARD_WINDOW)<br>+    double bwdRefQpDelta[6], bwdNonRefQpDelta[6], sliceTypeDelta[6];<br>+    for (int i = 0; i < 6; i++)<br>     {<br>-        if (bwdRefQpDelta < 0)<br>-            bwdRefQpDelta = WINDOW3_DELTA * fwdRefQpDelta;<br>-        double sliceTypeDelta = SLICE_TYPE_DELTA * bwdRefQpDelta;<br>-        if (bwdNonRefQpDelta < 0)<br>-            bwdNonRefQpDelta = bwdRefQpDelta + sliceTypeDelta;<br>+        windowSize[i] = prevWindow + (uint32_t((m_param->bwdScenecutWindow[i] / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5));<br>+        prevWindow = windowSize[i];<br>+        bwdRefQpDelta[i] = double(m_param->bwdRefQpDelta[i]);<br>+        bwdNonRefQpDelta[i] = double(m_param->bwdNonRefQpDelta[i]);<br> <br>+        if (bwdRefQpDelta[i] < 0)<br>+            bwdRefQpDelta[i] = BWD_WINDOW_DELTA * m_param->fwdRefQpDelta[i];<br>+        sliceTypeDelta[i] = SLICE_TYPE_DELTA * bwdRefQpDelta[i];<br>+<br>+        if (bwdNonRefQpDelta[i] < 0)<br>+            bwdNonRefQpDelta[i] = bwdRefQpDelta[i] + sliceTypeDelta[i];<br>+    }<br>+<br>+    if (curFrame->m_isInsideWindow == BACKWARD_WINDOW)<br>+    {<br>         if (curFrame->m_lowres.sliceType == X265_TYPE_P)<br>-            qp += bwdRefQpDelta - sliceTypeDelta;<br>+        {<br>+            //Add offsets corresponding to the window in which the P-frame occurs<br>+            if (curFrame->m_poc >= (lastScenecut - int(windowSize[0])))<br>+                qp += bwdRefQpDelta[0] - sliceTypeDelta[0];<br>+            else if (((curFrame->m_poc) < (lastScenecut - int(windowSize[0]))) && ((curFrame->m_poc) >= (lastScenecut - int(windowSize[1]))))<br>+                qp += bwdRefQpDelta[1] - sliceTypeDelta[1];<br>+            else if (((curFrame->m_poc) < (lastScenecut - int(windowSize[1]))) && ((curFrame->m_poc) >= (lastScenecut - int(windowSize[2]))))<br>+                qp += bwdRefQpDelta[2] - sliceTypeDelta[2];<br>+            else if (((curFrame->m_poc) < (lastScenecut - int(windowSize[2]))) && ((curFrame->m_poc) >= (lastScenecut - int(windowSize[3]))))<br>+                qp += bwdRefQpDelta[3] - sliceTypeDelta[3];<br>+            else if (((curFrame->m_poc) < (lastScenecut - int(windowSize[3]))) && ((curFrame->m_poc) >= (lastScenecut - int(windowSize[4]))))<br>+                qp += bwdRefQpDelta[4] - sliceTypeDelta[4];<br>+            else if (curFrame->m_poc < lastScenecut - int(windowSize[4]))<br>+                qp += bwdRefQpDelta[5] - sliceTypeDelta[5];<br>+        }<br>         else if (curFrame->m_lowres.sliceType == X265_TYPE_BREF)<br>-            qp += bwdRefQpDelta;<br>+        {<br>+            //Add offsets corresponding to the window in which the B-frame occurs<br>+            if (curFrame->m_poc >= (lastScenecut - int(windowSize[0])))<br>+                qp += bwdRefQpDelta[0];<br>+            else if (((curFrame->m_poc) < (lastScenecut - int(windowSize[0]))) && ((curFrame->m_poc) >= (lastScenecut - int(windowSize[1]))))<br>+                qp += bwdRefQpDelta[1];<br>+            else if (((curFrame->m_poc) < (lastScenecut - int(windowSize[1]))) && ((curFrame->m_poc) >= (lastScenecut - int(windowSize[2]))))<br>+                qp += bwdRefQpDelta[2];<br>+            else if (((curFrame->m_poc) < (lastScenecut - int(windowSize[2]))) && ((curFrame->m_poc) >= (lastScenecut - int(windowSize[3]))))<br>+                qp += bwdRefQpDelta[3];<br>+            else if (((curFrame->m_poc) < (lastScenecut - int(windowSize[3]))) && ((curFrame->m_poc) >= (lastScenecut - int(windowSize[4]))))<br>+                qp += bwdRefQpDelta[4];<br>+            else if (curFrame->m_poc < lastScenecut - int(windowSize[4]))<br>+                qp += bwdRefQpDelta[5];<br>+        }<br>         else if (curFrame->m_lowres.sliceType == X265_TYPE_B)<br>-            qp += bwdNonRefQpDelta;<br>+        {<br>+            //Add offsets corresponding to the window in which the b-frame occurs<br>+            if (curFrame->m_poc >= (lastScenecut - int(windowSize[0])))<br>+                qp += bwdNonRefQpDelta[0];<br>+            else if (((curFrame->m_poc) < (lastScenecut - int(windowSize[0]))) && ((curFrame->m_poc) >= (lastScenecut - int(windowSize[1]))))<br>+                qp += bwdNonRefQpDelta[1];<br>+            else if (((curFrame->m_poc) < (lastScenecut - int(windowSize[1]))) && ((curFrame->m_poc) >= (lastScenecut - int(windowSize[2]))))<br>+                qp += bwdNonRefQpDelta[2];<br>+            else if (((curFrame->m_poc) < (lastScenecut - int(windowSize[2]))) && ((curFrame->m_poc) >= (lastScenecut - int(windowSize[3]))))<br>+                qp += bwdNonRefQpDelta[3];<br>+            else if (((curFrame->m_poc) < (lastScenecut - int(windowSize[3]))) && ((curFrame->m_poc) >= (lastScenecut - int(windowSize[4]))))<br>+                qp += bwdNonRefQpDelta[4];<br>+            else if (curFrame->m_poc < lastScenecut - int(windowSize[4]))<br>+                qp += bwdNonRefQpDelta[5];<br>+        }<br>     }<br> <br>     return x265_qp2qScale(qp);<br>diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h<br>index d1734f8ff..e9fd0e182 100644<br>--- a/source/encoder/ratecontrol.h<br>+++ b/source/encoder/ratecontrol.h<br>@@ -47,14 +47,6 @@ struct SPS;<br> #define MIN_AMORTIZE_FRACTION 0.2<br> #define CLIP_DURATION(f) x265_clip3(MIN_FRAME_DURATION, MAX_FRAME_DURATION, f)<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.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>     double coeffMin;<br>diff --git a/source/x265.h b/source/x265.h<br>index 25efb17f1..0f092c5c4 100644<br>--- a/source/x265.h<br>+++ b/source/x265.h<br>@@ -614,6 +614,7 @@ typedef enum<br> #define SLICE_TYPE_DELTA        0.3 /* The offset decremented or incremented for P-frames or b-frames respectively*/<br> #define BACKWARD_WINDOW         1 /* Scenecut window before a scenecut */<br> #define FORWARD_WINDOW          2 /* Scenecut window after a scenecut */<br>+#define BWD_WINDOW_DELTA        0.4<br> <br> typedef struct x265_cli_csp<br> {<br>@@ -1886,14 +1887,15 @@ typedef struct x265_param<br> <br>     /* The duration(in milliseconds) for which there is a reduction in the bits spent on the inter-frames after a scenecut<br>      * by increasing their QP, when bEnableSceneCutAwareQp is 1 or 3. Default is 500ms.*/<br>-    int       fwdScenecutWindow;<br>+    int       fwdMaxScenecutWindow;<br>+    int       fwdScenecutWindow[6];<br> <br>     /* The offset by which QP is incremented for inter-frames after a scenecut when bEnableSceneCutAwareQp is 1 or 3.<br>      * Default is +5. */<br>-    double    fwdRefQpDelta;<br>+    double    fwdRefQpDelta[6];<br> <br>     /* The offset by which QP is incremented for non-referenced inter-frames after a scenecut when bEnableSceneCutAwareQp is 1 or 3. */<br>-    double    fwdNonRefQpDelta;<br>+    double    fwdNonRefQpDelta[6];<br> <br>     /* Enables histogram based scenecut detection algorithm to detect scenecuts. Default disabled */<br>     int       bHistBasedSceneCut;<br>@@ -1961,13 +1963,14 @@ typedef struct x265_param<br> <br>     /* The duration(in milliseconds) for which there is a reduction in the bits spent on the inter-frames before a scenecut<br>      * by increasing their QP, when bEnableSceneCutAwareQp is 2 or 3. Default is 100ms.*/<br>-    int       bwdScenecutWindow;<br>+    int       bwdMaxScenecutWindow;<br>+    int       bwdScenecutWindow[6];<br> <br>     /* The offset by which QP is incremented for inter-frames before a scenecut when bEnableSceneCutAwareQp is 2 or 3. */<br>-    double    bwdRefQpDelta;<br>+    double    bwdRefQpDelta[6];<br> <br>     /* The offset by which QP is incremented for non-referenced inter-frames before a scenecut when bEnableSceneCutAwareQp is 2 or 3. */<br>-    double    bwdNonRefQpDelta;<br>+    double    bwdNonRefQpDelta[6];<br> <br>     /* Specify combinations of color primaries, transfer characteristics, color matrix,<br>     * range of luma and chroma signals, and chroma sample location. This has higher<br>-- <br>2.18.0.windows.1<br><br><div><br></div>-- <br><div dir="ltr" class="gmail_signature" 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>