[x265] [PATCH] AQMotion: Add aq offsets based the relative motion of each CU
gopi.satykrishna at multicorewareinc.com
gopi.satykrishna at multicorewareinc.com
Wed Dec 28 14:08:52 CET 2016
# HG changeset patch
# User Gopi Satykrishna Akisetty <gopi.satykrishna at multicorewareinc.com>
# Date 1482137927 -19800
# Mon Dec 19 14:28:47 2016 +0530
# Node ID 93fd14d86372368f7120e8999b9eb45247f849fd
# Parent af10eaeb36cd22c7ad20ed2dafeac6f8e388ed9d
AQMotion: Add aq offsets based the relative motion of each CU
diff -r af10eaeb36cd -r 93fd14d86372 doc/reST/cli.rst
--- a/doc/reST/cli.rst Wed Dec 28 10:17:08 2016 +0530
+++ b/doc/reST/cli.rst Mon Dec 19 14:28:47 2016 +0530
@@ -1382,6 +1382,14 @@
Default 1.0.
**Range of values:** 0.0 to 3.0
+.. option:: --[no-]aq-motion
+
+ Adjust the AQ offsets based on the relative motion of each block with
+ respect to the motion of the frame. The more the relative motion of the block,
+ the more quantization is used. Default disabled.
+
+ Requires AQ Mode to be on.
+
.. option:: --qg-size <64|32|16|8>
Enable adaptive quantization for sub-CTUs. This parameter specifies
diff -r af10eaeb36cd -r 93fd14d86372 source/CMakeLists.txt
--- a/source/CMakeLists.txt Wed Dec 28 10:17:08 2016 +0530
+++ b/source/CMakeLists.txt Mon Dec 19 14:28:47 2016 +0530
@@ -29,7 +29,7 @@
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 105)
+set(X265_BUILD 106)
configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
"${PROJECT_BINARY_DIR}/x265.def")
configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff -r af10eaeb36cd -r 93fd14d86372 source/common/lowres.cpp
--- a/source/common/lowres.cpp Wed Dec 28 10:17:08 2016 +0530
+++ b/source/common/lowres.cpp Mon Dec 19 14:28:47 2016 +0530
@@ -56,6 +56,7 @@
if (bAQEnabled)
{
CHECKED_MALLOC_ZERO(qpAqOffset, double, cuCountFullRes);
+ CHECKED_MALLOC_ZERO(qpAqMotionOffset, double, cuCountFullRes);
CHECKED_MALLOC_ZERO(invQscaleFactor, int, cuCountFullRes);
CHECKED_MALLOC_ZERO(qpCuTreeOffset, double, cuCountFullRes);
CHECKED_MALLOC_ZERO(blockVariance, uint32_t, cuCountFullRes);
@@ -124,8 +125,8 @@
X265_FREE(lowresMvCosts[0][i]);
X265_FREE(lowresMvCosts[1][i]);
}
-
X265_FREE(qpAqOffset);
+ X265_FREE(qpAqMotionOffset);
X265_FREE(invQscaleFactor);
X265_FREE(qpCuTreeOffset);
X265_FREE(propagateCost);
diff -r af10eaeb36cd -r 93fd14d86372 source/common/lowres.h
--- a/source/common/lowres.h Wed Dec 28 10:17:08 2016 +0530
+++ b/source/common/lowres.h Mon Dec 19 14:28:47 2016 +0530
@@ -144,6 +144,7 @@
/* rate control / adaptive quant data */
double* qpAqOffset; // AQ QP offset values for each 16x16 CU
double* qpCuTreeOffset; // cuTree QP offset values for each 16x16 CU
+ double* qpAqMotionOffset;
int* invQscaleFactor; // qScale values for qp Aq Offsets
int* invQscaleFactor8x8; // temporary buffer for qg-size 8
uint32_t* blockVariance;
diff -r af10eaeb36cd -r 93fd14d86372 source/common/param.cpp
--- a/source/common/param.cpp Wed Dec 28 10:17:08 2016 +0530
+++ b/source/common/param.cpp Mon Dec 19 14:28:47 2016 +0530
@@ -266,6 +266,7 @@
param->bOptQpPPS = 1;
param->bOptRefListLengthPPS = 1;
param->bOptCUDeltaQP = 0;
+ param->bAQMotion = 0;
}
@@ -926,6 +927,7 @@
OPT("opt-cu-delta-qp") p->bOptCUDeltaQP = atobool(value);
OPT("multi-pass-opt-analysis") p->analysisMultiPassRefine = atobool(value);
OPT("multi-pass-opt-distortion") p->analysisMultiPassDistortion = atobool(value);
+ OPT("aq-motion") p->bAQMotion = atobool(value);
else
return X265_PARAM_BAD_NAME;
}
@@ -1621,6 +1623,7 @@
BOOL(p->bMultiPassOptRPS, "multi-pass-opt-rps");
s += sprintf(s, " scenecut-bias=%.2f", p->scenecutBias);
BOOL(p->bOptCUDeltaQP, "opt-cu-delta-qp");
+ BOOL(p->bAQMotion, "aq-motion");
#undef BOOL
return buf;
}
diff -r af10eaeb36cd -r 93fd14d86372 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Wed Dec 28 10:17:08 2016 +0530
+++ b/source/encoder/encoder.cpp Mon Dec 19 14:28:47 2016 +0530
@@ -2132,6 +2132,12 @@
x265_log(p, X265_LOG_WARNING, "--opt-cu-delta-qp disabled, requires RD level > 4\n");
}
+ if (p->bAQMotion && !p->rc.aqMode)
+ {
+ p->bAQMotion = false;
+ x265_log(p, X265_LOG_WARNING, "--aq-motion disabled, requires aq mode to be on\n");
+ }
+
if (p->limitTU && p->tuQTMaxInterDepth < 2)
{
p->limitTU = 0;
diff -r af10eaeb36cd -r 93fd14d86372 source/encoder/slicetype.cpp
--- a/source/encoder/slicetype.cpp Wed Dec 28 10:17:08 2016 +0530
+++ b/source/encoder/slicetype.cpp Mon Dec 19 14:28:47 2016 +0530
@@ -1495,6 +1495,8 @@
resetStart = bKeyframe ? 1 : 2;
}
+ if (m_param->bAQMotion)
+ aqMotion(frames, bKeyframe);
if (m_param->rc.cuTree)
cuTree(frames, X265_MIN(numFrames, m_param->keyframeMax), bKeyframe);
@@ -1724,6 +1726,88 @@
return cost;
}
+void Lookahead::aqMotion(Lowres **frames, bool bIntra)
+{
+ if (!bIntra)
+ {
+ int curnonb = 0, lastnonb = 1;
+ int bframes = 0, i = 1;
+ while (frames[lastnonb]->sliceType != X265_TYPE_P)
+ lastnonb++;
+ bframes = lastnonb - 1;
+ if (m_param->bBPyramid && bframes > 1)
+ {
+ int middle = (bframes + 1) / 2;
+ for (i = 1; i < lastnonb; i++)
+ {
+ int p0 = i > middle ? middle : curnonb;
+ int p1 = i < middle ? middle : lastnonb;
+ if (i != middle)
+ calcMotionAdaptiveQuantFrame(frames, p0, p1, i);
+ }
+ calcMotionAdaptiveQuantFrame(frames, curnonb, lastnonb, middle);
+ }
+ else
+ for (i = 1; i < lastnonb; i++)
+ calcMotionAdaptiveQuantFrame(frames, curnonb, lastnonb, i);
+ calcMotionAdaptiveQuantFrame(frames, curnonb, lastnonb, lastnonb);
+ }
+}
+
+void Lookahead::calcMotionAdaptiveQuantFrame(Lowres **frames, int p0, int p1, int b)
+{
+ int listDist[2] = { b - p0 - 1, p1 - b - 1 };
+ int32_t strideInCU = m_8x8Width;
+ double qp_adj = 0, avg_adj = 0, avg_adj_pow2 = 0, sd;
+ for (uint16_t blocky = 0; blocky < m_8x8Height; blocky++)
+ {
+ int cuIndex = blocky * strideInCU;
+ for (uint16_t blockx = 0; blockx < m_8x8Width; blockx++, cuIndex++)
+ {
+ int32_t lists_used = frames[b]->lowresCosts[b - p0][p1 - b][cuIndex] >> LOWRES_COST_SHIFT;
+ double displacement = 0;
+ for (uint16_t list = 0; list < 2; list++)
+ {
+ if ((lists_used >> list) & 1)
+ {
+ MV *mvs = frames[b]->lowresMvs[list][listDist[list]];
+ int32_t x = mvs[cuIndex].x;
+ int32_t y = mvs[cuIndex].y;
+ displacement += sqrt(pow(abs(x), 2) + pow(abs(y), 2));
+ }
+ else
+ displacement += 0.0;
+ }
+ if (lists_used == 3)
+ displacement = displacement / 2;
+ qp_adj = pow(displacement, 0.1);
+ frames[b]->qpAqMotionOffset[cuIndex] = qp_adj;
+ avg_adj += qp_adj;
+ avg_adj_pow2 += qp_adj * qp_adj;
+ }
+ }
+ avg_adj /= m_cuCount;
+ avg_adj_pow2 /= m_cuCount;
+ sd = sqrt((avg_adj_pow2 - (avg_adj * avg_adj)));
+ if (sd > 0)
+ {
+ for (uint16_t blocky = 0; blocky < m_8x8Height; blocky++)
+ {
+ int cuIndex = blocky * strideInCU;
+ for (uint16_t blockx = 0; blockx < m_8x8Width; blockx++, cuIndex++)
+ {
+ qp_adj = frames[b]->qpAqMotionOffset[cuIndex];
+ qp_adj = (qp_adj - avg_adj) / sd;
+ if (qp_adj > 1)
+ {
+ frames[b]->qpAqOffset[cuIndex] += qp_adj;
+ frames[b]->qpCuTreeOffset[cuIndex] += qp_adj;
+ frames[b]->invQscaleFactor[cuIndex] += x265_exp2fix8(qp_adj);
+ }
+ }
+ }
+ }
+}
void Lookahead::cuTree(Lowres **frames, int numframes, bool bIntra)
{
diff -r af10eaeb36cd -r 93fd14d86372 source/encoder/slicetype.h
--- a/source/encoder/slicetype.h Wed Dec 28 10:17:08 2016 +0530
+++ b/source/encoder/slicetype.h Mon Dec 19 14:28:47 2016 +0530
@@ -165,7 +165,8 @@
int64_t slicetypePathCost(Lowres **frames, char *path, int64_t threshold);
int64_t vbvFrameCost(Lowres **frames, int p0, int p1, int b);
void vbvLookahead(Lowres **frames, int numFrames, int keyframes);
-
+ void aqMotion(Lowres **frames, bool bintra);
+ void calcMotionAdaptiveQuantFrame(Lowres **frames, int p0, int p1, int b);
/* called by slicetypeAnalyse() to effect cuTree adjustments to adaptive
* quant offsets */
void cuTree(Lowres **frames, int numframes, bool bintra);
diff -r af10eaeb36cd -r 93fd14d86372 source/test/regression-tests.txt
--- a/source/test/regression-tests.txt Wed Dec 28 10:17:08 2016 +0530
+++ b/source/test/regression-tests.txt Mon Dec 19 14:28:47 2016 +0530
@@ -43,6 +43,7 @@
CrowdRun_1920x1080_50_10bit_444.yuv,--preset veryfast --temporal-layers --repeat-headers --limit-refs 2
CrowdRun_1920x1080_50_10bit_444.yuv,--preset medium --dither --keyint -1 --rdoq-level 1 --limit-modes
CrowdRun_1920x1080_50_10bit_444.yuv,--preset veryslow --tskip --tskip-fast --no-scenecut --limit-tu 1
+CrowdRun_1920x1080_50_10bit_444.yuv,--preset veryslow --aq-mode 3 --aq-strength 1.5 --aq-motion --bitrate 5000
DucksAndLegs_1920x1080_60_10bit_422.yuv,--preset superfast --weightp --qg-size 16
DucksAndLegs_1920x1080_60_10bit_422.yuv,--preset medium --tune psnr --bframes 16 --limit-modes
DucksAndLegs_1920x1080_60_10bit_422.yuv,--preset slow --temporal-layers --no-psy-rd --qg-size 32 --limit-refs 0 --cu-lossless
diff -r af10eaeb36cd -r 93fd14d86372 source/x265.h
--- a/source/x265.h Wed Dec 28 10:17:08 2016 +0530
+++ b/source/x265.h Mon Dec 19 14:28:47 2016 +0530
@@ -1360,6 +1360,9 @@
/* Refine analysis in multipass ratecontrol based on distortion data stored */
int analysisMultiPassDistortion;
+
+ /* Adaptive Quantization based on relative motion */
+ int bAQMotion;
} x265_param;
/* x265_param_alloc:
diff -r af10eaeb36cd -r 93fd14d86372 source/x265cli.h
--- a/source/x265cli.h Wed Dec 28 10:17:08 2016 +0530
+++ b/source/x265cli.h Mon Dec 19 14:28:47 2016 +0530
@@ -256,6 +256,8 @@
{ "analyze-src-pics", no_argument, NULL, 0 },
{ "no-analyze-src-pics", no_argument, NULL, 0 },
{ "slices", required_argument, NULL, 0 },
+ { "aq-motion", no_argument, NULL, 0 },
+ { "no-aq-motion", no_argument, NULL, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
@@ -414,6 +416,7 @@
H0(" --analysis-file <filename> Specify file name used for either dumping or reading analysis data.\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. Default %d\n", param->rc.aqMode);
H0(" --aq-strength <float> Reduces blocking and blurring in flat and textured areas (0 to 3.0). Default %.2f\n", param->rc.aqStrength);
+ H0(" --[no-]aq-motion Adaptive Quantization based on the relative motion of each CU w.r.t., frame. Default %s\n", OPT(param->bOptCUDeltaQP));
H0(" --qg-size <int> Specifies the size of the quantization group (64, 32, 16, 8). Default %d\n", param->rc.qgSize);
H0(" --[no-]cutree Enable cutree for Adaptive Quantization. Default %s\n", OPT(param->rc.cuTree));
H0(" --[no-]rc-grain Enable ratecontrol mode to handle grains specifically. turned on with tune grain. Default %s\n", OPT(param->rc.bEnableGrain));
More information about the x265-devel
mailing list