<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>