[x265] [PATCH] Extend gop boundary by doing gop lookahead
Aruna Matheswaran
aruna at multicorewareinc.com
Fri Dec 1 06:17:26 CET 2017
I have resent the patch after fixing a warning.
Thanks,
Aruna
On Fri, Dec 1, 2017 at 10:46 AM, <aruna at multicorewareinc.com> wrote:
> # HG changeset patch
> # User Aruna Matheswaran <aruna at multicorewareinc.com>
> # Date 1511241504 -19800
> # Tue Nov 21 10:48:24 2017 +0530
> # Node ID 805ac1fd3e058a590ffc65126c884ceea0473b38
> # Parent b1dfa312234ed72c3541831a15f307feaf79484d
> Extend gop boundary by doing gop lookahead
>
> diff -r b1dfa312234e -r 805ac1fd3e05 doc/reST/cli.rst
> --- a/doc/reST/cli.rst Thu Nov 30 10:06:49 2017 +0530
> +++ b/doc/reST/cli.rst Tue Nov 21 10:48:24 2017 +0530
> @@ -1374,6 +1374,17 @@
>
> **Range of values:** Between the maximum consecutive bframe count
> (:option:`--bframes`) and 250
>
> +.. option:: --gop-lookahead <integer>
> +
> + Number of frames for GOP boundary decision lookahead. If a
> scenecut frame is found
> + within this from the gop boundary set by `--keyint`, the GOP will
> be extented until such a point,
> + otherwise the GOP will be terminated as set by `--keyint`.
> Default 0.
> +
> + **Range of values:** Between 0 and (`--rc-lookahead` - mini-GOP
> length)
> +
> + It is recommended to have `--gop-lookahaed` less than
> `--min-keyint` as scenecuts beyond
> + `--min-keyint` are already being coded as keyframes.
> +
> .. option:: --lookahead-slices <0..16>
>
> Use multiple worker threads to measure the estimated cost of each
> frame
> diff -r b1dfa312234e -r 805ac1fd3e05 source/CMakeLists.txt
> --- a/source/CMakeLists.txt Thu Nov 30 10:06:49 2017 +0530
> +++ b/source/CMakeLists.txt Tue Nov 21 10:48:24 2017 +0530
> @@ -29,7 +29,7 @@
> option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)
> mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)
> # X265_BUILD must be incremented each time the public API is changed
> -set(X265_BUILD 146)
> +set(X265_BUILD 147)
> configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
> "${PROJECT_BINARY_DIR}/x265.def")
> configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
> diff -r b1dfa312234e -r 805ac1fd3e05 source/common/param.cpp
> --- a/source/common/param.cpp Thu Nov 30 10:06:49 2017 +0530
> +++ b/source/common/param.cpp Tue Nov 21 10:48:24 2017 +0530
> @@ -144,6 +144,7 @@
> /* Coding Structure */
> param->keyframeMin = 0;
> param->keyframeMax = 250;
> + param->gopLookahead = 0;
> param->bOpenGOP = 1;
> param->bframes = 4;
> param->lookaheadDepth = 20;
> @@ -1004,6 +1005,7 @@
> bError = true;
> }
> }
> + OPT("gop-lookahead") p->gopLookahead = atoi(value);
> else
> return X265_PARAM_BAD_NAME;
> }
> @@ -1314,6 +1316,8 @@
> "Valid penalty for 32x32 intra TU in non-I slices. 0:disabled
> 1:RD-penalty 2:maximum");
> CHECK(param->keyframeMax < -1,
> "Invalid max IDR period in frames. value should be greater than
> -1");
> + CHECK(param->gopLookahead < -1,
> + "GOP lookahead must be greater than -1");
> CHECK(param->decodedPictureHashSEI < 0 ||
> param->decodedPictureHashSEI > 3,
> "Invalid hash option. Decoded Picture Hash SEI 0: disabled, 1:
> MD5, 2: CRC, 3: Checksum");
> CHECK(param->rc.vbvBufferSize < 0,
> @@ -1561,6 +1565,7 @@
> BOOL(p->bOpenGOP, "open-gop");
> s += sprintf(s, " min-keyint=%d", p->keyframeMin);
> s += sprintf(s, " keyint=%d", p->keyframeMax);
> + s += sprintf(s, " gop-lookahead=%d", p->gopLookahead);
> s += sprintf(s, " bframes=%d", p->bframes);
> s += sprintf(s, " b-adapt=%d", p->bFrameAdaptive);
> BOOL(p->bBPyramid, "b-pyramid");
> diff -r b1dfa312234e -r 805ac1fd3e05 source/encoder/slicetype.cpp
> --- a/source/encoder/slicetype.cpp Thu Nov 30 10:06:49 2017 +0530
> +++ b/source/encoder/slicetype.cpp Tue Nov 21 10:48:24 2017 +0530
> @@ -589,6 +589,7 @@
> m_outputSignalRequired = false;
> m_isActive = true;
> m_inputCount = 0;
> + m_extendGopBoundary = false;
>
> m_8x8Height = ((m_param->sourceHeight / 2) + X265_LOWRES_CU_SIZE - 1)
> >> X265_LOWRES_CU_BITS;
> m_8x8Width = ((m_param->sourceWidth / 2) + X265_LOWRES_CU_SIZE - 1)
> >> X265_LOWRES_CU_BITS;
> @@ -647,6 +648,11 @@
> m_numCoopSlices = 1;
> }
>
> + if (param->gopLookahead && (param->gopLookahead >
> (param->lookaheadDepth - param->bframes - 2)))
> + {
> + param->gopLookahead = X265_MAX(0, param->lookaheadDepth -
> param->bframes - 2);
> + x265_log(param, X265_LOG_WARNING, "Gop-lookahead cannot be
> greater than (rc-lookahead - length of the mini-gop); Clipping
> gop-lookahead to %d\n", param->gopLookahead);
> + }
> #if DETAILED_CU_STATS
> m_slicetypeDecideElapsedTime = 0;
> m_preLookaheadElapsedTime = 0;
> @@ -1086,7 +1092,8 @@
> x265_log(m_param, X265_LOG_WARNING, "B-ref at frame %d
> incompatible with B-pyramid and %d reference frames\n",
> frm.sliceType, m_param->maxNumReferences);
> }
> - if ((!m_param->bIntraRefresh || frm.frameNum == 0) &&
> frm.frameNum - m_lastKeyframe >= m_param->keyframeMax)
> + if ((!m_param->bIntraRefresh || frm.frameNum == 0) &&
> frm.frameNum - m_lastKeyframe >= m_param->keyframeMax &&
> + (!m_extendGopBoundary || frm.frameNum - m_lastKeyframe >=
> m_param->keyframeMax + m_param->gopLookahead))
> {
> if (frm.sliceType == X265_TYPE_AUTO || frm.sliceType ==
> X265_TYPE_I)
> frm.sliceType = m_param->bOpenGOP && m_lastKeyframe >= 0
> ? X265_TYPE_I : X265_TYPE_IDR;
> @@ -1379,8 +1386,13 @@
> }
>
> frames[framecnt + 1] = NULL;
> + int keyFrameLimit = m_param->keyframeMax + m_lastKeyframe -
> frames[0]->frameNum - 1;
> + if (m_param->gopLookahead && keyFrameLimit <= m_param->bframes + 1)
> + keyintLimit = keyFrameLimit + m_param->gopLookahead;
> + else
> + keyintLimit = keyFrameLimit;
>
> - keyintLimit = m_param->keyframeMax - frames[0]->frameNum +
> m_lastKeyframe - 1;
> +
> origNumFrames = numFrames = m_param->bIntraRefresh ? framecnt :
> X265_MIN(framecnt, keyintLimit);
>
> if (bIsVbvLookahead)
> @@ -1473,6 +1485,26 @@
> return;
> }
>
> + if (m_param->gopLookahead && (keyFrameLimit >= 0) && (keyFrameLimit
> <= m_param->bframes + 1))
> + {
> + bool sceneTransition = m_isSceneTransition;
> + m_extendGopBoundary = false;
> + for (int i = m_param->bframes + 1; i < origNumFrames; i +=
> m_param->bframes + 1)
> + {
> + scenecut(frames, i, i + 1, true, origNumFrames);
> + for (int j = i + 1; j <= X265_MIN(i + m_param->bframes + 1,
> origNumFrames); j++)
> + {
> + if (frames[j]->bScenecut && scenecutInternal(frames, j -
> 1, j, true) )
> + {
> + m_extendGopBoundary = true;
> + break;
> + }
> + }
> + if (m_extendGopBoundary)
> + break;
> + }
> + m_isSceneTransition = sceneTransition;
> + }
> if (m_param->bframes)
> {
> if (m_param->bFrameAdaptive == X265_B_ADAPT_TRELLIS)
> @@ -1579,6 +1611,9 @@
> if (m_param->rc.cuTree)
> cuTree(frames, X265_MIN(numFrames, m_param->keyframeMax),
> bKeyframe);
>
> + if (m_param->gopLookahead && (keyFrameLimit >= 0) && (keyFrameLimit
> <= m_param->bframes + 1) && !m_extendGopBoundary)
> + keyintLimit = keyFrameLimit;
> +
> if (!m_param->bIntraRefresh)
> for (int j = keyintLimit + 1; j <= numFrames; j +=
> m_param->keyframeMax)
> {
> @@ -1589,7 +1624,8 @@
> if (bIsVbvLookahead)
> vbvLookahead(frames, numFrames, bKeyframe);
>
> - int maxp1 = X265_MIN(m_param->bframes + 1, origNumFrames);
> + int maxp1 = X265_MIN(m_param->bframes + 1, origNumFrames);
> +
> /* Restore frame types for all frames that haven't actually been
> decided yet. */
> for (int j = resetStart; j <= numFrames; j++)
> {
> @@ -1613,8 +1649,8 @@
> bool fluctuate = false;
> bool noScenecuts = false;
> int64_t avgSatdCost = 0;
> - if (frames[0]->costEst[1][0] > -1)
> - avgSatdCost = frames[0]->costEst[1][0];
> + if (frames[p0]->costEst[p1 - p0][0] > -1)
> + avgSatdCost = frames[p0]->costEst[p1 - p0][0];
> int cnt = 1;
> /* Where A and B are scenes: AAAAAABBBAAAAAA
> * If BBB is shorter than (maxp1-p0), it is detected as a flash
> @@ -1703,7 +1739,7 @@
>
> int64_t icost = frame->costEst[0][0];
> int64_t pcost = frame->costEst[p1 - p0][0];
> - int gopSize = frame->frameNum - m_lastKeyframe;
> + int gopSize = (frame->frameNum - m_lastKeyframe) %
> m_param->keyframeMax;
> float threshMax = (float)(m_param->scenecutThreshold / 100.0);
>
> /* magic numbers pulled out of thin air */
> diff -r b1dfa312234e -r 805ac1fd3e05 source/encoder/slicetype.h
> --- a/source/encoder/slicetype.h Thu Nov 30 10:06:49 2017 +0530
> +++ b/source/encoder/slicetype.h Tue Nov 21 10:48:24 2017 +0530
> @@ -132,6 +132,7 @@
> bool m_filled;
> bool m_isSceneTransition;
> int m_numPools;
> + bool m_extendGopBoundary;
> Lookahead(x265_param *param, ThreadPool *pool);
> #if DETAILED_CU_STATS
> int64_t m_slicetypeDecideElapsedTime;
> diff -r b1dfa312234e -r 805ac1fd3e05 source/test/regression-tests.txt
> --- a/source/test/regression-tests.txt Thu Nov 30 10:06:49 2017 +0530
> +++ b/source/test/regression-tests.txt Tue Nov 21 10:48:24 2017 +0530
> @@ -150,6 +150,7 @@
> Kimono1_1920x1080_24_400.yuv,--preset medium --rdoq-level 0 --limit-refs
> 3 --slices 2
> Kimono1_1920x1080_24_400.yuv,--preset veryslow --crf 4 --cu-lossless
> --slices 2 --limit-refs 3 --limit-modes
> Kimono1_1920x1080_24_400.yuv,--preset placebo --ctu 32 --max-tu-size 8
> --limit-tu 2
> +big_buck_bunny_360p24.y4m, --keyint 60 --min-keyint 40 --gop-lookahead 20
>
> # Main12 intraCost overflow bug test
> 720p50_parkrun_ter.y4m,--preset medium
> diff -r b1dfa312234e -r 805ac1fd3e05 source/x265.h
> --- a/source/x265.h Thu Nov 30 10:06:49 2017 +0530
> +++ b/source/x265.h Tue Nov 21 10:48:24 2017 +0530
> @@ -1535,6 +1535,11 @@
>
> /* Allow the encoder to have a copy of the planes of x265_picture in
> Frame */
> int bCopyPicToFrame;
> +
> + /*Number of frames for GOP boundary decision lookahead.If a scenecut
> frame is found
> + * within this from the gop boundary set by keyint, the GOP will be
> extented until such a point,
> + * otherwise the GOP will be terminated as set by keyint*/
> + int gopLookahead;
> } x265_param;
>
> /* x265_param_alloc:
> diff -r b1dfa312234e -r 805ac1fd3e05 source/x265cli.h
> --- a/source/x265cli.h Thu Nov 30 10:06:49 2017 +0530
> +++ b/source/x265cli.h Tue Nov 21 10:48:24 2017 +0530
> @@ -119,6 +119,7 @@
> { "open-gop", no_argument, NULL, 0 },
> { "keyint", required_argument, NULL, 'I' },
> { "min-keyint", required_argument, NULL, 'i' },
> + { "gop-lookahead", required_argument, NULL, 0 },
> { "scenecut", required_argument, NULL, 0 },
> { "no-scenecut", no_argument, NULL, 0 },
> { "scenecut-bias", required_argument, NULL, 0 },
> @@ -418,6 +419,7 @@
> H0(" --[no-]open-gop Enable open-GOP, allows I slices
> to be non-IDR. Default %s\n", OPT(param->bOpenGOP));
> H0("-I/--keyint <integer> Max IDR period in frames. -1 for
> infinite-gop. Default %d\n", param->keyframeMax);
> H0("-i/--min-keyint <integer> Scenecuts closer together than
> this are coded as I, not IDR. Default: auto\n");
> + H0(" --gop-lookahead <integer> Extends gop boundary if a
> scenecut is found within this from keyint boundary. Default 0\n");
> H0(" --no-scenecut Disable adaptive I-frame
> decision\n");
> H0(" --scenecut <integer> How aggressively to insert extra
> I-frames. Default %d\n", param->scenecutThreshold);
> H1(" --scenecut-bias <0..100.0> Bias for scenecut detection.
> Default %.2f\n", param->scenecutBias);
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20171201/5acbdbf3/attachment-0001.html>
More information about the x265-devel
mailing list