<div dir="ltr">Where is  
<span style="font-family:arial,helvetica,sans-serif"><code class="gmail-descname"><span style="font-family:arial,helvetica,sans-serif">the --qp-adaptation-range parameter used?</span></code></span>

</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Feb 9, 2019 at 4:44 AM Pooja Venkatesan <<a href="mailto:pooja@multicorewareinc.com">pooja@multicorewareinc.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div># HG changeset patch</div><div># User Ashok Kumar Mishra <<a href="mailto:ashok@multicorewareinc.com" target="_blank">ashok@multicorewareinc.com</a>></div><div># Date 1545902034 -19800</div><div>#      Thu Dec 27 14:43:54 2018 +0530</div><div># Node ID 3cd0b5ed0b91bcb3d5d6cfa1395cb502fc6d01ca</div><div># Parent  129416ec047966f7d7e7898fbe16110444b9a183</div><div>new aq implementation</div><div><br></div><div>It scales the quantization step size according to the spatial activity of one</div><div>coding unit relative to frame average spatial activity. This AQ method utilizes</div><div>the minimum variance of sub-unit in each coding unit to represent the coding</div><div>units spatial complexity.</div><div><br></div><div>diff -r 129416ec0479 -r 3cd0b5ed0b91 doc/reST/cli.rst</div><div>--- a/doc/reST/cli.rst<span style="white-space:pre-wrap">     </span>Fri Dec 28 09:03:26 2018 +0530</div><div>+++ b/doc/reST/cli.rst<span style="white-space:pre-wrap">     </span>Thu Dec 27 14:43:54 2018 +0530</div><div>@@ -1646,6 +1646,21 @@</div><div> <span style="white-space:pre-wrap">    </span>Default 1.0.</div><div> <span style="white-space:pre-wrap">   </span>**Range of values:** 0.0 to 3.0</div><div> </div><div>+.. option:: --hevc-aq</div><div>+</div><div>+<span style="white-space:pre-wrap">   </span>Enable adaptive quantization</div><div>+<span style="white-space:pre-wrap">    </span>It scales the quantization step size according to the spatial activity of one</div><div>+<span style="white-space:pre-wrap">   </span>coding unit relative to frame average spatial activity. This AQ method utilizes</div><div>+<span style="white-space:pre-wrap"> </span>the minimum variance of sub-unit in each coding unit to represent the coding</div><div>+<span style="white-space:pre-wrap">    </span>unit’s spatial complexity.</div><div>+</div><div>+.. option:: --qp-adaptation-range</div><div>+</div><div>+<span style="white-space:pre-wrap">   </span>Delta-QP range by QP adaptation based on a psycho-visual model.</div><div>+</div><div>+<span style="white-space:pre-wrap"> </span>Default 1.0.</div><div>+<span style="white-space:pre-wrap">    </span>**Range of values:** 1.0 to 6.0</div><div>+</div><div> .. option:: --aq-motion, --no-aq-motion</div><div> </div><div> <span style="white-space:pre-wrap">       </span>Adjust the AQ offsets based on the relative motion of each block with</div><div>diff -r 129416ec0479 -r 3cd0b5ed0b91 source/common/lowres.cpp</div><div>--- a/source/common/lowres.cpp<span style="white-space:pre-wrap">  </span>Fri Dec 28 09:03:26 2018 +0530</div><div>+++ b/source/common/lowres.cpp<span style="white-space:pre-wrap">     </span>Thu Dec 27 14:43:54 2018 +0530</div><div>@@ -2,6 +2,7 @@</div><div>  * Copyright (C) 2013-2017 MulticoreWare, Inc</div><div>  *</div><div>  * Authors: Gopu Govindaswamy <<a href="mailto:gopu@multicorewareinc.com" target="_blank">gopu@multicorewareinc.com</a>></div><div>+ *          Ashok Kumar Mishra <<a href="mailto:ashok@multicorewareinc.com" target="_blank">ashok@multicorewareinc.com</a>></div><div>  *</div><div>  * This program is free software; you can redistribute it and/or modify</div><div>  * it under the terms of the GNU General Public License as published by</div><div>@@ -27,10 +28,31 @@</div><div> </div><div> using namespace X265_NS;</div><div> </div><div>+bool PicQPAdaptationLayer::create(uint32_t width, uint32_t height, uint32_t partWidth, uint32_t partHeight, uint32_t numAQPartInWidthExt, uint32_t numAQPartInHeightExt)</div><div>+{</div><div>+    aqPartWidth = partWidth;</div><div>+    aqPartHeight = partHeight;</div><div>+    numAQPartInWidth = (width + partWidth - 1) / partWidth;</div><div>+    numAQPartInHeight = (height + partHeight - 1) / partHeight;</div><div>+</div><div>+    CHECKED_MALLOC_ZERO(dActivity, double, numAQPartInWidthExt * numAQPartInHeightExt);</div><div>+    CHECKED_MALLOC_ZERO(dQpOffset, double, numAQPartInWidthExt * numAQPartInHeightExt);</div><div>+    CHECKED_MALLOC_ZERO(dCuTreeOffset, double, numAQPartInWidthExt * numAQPartInHeightExt);</div><div>+</div><div>+    if (bQpSize)</div><div>+        CHECKED_MALLOC_ZERO(dCuTreeOffset8x8, double, numAQPartInWidthExt * numAQPartInHeightExt);</div><div>+</div><div>+    return true;</div><div>+fail:</div><div>+    return false;</div><div>+}</div><div>+</div><div> bool Lowres::create(x265_param* param, PicYuv *origPic, uint32_t qgSize)</div><div> {</div><div>     isLowres = true;</div><div>     bframes = param->bframes;</div><div>+    widthFullRes = origPic->m_picWidth;</div><div>+    heightFullRes = origPic->m_picHeight;</div><div>     width = origPic->m_picWidth / 2;</div><div>     lines = origPic->m_picHeight / 2;</div><div>     lumaStride = width + 2 * origPic->m_lumaMarginX;</div><div>@@ -49,7 +71,7 @@</div><div> </div><div>     size_t planesize = lumaStride * (lines + 2 * origPic->m_lumaMarginY);</div><div>     size_t padoffset = lumaStride * origPic->m_lumaMarginY + origPic->m_lumaMarginX;</div><div>-    if (!!param->rc.aqMode)</div><div>+    if (!!param->rc.aqMode || !!param->rc.hevcAq)</div><div>     {</div><div>         CHECKED_MALLOC_ZERO(qpAqOffset, double, cuCountFullRes);</div><div>         CHECKED_MALLOC_ZERO(invQscaleFactor, int, cuCountFullRes);</div><div>@@ -57,10 +79,50 @@</div><div>         if (qgSize == 8)</div><div>             CHECKED_MALLOC_ZERO(invQscaleFactor8x8, int, cuCount);</div><div>     }</div><div>+</div><div>     if (origPic->m_param->bAQMotion)</div><div>         CHECKED_MALLOC_ZERO(qpAqMotionOffset, double, cuCountFullRes);</div><div>     if (origPic->m_param->bDynamicRefine)</div><div>         CHECKED_MALLOC_ZERO(blockVariance, uint32_t, cuCountFullRes);</div><div>+</div><div>+    if (!!param->rc.hevcAq)</div><div>+    {</div><div>+        m_maxCUSize = param->maxCUSize;</div><div>+        m_qgSize = qgSize;</div><div>+</div><div>+        uint32_t partWidth, partHeight, nAQPartInWidth, nAQPartInHeight;</div><div>+</div><div>+        pAQLayer = new PicQPAdaptationLayer[4];</div><div>+        maxAQDepth = 0;</div><div>+        for (uint32_t d = 0; d < 4; d++)</div><div>+        {</div><div>+            int ctuSizeIdx = 6 - g_log2Size[param->maxCUSize];</div><div>+            int aqDepth = g_log2Size[param->maxCUSize] - g_log2Size[qgSize];</div><div>+            if (!aqLayerDepth[ctuSizeIdx][aqDepth][d])</div><div>+                continue;</div><div>+</div><div>+            pAQLayer->minAQDepth = d;</div><div>+            partWidth = param->maxCUSize >> d;</div><div>+            partHeight = param->maxCUSize >> d;</div><div>+</div><div>+            if (minAQSize[ctuSizeIdx] == d)</div><div>+            {</div><div>+                pAQLayer[d].bQpSize = true;</div><div>+                nAQPartInWidth = maxBlocksInRow * 2;</div><div>+                nAQPartInHeight = maxBlocksInCol * 2;</div><div>+            }</div><div>+            else</div><div>+            {</div><div>+                pAQLayer[d].bQpSize = false;</div><div>+                nAQPartInWidth = (origPic->m_picWidth + partWidth - 1) / partWidth;</div><div>+                nAQPartInHeight = (origPic->m_picHeight + partHeight - 1) / partHeight;</div><div>+            }</div><div>+</div><div>+            maxAQDepth++;</div><div>+</div><div>+            pAQLayer[d].create(origPic->m_picWidth, origPic->m_picHeight, partWidth, partHeight, nAQPartInWidth, nAQPartInHeight);</div><div>+        }</div><div>+    }</div><div>     CHECKED_MALLOC(propagateCost, uint16_t, cuCount);</div><div> </div><div>     /* allocate lowres buffers */</div><div>@@ -130,6 +192,25 @@</div><div>     X265_FREE(invQscaleFactor8x8);</div><div>     X265_FREE(qpAqMotionOffset);</div><div>     X265_FREE(blockVariance);</div><div>+    if (maxAQDepth > 0)</div><div>+    {</div><div>+        for (uint32_t d = 0; d < 4; d++)</div><div>+        {</div><div>+            int ctuSizeIdx = 6 - g_log2Size[m_maxCUSize];</div><div>+            int aqDepth = g_log2Size[m_maxCUSize] - g_log2Size[m_qgSize];</div><div>+            if (!aqLayerDepth[ctuSizeIdx][aqDepth][d])</div><div>+                continue;</div><div>+</div><div>+            X265_FREE(pAQLayer[d].dActivity);</div><div>+            X265_FREE(pAQLayer[d].dQpOffset);</div><div>+            X265_FREE(pAQLayer[d].dCuTreeOffset);</div><div>+</div><div>+            if (pAQLayer[d].bQpSize == true)</div><div>+                X265_FREE(pAQLayer[d].dCuTreeOffset8x8);</div><div>+        }</div><div>+</div><div>+        delete[] pAQLayer;</div><div>+    }</div><div> }</div><div> // (re) initialize lowres state</div><div> void Lowres::init(PicYuv *origPic, int poc)</div><div>diff -r 129416ec0479 -r 3cd0b5ed0b91 source/common/lowres.h</div><div>--- a/source/common/lowres.h<span style="white-space:pre-wrap">      </span>Fri Dec 28 09:03:26 2018 +0530</div><div>+++ b/source/common/lowres.h<span style="white-space:pre-wrap">       </span>Thu Dec 27 14:43:54 2018 +0530</div><div>@@ -103,6 +103,49 @@</div><div>     }</div><div> };</div><div> </div><div>+static const uint32_t aqLayerDepth[3][4][4] = {</div><div>+    {  // ctu size 64</div><div>+        { 1, 0, 1, 0 },</div><div>+        { 1, 1, 1, 0 },</div><div>+        { 1, 1, 1, 0 },</div><div>+        { 1, 1, 1, 1 }</div><div>+    },</div><div>+    {  // ctu size 32</div><div>+        { 1, 1, 0, 0 },</div><div>+        { 1, 1, 0, 0 },</div><div>+        { 1, 1, 1, 0 },</div><div>+        { 0, 0, 0, 0 },</div><div>+    },</div><div>+    {  // ctu size 16</div><div>+        { 1, 0, 0, 0 },</div><div>+        { 1, 1, 0, 0 },</div><div>+        { 0, 0, 0, 0 },</div><div>+        { 0, 0, 0, 0 }</div><div>+    }</div><div>+};</div><div>+</div><div>+// min aq size for ctu size 64, 32 and 16</div><div>+static const uint32_t minAQSize[3] = { 3, 2, 1 };</div><div>+</div><div>+struct PicQPAdaptationLayer</div><div>+{</div><div>+    uint32_t aqPartWidth;</div><div>+    uint32_t aqPartHeight;</div><div>+    uint32_t numAQPartInWidth;</div><div>+    uint32_t numAQPartInHeight;</div><div>+    uint32_t minAQDepth;</div><div>+    double*  dActivity;</div><div>+    double*  dQpOffset;</div><div>+</div><div>+    double*  dCuTreeOffset;</div><div>+    double*  dCuTreeOffset8x8;</div><div>+    double   dAvgActivity;</div><div>+    bool     bQpSize;</div><div>+</div><div>+    bool  create(uint32_t width, uint32_t height, uint32_t aqPartWidth, uint32_t aqPartHeight, uint32_t numAQPartInWidthExt, uint32_t numAQPartInHeightExt);</div><div>+    void  destroy();</div><div>+};</div><div>+</div><div> /* lowres buffers, sizes and strides */</div><div> struct Lowres : public ReferencePlanes</div><div> {</div><div>@@ -154,6 +197,13 @@</div><div>     uint64_t  wp_sum[3];</div><div> </div><div>     /* cutree intermediate data */</div><div>+    PicQPAdaptationLayer* pAQLayer;</div><div>+    uint32_t maxAQDepth;</div><div>+    uint32_t widthFullRes;</div><div>+    uint32_t heightFullRes;</div><div>+    uint32_t m_maxCUSize;</div><div>+    uint32_t m_qgSize;</div><div>+    </div><div>     uint16_t* propagateCost;</div><div>     double    weightedCostDelta[X265_BFRAME_MAX + 2];</div><div>     ReferencePlanes weightedRef[X265_BFRAME_MAX + 2];</div><div>diff -r 129416ec0479 -r 3cd0b5ed0b91 source/common/param.cpp</div><div>--- a/source/common/param.cpp<span style="white-space:pre-wrap">      </span>Fri Dec 28 09:03:26 2018 +0530</div><div>+++ b/source/common/param.cpp<span style="white-space:pre-wrap">      </span>Thu Dec 27 14:43:54 2018 +0530</div><div>@@ -233,8 +233,10 @@</div><div>     param->rc.rateControlMode = X265_RC_CRF;</div><div>     param->rc.qp = 32;</div><div>     param->rc.aqMode = X265_AQ_AUTO_VARIANCE;</div><div>+    param->rc.hevcAq = 0;</div><div>     param->rc.qgSize = 32;</div><div>     param->rc.aqStrength = 1.0;</div><div>+    param->rc.qpAdaptationRange = 1.0;</div><div>     param->rc.cuTree = 1;</div><div>     param->rc.rfConstantMax = 0;</div><div>     param->rc.rfConstantMin = 0;</div><div>@@ -528,6 +530,7 @@</div><div>             param->rc.pbFactor = 1.0;</div><div>             param->rc.cuTree = 0;</div><div>             param->rc.aqMode = 0;</div><div>+            param->rc.hevcAq = 0;</div><div>             param->rc.qpStep = 1;</div><div>             param->rc.bEnableGrain = 1;</div><div>             param->bEnableRecursionSkip = 0;</div><div>@@ -1186,6 +1189,8 @@</div><div>         }</div><div>         OPT("hrd-concat") p->bEnableHRDConcatFlag = atobool(value);</div><div>         OPT("refine-ctu-distortion") p->ctuDistortionRefine = atoi(value);</div><div>+        OPT("hevc-aq") p->rc.hevcAq = atobool(value);</div><div>+        OPT("qp-adaptation-range") p->rc.qpAdaptationRange = atof(value);</div><div>         else</div><div>             return X265_PARAM_BAD_NAME;</div><div>     }</div><div>@@ -1430,6 +1435,8 @@</div><div>           "Aq-Mode is out of range");</div><div>     CHECK(param->rc.aqStrength < 0 || param->rc.aqStrength > 3,</div><div>           "Aq-Strength is out of range");</div><div>+    CHECK(param->rc.qpAdaptationRange < 1.0f || param->rc.qpAdaptationRange > 6.0f,</div><div>+        "qp adaptation range is out of range");</div><div>     CHECK(param->deblockingFilterTCOffset < -6 || param->deblockingFilterTCOffset > 6,</div><div>           "deblocking filter tC offset must be in the range of -6 to +6");</div><div>     CHECK(param->deblockingFilterBetaOffset < -6 || param->deblockingFilterBetaOffset > 6,</div><div>@@ -1956,6 +1963,8 @@</div><div>     s += sprintf(s, " max-ausize-factor=%.1f", p->maxAUSizeFactor);</div><div>     BOOL(p->bDynamicRefine, "dynamic-refine");</div><div>     BOOL(p->bSingleSeiNal, "single-sei");</div><div>+    BOOL(p->rc.hevcAq, "hevc-aq");</div><div>+    s += sprintf(s, " qp-adaptation-range=%.2f", p->rc.qpAdaptationRange);</div><div> #undef BOOL</div><div>     return buf;</div><div> }</div><div>diff -r 129416ec0479 -r 3cd0b5ed0b91 source/encoder/analysis.cpp</div><div>--- a/source/encoder/analysis.cpp<span style="white-space:pre-wrap">   </span>Fri Dec 28 09:03:26 2018 +0530</div><div>+++ b/source/encoder/analysis.cpp<span style="white-space:pre-wrap">  </span>Thu Dec 27 14:43:54 2018 +0530</div><div>@@ -3556,10 +3556,39 @@</div><div>     return cuVariance / cnt;</div><div> }</div><div> </div><div>+double Analysis::aqQPOffset(const CUData& ctu, const CUGeom& cuGeom)</div><div>+{</div><div>+    uint32_t aqDepth = X265_MIN(cuGeom.depth, m_frame->m_lowres.maxAQDepth - 1);</div><div>+    PicQPAdaptationLayer* pQPLayer = &m_frame->m_lowres.pAQLayer[aqDepth];</div><div>+</div><div>+    uint32_t aqPosX = (ctu.m_cuPelX + g_zscanToPelX[cuGeom.absPartIdx]) / pQPLayer->aqPartWidth;</div><div>+    uint32_t aqPosY = (ctu.m_cuPelY + g_zscanToPelY[cuGeom.absPartIdx]) / pQPLayer->aqPartHeight;</div><div>+</div><div>+    uint32_t aqStride = pQPLayer->numAQPartInWidth;</div><div>+</div><div>+    double dQpOffset = pQPLayer->dQpOffset[aqPosY * aqStride + aqPosX];</div><div>+    return dQpOffset;</div><div>+}</div><div>+</div><div>+double Analysis::cuTreeQPOffset(const CUData& ctu, const CUGeom& cuGeom)</div><div>+{</div><div>+    uint32_t aqDepth = X265_MIN(cuGeom.depth, m_frame->m_lowres.maxAQDepth - 1);</div><div>+    PicQPAdaptationLayer* pcAQLayer = &m_frame->m_lowres.pAQLayer[aqDepth];</div><div>+</div><div>+    uint32_t aqPosX = (ctu.m_cuPelX + g_zscanToPelX[cuGeom.absPartIdx]) / pcAQLayer->aqPartWidth;</div><div>+    uint32_t aqPosY = (ctu.m_cuPelY + g_zscanToPelY[cuGeom.absPartIdx]) / pcAQLayer->aqPartHeight;</div><div>+</div><div>+    uint32_t aqStride = pcAQLayer->numAQPartInWidth;</div><div>+</div><div>+    double dQpOffset = pcAQLayer->dCuTreeOffset[aqPosY * aqStride + aqPosX];</div><div>+    return dQpOffset;</div><div>+}</div><div>+</div><div> int Analysis::calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom, int32_t complexCheck, double baseQp)</div><div> {</div><div>     FrameData& curEncData = *m_frame->m_encData;</div><div>     double qp = baseQp >= 0 ? baseQp : curEncData.m_cuStat[ctu.m_cuAddr].baseQp;</div><div>+    bool bCuTreeOffset = IS_REFERENCED(m_frame) && m_param->rc.cuTree && !complexCheck;</div><div> </div><div>     if ((m_param->analysisMultiPassDistortion && m_param->rc.bStatRead) || (m_param->ctuDistortionRefine && m_param->analysisLoad))</div><div>     {</div><div>@@ -3577,40 +3606,60 @@</div><div>         else</div><div>             return x265_clip3(m_param->rc.qpMin, m_param->rc.qpMax, (int32_t)(qp + 0.5 + ((x265_analysis_inter_data*)m_frame->m_analysisData.interData)->cuQPOff[cuIdx]));</div><div>     }</div><div>-    int loopIncr = (m_param->rc.qgSize == 8) ? 8 : 16;</div><div>-</div><div>-    /* Use cuTree offsets if cuTree enabled and frame is referenced, else use AQ offsets */</div><div>-    bool isReferenced = IS_REFERENCED(m_frame);</div><div>-    double *qpoffs = (isReferenced && m_param->rc.cuTree && !complexCheck) ? m_frame->m_lowres.qpCuTreeOffset :</div><div>-                                                                             m_frame->m_lowres.qpAqOffset;</div><div>-    if (qpoffs)</div><div>+    if (m_param->rc.hevcAq)</div><div>     {</div><div>-        uint32_t width = m_frame->m_fencPic->m_picWidth;</div><div>-        uint32_t height = m_frame->m_fencPic->m_picHeight;</div><div>-        uint32_t block_x = ctu.m_cuPelX + g_zscanToPelX[cuGeom.absPartIdx];</div><div>-        uint32_t block_y = ctu.m_cuPelY + g_zscanToPelY[cuGeom.absPartIdx];</div><div>-        uint32_t maxCols = (m_frame->m_fencPic->m_picWidth + (loopIncr - 1)) / loopIncr;</div><div>-        uint32_t blockSize = m_param->maxCUSize >> cuGeom.depth;</div><div>-        double qp_offset = 0;</div><div>-        uint32_t cnt = 0;</div><div>-        for (uint32_t block_yy = block_y; block_yy < block_y + blockSize && block_yy < height; block_yy += loopIncr)</div><div>+        /* Use cuTree offsets if cuTree enabled and frame is referenced, else use AQ offsets */</div><div>+        double dQpOffset = 0;</div><div>+        if (bCuTreeOffset)</div><div>         {</div><div>-            for (uint32_t block_xx = block_x; block_xx < block_x + blockSize && block_xx < width; block_xx += loopIncr)</div><div>+            dQpOffset = cuTreeQPOffset(ctu, cuGeom);</div><div>+        }</div><div>+        else</div><div>+        {</div><div>+            dQpOffset = aqQPOffset(ctu, cuGeom);</div><div>+            if (complexCheck)</div><div>             {</div><div>-                uint32_t idx = ((block_yy / loopIncr) * (maxCols)) + (block_xx / loopIncr);</div><div>-                qp_offset += qpoffs[idx];</div><div>-                cnt++;</div><div>+                int32_t offset = (int32_t)(dQpOffset * 100 + .5);</div><div>+                double threshold = (1 - ((x265_ADAPT_RD_STRENGTH - m_param->dynamicRd) * 0.5));</div><div>+                int32_t max_threshold = (int32_t)(threshold * 100 + .5);</div><div>+                return (offset < max_threshold);</div><div>             }</div><div>         }</div><div>-</div><div>-        qp_offset /= cnt;</div><div>-        qp += qp_offset;</div><div>-        if (complexCheck)</div><div>+        qp += dQpOffset;</div><div>+    }</div><div>+    else</div><div>+    {</div><div>+        int loopIncr = (m_param->rc.qgSize == 8) ? 8 : 16;</div><div>+        /* Use cuTree offsets if cuTree enabled and frame is referenced, else use AQ offsets */</div><div>+        double *qpoffs = bCuTreeOffset ? m_frame->m_lowres.qpCuTreeOffset : m_frame->m_lowres.qpAqOffset;</div><div>+        if (qpoffs)</div><div>         {</div><div>-            int32_t offset = (int32_t)(qp_offset * 100 + .5);</div><div>-            double threshold = (1 - ((x265_ADAPT_RD_STRENGTH - m_param->dynamicRd) * 0.5));</div><div>-            int32_t max_threshold = (int32_t)(threshold * 100 + .5);</div><div>-            return (offset < max_threshold);</div><div>+            uint32_t width = m_frame->m_fencPic->m_picWidth;</div><div>+            uint32_t height = m_frame->m_fencPic->m_picHeight;</div><div>+            uint32_t block_x = ctu.m_cuPelX + g_zscanToPelX[cuGeom.absPartIdx];</div><div>+            uint32_t block_y = ctu.m_cuPelY + g_zscanToPelY[cuGeom.absPartIdx];</div><div>+            uint32_t maxCols = (m_frame->m_fencPic->m_picWidth + (loopIncr - 1)) / loopIncr;</div><div>+            uint32_t blockSize = m_param->maxCUSize >> cuGeom.depth;</div><div>+            double dQpOffset = 0;</div><div>+            uint32_t cnt = 0;</div><div>+            for (uint32_t block_yy = block_y; block_yy < block_y + blockSize && block_yy < height; block_yy += loopIncr)</div><div>+            {</div><div>+                for (uint32_t block_xx = block_x; block_xx < block_x + blockSize && block_xx < width; block_xx += loopIncr)</div><div>+                {</div><div>+                    uint32_t idx = ((block_yy / loopIncr) * (maxCols)) + (block_xx / loopIncr);</div><div>+                    dQpOffset += qpoffs[idx];</div><div>+                    cnt++;</div><div>+                }</div><div>+            }</div><div>+            dQpOffset /= cnt;</div><div>+            qp += dQpOffset;</div><div>+            if (complexCheck)</div><div>+            {</div><div>+                int32_t offset = (int32_t)(dQpOffset * 100 + .5);</div><div>+                double threshold = (1 - ((x265_ADAPT_RD_STRENGTH - m_param->dynamicRd) * 0.5));</div><div>+                int32_t max_threshold = (int32_t)(threshold * 100 + .5);</div><div>+                return (offset < max_threshold);</div><div>+            }</div><div>         }</div><div>     }</div><div> </div><div>diff -r 129416ec0479 -r 3cd0b5ed0b91 source/encoder/analysis.h</div><div>--- a/source/encoder/analysis.h<span style="white-space:pre-wrap"> </span>Fri Dec 28 09:03:26 2018 +0530</div><div>+++ b/source/encoder/analysis.h<span style="white-space:pre-wrap">    </span>Thu Dec 27 14:43:54 2018 +0530</div><div>@@ -201,7 +201,8 @@</div><div> </div><div>     void classifyCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData);</div><div>     void trainCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData);</div><div>-</div><div>+    double aqQPOffset(const CUData& ctu, const CUGeom& cuGeom);</div><div>+    double cuTreeQPOffset(const CUData& ctu, const CUGeom& cuGeom);</div><div>     void calculateNormFactor(CUData& ctu, int qp);</div><div>     void normFactor(const pixel* src, uint32_t blockSize, CUData& ctu, int qp, TextType ttype);</div><div> </div><div>diff -r 129416ec0479 -r 3cd0b5ed0b91 source/encoder/encoder.cpp</div><div>--- a/source/encoder/encoder.cpp<span style="white-space:pre-wrap"> </span>Fri Dec 28 09:03:26 2018 +0530</div><div>+++ b/source/encoder/encoder.cpp<span style="white-space:pre-wrap">   </span>Thu Dec 27 14:43:54 2018 +0530</div><div>@@ -2839,6 +2839,12 @@</div><div>     if (p->rc.aqMode == X265_AQ_NONE && p->rc.cuTree == 0)</div><div>         p->rc.aqStrength = 0;</div><div> </div><div>+    if (p->rc.hevcAq && p->rc.aqMode)</div><div>+    {</div><div>+        p->rc.aqMode = X265_AQ_NONE;</div><div>+        x265_log(p, X265_LOG_WARNING, "hevc-aq enabled, disabling other aq-modes\n");</div><div>+    }</div><div>+</div><div>     if (p->totalFrames && p->totalFrames <= 2 * ((float)p->fpsNum) / p->fpsDenom && p->rc.bStrictCbr)</div><div>         p->lookaheadDepth = p->totalFrames;</div><div>     if (p->bIntraRefresh)</div><div>diff -r 129416ec0479 -r 3cd0b5ed0b91 source/encoder/ratecontrol.cpp</div><div>--- a/source/encoder/ratecontrol.cpp<span style="white-space:pre-wrap">       </span>Fri Dec 28 09:03:26 2018 +0530</div><div>+++ b/source/encoder/ratecontrol.cpp<span style="white-space:pre-wrap">       </span>Thu Dec 27 14:43:54 2018 +0530</div><div>@@ -153,10 +153,7 @@</div><div>     int lowresCuHeight = ((m_param->sourceHeight / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;</div><div>     m_ncu = lowresCuWidth * lowresCuHeight;</div><div> </div><div>-    if (m_param->rc.cuTree)</div><div>-        m_qCompress = 1;</div><div>-    else</div><div>-        m_qCompress = m_param->rc.qCompress;</div><div>+    m_qCompress = (m_param->rc.cuTree && !m_param->rc.hevcAq) ? 1 : m_param->rc.qCompress;</div><div> </div><div>     // validate for param->rc, maybe it is need to add a function like x265_parameters_valiate()</div><div>     m_residualFrames = 0;</div><div>@@ -381,13 +378,14 @@</div><div> </div><div>     m_isGrainEnabled = false;</div><div>     if(m_param->rc.bEnableGrain) // tune for grainy content OR equal p-b frame sizes</div><div>-    m_isGrainEnabled = true;</div><div>+        m_isGrainEnabled = true;</div><div>     for (int i = 0; i < 3; i++)</div><div>-    m_lastQScaleFor[i] = x265_qp2qScale(m_param->rc.rateControlMode == X265_RC_CRF ? CRF_INIT_QP : ABR_INIT_QP_MIN);</div><div>+        m_lastQScaleFor[i] = x265_qp2qScale(m_param->rc.rateControlMode == X265_RC_CRF ? CRF_INIT_QP : ABR_INIT_QP_MIN);</div><div>     m_avgPFrameQp = 0 ;</div><div> </div><div>     /* 720p videos seem to be a good cutoff for cplxrSum */</div><div>-    double tuneCplxFactor = (m_ncu > 3600 && m_param->rc.cuTree) ? 2.5 : m_isGrainEnabled ? 1.9 : 1;</div><div>+    double tuneCplxFactor = (m_ncu > 3600 && m_param->rc.cuTree && !m_param->rc.hevcAq) ? 2.5 : m_param->rc.hevcAq ? 1.5 : m_isGrainEnabled ? 1.9 : 1.0;</div><div>+</div><div>     /* estimated ratio that produces a reasonable QP for the first I-frame */</div><div>     m_cplxrSum = .01 * pow(7.0e5, m_qCompress) * pow(m_ncu, 0.5) * tuneCplxFactor;</div><div>     m_wantedBitsWindow = m_bitrate * m_frameDuration;</div><div>@@ -2563,7 +2561,7 @@</div><div> {</div><div>     double q;</div><div> </div><div>-    if (m_param->rc.cuTree)</div><div>+    if (m_param->rc.cuTree && !m_param->rc.hevcAq)</div><div>     {</div><div>         // Scale and units are obtained from rateNum and rateDenom for videos with fixed frame rates.</div><div>         double timescale = (double)m_param->fpsDenom / (2 * m_param->fpsNum);</div><div>@@ -2571,6 +2569,7 @@</div><div>     }</div><div>     else</div><div>         q = pow(rce->blurredComplexity, 1 - m_param->rc.qCompress);</div><div>+</div><div>     // avoid NaN's in the Rceq</div><div>     if (rce->coeffBits + rce->mvBits == 0)</div><div>         q = m_lastQScaleFor[rce->sliceType];</div><div>diff -r 129416ec0479 -r 3cd0b5ed0b91 source/encoder/slicetype.cpp</div><div>--- a/source/encoder/slicetype.cpp<span style="white-space:pre-wrap">        </span>Fri Dec 28 09:03:26 2018 +0530</div><div>+++ b/source/encoder/slicetype.cpp<span style="white-space:pre-wrap"> </span>Thu Dec 27 14:43:54 2018 +0530</div><div>@@ -3,6 +3,7 @@</div><div>  *</div><div>  * Authors: Gopu Govindaswamy <<a href="mailto:gopu@multicorewareinc.com" target="_blank">gopu@multicorewareinc.com</a>></div><div>  *          Steve Borho <<a href="mailto:steve@borho.org" target="_blank">steve@borho.org</a>></div><div>+ *          Ashok Kumar Mishra <<a href="mailto:ashok@multicorewareinc.com" target="_blank">ashok@multicorewareinc.com</a>></div><div>  *</div><div>  * This program is free software; you can redistribute it and/or modify</div><div>  * it under the terms of the GNU General Public License as published by</div><div>@@ -105,6 +106,7 @@</div><div>     x265_emms();</div><div>     return var;</div><div> }</div><div>+</div><div> /* Find the sum of pixels of each block for luma plane */</div><div> uint32_t LookaheadTLD::lumaSumCu(Frame* curFrame, uint32_t blockX, uint32_t blockY, uint32_t qgSize)</div><div> {</div><div>@@ -121,6 +123,157 @@</div><div>     return (uint32_t)sum_ssd;</div><div> }</div><div> </div><div>+void LookaheadTLD::xPreanalyzeQp(Frame* curFrame)</div><div>+{</div><div>+    const uint32_t width = curFrame->m_fencPic->m_picWidth;</div><div>+    const uint32_t height = curFrame->m_fencPic->m_picHeight;</div><div>+</div><div>+    for (uint32_t d = 0; d < 4; d++)</div><div>+    {</div><div>+        int ctuSizeIdx = 6 - g_log2Size[curFrame->m_param->maxCUSize];</div><div>+        int aqDepth = g_log2Size[curFrame->m_param->maxCUSize] - g_log2Size[curFrame->m_param->rc.qgSize];</div><div>+        if (!aqLayerDepth[ctuSizeIdx][aqDepth][d])</div><div>+            continue;</div><div>+</div><div>+        PicQPAdaptationLayer* pcAQLayer = &curFrame->m_lowres.pAQLayer[d];</div><div>+        const uint32_t aqPartWidth = pcAQLayer->aqPartWidth;</div><div>+        const uint32_t aqPartHeight = pcAQLayer->aqPartHeight;</div><div>+        double* pcAQU = pcAQLayer->dActivity;</div><div>+        double* pcQP = pcAQLayer->dQpOffset;</div><div>+        double* pcCuTree = pcAQLayer->dCuTreeOffset;</div><div>+</div><div>+        for (uint32_t y = 0; y < height; y += aqPartHeight)</div><div>+        {</div><div>+            for (uint32_t x = 0; x < width; x += aqPartWidth, pcAQU++, pcQP++, pcCuTree++)</div><div>+            {</div><div>+                double dMaxQScale = pow(2.0, curFrame->m_param->rc.qpAdaptationRange / 6.0);</div><div>+                double dCUAct = *pcAQU;</div><div>+                double dAvgAct = pcAQLayer->dAvgActivity;</div><div>+</div><div>+                double dNormAct = (dMaxQScale*dCUAct + dAvgAct) / (dCUAct + dMaxQScale*dAvgAct);</div><div>+                double dQpOffset = (X265_LOG2(dNormAct) / X265_LOG2(2.0)) * 6.0;</div><div>+                *pcQP = dQpOffset;</div><div>+                *pcCuTree = dQpOffset;</div><div>+            }</div><div>+        }</div><div>+    }</div><div>+}</div><div>+</div><div>+void LookaheadTLD::xPreanalyze(Frame* curFrame)</div><div>+{</div><div>+    const uint32_t width = curFrame->m_fencPic->m_picWidth;</div><div>+    const uint32_t height = curFrame->m_fencPic->m_picHeight;</div><div>+    const intptr_t stride = curFrame->m_fencPic->m_stride;</div><div>+</div><div>+    for (uint32_t d = 0; d < 4; d++)</div><div>+    {</div><div>+        int ctuSizeIdx = 6 - g_log2Size[curFrame->m_param->maxCUSize];</div><div>+        int aqDepth = g_log2Size[curFrame->m_param->maxCUSize] - g_log2Size[curFrame->m_param->rc.qgSize];</div><div>+        if (!aqLayerDepth[ctuSizeIdx][aqDepth][d])</div><div>+            continue;</div><div>+</div><div>+        const pixel* src = curFrame->m_fencPic->m_picOrg[0];;</div><div>+        PicQPAdaptationLayer* pQPLayer = &curFrame->m_lowres.pAQLayer[d];</div><div>+        const uint32_t aqPartWidth = pQPLayer->aqPartWidth;</div><div>+        const uint32_t aqPartHeight = pQPLayer->aqPartHeight;</div><div>+        double* pcAQU = pQPLayer->dActivity;</div><div>+</div><div>+        double dSumAct = 0.0;</div><div>+        for (uint32_t y = 0; y < height; y += aqPartHeight)</div><div>+        {</div><div>+            const uint32_t currAQPartHeight = X265_MIN(aqPartHeight, height - y);</div><div>+            for (uint32_t x = 0; x < width; x += aqPartWidth, pcAQU++)</div><div>+            {</div><div>+                const uint32_t currAQPartWidth = X265_MIN(aqPartWidth, width - x);</div><div>+                const pixel* pBlkY = &src[x];</div><div>+                uint64_t sum[4] = { 0, 0, 0, 0 };</div><div>+                uint64_t sumSq[4] = { 0, 0, 0, 0 };</div><div>+                uint32_t by = 0;</div><div>+                for (; by < currAQPartHeight >> 1; by++)</div><div>+                {</div><div>+                    uint32_t bx = 0;</div><div>+                    for (; bx < currAQPartWidth >> 1; bx++)</div><div>+                    {</div><div>+                        sum[0] += pBlkY[bx];</div><div>+                        sumSq[0] += pBlkY[bx] * pBlkY[bx];</div><div>+                    }</div><div>+                    for (; bx < currAQPartWidth; bx++)</div><div>+                    {</div><div>+                        sum[1] += pBlkY[bx];</div><div>+                        sumSq[1] += pBlkY[bx] * pBlkY[bx];</div><div>+                    }</div><div>+                    pBlkY += stride;</div><div>+                }</div><div>+                for (; by < currAQPartHeight; by++)</div><div>+                {</div><div>+                    uint32_t bx = 0;</div><div>+                    for (; bx < currAQPartWidth >> 1; bx++)</div><div>+                    {</div><div>+                        sum[2] += pBlkY[bx];</div><div>+                        sumSq[2] += pBlkY[bx] * pBlkY[bx];</div><div>+                    }</div><div>+                    for (; bx < currAQPartWidth; bx++)</div><div>+                    {</div><div>+                        sum[3] += pBlkY[bx];</div><div>+                        sumSq[3] += pBlkY[bx] * pBlkY[bx];</div><div>+                    }</div><div>+                    pBlkY += stride;</div><div>+                }</div><div>+</div><div>+                assert((currAQPartWidth & 1) == 0);</div><div>+                assert((currAQPartHeight & 1) == 0);</div><div>+                const uint32_t pixelWidthOfQuadrants = currAQPartWidth >> 1;</div><div>+                const uint32_t pixelHeightOfQuadrants = currAQPartHeight >> 1;</div><div>+                const uint32_t numPixInAQPart = pixelWidthOfQuadrants * pixelHeightOfQuadrants;</div><div>+</div><div>+                double dMinVar = MAX_DOUBLE;</div><div>+                if (numPixInAQPart != 0)</div><div>+                {</div><div>+                    for (int i = 0; i < 4; i++)</div><div>+                    {</div><div>+                        const double dAverage = double(sum[i]) / numPixInAQPart;</div><div>+                        const double dVariance = double(sumSq[i]) / numPixInAQPart - dAverage * dAverage;</div><div>+                        dMinVar = X265_MIN(dMinVar, dVariance);</div><div>+                    }</div><div>+                }</div><div>+                else</div><div>+                {</div><div>+                    dMinVar = 0.0;</div><div>+                }</div><div>+                double dActivity = 1.0 + dMinVar;</div><div>+                *pcAQU = dActivity;</div><div>+                dSumAct += dActivity;</div><div>+            }</div><div>+            src += stride * currAQPartHeight;</div><div>+        }</div><div>+</div><div>+        const double dAvgAct = dSumAct / (pQPLayer->numAQPartInWidth * pQPLayer->numAQPartInHeight);</div><div>+        pQPLayer->dAvgActivity = dAvgAct;</div><div>+    }</div><div>+</div><div>+    xPreanalyzeQp(curFrame);</div><div>+</div><div>+    int minAQDepth = curFrame->m_lowres.pAQLayer->minAQDepth;</div><div>+</div><div>+    PicQPAdaptationLayer* pQPLayer = &curFrame->m_lowres.pAQLayer[minAQDepth];</div><div>+    const uint32_t aqPartWidth = pQPLayer->aqPartWidth;</div><div>+    const uint32_t aqPartHeight = pQPLayer->aqPartHeight;</div><div>+    double* pcQP = pQPLayer->dQpOffset;</div><div>+</div><div>+    // Use new qp offset values for qpAqOffset, qpCuTreeOffset and invQscaleFactor buffer</div><div>+    int blockXY = 0;</div><div>+    for (uint32_t y = 0; y < height; y += aqPartHeight)</div><div>+    {</div><div>+        for (uint32_t x = 0; x < width; x += aqPartWidth, pcQP++)</div><div>+        {</div><div>+            curFrame->m_lowres.invQscaleFactor[blockXY] = x265_exp2fix8(*pcQP);</div><div>+            blockXY++;</div><div>+</div><div>+            acEnergyCu(curFrame, x, y, curFrame->m_param->internalCsp, curFrame->m_param->rc.qgSize);</div><div>+        }</div><div>+    }</div><div>+}</div><div>+</div><div> void LookaheadTLD::calcAdaptiveQuantFrame(Frame *curFrame, x265_param* param)</div><div> {</div><div>     /* Actual adaptive quantization */</div><div>@@ -176,90 +329,99 @@</div><div>         if (param->bEnableWeightedPred || param->bEnableWeightedBiPred)</div><div>         {</div><div>             for (int blockY = 0; blockY < maxRow; blockY += loopIncr)</div><div>-                for (int blockX = 0; blockX < maxCol; blockX += loopIncr)                </div><div>-                    acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);                </div><div>+                for (int blockX = 0; blockX < maxCol; blockX += loopIncr)</div><div>+                    acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);</div><div>         }</div><div>     }</div><div>     else</div><div>     {</div><div>-        int blockXY = 0;</div><div>-        double avg_adj_pow2 = 0.f, avg_adj = 0.f, qp_adj = 0.f;</div><div>-        double bias_strength = 0.f, strength = 0.f;</div><div>-        if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE || param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED)</div><div>+        if (param->rc.hevcAq)</div><div>         {</div><div>-            double bit_depth_correction = 1.f / (1 << (2*(X265_DEPTH-8)));            </div><div>-            </div><div>-            for (int blockY = 0; blockY < maxRow; blockY += loopIncr)</div><div>-            {                </div><div>-                for (int blockX = 0; blockX < maxCol; blockX += loopIncr)</div><div>-                {</div><div>-                    uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);                    </div><div>-                    qp_adj = pow(energy * bit_depth_correction + 1, 0.1);</div><div>-                    curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj;</div><div>-                    avg_adj += qp_adj;</div><div>-                    avg_adj_pow2 += qp_adj * qp_adj;</div><div>-                    blockXY++;</div><div>-                }</div><div>-            }</div><div>-            avg_adj /= blockCount;</div><div>-            avg_adj_pow2 /= blockCount;</div><div>-            strength = param->rc.aqStrength * avg_adj;</div><div>-            avg_adj = avg_adj - 0.5f * (avg_adj_pow2 - modeTwoConst) / avg_adj;</div><div>-            bias_strength = param->rc.aqStrength;</div><div>+            // New method for calculating variance and qp offset</div><div>+            xPreanalyze(curFrame);</div><div>         }</div><div>         else</div><div>-            strength = param->rc.aqStrength * 1.0397f;</div><div>-</div><div>-        blockXY = 0;</div><div>-        for (int blockY = 0; blockY < maxRow; blockY += loopIncr)</div><div>         {</div><div>-            for (int blockX = 0; blockX < maxCol; blockX += loopIncr)</div><div>+            int blockXY = 0;</div><div>+            double avg_adj_pow2 = 0, avg_adj = 0, qp_adj = 0;</div><div>+            double bias_strength = 0.f;</div><div>+            double strength = 0.f;</div><div>+            if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE || param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED)</div><div>             {</div><div>-                if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED)</div><div>-                {</div><div>-                    qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY];</div><div>-                    qp_adj = strength * (qp_adj - avg_adj) + bias_strength * (1.f - modeTwoConst / (qp_adj * qp_adj));</div><div>-                }</div><div>-                else if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE)</div><div>-                {</div><div>-                    qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY];</div><div>-                    qp_adj = strength * (qp_adj - avg_adj);</div><div>-                }</div><div>-                else</div><div>-                {</div><div>-                    uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp,param->rc.qgSize);</div><div>-                    qp_adj = strength * (X265_LOG2(X265_MAX(energy, 1)) - (modeOneConst + 2 * (X265_DEPTH - 8)));                    </div><div>-                }</div><div>-</div><div>-                if (param->bHDROpt)</div><div>+                double bit_depth_correction = 1.f / (1 << (2 * (X265_DEPTH - 8)));</div><div>+</div><div>+                for (int blockY = 0; blockY < maxRow; blockY += loopIncr)</div><div>                 {</div><div>-                    uint32_t sum = lumaSumCu(curFrame, blockX, blockY, param->rc.qgSize);</div><div>-                    uint32_t lumaAvg = sum / (loopIncr * loopIncr);</div><div>-                    if (lumaAvg < 301)</div><div>-                        qp_adj += 3;</div><div>-                    else if (lumaAvg >= 301 && lumaAvg < 367)</div><div>-                        qp_adj += 2;</div><div>-                    else if (lumaAvg >= 367 && lumaAvg < 434)</div><div>-                        qp_adj += 1;</div><div>-                    else if (lumaAvg >= 501 && lumaAvg < 567)</div><div>-                        qp_adj -= 1;</div><div>-                    else if (lumaAvg >= 567 && lumaAvg < 634)</div><div>-                        qp_adj -= 2;</div><div>-                    else if (lumaAvg >= 634 && lumaAvg < 701)</div><div>-                        qp_adj -= 3;</div><div>-                    else if (lumaAvg >= 701 && lumaAvg < 767)</div><div>-                        qp_adj -= 4;</div><div>-                    else if (lumaAvg >= 767 && lumaAvg < 834)</div><div>-                        qp_adj -= 5;</div><div>-                    else if (lumaAvg >= 834)</div><div>-                        qp_adj -= 6;</div><div>+                    for (int blockX = 0; blockX < maxCol; blockX += loopIncr)</div><div>+                    {</div><div>+                        uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);</div><div>+                        qp_adj = pow(energy * bit_depth_correction + 1, 0.1);</div><div>+                        curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj;</div><div>+                        avg_adj += qp_adj;</div><div>+                        avg_adj_pow2 += qp_adj * qp_adj;</div><div>+                        blockXY++;</div><div>+                    }</div><div>                 }</div><div>-                if (quantOffsets != NULL)</div><div>-                    qp_adj += quantOffsets[blockXY];</div><div>-                curFrame->m_lowres.qpAqOffset[blockXY] = qp_adj;</div><div>-                curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj;</div><div>-                curFrame->m_lowres.invQscaleFactor[blockXY] = x265_exp2fix8(qp_adj);</div><div>-                blockXY++;</div><div>+                avg_adj /= blockCount;</div><div>+                avg_adj_pow2 /= blockCount;</div><div>+                strength = param->rc.aqStrength * avg_adj;</div><div>+                avg_adj = avg_adj - 0.5f * (avg_adj_pow2 - modeTwoConst) / avg_adj;</div><div>+                bias_strength = param->rc.aqStrength;</div><div>+            }</div><div>+            else</div><div>+                strength = param->rc.aqStrength * 1.0397f;</div><div>+</div><div>+            blockXY = 0;</div><div>+            for (int blockY = 0; blockY < maxRow; blockY += loopIncr)</div><div>+            {</div><div>+                for (int blockX = 0; blockX < maxCol; blockX += loopIncr)</div><div>+                {</div><div>+                    if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED)</div><div>+                    {</div><div>+                        qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY];</div><div>+                        qp_adj = strength * (qp_adj - avg_adj) + bias_strength * (1.f - modeTwoConst / (qp_adj * qp_adj));</div><div>+                    }</div><div>+                    else if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE)</div><div>+                    {</div><div>+                        qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY];</div><div>+                        qp_adj = strength * (qp_adj - avg_adj);</div><div>+                    }</div><div>+                    else</div><div>+                    {</div><div>+                        uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);</div><div>+                        qp_adj = strength * (X265_LOG2(X265_MAX(energy, 1)) - (modeOneConst + 2 * (X265_DEPTH - 8)));</div><div>+                    }</div><div>+</div><div>+                    if (param->bHDROpt)</div><div>+                    {</div><div>+                        uint32_t sum = lumaSumCu(curFrame, blockX, blockY, param->rc.qgSize);</div><div>+                        uint32_t lumaAvg = sum / (loopIncr * loopIncr);</div><div>+                        if (lumaAvg < 301)</div><div>+                            qp_adj += 3;</div><div>+                        else if (lumaAvg >= 301 && lumaAvg < 367)</div><div>+                            qp_adj += 2;</div><div>+                        else if (lumaAvg >= 367 && lumaAvg < 434)</div><div>+                            qp_adj += 1;</div><div>+                        else if (lumaAvg >= 501 && lumaAvg < 567)</div><div>+                            qp_adj -= 1;</div><div>+                        else if (lumaAvg >= 567 && lumaAvg < 634)</div><div>+                            qp_adj -= 2;</div><div>+                        else if (lumaAvg >= 634 && lumaAvg < 701)</div><div>+                            qp_adj -= 3;</div><div>+                        else if (lumaAvg >= 701 && lumaAvg < 767)</div><div>+                            qp_adj -= 4;</div><div>+                        else if (lumaAvg >= 767 && lumaAvg < 834)</div><div>+                            qp_adj -= 5;</div><div>+                        else if (lumaAvg >= 834)</div><div>+                            qp_adj -= 6;</div><div>+                    }</div><div>+                    if (quantOffsets != NULL)</div><div>+                        qp_adj += quantOffsets[blockXY];</div><div>+                    curFrame->m_lowres.qpAqOffset[blockXY] = qp_adj;</div><div>+                    curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj;</div><div>+                    curFrame->m_lowres.invQscaleFactor[blockXY] = x265_exp2fix8(qp_adj);</div><div>+                    blockXY++;</div><div>+                }</div><div>             }</div><div>         }</div><div>     }</div><div>@@ -301,11 +463,13 @@</div><div>     {</div><div>         int blockXY = 0;</div><div>         for (int blockY = 0; blockY < maxRow; blockY += loopIncr)</div><div>+        {</div><div>             for (int blockX = 0; blockX < maxCol; blockX += loopIncr)</div><div>             {</div><div>                 curFrame->m_lowres.blockVariance[blockXY] = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);</div><div>                 blockXY++;</div><div>             }</div><div>+        }</div><div>     }</div><div> }</div><div> </div><div>@@ -596,13 +760,16 @@</div><div> </div><div>     /* Allow the strength to be adjusted via qcompress, since the two concepts</div><div>      * are very similar. */</div><div>-</div><div>-    m_cuTreeStrength = 5.0 * (1.0 - m_param->rc.qCompress);</div><div>+    m_cuTreeStrength = (m_param->rc.hevcAq ? 6.0 : 5.0) * (1.0 - m_param->rc.qCompress);</div><div> </div><div>     m_lastKeyframe = -m_param->keyframeMax;</div><div>     m_sliceTypeBusy = false;</div><div>     m_fullQueueSize = X265_MAX(1, m_param->lookaheadDepth);</div><div>-    m_bAdaptiveQuant = m_param->rc.aqMode || m_param->bEnableWeightedPred || m_param->bEnableWeightedBiPred || m_param->bAQMotion;</div><div>+    m_bAdaptiveQuant = m_param->rc.aqMode ||</div><div>+                       m_param->bEnableWeightedPred ||</div><div>+                       m_param->bEnableWeightedBiPred ||</div><div>+                       m_param->bAQMotion ||</div><div>+                       m_param->rc.hevcAq;</div><div> </div><div>     /* If we have a thread pool and are using --b-adapt 2, it is generally</div><div>      * preferable to perform all motion searches for each lowres frame in large</div><div>@@ -919,6 +1086,7 @@</div><div>     if (!m_param->analysisLoad || !m_param->bDisableLookahead)</div><div>     {</div><div>         X265_CHECK(curFrame->m_lowres.costEst[b - p0][p1 - b] > 0, "Slice cost not estimated\n")</div><div>+</div><div>         if (m_param->rc.cuTree && !m_param->rc.bStatRead)</div><div>             /* update row satds based on cutree offsets */</div><div>             curFrame->m_lowres.satdCost = frameCostRecalculate(frames, p0, p1, b);</div><div>@@ -1695,6 +1863,7 @@</div><div> </div><div>     if (m_param->rc.cuTree)</div><div>         cuTree(frames, X265_MIN(numFrames, m_param->keyframeMax), bKeyframe);</div><div>+</div><div>     if (m_param->gopLookahead && (keyFrameLimit >= 0) && (keyFrameLimit <= m_param->bframes + 1) && !m_extendGopBoundary)</div><div>         keyintLimit = keyFrameLimit;</div><div> </div><div>@@ -1928,6 +2097,7 @@</div><div> </div><div>     return cost;</div><div> }</div><div>+</div><div> void Lookahead::aqMotion(Lowres **frames, bool bIntra)</div><div> {</div><div>     if (!bIntra)</div><div>@@ -2223,44 +2393,191 @@</div><div>         cuTreeFinish(frames[b], averageDuration, b == p1 ? b - p0 : 0);</div><div> }</div><div> </div><div>-void Lookahead::cuTreeFinish(Lowres *frame, double averageDuration, int ref0Distance)</div><div>+void Lookahead::computeCUTreeQpOffset(Lowres *frame, double averageDuration, int ref0Distance)</div><div> {</div><div>     int fpsFactor = (int)(CLIP_DURATION(averageDuration) / CLIP_DURATION((double)m_param->fpsDenom / m_param->fpsNum) * 256);</div><div>+    uint32_t loopIncr = (m_param->rc.qgSize == 8) ? 8 : 16;</div><div>+</div><div>     double weightdelta = 0.0;</div><div>-</div><div>     if (ref0Distance && frame->weightedCostDelta[ref0Distance - 1] > 0)</div><div>         weightdelta = (1.0 - frame->weightedCostDelta[ref0Distance - 1]);</div><div> </div><div>+    uint32_t widthFullRes = frame->widthFullRes;</div><div>+    uint32_t heightFullRes = frame->heightFullRes;</div><div>+</div><div>     if (m_param->rc.qgSize == 8)</div><div>     {</div><div>+        int minAQDepth = frame->pAQLayer->minAQDepth;</div><div>+</div><div>+        PicQPAdaptationLayer* pQPLayerMin = &frame->pAQLayer[minAQDepth];</div><div>+        double* pcCuTree8x8 = pQPLayerMin->dCuTreeOffset8x8;</div><div>+</div><div>         for (int cuY = 0; cuY < m_8x8Height; cuY++)</div><div>         {</div><div>             for (int cuX = 0; cuX < m_8x8Width; cuX++)</div><div>             {</div><div>                 const int cuXY = cuX + cuY * m_8x8Width;</div><div>-                int intracost = ((frame->intraCost[cuXY]) / 4 * frame->invQscaleFactor8x8[cuXY] + 128) >> 8;</div><div>+                int intracost = ((frame->intraCost[cuXY] / 4) * frame->invQscaleFactor8x8[cuXY] + 128) >> 8;</div><div>                 if (intracost)</div><div>                 {</div><div>-                    int propagateCost = ((frame->propagateCost[cuXY]) / 4 * fpsFactor + 128) >> 8;</div><div>+                    int propagateCost = ((frame->propagateCost[cuXY] / 4)  * fpsFactor + 128) >> 8;</div><div>                     double log2_ratio = X265_LOG2(intracost + propagateCost) - X265_LOG2(intracost) + weightdelta;</div><div>-                    frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4] - m_cuTreeStrength * (log2_ratio);</div><div>-                    frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + 1] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + 1] - m_cuTreeStrength * (log2_ratio);</div><div>-                    frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes] - m_cuTreeStrength * (log2_ratio);</div><div>-                    frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes + 1] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes + 1] - m_cuTreeStrength * (log2_ratio);</div><div>+</div><div>+                    pcCuTree8x8[cuX * 2 + cuY * m_8x8Width * 4] = log2_ratio;</div><div>+                    pcCuTree8x8[cuX * 2 + cuY * m_8x8Width * 4 + 1] = log2_ratio;</div><div>+                    pcCuTree8x8[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes] = log2_ratio;</div><div>+                    pcCuTree8x8[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes + 1] = log2_ratio;</div><div>+                }</div><div>+            }</div><div>+        }</div><div>+</div><div>+        for (uint32_t d = 0; d < 4; d++)</div><div>+        {</div><div>+            int ctuSizeIdx = 6 - g_log2Size[m_param->maxCUSize];</div><div>+            int aqDepth = g_log2Size[m_param->maxCUSize] - g_log2Size[m_param->rc.qgSize];</div><div>+            if (!aqLayerDepth[ctuSizeIdx][aqDepth][d])</div><div>+                continue;</div><div>+</div><div>+            PicQPAdaptationLayer* pQPLayer = &frame->pAQLayer[d];</div><div>+            const uint32_t aqPartWidth = pQPLayer->aqPartWidth;</div><div>+            const uint32_t aqPartHeight = pQPLayer->aqPartHeight;</div><div>+</div><div>+            const uint32_t numAQPartInWidth = pQPLayer->numAQPartInWidth;</div><div>+            const uint32_t numAQPartInHeight = pQPLayer->numAQPartInHeight;</div><div>+</div><div>+            double* pcQP = pQPLayer->dQpOffset;</div><div>+            double* pcCuTree = pQPLayer->dCuTreeOffset;</div><div>+</div><div>+            uint32_t maxCols = frame->maxBlocksInRowFullRes;</div><div>+</div><div>+            for (uint32_t y = 0; y < numAQPartInHeight; y++)</div><div>+            {</div><div>+                for (uint32_t x = 0; x < numAQPartInWidth; x++, pcQP++, pcCuTree++)</div><div>+                {</div><div>+                    uint32_t block_x = x * aqPartWidth;</div><div>+                    uint32_t block_y = y * aqPartHeight;</div><div>+</div><div>+                    uint32_t blockXY = 0;</div><div>+                    double log2_ratio = 0;</div><div>+                    for (uint32_t block_yy = block_y; block_yy < block_y + aqPartHeight && block_yy < heightFullRes; block_yy += loopIncr)</div><div>+                    {</div><div>+                        for (uint32_t block_xx = block_x; block_xx < block_x + aqPartWidth && block_xx < widthFullRes; block_xx += loopIncr)</div><div>+                        {</div><div>+                            uint32_t idx = ((block_yy / loopIncr) * (maxCols)) + (block_xx / loopIncr);</div><div>+</div><div>+                            log2_ratio += *(pcCuTree8x8 + idx);</div><div>+                            </div><div>+                            blockXY++;</div><div>+                        }</div><div>+                    }</div><div>+</div><div>+                    double qp_offset = (m_cuTreeStrength * log2_ratio) / blockXY;</div><div>+</div><div>+                    *pcCuTree = *pcQP - qp_offset;</div><div>                 }</div><div>             }</div><div>         }</div><div>     }</div><div>     else</div><div>     {</div><div>-        for (int cuIndex = 0; cuIndex < m_cuCount; cuIndex++)</div><div>+        for (uint32_t d = 0; d < 4; d++)</div><div>         {</div><div>-            int intracost = (frame->intraCost[cuIndex] * frame->invQscaleFactor[cuIndex] + 128) >> 8;</div><div>-            if (intracost)</div><div>+            int ctuSizeIdx = 6 - g_log2Size[m_param->maxCUSize];</div><div>+            int aqDepth = g_log2Size[m_param->maxCUSize] - g_log2Size[m_param->rc.qgSize];</div><div>+            if (!aqLayerDepth[ctuSizeIdx][aqDepth][d])</div><div>+                continue;</div><div>+</div><div>+            PicQPAdaptationLayer* pQPLayer = &frame->pAQLayer[d];</div><div>+            const uint32_t aqPartWidth = pQPLayer->aqPartWidth;</div><div>+            const uint32_t aqPartHeight = pQPLayer->aqPartHeight;</div><div>+</div><div>+            const uint32_t numAQPartInWidth = pQPLayer->numAQPartInWidth;</div><div>+            const uint32_t numAQPartInHeight = pQPLayer->numAQPartInHeight;</div><div>+</div><div>+            double* pcQP = pQPLayer->dQpOffset;</div><div>+            double* pcCuTree = pQPLayer->dCuTreeOffset;</div><div>+</div><div>+            uint32_t maxCols = frame->maxBlocksInRow;</div><div>+</div><div>+            for (uint32_t y = 0; y < numAQPartInHeight; y++)</div><div>             {</div><div>-                int propagateCost = (frame->propagateCost[cuIndex] * fpsFactor + 128) >> 8;</div><div>-                double log2_ratio = X265_LOG2(intracost + propagateCost) - X265_LOG2(intracost) + weightdelta;</div><div>-                frame->qpCuTreeOffset[cuIndex] = frame->qpAqOffset[cuIndex] - m_cuTreeStrength * log2_ratio;</div><div>+                for (uint32_t x = 0; x < numAQPartInWidth; x++, pcQP++, pcCuTree++)</div><div>+                {</div><div>+                    uint32_t block_x = x * aqPartWidth;</div><div>+                    uint32_t block_y = y * aqPartHeight;</div><div>+</div><div>+                    uint32_t blockXY = 0;</div><div>+                    double log2_ratio = 0;</div><div>+                    for (uint32_t block_yy = block_y; block_yy < block_y + aqPartHeight && block_yy < heightFullRes; block_yy += loopIncr)</div><div>+                    {</div><div>+                        for (uint32_t block_xx = block_x; block_xx < block_x + aqPartWidth && block_xx < widthFullRes; block_xx += loopIncr)</div><div>+                        {</div><div>+                            uint32_t idx = ((block_yy / loopIncr) * (maxCols)) + (block_xx / loopIncr);</div><div>+</div><div>+                            int intraCost = (frame->intraCost[idx] * frame->invQscaleFactor[idx] + 128) >> 8;</div><div>+                            int propagateCost = (frame->propagateCost[idx] * fpsFactor + 128) >> 8;</div><div>+</div><div>+                            log2_ratio += (X265_LOG2(intraCost + propagateCost) - X265_LOG2(intraCost) + weightdelta);</div><div>+</div><div>+                            blockXY++;</div><div>+                        }</div><div>+                    }</div><div>+</div><div>+                    double qp_offset = (m_cuTreeStrength * log2_ratio) / blockXY;</div><div>+</div><div>+                    *pcCuTree = *pcQP - qp_offset;</div><div>+</div><div>+                }</div><div>+            }</div><div>+        }</div><div>+    }</div><div>+}</div><div>+</div><div>+void Lookahead::cuTreeFinish(Lowres *frame, double averageDuration, int ref0Distance)</div><div>+{</div><div>+    if (m_param->rc.hevcAq)</div><div>+    {</div><div>+        computeCUTreeQpOffset(frame, averageDuration, ref0Distance);</div><div>+    }</div><div>+    else</div><div>+    {</div><div>+        int fpsFactor = (int)(CLIP_DURATION(averageDuration) / CLIP_DURATION((double)m_param->fpsDenom / m_param->fpsNum) * 256);</div><div>+        double weightdelta = 0.0;</div><div>+</div><div>+        if (ref0Distance && frame->weightedCostDelta[ref0Distance - 1] > 0)</div><div>+            weightdelta = (1.0 - frame->weightedCostDelta[ref0Distance - 1]);</div><div>+</div><div>+        if (m_param->rc.qgSize == 8)</div><div>+        {</div><div>+            for (int cuY = 0; cuY < m_8x8Height; cuY++)</div><div>+            {</div><div>+                for (int cuX = 0; cuX < m_8x8Width; cuX++)</div><div>+                {</div><div>+                    const int cuXY = cuX + cuY * m_8x8Width;</div><div>+                    int intracost = ((frame->intraCost[cuXY]) / 4 * frame->invQscaleFactor8x8[cuXY] + 128) >> 8;</div><div>+                    if (intracost)</div><div>+                    {</div><div>+                        int propagateCost = ((frame->propagateCost[cuXY]) / 4 * fpsFactor + 128) >> 8;</div><div>+                        double log2_ratio = X265_LOG2(intracost + propagateCost) - X265_LOG2(intracost) + weightdelta;</div><div>+                        frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4] - m_cuTreeStrength * (log2_ratio);</div><div>+                        frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + 1] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + 1] - m_cuTreeStrength * (log2_ratio);</div><div>+                        frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes] - m_cuTreeStrength * (log2_ratio);</div><div>+                        frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes + 1] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes + 1] - m_cuTreeStrength * (log2_ratio);</div><div>+                    }</div><div>+                }</div><div>+            }</div><div>+        }</div><div>+        else</div><div>+        {</div><div>+            for (int cuIndex = 0; cuIndex < m_cuCount; cuIndex++)</div><div>+            {</div><div>+                int intracost = (frame->intraCost[cuIndex] * frame->invQscaleFactor[cuIndex] + 128) >> 8;</div><div>+                if (intracost)</div><div>+                {</div><div>+                    int propagateCost = (frame->propagateCost[cuIndex] * fpsFactor + 128) >> 8;</div><div>+                    double log2_ratio = X265_LOG2(intracost + propagateCost) - X265_LOG2(intracost) + weightdelta;</div><div>+                    frame->qpCuTreeOffset[cuIndex] = frame->qpAqOffset[cuIndex] - m_cuTreeStrength * log2_ratio;</div><div>+                }</div><div>             }</div><div>         }</div><div>     }</div><div>@@ -2275,31 +2592,71 @@</div><div> </div><div>     int64_t score = 0;</div><div>     int *rowSatd = frames[b]->rowSatds[b - p0][p1 - b];</div><div>-    double *qp_offset = frames[b]->qpCuTreeOffset;</div><div> </div><div>     x265_emms();</div><div>-    for (int cuy = m_8x8Height - 1; cuy >= 0; cuy--)</div><div>+</div><div>+    if (m_param->rc.hevcAq)</div><div>     {</div><div>-        rowSatd[cuy] = 0;</div><div>-        for (int cux = m_8x8Width - 1; cux >= 0; cux--)</div><div>+        int minAQDepth = frames[b]->pAQLayer->minAQDepth;</div><div>+        PicQPAdaptationLayer* pQPLayer = &frames[b]->pAQLayer[minAQDepth];</div><div>+        double* pcQPCuTree = pQPLayer->dCuTreeOffset;</div><div>+</div><div>+        // Use new qp offset values for qpAqOffset, qpCuTreeOffset and invQscaleFactor buffer</div><div>+        for (int cuy = m_8x8Height - 1; cuy >= 0; cuy--)</div><div>         {</div><div>-            int cuxy = cux + cuy * m_8x8Width;</div><div>-            int cuCost = frames[b]->lowresCosts[b - p0][p1 - b][cuxy] & LOWRES_COST_MASK;</div><div>-            double qp_adj;</div><div>-            if (m_param->rc.qgSize == 8)</div><div>-                qp_adj = (qp_offset[cux * 2 + cuy * m_8x8Width * 4] +</div><div>-                          qp_offset[cux * 2 + cuy * m_8x8Width * 4 + 1] +</div><div>-                          qp_offset[cux * 2 + cuy * m_8x8Width * 4 + frames[b]->maxBlocksInRowFullRes] +</div><div>-                          qp_offset[cux * 2 + cuy * m_8x8Width * 4 + frames[b]->maxBlocksInRowFullRes + 1]) / 4;</div><div>-            else </div><div>-                qp_adj = qp_offset[cuxy];</div><div>-            cuCost = (cuCost * x265_exp2fix8(qp_adj) + 128) >> 8;</div><div>-            rowSatd[cuy] += cuCost;</div><div>-            if ((cuy > 0 && cuy < m_8x8Height - 1 &&</div><div>-                 cux > 0 && cux < m_8x8Width - 1) ||</div><div>-                m_8x8Width <= 2 || m_8x8Height <= 2)</div><div>+            rowSatd[cuy] = 0;</div><div>+            for (int cux = m_8x8Width - 1; cux >= 0; cux--)</div><div>             {</div><div>-                score += cuCost;</div><div>+                int cuxy = cux + cuy * m_8x8Width;</div><div>+                int cuCost = frames[b]->lowresCosts[b - p0][p1 - b][cuxy] & LOWRES_COST_MASK;</div><div>+                double qp_adj;</div><div>+</div><div>+                if (m_param->rc.qgSize == 8)</div><div>+                    qp_adj = (pcQPCuTree[cux * 2 + cuy * m_8x8Width * 4] +</div><div>+                    pcQPCuTree[cux * 2 + cuy * m_8x8Width * 4 + 1] +</div><div>+                    pcQPCuTree[cux * 2 + cuy * m_8x8Width * 4 + frames[b]->maxBlocksInRowFullRes] +</div><div>+                    pcQPCuTree[cux * 2 + cuy * m_8x8Width * 4 + frames[b]->maxBlocksInRowFullRes + 1]) / 4;</div><div>+                else</div><div>+                    qp_adj = *(pcQPCuTree + cuxy);</div><div>+</div><div>+                cuCost = (cuCost * x265_exp2fix8(qp_adj) + 128) >> 8;</div><div>+                rowSatd[cuy] += cuCost;</div><div>+                if ((cuy > 0 && cuy < m_8x8Height - 1 &&</div><div>+                    cux > 0 && cux < m_8x8Width - 1) ||</div><div>+                    m_8x8Width <= 2 || m_8x8Height <= 2)</div><div>+                {</div><div>+                    score += cuCost;</div><div>+                }</div><div>+            }</div><div>+        }</div><div>+    }</div><div>+    else</div><div>+    {</div><div>+        double *qp_offset = frames[b]->qpCuTreeOffset;</div><div>+</div><div>+        for (int cuy = m_8x8Height - 1; cuy >= 0; cuy--)</div><div>+        {</div><div>+            rowSatd[cuy] = 0;</div><div>+            for (int cux = m_8x8Width - 1; cux >= 0; cux--)</div><div>+            {</div><div>+                int cuxy = cux + cuy * m_8x8Width;</div><div>+                int cuCost = frames[b]->lowresCosts[b - p0][p1 - b][cuxy] & LOWRES_COST_MASK;</div><div>+                double qp_adj;</div><div>+                if (m_param->rc.qgSize == 8)</div><div>+                    qp_adj = (qp_offset[cux * 2 + cuy * m_8x8Width * 4] +</div><div>+                    qp_offset[cux * 2 + cuy * m_8x8Width * 4 + 1] +</div><div>+                    qp_offset[cux * 2 + cuy * m_8x8Width * 4 + frames[b]->maxBlocksInRowFullRes] +</div><div>+                    qp_offset[cux * 2 + cuy * m_8x8Width * 4 + frames[b]->maxBlocksInRowFullRes + 1]) / 4;</div><div>+                else </div><div>+                    qp_adj = qp_offset[cuxy];</div><div>+                cuCost = (cuCost * x265_exp2fix8(qp_adj) + 128) >> 8;</div><div>+                rowSatd[cuy] += cuCost;</div><div>+                if ((cuy > 0 && cuy < m_8x8Height - 1 &&</div><div>+                    cux > 0 && cux < m_8x8Width - 1) ||</div><div>+                    m_8x8Width <= 2 || m_8x8Height <= 2)</div><div>+                {</div><div>+                    score += cuCost;</div><div>+                }</div><div>             }</div><div>         }</div><div>     }</div><div>diff -r 129416ec0479 -r 3cd0b5ed0b91 source/encoder/slicetype.h</div><div>--- a/source/encoder/slicetype.h<span style="white-space:pre-wrap"> </span>Fri Dec 28 09:03:26 2018 +0530</div><div>+++ b/source/encoder/slicetype.h<span style="white-space:pre-wrap">   </span>Thu Dec 27 14:43:54 2018 +0530</div><div>@@ -87,7 +87,8 @@</div><div>     void lowresIntraEstimate(Lowres& fenc, uint32_t qgSize);</div><div> </div><div>     void weightsAnalyse(Lowres& fenc, Lowres& ref);</div><div>-</div><div>+    void xPreanalyze(Frame* curFrame);</div><div>+    void xPreanalyzeQp(Frame* curFrame);</div><div> protected:</div><div> </div><div>     uint32_t acEnergyCu(Frame* curFrame, uint32_t blockX, uint32_t blockY, int csp, uint32_t qgSize);</div><div>@@ -175,6 +176,7 @@</div><div>     void    cuTree(Lowres **frames, int numframes, bool bintra);</div><div>     void    estimateCUPropagate(Lowres **frames, double average_duration, int p0, int p1, int b, int referenced);</div><div>     void    cuTreeFinish(Lowres *frame, double averageDuration, int ref0Distance);</div><div>+    void    computeCUTreeQpOffset(Lowres *frame, double averageDuration, int ref0Distance);</div><div> </div><div>     /* called by getEstimatedPictureCost() to finalize cuTree costs */</div><div>     int64_t frameCostRecalculate(Lowres **frames, int p0, int p1, int b);</div><div>diff -r 129416ec0479 -r 3cd0b5ed0b91 source/x265.h</div><div>--- a/source/x265.h<span style="white-space:pre-wrap">      </span>Fri Dec 28 09:03:26 2018 +0530</div><div>+++ b/source/x265.h<span style="white-space:pre-wrap">        </span>Thu Dec 27 14:43:54 2018 +0530</div><div>@@ -1347,10 +1347,22 @@</div><div>          * generally improves. Default: X265_AQ_AUTO_VARIANCE */</div><div>         int       aqMode;</div><div> </div><div>+        /*</div><div>+         * Enable adaptive quantization.</div><div>+         * It scales the quantization step size according to the spatial activity of one</div><div>+         * coding unit relative to frame average spatial activity. This AQ method utilizes</div><div>+         * the minimum variance of sub-unit in each coding unit to represent the coding</div><div>+         * unit’s spatial complexity. */</div><div>+        int       hevcAq;</div><div>+</div><div>         /* Sets the strength of AQ bias towards low detail CTUs. Valid only if</div><div>          * AQ is enabled. Default value: 1.0. Acceptable values between 0.0 and 3.0 */</div><div>         double    aqStrength;</div><div> </div><div>+        /* Delta QP range by QP adaptation based on a psycho-visual model.</div><div>+         * Acceptable values between 1.0 to 6.0 */</div><div>+        double    qpAdaptationRange;</div><div>+</div><div>         /* Sets the maximum rate the VBV buffer should be assumed to refill at</div><div>          * Default is zero */</div><div>         int       vbvMaxBitrate;</div><div>diff -r 129416ec0479 -r 3cd0b5ed0b91 source/x265cli.h</div><div>--- a/source/x265cli.h<span style="white-space:pre-wrap">   </span>Fri Dec 28 09:03:26 2018 +0530</div><div>+++ b/source/x265cli.h<span style="white-space:pre-wrap">     </span>Thu Dec 27 14:43:54 2018 +0530</div><div>@@ -311,6 +311,9 @@</div><div>     { "dolby-vision-rpu", required_argument, NULL, 0 },</div><div>     { "hrd-concat",          no_argument, NULL, 0},</div><div>     { "no-hrd-concat",       no_argument, NULL, 0 },</div><div>+    { "hevc-aq", no_argument, NULL, 0 },</div><div>+    { "no-hevc-aq", no_argument, NULL, 0 },</div><div>+    { "qp-adaptation-range", required_argument, NULL, 0 },</div><div>     { 0, 0, 0, 0 },</div><div>     { 0, 0, 0, 0 },</div><div>     { 0, 0, 0, 0 },</div><div>@@ -361,7 +364,7 @@</div><div>     H0("   --dhdr10-info <filename>      JSON file containing the Creative Intent Metadata to be encoded as Dynamic Tone Mapping\n");</div><div>     H0("   --[no-]dhdr10-opt             Insert tone mapping SEI only for IDR frames and when the tone mapping information changes. Default disabled\n");</div><div> #endif</div><div>-    H0("   --dolby-vision-profile <float|integer> Specifies Dolby Vision profile ID. Currently only profile 5, profile 8.1 and profile 8.2 enabled. Specified as '5' or '50'. Default 0 (disabled).\n");</div><div>+    H0("   --dolby-vision-profile <float|integer> Specifies Dolby Vision profile ID. Currently only profile 5, profile 8.1 and profile 8.2 enabled. Specified as '5' or '50'. Default 0 (disabled).\n");</div><div>     H0("   --dolby-vision-rpu <filename> File containing Dolby Vision RPU metadata.\n"</div><div>        "                                 If given, x265's Dolby Vision metadata parser will fill the RPU field of input pictures with the metadata read from the file. Default NULL(disabled).\n");</div><div>     H0("   --nalu-file <filename>        Text file containing SEI messages in the following format : <POC><space><PREFIX><space><NAL UNIT TYPE>/<SEI TYPE><space><SEI Payload>\n");</div><div>@@ -521,7 +524,9 @@</div><div>         "                                    - 1 : Store/Load ctu distortion to/from the file specified in analysis-save/load.\n"</div><div>         "                                Default 0 - Disabled\n");</div><div>     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);</div><div>+    H0("   --[no-]hevc-aq                Mode for HEVC Adaptive Quantization. Default %s\n", OPT(param->rc.hevcAq));</div><div>     H0("   --aq-strength <float>         Reduces blocking and blurring in flat and textured areas (0 to 3.0). Default %.2f\n", param->rc.aqStrength);</div><div>+    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);</div><div>     H0("   --[no-]aq-motion              Adaptive Quantization based on the relative motion of each CU w.r.t., frame. Default %s\n", OPT(param->bOptCUDeltaQP));</div><div>     H0("   --qg-size <int>               Specifies the size of the quantization group (64, 32, 16, 8). Default %d\n", param->rc.qgSize);</div><div>     H0("   --[no-]cutree                 Enable cutree for Adaptive Quantization. Default %s\n", OPT(param->rc.cuTree));</div><div><br></div></div></div>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org" target="_blank">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</blockquote></div>