<div dir="ltr">Pushed to Release_3.5</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Dec 11, 2020 at 7:59 PM Niranjan Bala <<a href="mailto:niranjan@multicorewareinc.com">niranjan@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"><br clear="all"><div>From 775cdc266297f390dab0256a5efa60c3781a3b0d Mon Sep 17 00:00:00 2001<br>From: Niranjan Kumar <<a href="mailto:niranjan@multicorewareinc.com" target="_blank">niranjan@multicorewareinc.com</a>><br>Date: Wed, 21 Oct 2020 19:18:14 +0530<br>Subject: [PATCH] Add: Forward and Backward masking<br><br>Enables scenecut-aware-qp in a specified direction<br>0 - Disabled<br>1 - Forward masking<br>2 - Backward masking<br>3 - Bi-directional masking<br>---<br> doc/reST/cli.rst | 95 +++++++++++++++++++++---------<br> source/CMakeLists.txt | 2 +-<br> source/common/param.cpp | 90 ++++++++++++++++++++++------<br> source/encoder/encoder.cpp | 8 +--<br> source/encoder/ratecontrol.cpp | 68 +++++++++++++++------<br> source/encoder/ratecontrol.h | 3 +-<br> source/test/rate-control-tests.txt | 4 +-<br> source/x265.h | 32 +++++++---<br> source/x265cli.cpp | 10 ++--<br> source/x265cli.h | 7 +--<br> 10 files changed, 229 insertions(+), 90 deletions(-)<br><br>diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst<br>index 1a1de9f50..e6acc7785 100755<br>--- a/doc/reST/cli.rst<br>+++ b/doc/reST/cli.rst<br>@@ -1963,37 +1963,76 @@ Quality, rate control and rate distortion options<br> <br> **CLI ONLY**<br> <br>-.. option:: --scenecut-aware-qp, --no-scenecut-aware-qp<br>- <br>- It reduces the bits spent on the inter-frames within the :option:`--scenecut-window`<br>- before and after a scenecut by increasing their QP in ratecontrol pass2 algorithm<br>- without any deterioration in visual quality. If a scenecut falls within the window,<br>- the QP of the inter-frames after this scenecut will not be modified. <br>- :option:`--scenecut-aware-qp` works only with --pass 2. Default disabled.<br>- <br>-.. option:: --scenecut-window <integer><br>+.. option:: --scenecut-aware-qp <integer><br> <br>- The duration(in milliseconds) for which there is a reduction in the bits spent<br>- on the inter-frames after a scenecut by increasing their QP, when<br>- :option:`--scenecut-aware-qp` is enabled. Default 500ms.<br>- <br>- **Range of values:** 0 to 1000<br>- <br>-.. option:: --qp-delta-ref <double><br>-<br>- The offset by which QP is incremented for inter-frames<br>- when :option:`--scenecut-aware-qp` is enabled. Default 5.<br>- <br>- **Range of values:** 0 to 10<br>- <br>-.. option:: --qp-delta-nonref <double><br>+ It reduces the bits spent on the inter-frames within the scenecut window<br>+ before and after a scenecut by increasing their QP in ratecontrol pass2 algorithm<br>+ without any deterioration in visual quality. If a scenecut falls within the window,<br>+ the QP of the inter-frames after this scenecut will not be modified.<br>+ :option:`--scenecut-aware-qp` works only with --pass 2. Default 0.<br> <br>- The offset by which QP is incremented for non-referenced<br>- inter-frames when :option:`--scenecut-aware-qp` is enabled.<br>- The offset is computed from :option:`--qp-delta-ref` when it<br>- is not explicitly specified.<br>+ +-------+---------------------------------------------------------------+<br>+ | Mode | Description |<br>+ +=======+===============================================================+<br>+ | 0 | Disabled. |<br>+ +-------+---------------------------------------------------------------+<br>+ | 1 | Forward masking. |<br>+ | | Applies QP modification for frames after the scenecut. |<br>+ +-------+---------------------------------------------------------------+<br>+ | 2 | Backward masking. |<br>+ | | Applies QP modification for frames before the scenecut. |<br>+ +-------+---------------------------------------------------------------+<br>+ | 3 | Bi-directional masking. |<br>+ | | Applies QP modification for frames before and after |<br>+ | | the scenecut. |<br>+ +-------+---------------------------------------------------------------+<br> <br>- **Range of values:** 0 to 10<br>+.. option:: --masking-strength <string><br>+<br>+ Comma separated list of values which specifies the duration and offset<br>+ for the QP increment for inter-frames when :option:`--scenecut-aware-qp`<br>+ is enabled.<br>+<br>+ When :option:`--scenecut-aware-qp` is::<br>+ * 1 (Forward masking):<br>+ --masking-strength <fwdWindow,fwdRefQPDelta,fwdNonRefQPDelta><br>+ * 2 (Backward masking):<br>+ --masking-strength <bwdWindow,bwdRefQPDelta,bwdNonRefQPDelta><br>+ * 3 (Bi-directional masking):<br>+ --masking-strength <fwdWindow,fwdRefQPDelta,fwdNonRefQPDelta,bwdWindow,bwdRefQPDelta,bwdNonRefQPDelta><br>+<br>+ +-----------------+---------------------------------------------------------------+<br>+ | Parameter | Description |<br>+ +=================+===============================================================+<br>+ | fwdWindow | The duration(in milliseconds) for which there is a reduction |<br>+ | | in the bits spent on the inter-frames after a scenecut by |<br>+ | | increasing their QP. Default 500ms. |<br>+ | | **Range of values:** 0 to 1000 |<br>+ +-----------------+---------------------------------------------------------------+<br>+ | fwdRefQPDelta | The offset by which QP is incremented for inter-frames |<br>+ | | after a scenecut. Default 5. |<br>+ | | **Range of values:** 0 to 10 |<br>+ +-----------------+---------------------------------------------------------------+<br>+ | fwdNonRefQPDelta| The offset by which QP is incremented for non-referenced |<br>+ | | inter-frames after a scenecut. The offset is computed from |<br>+ | | fwdRefQPDelta when it is not explicitly specified. |<br>+ | | **Range of values:** 0 to 10 |<br>+ +-----------------+---------------------------------------------------------------+<br>+ | bwdWindow | The duration(in milliseconds) for which there is a reduction |<br>+ | | in the bits spent on the inter-frames before a scenecut by |<br>+ | | increasing their QP. Default 100ms. |<br>+ | | **Range of values:** 0 to 1000 |<br>+ +-----------------+---------------------------------------------------------------+<br>+ | bwdRefQPDelta | The offset by which QP is incremented for inter-frames |<br>+ | | before a scenecut. The offset is computed from |<br>+ | | fwdRefQPDelta when it is not explicitly specified. |<br>+ | | **Range of values:** 0 to 10 |<br>+ +-----------------+---------------------------------------------------------------+<br>+ | bwdNonRefQPDelta| The offset by which QP is incremented for non-referenced |<br>+ | | inter-frames before a scenecut. The offset is computed from |<br>+ | | bwdRefQPDelta when it is not explicitly specified. |<br>+ | | **Range of values:** 0 to 10 |<br>+ +-----------------+---------------------------------------------------------------+<br> <br> .. option:: --vbv-live-multi-pass, --no-vbv-live-multi-pass<br> <br>diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt<br>index 67e737512..48ca4af7c 100755<br>--- a/source/CMakeLists.txt<br>+++ b/source/CMakeLists.txt<br>@@ -29,7 +29,7 @@ option(NATIVE_BUILD "Target the build CPU" OFF)<br> option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)<br> mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)<br> # X265_BUILD must be incremented each time the public API is changed<br>-set(X265_BUILD 198)<br>+set(X265_BUILD 199)<br> configure_file("${PROJECT_SOURCE_DIR}/<a href="http://x265.def.in" target="_blank">x265.def.in</a>"<br> "${PROJECT_BINARY_DIR}/x265.def")<br> configure_file("${PROJECT_SOURCE_DIR}/<a href="http://x265_config.h.in" target="_blank">x265_config.h.in</a>"<br>diff --git a/source/common/param.cpp b/source/common/param.cpp<br>index 47a7a7c47..7a9be18c3 100755<br>--- a/source/common/param.cpp<br>+++ b/source/common/param.cpp<br>@@ -179,9 +179,12 @@ void x265_param_default(x265_param* param)<br> param->bEnableHRDConcatFlag = 0;<br> param->bEnableFades = 0;<br> param->bEnableSceneCutAwareQp = 0;<br>- param->scenecutWindow = 500;<br>- param->refQpDelta = 5;<br>- param->nonRefQpDelta = param->refQpDelta + (SLICE_TYPE_DELTA * param->refQpDelta);<br>+ param->fwdScenecutWindow = 500;<br>+ param->fwdRefQpDelta = 5;<br>+ param->fwdNonRefQpDelta = param->fwdRefQpDelta + (SLICE_TYPE_DELTA * param->fwdRefQpDelta);<br>+ param->bwdScenecutWindow = 100;<br>+ param->bwdRefQpDelta = -1;<br>+ param->bwdNonRefQpDelta = -1;<br> <br> /* Intra Coding Tools */<br> param->bEnableConstrainedIntra = 0;<br>@@ -1344,10 +1347,51 @@ int x265_param_parse(x265_param* p, const char* name, const char* value)<br> p->selectiveSAO = atoi(value);<br> }<br> OPT("fades") p->bEnableFades = atobool(value);<br>- OPT("scenecut-aware-qp") p->bEnableSceneCutAwareQp = atobool(value);<br>- OPT("scenecut-window") p->scenecutWindow = atoi(value);<br>- OPT("qp-delta-ref") p->refQpDelta = atoi(value);<br>- OPT("qp-delta-nonref") p->nonRefQpDelta = atoi(value);<br>+ OPT("scenecut-aware-qp") p->bEnableSceneCutAwareQp = atoi(value);<br>+ OPT("masking-strength")<br>+ {<br>+ int window1;<br>+ double refQpDelta1, nonRefQpDelta1;<br>+<br>+ if (p->bEnableSceneCutAwareQp == FORWARD)<br>+ {<br>+ sscanf(value, "%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1);<br>+ if (window1 > 0)<br>+ p->fwdScenecutWindow = window1;<br>+ if (refQpDelta1 > 0)<br>+ p->fwdRefQpDelta = refQpDelta1;<br>+ if (nonRefQpDelta1 > 0)<br>+ p->fwdNonRefQpDelta = nonRefQpDelta1;<br>+ }<br>+ else if (p->bEnableSceneCutAwareQp == BACKWARD)<br>+ {<br>+ sscanf(value, "%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1);<br>+ if (window1 > 0)<br>+ p->bwdScenecutWindow = window1;<br>+ if (refQpDelta1 > 0)<br>+ p->bwdRefQpDelta = refQpDelta1;<br>+ if (nonRefQpDelta1 > 0)<br>+ p->bwdNonRefQpDelta = nonRefQpDelta1;<br>+ }<br>+ else if (p->bEnableSceneCutAwareQp == BI_DIRECTIONAL)<br>+ {<br>+ int window2;<br>+ double refQpDelta2, nonRefQpDelta2;<br>+ sscanf(value, "%d,%lf,%lf,%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1, &window2, &refQpDelta2, &nonRefQpDelta2);<br>+ if (window1 > 0)<br>+ p->fwdScenecutWindow = window1;<br>+ if (refQpDelta1 > 0)<br>+ p->fwdRefQpDelta = refQpDelta1;<br>+ if (nonRefQpDelta1 > 0)<br>+ p->fwdNonRefQpDelta = nonRefQpDelta1;<br>+ if (window2 > 0)<br>+ p->bwdScenecutWindow = window2;<br>+ if (refQpDelta2 > 0)<br>+ p->bwdRefQpDelta = refQpDelta2;<br>+ if (nonRefQpDelta2 > 0)<br>+ p->bwdNonRefQpDelta = nonRefQpDelta2;<br>+ }<br>+ }<br> OPT("field") p->bField = atobool( value );<br> OPT("cll") p->bEmitCLL = atobool(value);<br> OPT("frame-dup") p->bEnableFrameDuplication = atobool(value);<br>@@ -1787,12 +1831,19 @@ int x265_check_params(x265_param* param)<br> }<br> else<br> {<br>- CHECK(param->scenecutWindow < 0 || param->scenecutWindow > 1000,<br>- "Invalid scenecut Window duration. Value must be between 0 and 1000(inclusive)");<br>- CHECK(param->refQpDelta < 0 || param->refQpDelta > 10,<br>- "Invalid refQpDelta value. Value must be between 0 and 10 (inclusive)");<br>- CHECK(param->nonRefQpDelta < 0 || param->nonRefQpDelta > 10,<br>- "Invalid nonRefQpDelta value. Value must be between 0 and 10 (inclusive)");<br>+ CHECK(param->fwdScenecutWindow < 0 || param->fwdScenecutWindow > 1000,<br>+ "Invalid forward scenecut Window duration. Value must be between 0 and 1000(inclusive)");<br>+ CHECK(param->fwdRefQpDelta < 0 || param->fwdRefQpDelta > 10,<br>+ "Invalid fwdRefQpDelta value. Value must be between 0 and 10 (inclusive)");<br>+ CHECK(param->fwdNonRefQpDelta < 0 || param->fwdNonRefQpDelta > 10,<br>+ "Invalid fwdNonRefQpDelta value. Value must be between 0 and 10 (inclusive)");<br>+<br>+ CHECK(param->bwdScenecutWindow < 0 || param->bwdScenecutWindow > 1000,<br>+ "Invalid backward scenecut Window duration. Value must be between 0 and 1000(inclusive)");<br>+ CHECK(param->bwdRefQpDelta < -1 || param->bwdRefQpDelta > 10,<br>+ "Invalid bwdRefQpDelta value. Value must be between 0 and 10 (inclusive)");<br>+ CHECK(param->bwdNonRefQpDelta < -1 || param->bwdNonRefQpDelta > 10,<br>+ "Invalid bwdNonRefQpDelta value. Value must be between 0 and 10 (inclusive)");<br> }<br> }<br> if (param->bEnableHME)<br>@@ -2252,9 +2303,9 @@ char *x265_param2string(x265_param* p, int padx, int pady)<br> BOOL(p->bEnableSvtHevc, "svt");<br> BOOL(p->bField, "field");<br> s += sprintf(s, " qp-adaptation-range=%.2f", p->rc.qpAdaptationRange);<br>- BOOL(p->bEnableSceneCutAwareQp, "scenecut-aware-qp");<br>+ s += sprintf(s, " scenecut-aware-qp=%d", p->bEnableSceneCutAwareQp);<br> if (p->bEnableSceneCutAwareQp)<br>- s += sprintf(s, " scenecut-window=%d qp-delta-ref=%f qp-delta-nonref=%f", p->scenecutWindow, p->refQpDelta, p->nonRefQpDelta);<br>+ s += sprintf(s, " fwd-scenecut-window=%d fwd-ref-qp-delta=%f fwd-nonref-qp-delta=%f bwd-scenecut-window=%d bwd-ref-qp-delta=%f bwd-nonref-qp-delta=%f", p->fwdScenecutWindow, p->fwdRefQpDelta, p->fwdNonRefQpDelta, p->bwdScenecutWindow, p->bwdRefQpDelta, p->bwdNonRefQpDelta);<br> s += sprintf(s, "conformance-window-offsets right=%d bottom=%d", p->confWinRightOffset, p->confWinBottomOffset);<br> s += sprintf(s, " decoder-max-rate=%d", p->decoderVbvMaxRate);<br> BOOL(p->bliveVBV2pass, "vbv-live-multi-pass");<br>@@ -2608,9 +2659,12 @@ void x265_copy_params(x265_param* dst, x265_param* src)<br> dst->bEnableSvtHevc = src->bEnableSvtHevc;<br> dst->bEnableFades = src->bEnableFades;<br> dst->bEnableSceneCutAwareQp = src->bEnableSceneCutAwareQp;<br>- dst->scenecutWindow = src->scenecutWindow;<br>- dst->refQpDelta = src->refQpDelta;<br>- dst->nonRefQpDelta = src->nonRefQpDelta;<br>+ dst->fwdScenecutWindow = src->fwdScenecutWindow;<br>+ dst->fwdRefQpDelta = src->fwdRefQpDelta;<br>+ dst->fwdNonRefQpDelta = src->fwdNonRefQpDelta;<br>+ dst->bwdScenecutWindow = src->bwdScenecutWindow;<br>+ dst->bwdRefQpDelta = src->bwdRefQpDelta;<br>+ dst->bwdNonRefQpDelta = src->bwdNonRefQpDelta;<br> dst->bField = src->bField;<br> <br> dst->confWinRightOffset = src->confWinRightOffset;<br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index 1f710e1ce..18c3b6788 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -1810,13 +1810,13 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)<br> inFrame->m_lowres.m_bIsHardScenecut = isHardSC;<br> }<br> <br>- if (m_param->bEnableSceneCutAwareQp && m_param->rc.bStatRead)<br>+ if ((m_param->bEnableSceneCutAwareQp == BI_DIRECTIONAL || m_param->bEnableSceneCutAwareQp == BACKWARD) && m_param->rc.bStatRead)<br> {<br> RateControlEntry * rcEntry = NULL;<br> rcEntry = &(m_rateControl->m_rce2Pass[inFrame->m_poc]);<br> if(rcEntry->scenecut)<br> {<br>- int backwardWindow = X265_MIN(int((p->fpsNum / p->fpsDenom) / 10), p->lookaheadDepth);<br>+ int backwardWindow = X265_MIN(int((m_param->bwdScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom)), p->lookaheadDepth);<br> for (int i = 1; i <= backwardWindow; i++)<br> {<br> int frameNum = inFrame->m_poc - i;<br>@@ -2242,7 +2242,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)<br> frameEnc = m_lookahead->getDecidedPicture();<br> if (frameEnc && !pass && (!m_param->chunkEnd || (m_encodedFrameNum < m_param->chunkEnd)))<br> {<br>- if (m_param->bEnableSceneCutAwareQp && m_param->rc.bStatRead)<br>+ if ((m_param->bEnableSceneCutAwareQp == BI_DIRECTIONAL || m_param->bEnableSceneCutAwareQp == FORWARD) && m_param->rc.bStatRead)<br> {<br> RateControlEntry * rcEntry;<br> rcEntry = &(m_rateControl->m_rce2Pass[frameEnc->m_poc]);<br>@@ -2253,7 +2253,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)<br> m_rateControl->m_lastScenecut = frameEnc->m_poc;<br> else<br> {<br>- int maxWindowSize = int((m_param->scenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5);<br>+ int maxWindowSize = int((m_param->fwdScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5);<br> if (frameEnc->m_poc > (m_rateControl->m_lastScenecut + maxWindowSize))<br> m_rateControl->m_lastScenecut = frameEnc->m_poc;<br> }<br>diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp<br>index 4e7d52419..554acfe38 100644<br>--- a/source/encoder/ratecontrol.cpp<br>+++ b/source/encoder/ratecontrol.cpp<br>@@ -1858,7 +1858,10 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)<br> {<br> double lqmin = m_lmin[m_sliceType];<br> double lqmax = m_lmax[m_sliceType];<br>- qScale = scenecutAwareMasking(curFrame, qScale);<br>+ if (m_param->bEnableSceneCutAwareQp == FORWARD || m_param->bEnableSceneCutAwareQp == BI_DIRECTIONAL)<br>+ qScale = forwardMasking(curFrame, qScale);<br>+ else if (m_param->bEnableSceneCutAwareQp == BACKWARD || m_param->bEnableSceneCutAwareQp == BI_DIRECTIONAL)<br>+ qScale = backwardMasking(curFrame, qScale);<br> qScale = x265_clip3(lqmin, lqmax, qScale);<br> q = x265_qScale2qp(qScale);<br> rce->qpNoVbv = q;<br>@@ -1981,7 +1984,12 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)<br> {<br> double qmin = m_lmin[m_sliceType];<br> double qmax = m_lmax[m_sliceType];<br>- q = scenecutAwareMasking(curFrame, q);<br>+<br>+ if (m_param->bEnableSceneCutAwareQp == FORWARD || m_param->bEnableSceneCutAwareQp == BI_DIRECTIONAL)<br>+ q = forwardMasking(curFrame, q);<br>+ else if (m_param->bEnableSceneCutAwareQp == BACKWARD || m_param->bEnableSceneCutAwareQp == BI_DIRECTIONAL)<br>+ q = backwardMasking(curFrame, q);<br>+<br> q = x265_clip3(qmin, qmax, q);<br> rce->qpNoVbv = x265_qScale2qp(q);<br> }<br>@@ -2145,7 +2153,12 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)<br> {<br> double qmin = m_lmin[m_sliceType];<br> double qmax = m_lmax[m_sliceType];<br>- q = scenecutAwareMasking(curFrame, q);<br>+<br>+ if (m_param->bEnableSceneCutAwareQp == FORWARD || m_param->bEnableSceneCutAwareQp == BI_DIRECTIONAL)<br>+ q = forwardMasking(curFrame, q);<br>+ else if (m_param->bEnableSceneCutAwareQp == BACKWARD || m_param->bEnableSceneCutAwareQp == BI_DIRECTIONAL)<br>+ q = backwardMasking(curFrame, q);<br>+<br> q = x265_clip3(qmin, qmax, q);<br> rce->qpNoVbv = x265_qScale2qp(q);<br> }<br>@@ -3168,18 +3181,20 @@ void RateControl::splitbUsed(char bused[], RateControlEntry *rce)<br> }<br> }<br> <br>-double RateControl::scenecutAwareMasking(Frame* curFrame, double q)<br>+double RateControl::forwardMasking(Frame* curFrame, double q)<br> {<br> double qp = x265_qScale2qp(q);<br>- uint32_t maxWindowSize = uint32_t((m_param->scenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5);<br>+ uint32_t maxWindowSize = uint32_t((m_param->fwdScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5);<br> uint32_t windowSize = maxWindowSize / 3;<br> int lastScenecut = m_top->m_rateControl->m_lastScenecut;<br> int lastIFrame = m_top->m_rateControl->m_lastScenecutAwareIFrame;<br>- double refQpDelta = double(m_param->refQpDelta);<br>- double nonRefQpDelta = double(m_param->nonRefQpDelta);<br>- double sliceTypeDelta = SLICE_TYPE_DELTA * refQpDelta;<br>- double window2Delta = WINDOW2_DELTA * refQpDelta;<br>- double window3Delta = WINDOW3_DELTA * refQpDelta;<br>+ double fwdRefQpDelta = double(m_param->fwdRefQpDelta);<br>+ double fwdNonRefQpDelta = double(m_param->fwdNonRefQpDelta);<br>+ double bwdRefQpDelta = double(m_param->bwdRefQpDelta);<br>+ double bwdNonRefQpDelta = double(m_param->bwdNonRefQpDelta);<br>+ double sliceTypeDelta = SLICE_TYPE_DELTA * fwdRefQpDelta;<br>+ double window2Delta = WINDOW2_DELTA * fwdRefQpDelta;<br>+ double window3Delta = WINDOW3_DELTA * fwdRefQpDelta;<br> <br> if (curFrame->m_poc > lastScenecut && curFrame->m_poc <= (lastScenecut + int(maxWindowSize)))<br> curFrame->m_isInsideWindow = FORWARD_WINDOW;<br>@@ -3194,7 +3209,7 @@ double RateControl::scenecutAwareMasking(Frame* curFrame, double q)<br> if (!(lastIFrame > lastScenecut && lastIFrame <= (lastScenecut + int(maxWindowSize))<br> && curFrame->m_poc >= lastIFrame))<br> {<br>- qp += refQpDelta - sliceTypeDelta;<br>+ qp += fwdRefQpDelta - sliceTypeDelta;<br> if (((curFrame->m_poc) > (lastScenecut + int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 2 * int(windowSize))))<br> qp -= window2Delta;<br> else if (curFrame->m_poc > lastScenecut + 2 * int(windowSize))<br>@@ -3206,7 +3221,7 @@ double RateControl::scenecutAwareMasking(Frame* curFrame, double q)<br> if (!(lastIFrame > lastScenecut && lastIFrame <= (lastScenecut + int(maxWindowSize))<br> && curFrame->m_poc >= lastIFrame))<br> {<br>- qp += refQpDelta;<br>+ qp += fwdRefQpDelta;<br> if (((curFrame->m_poc) > (lastScenecut + int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 2 * int(windowSize))))<br> qp -= window2Delta;<br> else if (curFrame->m_poc > lastScenecut + 2 * int(windowSize))<br>@@ -3218,7 +3233,7 @@ double RateControl::scenecutAwareMasking(Frame* curFrame, double q)<br> if (!(lastIFrame > lastScenecut && lastIFrame <= (lastScenecut + int(maxWindowSize))<br> && curFrame->m_poc >= lastIFrame))<br> {<br>- qp += nonRefQpDelta;<br>+ qp += fwdNonRefQpDelta;<br> if (((curFrame->m_poc) > (lastScenecut + int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 2 * int(windowSize))))<br> qp -= window2Delta;<br> else if (curFrame->m_poc > lastScenecut + 2 * int(windowSize))<br>@@ -3226,16 +3241,31 @@ double RateControl::scenecutAwareMasking(Frame* curFrame, double q)<br> }<br> }<br> }<br>- else if (curFrame->m_isInsideWindow == BACKWARD_WINDOW)<br>+<br>+ return x265_qp2qScale(qp);<br>+}<br>+double RateControl::backwardMasking(Frame* curFrame, double q)<br>+{<br>+ double qp = x265_qScale2qp(q);<br>+ double fwdRefQpDelta = double(m_param->fwdRefQpDelta);<br>+ double window3Delta = WINDOW3_DELTA * fwdRefQpDelta;<br>+ double bwdRefQpDelta = double(m_param->bwdRefQpDelta);<br>+ double bwdNonRefQpDelta = double(m_param->bwdNonRefQpDelta);<br>+<br>+ if (curFrame->m_isInsideWindow == BACKWARD_WINDOW)<br> {<br>- refQpDelta -= window3Delta;<br>- nonRefQpDelta -= window3Delta;<br>+ if (bwdRefQpDelta < 0)<br>+ bwdRefQpDelta = fwdRefQpDelta - window3Delta;<br>+ double sliceTypeDelta = SLICE_TYPE_DELTA * bwdRefQpDelta;<br>+ if (bwdNonRefQpDelta < 0)<br>+ bwdNonRefQpDelta = bwdRefQpDelta + sliceTypeDelta;<br>+<br> if (curFrame->m_lowres.sliceType == X265_TYPE_P)<br>- qp += refQpDelta - sliceTypeDelta;<br>+ qp += bwdRefQpDelta - sliceTypeDelta;<br> else if (curFrame->m_lowres.sliceType == X265_TYPE_BREF)<br>- qp += refQpDelta;<br>+ qp += bwdRefQpDelta;<br> else if (curFrame->m_lowres.sliceType == X265_TYPE_B)<br>- qp += nonRefQpDelta;<br>+ qp += bwdNonRefQpDelta;<br> }<br> <br> return x265_qp2qScale(qp);<br>diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h<br>index 809e0c620..41bbddcf2 100644<br>--- a/source/encoder/ratecontrol.h<br>+++ b/source/encoder/ratecontrol.h<br>@@ -269,7 +269,8 @@ public:<br> int writeRateControlFrameStats(Frame* curFrame, RateControlEntry* rce);<br> bool initPass2();<br> <br>- double scenecutAwareMasking(Frame* curFrame, double q);<br>+ double forwardMasking(Frame* curFrame, double q);<br>+ double backwardMasking(Frame* curFrame, double q);<br> <br> protected:<br> <br>diff --git a/source/test/rate-control-tests.txt b/source/test/rate-control-tests.txt<br>index eed92f809..6c8f10cb6 100644<br>--- a/source/test/rate-control-tests.txt<br>+++ b/source/test/rate-control-tests.txt<br>@@ -44,8 +44,8 @@ CrowdRun_1920x1080_50_10bit_422.yuv,--preset superfast --bitrate 2500 --pass 1 -<br> RaceHorses_416x240_30_10bit.yuv,--preset medium --crf 26 --vbv-maxrate 1000 --vbv-bufsize 1000 --pass 1::--preset fast --bitrate 1000 --vbv-maxrate 1000 --vbv-bufsize 700 --pass 3 -F4::--preset slow --bitrate 500 --vbv-maxrate 500 --vbv-bufsize 700 --pass 2 -F4<br> sita_1920x1080_30.yuv, --preset ultrafast --crf 20 --no-cutree --keyint 50 --min-keyint 50 --no-open-gop --pass 1 --vbv-bufsize 7000 --vbv-maxrate 5000:: --preset ultrafast --crf 20 --no-cutree --keyint 50 --min-keyint 50 --no-open-gop --pass 2 --vbv-bufsize 7000 --vbv-maxrate 5000 --repeat-headers<br> sita_1920x1080_30.yuv, --preset medium --crf 20 --no-cutree --keyint 50 --min-keyint 50 --no-open-gop --pass 1 --vbv-bufsize 7000 --vbv-maxrate 5000 --repeat-headers --multi-pass-opt-rps:: --preset medium --crf 20 --no-cutree --keyint 50 --min-keyint 50 --no-open-gop --pass 2 --vbv-bufsize 7000 --vbv-maxrate 5000 --repeat-headers --multi-pass-opt-rps<br>-sintel_trailer_2k_1920x1080_24.yuv,--preset medium --bitrate 6000 --no-cutree --aq-mode 0 --pass 1::--preset medium --bitrate 6000 --no-cutree --aq-mode 0 --pass 2 --scenecut-aware-qp<br>-sintel_trailer_2k_1920x1080_24.yuv,--preset medium --bitrate 6000 --no-cutree --aq-mode 0 --hist-scenecut --pass 1::--preset medium --bitrate 6000 --no-cutree --aq-mode 0 --hist-scenecut --pass 2 --scenecut-aware-qp --qp-delta-nonref 8<br>+sintel_trailer_2k_1920x1080_24.yuv,--preset medium --bitrate 6000 --no-cutree --aq-mode 0 --pass 1::--preset medium --bitrate 6000 --no-cutree --aq-mode 0 --pass 2 --scenecut-aware-qp 1<br>+sintel_trailer_2k_1920x1080_24.yuv,--preset medium --bitrate 6000 --no-cutree --aq-mode 0 --hist-scenecut --pass 1::--preset medium --bitrate 6000 --no-cutree --aq-mode 0 --hist-scenecut --pass 2 --scenecut-aware-qp 3 --masking-strength 300,-1,7,100,2,3<br> <br> # multi-pass rate control and analysis<br> ducks_take_off_1080p50.y4m,--bitrate 6000 --pass 1 --multi-pass-opt-analysis --hash 1 --ssim --psnr:: --bitrate 6000 --pass 2 --multi-pass-opt-analysis --hash 1 --ssim --psnr<br>diff --git a/source/x265.h b/source/x265.h<br>index f44040ba7..b064f67c2 100644<br>--- a/source/x265.h<br>+++ b/source/x265.h<br>@@ -607,6 +607,9 @@ typedef enum<br> #define X265_ANALYSIS_SAVE 1<br> #define X265_ANALYSIS_LOAD 2<br> <br>+#define FORWARD 1<br>+#define BACKWARD 2<br>+#define BI_DIRECTIONAL 3<br> #define SLICE_TYPE_DELTA 0.3 /* The offset decremented or incremented for P-frames or b-frames respectively*/<br> #define BACKWARD_WINDOW 1 /* Scenecut window before a scenecut */<br> #define FORWARD_WINDOW 2 /* Scenecut window after a scenecut */<br>@@ -1847,21 +1850,24 @@ typedef struct x265_param<br> Default 1 (Enabled). API only. */<br> int bResetZoneConfig;<br> <br>- /* It reduces the bits spent on the inter-frames within the scenecutWindow before and after a scenecut<br>+ /* It reduces the bits spent on the inter-frames within the scenecutWindow before and / or after a scenecut<br> * by increasing their QP in ratecontrol pass2 algorithm without any deterioration in visual quality.<br>- * Default is disabled. */<br>+ * 0 - Disabled (default).<br>+ * 1 - Forward masking.<br>+ * 2 - Backward masking.<br>+ * 3 - Bi-directional masking. */<br> int bEnableSceneCutAwareQp;<br> <br> /* The duration(in milliseconds) for which there is a reduction in the bits spent on the inter-frames after a scenecut<br>- * by increasing their QP, when bEnableSceneCutAwareQp is set. Default is 500ms.*/<br>- int scenecutWindow;<br>+ * by increasing their QP, when bEnableSceneCutAwareQp is 1 or 3. Default is 500ms.*/<br>+ int fwdScenecutWindow;<br> <br>- /* The offset by which QP is incremented for inter-frames when bEnableSceneCutAwareQp is set.<br>+ /* The offset by which QP is incremented for inter-frames after a scenecut when bEnableSceneCutAwareQp is 1 or 3.<br> * Default is +5. */<br>- double refQpDelta;<br>+ double fwdRefQpDelta;<br> <br>- /* The offset by which QP is incremented for non-referenced inter-frames when bEnableSceneCutAwareQp is set. */<br>- double nonRefQpDelta;<br>+ /* The offset by which QP is incremented for non-referenced inter-frames after a scenecut when bEnableSceneCutAwareQp is 1 or 3. */<br>+ double fwdNonRefQpDelta;<br> <br> /* A genuine threshold used for histogram based scene cut detection.<br> * This threshold determines whether a frame is a scenecut or not<br>@@ -1932,6 +1938,16 @@ typedef struct x265_param<br> /* Maximum VBV fullness to be maintained. Default 80. Keep the buffer<br> * at max 80% full */<br> double maxVbvFullness;<br>+<br>+ /* The duration(in milliseconds) for which there is a reduction in the bits spent on the inter-frames before a scenecut<br>+ * by increasing their QP, when bEnableSceneCutAwareQp is 2 or 3. Default is 100ms.*/<br>+ int bwdScenecutWindow;<br>+<br>+ /* The offset by which QP is incremented for inter-frames before a scenecut when bEnableSceneCutAwareQp is 2 or 3. */<br>+ double bwdRefQpDelta;<br>+<br>+ /* The offset by which QP is incremented for non-referenced inter-frames before a scenecut when bEnableSceneCutAwareQp is 2 or 3. */<br>+ double bwdNonRefQpDelta;<br> } x265_param;<br> <br> /* x265_param_alloc:<br>diff --git a/source/x265cli.cpp b/source/x265cli.cpp<br>index c28dd7f8c..0f50589c1 100755<br>--- a/source/x265cli.cpp<br>+++ b/source/x265cli.cpp<br>@@ -177,10 +177,12 @@ namespace X265_NS {<br> H0(" --no-hist-scenecut Disables histogram based scene-cut detection using histogram based algorithm.\n");<br> H1(" --hist-threshold <0.0..1.0> Luma Edge histogram's Normalized SAD threshold for histogram based scenecut detection Default %.2f\n", param->edgeTransitionThreshold);<br> H0(" --[no-]fades Enable detection and handling of fade-in regions. Default %s\n", OPT(param->bEnableFades));<br>- H1(" --[no-]scenecut-aware-qp Enable increasing QP for frames inside the scenecut window after scenecut. Default %s\n", OPT(param->bEnableSceneCutAwareQp));<br>- H1(" --scenecut-window <0..1000> QP incremental duration(in milliseconds) when scenecut-aware-qp is enabled. Default %d\n", param->scenecutWindow);<br>- H1(" --qp-delta-ref <0..10> QP offset to increment with base QP for inter-frames. Default %f\n", param->refQpDelta);<br>- H1(" --qp-delta-nonref <0..10> QP offset to increment with base QP for non-referenced inter-frames. Default %f\n", param->nonRefQpDelta);<br>+ H1(" --scenecut-aware-qp <0..3> Enable increasing QP for frames inside the scenecut window around scenecut. Default %s\n", OPT(param->bEnableSceneCutAwareQp));<br>+ H1(" 0 - Disabled\n");<br>+ H1(" 1 - Forward masking\n");<br>+ H1(" 2 - Backward masking\n");<br>+ H1(" 3 - Bidirectional masking\n");<br>+ H1(" --masking-strength <string> Comma separated values which specifies the duration and offset for the QP increment for inter-frames");<br> H0(" --radl <integer> Number of RADL pictures allowed in front of IDR. Default %d\n", param->radl);<br> H0(" --intra-refresh Use Periodic Intra Refresh instead of IDR frames\n");<br> H0(" --rc-lookahead <integer> Number of frames for frame-type lookahead (determines encoder latency) Default %d\n", param->lookaheadDepth);<br>diff --git a/source/x265cli.h b/source/x265cli.h<br>index a24d25435..7a2e0a267 100644<br>--- a/source/x265cli.h<br>+++ b/source/x265cli.h<br>@@ -148,11 +148,8 @@ static const struct option long_options[] =<br> { "hist-threshold", required_argument, NULL, 0},<br> { "fades", no_argument, NULL, 0 },<br> { "no-fades", no_argument, NULL, 0 },<br>- { "scenecut-aware-qp", no_argument, NULL, 0 },<br>- { "no-scenecut-aware-qp", no_argument, NULL, 0 },<br>- { "scenecut-window",required_argument, NULL, 0 },<br>- { "qp-delta-ref", required_argument, NULL, 0 },<br>- { "qp-delta-nonref",required_argument, NULL, 0 },<br>+ { "scenecut-aware-qp", required_argument, NULL, 0 },<br>+ { "masking-strength", required_argument, NULL, 0 },<br> { "radl", required_argument, NULL, 0 },<br> { "ctu-info", required_argument, NULL, 0 },<br> { "intra-refresh", no_argument, NULL, 0 },<br>-- <br>2.18.0.windows.1<br><br></div>-- <br><div dir="ltr"><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div dir="ltr"><font color="#0c343d" face="verdana, sans-serif"><br></font></div><div dir="ltr"><font color="#0c343d" face="verdana, sans-serif">Thanks & Regards</font><div><font color="#0c343d" face="verdana, sans-serif"><b>Niranjan Kumar B</b></font></div><div><font size="1" color="#0c343d" face="verdana, sans-serif">Video Codec Engineer </font></div><div><font size="1" color="#0c343d" face="verdana, sans-serif">Media & AI Analytics</font></div><div><font face="trebuchet ms, sans-serif" color="#0c343d">+91 958 511 1449</font></div><div><a href="https://multicorewareinc.com/" style="color:rgb(17,85,204)" target="_blank"><img src="https://docs.google.com/uc?export=download&id=1kc3RJu9M8bnIf6Xa5rUw2d-eEVUsPBE5&revid=0B7tw9XJBmynaemR1VUpQUi9DVytRVW5SVkRwVTFjb1hBMUcwPQ"></a></div></div></div></div></div></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><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><font face="georgia, serif">Regards,</font><div><b><font face="georgia, serif">Aruna Matheswaran,</font></b></div><div><font face="georgia, serif">Video Codec Engineer,</font></div><div><font face="georgia, serif">Media & AI analytics BU,</font></div><div><span><span style="font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"><span style="border:none;display:inline-block;overflow:hidden;width:153px;height:58px"><img src="https://lh5.googleusercontent.com/gjX5cPNIZgwUrhfqkTwQUZWztIKmmo0qs3kbwvkS5H-bDVE2ftte9pMTVnFLSjOcjYWLtfc6_OGpxW4vraLg2r5QAIf1Q3MpldFDgWtzK_gXi8ptw5B3joIbsGL6mxj-JRdjHzT5" width="96" height="36" style="margin-left: 0px; margin-top: 0px;"></span></span></span><font face="georgia, serif"><br></font></div><div><span><span style="font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap"><span style="border:none;display:inline-block;overflow:hidden;width:153px;height:58px"><img src="https://lh5.googleusercontent.com/gjX5cPNIZgwUrhfqkTwQUZWztIKmmo0qs3kbwvkS5H-bDVE2ftte9pMTVnFLSjOcjYWLtfc6_OGpxW4vraLg2r5QAIf1Q3MpldFDgWtzK_gXi8ptw5B3joIbsGL6mxj-JRdjHzT5" style="margin-left: 0px; margin-top: 0px;"></span></span></span><font face="georgia, serif"><br></font></div><div><font face="georgia, serif"><br></font></div></div></div></div></div></div></div></div></div>