[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