<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>