>From cf25444e6b0f82de7b751c2436dec22ea94755b9 Mon Sep 17 00:00:00 2001 From: Niranjan Kumar <niran...@multicorewareinc.com> Date: Wed, 21 Oct 2020 19:18:14 +0530 Subject: [PATCH] Add: Forward and Backward masking
Enables scenecut-aware-qp in a specified direction 0 - Disabled 1 - Forward masking 2 - Backward masking 3 - Bi-directional masking --- doc/reST/cli.rst | 85 +++++++++++++++++++++++-------- source/common/param.cpp | 90 ++++++++++++++++++++++++++------- source/encoder/encoder.cpp | 6 +-- source/encoder/ratecontrol.cpp | 91 +++++++++++++++++++++++++++------- source/encoder/ratecontrol.h | 1 + source/x265.h | 32 +++++++++--- source/x265cli.cpp | 10 ++-- source/x265cli.h | 7 +-- 8 files changed, 244 insertions(+), 78 deletions(-) diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst index 1a1de9f50..4e20daa90 100755 --- a/doc/reST/cli.rst +++ b/doc/reST/cli.rst @@ -1963,37 +1963,78 @@ Quality, rate control and rate distortion options **CLI ONLY** -.. option:: --scenecut-aware-qp, --no-scenecut-aware-qp +.. option:: --scenecut-aware-qp <integer> - It reduces the bits spent on the inter-frames within the :option:`--scenecut-window` + It reduces the bits spent on the inter-frames within the scenecut window before and after a scenecut by increasing their QP in ratecontrol pass2 algorithm without any deterioration in visual quality. If a scenecut falls within the window, the QP of the inter-frames after this scenecut will not be modified. - :option:`--scenecut-aware-qp` works only with --pass 2. Default disabled. + :option:`--scenecut-aware-qp` works only with --pass 2. Default 0. -.. option:: --scenecut-window <integer> - - The duration(in milliseconds) for which there is a reduction in the bits spent - on the inter-frames after a scenecut by increasing their QP, when - :option:`--scenecut-aware-qp` is enabled. Default 500ms. + +-------+---------------------------------------------------------------+ + | Mode | Description | + +=======+===============================================================+ + | 0 | Disabled. | + +-------+---------------------------------------------------------------+ + | 1 | Forward masking. | + | | Applies QP modification for frames after the scenecut. | + +-------+---------------------------------------------------------------+ + | 2 | Backward masking. | + | | Applies QP modification for frames before the scenecut. | + +-------+---------------------------------------------------------------+ + | 3 | Bi-directional masking. | + | | Applies QP modification for frames before and after | + | | the scenecut. | + +-------+---------------------------------------------------------------+ - **Range of values:** 0 to 1000 +.. option:: --masking-strength <string> -.. option:: --qp-delta-ref <double> - - The offset by which QP is incremented for inter-frames - when :option:`--scenecut-aware-qp` is enabled. Default 5. + Comma separated list of values which specifies the duration and offset + for the QP increment for inter-frames when :option:`--scenecut-aware-qp` + is enabled. - **Range of values:** 0 to 10 + When :option:`--scenecut-aware-qp` is:: + * 1 (Forward masking): + --masking-strength <fwdWindow,fwdRefQPDelta,fwdNonRefQPDelta> -.. option:: --qp-delta-nonref <double> - - The offset by which QP is incremented for non-referenced - inter-frames when :option:`--scenecut-aware-qp` is enabled. - The offset is computed from :option:`--qp-delta-ref` when it - is not explicitly specified. - - **Range of values:** 0 to 10 + * 2 (Backward masking): + --masking-strength <bwdWindow,bwdRefQPDelta,bwdNonRefQPDelta> + + * 3 (Bi-directional masking): + --masking-strength <fwdWindow,fwdRefQPDelta,fwdNonRefQPDelta,bwdWindow,bwdRefQPDelta,bwdNonRefQPDelta> + + +-----------------+---------------------------------------------------------------+ + | Parameter | Description | + +=================+===============================================================+ + | fwdWindow | The duration(in milliseconds) for which there is a reduction | + | | in the bits spent on the inter-frames after a scenecut by | + | | increasing their QP. Default 500ms. | + | | **Range of values:** 0 to 1000 | + +-----------------+---------------------------------------------------------------+ + | fwdRefQPDelta | The offset by which QP is incremented for inter-frames | + | | after a scenecut. Default 5. | + | | **Range of values:** 0 to 10 | + +-----------------+---------------------------------------------------------------+ + | fwdNonRefQPDelta| The offset by which QP is incremented for non-referenced | + | | inter-frames after a scenecut. The offset is computed from | + | | fwdRefQPDelta when it is not explicitly specified. | + | | **Range of values:** 0 to 10 | + +-----------------+---------------------------------------------------------------+ + | bwdWindow | The duration(in milliseconds) for which there is a reduction | + | | in the bits spent on the inter-frames before a scenecut by | + | | increasing their QP. Default 100ms. | + | | **Range of values:** 0 to 1000 | + +-----------------+---------------------------------------------------------------+ + | bwdRefQPDelta | The offset by which QP is incremented for inter-frames | + | | before a scenecut. The offset is computed from | + | | fwdRefQPDelta when it is not explicitly specified. | + | | **Range of values:** 0 to 10 | + +-----------------+---------------------------------------------------------------+ + | bwdNonRefQPDelta| The offset by which QP is incremented for non-referenced | + | | inter-frames before a scenecut. The offset is computed from | + | | bwdRefQPDelta when it is not explicitly specified. | + | | **Range of values:** 0 to 10 | + +-----------------+---------------------------------------------------------------+ .. option:: --vbv-live-multi-pass, --no-vbv-live-multi-pass diff --git a/source/common/param.cpp b/source/common/param.cpp index 47a7a7c47..fe038fdf2 100755 --- a/source/common/param.cpp +++ b/source/common/param.cpp @@ -179,9 +179,12 @@ void x265_param_default(x265_param* param) param->bEnableHRDConcatFlag = 0; param->bEnableFades = 0; param->bEnableSceneCutAwareQp = 0; - param->scenecutWindow = 500; - param->refQpDelta = 5; - param->nonRefQpDelta = param->refQpDelta + (SLICE_TYPE_DELTA * param->refQpDelta); + param->fwdScenecutWindow = 500; + param->fwdRefQpDelta = 5; + param->fwdNonRefQpDelta = param->fwdRefQpDelta + (SLICE_TYPE_DELTA * param->fwdRefQpDelta); + param->bwdScenecutWindow = 100; + param->bwdRefQpDelta = -1; + param->bwdNonRefQpDelta = -1; /* Intra Coding Tools */ param->bEnableConstrainedIntra = 0; @@ -1344,10 +1347,51 @@ int x265_param_parse(x265_param* p, const char* name, const char* value) p->selectiveSAO = atoi(value); } OPT("fades") p->bEnableFades = atobool(value); - OPT("scenecut-aware-qp") p->bEnableSceneCutAwareQp = atobool(value); - OPT("scenecut-window") p->scenecutWindow = atoi(value); - OPT("qp-delta-ref") p->refQpDelta = atoi(value); - OPT("qp-delta-nonref") p->nonRefQpDelta = atoi(value); + OPT("scenecut-aware-qp") p->bEnableSceneCutAwareQp = atoi(value); + OPT("masking-strength") + { + int window1; + double refQpDelta1, nonRefQpDelta1; + + if (p->bEnableSceneCutAwareQp == FORWARD) + { + sscanf(value, "%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1); + if (window1 > 0) + p->fwdScenecutWindow = window1; + if (refQpDelta1 > 0) + p->fwdRefQpDelta = refQpDelta1; + if (nonRefQpDelta1 > 0) + p->fwdNonRefQpDelta = nonRefQpDelta1; + } + else if (p->bEnableSceneCutAwareQp == BACKWARD) + { + sscanf(value, "%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1); + if (window1 > 0) + p->bwdScenecutWindow = window1; + if (refQpDelta1 > 0) + p->bwdRefQpDelta = refQpDelta1; + if (nonRefQpDelta1 > 0) + p->bwdNonRefQpDelta = nonRefQpDelta1; + } + else if (p->bEnableSceneCutAwareQp == BI_DIRECTIONAL) + { + int window2; + double refQpDelta2, nonRefQpDelta2; + sscanf(value, "%d,%lf,%lf,%d,%lf,%lf", &window1, &refQpDelta1, &nonRefQpDelta1, &window2, &refQpDelta2, &nonRefQpDelta2); + if (window1 > 0) + p->fwdScenecutWindow = window1; + if (refQpDelta1 > 0) + p->fwdRefQpDelta = refQpDelta1; + if (nonRefQpDelta1 > 0) + p->fwdNonRefQpDelta = nonRefQpDelta1; + if (window2 > 0) + p->bwdScenecutWindow = window2; + if (refQpDelta2 > 0) + p->bwdRefQpDelta = refQpDelta2; + if (nonRefQpDelta2 > 0) + p->bwdNonRefQpDelta = nonRefQpDelta2; + } + } OPT("field") p->bField = atobool( value ); OPT("cll") p->bEmitCLL = atobool(value); OPT("frame-dup") p->bEnableFrameDuplication = atobool(value); @@ -1787,12 +1831,19 @@ int x265_check_params(x265_param* param) } else { - CHECK(param->scenecutWindow < 0 || param->scenecutWindow > 1000, - "Invalid scenecut Window duration. Value must be between 0 and 1000(inclusive)"); - CHECK(param->refQpDelta < 0 || param->refQpDelta > 10, - "Invalid refQpDelta value. Value must be between 0 and 10 (inclusive)"); - CHECK(param->nonRefQpDelta < 0 || param->nonRefQpDelta > 10, - "Invalid nonRefQpDelta value. Value must be between 0 and 10 (inclusive)"); + CHECK(param->fwdScenecutWindow < 0 || param->fwdScenecutWindow > 1000, + "Invalid forward scenecut Window duration. Value must be between 0 and 1000(inclusive)"); + CHECK(param->fwdRefQpDelta < 0 || param->fwdRefQpDelta > 10, + "Invalid fwdRefQpDelta value. Value must be between 0 and 10 (inclusive)"); + CHECK(param->fwdNonRefQpDelta < 0 || param->fwdNonRefQpDelta > 10, + "Invalid fwdNonRefQpDelta value. Value must be between 0 and 10 (inclusive)"); + + CHECK(param->bwdScenecutWindow < 0 || param->bwdScenecutWindow > 1000, + "Invalid backward scenecut Window duration. Value must be between 0 and 1000(inclusive)"); + CHECK(param->bwdRefQpDelta < -1 || param->bwdRefQpDelta > 10, + "Invalid bwdRefQpDelta value. Value must be between 0 and 10 (inclusive)"); + CHECK(param->bwdNonRefQpDelta < -1 || param->bwdNonRefQpDelta > 10, + "Invalid bwdNonRefQpDelta value. Value must be between 0 and 10 (inclusive)"); } } if (param->bEnableHME) @@ -2252,9 +2303,7 @@ char *x265_param2string(x265_param* p, int padx, int pady) BOOL(p->bEnableSvtHevc, "svt"); BOOL(p->bField, "field"); s += sprintf(s, " qp-adaptation-range=%.2f", p->rc.qpAdaptationRange); - BOOL(p->bEnableSceneCutAwareQp, "scenecut-aware-qp"); - if (p->bEnableSceneCutAwareQp) - s += sprintf(s, " scenecut-window=%d qp-delta-ref=%f qp-delta-nonref=%f", p->scenecutWindow, p->refQpDelta, p->nonRefQpDelta); + s += sprintf(s, " scenecut-aware-qp=%d", p->bEnableSceneCutAwareQp); s += sprintf(s, "conformance-window-offsets right=%d bottom=%d", p->confWinRightOffset, p->confWinBottomOffset); s += sprintf(s, " decoder-max-rate=%d", p->decoderVbvMaxRate); BOOL(p->bliveVBV2pass, "vbv-live-multi-pass"); @@ -2608,9 +2657,12 @@ void x265_copy_params(x265_param* dst, x265_param* src) dst->bEnableSvtHevc = src->bEnableSvtHevc; dst->bEnableFades = src->bEnableFades; dst->bEnableSceneCutAwareQp = src->bEnableSceneCutAwareQp; - dst->scenecutWindow = src->scenecutWindow; - dst->refQpDelta = src->refQpDelta; - dst->nonRefQpDelta = src->nonRefQpDelta; + dst->fwdScenecutWindow = src->fwdScenecutWindow; + dst->fwdRefQpDelta = src->fwdRefQpDelta; + dst->fwdNonRefQpDelta = src->fwdNonRefQpDelta; + dst->bwdScenecutWindow = src->bwdScenecutWindow; + dst->bwdRefQpDelta = src->bwdRefQpDelta; + dst->bwdNonRefQpDelta = src->bwdNonRefQpDelta; dst->bField = src->bField; dst->confWinRightOffset = src->confWinRightOffset; diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp index 1f710e1ce..d880bc62a 100644 --- a/source/encoder/encoder.cpp +++ b/source/encoder/encoder.cpp @@ -1810,13 +1810,13 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out) inFrame->m_lowres.m_bIsHardScenecut = isHardSC; } - if (m_param->bEnableSceneCutAwareQp && m_param->rc.bStatRead) + if ((m_param->bEnableSceneCutAwareQp == BI_DIRECTIONAL || m_param->bEnableSceneCutAwareQp == BACKWARD) && m_param->rc.bStatRead) { RateControlEntry * rcEntry = NULL; rcEntry = &(m_rateControl->m_rce2Pass[inFrame->m_poc]); if(rcEntry->scenecut) { - int backwardWindow = X265_MIN(int((p->fpsNum / p->fpsDenom) / 10), p->lookaheadDepth); + int backwardWindow = X265_MIN(int((m_param->bwdScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom)), p->lookaheadDepth); for (int i = 1; i <= backwardWindow; i++) { int frameNum = inFrame->m_poc - i; @@ -2253,7 +2253,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out) m_rateControl->m_lastScenecut = frameEnc->m_poc; else { - int maxWindowSize = int((m_param->scenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5); + int maxWindowSize = int((m_param->fwdScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5); if (frameEnc->m_poc > (m_rateControl->m_lastScenecut + maxWindowSize)) m_rateControl->m_lastScenecut = frameEnc->m_poc; } diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp index 4e7d52419..606c36bf5 100644 --- a/source/encoder/ratecontrol.cpp +++ b/source/encoder/ratecontrol.cpp @@ -1854,7 +1854,7 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce) rce->qpNoVbv = q; } /* Scenecut Aware QP offsets*/ - if (m_param->bEnableSceneCutAwareQp) + if (m_param->bEnableSceneCutAwareQp == BI_DIRECTIONAL || m_param->bEnableSceneCutAwareQp == FORWARD) { double lqmin = m_lmin[m_sliceType]; double lqmax = m_lmax[m_sliceType]; @@ -1863,6 +1863,15 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce) q = x265_qScale2qp(qScale); rce->qpNoVbv = q; } + else if(m_param->bEnableSceneCutAwareQp == BACKWARD) + { + double lqmin = m_lmin[m_sliceType]; + double lqmax = m_lmax[m_sliceType]; + qScale = backwardMasking(curFrame, qScale); + qScale = x265_clip3(lqmin, lqmax, qScale); + q = x265_qScale2qp(qScale); + rce->qpNoVbv = q; + } if (m_isVbv) { @@ -1977,7 +1986,7 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce) } /* Scenecut Aware QP offsets*/ - if (m_param->bEnableSceneCutAwareQp) + if (m_param->bEnableSceneCutAwareQp == BI_DIRECTIONAL || m_param->bEnableSceneCutAwareQp == FORWARD) { double qmin = m_lmin[m_sliceType]; double qmax = m_lmax[m_sliceType]; @@ -1985,6 +1994,14 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce) q = x265_clip3(qmin, qmax, q); rce->qpNoVbv = x265_qScale2qp(q); } + else if (m_param->bEnableSceneCutAwareQp == BACKWARD) + { + double qmin = m_lmin[m_sliceType]; + double qmax = m_lmax[m_sliceType]; + q = backwardMasking(curFrame, q); + q = x265_clip3(qmin, qmax, q); + rce->qpNoVbv = x265_qScale2qp(q); + } if (m_isVbv) { @@ -2141,7 +2158,7 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce) q = x265_clip3(lqmin, lqmax, q); } /* Scenecut Aware QP offsets*/ - if (m_param->bEnableSceneCutAwareQp) + if (m_param->bEnableSceneCutAwareQp == BI_DIRECTIONAL || m_param->bEnableSceneCutAwareQp == FORWARD) { double qmin = m_lmin[m_sliceType]; double qmax = m_lmax[m_sliceType]; @@ -2149,6 +2166,14 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce) q = x265_clip3(qmin, qmax, q); rce->qpNoVbv = x265_qScale2qp(q); } + else if (m_param->bEnableSceneCutAwareQp == BACKWARD) + { + double qmin = m_lmin[m_sliceType]; + double qmax = m_lmax[m_sliceType]; + q = backwardMasking(curFrame, q); + q = x265_clip3(qmin, qmax, q); + rce->qpNoVbv = x265_qScale2qp(q); + } q = clipQscale(curFrame, rce, q); if (m_2pass) @@ -3171,15 +3196,17 @@ void RateControl::splitbUsed(char bused[], RateControlEntry *rce) double RateControl::scenecutAwareMasking(Frame* curFrame, double q) { double qp = x265_qScale2qp(q); - uint32_t maxWindowSize = uint32_t((m_param->scenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5); + uint32_t maxWindowSize = uint32_t((m_param->fwdScenecutWindow / 1000.0) * (m_param->fpsNum / m_param->fpsDenom) + 0.5); uint32_t windowSize = maxWindowSize / 3; int lastScenecut = m_top->m_rateControl->m_lastScenecut; int lastIFrame = m_top->m_rateControl->m_lastScenecutAwareIFrame; - double refQpDelta = double(m_param->refQpDelta); - double nonRefQpDelta = double(m_param->nonRefQpDelta); - double sliceTypeDelta = SLICE_TYPE_DELTA * refQpDelta; - double window2Delta = WINDOW2_DELTA * refQpDelta; - double window3Delta = WINDOW3_DELTA * refQpDelta; + double fwdRefQpDelta = double(m_param->fwdRefQpDelta); + double fwdNonRefQpDelta = double(m_param->fwdNonRefQpDelta); + double bwdRefQpDelta = double(m_param->bwdRefQpDelta); + double bwdNonRefQpDelta = double(m_param->bwdNonRefQpDelta); + double sliceTypeDelta = SLICE_TYPE_DELTA * fwdRefQpDelta; + double window2Delta = WINDOW2_DELTA * fwdRefQpDelta; + double window3Delta = WINDOW3_DELTA * fwdRefQpDelta; if (curFrame->m_poc > lastScenecut && curFrame->m_poc <= (lastScenecut + int(maxWindowSize))) curFrame->m_isInsideWindow = FORWARD_WINDOW; @@ -3194,7 +3221,7 @@ double RateControl::scenecutAwareMasking(Frame* curFrame, double q) if (!(lastIFrame > lastScenecut && lastIFrame <= (lastScenecut + int(maxWindowSize)) && curFrame->m_poc >= lastIFrame)) { - qp += refQpDelta - sliceTypeDelta; + qp += fwdRefQpDelta - sliceTypeDelta; if (((curFrame->m_poc) > (lastScenecut + int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 2 * int(windowSize)))) qp -= window2Delta; else if (curFrame->m_poc > lastScenecut + 2 * int(windowSize)) @@ -3206,7 +3233,7 @@ double RateControl::scenecutAwareMasking(Frame* curFrame, double q) if (!(lastIFrame > lastScenecut && lastIFrame <= (lastScenecut + int(maxWindowSize)) && curFrame->m_poc >= lastIFrame)) { - qp += refQpDelta; + qp += fwdRefQpDelta; if (((curFrame->m_poc) > (lastScenecut + int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 2 * int(windowSize)))) qp -= window2Delta; else if (curFrame->m_poc > lastScenecut + 2 * int(windowSize)) @@ -3218,7 +3245,7 @@ double RateControl::scenecutAwareMasking(Frame* curFrame, double q) if (!(lastIFrame > lastScenecut && lastIFrame <= (lastScenecut + int(maxWindowSize)) && curFrame->m_poc >= lastIFrame)) { - qp += nonRefQpDelta; + qp += fwdNonRefQpDelta; if (((curFrame->m_poc) > (lastScenecut + int(windowSize))) && ((curFrame->m_poc) <= (lastScenecut + 2 * int(windowSize)))) qp -= window2Delta; else if (curFrame->m_poc > lastScenecut + 2 * int(windowSize)) @@ -3228,14 +3255,44 @@ double RateControl::scenecutAwareMasking(Frame* curFrame, double q) } else if (curFrame->m_isInsideWindow == BACKWARD_WINDOW) { - refQpDelta -= window3Delta; - nonRefQpDelta -= window3Delta; + if (bwdRefQpDelta < 0) + bwdRefQpDelta = fwdRefQpDelta - window3Delta; + sliceTypeDelta = SLICE_TYPE_DELTA * bwdRefQpDelta; + if (bwdNonRefQpDelta < 0) + bwdNonRefQpDelta = bwdRefQpDelta + sliceTypeDelta; + + if (curFrame->m_lowres.sliceType == X265_TYPE_P) + qp += bwdRefQpDelta - sliceTypeDelta; + else if (curFrame->m_lowres.sliceType == X265_TYPE_BREF) + qp += bwdRefQpDelta; + else if (curFrame->m_lowres.sliceType == X265_TYPE_B) + qp += bwdNonRefQpDelta; + } + + return x265_qp2qScale(qp); +} +double RateControl::backwardMasking(Frame* curFrame, double q) +{ + double qp = x265_qScale2qp(q); + double fwdRefQpDelta = double(m_param->fwdRefQpDelta); + double window3Delta = WINDOW3_DELTA * fwdRefQpDelta; + double bwdRefQpDelta = double(m_param->bwdRefQpDelta); + double bwdNonRefQpDelta = double(m_param->bwdNonRefQpDelta); + + if (curFrame->m_isInsideWindow == BACKWARD_WINDOW) + { + if (bwdRefQpDelta < 0) + bwdRefQpDelta = fwdRefQpDelta - window3Delta; + double sliceTypeDelta = SLICE_TYPE_DELTA * bwdRefQpDelta; + if (bwdNonRefQpDelta < 0) + bwdNonRefQpDelta = bwdRefQpDelta + sliceTypeDelta; + if (curFrame->m_lowres.sliceType == X265_TYPE_P) - qp += refQpDelta - sliceTypeDelta; + qp += bwdRefQpDelta - sliceTypeDelta; else if (curFrame->m_lowres.sliceType == X265_TYPE_BREF) - qp += refQpDelta; + qp += bwdRefQpDelta; else if (curFrame->m_lowres.sliceType == X265_TYPE_B) - qp += nonRefQpDelta; + qp += bwdNonRefQpDelta; } return x265_qp2qScale(qp); diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h index 809e0c620..dc4d882a6 100644 --- a/source/encoder/ratecontrol.h +++ b/source/encoder/ratecontrol.h @@ -270,6 +270,7 @@ public: bool initPass2(); double scenecutAwareMasking(Frame* curFrame, double q); + double backwardMasking(Frame* curFrame, double q); protected: diff --git a/source/x265.h b/source/x265.h index f44040ba7..668e9a9c2 100644 --- a/source/x265.h +++ b/source/x265.h @@ -607,6 +607,9 @@ typedef enum #define X265_ANALYSIS_SAVE 1 #define X265_ANALYSIS_LOAD 2 +#define FORWARD 1 +#define BACKWARD 2 +#define BI_DIRECTIONAL 3 #define SLICE_TYPE_DELTA 0.3 /* The offset decremented or incremented for P-frames or b-frames respectively*/ #define BACKWARD_WINDOW 1 /* Scenecut window before a scenecut */ #define FORWARD_WINDOW 2 /* Scenecut window after a scenecut */ @@ -1847,21 +1850,34 @@ typedef struct x265_param Default 1 (Enabled). API only. */ int bResetZoneConfig; - /* It reduces the bits spent on the inter-frames within the scenecutWindow before and after a scenecut + /* It reduces the bits spent on the inter-frames within the scenecutWindow before and / or after a scenecut * by increasing their QP in ratecontrol pass2 algorithm without any deterioration in visual quality. - * Default is disabled. */ + * 0 - Disabled (default). + * 1 - Forward masking. + * 2 - Backward masking. + * 3 - Bi-directional masking. */ int bEnableSceneCutAwareQp; /* The duration(in milliseconds) for which there is a reduction in the bits spent on the inter-frames after a scenecut - * by increasing their QP, when bEnableSceneCutAwareQp is set. Default is 500ms.*/ - int scenecutWindow; + * by increasing their QP, when bEnableSceneCutAwareQp is 1 or 3. Default is 500ms.*/ + int fwdScenecutWindow; - /* The offset by which QP is incremented for inter-frames when bEnableSceneCutAwareQp is set. + /* The offset by which QP is incremented for inter-frames after a scenecut when bEnableSceneCutAwareQp is 1 or 3. * Default is +5. */ - double refQpDelta; + double fwdRefQpDelta; - /* The offset by which QP is incremented for non-referenced inter-frames when bEnableSceneCutAwareQp is set. */ - double nonRefQpDelta; + /* The offset by which QP is incremented for non-referenced inter-frames after a scenecut when bEnableSceneCutAwareQp is 1 or 3. */ + double fwdNonRefQpDelta; + + /* The duration(in milliseconds) for which there is a reduction in the bits spent on the inter-frames before a scenecut + * by increasing their QP, when bEnableSceneCutAwareQp is 2 or 3. Default is 100ms.*/ + int bwdScenecutWindow; + + /* The offset by which QP is incremented for inter-frames before a scenecut when bEnableSceneCutAwareQp is 2 or 3. */ + double bwdRefQpDelta; + + /* The offset by which QP is incremented for non-referenced inter-frames before a scenecut when bEnableSceneCutAwareQp is 2 or 3. */ + double bwdNonRefQpDelta; /* A genuine threshold used for histogram based scene cut detection. * This threshold determines whether a frame is a scenecut or not diff --git a/source/x265cli.cpp b/source/x265cli.cpp index c28dd7f8c..0f50589c1 100755 --- a/source/x265cli.cpp +++ b/source/x265cli.cpp @@ -177,10 +177,12 @@ namespace X265_NS { H0(" --no-hist-scenecut Disables histogram based scene-cut detection using histogram based algorithm.\n"); H1(" --hist-threshold <0.0..1.0> Luma Edge histogram's Normalized SAD threshold for histogram based scenecut detection Default %.2f\n", param->edgeTransitionThreshold); H0(" --[no-]fades Enable detection and handling of fade-in regions. Default %s\n", OPT(param->bEnableFades)); - H1(" --[no-]scenecut-aware-qp Enable increasing QP for frames inside the scenecut window after scenecut. Default %s\n", OPT(param->bEnableSceneCutAwareQp)); - H1(" --scenecut-window <0..1000> QP incremental duration(in milliseconds) when scenecut-aware-qp is enabled. Default %d\n", param->scenecutWindow); - H1(" --qp-delta-ref <0..10> QP offset to increment with base QP for inter-frames. Default %f\n", param->refQpDelta); - H1(" --qp-delta-nonref <0..10> QP offset to increment with base QP for non-referenced inter-frames. Default %f\n", param->nonRefQpDelta); + H1(" --scenecut-aware-qp <0..3> Enable increasing QP for frames inside the scenecut window around scenecut. Default %s\n", OPT(param->bEnableSceneCutAwareQp)); + H1(" 0 - Disabled\n"); + H1(" 1 - Forward masking\n"); + H1(" 2 - Backward masking\n"); + H1(" 3 - Bidirectional masking\n"); + H1(" --masking-strength <string> Comma separated values which specifies the duration and offset for the QP increment for inter-frames"); H0(" --radl <integer> Number of RADL pictures allowed in front of IDR. Default %d\n", param->radl); H0(" --intra-refresh Use Periodic Intra Refresh instead of IDR frames\n"); H0(" --rc-lookahead <integer> Number of frames for frame-type lookahead (determines encoder latency) Default %d\n", param->lookaheadDepth); diff --git a/source/x265cli.h b/source/x265cli.h index a24d25435..7a2e0a267 100644 --- a/source/x265cli.h +++ b/source/x265cli.h @@ -148,11 +148,8 @@ static const struct option long_options[] = { "hist-threshold", required_argument, NULL, 0}, { "fades", no_argument, NULL, 0 }, { "no-fades", no_argument, NULL, 0 }, - { "scenecut-aware-qp", no_argument, NULL, 0 }, - { "no-scenecut-aware-qp", no_argument, NULL, 0 }, - { "scenecut-window",required_argument, NULL, 0 }, - { "qp-delta-ref", required_argument, NULL, 0 }, - { "qp-delta-nonref",required_argument, NULL, 0 }, + { "scenecut-aware-qp", required_argument, NULL, 0 }, + { "masking-strength", required_argument, NULL, 0 }, { "radl", required_argument, NULL, 0 }, { "ctu-info", required_argument, NULL, 0 }, { "intra-refresh", no_argument, NULL, 0 }, -- 2.18.0.windows.1 -- Thanks & Regards *Niranjan Kumar B* Video Codec Engineer Media & AI Analytics +91 958 511 1449 <https://multicorewareinc.com/>
x265.diff
Description: Binary data
_______________________________________________ x265-devel mailing list x265-devel@videolan.org https://mailman.videolan.org/listinfo/x265-devel