<div dir="ltr"># HG changeset patch<br># User Pooja Venkatesan <<a href="mailto:pooja@multicorewareinc.com" target="_blank">pooja@multicorewareinc.com</a>><br># Date 1555911695 -19800<br>#      Mon Apr 22 11:11:35 2019 +0530<br># Node ID eb2ecf2d2f7289398bd8c82658752ae75efdf985<br># Parent  39b35ea862834f05e7437e1670e55de595c8f875<br>api: Add option "--fades" to detect and handle fade-in regions <div><br></div><div>Pushed Patch to x265 default branch.</div><div><br></div><div>Thanks & Regards,<br></div><div>Dinesh</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, May 17, 2019 at 2:41 PM <<a href="mailto:pooja@multicorewareinc.com">pooja@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"># HG changeset patch<br>
# User Pooja Venkatesan <<a href="mailto:pooja@multicorewareinc.com" target="_blank">pooja@multicorewareinc.com</a>><br>
# Date 1555911695 -19800<br>
#      Mon Apr 22 11:11:35 2019 +0530<br>
# Node ID eb2ecf2d2f7289398bd8c82658752ae75efdf985<br>
# Parent  39b35ea862834f05e7437e1670e55de595c8f875<br>
api: Add option "--fades" to detect and handle fade-in regions<br>
<br>
It does the following:<br>
Force I-slice and<br>
Initialize RC history for the brightest frame after fade-in.<br>
<br>
diff -r 39b35ea86283 -r eb2ecf2d2f72 doc/reST/cli.rst<br>
--- a/doc/reST/cli.rst  Tue Mar 26 10:31:41 2019 +0530<br>
+++ b/doc/reST/cli.rst  Mon Apr 22 11:11:35 2019 +0530<br>
@@ -1520,6 +1520,10 @@<br>
            slicetype decision may change with this option.<br>
        2 - flush the slicetype decided frames only.   <br>
<br>
+.. option:: --fades, --no-fades<br>
+<br>
+       Detect and handle fade-in regions. Default disabled.<br>
+<br>
 Quality, rate control and rate distortion options<br>
 =================================================<br>
<br>
diff -r 39b35ea86283 -r eb2ecf2d2f72 source/CMakeLists.txt<br>
--- a/source/CMakeLists.txt     Tue Mar 26 10:31:41 2019 +0530<br>
+++ b/source/CMakeLists.txt     Mon Apr 22 11:11:35 2019 +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 173)<br>
+set(X265_BUILD 174)<br>
 configure_file("${PROJECT_SOURCE_DIR}/<a href="http://x265.def.in" rel="noreferrer" 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" rel="noreferrer" target="_blank">x265_config.h.in</a>"<br>
diff -r 39b35ea86283 -r eb2ecf2d2f72 source/common/lowres.cpp<br>
--- a/source/common/lowres.cpp  Tue Mar 26 10:31:41 2019 +0530<br>
+++ b/source/common/lowres.cpp  Mon Apr 22 11:11:35 2019 +0530<br>
@@ -82,7 +82,7 @@<br>
<br>
     if (origPic->m_param->bAQMotion)<br>
         CHECKED_MALLOC_ZERO(qpAqMotionOffset, double, cuCountFullRes);<br>
-    if (origPic->m_param->bDynamicRefine)<br>
+    if (origPic->m_param->bDynamicRefine || origPic->m_param->bEnableFades)<br>
         CHECKED_MALLOC_ZERO(blockVariance, uint32_t, cuCountFullRes);<br>
<br>
     if (!!param->rc.hevcAq)<br>
@@ -217,6 +217,7 @@<br>
 {<br>
     bLastMiniGopBFrame = false;<br>
     bKeyframe = false; // Not a keyframe unless identified by lookahead<br>
+    bIsFadeEnd = false;<br>
     frameNum = poc;<br>
     leadingBframes = 0;<br>
     indB = 0;<br>
diff -r 39b35ea86283 -r eb2ecf2d2f72 source/common/lowres.h<br>
--- a/source/common/lowres.h    Tue Mar 26 10:31:41 2019 +0530<br>
+++ b/source/common/lowres.h    Mon Apr 22 11:11:35 2019 +0530<br>
@@ -160,6 +160,7 @@<br>
     bool   bScenecut;        // Set to false if the frame cannot possibly be part of a real scenecut.<br>
     bool   bKeyframe;<br>
     bool   bLastMiniGopBFrame;<br>
+    bool   bIsFadeEnd;<br>
<br>
     double ipCostRatio;<br>
<br>
@@ -195,6 +196,7 @@<br>
     uint32_t* blockVariance;<br>
     uint64_t  wp_ssd[3];       // This is different than SSDY, this is sum(pixel^2) - sum(pixel)^2 for entire frame<br>
     uint64_t  wp_sum[3];<br>
+    double    frameVariance;<br>
<br>
     /* cutree intermediate data */<br>
     PicQPAdaptationLayer* pAQLayer;<br>
diff -r 39b35ea86283 -r eb2ecf2d2f72 source/common/param.cpp<br>
--- a/source/common/param.cpp   Tue Mar 26 10:31:41 2019 +0530<br>
+++ b/source/common/param.cpp   Mon Apr 22 11:11:35 2019 +0530<br>
@@ -172,6 +172,7 @@<br>
     param->chunkStart = 0;<br>
     param->chunkEnd = 0;<br>
     param->bEnableHRDConcatFlag = 0;<br>
+    param->bEnableFades = 0;<br>
<br>
     /* Intra Coding Tools */<br>
     param->bEnableConstrainedIntra = 0;<br>
@@ -1265,6 +1266,7 @@<br>
         OPT("svt-pred-struct") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name);<br>
         OPT("svt-fps-in-vps") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name);<br>
 #endif<br>
+        OPT("fades") p->bEnableFades = atobool(value);<br>
         else<br>
             return X265_PARAM_BAD_NAME;<br>
     }<br>
@@ -2367,6 +2369,7 @@<br>
     dst->bEnableHRDConcatFlag = src->bEnableHRDConcatFlag;<br>
     dst->dolbyProfile = src->dolbyProfile;<br>
     dst->bEnableSvtHevc = src->bEnableSvtHevc;<br>
+    dst->bEnableFades = src->bEnableFades;<br>
<br>
 #ifdef SVT_HEVC<br>
     memcpy(dst->svtHevcParam, src->svtHevcParam, sizeof(EB_H265_ENC_CONFIGURATION));<br>
diff -r 39b35ea86283 -r eb2ecf2d2f72 source/encoder/ratecontrol.cpp<br>
--- a/source/encoder/ratecontrol.cpp    Tue Mar 26 10:31:41 2019 +0530<br>
+++ b/source/encoder/ratecontrol.cpp    Mon Apr 22 11:11:35 2019 +0530<br>
@@ -1262,6 +1262,7 @@<br>
     }<br>
     rce->isActive = true;<br>
     rce->scenecut = false;<br>
+    rce->isFadeEnd = curFrame->m_lowres.bIsFadeEnd;<br>
     bool isRefFrameScenecut = m_sliceType!= I_SLICE && m_curSlice->m_refFrameList[0][0]->m_lowres.bScenecut;<br>
     m_isFirstMiniGop = m_sliceType == I_SLICE ? true : m_isFirstMiniGop;<br>
     if (curFrame->m_lowres.bScenecut)<br>
@@ -1373,6 +1374,8 @@<br>
                         m_numBframesInPattern++;<br>
                 }<br>
             }<br>
+            if (rce->isFadeEnd)<br>
+                m_isPatternPresent = true;<br>
         }<br>
         /* For a scenecut that occurs within the mini-gop, enable scene transition<br>
          * switch until the next mini-gop to ensure a min qp for all the frames within <br>
@@ -2097,7 +2100,7 @@<br>
     double abrBuffer = 2 * m_rateTolerance * m_bitrate;<br>
<br>
     // Check if current Slice is a scene cut that follows low detailed/blank frames<br>
-    if (rce->lastSatd > 4 * rce->movingAvgSum || rce->scenecut)<br>
+    if (rce->lastSatd > 4 * rce->movingAvgSum || rce->scenecut || rce->isFadeEnd)<br>
     {<br>
         if (!m_isAbrReset && rce->movingAvgSum > 0<br>
             && (m_isPatternPresent || !m_param->bframes))<br>
@@ -2110,7 +2113,7 @@<br>
                 shrtTermTotalBitsSum += m_encodedBitsWindow[i];<br>
             double underflow = (shrtTermTotalBitsSum - shrtTermWantedBits) / abrBuffer;<br>
             const double epsilon = 0.0001f;<br>
-            if (underflow < epsilon && !isFrameDone)<br>
+            if ((underflow < epsilon || rce->isFadeEnd) && !isFrameDone)<br>
             {<br>
                 init(*m_curSlice->m_sps);<br>
                 m_shortTermCplxSum = rce->lastSatd / (CLIP_DURATION(m_frameDuration) / BASE_FRAME_DURATION);<br>
diff -r 39b35ea86283 -r eb2ecf2d2f72 source/encoder/ratecontrol.h<br>
--- a/source/encoder/ratecontrol.h      Tue Mar 26 10:31:41 2019 +0530<br>
+++ b/source/encoder/ratecontrol.h      Mon Apr 22 11:11:35 2019 +0530<br>
@@ -115,6 +115,7 @@<br>
     HRDTiming        *hrdTiming;<br>
     int      rpsIdx;<br>
     RPS      rpsData;<br>
+    bool     isFadeEnd;<br>
 };<br>
<br>
 class RateControl<br>
diff -r 39b35ea86283 -r eb2ecf2d2f72 source/encoder/slicetype.cpp<br>
--- a/source/encoder/slicetype.cpp      Tue Mar 26 10:31:41 2019 +0530<br>
+++ b/source/encoder/slicetype.cpp      Mon Apr 22 11:11:35 2019 +0530<br>
@@ -459,17 +459,21 @@<br>
         }<br>
     }<br>
<br>
-    if (param->bDynamicRefine)<br>
+    if (param->bDynamicRefine || param->bEnableFades)<br>
     {<br>
-        int blockXY = 0;<br>
+        uint64_t blockXY = 0, rowVariance = 0;<br>
+        curFrame->m_lowres.frameVariance = 0;<br>
         for (int blockY = 0; blockY < maxRow; blockY += loopIncr)<br>
         {<br>
             for (int blockX = 0; blockX < maxCol; blockX += loopIncr)<br>
             {<br>
                 curFrame->m_lowres.blockVariance[blockXY] = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);<br>
+                rowVariance += curFrame->m_lowres.blockVariance[blockXY];<br>
                 blockXY++;<br>
             }<br>
+            curFrame->m_lowres.frameVariance += (rowVariance / maxCol);<br>
         }<br>
+        curFrame->m_lowres.frameVariance /= maxRow;<br>
     }<br>
 }<br>
<br>
@@ -757,6 +761,9 @@<br>
     m_8x8Width = ((m_param->sourceWidth / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;<br>
     m_cuCount = m_8x8Width * m_8x8Height;<br>
     m_8x8Blocks = m_8x8Width > 2 && m_8x8Height > 2 ? (m_cuCount + 4 - 2 * (m_8x8Width + m_8x8Height)) : m_cuCount;<br>
+    m_isFadeIn = false;<br>
+    m_fadeCount = 0;<br>
+    m_fadeStart = -1;<br>
<br>
     /* Allow the strength to be adjusted via qcompress, since the two concepts<br>
      * are very similar. */<br>
@@ -1179,7 +1186,6 @@<br>
 void Lookahead::slicetypeDecide()<br>
 {<br>
     PreLookaheadGroup pre(*this);<br>
-<br>
     Lowres* frames[X265_LOOKAHEAD_MAX + X265_BFRAME_MAX + 4];<br>
     Frame*  list[X265_BFRAME_MAX + 4];<br>
     memset(frames, 0, sizeof(frames));<br>
@@ -1224,6 +1230,54 @@<br>
         pre.waitForExit();<br>
     }<br>
<br>
+    if(m_param->bEnableFades)<br>
+    {<br>
+        int j, endIndex = 0, length = X265_BFRAME_MAX + 4;<br>
+        for (j = 0; j < length; j++)<br>
+            m_frameVariance[j] = -1;<br>
+        for (j = 0; list[j] != NULL; j++)<br>
+            m_frameVariance[list[j]->m_poc % length] = list[j]->m_lowres.frameVariance;<br>
+        for (int k = list[0]->m_poc % length; k <= list[j - 1]->m_poc % length; k++)<br>
+        {<br>
+            if (m_frameVariance[k]  == -1)<br>
+                break;<br>
+            if((k > 0 && m_frameVariance[k] >= m_frameVariance[k - 1]) || <br>
+                (k == 0 && m_frameVariance[k] >= m_frameVariance[length - 1]))<br>
+            {<br>
+                m_isFadeIn = true;<br>
+                if (m_fadeCount == 0 && m_fadeStart == -1)<br>
+                {<br>
+                    for(int temp = list[0]->m_poc; temp <= list[j - 1]->m_poc; temp++)<br>
+                        if (k == temp % length) {<br>
+                            m_fadeStart = temp ? temp - 1 : 0;<br>
+                            break;<br>
+                        }<br>
+                }<br>
+                m_fadeCount = list[endIndex]->m_poc > m_fadeStart ? list[endIndex]->m_poc - m_fadeStart : 0;<br>
+                endIndex++;<br>
+            }<br>
+            else<br>
+            {<br>
+                if (m_isFadeIn && m_fadeCount >= m_param->fpsNum / m_param->fpsDenom)<br>
+                {<br>
+                    for (int temp = 0; list[temp] != NULL; temp++)<br>
+                    {<br>
+                        if (list[temp]->m_poc == m_fadeStart + (int)m_fadeCount)<br>
+                        {<br>
+                            list[temp]->m_lowres.bIsFadeEnd = true;<br>
+                            break;<br>
+                        }<br>
+                    }<br>
+                }<br>
+                m_isFadeIn = false;<br>
+                m_fadeCount = 0;<br>
+                m_fadeStart = -1;<br>
+            }<br>
+            if (k == length - 1)<br>
+                k = -1;<br>
+        }<br>
+    }<br>
+<br>
     if (m_lastNonB && !m_param->rc.bStatRead &&<br>
         ((m_param->bFrameAdaptive && m_param->bframes) ||<br>
          m_param->rc.cuTree || m_param->scenecutThreshold ||<br>
@@ -1283,6 +1337,9 @@<br>
                     frm.sliceType = m_param->bOpenGOP && m_lastKeyframe >= 0 ? X265_TYPE_I : X265_TYPE_IDR;<br>
                 }<br>
             }<br>
+            if (frm.bIsFadeEnd){<br>
+                frm.sliceType = m_param->bOpenGOP && m_lastKeyframe >= 0 ? X265_TYPE_I : X265_TYPE_IDR;<br>
+            }<br>
             for (int i = 0; i < m_param->rc.zonefileCount; i++)<br>
             {<br>
                 int curZoneStart = m_param->rc.zones[i].startFrame;<br>
diff -r 39b35ea86283 -r eb2ecf2d2f72 source/encoder/slicetype.h<br>
--- a/source/encoder/slicetype.h        Tue Mar 26 10:31:41 2019 +0530<br>
+++ b/source/encoder/slicetype.h        Mon Apr 22 11:11:35 2019 +0530<br>
@@ -134,6 +134,10 @@<br>
     bool          m_isSceneTransition;<br>
     int           m_numPools;<br>
     bool          m_extendGopBoundary;<br>
+    double        m_frameVariance[X265_BFRAME_MAX + 4];<br>
+    bool          m_isFadeIn;<br>
+    uint64_t      m_fadeCount;<br>
+    int           m_fadeStart;<br>
     Lookahead(x265_param *param, ThreadPool *pool);<br>
 #if DETAILED_CU_STATS<br>
     int64_t       m_slicetypeDecideElapsedTime;<br>
diff -r 39b35ea86283 -r eb2ecf2d2f72 source/test/regression-tests.txt<br>
--- a/source/test/regression-tests.txt  Tue Mar 26 10:31:41 2019 +0530<br>
+++ b/source/test/regression-tests.txt  Mon Apr 22 11:11:35 2019 +0530<br>
@@ -151,6 +151,7 @@<br>
 Kimono1_1920x1080_24_400.yuv,--preset placebo --ctu 32 --max-tu-size 8 --limit-tu 2<br>
 big_buck_bunny_360p24.y4m, --keyint 60 --min-keyint 40 --gop-lookahead 14<br>
 BasketballDrive_1920x1080_50.y4m, --preset medium --no-open-gop --keyint 50 --min-keyint 50 --radl 2 --vbv-maxrate 5000 --vbv-bufsize 5000<br>
+big_buck_bunny_360p24.y4m, --bitrate 500 --fades<br>
<br>
 # Main12 intraCost overflow bug test<br>
 720p50_parkrun_ter.y4m,--preset medium<br>
diff -r 39b35ea86283 -r eb2ecf2d2f72 source/x265.h<br>
--- a/source/x265.h     Tue Mar 26 10:31:41 2019 +0530<br>
+++ b/source/x265.h     Mon Apr 22 11:11:35 2019 +0530<br>
@@ -1771,6 +1771,10 @@<br>
<br>
     /* SVT-HEVC param structure. For internal use when SVT HEVC encoder is enabled */<br>
     void* svtHevcParam;<br>
+<br>
+    /* Detect fade-in regions. Enforces I-slice for the brightest point.<br>
+       Re-init RC history at that point in ABR mode. Default is disabled. */<br>
+    int       bEnableFades;<br>
 } x265_param;<br>
 /* x265_param_alloc:<br>
  *  Allocates an x265_param instance. The returned param structure is not<br>
diff -r 39b35ea86283 -r eb2ecf2d2f72 source/x265cli.h<br>
--- a/source/x265cli.h  Tue Mar 26 10:31:41 2019 +0530<br>
+++ b/source/x265cli.h  Mon Apr 22 11:11:35 2019 +0530<br>
@@ -124,6 +124,8 @@<br>
     { "scenecut",       required_argument, NULL, 0 },<br>
     { "no-scenecut",          no_argument, NULL, 0 },<br>
     { "scenecut-bias",  required_argument, NULL, 0 },<br>
+    { "fades",                no_argument, NULL, 0 },<br>
+    { "no-fades",             no_argument, NULL, 0 },<br>
     { "radl",           required_argument, NULL, 0 },<br>
     { "ctu-info",       required_argument, NULL, 0 },<br>
     { "intra-refresh",        no_argument, NULL, 0 },<br>
@@ -471,6 +473,7 @@<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>
+    H0("   --[no-]fades                  Enable detection and handling of fade-in regions. Default %s\n", OPT(param->bEnableFades));<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>
_______________________________________________<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>