[x265] [PATCH] Add support for RADL pictures
aruna at multicorewareinc.com
aruna at multicorewareinc.com
Fri Dec 22 10:50:19 CET 2017
# HG changeset patch
# User Aruna Matheswaran <aruna at multicorewareinc.com>
# Date 1513934408 -19800
# Fri Dec 22 14:50:08 2017 +0530
# Node ID ecba08b10f3aad17e68e3bd0ea3718c8653b568b
# Parent 95fc0c4f03dbf4e81a9ff12e8c6816136a376b10
Add support for RADL pictures
diff -r 95fc0c4f03db -r ecba08b10f3a doc/reST/cli.rst
--- a/doc/reST/cli.rst Fri Dec 22 15:14:57 2017 +0530
+++ b/doc/reST/cli.rst Fri Dec 22 14:50:08 2017 +0530
@@ -1345,7 +1345,14 @@
This value represents the percentage difference between the inter cost and
intra cost of a frame used in scenecut detection. For example, a value of 5 indicates,
if the inter cost of a frame is greater than or equal to 95 percent of the intra cost of the frame,
- then detect this frame as scenecut. Values between 5 and 15 are recommended. Default 5.
+ then detect this frame as scenecut. Values between 5 and 15 are recommended. Default 5.
+
+.. option:: --radl <integer>
+
+ Number of RADL pictures allowed infront of IDR. Requires fixed keyframe interval.
+ Recommended value is 2-3. Default 0 (disabled).
+
+ **Range of values: Between 0 and `--bframes`
.. option:: --ctu-info <0, 1, 2, 4, 6>
diff -r 95fc0c4f03db -r ecba08b10f3a source/CMakeLists.txt
--- a/source/CMakeLists.txt Fri Dec 22 15:14:57 2017 +0530
+++ b/source/CMakeLists.txt Fri Dec 22 14:50:08 2017 +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 149)
+set(X265_BUILD 150)
configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
"${PROJECT_BINARY_DIR}/x265.def")
configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff -r 95fc0c4f03db -r ecba08b10f3a source/common/lowres.cpp
--- a/source/common/lowres.cpp Fri Dec 22 15:14:57 2017 +0530
+++ b/source/common/lowres.cpp Fri Dec 22 14:50:08 2017 +0530
@@ -89,7 +89,7 @@
}
}
- for (int i = 0; i < bframes + 1; i++)
+ for (int i = 0; i < bframes + 2; i++)
{
CHECKED_MALLOC(lowresMvs[0][i], MV, cuCount);
CHECKED_MALLOC(lowresMvs[1][i], MV, cuCount);
@@ -118,7 +118,7 @@
}
}
- for (int i = 0; i < bframes + 1; i++)
+ for (int i = 0; i < bframes + 2; i++)
{
X265_FREE(lowresMvs[0][i]);
X265_FREE(lowresMvs[1][i]);
@@ -152,7 +152,7 @@
for (int x = 0; x < bframes + 2; x++)
rowSatds[y][x][0] = -1;
- for (int i = 0; i < bframes + 1; i++)
+ for (int i = 0; i < bframes + 2; i++)
{
lowresMvs[0][i][0].x = 0x7FFF;
lowresMvs[1][i][0].x = 0x7FFF;
diff -r 95fc0c4f03db -r ecba08b10f3a source/common/lowres.h
--- a/source/common/lowres.h Fri Dec 22 15:14:57 2017 +0530
+++ b/source/common/lowres.h Fri Dec 22 14:50:08 2017 +0530
@@ -130,8 +130,8 @@
int64_t satdCost;
uint16_t* lowresCostForRc;
uint16_t* lowresCosts[X265_BFRAME_MAX + 2][X265_BFRAME_MAX + 2];
- int32_t* lowresMvCosts[2][X265_BFRAME_MAX + 1];
- MV* lowresMvs[2][X265_BFRAME_MAX + 1];
+ int32_t* lowresMvCosts[2][X265_BFRAME_MAX + 2];
+ MV* lowresMvs[2][X265_BFRAME_MAX + 2];
uint32_t maxBlocksInRow;
uint32_t maxBlocksInCol;
uint32_t maxBlocksInRowFullRes;
diff -r 95fc0c4f03db -r ecba08b10f3a source/common/param.cpp
--- a/source/common/param.cpp Fri Dec 22 15:14:57 2017 +0530
+++ b/source/common/param.cpp Fri Dec 22 14:50:08 2017 +0530
@@ -154,6 +154,7 @@
param->lookaheadSlices = 8;
param->lookaheadThreads = 0;
param->scenecutBias = 5.0;
+ param->radl = 0;
/* Intra Coding Tools */
param->bEnableConstrainedIntra = 0;
param->bEnableStrongIntraSmoothing = 1;
@@ -1010,6 +1011,7 @@
OPT("gop-lookahead") p->gopLookahead = atoi(value);
OPT("analysis-save") p->analysisSave = strdup(value);
OPT("analysis-load") p->analysisLoad = strdup(value);
+ OPT("radl") p->radl = atoi(value);
else
return X265_PARAM_BAD_NAME;
}
@@ -1316,6 +1318,8 @@
"scenecutThreshold must be greater than 0");
CHECK(param->scenecutBias < 0 || 100 < param->scenecutBias,
"scenecut-bias must be between 0 and 100");
+ CHECK(param->radl < 0 || param->radl > param->bframes,
+ "radl must be between 0 and bframes");
CHECK(param->rdPenalty < 0 || param->rdPenalty > 2,
"Valid penalty for 32x32 intra TU in non-I slices. 0:disabled 1:RD-penalty 2:maximum");
CHECK(param->keyframeMax < -1,
@@ -1575,6 +1579,7 @@
s += sprintf(s, " rc-lookahead=%d", p->lookaheadDepth);
s += sprintf(s, " lookahead-slices=%d", p->lookaheadSlices);
s += sprintf(s, " scenecut=%d", p->scenecutThreshold);
+ s += sprintf(s, " radl=%d", p->radl);
BOOL(p->bIntraRefresh, "intra-refresh");
s += sprintf(s, " ctu=%d", p->maxCUSize);
s += sprintf(s, " min-cu-size=%d", p->minCUSize);
diff -r 95fc0c4f03db -r ecba08b10f3a source/encoder/dpb.cpp
--- a/source/encoder/dpb.cpp Fri Dec 22 15:14:57 2017 +0530
+++ b/source/encoder/dpb.cpp Fri Dec 22 14:50:08 2017 +0530
@@ -181,7 +181,10 @@
// Mark pictures in m_piclist as unreferenced if they are not included in RPS
applyReferencePictureSet(&slice->m_rps, pocCurr);
- slice->m_numRefIdx[0] = X265_MIN(newFrame->m_param->maxNumReferences, slice->m_rps.numberOfNegativePictures); // Ensuring L0 contains just the -ve POC
+ if (slice->m_sliceType != I_SLICE)
+ slice->m_numRefIdx[0] = x265_clip3(1, newFrame->m_param->maxNumReferences, slice->m_rps.numberOfNegativePictures);
+ else
+ slice->m_numRefIdx[0] = X265_MIN(newFrame->m_param->maxNumReferences, slice->m_rps.numberOfNegativePictures); // Ensuring L0 contains just the -ve POC
slice->m_numRefIdx[1] = X265_MIN(newFrame->m_param->bBPyramid ? 2 : 1, slice->m_rps.numberOfPositivePictures);
slice->setRefPicList(m_picList);
@@ -230,11 +233,14 @@
{
if ((iterPic->m_poc != curPoc) && iterPic->m_encData->m_bHasReferences)
{
- rps->poc[poci] = iterPic->m_poc;
- rps->deltaPOC[poci] = rps->poc[poci] - curPoc;
- (rps->deltaPOC[poci] < 0) ? numNeg++ : numPos++;
- rps->bUsed[poci] = !isRAP;
- poci++;
+ if ((m_lastIDR >= curPoc) || (m_lastIDR <= iterPic->m_poc))
+ {
+ rps->poc[poci] = iterPic->m_poc;
+ rps->deltaPOC[poci] = rps->poc[poci] - curPoc;
+ (rps->deltaPOC[poci] < 0) ? numNeg++ : numPos++;
+ rps->bUsed[poci] = !isRAP;
+ poci++;
+ }
}
iterPic = iterPic->m_next;
}
diff -r 95fc0c4f03db -r ecba08b10f3a source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Fri Dec 22 15:14:57 2017 +0530
+++ b/source/encoder/encoder.cpp Fri Dec 22 14:50:08 2017 +0530
@@ -3046,6 +3046,12 @@
p->maxCUDepth = p->maxLog2CUSize - g_log2Size[p->minCUSize];
p->unitSizeDepth = p->maxLog2CUSize - LOG2_UNIT_SIZE;
p->num4x4Partitions = (1U << (p->unitSizeDepth << 1));
+
+ if (p->radl && (p->keyframeMax != p->keyframeMin))
+ {
+ p->radl = 0;
+ x265_log(p, X265_LOG_WARNING, "Radl requires fixed gop-length (keyint == min-keyint). Disabling radl.\n");
+ }
}
void Encoder::allocAnalysis(x265_analysis_data* analysis)
diff -r 95fc0c4f03db -r ecba08b10f3a source/encoder/search.cpp
--- a/source/encoder/search.cpp Fri Dec 22 15:14:57 2017 +0530
+++ b/source/encoder/search.cpp Fri Dec 22 14:50:08 2017 +0530
@@ -1947,7 +1947,7 @@
/* poc difference is out of range for lookahead */
return 0;
- MV* mvs = m_frame->m_lowres.lowresMvs[list][diffPoc - 1];
+ MV* mvs = m_frame->m_lowres.lowresMvs[list][diffPoc];
if (mvs[0].x == 0x7FFF)
/* this motion search was not estimated by lookahead */
return 0;
diff -r 95fc0c4f03db -r ecba08b10f3a source/encoder/slicetype.cpp
--- a/source/encoder/slicetype.cpp Fri Dec 22 15:14:57 2017 +0530
+++ b/source/encoder/slicetype.cpp Fri Dec 22 14:50:08 2017 +0530
@@ -879,7 +879,7 @@
Slice *slice = curFrame->m_encData->m_slice;
int p0 = 0, p1, b;
int poc = slice->m_poc;
- int l0poc = slice->m_refPOCList[0][0];
+ int l0poc = slice->m_rps.numberOfNegativePictures ? slice->m_refPOCList[0][0] : -1;
int l1poc = slice->m_refPOCList[1][0];
switch (slice->m_sliceType)
@@ -896,11 +896,22 @@
break;
case B_SLICE:
- b = poc - l0poc;
- p1 = b + l1poc - poc;
- frames[p0] = &slice->m_refFrameList[0][0]->m_lowres;
- frames[b] = &curFrame->m_lowres;
- frames[p1] = &slice->m_refFrameList[1][0]->m_lowres;
+ if (l0poc >= 0)
+ {
+ b = poc - l0poc;
+ p1 = b + l1poc - poc;
+ frames[p0] = &slice->m_refFrameList[0][0]->m_lowres;
+ frames[b] = &curFrame->m_lowres;
+ frames[p1] = &slice->m_refFrameList[1][0]->m_lowres;
+ }
+ else
+ {
+ p0 = b = 0;
+ p1 = b + l1poc - poc;
+ frames[p0] = frames[b] = &curFrame->m_lowres;
+ frames[p1] = &slice->m_refFrameList[1][0]->m_lowres;
+ }
+
break;
default:
@@ -1120,12 +1131,20 @@
/* Closed GOP */
m_lastKeyframe = frm.frameNum;
frm.bKeyframe = true;
- if (bframes > 0)
+ if (bframes > 0 && !m_param->radl)
{
list[bframes - 1]->m_lowres.sliceType = X265_TYPE_P;
bframes--;
}
}
+ if (m_param->radl && !m_param->bOpenGOP && list[bframes + 1])
+ {
+ if ((frm.frameNum - m_lastKeyframe) > (m_param->keyframeMax - m_param->radl - 1) && (frm.frameNum - m_lastKeyframe) < m_param->keyframeMax)
+ frm.sliceType = X265_TYPE_B;
+ if ((frm.frameNum - m_lastKeyframe) == (m_param->keyframeMax - m_param->radl - 1))
+ frm.sliceType = X265_TYPE_P;
+ }
+
if (bframes == m_param->bframes || !list[bframes + 1])
{
if (IS_X265_TYPE_B(frm.sliceType))
@@ -1175,8 +1194,13 @@
if (bframes)
{
p0 = 0; // last nonb
+ bool isp0available = frames[bframes + 1]->sliceType == X265_TYPE_IDR ? false : true;
+
for (b = 1; b <= bframes; b++)
{
+ if (!isp0available)
+ p0 = b;
+
if (frames[b]->sliceType == X265_TYPE_B)
for (p1 = b; frames[p1]->sliceType == X265_TYPE_B; p1++)
; // find new nonb or bref
@@ -1186,7 +1210,10 @@
estGroup.singleCost(p0, p1, b);
if (frames[b]->sliceType == X265_TYPE_BREF)
+ {
p0 = b;
+ isp0available = true;
+ }
}
}
}
@@ -1413,12 +1440,12 @@
continue;
/* Skip search if already done */
- if (frames[b]->lowresMvs[0][i - 1][0].x != 0x7FFF)
+ if (frames[b]->lowresMvs[0][i][0].x != 0x7FFF)
continue;
/* perform search to p1 at same distance, if possible */
int p1 = b + i;
- if (p1 >= numFrames || frames[b]->lowresMvs[1][i - 1][0].x != 0x7FFF)
+ if (p1 >= numFrames || frames[b]->lowresMvs[1][i][0].x != 0x7FFF)
p1 = b;
estGroup.add(p0, p1, b);
@@ -1440,7 +1467,7 @@
/* only measure frame cost in this pass if motion searches
* are already done */
- if (frames[b]->lowresMvs[0][i - 1][0].x == 0x7FFF)
+ if (frames[b]->lowresMvs[0][i][0].x == 0x7FFF)
continue;
int p0 = b - i;
@@ -1452,7 +1479,7 @@
break;
/* ensure P1 search is done */
- if (j && frames[b]->lowresMvs[1][j - 1][0].x == 0x7FFF)
+ if (j && frames[b]->lowresMvs[1][j][0].x == 0x7FFF)
continue;
/* ensure frame cost is not done */
@@ -1867,7 +1894,7 @@
void Lookahead::calcMotionAdaptiveQuantFrame(Lowres **frames, int p0, int p1, int b)
{
- int listDist[2] = { b - p0 - 1, p1 - b - 1 };
+ int listDist[2] = { b - p0, p1 - b };
int32_t strideInCU = m_8x8Width;
double qp_adj = 0, avg_adj = 0, avg_adj_pow2 = 0, sd;
for (uint16_t blocky = 0; blocky < m_8x8Height; blocky++)
@@ -2030,7 +2057,7 @@
int32_t distScaleFactor = (((b - p0) << 8) + ((p1 - p0) >> 1)) / (p1 - p0);
int32_t bipredWeight = m_param->bEnableWeightedBiPred ? 64 - (distScaleFactor >> 2) : 32;
int32_t bipredWeights[2] = { bipredWeight, 64 - bipredWeight };
- int listDist[2] = { b - p0 - 1, p1 - b - 1 };
+ int listDist[2] = { b - p0, p1 - b };
memset(m_scratch, 0, m_8x8Width * sizeof(int));
@@ -2305,17 +2332,15 @@
score = fenc->costEst[b - p0][p1 - b];
else
{
- X265_CHECK(p0 != b, "I frame estimates should always be pre-calculated\n");
-
bool bDoSearch[2];
- bDoSearch[0] = p0 < b && fenc->lowresMvs[0][b - p0 - 1][0].x == 0x7FFF;
- bDoSearch[1] = p1 > b && fenc->lowresMvs[1][p1 - b - 1][0].x == 0x7FFF;
+ bDoSearch[0] = fenc->lowresMvs[0][b - p0][0].x == 0x7FFF;
+ bDoSearch[1] = p1 > b && fenc->lowresMvs[1][p1 - b][0].x == 0x7FFF;
#if CHECKED_BUILD
- X265_CHECK(!(p0 < b && fenc->lowresMvs[0][b - p0 - 1][0].x == 0x7FFE), "motion search batch duplication L0\n");
- X265_CHECK(!(p1 > b && fenc->lowresMvs[1][p1 - b - 1][0].x == 0x7FFE), "motion search batch duplication L1\n");
- if (bDoSearch[0]) fenc->lowresMvs[0][b - p0 - 1][0].x = 0x7FFE;
- if (bDoSearch[1]) fenc->lowresMvs[1][p1 - b - 1][0].x = 0x7FFE;
+ X265_CHECK(!(p0 < b && fenc->lowresMvs[0][b - p0][0].x == 0x7FFE), "motion search batch duplication L0\n");
+ X265_CHECK(!(p1 > b && fenc->lowresMvs[1][p1 - b][0].x == 0x7FFE), "motion search batch duplication L1\n");
+ if (bDoSearch[0]) fenc->lowresMvs[0][b - p0][0].x = 0x7FFE;
+ if (bDoSearch[1]) fenc->lowresMvs[1][p1 - b][0].x = 0x7FFE;
#endif
fenc->weightedRef[b - p0].isWeighted = false;
@@ -2406,7 +2431,7 @@
/* A small, arbitrary bias to avoid VBV problems caused by zero-residual lookahead blocks. */
int lowresPenalty = 4;
- int listDist[2] = { b - p0 - 1, p1 - b - 1 };
+ int listDist[2] = { b - p0, p1 - b};
MV mvmin, mvmax;
int bcost = tld.me.COST_MAX;
diff -r 95fc0c4f03db -r ecba08b10f3a source/encoder/weightPrediction.cpp
--- a/source/encoder/weightPrediction.cpp Fri Dec 22 15:14:57 2017 +0530
+++ b/source/encoder/weightPrediction.cpp Fri Dec 22 14:50:08 2017 +0530
@@ -323,7 +323,7 @@
if (!plane && diffPoc <= param.bframes + 1)
{
- mvs = fenc.lowresMvs[list][diffPoc - 1];
+ mvs = fenc.lowresMvs[list][diffPoc];
/* test whether this motion search was performed by lookahead */
if (mvs[0].x != 0x7FFF)
diff -r 95fc0c4f03db -r ecba08b10f3a source/test/regression-tests.txt
--- a/source/test/regression-tests.txt Fri Dec 22 15:14:57 2017 +0530
+++ b/source/test/regression-tests.txt Fri Dec 22 14:50:08 2017 +0530
@@ -151,6 +151,7 @@
Kimono1_1920x1080_24_400.yuv,--preset veryslow --crf 4 --cu-lossless --slices 2 --limit-refs 3 --limit-modes
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
# Main12 intraCost overflow bug test
720p50_parkrun_ter.y4m,--preset medium
diff -r 95fc0c4f03db -r ecba08b10f3a source/x265.h
--- a/source/x265.h Fri Dec 22 15:14:57 2017 +0530
+++ b/source/x265.h Fri Dec 22 14:50:08 2017 +0530
@@ -1268,6 +1268,7 @@
/* internally enable if tune grain is set */
int bEnableConstVbv;
+
} rc;
/*== Video Usability Information ==*/
@@ -1542,6 +1543,8 @@
* to reduce the amount of work the encoder must perform. Default disabled. */
const char* analysisLoad;
+ /*Number of RADL pictures allowed in front of IDR*/
+ int radl;
} x265_param;
/* x265_param_alloc:
diff -r 95fc0c4f03db -r ecba08b10f3a source/x265cli.h
--- a/source/x265cli.h Fri Dec 22 15:14:57 2017 +0530
+++ b/source/x265cli.h Fri Dec 22 14:50:08 2017 +0530
@@ -124,6 +124,7 @@
{ "scenecut", required_argument, NULL, 0 },
{ "no-scenecut", no_argument, NULL, 0 },
{ "scenecut-bias", required_argument, NULL, 0 },
+ { "radl", required_argument, NULL, 0 },
{ "ctu-info", required_argument, NULL, 0 },
{ "intra-refresh", no_argument, NULL, 0 },
{ "rc-lookahead", required_argument, NULL, 0 },
@@ -427,6 +428,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(" --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);
H1(" --lookahead-slices <0..16> Number of slices to use per lookahead cost estimate. Default %d\n", param->lookaheadSlices);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: x265_clone.patch
Type: text/x-patch
Size: 18026 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20171222/31ac8bef/attachment-0001.bin>
More information about the x265-devel
mailing list