[x264-devel] commit: Fix various early terminations with slices (Jason Garrett-Glaser )

git at videolan.org git at videolan.org
Wed Apr 14 11:39:13 CEST 2010


x264 | branch: master | Jason Garrett-Glaser <darkshikari at gmail.com> | Sun Apr 11 13:36:50 2010 -0700| [5b86182d1240b441f28462abf3d40b7371de5ba3] | committer: Jason Garrett-Glaser 

Fix various early terminations with slices
Neighbouring type values (type_top, etc) are now loaded even if the MB isn't available for prediction.
Significant overall performance increase (as high as 5-10%+) with lots of slices (e.g. with slice-max-size).

> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=5b86182d1240b441f28462abf3d40b7371de5ba3
---

 common/macroblock.c |   71 +++++++++++++++++++++++++--------------------------
 encoder/cabac.c     |   12 ++++----
 2 files changed, 41 insertions(+), 42 deletions(-)

diff --git a/common/macroblock.c b/common/macroblock.c
index 6dd19f6..0b9b903 100644
--- a/common/macroblock.c
+++ b/common/macroblock.c
@@ -958,66 +958,65 @@ static void inline x264_macroblock_cache_load_neighbours( x264_t *h, int mb_x, i
     h->mb.i_mb_type_topleft = -1;
     h->mb.i_mb_type_topright = -1;
 
-    if( top >= 0 )
-    {
-        h->mb.i_neighbour_frame |= MB_TOP;
-        h->mb.i_mb_top_xy = top;
-        if( top >= h->sh.i_first_mb )
-        {
-            h->mb.i_neighbour |= MB_TOP;
-            h->mb.i_mb_type_top = h->mb.type[h->mb.i_mb_top_xy];
-
-            if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_top ) )
-                h->mb.i_neighbour_intra |= MB_TOP;
-        }
-    }
-
     if( mb_x > 0 )
     {
         h->mb.i_neighbour_frame |= MB_LEFT;
         h->mb.i_mb_left_xy = h->mb.i_mb_xy - 1;
+        h->mb.i_mb_type_left = h->mb.type[h->mb.i_mb_left_xy];
         if( h->mb.i_mb_xy > h->sh.i_first_mb )
         {
             h->mb.i_neighbour |= MB_LEFT;
-            h->mb.i_mb_type_left = h->mb.type[h->mb.i_mb_left_xy];
 
             if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_left ) )
                 h->mb.i_neighbour_intra |= MB_LEFT;
         }
     }
 
-    if( mb_x > 0 && top - 1 >= 0  )
+    /* We can't predict from the previous threadslice since it hasn't been encoded yet. */
+    if( (h->i_threadslice_start >> h->mb.b_interlaced) != (mb_y >> h->mb.b_interlaced) )
     {
-        h->mb.i_neighbour_frame |= MB_TOPLEFT;
-        h->mb.i_mb_topleft_xy = top - 1;
-        if( top - 1 >= h->sh.i_first_mb )
+        if( top >= 0 )
         {
-            h->mb.i_neighbour |= MB_TOPLEFT;
+            h->mb.i_neighbour_frame |= MB_TOP;
+            h->mb.i_mb_top_xy = top;
+            h->mb.i_mb_type_top = h->mb.type[h->mb.i_mb_top_xy];
+            if( top >= h->sh.i_first_mb )
+            {
+                h->mb.i_neighbour |= MB_TOP;
+
+                if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_top ) )
+                    h->mb.i_neighbour_intra |= MB_TOP;
+            }
+        }
+
+        if( mb_x > 0 && top - 1 >= 0  )
+        {
+            h->mb.i_neighbour_frame |= MB_TOPLEFT;
+            h->mb.i_mb_topleft_xy = top - 1;
             h->mb.i_mb_type_topright = h->mb.type[h->mb.i_mb_topleft_xy];
+            if( top - 1 >= h->sh.i_first_mb )
+            {
+                h->mb.i_neighbour |= MB_TOPLEFT;
 
-            if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_topleft ) )
-                h->mb.i_neighbour_intra |= MB_TOPLEFT;
+                if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_topleft ) )
+                    h->mb.i_neighbour_intra |= MB_TOPLEFT;
+            }
         }
-    }
 
-    if( mb_x < h->sps->i_mb_width - 1 && top + 1 >= 0 )
-    {
-        h->mb.i_neighbour_frame |= MB_TOPRIGHT;
-        h->mb.i_mb_topright_xy = top + 1;
-        if( top + 1 >= h->sh.i_first_mb )
+        if( mb_x < h->sps->i_mb_width - 1 && top + 1 >= 0 )
         {
-            h->mb.i_neighbour |= MB_TOPRIGHT;
+            h->mb.i_neighbour_frame |= MB_TOPRIGHT;
+            h->mb.i_mb_topright_xy = top + 1;
             h->mb.i_mb_type_topleft = h->mb.type[h->mb.i_mb_topright_xy];
+            if( top + 1 >= h->sh.i_first_mb )
+            {
+                h->mb.i_neighbour |= MB_TOPRIGHT;
 
-            if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_topright ) )
-                h->mb.i_neighbour_intra |= MB_TOPRIGHT;
+                if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_topright ) )
+                    h->mb.i_neighbour_intra |= MB_TOPRIGHT;
+            }
         }
     }
-
-    /* We can't predict from the previous threadslice since it hasn't been encoded yet, so
-     * only use left. */
-    if( h->i_threadslice_start == mb_y )
-        h->mb.i_neighbour_frame &= MB_LEFT;
 }
 
 void x264_macroblock_cache_load( x264_t *h, int mb_x, int mb_y )
diff --git a/encoder/cabac.c b/encoder/cabac.c
index 427dba7..a0dcff2 100644
--- a/encoder/cabac.c
+++ b/encoder/cabac.c
@@ -76,9 +76,9 @@ static void x264_cabac_mb_type( x264_t *h, x264_cabac_t *cb )
     if( h->sh.i_type == SLICE_TYPE_I )
     {
         int ctx = 0;
-        if( h->mb.i_mb_type_left >= 0 && h->mb.i_mb_type_left != I_4x4 )
+        if( (h->mb.i_neighbour & MB_LEFT) && h->mb.i_mb_type_left != I_4x4 )
             ctx++;
-        if( h->mb.i_mb_type_top >= 0 && h->mb.i_mb_type_top != I_4x4 )
+        if( (h->mb.i_neighbour & MB_TOP) && h->mb.i_mb_type_top != I_4x4 )
             ctx++;
 
         x264_cabac_mb_type_intra( h, cb, i_mb_type, 3+ctx, 3+3, 3+4, 3+5, 3+6, 3+7 );
@@ -110,9 +110,9 @@ static void x264_cabac_mb_type( x264_t *h, x264_cabac_t *cb )
     else //if( h->sh.i_type == SLICE_TYPE_B )
     {
         int ctx = 0;
-        if( h->mb.i_mb_type_left >= 0 && h->mb.i_mb_type_left != B_SKIP && h->mb.i_mb_type_left != B_DIRECT )
+        if( (h->mb.i_neighbour & MB_LEFT) && h->mb.i_mb_type_left != B_SKIP && h->mb.i_mb_type_left != B_DIRECT )
             ctx++;
-        if( h->mb.i_mb_type_top >= 0 && h->mb.i_mb_type_top != B_SKIP && h->mb.i_mb_type_top != B_DIRECT )
+        if( (h->mb.i_neighbour & MB_TOP) && h->mb.i_mb_type_top != B_SKIP && h->mb.i_mb_type_top != B_DIRECT )
             ctx++;
 
         if( i_mb_type == B_DIRECT )
@@ -277,8 +277,8 @@ static void x264_cabac_mb_qp_delta( x264_t *h, x264_cabac_t *cb )
 #if !RDO_SKIP_BS
 void x264_cabac_mb_skip( x264_t *h, int b_skip )
 {
-    int ctx = (h->mb.i_mb_type_left >= 0 && !IS_SKIP( h->mb.i_mb_type_left ))
-            + (h->mb.i_mb_type_top >= 0 && !IS_SKIP( h->mb.i_mb_type_top ))
+    int ctx = ((h->mb.i_neighbour & MB_LEFT) && !IS_SKIP( h->mb.i_mb_type_left ))
+            + ((h->mb.i_neighbour & MB_TOP) && !IS_SKIP( h->mb.i_mb_type_top ))
             + (h->sh.i_type == SLICE_TYPE_P ? 11 : 24);
     x264_cabac_encode_decision( &h->cabac, ctx, b_skip );
 }



More information about the x264-devel mailing list