[x265] [PATCH] Add command line support for scene cut aware qp feature
Kirithika Kalirathnam
kirithika at multicorewareinc.com
Fri Jan 13 09:32:20 UTC 2023
>From e3402211edcd19acf172d2597ff65890d7fc227e Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Thu, 12 Jan 2023 15:50:58 +0530
Subject: [PATCH] Add command line support for scene cut aware qp feature
This commit enables the scene cut aware qp feature through the command line
parameters
--scenecut-aware-qp and --masking-strength.It doesn't disable the scenecut
aware qp configuration via config file.
User can choose between either of these two ways to configure
scenecut-aware-qp.
---
doc/reST/cli.rst | 3 +-
source/CMakeLists.txt | 2 +-
source/common/param.cpp | 290 ++++++++++++++++++++--------------------
source/common/param.h | 1 +
4 files changed, 151 insertions(+), 145 deletions(-)
diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
index f1d9fa36c..a98c860d0 100755
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -1987,7 +1987,6 @@ Quality, rate control and rate distortion options
It reduces the bits spent on the inter-frames within the scenecut window
before and after a scenecut by increasing their QP in ratecontrol pass2
algorithm
without any deterioration in visual quality.
- It is mentioned inside :option:`--scenecut-qp-config` file.
:option:`--scenecut-aware-qp` works only with --pass 2. Default 0.
+-------+---------------------------------------------------------------+
@@ -2010,7 +2009,7 @@ Quality, rate control and rate distortion options
Comma separated list of values which specifies the duration and offset
for the QP increment for inter-frames when :option:`--scenecut-aware-qp`
- is enabled. It is mentioned inside :option:`--scenecut-qp-config` file.
+ is enabled.
When :option:`--scenecut-aware-qp` is:
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index 04ceea0ec..4c3274f63 100755
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -29,7 +29,7 @@ option(NATIVE_BUILD "Target the build CPU" OFF)
option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)
mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)
# X265_BUILD must be incremented each time the public API is changed
-set(X265_BUILD 206)
+set(X265_BUILD 207)
configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
"${PROJECT_BINARY_DIR}/x265.def")
configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff --git a/source/common/param.cpp b/source/common/param.cpp
index fe85d8726..8c32fafa2 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -711,148 +711,7 @@ int x265_scenecut_aware_qp_param_parse(x265_param* p,
const char* name, const ch
#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[6];
- double refQpDelta1[6], nonRefQpDelta1[6];
- if (p->bEnableSceneCutAwareQp == FORWARD)
- {
- if (3 == sscanf(value, "%d,%lf,%lf", &window1[0],
&refQpDelta1[0], &nonRefQpDelta1[0]))
- {
- if (window1[0] > 0)
- p->fwdMaxScenecutWindow = window1[0];
- if (refQpDelta1[0] > 0)
- p->fwdRefQpDelta[0] = refQpDelta1[0];
- if (nonRefQpDelta1[0] > 0)
- p->fwdNonRefQpDelta[0] = nonRefQpDelta1[0];
-
- p->fwdScenecutWindow[0] = p->fwdMaxScenecutWindow / 6;
- for (int i = 1; i < 6; i++)
- {
- p->fwdScenecutWindow[i] = p->fwdMaxScenecutWindow / 6;
- p->fwdRefQpDelta[i] = p->fwdRefQpDelta[i - 1] - (0.15
* p->fwdRefQpDelta[i - 1]);
- p->fwdNonRefQpDelta[i] = p->fwdNonRefQpDelta[i - 1] -
(0.15 * p->fwdNonRefQpDelta[i - 1]);
- }
- }
- else if (18 == sscanf(value,
"%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf"
- , &window1[0], &refQpDelta1[0], &nonRefQpDelta1[0],
&window1[1], &refQpDelta1[1], &nonRefQpDelta1[1]
- , &window1[2], &refQpDelta1[2], &nonRefQpDelta1[2],
&window1[3], &refQpDelta1[3], &nonRefQpDelta1[3]
- , &window1[4], &refQpDelta1[4], &nonRefQpDelta1[4],
&window1[5], &refQpDelta1[5], &nonRefQpDelta1[5]))
- {
- p->fwdMaxScenecutWindow = 0;
- for (int i = 0; i < 6; i++)
- {
- p->fwdScenecutWindow[i] = window1[i];
- p->fwdRefQpDelta[i] = refQpDelta1[i];
- p->fwdNonRefQpDelta[i] = nonRefQpDelta1[i];
- p->fwdMaxScenecutWindow += p->fwdScenecutWindow[i];
- }
- }
- 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[0],
&refQpDelta1[0], &nonRefQpDelta1[0]))
- {
- if (window1[0] > 0)
- p->bwdMaxScenecutWindow = window1[0];
- if (refQpDelta1[0] > 0)
- p->bwdRefQpDelta[0] = refQpDelta1[0];
- if (nonRefQpDelta1[0] > 0)
- p->bwdNonRefQpDelta[0] = nonRefQpDelta1[0];
-
- p->bwdScenecutWindow[0] = p->bwdMaxScenecutWindow / 6;
- for (int i = 1; i < 6; i++)
- {
- p->bwdScenecutWindow[i] = p->bwdMaxScenecutWindow / 6;
- p->bwdRefQpDelta[i] = p->bwdRefQpDelta[i - 1] - (0.15
* p->bwdRefQpDelta[i - 1]);
- p->bwdNonRefQpDelta[i] = p->bwdNonRefQpDelta[i - 1] -
(0.15 * p->bwdNonRefQpDelta[i - 1]);
- }
- }
- else if (18 == sscanf(value,
"%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf"
- , &window1[0], &refQpDelta1[0], &nonRefQpDelta1[0],
&window1[1], &refQpDelta1[1], &nonRefQpDelta1[1]
- , &window1[2], &refQpDelta1[2], &nonRefQpDelta1[2],
&window1[3], &refQpDelta1[3], &nonRefQpDelta1[3]
- , &window1[4], &refQpDelta1[4], &nonRefQpDelta1[4],
&window1[5], &refQpDelta1[5], &nonRefQpDelta1[5]))
- {
- p->bwdMaxScenecutWindow = 0;
- for (int i = 0; i < 6; i++)
- {
- p->bwdScenecutWindow[i] = window1[i];
- p->bwdRefQpDelta[i] = refQpDelta1[i];
- p->bwdNonRefQpDelta[i] = nonRefQpDelta1[i];
- p->bwdMaxScenecutWindow += p->bwdScenecutWindow[i];
- }
- }
- 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[6];
- double refQpDelta2[6], nonRefQpDelta2[6];
- if (6 == sscanf(value, "%d,%lf,%lf,%d,%lf,%lf", &window1[0],
&refQpDelta1[0], &nonRefQpDelta1[0], &window2[0], &refQpDelta2[0],
&nonRefQpDelta2[0]))
- {
- if (window1[0] > 0)
- p->fwdMaxScenecutWindow = window1[0];
- if (refQpDelta1[0] > 0)
- p->fwdRefQpDelta[0] = refQpDelta1[0];
- if (nonRefQpDelta1[0] > 0)
- p->fwdNonRefQpDelta[0] = nonRefQpDelta1[0];
- if (window2[0] > 0)
- p->bwdMaxScenecutWindow = window2[0];
- if (refQpDelta2[0] > 0)
- p->bwdRefQpDelta[0] = refQpDelta2[0];
- if (nonRefQpDelta2[0] > 0)
- p->bwdNonRefQpDelta[0] = nonRefQpDelta2[0];
-
- p->fwdScenecutWindow[0] = p->fwdMaxScenecutWindow / 6;
- p->bwdScenecutWindow[0] = p->bwdMaxScenecutWindow / 6;
- for (int i = 1; i < 6; i++)
- {
- p->fwdScenecutWindow[i] = p->fwdMaxScenecutWindow / 6;
- p->bwdScenecutWindow[i] = p->bwdMaxScenecutWindow / 6;
- p->fwdRefQpDelta[i] = p->fwdRefQpDelta[i - 1] - (0.15
* p->fwdRefQpDelta[i - 1]);
- p->fwdNonRefQpDelta[i] = p->fwdNonRefQpDelta[i - 1] -
(0.15 * p->fwdNonRefQpDelta[i - 1]);
- p->bwdRefQpDelta[i] = p->bwdRefQpDelta[i - 1] - (0.15
* p->bwdRefQpDelta[i - 1]);
- p->bwdNonRefQpDelta[i] = p->bwdNonRefQpDelta[i - 1] -
(0.15 * p->bwdNonRefQpDelta[i - 1]);
- }
- }
- else if (36 == sscanf(value,
"%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf"
- , &window1[0], &refQpDelta1[0], &nonRefQpDelta1[0],
&window1[1], &refQpDelta1[1], &nonRefQpDelta1[1]
- , &window1[2], &refQpDelta1[2], &nonRefQpDelta1[2],
&window1[3], &refQpDelta1[3], &nonRefQpDelta1[3]
- , &window1[4], &refQpDelta1[4], &nonRefQpDelta1[4],
&window1[5], &refQpDelta1[5], &nonRefQpDelta1[5]
- , &window2[0], &refQpDelta2[0], &nonRefQpDelta2[0],
&window2[1], &refQpDelta2[1], &nonRefQpDelta2[1]
- , &window2[2], &refQpDelta2[2], &nonRefQpDelta2[2],
&window2[3], &refQpDelta2[3], &nonRefQpDelta2[3]
- , &window2[4], &refQpDelta2[4], &nonRefQpDelta2[4],
&window2[5], &refQpDelta2[5], &nonRefQpDelta2[5]))
- {
- p->fwdMaxScenecutWindow = 0;
- p->bwdMaxScenecutWindow = 0;
- for (int i = 0; i < 6; i++)
- {
- p->fwdScenecutWindow[i] = window1[i];
- p->fwdRefQpDelta[i] = refQpDelta1[i];
- p->fwdNonRefQpDelta[i] = nonRefQpDelta1[i];
- p->bwdScenecutWindow[i] = window2[i];
- p->bwdRefQpDelta[i] = refQpDelta2[i];
- p->bwdNonRefQpDelta[i] = nonRefQpDelta2[i];
- p->fwdMaxScenecutWindow += p->fwdScenecutWindow[i];
- p->bwdMaxScenecutWindow += p->bwdScenecutWindow[i];
- }
- }
- else
- {
- x265_log(NULL, X265_LOG_ERROR, "Specify all the necessary
offsets for masking-strength \n");
- bError = true;
- }
- }
- }
+ OPT("masking-strength") bError = parseMaskingStrength(p, value);
else
return X265_PARAM_BAD_NAME;
#undef OPT
@@ -1534,6 +1393,8 @@ 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") bError |= parseMaskingStrength(p, value);
OPT("field") p->bField = atobool( value );
OPT("cll") p->bEmitCLL = atobool(value);
OPT("frame-dup") p->bEnableFrameDuplication = atobool(value);
@@ -2548,6 +2409,151 @@ bool parseLambdaFile(x265_param* param)
return false;
}
+bool parseMaskingStrength(x265_param* p, const char* value)
+{
+ bool bError = false;
+ int window1[6];
+ double refQpDelta1[6], nonRefQpDelta1[6];
+ if (p->bEnableSceneCutAwareQp == FORWARD)
+ {
+ if (3 == sscanf(value, "%d,%lf,%lf", &window1[0], &refQpDelta1[0],
&nonRefQpDelta1[0]))
+ {
+ if (window1[0] > 0)
+ p->fwdMaxScenecutWindow = window1[0];
+ if (refQpDelta1[0] > 0)
+ p->fwdRefQpDelta[0] = refQpDelta1[0];
+ if (nonRefQpDelta1[0] > 0)
+ p->fwdNonRefQpDelta[0] = nonRefQpDelta1[0];
+
+ p->fwdScenecutWindow[0] = p->fwdMaxScenecutWindow / 6;
+ for (int i = 1; i < 6; i++)
+ {
+ p->fwdScenecutWindow[i] = p->fwdMaxScenecutWindow / 6;
+ p->fwdRefQpDelta[i] = p->fwdRefQpDelta[i - 1] - (0.15 *
p->fwdRefQpDelta[i - 1]);
+ p->fwdNonRefQpDelta[i] = p->fwdNonRefQpDelta[i - 1] -
(0.15 * p->fwdNonRefQpDelta[i - 1]);
+ }
+ }
+ else if (18 == sscanf(value,
"%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf"
+ , &window1[0], &refQpDelta1[0], &nonRefQpDelta1[0],
&window1[1], &refQpDelta1[1], &nonRefQpDelta1[1]
+ , &window1[2], &refQpDelta1[2], &nonRefQpDelta1[2],
&window1[3], &refQpDelta1[3], &nonRefQpDelta1[3]
+ , &window1[4], &refQpDelta1[4], &nonRefQpDelta1[4],
&window1[5], &refQpDelta1[5], &nonRefQpDelta1[5]))
+ {
+ p->fwdMaxScenecutWindow = 0;
+ for (int i = 0; i < 6; i++)
+ {
+ p->fwdScenecutWindow[i] = window1[i];
+ p->fwdRefQpDelta[i] = refQpDelta1[i];
+ p->fwdNonRefQpDelta[i] = nonRefQpDelta1[i];
+ p->fwdMaxScenecutWindow += p->fwdScenecutWindow[i];
+ }
+ }
+ 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[0], &refQpDelta1[0],
&nonRefQpDelta1[0]))
+ {
+ if (window1[0] > 0)
+ p->bwdMaxScenecutWindow = window1[0];
+ if (refQpDelta1[0] > 0)
+ p->bwdRefQpDelta[0] = refQpDelta1[0];
+ if (nonRefQpDelta1[0] > 0)
+ p->bwdNonRefQpDelta[0] = nonRefQpDelta1[0];
+
+ p->bwdScenecutWindow[0] = p->bwdMaxScenecutWindow / 6;
+ for (int i = 1; i < 6; i++)
+ {
+ p->bwdScenecutWindow[i] = p->bwdMaxScenecutWindow / 6;
+ p->bwdRefQpDelta[i] = p->bwdRefQpDelta[i - 1] - (0.15 *
p->bwdRefQpDelta[i - 1]);
+ p->bwdNonRefQpDelta[i] = p->bwdNonRefQpDelta[i - 1] -
(0.15 * p->bwdNonRefQpDelta[i - 1]);
+ }
+ }
+ else if (18 == sscanf(value,
"%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf"
+ , &window1[0], &refQpDelta1[0], &nonRefQpDelta1[0],
&window1[1], &refQpDelta1[1], &nonRefQpDelta1[1]
+ , &window1[2], &refQpDelta1[2], &nonRefQpDelta1[2],
&window1[3], &refQpDelta1[3], &nonRefQpDelta1[3]
+ , &window1[4], &refQpDelta1[4], &nonRefQpDelta1[4],
&window1[5], &refQpDelta1[5], &nonRefQpDelta1[5]))
+ {
+ p->bwdMaxScenecutWindow = 0;
+ for (int i = 0; i < 6; i++)
+ {
+ p->bwdScenecutWindow[i] = window1[i];
+ p->bwdRefQpDelta[i] = refQpDelta1[i];
+ p->bwdNonRefQpDelta[i] = nonRefQpDelta1[i];
+ p->bwdMaxScenecutWindow += p->bwdScenecutWindow[i];
+ }
+ }
+ 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[6];
+ double refQpDelta2[6], nonRefQpDelta2[6];
+ if (6 == sscanf(value, "%d,%lf,%lf,%d,%lf,%lf", &window1[0],
&refQpDelta1[0], &nonRefQpDelta1[0], &window2[0], &refQpDelta2[0],
&nonRefQpDelta2[0]))
+ {
+ if (window1[0] > 0)
+ p->fwdMaxScenecutWindow = window1[0];
+ if (refQpDelta1[0] > 0)
+ p->fwdRefQpDelta[0] = refQpDelta1[0];
+ if (nonRefQpDelta1[0] > 0)
+ p->fwdNonRefQpDelta[0] = nonRefQpDelta1[0];
+ if (window2[0] > 0)
+ p->bwdMaxScenecutWindow = window2[0];
+ if (refQpDelta2[0] > 0)
+ p->bwdRefQpDelta[0] = refQpDelta2[0];
+ if (nonRefQpDelta2[0] > 0)
+ p->bwdNonRefQpDelta[0] = nonRefQpDelta2[0];
+
+ p->fwdScenecutWindow[0] = p->fwdMaxScenecutWindow / 6;
+ p->bwdScenecutWindow[0] = p->bwdMaxScenecutWindow / 6;
+ for (int i = 1; i < 6; i++)
+ {
+ p->fwdScenecutWindow[i] = p->fwdMaxScenecutWindow / 6;
+ p->bwdScenecutWindow[i] = p->bwdMaxScenecutWindow / 6;
+ p->fwdRefQpDelta[i] = p->fwdRefQpDelta[i - 1] - (0.15 *
p->fwdRefQpDelta[i - 1]);
+ p->fwdNonRefQpDelta[i] = p->fwdNonRefQpDelta[i - 1] -
(0.15 * p->fwdNonRefQpDelta[i - 1]);
+ p->bwdRefQpDelta[i] = p->bwdRefQpDelta[i - 1] - (0.15 *
p->bwdRefQpDelta[i - 1]);
+ p->bwdNonRefQpDelta[i] = p->bwdNonRefQpDelta[i - 1] -
(0.15 * p->bwdNonRefQpDelta[i - 1]);
+ }
+ }
+ else if (36 == sscanf(value,
"%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf,%d,%lf,%lf"
+ , &window1[0], &refQpDelta1[0], &nonRefQpDelta1[0],
&window1[1], &refQpDelta1[1], &nonRefQpDelta1[1]
+ , &window1[2], &refQpDelta1[2], &nonRefQpDelta1[2],
&window1[3], &refQpDelta1[3], &nonRefQpDelta1[3]
+ , &window1[4], &refQpDelta1[4], &nonRefQpDelta1[4],
&window1[5], &refQpDelta1[5], &nonRefQpDelta1[5]
+ , &window2[0], &refQpDelta2[0], &nonRefQpDelta2[0],
&window2[1], &refQpDelta2[1], &nonRefQpDelta2[1]
+ , &window2[2], &refQpDelta2[2], &nonRefQpDelta2[2],
&window2[3], &refQpDelta2[3], &nonRefQpDelta2[3]
+ , &window2[4], &refQpDelta2[4], &nonRefQpDelta2[4],
&window2[5], &refQpDelta2[5], &nonRefQpDelta2[5]))
+ {
+ p->fwdMaxScenecutWindow = 0;
+ p->bwdMaxScenecutWindow = 0;
+ for (int i = 0; i < 6; i++)
+ {
+ p->fwdScenecutWindow[i] = window1[i];
+ p->fwdRefQpDelta[i] = refQpDelta1[i];
+ p->fwdNonRefQpDelta[i] = nonRefQpDelta1[i];
+ p->bwdScenecutWindow[i] = window2[i];
+ p->bwdRefQpDelta[i] = refQpDelta2[i];
+ p->bwdNonRefQpDelta[i] = nonRefQpDelta2[i];
+ p->fwdMaxScenecutWindow += p->fwdScenecutWindow[i];
+ p->bwdMaxScenecutWindow += p->bwdScenecutWindow[i];
+ }
+ }
+ else
+ {
+ x265_log(NULL, X265_LOG_ERROR, "Specify all the necessary
offsets for masking-strength \n");
+ bError = true;
+ }
+ }
+ return bError;
+}
+
void x265_copy_params(x265_param* dst, x265_param* src)
{
dst->cpuid = src->cpuid;
diff --git a/source/common/param.h b/source/common/param.h
index 7808947f6..f504ec9e4 100644
--- a/source/common/param.h
+++ b/source/common/param.h
@@ -38,6 +38,7 @@ void setParamAspectRatio(x265_param *p, int width, int
height);
void getParamAspectRatio(x265_param *p, int& width, int& height);
bool parseLambdaFile(x265_param *param);
void x265_copy_params(x265_param* dst, x265_param* src);
+bool parseMaskingStrength(x265_param* p, const char* value);
/* this table is kept internal to avoid confusion, since log level indices
start at -1 */
static const char * const logLevelNames[] = { "none", "error", "warning",
"info", "debug", "full", 0 };
--
2.28.0.windows.1
*Thanks,*
*Kirithika*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20230113/8982467c/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch-for-bbaq-CLI.diff
Type: application/octet-stream
Size: 19306 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20230113/8982467c/attachment-0001.obj>
More information about the x265-devel
mailing list