[x265] [PATCH 1 of 2] lookahead : call sliceTypeAnalyse even when cutree is On or lookaheadDepth or scenecutThreashold >0

Aarthi Thirumalai aarthi at multicorewareinc.com
Fri Jan 17 14:18:51 CET 2014


# HG changeset patch
# User Aarthi Thirumalai
# Date 1389964535 -19800
#      Fri Jan 17 18:45:35 2014 +0530
# Node ID f2b8eda2fb94f50e6dc79e3151a8dadb40207b6a
# Parent  1d7ea03e1a386301b82287c87f6c4d08fce638d6
lookahead : call sliceTypeAnalyse even when cutree is On or lookaheadDepth or scenecutThreashold >0

performs lookahead when lookaheadDepth > 0 , activates lookahead for cutree when b-adapt/bframes =0 and cutree
is set , also enables scenecut for bframes =0 cases.
improves psnr/ssim by .5 dB.

diff -r 1d7ea03e1a38 -r f2b8eda2fb94 source/common/common.cpp
--- a/source/common/common.cpp	Wed Jan 15 19:18:53 2014 +0530
+++ b/source/common/common.cpp	Fri Jan 17 18:45:35 2014 +0530
@@ -527,7 +527,7 @@
         param->rc.aqStrength = 0.0;
     }
 
-    if(param->bFrameAdaptive == 0 && param->rc.cuTree)
+    if(param->lookaheadDepth == 0 && param->rc.cuTree)
     {
         x265_log(NULL, X265_LOG_WARNING, "cuTree disabled, requires lookahead to be enabled\n");
         param->rc.cuTree = 0;
diff -r 1d7ea03e1a38 -r f2b8eda2fb94 source/encoder/slicetype.cpp
--- a/source/encoder/slicetype.cpp	Wed Jan 15 19:18:53 2014 +0530
+++ b/source/encoder/slicetype.cpp	Fri Jan 17 18:45:35 2014 +0530
@@ -631,105 +631,132 @@
 
 void Lookahead::slicetypeDecide()
 {
-    if (cfg->param.bFrameAdaptive && cfg->param.lookaheadDepth && cfg->param.bframes)
+    if ((cfg->param.bFrameAdaptive && cfg->param.bframes )||
+        cfg->param.rc.cuTree || cfg->param.scenecutThreshold ||
+        (cfg->param.lookaheadDepth && cfg->param.rc.vbvBufferSize))
     {
         slicetypeAnalyse(false);
+    }
 
-        TComPic *list[X265_LOOKAHEAD_MAX];
-        TComPic *ipic = inputQueue.first();
-        int j;
-        for (j = 0; ipic && j < cfg->param.bframes + 2; ipic = ipic->m_next)
+
+    TComPic *list[X265_LOOKAHEAD_MAX];
+    TComPic *ipic = inputQueue.first();
+    int j;
+    for (j = 0; ipic && j < cfg->param.bframes + 2; ipic = ipic->m_next)
+    {
+        list[j++] = ipic;
+    }
+
+    list[j] = NULL;
+
+    int bframes, brefs;
+    for (bframes = 0, brefs = 0;; bframes++)
+    {
+        Lowres& frm = list[bframes]->m_lowres;
+
+        if (frm.sliceType == X265_TYPE_BREF && !cfg->param.bBPyramid && brefs == cfg->param.bBPyramid)
         {
-            list[j++] = ipic;
+            frm.sliceType = X265_TYPE_B;
+            x265_log(&cfg->param, X265_LOG_WARNING, "B-ref at frame %d incompatible with B-pyramid\n",
+                     frm.frameNum);
         }
 
-        list[j] = NULL;
+        /* pyramid with multiple B-refs needs a big enough dpb that the preceding P-frame stays available.
+           smaller dpb could be supported by smart enough use of mmco, but it's easier just to forbid it.*/
+        else if (frm.sliceType == X265_TYPE_BREF && cfg->param.bBPyramid && brefs &&
+                 cfg->param.maxNumReferences <= (brefs + 3))
+        {
+            frm.sliceType = X265_TYPE_B;
+            x265_log(&cfg->param, X265_LOG_WARNING, "B-ref at frame %d incompatible with B-pyramid and %d reference frames\n",
+                     frm.sliceType, cfg->param.maxNumReferences);
+        }
 
-        int bframes, brefs;
-        for (bframes = 0, brefs = 0;; bframes++)
+        if (frm.sliceType == X265_TYPE_KEYFRAME)
+            frm.sliceType = cfg->param.bOpenGOP ? X265_TYPE_I : X265_TYPE_IDR;
+        if (( /* !cfg->param.intraRefresh || */ frm.frameNum == 0) && frm.frameNum - lastKeyframe >= cfg->param.keyframeMax)
         {
-            Lowres& frm = list[bframes]->m_lowres;
-
-            if (frm.sliceType == X265_TYPE_BREF && !cfg->param.bBPyramid && brefs == cfg->param.bBPyramid)
+            if (frm.sliceType == X265_TYPE_AUTO || frm.sliceType == X265_TYPE_I)
+                frm.sliceType = cfg->param.bOpenGOP && lastKeyframe >= 0 ? X265_TYPE_I : X265_TYPE_IDR;
+            bool warn = frm.sliceType != X265_TYPE_IDR;
+            if (warn && cfg->param.bOpenGOP)
+                warn &= frm.sliceType != X265_TYPE_I;
+            if (warn)
             {
-                frm.sliceType = X265_TYPE_B;
-                x265_log(&cfg->param, X265_LOG_WARNING, "B-ref at frame %d incompatible with B-pyramid\n",
-                         frm.frameNum);
+                x265_log(&cfg->param, X265_LOG_WARNING, "specified frame type (%d) at %d is not compatible with keyframe interval\n", frm.sliceType, frm.frameNum);
+                frm.sliceType = cfg->param.bOpenGOP && lastKeyframe >= 0 ? X265_TYPE_I : X265_TYPE_IDR;
             }
-
-            /* pyramid with multiple B-refs needs a big enough dpb that the preceding P-frame stays available.
-               smaller dpb could be supported by smart enough use of mmco, but it's easier just to forbid it.*/
-            else if (frm.sliceType == X265_TYPE_BREF && cfg->param.bBPyramid && brefs &&
-                     cfg->param.maxNumReferences <= (brefs + 3))
+        }
+        if (frm.sliceType == X265_TYPE_I && frm.frameNum - lastKeyframe >= cfg->param.keyframeMin)
+        {
+            if (cfg->param.bOpenGOP)
             {
-                frm.sliceType = X265_TYPE_B;
-                x265_log(&cfg->param, X265_LOG_WARNING, "B-ref at frame %d incompatible with B-pyramid and %d reference frames\n",
-                         frm.sliceType, cfg->param.maxNumReferences);
-            }
-
-            if (frm.sliceType == X265_TYPE_KEYFRAME)
-                frm.sliceType = cfg->param.bOpenGOP ? X265_TYPE_I : X265_TYPE_IDR;
-            if (( /* !cfg->param.intraRefresh || */ frm.frameNum == 0) && frm.frameNum - lastKeyframe >= cfg->param.keyframeMax)
-            {
-                if (frm.sliceType == X265_TYPE_AUTO || frm.sliceType == X265_TYPE_I)
-                    frm.sliceType = cfg->param.bOpenGOP && lastKeyframe >= 0 ? X265_TYPE_I : X265_TYPE_IDR;
-                bool warn = frm.sliceType != X265_TYPE_IDR;
-                if (warn && cfg->param.bOpenGOP)
-                    warn &= frm.sliceType != X265_TYPE_I;
-                if (warn)
-                {
-                    x265_log(&cfg->param, X265_LOG_WARNING, "specified frame type (%d) at %d is not compatible with keyframe interval\n", frm.sliceType, frm.frameNum);
-                    frm.sliceType = cfg->param.bOpenGOP && lastKeyframe >= 0 ? X265_TYPE_I : X265_TYPE_IDR;
-                }
-            }
-            if (frm.sliceType == X265_TYPE_I && frm.frameNum - lastKeyframe >= cfg->param.keyframeMin)
-            {
-                if (cfg->param.bOpenGOP)
-                {
-                    lastKeyframe = frm.frameNum;
-                    frm.bKeyframe = true;
-                }
-                else
-                    frm.sliceType = X265_TYPE_IDR;
-            }
-            if (frm.sliceType == X265_TYPE_IDR)
-            {
-                /* Closed GOP */
                 lastKeyframe = frm.frameNum;
                 frm.bKeyframe = true;
-                if (bframes > 0)
-                {
-                    frames[bframes]->sliceType = X265_TYPE_P;
-                    bframes--;
-                }
             }
+            else
+                frm.sliceType = X265_TYPE_IDR;
+        }
+        if (frm.sliceType == X265_TYPE_IDR)
+        {
+            /* Closed GOP */
+            lastKeyframe = frm.frameNum;
+            frm.bKeyframe = true;
+            if (bframes > 0)
+            {
+                frames[bframes]->sliceType = X265_TYPE_P;
+                bframes--;
+            }
+        }
+                 if (bframes == cfg->param.bframes || !list[bframes + 1])
+        {
+            if (IS_X265_TYPE_B(frm.sliceType))
+                x265_log(&cfg->param, X265_LOG_WARNING, "specified frame type is not compatible with max B-frames\n");
+            if (frm.sliceType == X265_TYPE_AUTO || IS_X265_TYPE_B(frm.sliceType))
+                frm.sliceType = X265_TYPE_P;
+        }
+        if (frm.sliceType == X265_TYPE_BREF)
+            brefs++;
+        if (frm.sliceType == X265_TYPE_AUTO)
+            frm.sliceType = X265_TYPE_B;
+        else if (!IS_X265_TYPE_B(frm.sliceType))
+            break;
+    }
 
-            if (bframes == cfg->param.bframes || !list[bframes + 1])
-            {
-                if (IS_X265_TYPE_B(frm.sliceType))
-                    x265_log(&cfg->param, X265_LOG_WARNING, "specified frame type is not compatible with max B-frames\n");
-                if (frm.sliceType == X265_TYPE_AUTO || IS_X265_TYPE_B(frm.sliceType))
-                    frm.sliceType = X265_TYPE_P;
-            }
-            if (frm.sliceType == X265_TYPE_BREF)
-                brefs++;
-            if (frm.sliceType == X265_TYPE_AUTO)
-                frm.sliceType = X265_TYPE_B;
-            else if (!IS_X265_TYPE_B(frm.sliceType))
-                break;
+    if (bframes)
+        list[bframes - 1]->m_lowres.bLastMiniGopBFrame = true;
+    list[bframes]->m_lowres.leadingBframes = bframes;
+    lastNonB = &list[bframes]->m_lowres;
+
+    /* insert a bref into the sequence */
+    if (cfg->param.bBPyramid && bframes > 1 && !brefs)
+    {
+        list[bframes / 2]->m_lowres.sliceType = X265_TYPE_BREF;
+        brefs++;
+    }
+
+    /* calculate the frame costs ahead of time for x264_rc_analyse_slice while we still have lowres */
+    if (cfg->param.rc.rateControlMode != X265_RC_CQP)
+    {
+        int p0, p1, b;
+        p1 = b = bframes + 1;
+
+        frames[0] = lastNonB;
+        for (int i = 0; i <= bframes; i++)
+        {
+            frames[i + 1] = &list[i]->m_lowres;
         }
 
-        if (bframes)
-            list[bframes - 1]->m_lowres.bLastMiniGopBFrame = true;
-        list[bframes]->m_lowres.leadingBframes = bframes;
-        lastNonB = &list[bframes]->m_lowres;
+        if (IS_X265_TYPE_I(frames[bframes + 1]->sliceType))
+            p0 = bframes + 1;
+        else // P
+            p0 = 0;
 
-        /* insert a bref into the sequence */
-        if (cfg->param.bBPyramid && bframes > 1 && !brefs)
+        estimateFrameCost(p0, p1, b, 0);
+
+        if ((p0 != p1 || bframes) /*&& cfg->param.rc.i_vbv_buffer_size*/)
         {
-            list[bframes / 2]->m_lowres.sliceType = X265_TYPE_BREF;
-            brefs++;
-        }
+            // We need the intra costs for row SATDs
+            estimateFrameCost(b, b, b, 0);
 
         /* calculate the frame costs ahead of time for x264_rc_analyse_slice while we still have lowres */
         if (cfg->param.rc.rateControlMode != X265_RC_CQP)
@@ -737,188 +764,56 @@
             int p0, p1, b;
             p1 = b = bframes + 1;
 
-            frames[0] = lastNonB;
-            for (int i = 0; i <= bframes; i++)
-            {
-                frames[i + 1] = &list[i]->m_lowres;
-            }
-
-            if (IS_X265_TYPE_I(frames[bframes + 1]->sliceType))
-                p0 = bframes + 1;
-            else // P
-                p0 = 0;
-
-            estimateFrameCost(p0, p1, b, 0);
-
-            if ((p0 != p1 || bframes) /*&& cfg->param.rc.i_vbv_buffer_size*/)
-            {
-                // We need the intra costs for row SATDs
-                estimateFrameCost(b, b, b, 0);
-
-                // We need B-frame costs for row SATDs
-                p0 = 0;
-                for (b = 1; b <= bframes; b++)
-                {
-                    if (frames[b]->sliceType == X265_TYPE_B)
-                        for (p1 = b; frames[p1]->sliceType == X265_TYPE_B; )
-                        {
-                            p1++;
-                        }
-
-                    else
-                        p1 = bframes + 1;
-                    estimateFrameCost(p0, p1, b, 0);
-                    if (frames[b]->sliceType == X265_TYPE_BREF)
-                        p0 = b;
-                }
+                else
+                    p1 = bframes + 1;
+                estimateFrameCost(p0, p1, b, 0);
+                if (frames[b]->sliceType == X265_TYPE_BREF)
+                    p0 = b;
             }
         }
+    }
 
-        /* dequeue all frames from inputQueue that are about to be enqueued
-         * in the output queue.  The order is important because TComPic can
-         * only be in one list at a time */
-        int64_t pts[X265_BFRAME_MAX + 1];
-        for (int i = 0; i <= bframes; i++)
-        {
-            TComPic *pic;
-            pic = inputQueue.popFront();
-            pts[i] = pic->m_pts;
-        }
+    /* dequeue all frames from inputQueue that are about to be enqueued
+     * in the output queue.  The order is important because TComPic can
+     * only be in one list at a time */
+    int64_t pts[X265_BFRAME_MAX + 1];
+    for (int i = 0; i <= bframes; i++)
+    {
+        TComPic *pic;
+        pic = inputQueue.popFront();
+        pts[i] = pic->m_pts;
+    }
 
-        /* add non-B to output queue */
-        int idx = 0;
-        list[bframes]->m_reorderedPts = pts[idx++];
-        outputQueue.pushBack(*list[bframes]);
+    /* add non-B to output queue */
+    int idx = 0;
+    list[bframes]->m_reorderedPts = pts[idx++];
+    outputQueue.pushBack(*list[bframes]);
 
-        /* Add B-ref frame next to P frame in output queue, the B-ref encode before non B-ref frame */
-        if (bframes > 1 && cfg->param.bBPyramid)
-        {
-            for (int i = 0; i < bframes; i++)
-            {
-                if (list[i]->m_lowres.sliceType == X265_TYPE_BREF)
-                {
-                    list[i]->m_reorderedPts = pts[idx++];
-                    outputQueue.pushBack(*list[i]);
-                }
-            }
-        }
-
-        /* add B frames to output queue */
+    /* Add B-ref frame next to P frame in output queue, the B-ref encode before non B-ref frame */
+    if (bframes > 1 && cfg->param.bBPyramid)
+    {
         for (int i = 0; i < bframes; i++)
         {
-            /* push all the B frames into output queue except B-ref, which already pushed into output queue*/
-            if (list[i]->m_lowres.sliceType != X265_TYPE_BREF)
+            if (list[i]->m_lowres.sliceType == X265_TYPE_BREF)
             {
                 list[i]->m_reorderedPts = pts[idx++];
                 outputQueue.pushBack(*list[i]);
             }
         }
-
-        return;
     }
 
-    // Fixed GOP structures for when B-Adapt and/or lookahead are disabled
-    if (numDecided == 0 || cfg->param.keyframeMax <= 1)
+    /* add B frames to output queue */
+    for (int i = 0; i < bframes; i++)
     {
-        TComPic *pic = inputQueue.popFront();
-        pic->m_lowres.sliceType = X265_TYPE_I;
-        pic->m_lowres.bKeyframe = true;
-        lastKeyframe = pic->m_lowres.frameNum;
-        lastNonB = &pic->m_lowres;
-        numDecided++;
-
-        pic->m_reorderedPts = pic->m_pts;
-        outputQueue.pushBack(*pic);
-    }
-    else if (cfg->param.bframes == 0 || inputQueue.size() == 1)
-    {
-        TComPic *pic = inputQueue.popFront();
-        if (pic->getPOC() % cfg->param.keyframeMax)
-            pic->m_lowres.sliceType = X265_TYPE_P;
-        else
+        /* push all the B frames into output queue except B-ref, which already pushed into output queue*/
+        if (list[i]->m_lowres.sliceType != X265_TYPE_BREF)
         {
-            pic->m_lowres.sliceType = X265_TYPE_I;
-            pic->m_lowres.bKeyframe = true;
-            lastKeyframe = pic->m_lowres.frameNum;
-        }
-        lastNonB = &pic->m_lowres;
-        pic->m_reorderedPts = pic->m_pts;
-        outputQueue.pushBack(*pic);
-        numDecided++;
-    }
-    else
-    {
-        TComPic *list[X265_BFRAME_MAX + 1];
-        int64_t pts[X265_BFRAME_MAX + 1];
-        int j;
-        for (j = 0; j <= cfg->param.bframes && !inputQueue.empty(); j++)
-        {
-            TComPic *pic = inputQueue.popFront();
-            list[j] = pic;
-            pts[j] = pic->m_pts;
-            if (pic->m_lowres.frameNum >= lastKeyframe + cfg->param.keyframeMax)
-            {
-                if (j)
-                {
-                    list[j - 1]->m_lowres.sliceType = X265_TYPE_P;
-                    inputQueue.pushFront(*pic); // push I-frame back onto input queue
-                }
-                else
-                {
-                    pic->m_lowres.sliceType = X265_TYPE_I;
-                    pic->m_lowres.bKeyframe = true;
-                    lastKeyframe = pic->m_lowres.frameNum;
-                    j++;
-                }
-                break;
-            }
-        }
-
-        if (!j)
-            return;
-        int bframes = j - 1;
-        if (bframes)
-            list[bframes - 1]->m_lowres.bLastMiniGopBFrame = true;
-        list[bframes]->m_lowres.leadingBframes = bframes;
-        lastNonB = &list[bframes]->m_lowres;
-
-        TComPic *pic = list[bframes];
-        if (pic->m_lowres.sliceType == X265_TYPE_AUTO)
-            pic->m_lowres.sliceType = X265_TYPE_P;
-
-        int idx = 0;
-        pic->m_reorderedPts = pts[idx++];
-
-        outputQueue.pushBack(*pic);
-        numDecided++;
-
-        if (cfg->param.bBPyramid && bframes > 1)
-        {
-            int bref = bframes / 2;
-            if (list[bref - 1]->m_lowres.sliceType == X265_TYPE_AUTO)
-            {
-                list[bref - 1]->m_lowres.sliceType = X265_TYPE_BREF;
-
-                list[bref - 1]->m_reorderedPts = pts[idx++];
-                outputQueue.pushBack(*list[bref - 1]);
-                numDecided++;
-            }
-        }
-
-        for (int i = 0; i < bframes; i++)
-        {
-            pic = list[i];
-            if (pic->m_lowres.sliceType == X265_TYPE_AUTO)
-                pic->m_lowres.sliceType = X265_TYPE_B;
-
-            if (pic->m_lowres.sliceType != X265_TYPE_BREF)
-            {
-                pic->m_reorderedPts = pts[idx++];
-                outputQueue.pushBack(*pic);
-                numDecided++;
-            }
+            list[i]->m_reorderedPts = pts[idx++];
+            outputQueue.pushBack(*list[i]);
         }
     }
+
+    return;
 }
 
 void Lookahead::slicetypeAnalyse(bool bKeyframe)


More information about the x265-devel mailing list