[x265] [PATCH 2 of 2] Add support for RADL pictures at IDR scenecuts.
Pooja Venkatesan
pooja at multicorewareinc.com
Mon Jun 29 15:13:44 CEST 2020
>From 095b73ef10eaf0600f0078cbae433ecc0942cb46 Mon Sep 17 00:00:00 2001
From: Pooja Venkatesan <pooja at multicorewareinc.com>
Date: Mon, 29 Jun 2020 17:13:34 +0530
Subject: [PATCH] Add support for RADL pictures at IDR scenecuts
---
doc/reST/cli.rst | 5 ++++-
source/common/lowres.cpp | 1 +
source/common/lowres.h | 1 +
source/encoder/encoder.cpp | 14 ++++++++++----
source/encoder/encoder.h | 2 +-
source/encoder/slicetype.cpp | 12 +++++++++++-
6 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
index 23b74c3d8..3b8a6e2e6 100644
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -1475,7 +1475,10 @@ Slice decision options
.. option:: --radl <integer>
- Number of RADL pictures allowed infront of IDR. Requires fixed keyframe
interval.
+ Number of RADL pictures allowed infront of IDR. Requires closed gop
interval.
+ If enabled for fixed keyframe interval, inserts RADL at every IDR.
+ If enabled for closed gop interval, in case of :option:`--hist-scenecut`
inserts RADL at every hard scenecut
+ whereas for the :option:`--scenecut`, inserts RADL at every scenecut.
Recommended value is 2-3. Default 0 (disabled).
**Range of values: Between 0 and `--bframes`
diff --git a/source/common/lowres.cpp b/source/common/lowres.cpp
index db1c2d159..578981d64 100644
--- a/source/common/lowres.cpp
+++ b/source/common/lowres.cpp
@@ -269,6 +269,7 @@ void Lowres::init(PicYuv *origPic, int poc)
interPCostPercDiff = 0.0;
intraCostPercDiff = 0.0;
m_bIsMaxThres = false;
+ m_bIsHardScenecut = false;
if (qpAqOffset && invQscaleFactor)
memset(costEstAq, -1, sizeof(costEstAq));
diff --git a/source/common/lowres.h b/source/common/lowres.h
index 200b1f032..2a7497258 100644
--- a/source/common/lowres.h
+++ b/source/common/lowres.h
@@ -238,6 +238,7 @@ struct Lowres : public ReferencePlanes
bool m_bIsMaxThres;
double interPCostPercDiff;
double intraCostPercDiff;
+ bool m_bIsHardScenecut;
bool create(x265_param* param, PicYuv *origPic, uint32_t qgSize);
void destroy();
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 0c6fd80bf..6101eeacd 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -1528,7 +1528,7 @@ double Encoder::normalizeRange(int32_t value, int32_t
minValue, int32_t maxValue
return (double)(value - minValue) * (rangeEnd - rangeStart) /
(maxValue - minValue) + rangeStart;
}
-void Encoder::findSceneCuts(x265_picture *pic, bool& bDup, double
maxUVSad, double edgeSad, bool& isMaxThres)
+void Encoder::findSceneCuts(x265_picture *pic, bool& bDup, double
maxUVSad, double edgeSad, bool& isMaxThres, bool& isHardSC)
{
double minEdgeT = m_edgeHistThreshold * MIN_EDGE_FACTOR;
double minChromaT = minEdgeT * SCENECUT_CHROMA_FACTOR;
@@ -1556,12 +1556,15 @@ void Encoder::findSceneCuts(x265_picture *pic,
bool& bDup, double maxUVSad, doub
{
pic->frameData.bScenecut = true;
isMaxThres = true;
+ isHardSC = true;
}
else if (edgeSad > m_scaledEdgeThreshold || maxUVSad >=
m_scaledChromaThreshold
|| (edgeSad > m_edgeHistThreshold && maxUVSad >=
m_chromaHistThreshold))
{
pic->frameData.bScenecut = true;
bDup = false;
+ if (edgeSad > m_scaledEdgeThreshold || maxUVSad >=
m_scaledChromaThreshold)
+ isHardSC = true;
}
}
}
@@ -1595,6 +1598,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
bool bdropFrame = false;
bool dropflag = false;
bool isMaxThres = false;
+ bool isHardSC = false;
if (m_exportedPic)
{
@@ -1621,7 +1625,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
{
double maxUVSad = 0.0, edgeSad = 0.0;
computeHistogramSAD(&maxUVSad, &edgeSad, pic_in->poc);
- findSceneCuts(pic, bdropFrame, maxUVSad, edgeSad,
isMaxThres);
+ findSceneCuts(pic, bdropFrame, maxUVSad, edgeSad,
isMaxThres, isHardSC);
}
}
@@ -1801,6 +1805,8 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
{
inFrame->m_lowres.bScenecut = (inputPic->frameData.bScenecut
== 1) ? true : false;
inFrame->m_lowres.m_bIsMaxThres = isMaxThres;
+ if (m_param->radl && m_param->keyframeMax !=
m_param->keyframeMin)
+ inFrame->m_lowres.m_bIsHardScenecut = isHardSC;
}
if (m_param->bHistBasedSceneCut && m_param->analysisSave)
{
@@ -4218,10 +4224,10 @@ void Encoder::configure(x265_param *p)
p->unitSizeDepth = p->maxLog2CUSize - LOG2_UNIT_SIZE;
p->num4x4Partitions = (1U << (p->unitSizeDepth << 1));
- if (p->radl && (p->keyframeMax != p->keyframeMin))
+ if (p->radl && p->bOpenGOP)
{
p->radl = 0;
- x265_log(p, X265_LOG_WARNING, "Radl requires fixed gop-length
(keyint == min-keyint). Disabling radl.\n");
+ x265_log(p, X265_LOG_WARNING, "Radl requires closed gop structure.
Disabling radl.\n");
}
if ((p->chunkStart || p->chunkEnd) && p->bOpenGOP &&
m_param->bResetZoneConfig)
diff --git a/source/encoder/encoder.h b/source/encoder/encoder.h
index 507c42d5e..ecb6e153f 100644
--- a/source/encoder/encoder.h
+++ b/source/encoder/encoder.h
@@ -376,7 +376,7 @@ public:
bool computeHistograms(x265_picture *pic);
void computeHistogramSAD(double *maxUVNormalizedSAD, double
*edgeNormalizedSAD, int curPoc);
double normalizeRange(int32_t value, int32_t minValue, int32_t
maxValue, double rangeStart, double rangeEnd);
- void findSceneCuts(x265_picture *pic, bool& bDup, double
m_maxUVSADVal, double m_edgeSADVal, bool& isMaxThres);
+ void findSceneCuts(x265_picture *pic, bool& bDup, double
m_maxUVSADVal, double m_edgeSADVal, bool& isMaxThres, bool& isHardSC);
void initRefIdx();
void analyseRefIdx(int *numRefIdx);
diff --git a/source/encoder/slicetype.cpp b/source/encoder/slicetype.cpp
index d3783cfe1..5292473b1 100644
--- a/source/encoder/slicetype.cpp
+++ b/source/encoder/slicetype.cpp
@@ -1520,6 +1520,7 @@ void Lookahead::slicetypeDecide()
int bframes, brefs;
if (!m_param->analysisLoad || m_param->bAnalysisType == HEVC_INFO)
{
+ bool isClosedGopRadl = m_param->radl && (m_param->keyframeMax !=
m_param->keyframeMin);
for (bframes = 0, brefs = 0;; bframes++)
{
Lowres& frm = list[bframes]->m_lowres;
@@ -1579,6 +1580,15 @@ void Lookahead::slicetypeDecide()
else
frm.sliceType = X265_TYPE_IDR;
}
+ if (frm.sliceType == X265_TYPE_IDR && frm.bScenecut &&
isClosedGopRadl)
+ {
+ if (!m_param->bHistBasedSceneCut ||
(m_param->bHistBasedSceneCut && frm.m_bIsHardScenecut))
+ {
+ for (int i = bframes; i < bframes + m_param->radl; i++)
+ list[i]->m_lowres.sliceType = X265_TYPE_B;
+ list[(bframes + m_param->radl)]->m_lowres.sliceType =
X265_TYPE_IDR;
+ }
+ }
if (frm.sliceType == X265_TYPE_IDR)
{
/* Closed GOP */
@@ -2147,7 +2157,7 @@ void Lookahead::slicetypeAnalyse(Lowres **frames,
bool bKeyframe)
}
int zoneRadl = m_param->rc.zonefileCount &&
m_param->bResetZoneConfig ? m_param->rc.zones->zoneParam->radl : 0;
- bool bForceRADL = (m_param->radl || zoneRadl) &&
!m_param->bOpenGOP;
+ bool bForceRADL = zoneRadl || (m_param->radl &&
(m_param->keyframeMax == m_param->keyframeMin));
bool bLastMiniGop = (framecnt >= m_param->bframes + 1) ? false :
true;
int radl = m_param->radl ? m_param->radl : zoneRadl;
int preRADL = m_lastKeyframe + m_param->keyframeMax - radl - 1;
/*Frame preceeding RADL in POC order*/
--
2.24.0.windows.2
Regards,
*Pooja Venkatesan*,
Video Codec Engineer,
Media & AI analytics BU
On Thu, Jun 25, 2020 at 9:00 PM Pooja Venkatesan <pooja at multicorewareinc.com>
wrote:
> From 9d8c8657374b1154cab1a75ac6e23d04be58015c Mon Sep 17 00:00:00 2001
> From: Pooja Venkatesan <pooja at multicorewareinc.com>
> Date: Thu, 25 Jun 2020 20:48:22 +0530
> Subject: [PATCH] Add support for RADL pictures at IDR scenecuts.
>
> ---
> source/common/lowres.h | 1 +
> source/encoder/encoder.cpp | 21 +++++++++++++--------
> source/encoder/encoder.h | 2 +-
> source/encoder/slicetype.cpp | 13 ++++++++++++-
> 4 files changed, 27 insertions(+), 10 deletions(-)
>
> diff --git a/source/common/lowres.h b/source/common/lowres.h
> index 200b1f032..a0ec05b25 100644
> --- a/source/common/lowres.h
> +++ b/source/common/lowres.h
> @@ -238,6 +238,7 @@ struct Lowres : public ReferencePlanes
> bool m_bIsMaxThres;
> double interPCostPercDiff;
> double intraCostPercDiff;
> + bool m_bIsHardScenecut;
>
> bool create(x265_param* param, PicYuv *origPic, uint32_t qgSize);
> void destroy();
> diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
> index bec7ff5c0..c9bcf2664 100644
> --- a/source/encoder/encoder.cpp
> +++ b/source/encoder/encoder.cpp
> @@ -1528,11 +1528,11 @@ double Encoder::normalizeRange(int32_t value,
> int32_t minValue, int32_t maxValue
> return (double)(value - minValue) * (rangeEnd - rangeStart) /
> (maxValue - minValue) + rangeStart;
> }
>
> -void Encoder::findSceneCuts(x265_picture *pic, bool& isMax, bool& bDup,
> double maxUVSad, double edgeSad)
> +void Encoder::findSceneCuts(x265_picture *pic, bool& isMax, bool&
> isHardSC, bool& bDup, double maxUVSad, double edgeSad)
> {
> - double minEdgeT = m_edgeHistThreshold * 0.5;
> - double minChromaT = minEdgeT * 10.0;
> - double maxEdgeT = m_edgeHistThreshold * 1.5;
> + double minEdgeT = m_edgeHistThreshold * 0.5;
> + double minChromaT = minEdgeT * 10.0;
> + double maxEdgeT = m_edgeHistThreshold * 1.5;
> double maxChromaT = maxEdgeT * 10.0;
> pic->frameData.bScenecut = false;
>
> @@ -1555,11 +1555,14 @@ void Encoder::findSceneCuts(x265_picture *pic,
> bool& isMax, bool& bDup, double m
> else if (edgeSad > maxEdgeT && maxUVSad > maxChromaT)
> {
> pic->frameData.bScenecut = true;
> + isHardSC = true;
> isMax = true;
> }
> else if (edgeSad > m_scaledEdgeThreshold || maxUVSad >=
> m_scaledChromaThreshold
> || (edgeSad > m_edgeHistThreshold && maxUVSad >=
> m_chromaHistThreshold))
> {
> + if (edgeSad > m_scaledEdgeThreshold || maxUVSad >=
> m_scaledChromaThreshold)
> + isHardSC = true;
> pic->frameData.bScenecut = true;
> bDup = false;
> }
> @@ -1594,7 +1597,7 @@ int Encoder::encode(const x265_picture* pic_in,
> x265_picture* pic_out)
> bool dontRead = false;
> bool bdropFrame = false;
> bool dropflag = false;
> - bool isMaxThreshold = false;
> + bool isMaxThreshold = false, isHardSC = false;
>
> if (m_exportedPic)
> {
> @@ -1621,7 +1624,7 @@ int Encoder::encode(const x265_picture* pic_in,
> x265_picture* pic_out)
> {
> double maxUVSad = 0.0, edgeSad = 0.0;
> computeHistogramSAD(&maxUVSad, &edgeSad, pic_in->poc);
> - findSceneCuts(pic, isMaxThreshold, bdropFrame, maxUVSad,
> edgeSad);
> + findSceneCuts(pic, isMaxThreshold, isHardSC, bdropFrame,
> maxUVSad, edgeSad);
> }
> }
>
> @@ -1801,6 +1804,8 @@ int Encoder::encode(const x265_picture* pic_in,
> x265_picture* pic_out)
> {
> inFrame->m_lowres.bScenecut = (inputPic->frameData.bScenecut
> == 1) ? true : false;
> inFrame->m_lowres.m_bIsMaxThres = isMaxThreshold;
> + if (m_param->radl && m_param->keyframeMax !=
> m_param->keyframeMin)
> + inFrame->m_lowres.m_bIsHardScenecut = isHardSC;
> }
> if (m_param->bHistBasedSceneCut && m_param->analysisSave)
> {
> @@ -4218,10 +4223,10 @@ void Encoder::configure(x265_param *p)
> p->unitSizeDepth = p->maxLog2CUSize - LOG2_UNIT_SIZE;
> p->num4x4Partitions = (1U << (p->unitSizeDepth << 1));
>
> - if (p->radl && (p->keyframeMax != p->keyframeMin))
> + if (p->radl && p->bOpenGOP)
> {
> p->radl = 0;
> - x265_log(p, X265_LOG_WARNING, "Radl requires fixed gop-length
> (keyint == min-keyint). Disabling radl.\n");
> + x265_log(p, X265_LOG_WARNING, "Radl requires closed gop
> structure. Disabling radl.\n");
> }
>
> if ((p->chunkStart || p->chunkEnd) && p->bOpenGOP &&
> m_param->bResetZoneConfig)
> diff --git a/source/encoder/encoder.h b/source/encoder/encoder.h
> index 1d4fe2476..4fbd234c2 100644
> --- a/source/encoder/encoder.h
> +++ b/source/encoder/encoder.h
> @@ -373,7 +373,7 @@ public:
> bool computeHistograms(x265_picture *pic);
> void computeHistogramSAD(double *maxUVNormalizedSAD, double
> *edgeNormalizedSAD, int curPoc);
> double normalizeRange(int32_t value, int32_t minValue, int32_t
> maxValue, double rangeStart, double rangeEnd);
> - void findSceneCuts(x265_picture *pic, bool& isMax, bool& bDup, double
> m_maxUVSADVal, double m_edgeSADVal);
> + void findSceneCuts(x265_picture *pic, bool& isMax, bool& isHardSC,
> bool& bDup, double m_maxUVSADVal, double m_edgeSADVal);
>
> void initRefIdx();
> void analyseRefIdx(int *numRefIdx);
> diff --git a/source/encoder/slicetype.cpp b/source/encoder/slicetype.cpp
> index 27052ca4e..2006fd434 100644
> --- a/source/encoder/slicetype.cpp
> +++ b/source/encoder/slicetype.cpp
> @@ -1520,6 +1520,7 @@ void Lookahead::slicetypeDecide()
> int bframes, brefs;
> if (!m_param->analysisLoad || m_param->bAnalysisType == HEVC_INFO)
> {
> + bool isClosedGopRadl = m_param->radl && m_param->keyframeMax !=
> m_param->keyframeMin;
> for (bframes = 0, brefs = 0;; bframes++)
> {
> Lowres& frm = list[bframes]->m_lowres;
> @@ -1579,6 +1580,16 @@ void Lookahead::slicetypeDecide()
> else
> frm.sliceType = X265_TYPE_IDR;
> }
> + if (frm.sliceType == X265_TYPE_IDR && frm.bScenecut &&
> isClosedGopRadl)
> + {
> + if ((m_param->bHistBasedSceneCut &&
> frm.m_bIsHardScenecut) ||
> + !m_param->bHistBasedSceneCut)
> + {
> + for (int i = bframes; i < bframes + m_param->radl;
> i++)
> + list[i]->m_lowres.sliceType = X265_TYPE_B;
> + list[(bframes + m_param->radl)]->m_lowres.sliceType =
> X265_TYPE_IDR;
> + }
> + }
> if (frm.sliceType == X265_TYPE_IDR)
> {
> /* Closed GOP */
> @@ -2146,7 +2157,7 @@ void Lookahead::slicetypeAnalyse(Lowres **frames,
> bool bKeyframe)
> }
>
> int zoneRadl = m_param->rc.zonefileCount &&
> m_param->bResetZoneConfig ? m_param->rc.zones->zoneParam->radl : 0;
> - bool bForceRADL = (m_param->radl || zoneRadl) &&
> !m_param->bOpenGOP;
> + bool bForceRADL = ((m_param->radl && m_param->keyframeMax ==
> m_param->keyframeMin) || zoneRadl) && !m_param->bOpenGOP;
> bool bLastMiniGop = (framecnt >= m_param->bframes + 1) ? false :
> true;
> int radl = m_param->radl ? m_param->radl : zoneRadl;
> int preRADL = m_lastKeyframe + m_param->keyframeMax - radl - 1;
> /*Frame preceeding RADL in POC order*/
> --
> 2.24.0.windows.2
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20200629/185f33ca/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SCD2-final.diff
Type: application/octet-stream
Size: 8028 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20200629/185f33ca/attachment-0001.obj>
More information about the x265-devel
mailing list