<div dir="ltr">From 9d8c8657374b1154cab1a75ac6e23d04be58015c Mon Sep 17 00:00:00 2001<br>From: Pooja Venkatesan <<a href="mailto:pooja@multicorewareinc.com">pooja@multicorewareinc.com</a>><br>Date: Thu, 25 Jun 2020 20:48:22 +0530<br>Subject: [PATCH] Add support for RADL pictures at IDR scenecuts.<br><br>---<br> source/common/lowres.h    |  1 +<br> source/encoder/encoder.cpp  | 21 +++++++++++++--------<br> source/encoder/encoder.h   |  2 +-<br> source/encoder/slicetype.cpp | 13 ++++++++++++-<br> 4 files changed, 27 insertions(+), 10 deletions(-)<br><br>diff --git a/source/common/lowres.h b/source/common/lowres.h<br>index 200b1f032..a0ec05b25 100644<br>--- a/source/common/lowres.h<br>+++ b/source/common/lowres.h<br>@@ -238,6 +238,7 @@ struct Lowres : public ReferencePlanes<br>   bool  m_bIsMaxThres;<br>   double interPCostPercDiff;<br>   double intraCostPercDiff;<br>+   bool m_bIsHardScenecut;<br> <br>   bool create(x265_param* param, PicYuv *origPic, uint32_t qgSize);<br>   void destroy();<br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index bec7ff5c0..c9bcf2664 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -1528,11 +1528,11 @@ double Encoder::normalizeRange(int32_t value, int32_t minValue, int32_t maxValue<br>   return (double)(value - minValue) * (rangeEnd - rangeStart) / (maxValue - minValue) + rangeStart;<br> }<br> <br>-void Encoder::findSceneCuts(x265_picture *pic, bool& isMax, bool& bDup, double maxUVSad, double edgeSad)<br>+void Encoder::findSceneCuts(x265_picture *pic, bool& isMax, bool& isHardSC, bool& bDup, double maxUVSad, double edgeSad)<br> {<br>-   double minEdgeT = m_edgeHistThreshold * 0.5;<br>-   double minChromaT = minEdgeT * 10.0;<br>-   double maxEdgeT = m_edgeHistThreshold * 1.5;<br>+   double minEdgeT = m_edgeHistThreshold * 0.5;<br>+   double minChromaT = minEdgeT * 10.0;<br>+   double maxEdgeT = m_edgeHistThreshold * 1.5;<br>   double maxChromaT = maxEdgeT * 10.0;<br>   pic->frameData.bScenecut = false;<br> <br>@@ -1555,11 +1555,14 @@ void Encoder::findSceneCuts(x265_picture *pic, bool& isMax, bool& bDup, double m<br>     else if (edgeSad > maxEdgeT && maxUVSad > maxChromaT)<br>     {<br>       pic->frameData.bScenecut = true;<br>+       isHardSC = true;<br>       isMax = true;<br>     }<br>     else if (edgeSad > m_scaledEdgeThreshold || maxUVSad >= m_scaledChromaThreshold<br>         || (edgeSad > m_edgeHistThreshold && maxUVSad >= m_chromaHistThreshold))<br>     {<br>+       if (edgeSad > m_scaledEdgeThreshold || maxUVSad >= m_scaledChromaThreshold)<br>+         isHardSC = true;<br>       pic->frameData.bScenecut = true;<br>       bDup = false;<br>     }<br>@@ -1594,7 +1597,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)<br>   bool dontRead = false;<br>   bool bdropFrame = false;<br>   bool dropflag = false;<br>-   bool isMaxThreshold = false;<br>+   bool isMaxThreshold = false, isHardSC = false;<br> <br>   if (m_exportedPic)<br>   {<br>@@ -1621,7 +1624,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)<br>       {<br>         double maxUVSad = 0.0, edgeSad = 0.0;<br>         computeHistogramSAD(&maxUVSad, &edgeSad, pic_in->poc);<br>-         findSceneCuts(pic, isMaxThreshold, bdropFrame, maxUVSad, edgeSad);<br>+         findSceneCuts(pic, isMaxThreshold, isHardSC, bdropFrame, maxUVSad, edgeSad);<br>       }<br>     }<br> <br>@@ -1801,6 +1804,8 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)<br>     {<br>       inFrame->m_lowres.bScenecut = (inputPic->frameData.bScenecut == 1) ? true : false;<br>       inFrame->m_lowres.m_bIsMaxThres = isMaxThreshold;<br>+       if (m_param->radl && m_param->keyframeMax != m_param->keyframeMin)<br>+         inFrame->m_lowres.m_bIsHardScenecut = isHardSC;<br>     }<br>     if (m_param->bHistBasedSceneCut && m_param->analysisSave)<br>     {<br>@@ -4218,10 +4223,10 @@ void Encoder::configure(x265_param *p)<br>   p->unitSizeDepth = p->maxLog2CUSize - LOG2_UNIT_SIZE;<br>   p->num4x4Partitions = (1U << (p->unitSizeDepth << 1));<br> <br>-   if (p->radl && (p->keyframeMax != p->keyframeMin))<br>+   if (p->radl && p->bOpenGOP)<br>   {<br>     p->radl = 0;<br>-     x265_log(p, X265_LOG_WARNING, "Radl requires fixed gop-length (keyint == min-keyint). Disabling radl.\n");<br>+     x265_log(p, X265_LOG_WARNING, "Radl requires closed gop structure. Disabling radl.\n");<br>   }<br> <br>   if ((p->chunkStart || p->chunkEnd) && p->bOpenGOP && m_param->bResetZoneConfig)<br>diff --git a/source/encoder/encoder.h b/source/encoder/encoder.h<br>index 1d4fe2476..4fbd234c2 100644<br>--- a/source/encoder/encoder.h<br>+++ b/source/encoder/encoder.h<br>@@ -373,7 +373,7 @@ public:<br>   bool computeHistograms(x265_picture *pic);<br>   void computeHistogramSAD(double *maxUVNormalizedSAD, double *edgeNormalizedSAD, int curPoc);<br>   double normalizeRange(int32_t value, int32_t minValue, int32_t maxValue, double rangeStart, double rangeEnd);<br>-   void findSceneCuts(x265_picture *pic, bool& isMax, bool& bDup, double m_maxUVSADVal, double m_edgeSADVal);<br>+   void findSceneCuts(x265_picture *pic, bool& isMax, bool& isHardSC, bool& bDup, double m_maxUVSADVal, double m_edgeSADVal);<br> <br>   void initRefIdx();<br>   void analyseRefIdx(int *numRefIdx);<br>diff --git a/source/encoder/slicetype.cpp b/source/encoder/slicetype.cpp<br>index 27052ca4e..2006fd434 100644<br>--- a/source/encoder/slicetype.cpp<br>+++ b/source/encoder/slicetype.cpp<br>@@ -1520,6 +1520,7 @@ void Lookahead::slicetypeDecide()<br>   int bframes, brefs;<br>   if (!m_param->analysisLoad || m_param->bAnalysisType == HEVC_INFO)<br>   {<br>+     bool isClosedGopRadl = m_param->radl && m_param->keyframeMax != m_param->keyframeMin;<br>     for (bframes = 0, brefs = 0;; bframes++)<br>     {<br>       Lowres& frm = list[bframes]->m_lowres;<br>@@ -1579,6 +1580,16 @@ void Lookahead::slicetypeDecide()<br>         else<br>           frm.sliceType = X265_TYPE_IDR;<br>       }<br>+       if (frm.sliceType == X265_TYPE_IDR && frm.bScenecut && isClosedGopRadl)<br>+       {<br>+         if ((m_param->bHistBasedSceneCut && frm.m_bIsHardScenecut) ||<br>+           !m_param->bHistBasedSceneCut)<br>+         {<br>+           for (int i = bframes; i < bframes + m_param->radl; i++)<br>+             list[i]->m_lowres.sliceType = X265_TYPE_B;<br>+           list[(bframes + m_param->radl)]->m_lowres.sliceType = X265_TYPE_IDR;<br>+         }<br>+       }<br>       if (frm.sliceType == X265_TYPE_IDR)<br>       {<br>         /* Closed GOP */<br>@@ -2146,7 +2157,7 @@ void Lookahead::slicetypeAnalyse(Lowres **frames, bool bKeyframe)<br>     }<br> <br>     int zoneRadl = m_param->rc.zonefileCount && m_param->bResetZoneConfig ? m_param->rc.zones->zoneParam->radl : 0;<br>-     bool bForceRADL = (m_param->radl || zoneRadl) && !m_param->bOpenGOP;<br>+     bool bForceRADL = ((m_param->radl && m_param->keyframeMax == m_param->keyframeMin) || zoneRadl) && !m_param->bOpenGOP;<br>     bool bLastMiniGop = (framecnt >= m_param->bframes + 1) ? false : true;<br>     int radl = m_param->radl ? m_param->radl : zoneRadl;<br>     int preRADL = m_lastKeyframe + m_param->keyframeMax - radl - 1; /*Frame preceeding RADL in POC order*/<br>-- <br>2.24.0.windows.2<br><br></div>