<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Nov 18, 2013 at 3:40 PM, Gopu Govindaswamy <span dir="ltr"><<a href="mailto:gopu@multicorewareinc.com" target="_blank">gopu@multicorewareinc.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Gopu Govindaswamy <<a href="mailto:gopu@multicorewareinc.com">gopu@multicorewareinc.com</a>><br>
# Date 1384769433 -19800<br>
# Node ID 1e22b93638072ed805478d7af17f90e285fb4969<br>
# Parent  2321ebe0bf64e5f3c0034076c7edb3ecbcd48039<br>
b-pyramid implementation: Allow the use of B-frames as references for non B and B frames<br>
<br>
when we enable the b-pyramid the bitrates efficienctly reduced and there is not much diff in the performance<br>
and the PSNR 00. increased some of the clips and decreased some of clips<br>
<br>
Test results for reference when enable and disable the b-pyramid:<br>
cli option : -b 10 --hash=1 -f 100 --b-pyramid=1 --ref=1 --b-adapt=2<br>
Enable B-reference  : --b-pyramid=1<br>
Disable B-reference : --b-pyramid=0<br>
<br>
Results:<br>
Enable / Disable<br>
<br>
clip - FourPeople_1280x720_60.yuv<br>
Total time taken - 9.70s (10.31 fps) / 9.93s (10.07 fps)<br>
Bitrates - 516.30 kb/s / 544.68 kb/s<br>
PSNR     - 39.725 / 39.701<br>
<br>
clip - BasketballDrive_1920x1080_50.y4m<br>
Total time taken - 39.06s (2.51 fps) / 38.98s (2.57 fps)<br>
Bitrates -  4166.92 kb/s / 4370.43 kb/s<br>
PSNR     -  37.261 / 37.268<br>
<br>
clip - Johnny_1280x720_60.y4m<br>
Total time taken - 8.88s (11.27 fps) / 11.08s (9.03 fps)<br>
Bitrates - 304.29 kb/s / 328.84 kb/s<br>
PSNR     - 40.605 / 40.551<br>
<br>
Total time taken - 30.97s (3.23 fps) / 33.65s (2.97 fps)<br>
Bitrates - 3496.84 kb/s / 3683.93 kb/s<br>
PSNR     - 35.645 / 35.660<br>
<br>
diff -r 2321ebe0bf64 -r 1e22b9363807 source/common/common.cpp<br>
--- a/source/common/common.cpp  Mon Nov 18 11:32:06 2013 +0530<br>
+++ b/source/common/common.cpp  Mon Nov 18 15:40:33 2013 +0530<br>
@@ -54,6 +54,7 @@<br>
<br>
 static int parseCspName(const char *arg, int& error);<br>
 static int parseName(const char *arg, const char * const * names, int& error);<br>
+static int parse_enum(const char *, const char * const * names, int *dst);<br>
<br>
 using namespace x265;<br>
<br>
@@ -165,6 +166,7 @@<br>
     param->bframes = 3;<br>
     param->lookaheadDepth = 40;<br>
     param->bFrameAdaptive = X265_B_ADAPT_FAST;<br>
+    param->bpyramid = 0;<br>
     param->scenecutThreshold = 40; /* Magic number pulled in from x264*/<br>
<br>
     /* Intra Coding Tools */<br>
@@ -532,7 +534,7 @@<br>
     }<br>
<br>
     CHECK(param->bEnableWavefront < 0, "WaveFrontSynchro cannot be negative");<br>
-<br>
+    CHECK(param->bpyramid >= 2, "b-pyramid is 0 or 1");<br>
     return check_failed;<br>
 }<br>
<br>
@@ -620,6 +622,7 @@<br>
         x265_log(param, X265_LOG_INFO, "RDpenalty                    : %d\n", param->rdPenalty);<br>
     }<br>
     x265_log(param, X265_LOG_INFO, "Lookahead / bframes / badapt : %d / %d / %d\n", param->lookaheadDepth, param->bframes, param->bFrameAdaptive);<br>
+    x265_log(param, X265_LOG_INFO, "b-pyramid / weightp / ref    : %d / %d / %d\n", param->bpyramid, param->bEnableWeightedPred, param->maxNumReferences);<br>
     x265_log(param, X265_LOG_INFO, "tools: ");<br>
 #define TOOLOPT(FLAG, STR) if (FLAG) fprintf(stderr, "%s ", STR)<br>
     TOOLOPT(param->bEnableRectInter, "rect");<br>
@@ -628,7 +631,6 @@<br>
     TOOLOPT(param->bEnableConstrainedIntra, "cip");<br>
     TOOLOPT(param->bEnableEarlySkip, "esd");<br>
     fprintf(stderr, "rd=%d ", param->rdLevel);<br>
-    fprintf(stderr, "ref=%d ", param->maxNumReferences);<br>
<br>
     TOOLOPT(param->bEnableLoopFilter, "lft");<br>
     if (param->bEnableSAO)<br>
@@ -650,7 +652,6 @@<br>
         else<br>
             fprintf(stderr, "tskip ");<br>
     }<br>
-    TOOLOPT(param->bEnableWeightedPred, "weightp");<br>
     TOOLOPT(param->bEnableWeightedBiPred, "weightbp");<br>
     TOOLOPT(param->rc.aqMode, "aq");<br>
     fprintf(stderr, "\n");<br>
@@ -747,6 +748,15 @@<br>
     }<br>
     OPT("input-csp") p->sourceCsp = ::parseCspName(value, berror);<br>
     OPT("me")        p->searchMethod = ::parseName(value, x265_motion_est_names, berror);<br>
+    OPT("b-pyramid")<br>
+    {<br>
+        berror |= parse_enum(value, x265_b_pyramid_names, &p->bpyramid);<br>
+        if (berror)<br>
+        {<br>
+            berror = 0;<br>
+            p->bpyramid = atoi(value);<br>
+        }<br>
+    }<br>
     else<br>
         return X265_PARAM_BAD_NAME;<br>
 #undef OPT<br>
@@ -802,6 +812,7 @@<br>
     BOOL(p->bEnableSAO, "sao");<br>
     s += sprintf(s, " sao-lcu-bounds=%d", p->saoLcuBoundary);<br>
     s += sprintf(s, " sao-lcu-opt=%d", p->saoLcuBasedOptimization);<br>
+    s += sprintf(s, " b-pyramid=%d", p->bpyramid);<br>
 #undef BOOL<br>
<br>
     return buf;<br>
@@ -843,3 +854,13 @@<br>
         error = 1;<br>
     return a;<br>
 }<br>
+static int parse_enum(const char *arg, const char * const * names, int *dst)<br>
+{<br>
+    for (int i = 0; names[i]; i++)<br>
+        if (!strcmp(arg, names[i]))<br>
+        {<br>
+            *dst = i;<br>
+            return 0;<br>
+        }<br>
+    return -1;<br>
+}<br>
diff -r 2321ebe0bf64 -r 1e22b9363807 source/common/common.h<br>
--- a/source/common/common.h    Mon Nov 18 11:32:06 2013 +0530<br>
+++ b/source/common/common.h    Mon Nov 18 15:40:33 2013 +0530<br>
@@ -107,6 +107,7 @@<br>
 #define X265_LOG2(x)  log2(x)<br>
 #endif<br>
<br>
+static const char * const x265_b_pyramid_names[] = {"none", "normal", 0};<br>
 /* defined in common.cpp */<br>
 int64_t x265_mdate(void);<br>
 void x265_log(x265_param *param, int level, const char *fmt, ...);<br>
diff -r 2321ebe0bf64 -r 1e22b9363807 source/encoder/dpb.cpp<br>
--- a/source/encoder/dpb.cpp    Mon Nov 18 11:32:06 2013 +0530<br>
+++ b/source/encoder/dpb.cpp    Mon Nov 18 15:40:33 2013 +0530<br>
@@ -78,7 +78,17 @@<br>
         m_lastIDR = pocCurr;<br>
     }<br>
     slice->setLastIDR(m_lastIDR);<br>
-    slice->setReferenced(slice->getSliceType() != B_SLICE);<br>
+<br>
+    if (slice->getSliceType() != B_SLICE)<br>
+        slice->setReferenced(true);<br>
+    else<br>
+    {<br>
+        if (pic->m_lowres.sliceType == X265_TYPE_BREF)<br>
+            slice->setReferenced(true);<br>
+        else<br>
+            slice->setReferenced(false);<br>
+    }<br>
+<br>
     slice->setTemporalLayerNonReferenceFlag(!slice->isReferenced());<br>
     // Set the nal unit type<br>
     slice->setNalUnitType(getNalUnitType(pocCurr, m_lastIDR, pic));<br>
diff -r 2321ebe0bf64 -r 1e22b9363807 source/encoder/encoder.cpp<br>
--- a/source/encoder/encoder.cpp        Mon Nov 18 11:32:06 2013 +0530<br>
+++ b/source/encoder/encoder.cpp        Mon Nov 18 15:40:33 2013 +0530<br>
@@ -1223,7 +1223,13 @@<br>
     vps.setMaxLayers(1);<br>
     for (int i = 0; i < MAX_TLAYER; i++)<br>
     {<br>
-        m_numReorderPics[i] = 1;<br>
+        /* Increase the DPB size if enabled the bpyramid the b-ref always should take Lo and L1 as a non B frames<br>
+        the dpb size is always 3 when enabled the b-pyramid */<br>
+        if (_param->bpyramid && _param->bframes > 1)<br>
+            m_numReorderPics[i] = 3;<br>
+        else<br>
+            m_numReorderPics[i] = 1;<br>
+<br></blockquote><div><br></div><div>Shouldn't it be numReorderPics = 2 with bpyramid? Because only two frames will be out of order.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

         m_maxDecPicBuffering[i] = X265_MIN(MAX_NUM_REF, X265_MAX(m_numReorderPics[i] + 1, _param->maxNumReferences) + 1);<br>
         vps.setNumReorderPics(m_numReorderPics[i], i);<br>
         vps.setMaxDecPicBuffering(m_maxDecPicBuffering[i], i);<br>
diff -r 2321ebe0bf64 -r 1e22b9363807 source/encoder/slicetype.cpp<br>
--- a/source/encoder/slicetype.cpp      Mon Nov 18 11:32:06 2013 +0530<br>
+++ b/source/encoder/slicetype.cpp      Mon Nov 18 15:40:33 2013 +0530<br>
@@ -643,21 +643,22 @@<br>
             Lowres& frm = list[bframes]->m_lowres;<br>
<br>
             if (frm.sliceType == X265_TYPE_BREF<br>
-                /* && h->param.i_bframe_pyramid < X264_B_PYRAMID_NORMAL && brefs == h->param.i_bframe_pyramid*/)<br>
+                && cfg->param.bpyramid < X265_B_PYRAMID_NORMAL && brefs == cfg->param.bpyramid)<br>
             {<br>
                 frm.sliceType = X265_TYPE_B;<br>
-                x265_log(&cfg->param, X265_LOG_WARNING, "B-ref is not yet supported\n");<br>
+                x265_log(&cfg->param, X265_LOG_WARNING, "B-ref at frame %d incompatible with B-pyramid %s \n",<br>
+                        frm.frameNum, x265_b_pyramid_names[cfg->param.bpyramid] );<br>
             }<br>
<br>
             /* pyramid with multiple B-refs needs a big enough dpb that the preceding P-frame stays available.<br>
-               smaller dpb could be supported by smart enough use of mmco, but it's easier just to forbid it.<br>
-            else if (frm.sliceType == X265_TYPE_BREF && cfg->param.i_bframe_pyramid == X265_B_PYRAMID_NORMAL &&<br>
-                     brefs && cfg->param.i_frame_reference <= (brefs+3))<br>
+               smaller dpb could be supported by smart enough use of mmco, but it's easier just to forbid it.*/<br>
+            else if (frm.sliceType == X265_TYPE_BREF && cfg->param.bpyramid == X265_B_PYRAMID_NORMAL &&<br>
+                     brefs && cfg->param.maxNumReferences <= (brefs+3))<br>
             {<br>
                 frm.sliceType = X265_TYPE_B;<br>
                 x265_log(&cfg->param, X265_LOG_WARNING, "B-ref at frame %d incompatible with B-pyramid %s and %d reference frames\n",<br>
-                          frm.sliceType, x264_b_pyramid_names[h->param.i_bframe_pyramid], h->param.i_frame_reference);<br>
-            } */<br>
+                        frm.sliceType, x265_b_pyramid_names[cfg->param.bpyramid], cfg->param.maxNumReferences);<br>
+            }<br>
<br>
             if (frm.sliceType == X265_TYPE_KEYFRAME)<br>
                 frm.sliceType = cfg->param.bOpenGOP ? X265_TYPE_I : X265_TYPE_IDR;<br>
@@ -716,12 +717,12 @@<br>
         list[bframes]->m_lowres.leadingBframes = bframes;<br>
         lastNonB = &list[bframes]->m_lowres;<br>
<br>
-        /* insert a bref into the sequence<br>
-        if (h->param.i_bframe_pyramid && bframes > 1 && !brefs)<br>
+        /* insert a bref into the sequence */<br>
+        if (cfg->param.bpyramid && bframes > 1 && !brefs)<br>
         {<br>
-            h->lookahead->next.list[bframes/2]->i_type = X264_TYPE_BREF;<br>
+            list[bframes/2]->m_lowres.sliceType = X265_TYPE_BREF;<br>
             brefs++;<br>
-        } */<br>
+        }<br>
<br>
         /* calculate the frame costs ahead of time for x264_rc_analyse_slice while we still have lowres */<br>
         if (cfg->param.rc.rateControlMode != X265_RC_CQP)<br>
@@ -742,8 +743,7 @@<br>
<br>
             estimateFrameCost(p0, p1, b, 0);<br>
<br>
-            /*<br>
-            if ((p0 != p1 || bframes) && cfg->param.rc.i_vbv_buffer_size)<br>
+            if ((p0 != p1 || bframes) /*&& cfg->param.rc.i_vbv_buffer_size*/ )<br>
             {<br>
                 // We need the intra costs for row SATDs<br>
                 estimateFrameCost(b, b, b, 0);<br>
@@ -752,7 +752,7 @@<br>
                 p0 = 0;<br>
                 for (b = 1; b <= bframes; b++)<br>
                 {<br>
-                    if (frames[b]->i_type == X265_TYPE_B)<br>
+                    if (frames[b]->sliceType == X265_TYPE_B)<br>
                         for (p1 = b; frames[p1]->sliceType == X265_TYPE_B;)<br>
                             p1++;<br>
                     else<br>
@@ -761,7 +761,7 @@<br>
                     if (frames[b]->sliceType == X265_TYPE_BREF)<br>
                         p0 = b;<br>
                 }<br>
-            } */<br>
+            }<br>
         }<br>
<br>
         /* dequeue all frames from inputQueue that are about to be enqueued<br>
@@ -774,10 +774,23 @@<br>
<br>
         /* add non-B to output queue */<br>
         outputQueue.pushBack(*list[bframes]);<br>
+<br>
+        /* Add B-ref frame next to P frame in output queue, the B-ref encode before non B-ref frame */<br>
+        if (bframes > 1 && cfg->param.bpyramid)<br>
+        {<br>
+            for (int i = 0; i < bframes; i++)<br>
+            {<br>
+                if(list[i]->m_lowres.sliceType == X265_TYPE_BREF)<br>
+                    outputQueue.pushBack(*list[i]);<br>
+            }<br>
+        }<br>
+<br>
         /* add B frames to output queue */<br>
         for (int i = 0; i < bframes; i++)<br>
         {<br>
-            outputQueue.pushBack(*list[i]);<br>
+            /* push all the B frames into output queue except B-ref, which already pushed into output queue*/<br>
+            if (list[i]->m_lowres.sliceType != X265_TYPE_BREF)<br>
+                outputQueue.pushBack(*list[i]);<br>
         }<br>
<br>
         return;<br>
@@ -1155,11 +1168,7 @@<br>
         if (cost > threshold)<br>
             break;<br>
<br>
-        /* Keep some B-frames as references: 0=off, 1=strict hierarchical, 2=normal */<br>
-        //TODO Add this into param<br>
-        int bframe_pyramid = 0;<br>
-<br>
-        if (bframe_pyramid && next_p - cur_p > 2)<br>
+        if (cfg->param.bpyramid && next_p - cur_p > 2)<br>
         {<br>
             int middle = cur_p + (next_p - cur_p) / 2;<br>
             cost += estimateFrameCost(cur_p, next_p, middle, 0);<br>
diff -r 2321ebe0bf64 -r 1e22b9363807 source/x265.cpp<br>
--- a/source/x265.cpp   Mon Nov 18 11:32:06 2013 +0530<br>
+++ b/source/x265.cpp   Mon Nov 18 15:40:33 2013 +0530<br>
@@ -116,6 +116,7 @@<br>
     { "bframes",        required_argument, NULL, 'b' },<br>
     { "bframe-bias",    required_argument, NULL, 0 },<br>
     { "b-adapt",        required_argument, NULL, 0 },<br>
+    { "b-pyramid",      required_argument, NULL, 0 },<br>
     { "ref",            required_argument, NULL, 0 },<br>
     { "no-weightp",           no_argument, NULL, 0 },<br>
     { "weightp",              no_argument, NULL, 'w' },<br>
@@ -303,6 +304,7 @@<br>
     H0("   --bframes                     Maximum number of consecutive b-frames (now it only enables B GOP structure) Default %d\n", param->bframes);<br>
     H0("   --bframe-bias                 Bias towards B frame decisions. Default %d\n", param->bFrameBias);<br>
     H0("   --b-adapt                     0 - none, 1 - fast, 2 - full (trellis) adaptive B frame scheduling. Default %d\n", param->bFrameAdaptive);<br>
+    H0("...--b-pyramid...................Use B-frame reference 0: Disabled, 1: Enabled Default\n", param->bpyramid);<br>
     H0("   --ref                         max number of L0 references to be allowed (1 .. 16) Default %d\n", param->maxNumReferences);<br>
     H0("-w/--[no-]weightp                Enable weighted prediction in P slices. Default %s\n", OPT(param->bEnableWeightedPred));<br>
     H0("\nQP, rate control and rate distortion options:\n");<br>
diff -r 2321ebe0bf64 -r 1e22b9363807 source/x265.h<br>
--- a/source/x265.h     Mon Nov 18 11:32:06 2013 +0530<br>
+++ b/source/x265.h     Mon Nov 18 15:40:33 2013 +0530<br>
@@ -204,6 +204,7 @@<br>
 #define X265_TYPE_I             0x0002<br>
 #define X265_TYPE_P             0x0003<br>
 #define X265_TYPE_BREF          0x0004  /* Non-disposable B-frame */<br>
+#define X265_B_PYRAMID_NORMAL   0x0001<br>
 #define X265_TYPE_B             0x0005<br>
 #define X265_TYPE_KEYFRAME      0x0006  /* IDR or I depending on b_open_gop option */<br>
 #define X265_AQ_NONE                 0<br>
@@ -315,6 +316,7 @@<br>
     int       bframes;                         ///< Max number of consecutive B-frames<br>
     int       lookaheadDepth;                  ///< Number of frames to use for lookahead, determines encoder latency<br>
     int       bFrameAdaptive;                  ///< 0 - none, 1 - fast, 2 - full (trellis) adaptive B frame scheduling<br>
+    int       bpyramid;                        ///< 0 - none, 1 - normal use B-frame reference<br>
     int       bFrameBias;<br>
     int       scenecutThreshold;               ///< how aggressively to insert extra I frames<br>
<br>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</blockquote></div><br></div></div>