<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Nov 20, 2017 at 11:12 AM,  <span dir="ltr"><<a href="mailto:aruna@multicorewareinc.com" target="_blank">aruna@multicorewareinc.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Aruna Matheswaran <<a href="mailto:aruna@multicorewareinc.com">aruna@multicorewareinc.com</a>><br>
# Date 1511155419 -19800<br>
#  Â  Â  Mon Nov 20 10:53:39 2017 +0530<br>
# Node ID d37d703039dae201c5a7114ff71e6c<wbr>4d4196347c<br>
# Parent  0f0d608e732be425d71169b4cf0563<wbr>adbfb7729b<br>
Extend gop boundary by doing gop lookahead<br></blockquote><div><br></div><div>Patch doesn't apply on default tip. Please fix and resend.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
diff -r 0f0d608e732b -r d37d703039da doc/reST/cli.rst<br>
--- a/doc/reST/cli.rst  Fri Nov 17 19:23:14 2017 +0530<br>
+++ b/doc/reST/cli.rst  Mon Nov 20 10:53:39 2017 +0530<br>
@@ -1373,6 +1373,14 @@<br>
  Â  Â  Â  Default 20<br>
<br>
  Â  Â  Â  **Range of values:** Between the maximum consecutive bframe count (:option:`--bframes`) and 250<br>
+<br>
+.. option:: --gop-lookahead <integer><br>
+<br>
+  Â  Â  Â Number of frames for GOP boundary decision lookahead. If a scenecut frame is found<br>
+  Â  Â  Â within this from the gop boundary set by `--keyint`, the GOP will be extented until such a point,<br>
+  Â  Â  Â otherwise the GOP will be terminated as set by `--keyint`. Default 0.<br>
+<br>
+  Â  Â  Â **Range of values:** Between 0 and `--rc-lookahead`.<br>
<br>
 .. option:: --lookahead-slices <0..16><br>
<br>
diff -r 0f0d608e732b -r d37d703039da source/CMakeLists.txt<br>
--- a/source/CMakeLists.txt  Â  Â Fri Nov 17 19:23:14 2017 +0530<br>
+++ b/source/CMakeLists.txt  Â  Â Mon Nov 20 10:53:39 2017 +0530<br>
@@ -29,7 +29,7 @@<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 146)<br>
+set(X265_BUILD 147)<br>
 configure_file("${PROJECT_<wbr>SOURCE_DIR}/<a href="http://x265.def.in" rel="noreferrer" target="_blank">x265.def.in</a>"<br>
  Â  Â  Â  Â  Â  Â  Â  "${PROJECT_BINARY_DIR}/x265.<wbr>def")<br>
 configure_file("${PROJECT_<wbr>SOURCE_DIR}/<a href="http://x265_config.h.in" rel="noreferrer" target="_blank">x265_config.h.in</a>"<br>
diff -r 0f0d608e732b -r d37d703039da source/common/param.cpp<br>
--- a/source/common/param.cpp  Â Fri Nov 17 19:23:14 2017 +0530<br>
+++ b/source/common/param.cpp  Â Mon Nov 20 10:53:39 2017 +0530<br>
@@ -144,6 +144,7 @@<br>
  Â  Â /* Coding Structure */<br>
  Â  Â param->keyframeMin = 0;<br>
  Â  Â param->keyframeMax = 250;<br>
+  Â  param->gopLookahead = 0;<br>
  Â  Â param->bOpenGOP = 1;<br>
  Â  Â param->bframes = 4;<br>
  Â  Â param->lookaheadDepth = 20;<br>
@@ -1004,6 +1005,7 @@<br>
  Â  Â  Â  Â  Â  Â  Â  Â bError = true;<br>
  Â  Â  Â  Â  Â  Â }<br>
  Â  Â  Â  Â  }<br>
+  Â  Â  Â  OPT("gop-lookahead") p->gopLookahead = atoi(value);<br>
  Â  Â  Â  Â else<br>
  Â  Â  Â  Â  Â  Â return X265_PARAM_BAD_NAME;<br>
  Â  Â }<br>
@@ -1314,6 +1316,8 @@<br>
  Â  Â  Â  Â  Â "Valid penalty for 32x32 intra TU in non-I slices. 0:disabled 1:RD-penalty 2:maximum");<br>
  Â  Â CHECK(param->keyframeMax < -1,<br>
  Â  Â  Â  Â  Â "Invalid max IDR period in frames. value should be greater than -1");<br>
+  Â  CHECK(param->gopLookahead < -1,<br>
+  Â  Â  Â  Â  "GOP lookahead must be greater than -1");<br>
  Â  Â CHECK(param-><wbr>decodedPictureHashSEI < 0 || param->decodedPictureHashSEI > 3,<br>
  Â  Â  Â  Â  Â "Invalid hash option. Decoded Picture Hash SEI 0: disabled, 1: MD5, 2: CRC, 3: Checksum");<br>
  Â  Â CHECK(param->rc.vbvBufferSize < 0,<br>
@@ -1561,6 +1565,7 @@<br>
  Â  Â BOOL(p->bOpenGOP, "open-gop");<br>
  Â  Â s += sprintf(s, " min-keyint=%d", p->keyframeMin);<br>
  Â  Â s += sprintf(s, " keyint=%d", p->keyframeMax);<br>
+  Â  s += sprintf(s, " gop-lookahead=%d", p->gopLookahead);<br>
  Â  Â s += sprintf(s, " bframes=%d", p->bframes);<br>
  Â  Â s += sprintf(s, " b-adapt=%d", p->bFrameAdaptive);<br>
  Â  Â BOOL(p->bBPyramid, "b-pyramid");<br>
diff -r 0f0d608e732b -r d37d703039da source/encoder/slicetype.cpp<br>
--- a/source/encoder/slicetype.cpp  Â  Â  Fri Nov 17 19:23:14 2017 +0530<br>
+++ b/source/encoder/slicetype.cpp  Â  Â  Mon Nov 20 10:53:39 2017 +0530<br>
@@ -589,6 +589,7 @@<br>
  Â  Â m_outputSignalRequired = false;<br>
  Â  Â m_isActive = true;<br>
  Â  Â m_inputCount = 0;<br>
+  Â  m_extendGopBoundary = false;<br>
<br>
  Â  Â m_8x8Height = ((m_param->sourceHeight / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;<br>
  Â  Â m_8x8Width = ((m_param->sourceWidth / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;<br>
@@ -647,6 +648,12 @@<br>
  Â  Â  Â  Â m_numCoopSlices = 1;<br>
  Â  Â }<br>
<br>
+  Â  if (param->gopLookahead > param->lookaheadDepth)<br>
+  Â  {<br>
+  Â  Â  Â  x265_log(param, X265_LOG_WARNING, "Gop-lookahead cannot be greater than rc-lookahead; Clipping gop-lookahead to rc-lookahead\n");<br>
+  Â  Â  Â  param->gopLookahead = param->lookaheadDepth;<br>
+  Â  }<br>
+<br>
 #if DETAILED_CU_STATS<br>
  Â  Â m_slicetypeDecideElapsedTime = 0;<br>
  Â  Â m_preLookaheadElapsedTime = 0;<br>
@@ -1086,7 +1093,8 @@<br>
  Â  Â  Â  Â  Â  Â x265_log(m_param, X265_LOG_WARNING, "B-ref at frame %d incompatible with B-pyramid and %d reference frames\n",<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  frm.sliceType, m_param->maxNumReferences);<br>
  Â  Â  Â  Â }<br>
-  Â  Â  Â  if ((!m_param->bIntraRefresh || frm.frameNum == 0) && frm.frameNum - m_lastKeyframe >= m_param->keyframeMax)<br>
+  Â  Â  Â  if ((!m_param->bIntraRefresh || frm.frameNum == 0) && frm.frameNum - m_lastKeyframe >= m_param->keyframeMax &&<br>
+  Â  Â  Â  Â  Â  (!m_extendGopBoundary || frm.frameNum - m_lastKeyframe >= m_param->keyframeMax + m_param->gopLookahead))<br>
  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â if (frm.sliceType == X265_TYPE_AUTO || frm.sliceType == X265_TYPE_I)<br>
  Â  Â  Â  Â  Â  Â  Â  Â frm.sliceType = m_param->bOpenGOP && m_lastKeyframe >= 0 ? X265_TYPE_I : X265_TYPE_IDR;<br>
@@ -1380,7 +1388,14 @@<br>
<br>
  Â  Â frames[framecnt + 1] = NULL;<br>
<br>
-  Â  keyintLimit = m_param->keyframeMax - frames[0]->frameNum + m_lastKeyframe - 1;<br>
+  Â  int keyFrameLimit = m_param->keyframeMax + m_lastKeyframe - frames[1]->frameNum;<br>
+<br>
+  Â  if (m_param->gopLookahead && keyFrameLimit < m_param->bframes + 2)<br>
+  Â  Â  Â  keyintLimit = m_param->keyframeMax + m_param->gopLookahead - frames[0]->frameNum + m_lastKeyframe - 1;<br>
+  Â  else<br>
+  Â  Â  Â  keyintLimit = m_param->keyframeMax - frames[0]->frameNum + m_lastKeyframe - 1;<br>
+<br>
+<br></blockquote><div><br></div><div>Use keyFrameLimit to evaluate keyintLimit so that the evaluation on the RHS of the assignment can be simplified.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  Â  Â origNumFrames = numFrames = m_param->bIntraRefresh ? framecnt : X265_MIN(framecnt, keyintLimit);<br>
<br>
  Â  Â if (bIsVbvLookahead)<br>
@@ -1473,6 +1488,26 @@<br>
  Â  Â  Â  Â return;<br>
  Â  Â }<br>
<br>
+  Â  if (m_param->gopLookahead && keyFrameLimit >= 0 && keyFrameLimit < m_param->bframes + 2)<br></blockquote><div><br></div><div>Use parenthesis here to make each conditional check explicit.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+  Â  {<br>
+  Â  Â  Â  bool sceneTransition = m_isSceneTransition;<br>
+  Â  Â  Â  m_extendGopBoundary = false;<br>
+  Â  Â  Â  for (int i = m_param->bframes + 1; i < origNumFrames; i += m_param->bframes + 1)<br>
+  Â  Â  Â  {<br>
+  Â  Â  Â  Â  Â  scenecut(frames, i, i + 1, true, origNumFrames);<br>
+  Â  Â  Â  Â  Â  for (int j = i + 1; j <= X265_MIN(i + m_param->bframes + 1, origNumFrames); j++)<br>
+  Â  Â  Â  Â  Â  {<br>
+  Â  Â  Â  Â  Â  Â  Â  if (frames[j]->bScenecut && m_isSceneTransition && scenecut(frames, j - 1, j, false, origNumFrames))<br>
+  Â  Â  Â  Â  Â  Â  Â  {<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  m_extendGopBoundary = true;<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  break;<br>
+  Â  Â  Â  Â  Â  Â  Â  }<br>
+  Â  Â  Â  Â  Â  }<br>
+  Â  Â  Â  Â  Â  if (m_extendGopBoundary)<br>
+  Â  Â  Â  Â  Â  Â  Â  break;<br>
+  Â  Â  Â  }<br>
+  Â  Â  Â  m_isSceneTransition = sceneTransition;<br>
+  Â  }<br>
  Â  Â if (m_param->bframes)<br>
  Â  Â {<br>
  Â  Â  Â  Â if (m_param->bFrameAdaptive == X265_B_ADAPT_TRELLIS)<br>
@@ -1579,6 +1614,9 @@<br>
  Â  Â if (m_param->rc.cuTree)<br>
  Â  Â  Â  Â cuTree(frames, X265_MIN(numFrames, m_param->keyframeMax), bKeyframe);<br>
<br>
+  Â  if (m_param->gopLookahead && keyFrameLimit >= 0 && keyFrameLimit < m_param->bframes + 2 && !m_extendGopBoundary)<br>
+  Â  Â  Â  keyintLimit = m_param->keyframeMax - frames[0]->frameNum + m_lastKeyframe - 1;<br>
+<br>
  Â  Â if (!m_param->bIntraRefresh)<br>
  Â  Â  Â  Â for (int j = keyintLimit + 1; j <= numFrames; j += m_param->keyframeMax)<br>
  Â  Â  Â  Â {<br>
@@ -1588,8 +1626,9 @@<br>
<br>
  Â  Â if (bIsVbvLookahead)<br>
  Â  Â  Â  Â vbvLookahead(frames, numFrames, bKeyframe);<br>
-<br>
-  Â  Â int maxp1 = X265_MIN(m_param->bframes + 1, origNumFrames);<br>
+<br>
+  Â  int maxp1 = X265_MIN(m_param->bframes + 1, origNumFrames);<br>
+<br>
  Â  Â /* Restore frame types for all frames that haven't actually been decided yet. */<br>
  Â  Â for (int j = resetStart; j <= numFrames; j++)<br>
  Â  Â {<br>
@@ -1613,8 +1652,8 @@<br>
  Â  Â  Â  Â bool fluctuate = false;<br>
  Â  Â  Â  Â bool noScenecuts = false;<br>
  Â  Â  Â  Â int64_t avgSatdCost = 0;<br>
-  Â  Â  Â  if (frames[0]->costEst[1][0] > -1)<br>
-  Â  Â  Â  Â  Â  avgSatdCost = frames[0]->costEst[1][0];<br>
+  Â  Â  Â  if (frames[p0]->costEst[p1 - p0][0] > -1)<br>
+  Â  Â  Â  Â  Â  avgSatdCost = frames[p0]->costEst[p1 - p0][0];<br>
  Â  Â  Â  Â int cnt = 1;<br>
  Â  Â  Â  Â /* Where A and B are scenes: AAAAAABBBAAAAAA<br>
  Â  Â  Â  Â  * If BBB is shorter than (maxp1-p0), it is detected as a flash<br>
@@ -1717,14 +1756,21 @@<br>
  Â  Â  Â  Â  Â  Â bias = threshMin / 4;<br>
  Â  Â  Â  Â else if (gopSize <= m_param->keyframeMin)<br>
  Â  Â  Â  Â  Â  Â bias = threshMin * gopSize / m_param->keyframeMin;<br>
-  Â  Â  Â  else<br>
+  Â  Â  Â  else if (gopSize <= m_param->keyframeMax)<br>
  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â bias = threshMin<br>
  Â  Â  Â  Â  Â  Â  Â  Â + (threshMax - threshMin)<br>
  Â  Â  Â  Â  Â  Â  Â  Â * (gopSize - m_param->keyframeMin)<br>
  Â  Â  Â  Â  Â  Â  Â  Â / (m_param->keyframeMax - m_param->keyframeMin);<br>
  Â  Â  Â  Â }<br>
-  Â  }<br>
+  Â  Â  Â  else<br>
+  Â  Â  Â  {<br>
+  Â  Â  Â  Â  Â  bias = threshMin<br>
+  Â  Â  Â  Â  Â  Â  Â  + (threshMax - threshMin)<br>
+  Â  Â  Â  Â  Â  Â  Â  * (gopSize - m_param->keyframeMax)<br>
+  Â  Â  Â  Â  Â  Â  Â  / (m_param->gopLookahead);<br>
+  Â  Â  Â  }<br>
+ }<br>
  Â  Â bool res = pcost >= (1.0 - bias) * icost;<br>
  Â  Â if (res && bRealScenecut)<br>
  Â  Â {<br>
diff -r 0f0d608e732b -r d37d703039da source/encoder/slicetype.h<br>
--- a/source/encoder/slicetype.h  Â  Â  Â  Fri Nov 17 19:23:14 2017 +0530<br>
+++ b/source/encoder/slicetype.h  Â  Â  Â  Mon Nov 20 10:53:39 2017 +0530<br>
@@ -132,6 +132,7 @@<br>
  Â  Â bool  Â  Â  Â  Â  m_filled;<br>
  Â  Â bool  Â  Â  Â  Â  m_isSceneTransition;<br>
  Â  Â int  Â  Â  Â  Â  Â m_numPools;<br>
+  Â  bool  Â  Â  Â  Â  m_extendGopBoundary;<br>
  Â  Â Lookahead(x265_param *param, ThreadPool *pool);<br>
 #if DETAILED_CU_STATS<br>
  Â  Â int64_t  Â  Â  Â m_slicetypeDecideElapsedTime;<br>
diff -r 0f0d608e732b -r d37d703039da source/test/regression-tests.<wbr>txt<br>
--- a/source/test/regression-<wbr>tests.txt  Fri Nov 17 19:23:14 2017 +0530<br>
+++ b/source/test/regression-<wbr>tests.txt  Mon Nov 20 10:53:39 2017 +0530<br>
@@ -150,6 +150,7 @@<br>
 Kimono1_1920x1080_24_400.yuv,-<wbr>-preset medium --rdoq-level 0 --limit-refs 3 --slices 2<br>
 Kimono1_1920x1080_24_400.yuv,-<wbr>-preset veryslow --crf 4 --cu-lossless --slices 2 --limit-refs 3 --limit-modes<br>
 Kimono1_1920x1080_24_400.yuv,-<wbr>-preset placebo --ctu 32 --max-tu-size 8 --limit-tu 2<br>
+big_buck_bunny_360p24.y4m, --keyint 60 --min-keyint 40 --gop-lookahead 20<br>
<br>
 # Main12 intraCost overflow bug test<br>
 720p50_parkrun_ter.y4m,--<wbr>preset medium<br>
diff -r 0f0d608e732b -r d37d703039da source/test/smoke-tests.txt<br>
--- a/source/test/smoke-tests.txt  Â  Â  Â Fri Nov 17 19:23:14 2017 +0530<br>
+++ b/source/test/smoke-tests.txt  Â  Â  Â Mon Nov 20 10:53:39 2017 +0530<br>
@@ -20,5 +20,6 @@<br>
 DucksAndLegs_1920x1080_60_<wbr>10bit_422.yuv,--preset=fast --weightb --interlace bff<br>
 DucksAndLegs_1920x1080_60_<wbr>10bit_422.yuv,--preset=<wbr>veryslow --limit-ref 1 --limit-mode --tskip --limit-tu 1<br>
 CrowdRun_1920x1080_50_10bit_<wbr>444.yuv,--preset=superfast --bitrate 7000 --sao --limit-sao<br>
+RaceHorses_416x240_30_10bit.<wbr>yuv, --preset=fast --bitrate 500 --gop-lookahead 10<br></blockquote><div><br></div><div>Lets not add a separate line in smoke test for this feature. Just piggy-back on another command line to limit run-time of smoke tests. A separate test in regression is ok.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 # Main12 intraCost overflow bug test<br>
 720p50_parkrun_ter.y4m,--<wbr>preset medium<br>
diff -r 0f0d608e732b -r d37d703039da source/x265.h<br>
--- a/source/x265.h  Â  Â Fri Nov 17 19:23:14 2017 +0530<br>
+++ b/source/x265.h  Â  Â Mon Nov 20 10:53:39 2017 +0530<br>
@@ -1535,6 +1535,11 @@<br>
<br>
  Â  Â /* Allow the encoder to have a copy of the planes of x265_picture in Frame */<br>
  Â  Â int  Â  Â  Â bCopyPicToFrame;<br>
+<br>
+  Â  /*Number of frames for GOP boundary decision lookahead.If a scenecut frame is found<br>
+  Â  * within this from the gop boundary set by keyint, the GOP will be extented until such a point,<br>
+  Â  * otherwise the GOP will be terminated as set by keyint*/<br>
+  Â  int  Â  Â  Â gopLookahead;<br>
 } x265_param;<br>
<br>
 /* x265_param_alloc:<br>
diff -r 0f0d608e732b -r d37d703039da source/x265cli.h<br>
--- a/source/x265cli.h  Fri Nov 17 19:23:14 2017 +0530<br>
+++ b/source/x265cli.h  Mon Nov 20 10:53:39 2017 +0530<br>
@@ -119,6 +119,7 @@<br>
  Â  Â { "open-gop",  Â  Â  Â  Â  Â  Â no_argument, NULL, 0 },<br>
  Â  Â { "keyint",  Â  Â  Â  Â required_argument, NULL, 'I' },<br>
  Â  Â { "min-keyint",  Â  Â required_argument, NULL, 'i' },<br>
+  Â  { "gop-lookahead",  required_argument, NULL, 0 },<br>
  Â  Â { "scenecut",  Â  Â  Â required_argument, NULL, 0 },<br>
  Â  Â { "no-scenecut",  Â  Â  Â  Â  no_argument, NULL, 0 },<br>
  Â  Â { "scenecut-bias",  required_argument, NULL, 0 },<br>
@@ -418,6 +419,7 @@<br>
  Â  Â H0("  Â --[no-]open-gop  Â  Â  Â  Â  Â  Â  Â Enable open-GOP, allows I slices to be non-IDR. Default %s\n", OPT(param->bOpenGOP));<br>
  Â  Â H0("-I/--keyint <integer>  Â  Â  Â  Â  Â  Max IDR period in frames. -1 for infinite-gop. Default %d\n", param->keyframeMax);<br>
  Â  Â H0("-i/--min-keyint <integer>  Â  Â  Â  Scenecuts closer together than this are coded as I, not IDR. Default: auto\n");<br>
+  Â  H0("  Â --gop-lookahead <integer>  Â  Â Extends gop boundary if a scenecut is found within this from keyint boundary. Default 0\n");<br>
  Â  Â H0("  Â --no-scenecut  Â  Â  Â  Â  Â  Â  Â  Â Disable adaptive I-frame decision\n");<br>
  Â  Â H0("  Â --scenecut <integer>  Â  Â  Â  Â  How aggressively to insert extra I-frames. Default %d\n", param->scenecutThreshold);<br>
  Â  Â H1("  Â --scenecut-bias <0..100.0>  Â  Bias for scenecut detection. Default %.2f\n", param->scenecutBias);<br>
<br>______________________________<wbr>_________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/<wbr>listinfo/x265-devel</a><br>
<br></blockquote></div><br></div></div>