<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Nov 6, 2017 at 11:42 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 1509948124 -19800<br>
#      Mon Nov 06 11:32:04 2017 +0530<br>
# Node ID 8a121d8cc134cc348466e5d63a6a02<wbr>d1531d8055<br>
# Parent  aa9649a2aa8c30bcb84ee8287839fa<wbr>877978d4a7<br>
Add vbv-end to denote VBV emptiness after inserting all the frames into it.<br></blockquote><div><br></div><div>Pushed to default branch. Thanks.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
diff -r aa9649a2aa8c -r 8a121d8cc134 doc/reST/cli.rst<br>
--- a/doc/reST/cli.rst  Mon Nov 06 09:43:36 2017 +0530<br>
+++ b/doc/reST/cli.rst  Mon Nov 06 11:32:04 2017 +0530<br>
@@ -1496,6 +1496,24 @@<br>
        Default 0.9<br>
<br>
        **Range of values:** fractional: 0 - 1.0, or kbits: 2 .. bufsize<br>
+<br>
+.. option:: --vbv-end <float><br>
+<br>
+    Final buffer emptiness. The portion of the decode buffer that must be<br>
+       available after all the specified frames have been inserted into the<br>
+       decode buffer. Specified as a fractional value between 0 and 1, or in<br>
+       kbits. Default 0 (disabled)<br>
+<br>
+       This enables basic support for chunk-parallel encoding where each segment<br>
+       can specify the starting and ending state of the VBV buffer so that VBV<br>
+       compliance can be maintained when chunks are independently encoded and<br>
+       stitched together.<br>
+<br>
+.. option:: --vbv-end-fr-adj <float><br>
+<br>
+    Frame from which qp has to be adjusted to achieve final decode buffer<br>
+       emptiness. Specified as a fraction of the total frames. Fractions > 0 are<br>
+       supported only when the total number of frames is known. Default 0.<br>
<br>
 .. option:: --qp, -q <integer><br>
<br>
diff -r aa9649a2aa8c -r 8a121d8cc134 source/CMakeLists.txt<br>
--- a/source/CMakeLists.txt     Mon Nov 06 09:43:36 2017 +0530<br>
+++ b/source/CMakeLists.txt     Mon Nov 06 11:32:04 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 139)<br>
+set(X265_BUILD 140)<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 aa9649a2aa8c -r 8a121d8cc134 source/common/param.cpp<br>
--- a/source/common/param.cpp   Mon Nov 06 09:43:36 2017 +0530<br>
+++ b/source/common/param.cpp   Mon Nov 06 11:32:04 2017 +0530<br>
@@ -212,6 +212,8 @@<br>
     param->rc.vbvMaxBitrate = 0;<br>
     param->rc.vbvBufferSize = 0;<br>
     param->rc.vbvBufferInit = 0.9;<br>
+    param->vbvBufferEnd = 0;<br>
+    param->vbvEndFrameAdjust = 0;<br>
     param->rc.rfConstant = 28;<br>
     param->rc.bitrate = 0;<br>
     param->rc.qCompress = 0.6;<br>
@@ -982,6 +984,8 @@<br>
         OPT("force-flush")p-><wbr>forceFlush = atoi(value);<br>
         OPT("splitrd-skip") p->bEnableSplitRdSkip = atobool(value);<br>
                OPT("lowpass-dct") p->bLowPassDct = atobool(value);<br>
+        OPT("vbv-end") p->vbvBufferEnd = atof(value);<br>
+        OPT("vbv-end-fr-adj") p->vbvEndFrameAdjust = atof(value);<br>
         else<br>
             return X265_PARAM_BAD_NAME;<br>
     }<br>
@@ -1300,6 +1304,12 @@<br>
           "Maximum local bit rate can not be less than zero");<br>
     CHECK(param->rc.vbvBufferInit < 0,<br>
           "Valid initial VBV buffer occupancy must be a fraction 0 - 1, or size in kbits");<br>
+    CHECK(param->vbvBufferEnd < 0,<br>
+        "Valid final VBV buffer emptiness must be a fraction 0 - 1, or size in kbits");<br>
+    CHECK(param->vbvEndFrameAdjust < 0,<br>
+        "Valid vbv-end-fr-adj must be a fraction 0 - 1");<br>
+    CHECK(!param->totalFrames && param->vbvEndFrameAdjust,<br>
+        "vbv-end-fr-adj cannot be enabled when total number of frames is unknown");<br>
     CHECK(param->rc.bitrate < 0,<br>
           "Target bitrate can not be less than zero");<br>
     CHECK(param->rc.qCompress < 0.5 || param->rc.qCompress > 1.0,<br>
@@ -1423,9 +1433,15 @@<br>
     }<br>
<br>
     if (param->rc.vbvBufferSize)<br>
-        x265_log(param, X265_LOG_INFO, "VBV/HRD buffer / max-rate / init    : %d / %d / %.3f\n",<br>
-                 param->rc.vbvBufferSize, param->rc.vbvMaxBitrate, param->rc.vbvBufferInit);<br>
-<br>
+    {<br>
+        if (param->vbvBufferEnd)<br>
+            x265_log(param, X265_LOG_INFO, "VBV/HRD buffer / max-rate / init / end / fr-adj: %d / %d / %.3f / %.3f / %.3f\n",<br>
+            param->rc.vbvBufferSize, param->rc.vbvMaxBitrate, param->rc.vbvBufferInit, param->vbvBufferEnd, param->vbvEndFrameAdjust);<br>
+        else<br>
+            x265_log(param, X265_LOG_INFO, "VBV/HRD buffer / max-rate / init    : %d / %d / %.3f\n",<br>
+            param->rc.vbvBufferSize, param->rc.vbvMaxBitrate, param->rc.vbvBufferInit);<br>
+    }<br>
+<br>
     char buf[80] = { 0 };<br>
     char tmp[40];<br>
 #define TOOLOPT(FLAG, STR) if (FLAG) appendtool(param, buf, sizeof(buf), STR);<br>
@@ -1602,8 +1618,10 @@<br>
         {<br>
             s += sprintf(s, " vbv-maxrate=%d vbv-bufsize=%d vbv-init=%.1f",<br>
                  p->rc.vbvMaxBitrate, p->rc.vbvBufferSize, p->rc.vbvBufferInit);<br>
+            if (p->vbvBufferEnd)<br>
+                s += sprintf(s, " vbv-end=%.1f vbv-end-fr-adj=%.1f", p->vbvBufferEnd, p->vbvEndFrameAdjust);<br>
             if (p->rc.rateControlMode == X265_RC_CRF)<br>
-                s += sprintf(s, " crf-max=%.1f crf-min=%.1f", p->rc.rfConstantMax, p->rc.rfConstantMin);<br>
+                s += sprintf(s, " crf-max=%.1f crf-min=%.1f", p->rc.rfConstantMax, p->rc.rfConstantMin);<br>
         }<br>
     }<br>
     else if (p->rc.rateControlMode == X265_RC_CQP)<br>
diff -r aa9649a2aa8c -r 8a121d8cc134 source/encoder/ratecontrol.cpp<br>
--- a/source/encoder/ratecontrol.<wbr>cpp    Mon Nov 06 09:43:36 2017 +0530<br>
+++ b/source/encoder/ratecontrol.<wbr>cpp    Mon Nov 06 11:32:04 2017 +0530<br>
@@ -218,6 +218,7 @@<br>
     m_param->rc.vbvBufferSize = x265_clip3(0, 2000000, m_param->rc.vbvBufferSize);<br>
     m_param->rc.vbvMaxBitrate = x265_clip3(0, 2000000, m_param->rc.vbvMaxBitrate);<br>
     m_param->rc.vbvBufferInit = x265_clip3(0.0, 2000000.0, m_param->rc.vbvBufferInit);<br>
+    m_param->vbvBufferEnd = x265_clip3(0.0, 2000000.0, m_param->vbvBufferEnd);<br>
     m_singleFrameVbv = 0;<br>
     m_rateTolerance = 1.0;<br>
<br>
@@ -255,6 +256,11 @@<br>
         m_param->rc.vbvMaxBitrate = 0;<br>
     }<br>
     m_isVbv = m_param->rc.vbvMaxBitrate > 0 && m_param->rc.vbvBufferSize > 0;<br>
+    if (m_param->vbvBufferEnd && !m_isVbv)<br>
+    {<br>
+        x265_log(m_param, X265_LOG_WARNING, "vbv-end requires VBV parameters, ignored\n");<br>
+        m_param->vbvBufferEnd = 0;<br>
+    }<br>
     if (m_param->bEmitHRDSEI && !m_isVbv)<br>
     {<br>
         x265_log(m_param, X265_LOG_WARNING, "NAL HRD parameters require VBV parameters, ignored\n");<br>
@@ -339,6 +345,10 @@<br>
<br>
         if (m_param->rc.vbvBufferInit > 1.)<br>
             m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0, m_param->rc.vbvBufferInit / m_param->rc.vbvBufferSize);<br>
+        if (m_param->vbvBufferEnd > 1.)<br>
+            m_param->vbvBufferEnd = x265_clip3(0.0, 1.0, m_param->vbvBufferEnd / m_param->rc.vbvBufferSize);<br>
+        if (m_param->vbvEndFrameAdjust > 1.)<br>
+            m_param->vbvEndFrameAdjust = x265_clip3(0.0, 1.0, m_param->vbvEndFrameAdjust);<br>
         m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0, X265_MAX(m_param->rc.<wbr>vbvBufferInit, m_bufferRate / m_bufferSize));<br>
         m_bufferFillFinal = m_bufferSize * m_param->rc.vbvBufferInit;<br>
         m_bufferFillActual = m_bufferFillFinal;<br>
@@ -2160,29 +2170,51 @@<br>
                     curBits = predictSize(&m_pred[predType], frameQ[type], (double)satd);<br>
                     bufferFillCur -= curBits;<br>
                 }<br>
-<br>
-                /* Try to get the buffer at least 50% filled, but don't set an impossible goal. */<br>
-                double finalDur = 1;<br>
-                if (m_param->rc.bStrictCbr)<br>
+                if (m_param->vbvBufferEnd && rce->encodeOrder >= m_param->vbvEndFrameAdjust * m_param->totalFrames)<br>
                 {<br>
-                    finalDur = x265_clip3(0.4, 1.0, totalDuration);<br>
+                    bool loopBreak = false;<br>
+                    double bufferDiff = m_param->vbvBufferEnd - (m_bufferFill / m_bufferSize);<br>
+                    targetFill = m_bufferFill + m_bufferSize * (bufferDiff / (m_param->totalFrames - rce->encodeOrder));<br>
+                    if (bufferFillCur < targetFill)<br>
+                    {<br>
+                        q *= 1.01;<br>
+                        loopTerminate |= 1;<br>
+                        loopBreak = true;<br>
+                    }<br>
+                    if (bufferFillCur > m_param->vbvBufferEnd * m_bufferSize)<br>
+                    {<br>
+                        q /= 1.01;<br>
+                        loopTerminate |= 2;<br>
+                        loopBreak = true;<br>
+                    }<br>
+                    if (!loopBreak)<br>
+                        break;<br>
                 }<br>
-                targetFill = X265_MIN(m_bufferFill + totalDuration * m_vbvMaxRate * 0.5 , m_bufferSize * (1 - 0.5 * finalDur));<br>
-                if (bufferFillCur < targetFill)<br>
+                else<br>
                 {<br>
-                    q *= 1.01;<br>
-                    loopTerminate |= 1;<br>
-                    continue;<br>
+                    /* Try to get the buffer at least 50% filled, but don't set an impossible goal. */<br>
+                    double finalDur = 1;<br>
+                    if (m_param->rc.bStrictCbr)<br>
+                    {<br>
+                        finalDur = x265_clip3(0.4, 1.0, totalDuration);<br>
+                    }<br>
+                    targetFill = X265_MIN(m_bufferFill + totalDuration * m_vbvMaxRate * 0.5, m_bufferSize * (1 - 0.5 * finalDur));<br>
+                    if (bufferFillCur < targetFill)<br>
+                    {<br>
+                        q *= 1.01;<br>
+                        loopTerminate |= 1;<br>
+                        continue;<br>
+                    }<br>
+                    /* Try to get the buffer not more than 80% filled, but don't set an impossible goal. */<br>
+                    targetFill = x265_clip3(m_bufferSize * (1 - 0.2 * finalDur), m_bufferSize, m_bufferFill - totalDuration * m_vbvMaxRate * 0.5);<br>
+                    if (m_isCbr && bufferFillCur > targetFill && !m_isSceneTransition)<br>
+                    {<br>
+                        q /= 1.01;<br>
+                        loopTerminate |= 2;<br>
+                        continue;<br>
+                    }<br>
+                    break;<br>
                 }<br>
-                /* Try to get the buffer not more than 80% filled, but don't set an impossible goal. */<br>
-                targetFill = x265_clip3(m_bufferSize * (1 - 0.2 * finalDur), m_bufferSize, m_bufferFill - totalDuration * m_vbvMaxRate * 0.5);<br>
-                if (m_isCbr && bufferFillCur > targetFill && !m_isSceneTransition)<br>
-                {<br>
-                    q /= 1.01;<br>
-                    loopTerminate |= 2;<br>
-                    continue;<br>
-                }<br>
-                break;<br>
             }<br>
             q = X265_MAX(q0 / 2, q);<br>
         }<br>
diff -r aa9649a2aa8c -r 8a121d8cc134 source/test/rate-control-<wbr>tests.txt<br>
--- a/source/test/rate-control-<wbr>tests.txt        Mon Nov 06 09:43:36 2017 +0530<br>
+++ b/source/test/rate-control-<wbr>tests.txt        Mon Nov 06 11:32:04 2017 +0530<br>
@@ -25,7 +25,7 @@<br>
 big_buck_bunny_360p24.y4m,--<wbr>preset medium --bitrate 400 --vbv-bufsize 600 --vbv-maxrate 600 --no-wpp --aud --hrd --tune fast-decode<br>
 sita_1920x1080_30.yuv,--preset superfast --bitrate 3000 --vbv-bufsize 3000 --vbv-maxrate 3000 --aud --strict-cbr --no-wpp<br>
 sintel_trailer_2k_480p24.y4m, --preset slow --crf 24 --vbv-bufsize 150 --vbv-maxrate 150 --dynamic-rd 1.53<br>
-<br>
+BasketballDrive_1920x1080_50.<wbr>y4m,--preset medium --bitrate 10000 --vbv-bufsize 15000 --vbv-maxrate 11500 --vbv-end 0.9 --vbv-end-fr-adj 0.7<br>
<br>
<br>
 # multi-pass rate control tests<br>
diff -r aa9649a2aa8c -r 8a121d8cc134 source/x265.h<br>
--- a/source/x265.h     Mon Nov 06 09:43:36 2017 +0530<br>
+++ b/source/x265.h     Mon Nov 06 11:32:04 2017 +0530<br>
@@ -1514,6 +1514,16 @@<br>
     *  This DCT approximation is less computational intensive and gives results close to<br>
     *  standard DCT for QP >= 23 */<br>
     int       bLowPassDct;<br>
+<br>
+    /* Sets the portion of the decode buffer that must be available after all the<br>
+    * specified frames have been inserted into the decode buffer. If it is less<br>
+    * than 1, then the final buffer available is vbv-end * vbvBufferSize.  Otherwise,<br>
+    * it is interpreted as the final buffer available in kbits. Default 0 (disabled) */<br>
+    double    vbvBufferEnd;<br>
+<br>
+    /* Frame from which qp has to be adjusted to hit final decode buffer emptiness.<br>
+    * Specified as a fraction of the total frames. Default 0 */<br>
+    double    vbvEndFrameAdjust;<br>
 } x265_param;<br>
<br>
 /* x265_param_alloc:<br>
diff -r aa9649a2aa8c -r 8a121d8cc134 source/x265cli.h<br>
--- a/source/x265cli.h  Mon Nov 06 09:43:36 2017 +0530<br>
+++ b/source/x265cli.h  Mon Nov 06 11:32:04 2017 +0530<br>
@@ -147,6 +147,8 @@<br>
     { "vbv-maxrate",    required_argument, NULL, 0 },<br>
     { "vbv-bufsize",    required_argument, NULL, 0 },<br>
     { "vbv-init",       required_argument, NULL, 0 },<br>
+    { "vbv-end",        required_argument, NULL, 0 },<br>
+    { "vbv-end-fr-adj", required_argument, NULL, 0 },<br>
     { "bitrate",        required_argument, NULL, 0 },<br>
     { "qp",             required_argument, NULL, 'q' },<br>
     { "aq-mode",        required_argument, NULL, 0 },<br>
@@ -443,6 +445,8 @@<br>
     H0("   --vbv-maxrate <integer>       Max local bitrate (kbit/s). Default %d\n", param->rc.vbvMaxBitrate);<br>
     H0("   --vbv-bufsize <integer>       Set size of the VBV buffer (kbit). Default %d\n", param->rc.vbvBufferSize);<br>
     H0("   --vbv-init <float>            Initial VBV buffer occupancy (fraction of bufsize or in kbits). Default %.2f\n", param->rc.vbvBufferInit);<br>
+    H0("   --vbv-end <float>             Final VBV buffer emptiness (fraction of bufsize or in kbits). Default 0 (disabled)");<br>
+    H0("   --vbv-end-fr-adj <float>      Frame from which qp has to be adjusted to achieve final decode buffer emptiness. Default 0");<br>
     H0("   --pass                        Multi pass rate control.\n"<br>
        "                                   - 1 : First pass, creates stats file\n"<br>
        "                                   - 2 : Last pass, does not overwrite stats file\n"<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>