[x264-devel] MBAFF: Track what interlace decision the decoder is using

Simon Horlick git at videolan.org
Thu May 12 08:39:00 CEST 2011


x264 | branch: master | Simon Horlick <simonhorlick at gmail.com> | Sun Feb 20 15:31:55 2011 +0000| [cf58ce08a9121967048a4d5fee68183c7f8f6d32] | committer: Jason Garrett-Glaser

MBAFF: Track what interlace decision the decoder is using

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

 common/common.h     |    3 ++-
 common/macroblock.c |   12 ++++++++----
 encoder/cabac.c     |   18 +++++++++++++++++-
 encoder/encoder.c   |    1 +
 4 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/common/common.h b/common/common.h
index 6706e3a..263f994 100644
--- a/common/common.h
+++ b/common/common.h
@@ -623,8 +623,10 @@ struct x264_t
         int     i_mb_topleft_y;
         int     i_mb_topright_y;
         x264_left_table_t *left_index_table;
+        int     i_mb_top_mbpair_xy;
         int     topleft_partition;
         int     b_allow_skip;
+        int     field_decoding_flag;
 
         /**** thread synchronization ends here ****/
         /* subsequent variables are either thread-local or constant,
@@ -748,7 +750,6 @@ struct x264_t
 
             /* number of neighbors (top and left) that used 8x8 dct */
             int     i_neighbour_transform_size;
-            int     i_neighbour_interlaced;
 
             /* neighbor CBPs */
             int     i_cbp_top;
diff --git a/common/macroblock.c b/common/macroblock.c
index 3ee8ca6..d8e95ca 100644
--- a/common/macroblock.c
+++ b/common/macroblock.c
@@ -458,7 +458,7 @@ void x264_macroblock_thread_init( x264_t *h )
                          (h->sh.i_type == SLICE_TYPE_B && h->mb.i_subpel_refine >= 9));
     h->mb.b_dct_decimate = h->sh.i_type == SLICE_TYPE_B ||
                           (h->param.analyse.b_dct_decimate && h->sh.i_type != SLICE_TYPE_I);
-
+    h->mb.i_mb_prev_xy = -1;
 
     /* fdec:      fenc:
      * yyyyyyy
@@ -623,6 +623,7 @@ static void inline x264_macroblock_cache_load_neighbours( x264_t *h, int mb_x, i
     h->mb.i_mb_topright_xy = -1;
     h->mb.i_mb_topleft_y = -1;
     h->mb.i_mb_topright_y = -1;
+    h->mb.i_mb_top_mbpair_xy = h->mb.i_mb_xy - 2*h->mb.i_mb_stride;
     h->mb.i_mb_type_top = -1;
     h->mb.i_mb_type_left[0] = h->mb.i_mb_type_left[1] = -1;
     h->mb.i_mb_type_topleft = -1;
@@ -884,9 +885,6 @@ void x264_macroblock_cache_load( x264_t *h, int mb_x, int mb_y )
     {
         h->mb.pic.i_fref[0] = h->i_ref[0] << h->mb.b_interlaced;
         h->mb.pic.i_fref[1] = h->i_ref[1] << h->mb.b_interlaced;
-        h->mb.cache.i_neighbour_interlaced =
-            !!(h->mb.i_neighbour & MB_LEFT && h->mb.field[left[0]])
-          + !!(h->mb.i_neighbour & MB_TOP && h->mb.field[top]);
     }
 
     if( !h->param.b_interlaced )
@@ -1109,11 +1107,17 @@ void x264_macroblock_cache_load( x264_t *h, int mb_x, int mb_y )
         }
     }
 
+    if( h->sh.b_mbaff && mb_x == 0 && !(mb_y&1) && mb_y > 0 )
+        h->mb.field_decoding_flag = h->mb.field[h->mb.i_mb_xy - h->mb.i_mb_stride];
+
     /* Check whether skip here would cause decoder to predict interlace mode incorrectly.
      * FIXME: It might be better to change the interlace type rather than forcing a skip to be non-skip. */
     h->mb.b_allow_skip = 1;
     if( h->sh.b_mbaff )
     {
+        if( h->mb.b_interlaced != h->mb.field_decoding_flag &&
+            h->mb.i_mb_prev_xy >= 0 && IS_SKIP(h->mb.type[h->mb.i_mb_prev_xy]) )
+            h->mb.b_allow_skip = 0;
         if( (mb_y&1) && IS_SKIP(h->mb.type[h->mb.i_mb_xy - h->mb.i_mb_stride]) )
         {
             if( h->mb.i_neighbour & MB_LEFT )
diff --git a/encoder/cabac.c b/encoder/cabac.c
index 8c9f060..02dcedd 100644
--- a/encoder/cabac.c
+++ b/encoder/cabac.c
@@ -66,15 +66,31 @@ static inline void x264_cabac_mb_type_intra( x264_t *h, x264_cabac_t *cb, int i_
     }
 }
 
+#if !RDO_SKIP_BS
+static void x264_cabac_field_decoding_flag( x264_t *h, x264_cabac_t *cb )
+{
+    int ctx = 0;
+    ctx += h->mb.field_decoding_flag & !!h->mb.i_mb_x;
+    ctx += (h->mb.i_mb_top_mbpair_xy >= 0
+            && h->mb.slice_table[h->mb.i_mb_top_mbpair_xy] == h->sh.i_first_mb
+            && h->mb.field[h->mb.i_mb_top_mbpair_xy]);
+
+    x264_cabac_encode_decision_noup( cb, 70 + ctx, h->mb.b_interlaced );
+    h->mb.field_decoding_flag = h->mb.b_interlaced;
+}
+#endif
+
 static void x264_cabac_mb_type( x264_t *h, x264_cabac_t *cb )
 {
     const int i_mb_type = h->mb.i_type;
 
+#if !RDO_SKIP_BS
     if( h->sh.b_mbaff &&
         (!(h->mb.i_mb_y & 1) || IS_SKIP(h->mb.type[h->mb.i_mb_xy - h->mb.i_mb_stride])) )
     {
-        x264_cabac_encode_decision_noup( cb, 70 + h->mb.cache.i_neighbour_interlaced, h->mb.b_interlaced );
+        x264_cabac_field_decoding_flag( h, cb );
     }
+#endif
 
     if( h->sh.i_type == SLICE_TYPE_I )
     {
diff --git a/encoder/encoder.c b/encoder/encoder.c
index 476687a..4232a45 100644
--- a/encoder/encoder.c
+++ b/encoder/encoder.c
@@ -2015,6 +2015,7 @@ static int x264_slice_write( x264_t *h )
         last_emu_check = h->out.bs.p;
     h->mb.i_last_qp = h->sh.i_qp;
     h->mb.i_last_dqp = 0;
+    h->mb.field_decoding_flag = 0;
 
     i_mb_y = h->sh.i_first_mb / h->mb.i_mb_width;
     i_mb_x = h->sh.i_first_mb % h->mb.i_mb_width;



More information about the x264-devel mailing list