[x265] [PATCH 2 of 2] Add support for RADL pictures at IDR scenecuts.

Pooja Venkatesan pooja at multicorewareinc.com
Thu Jun 25 17:30:26 CEST 2020


>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/20200625/b4bfa09a/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SCD2.diff
Type: application/octet-stream
Size: 7177 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20200625/b4bfa09a/attachment-0001.obj>


More information about the x265-devel mailing list