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

Aruna Matheswaran aruna at multicorewareinc.com
Mon Jun 29 16:42:55 CEST 2020


Pushed to master

On Mon, Jun 29, 2020 at 6:44 PM Pooja Venkatesan <pooja at multicorewareinc.com>
wrote:

> 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
>>
>>

-- 
Regards,
*Aruna Matheswaran,*
Video Codec Engineer,
Media & AI analytics BU,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20200629/3bb81089/attachment-0001.html>


More information about the x265-devel mailing list