[x265] [PATCH 1 of 2] slicetype: Modify Scenecut algorithm to detect scene transition points

Deepthi Nandakumar deepthi at multicorewareinc.com
Thu Jul 30 08:51:08 CEST 2015


On Tue, Jul 28, 2015 at 1:07 PM, <aarthi at multicorewareinc.com> wrote:

> # HG changeset patch
> # User Aarthi Thirumalai
> # Date 1437505166 -19800
> #      Wed Jul 22 00:29:26 2015 +0530
> # Node ID 2a901547b3b8ebed95a4580ff4bcbc2582e55437
> # Parent  46152345eb6ff261fd90272f7a0712300d6324c0
> slicetype: Modify Scenecut algorithm to detect scene transition points
> to improve Rate Control.
>
> identify scene trasitions, fade-ins, fadeouts, sceneCuts and signal the
> flag bSceneChange
> in Lowres structure. This flag will be used by RateControl to adjust the
> wps during scene cuts.
> No changes in sliceType decisions or I frame placement.
>
> diff -r 46152345eb6f -r 2a901547b3b8 source/common/lowres.cpp
> --- a/source/common/lowres.cpp  Mon Jul 20 17:18:54 2015 -0700
> +++ b/source/common/lowres.cpp  Wed Jul 22 00:29:26 2015 +0530
> @@ -127,6 +127,7 @@
>  {
>      bLastMiniGopBFrame = false;
>      bScenecut = true;  // could be a scene-cut, until ruled out by flash
> detection
> +    bSceneChange = true;
>      bKeyframe = false; // Not a keyframe unless identified by lookahead
>      frameNum = poc;
>      leadingBframes = 0;
> diff -r 46152345eb6f -r 2a901547b3b8 source/common/lowres.h
> --- a/source/common/lowres.h    Mon Jul 20 17:18:54 2015 -0700
> +++ b/source/common/lowres.h    Wed Jul 22 00:29:26 2015 +0530
> @@ -115,6 +115,7 @@
>      int    leadingBframes;   // number of leading B frames for P or I
>
>      bool   bScenecut;        // Set to false if the frame cannot possibly
> be part of a real scenecut.
> +    bool   bSceneChange;
>      bool   bKeyframe;
>      bool   bLastMiniGopBFrame;
>
> diff -r 46152345eb6f -r 2a901547b3b8 source/encoder/slicetype.cpp
> --- a/source/encoder/slicetype.cpp      Mon Jul 20 17:18:54 2015 -0700
> +++ b/source/encoder/slicetype.cpp      Wed Jul 22 00:29:26 2015 +0530
> @@ -462,6 +462,7 @@
>      m_pool  = pool;
>
>      m_lastNonB = NULL;
> +    m_isSceneTransition = false;
>      m_scratch  = NULL;
>      m_tld      = NULL;
>      m_filled   = false;
> @@ -881,6 +882,8 @@
>
>          if (/* (!param->intraRefresh || frm.frameNum == 0) && */
> frm.frameNum - m_lastKeyframe >= m_param->keyframeMax)
>          {
> +            if (frm.sliceType != X265_TYPE_I)
> +                frm.bSceneChange = false;
>

We're still conflating scene changes and scene transitions with slicetype
decisions.


>              if (frm.sliceType == X265_TYPE_AUTO || frm.sliceType ==
> X265_TYPE_I)
>                  frm.sliceType = m_param->bOpenGOP && m_lastKeyframe >= 0
> ? X265_TYPE_I : X265_TYPE_IDR;
>              bool warn = frm.sliceType != X265_TYPE_IDR;
> @@ -1375,6 +1378,9 @@
>  bool Lookahead::scenecut(Lowres **frames, int p0, int p1, bool
> bRealScenecut, int numFrames, int maxSearch)
>  {
>      /* Only do analysis during a normal scenecut check. */
> +    int64_t avgSatdCost = 0;
> +    int cnt = 0;
> +
>      if (bRealScenecut && m_param->bframes)
>      {
>          int origmaxp1 = p0 + 1;
> @@ -1392,11 +1398,45 @@
>          for (int cp1 = p1; cp1 <= maxp1; cp1++)
>          {
>              if (!scenecutInternal(frames, p0, cp1, false))
> +            {
>                  /* Any frame in between p0 and cur_p1 cannot be a real
> scenecut. */
>                  for (int i = cp1; i > p0; i--)
> +                {
>                      frames[i]->bScenecut = false;
> +                    frames[i]->bSceneChange = false;
> +                }
> +            }
> +            else if (!scenecutInternal(frames,cp1 - 1, cp1, false))
> +            {
> +                /* Prevent false flashes. */
> +                frames[cp1]->bSceneChange = false;
> +            }
> +            else
> +            {
> +                /* compute average satdcost of flashes of scenecuts to
> confirm
> +                 * bwhether a scene transition is possible within the
> segment. */
> +                avgSatdCost += frames[cp1]->costEst[1][0];
> +                cnt++;
> +            }
>          }
> -
> +        /* Identify possible scene fluctuations by comparing the satd
> cost of the flashes.
> +         * This could denote the beginning or ending of scene transitions.
> +         * During a scene transition(fade in/fade outs), if fluctuate
> remains false,
> +         * then the scene had completed its transition or stabilized.
> +         */
> +        bool fluctuate = false;
> +        if (avgSatdCost > 0)
> +        {
> +            avgSatdCost /= cnt;
> +            for (int i= p1 ; i <= maxp1; i++)
> +            {
> +                if (abs(frames[i]->costEst[1][0] - avgSatdCost)  > 0.1 *
> avgSatdCost)
> +                {
> +                    fluctuate = true;
> +                    break;
> +                }
> +            }
> +        }
>
Looks good, the adaptive cost thresholding will hopefully avoid spurious
decisions.


>          /* Where A-F are scenes: AAAAABBCCDDEEFFFFFF
>           * If each of BB ... EE are shorter than (maxp1-p0), they are
>           * detected as flashes and not considered scenecuts.
> @@ -1405,8 +1445,25 @@
>          for (int cp0 = p0; cp0 <= maxp1; cp0++)
>          {
>              if (origmaxp1 > maxSearch || (cp0 < maxp1 &&
> scenecutInternal(frames, cp0, maxp1, false)))
> +            {
>                  /* If cur_p0 is the p0 of a scenecut, it cannot be the p1
> of a scenecut. */
>                  frames[cp0]->bScenecut = false;
> +                /* Check for start of flash sequence for a new scene
> transition segment. */
> +                bool isSceneChangeNext = scenecutInternal(frames, cp0,
> cp0 + 1, false);
> +                if (frames[cp0]->bSceneChange && isSceneChangeNext)
> +                {
> +                    if (!m_isSceneTransition && fluctuate)
> +                        m_isSceneTransition = true;
> +                    else
> +                        frames[cp0]->bSceneChange = false;
> +                }
> +             }
> +        }
> +
>

To determine m_isSceneTransition for this frame, we need to look at this
flag for the previous frames (in addition to checking for end of the scene
transition), no?

also, why are sceneChange and sceneTransition in different classes? They
should both be in lowres, and will be consumed by ratecontrol only.

+        if (numFrames > origmaxp1 && (avgSatdCost == 0 || !fluctuate))
> +        {
> +            /* Signal end of scene transitioning */
> +            m_isSceneTransition = false;
>          }
>      }
>
> diff -r 46152345eb6f -r 2a901547b3b8 source/encoder/slicetype.h
> --- a/source/encoder/slicetype.h        Mon Jul 20 17:18:54 2015 -0700
> +++ b/source/encoder/slicetype.h        Wed Jul 22 00:29:26 2015 +0530
> @@ -127,7 +127,7 @@
>      int           m_numCoopSlices;
>      int           m_numRowsPerSlice;
>      bool          m_filled;
> -
> +    bool          m_isSceneTransition;
>      Lookahead(x265_param *param, ThreadPool *pool);
>
>  #if DETAILED_CU_STATS
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20150730/04b00ee6/attachment-0001.html>


More information about the x265-devel mailing list