[x265] [PATCH EXPERIMENTAL] api: make RDOQ level externally configurable, make two levels visible
Steve Borho
steve at borho.org
Thu Feb 26 23:38:16 CET 2015
# HG changeset patch
# User Steve Borho <steve at borho.org>
# Date 1424990270 21600
# Thu Feb 26 16:37:50 2015 -0600
# Node ID 6ca5304a89371341f5e1cd5888a3119a36e8e8f5
# Parent 394c2f94a2dc5d0e9e6d1c063361b19b86b88cf6
api: make RDOQ level externally configurable, make two levels visible
This commit doesn't change any preset defaults, but it does allow much more
flexibility - a user can chose to enable rdoq and psy-rdoq at fast presets if
they so chose. And in noisy situations a user may decide to lower rdoq level to
1 to reduce decimation (psy-rdoq is a blunt hammer for this purpose)
This commit does change --tune grain to use --rdoqLevel 1 so --tune grain will
be effective at all RD levels and avoids the coding group decimation logic
within RDOQ
diff -r 394c2f94a2dc -r 6ca5304a8937 doc/reST/cli.rst
--- a/doc/reST/cli.rst Thu Feb 26 15:26:39 2015 -0600
+++ b/doc/reST/cli.rst Thu Feb 26 16:37:50 2015 -0600
@@ -613,6 +613,28 @@
Options which affect the transform unit quad-tree, sometimes referred to
as the residual quad-tree (RQT).
+.. option:: --rdoq-level <0|1|2>, --no-rdoq-level
+
+ Specify the amount of rate-distortion analysis to use within
+ quantization::
+
+ At level 0 rate-distortion cost is not considered in quant
+
+ At level 1 rate-distortion cost is used to find optimal rounding
+ values for each level (and allows psy-rdoq to be effective). It
+ trades-off the signaling cost of the coefficient vs its post-inverse
+ quant distortion from the pre-quant coefficient. When
+ :option:`--psy-rdoq` is enabled, this formula is biased in favor of
+ more energy in the residual (larger coefficient absolute levels)
+
+ At level 2 rate-distortion cost is used to make decimate decisions
+ on each 4x4 coding group, including the cost of signaling the group
+ within the group bitmap. If the total distortion of not signaling
+ the entire coding group is less than the rate cost, the block is
+ decimated. Psy-rdoq is less effective at preserving energy when
+ RDOQ is at level 2, since it only has influence over the level
+ distortion costs.
+
.. option:: --tu-intra-depth <1..4>
The transform unit (residual) quad-tree begins with the same depth
@@ -829,8 +851,8 @@
inter prediction.
:option:`--psy-rdoq` will adjust the distortion cost used in
-rate-distortion optimized quantization (RDO quant), enabled in
-:option:`--rd` 4 and above, favoring the preservation of energy in the
+rate-distortion optimized quantization (RDO quant), enabled by
+:option:`--rdoq-level` 1 or 2, favoring the preservation of energy in the
reconstructed image. :option:`--psy-rdoq` prevents RDOQ from blurring
all of the encoding options which psy-rd has to chose from. At low
strength levels, psy-rdoq will influence the quantization level
@@ -878,9 +900,8 @@
Influence rate distortion optimized quantization by favoring higher
energy in the reconstructed image. This generally improves perceived
visual quality at the cost of lower quality metric scores. It only
- has effect on slower presets which use RDO Quantization
- (:option:`--rd` 4, 5 and 6). 1.0 is a typical value. High values can
- be beneficial in preserving high-frequency detail like film grain.
+ has effect when :option:`--rdoq-level` is 1 or 2. High values can
+ be beneficial in preserving high-frequency detail like film grain.
Default: 1.0
**Range of values:** 0 .. 50.0
diff -r 394c2f94a2dc -r 6ca5304a8937 doc/reST/presets.rst
--- a/doc/reST/presets.rst Thu Feb 26 15:26:39 2015 -0600
+++ b/doc/reST/presets.rst Thu Feb 26 16:37:50 2015 -0600
@@ -66,6 +66,8 @@
+--------------+-----------+-----------+----------+--------+------+--------+------+--------+----------+---------+
| rdLevel | 2 | 2 | 2 | 2 | 2 | 3 | 4 | 6 | 6 | 6 |
+--------------+-----------+-----------+----------+--------+------+--------+------+--------+----------+---------+
+| rdoq-level | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 2 | 2 | 2 |
++--------------+-----------+-----------+----------+--------+------+--------+------+--------+----------+---------+
| tu-intra | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 3 | 4 |
+--------------+-----------+-----------+----------+--------+------+--------+------+--------+----------+---------+
| tu-inter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 3 | 4 |
@@ -114,13 +116,9 @@
modes which preserve high frequency noise:
* :option:`--psy-rd` 0.5
+ * :option:`--rdoq-level` 1
* :option:`--psy-rdoq` 30
-.. Note::
-
- --psy-rdoq is only effective when RDOQuant is enabled, which is at
- RD levels 4, 5, and 6 (presets slow and below).
-
It lowers the strength of adaptive quantization, so residual energy can
be more evenly distributed across the (noisy) picture:
diff -r 394c2f94a2dc -r 6ca5304a8937 source/CMakeLists.txt
--- a/source/CMakeLists.txt Thu Feb 26 15:26:39 2015 -0600
+++ b/source/CMakeLists.txt Thu Feb 26 16:37:50 2015 -0600
@@ -21,7 +21,7 @@
include(CheckCXXCompilerFlag)
# X265_BUILD must be incremented each time the public API is changed
-set(X265_BUILD 47)
+set(X265_BUILD 48)
configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
"${PROJECT_BINARY_DIR}/x265.def")
configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff -r 394c2f94a2dc -r 6ca5304a8937 source/common/param.cpp
--- a/source/common/param.cpp Thu Feb 26 15:26:39 2015 -0600
+++ b/source/common/param.cpp Thu Feb 26 16:37:50 2015 -0600
@@ -320,6 +320,7 @@
param->bEnableRectInter = 1;
param->lookaheadDepth = 25;
param->rdLevel = 4;
+ param->rdoqLevel = 2;
param->subpelRefine = 3;
param->maxNumMergeCand = 3;
param->searchMethod = X265_STAR_SEARCH;
@@ -334,6 +335,7 @@
param->tuQTMaxInterDepth = 2;
param->tuQTMaxIntraDepth = 2;
param->rdLevel = 6;
+ param->rdoqLevel = 2;
param->subpelRefine = 3;
param->maxNumMergeCand = 3;
param->searchMethod = X265_STAR_SEARCH;
@@ -349,6 +351,7 @@
param->tuQTMaxInterDepth = 3;
param->tuQTMaxIntraDepth = 3;
param->rdLevel = 6;
+ param->rdoqLevel = 2;
param->subpelRefine = 4;
param->maxNumMergeCand = 4;
param->searchMethod = X265_STAR_SEARCH;
@@ -366,6 +369,7 @@
param->tuQTMaxInterDepth = 4;
param->tuQTMaxIntraDepth = 4;
param->rdLevel = 6;
+ param->rdoqLevel = 2;
param->subpelRefine = 5;
param->maxNumMergeCand = 5;
param->searchMethod = X265_STAR_SEARCH;
@@ -416,6 +420,7 @@
param->deblockingFilterBetaOffset = -2;
param->deblockingFilterTCOffset = -2;
param->bIntraInBFrames = 0;
+ param->rdoqLevel = 1;
param->psyRdoq = 30;
param->psyRd = 0.5;
param->rc.ipFactor = 1.1;
@@ -629,6 +634,17 @@
OPT("cbqpoffs") p->cbQpOffset = atoi(value);
OPT("crqpoffs") p->crQpOffset = atoi(value);
OPT("rd") p->rdLevel = atoi(value);
+ OPT2("rdoq", "rdoq-level")
+ {
+ int bval = atobool(value);
+ if (bError || bval)
+ {
+ bError = false;
+ p->rdoqLevel = atoi(value);
+ }
+ else
+ p->rdoqLevel = 0;
+ }
OPT("psy-rd")
{
int bval = atobool(value);
@@ -1034,6 +1050,8 @@
"Rate control mode is out of range");
CHECK(param->rdLevel < 0 || param->rdLevel > 6,
"RD Level is out of range");
+ CHECK(param->rdoqLevel < 0 || param->rdoqLevel > 2,
+ "RDOQ Level is out of range");
CHECK(param->bframes > param->lookaheadDepth && !param->rc.bStatRead,
"Lookahead depth must be greater than the max consecutive bframe count");
CHECK(param->bframes < 0,
@@ -1251,7 +1269,7 @@
#define TOOLOPT(FLAG, STR) if (FLAG) fprintf(stderr, "%s ", STR)
TOOLOPT(param->bEnableRectInter, "rect");
TOOLOPT(param->bEnableAMP, "amp");
- fprintf(stderr, "rd=%d ", param->rdLevel);
+ fprintf(stderr, "rd=%d rdoq=%d ", param->rdLevel, param->rdoqLevel);
if (param->psyRd > 0.)
fprintf(stderr, "psy-rd=%.2lf ", param->psyRd);
if (param->psyRdoq > 0.)
diff -r 394c2f94a2dc -r 6ca5304a8937 source/common/quant.cpp
--- a/source/common/quant.cpp Thu Feb 26 15:26:39 2015 -0600
+++ b/source/common/quant.cpp Thu Feb 26 16:37:50 2015 -0600
@@ -194,12 +194,12 @@
m_nr = NULL;
}
-bool Quant::init(bool useRDOQ, double psyScale, const ScalingList& scalingList, Entropy& entropy)
+bool Quant::init(int rdoqLevel, double psyScale, const ScalingList& scalingList, Entropy& entropy)
{
m_entropyCoder = &entropy;
- m_useRDOQ = useRDOQ;
+ m_rdoqLevel = rdoqLevel;
m_psyRdoqScale = (int64_t)(psyScale * 256.0);
- m_scalingList = &scalingList;
+ m_scalingList = &scalingList;
m_resiDctCoeff = X265_MALLOC(int16_t, MAX_TR_SIZE * MAX_TR_SIZE * 2);
m_fencDctCoeff = m_resiDctCoeff + (MAX_TR_SIZE * MAX_TR_SIZE);
m_fencShortBuf = X265_MALLOC(int16_t, MAX_TR_SIZE * MAX_TR_SIZE);
@@ -416,7 +416,7 @@
}
}
- if (m_useRDOQ)
+ if (m_rdoqLevel)
return rdoQuant(cu, coeff, log2TrSize, ttype, absPartIdx, usePsy);
else
{
@@ -825,7 +825,7 @@
costCoeffGroupSig[cgScanPos] = SIGCOST(estBitsSbac.significantCoeffGroupBits[sigCtx][1]);
totalRdCost += costCoeffGroupSig[cgScanPos]; /* add the cost of 1 bit in significant CG bitmap */
- if (costZeroCG < totalRdCost)
+ if (costZeroCG < totalRdCost && m_rdoqLevel > 1)
{
sigCoeffGroupFlag64 &= ~cgBlkPosMask;
totalRdCost = costZeroCG;
diff -r 394c2f94a2dc -r 6ca5304a8937 source/common/quant.h
--- a/source/common/quant.h Thu Feb 26 15:26:39 2015 -0600
+++ b/source/common/quant.h Thu Feb 26 16:37:50 2015 -0600
@@ -81,7 +81,7 @@
QpParam m_qpParam[3];
- bool m_useRDOQ;
+ int m_rdoqLevel;
int64_t m_psyRdoqScale;
int16_t* m_resiDctCoeff;
int16_t* m_fencDctCoeff;
@@ -99,7 +99,7 @@
~Quant();
/* one-time setup */
- bool init(bool useRDOQ, double psyScale, const ScalingList& scalingList, Entropy& entropy);
+ bool init(int rdoqLevel, double psyScale, const ScalingList& scalingList, Entropy& entropy);
bool allocNoiseReduction(const x265_param& param);
/* CU setup */
diff -r 394c2f94a2dc -r 6ca5304a8937 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Thu Feb 26 15:26:39 2015 -0600
+++ b/source/encoder/encoder.cpp Thu Feb 26 16:37:50 2015 -0600
@@ -1555,12 +1555,12 @@
}
p->keyframeMin = X265_MAX(1, X265_MIN(p->keyframeMin, p->keyframeMax / 2 + 1));
- if (p->bBPyramid && !p->bframes)
+ if (!p->bframes)
p->bBPyramid = 0;
+ if (!p->rdoqLevel)
+ p->psyRdoq = 0;
/* Disable features which are not supported by the current RD level */
- if (p->rdLevel < 4)
- p->psyRdoq = 0; /* impossible */
if (p->rdLevel < 3)
{
if (p->bCULossless) /* impossible */
diff -r 394c2f94a2dc -r 6ca5304a8937 source/encoder/search.cpp
--- a/source/encoder/search.cpp Thu Feb 26 15:26:39 2015 -0600
+++ b/source/encoder/search.cpp Thu Feb 26 16:37:50 2015 -0600
@@ -72,14 +72,14 @@
{
uint32_t maxLog2CUSize = g_log2Size[param.maxCUSize];
m_param = ¶m;
- m_bEnableRDOQ = param.rdLevel >= 4;
+ m_bEnableRDOQ = !!param.rdoqLevel;
m_bFrameParallel = param.frameNumThreads > 1;
m_numLayers = g_log2Size[param.maxCUSize] - 2;
m_rdCost.setPsyRdScale(param.psyRd);
m_me.init(param.searchMethod, param.subpelRefine, param.internalCsp);
- bool ok = m_quant.init(m_bEnableRDOQ, param.psyRdoq, scalingList, m_entropyCoder);
+ bool ok = m_quant.init(param.rdoqLevel, param.psyRdoq, scalingList, m_entropyCoder);
if (m_param->noiseReductionIntra || m_param->noiseReductionInter)
ok &= m_quant.allocNoiseReduction(param);
diff -r 394c2f94a2dc -r 6ca5304a8937 source/x265.h
--- a/source/x265.h Thu Feb 26 15:26:39 2015 -0600
+++ b/source/x265.h Thu Feb 26 16:37:50 2015 -0600
@@ -660,6 +660,15 @@
* compressed by the DCT transforms, at the expense of much more compute */
uint32_t tuQTMaxIntraDepth;
+ /* Set the amount of rate-distortion analysis to use within quant. 0 implies
+ * no rate-distortion optimization. At level 1 rate-distortion cost is used to
+ * find optimal rounding values for each level (and allows psy-rdoq to be
+ * enabled). At level 2 rate-distortion cost is used to make decimate decisions
+ * on each 4x4 coding group (including the cost of signaling the group within
+ * the group bitmap). Psy-rdoq is less effective at preserving energy when
+ * RDOQ is at level 2 */
+ int rdoqLevel;
+
/* Enable the implicit signaling of the sign bit of the last coefficient of
* each transform unit. This saves one bit per TU at the expense of figuring
* out which coefficient can be toggled with the least distortion.
diff -r 394c2f94a2dc -r 6ca5304a8937 source/x265cli.h
--- a/source/x265cli.h Thu Feb 26 15:26:39 2015 -0600
+++ b/source/x265cli.h Thu Feb 26 16:37:50 2015 -0600
@@ -139,6 +139,8 @@
{ "cbqpoffs", required_argument, NULL, 0 },
{ "crqpoffs", required_argument, NULL, 0 },
{ "rd", required_argument, NULL, 0 },
+ { "rdoq-level", required_argument, NULL, 0 },
+ { "no-rdoq-level", no_argument, NULL, 0 },
{ "psy-rd", required_argument, NULL, 0 },
{ "psy-rdoq", required_argument, NULL, 0 },
{ "no-psy-rd", no_argument, NULL, 0 },
@@ -273,9 +275,10 @@
H0(" --tu-intra-depth <integer> Max TU recursive depth for intra CUs. Default %d\n", param->tuQTMaxIntraDepth);
H0(" --tu-inter-depth <integer> Max TU recursive depth for inter CUs. Default %d\n", param->tuQTMaxInterDepth);
H0("\nAnalysis:\n");
- H0(" --rd <0..6> Level of RD in mode decision 0:least....6:full RDO. Default %d\n", param->rdLevel);
+ H0(" --rd <0..6> Level of RDO in mode decision 0:least....6:full RDO. Default %d\n", param->rdLevel);
H0(" --[no-]psy-rd <0..2.0> Strength of psycho-visual rate distortion optimization, 0 to disable. Default %.1f\n", param->psyRd);
- H0(" --[no-]psy-rdoq <0..50.0> Strength of psycho-visual optimization in quantization, 0 to disable. Default %.1f\n", param->psyRdoq);
+ H0(" --[no-]rdoq-level <0|1|2> Level of RDO in quantization 0:none, 1:levels, 2:levels & coding groups. Default %d\n", param->rdoqLevel);
+ H0(" --[no-]psy-rdoq <0..50.0> Strength of psycho-visual optimization in RDO quantization, 0 to disable. Default %.1f\n", param->psyRdoq);
H0(" --[no-]early-skip Enable early SKIP detection. Default %s\n", OPT(param->bEnableEarlySkip));
H1(" --[no-]tskip-fast Enable fast intra transform skipping. Default %s\n", OPT(param->bEnableTSkipFast));
H1(" --nr-intra <integer> An integer value in range of 0 to 2000, which denotes strength of noise reduction in intra CUs. Default 0\n");
More information about the x265-devel
mailing list