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