Skip to content

Instantly share code, notes, and snippets.

@al3xtjames
Forked from noizuy/aq_edge_biased.patch
Last active July 24, 2023 01:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save al3xtjames/ea0ba892644ba8da96ddeead1c892d76 to your computer and use it in GitHub Desktop.
Save al3xtjames/ea0ba892644ba8da96ddeead1c892d76 to your computer and use it in GitHub Desktop.
x265 patch to add an AQ mode adding AQ mode 3's dark bias to AQ mode 4.
From 06661cfa70b74b49cf6fd8ffe62045d327b118dd Mon Sep 17 00:00:00 2001
From: noizuy <85082087+noizuy@users.noreply.github.com>
Date: Fri, 18 Feb 2022 17:09:39 +0000
Subject: [PATCH] add new AQ mode (#17)
add new AQ mode
This just adds AQ mode 3's dark bias to AQ mode 4. Because of normal AQ
strength values for mode 4 not really working well with the dark bias,
an additional bias-strength parameter has been added.
---
doc/reST/cli.rst | 10 +++++++++-
source/common/frame.cpp | 4 ++--
source/common/param.cpp | 7 ++++++-
source/encoder/frameencoder.cpp | 2 +-
source/encoder/slicetype.cpp | 21 ++++++++++++++++-----
source/x265.h | 4 ++++
source/x265cli.cpp | 5 +++--
source/x265cli.h | 1 +
8 files changed, 42 insertions(+), 12 deletions(-)
diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
index a98c860d0..b8b5fe71c 100755
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -1733,7 +1733,7 @@ Quality, rate control and rate distortion options
ignored. Slower presets will generally achieve better compression
efficiency (and generate smaller bitstreams). Default disabled.
-.. option:: --aq-mode <0|1|2|3|4>
+.. option:: --aq-mode <0|1|2|3|4|5>
Adaptive Quantization operating mode. Raise or lower per-block
quantization based on complexity analysis of the source image. The
@@ -1748,6 +1748,7 @@ Quality, rate control and rate distortion options
recommended for 8-bit encodes or low-bitrate 10-bit encodes, to
prevent color banding/blocking.
4. AQ enabled with auto-variance and edge information.
+ 5. AQ enabled with auto-variance, edge information, and bias to dark scenes.
.. option:: --aq-strength <float>
@@ -1765,6 +1766,13 @@ Quality, rate control and rate distortion options
keyframe interval specified.If unspecified,default keyframe interval will be used.
Default: disabled.
+.. option:: --aq-bias-strength <float>
+
+ Adjust the strength of dark scene bias in AQ modes 3 and 5. Setting this
+ to 0 will disable the dark scene bias, meaning modes will be equivalent to
+ their unbiased counterparts (2 and 4).
+ Default 1.0.
+
.. option:: --hevc-aq
Enable adaptive quantization
diff --git a/source/common/frame.cpp b/source/common/frame.cpp
index ae3773e83..e8dcae10f 100644
--- a/source/common/frame.cpp
+++ b/source/common/frame.cpp
@@ -132,7 +132,7 @@ bool Frame::create(x265_param *param, float* quantOffsets)
CHECKED_MALLOC_ZERO(m_classifyCount, uint32_t, size);
}
- if (param->rc.aqMode == X265_AQ_EDGE || (param->rc.zonefileCount && param->rc.aqMode != 0))
+ if (param->rc.aqMode == X265_AQ_EDGE || param->rc.aqMode == X265_AQ_EDGE_BIASED || (param->rc.zonefileCount && param->rc.aqMode != 0))
{
uint32_t numCuInWidth = (param->sourceWidth + param->maxCUSize - 1) / param->maxCUSize;
uint32_t numCuInHeight = (param->sourceHeight + param->maxCUSize - 1) / param->maxCUSize;
@@ -342,7 +342,7 @@ void Frame::destroy()
X265_FREE_ZERO(m_classifyCount);
}
- if (m_param->rc.aqMode == X265_AQ_EDGE || (m_param->rc.zonefileCount && m_param->rc.aqMode != 0))
+ if (m_param->rc.aqMode == X265_AQ_EDGE || m_param->rc.aqMode == X265_AQ_EDGE_BIASED || (m_param->rc.zonefileCount && m_param->rc.aqMode != 0))
{
X265_FREE(m_edgePic);
X265_FREE(m_gaussianPic);
diff --git a/source/common/param.cpp b/source/common/param.cpp
index 1a4df4cdc..f7f4fd9ac 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -281,6 +281,7 @@ void x265_param_default(x265_param* param)
param->rc.hevcAq = 0;
param->rc.qgSize = 32;
param->rc.aqStrength = 1.0;
+ param->rc.aqBiasStrength = 1.0;
param->rc.qpAdaptationRange = 1.0;
param->rc.cuTree = 1;
param->rc.rfConstantMax = 0;
@@ -811,6 +812,7 @@ int x265_zone_param_parse(x265_param* p, const char* name, const char* value)
}
OPT("aq-mode") p->rc.aqMode = atoi(value);
OPT("aq-strength") p->rc.aqStrength = atof(value);
+ OPT("aq-bias-strength") p->rc.aqBiasStrength = atof(value);
OPT("nr-intra") p->noiseReductionIntra = atoi(value);
OPT("nr-inter") p->noiseReductionInter = atoi(value);
OPT("limit-modes") p->limitModes = atobool(value);
@@ -1112,6 +1114,7 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)
OPT("qblur") p->rc.qblur = atof(value);
OPT("aq-mode") p->rc.aqMode = atoi(value);
OPT("aq-strength") p->rc.aqStrength = atof(value);
+ OPT("aq-bias-strength") p->rc.aqBiasStrength = atof(value);
OPT("vbv-maxrate") p->rc.vbvMaxBitrate = atoi(value);
OPT("vbv-bufsize") p->rc.vbvBufferSize = atoi(value);
OPT("vbv-init") p->rc.vbvBufferInit = atof(value);
@@ -1682,7 +1685,7 @@ int x265_check_params(x265_param* param)
"Lookahead depth must be less than 256");
CHECK(param->lookaheadSlices > 16 || param->lookaheadSlices < 0,
"Lookahead slices must between 0 and 16");
- CHECK(param->rc.aqMode < X265_AQ_NONE || X265_AQ_EDGE < param->rc.aqMode,
+ CHECK(param->rc.aqMode < X265_AQ_NONE || X265_AQ_EDGE_BIASED < param->rc.aqMode,
"Aq-Mode is out of range");
CHECK(param->rc.aqStrength < 0 || param->rc.aqStrength > 3,
"Aq-Strength is out of range");
@@ -2242,6 +2245,7 @@ char *x265_param2string(x265_param* p, int padx, int pady)
}
s += sprintf(s, " aq-mode=%d", p->rc.aqMode);
s += sprintf(s, " aq-strength=%.2f", p->rc.aqStrength);
+ s += sprintf(s, " aq-bias-strength=%.2f", p->rc.aqBiasStrength);
BOOL(p->rc.cuTree, "cutree");
s += sprintf(s, " zone-count=%d", p->rc.zoneCount);
if (p->rc.zoneCount)
@@ -2680,6 +2684,7 @@ void x265_copy_params(x265_param* dst, x265_param* src)
dst->rc.qpStep = src->rc.qpStep;
dst->rc.aqMode = src->rc.aqMode;
dst->rc.aqStrength = src->rc.aqStrength;
+ dst->rc.aqBiasStrength = src->rc.aqBiasStrength;
dst->rc.vbvBufferSize = src->rc.vbvBufferSize;
dst->rc.vbvMaxBitrate = src->rc.vbvMaxBitrate;
diff --git a/source/encoder/frameencoder.cpp b/source/encoder/frameencoder.cpp
index 659b87c89..02a2b5236 100644
--- a/source/encoder/frameencoder.cpp
+++ b/source/encoder/frameencoder.cpp
@@ -471,7 +471,7 @@ void FrameEncoder::compressFrame()
m_ssimCnt = 0;
memset(&(m_frame->m_encData->m_frameStats), 0, sizeof(m_frame->m_encData->m_frameStats));
- if (m_param->rc.aqMode != X265_AQ_EDGE && m_param->recursionSkipMode == EDGE_BASED_RSKIP)
+ if (m_param->rc.aqMode != X265_AQ_EDGE_BIASED && m_param->rc.aqMode != X265_AQ_EDGE && m_param->recursionSkipMode == EDGE_BASED_RSKIP)
{
int height = m_frame->m_fencPic->m_picHeight;
int width = m_frame->m_fencPic->m_picWidth;
diff --git a/source/encoder/slicetype.cpp b/source/encoder/slicetype.cpp
index 8e67c2ed4..7cd3773d9 100644
--- a/source/encoder/slicetype.cpp
+++ b/source/encoder/slicetype.cpp
@@ -524,17 +524,17 @@ void LookaheadTLD::calcAdaptiveQuantFrame(Frame *curFrame, x265_param* param)
double bias_strength = 0.f;
double strength = 0.f;
- if (param->rc.aqMode == X265_AQ_EDGE)
+ if (param->rc.aqMode == X265_AQ_EDGE || param->rc.aqMode == X265_AQ_EDGE_BIASED)
edgeFilter(curFrame, param);
- if (param->rc.aqMode == X265_AQ_EDGE && param->recursionSkipMode == EDGE_BASED_RSKIP)
+ if ((param->rc.aqMode == X265_AQ_EDGE || param->rc.aqMode == X265_AQ_EDGE_BIASED) && param->recursionSkipMode == EDGE_BASED_RSKIP)
{
pixel* src = curFrame->m_edgePic + curFrame->m_fencPic->m_lumaMarginY * curFrame->m_fencPic->m_stride + curFrame->m_fencPic->m_lumaMarginX;
primitives.planecopy_pp_shr(src, curFrame->m_fencPic->m_stride, curFrame->m_edgeBitPic,
curFrame->m_fencPic->m_stride, curFrame->m_fencPic->m_picWidth, curFrame->m_fencPic->m_picHeight, SHIFT_TO_BITPLANE);
}
- if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE || param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED || param->rc.aqMode == X265_AQ_EDGE)
+ if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE || param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED || param->rc.aqMode == X265_AQ_EDGE || param->rc.aqMode == X265_AQ_EDGE_BIASED)
{
double bit_depth_correction = 1.f / (1 << (2 * (X265_DEPTH - 8)));
for (int blockY = 0; blockY < maxRow; blockY += loopIncr)
@@ -543,7 +543,7 @@ void LookaheadTLD::calcAdaptiveQuantFrame(Frame *curFrame, x265_param* param)
{
uint32_t energy, edgeDensity, avgAngle;
energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);
- if (param->rc.aqMode == X265_AQ_EDGE)
+ if (param->rc.aqMode == X265_AQ_EDGE || param->rc.aqMode == X265_AQ_EDGE_BIASED)
{
edgeDensity = edgeDensityCu(curFrame, avgAngle, blockX, blockY, param->rc.qgSize);
if (edgeDensity)
@@ -573,7 +573,7 @@ void LookaheadTLD::calcAdaptiveQuantFrame(Frame *curFrame, x265_param* param)
avg_adj_pow2 /= blockCount;
strength = param->rc.aqStrength * avg_adj;
avg_adj = avg_adj - 0.5f * (avg_adj_pow2 - modeTwoConst) / avg_adj;
- bias_strength = param->rc.aqStrength;
+ bias_strength = param->rc.aqBiasStrength * param->rc.aqStrength;
}
else
strength = param->rc.aqStrength * 1.0397f;
@@ -602,6 +602,17 @@ void LookaheadTLD::calcAdaptiveQuantFrame(Frame *curFrame, x265_param* param)
else
qp_adj = strength * (qp_adj - avg_adj);
}
+ else if (param->rc.aqMode == X265_AQ_EDGE_BIASED)
+ {
+ inclinedEdge = curFrame->m_lowres.edgeInclined[blockXY];
+ qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY];
+ double dark_bias = bias_strength * (1.f - modeTwoConst / (qp_adj * qp_adj)) / 10.f;
+ if(inclinedEdge && (qp_adj - avg_adj > 0))
+ qp_adj = ((strength + AQ_EDGE_BIAS) * (qp_adj - avg_adj));
+ else
+ qp_adj = strength * (qp_adj - avg_adj);
+ qp_adj += dark_bias;
+ }
else
{
uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);
diff --git a/source/x265.h b/source/x265.h
index 1561a7a3e..af8c327b4 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -583,6 +583,7 @@ typedef enum
#define X265_AQ_AUTO_VARIANCE 2
#define X265_AQ_AUTO_VARIANCE_BIASED 3
#define X265_AQ_EDGE 4
+#define X265_AQ_EDGE_BIASED 5
#define x265_ADAPT_RD_STRENGTH 4
#define X265_REFINE_INTER_LEVELS 3
/* NOTE! For this release only X265_CSP_I420 and X265_CSP_I444 are supported */
@@ -1678,6 +1679,9 @@ typedef struct x265_param
* AQ is enabled. Default value: 1.0. Acceptable values between 0.0 and 3.0 */
double aqStrength;
+ /* Sets the bias towards dark scenes in AQ modes 3 and 5. */
+ double aqBiasStrength;
+
/* Delta QP range by QP adaptation based on a psycho-visual model.
* Acceptable values between 1.0 to 6.0 */
double qpAdaptationRange;
diff --git a/source/x265cli.cpp b/source/x265cli.cpp
index cbb3be593..2fe251e56 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -257,9 +257,10 @@ namespace X265_NS {
" - 0 : Disabled.\n"
" - 1 : Store/Load ctu distortion to/from the file specified in analysis-save/load.\n"
" Default 0 - Disabled\n");
- H0(" --aq-mode <integer> Mode for Adaptive Quantization - 0:none 1:uniform AQ 2:auto variance 3:auto variance with bias to dark scenes 4:auto variance with edge information. Default %d\n", param->rc.aqMode);
+ H0(" --aq-mode <integer> Mode for Adaptive Quantization - 0:none 1:uniform AQ 2:auto variance 3:auto variance with bias to dark scenes 4:auto variance with edge information 5:auto variance with edge information and bias to dark scenes. Default %d\n", param->rc.aqMode);
H0(" --[no-]hevc-aq Mode for HEVC Adaptive Quantization. Default %s\n", OPT(param->rc.hevcAq));
H0(" --aq-strength <float> Reduces blocking and blurring in flat and textured areas (0 to 3.0). Default %.2f\n", param->rc.aqStrength);
+ H0(" --aq-bias-strength <float> Sets the bias to dark strength in AQ modes 3 and 5. Default %.2f\n", param->rc.aqBiasStrength);
H0(" --qp-adaptation-range <float> Delta QP range by QP adaptation based on a psycho-visual model (1.0 to 6.0). Default %.2f\n", param->rc.qpAdaptationRange);
H0(" --[no-]aq-motion Block level QP adaptation based on the relative motion between the block and the frame. Default %s\n", OPT(param->bAQMotion));
H1(" --[no-]sbrc Enables the segment based rate control. Default %s\n", OPT(param->bEnableSBRC));
@@ -1229,4 +1230,4 @@ namespace X265_NS {
#ifdef __cplusplus
}
-#endif
\ No newline at end of file
+#endif
diff --git a/source/x265cli.h b/source/x265cli.h
index e937f6d77..cdee25ba4 100644
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -181,6 +181,7 @@ static const struct option long_options[] =
{ "qp", required_argument, NULL, 'q' },
{ "aq-mode", required_argument, NULL, 0 },
{ "aq-strength", required_argument, NULL, 0 },
+ { "aq-bias-strength", required_argument, NULL, 0 },
{ "sbrc", no_argument, NULL, 0 },
{ "no-sbrc", no_argument, NULL, 0 },
{ "rc-grain", no_argument, NULL, 0 },
--
2.41.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment