]> granicus.if.org Git - libx264/commitdiff
improved mv prediction: 1-3% better compression of B-frames
authorLoren Merritt <pengvado@videolan.org>
Sat, 8 Jan 2005 02:51:24 +0000 (02:51 +0000)
committerLoren Merritt <pengvado@videolan.org>
Sat, 8 Jan 2005 02:51:24 +0000 (02:51 +0000)
early termination for B-frame ref search: up to 20% faster with lots of refs.

git-svn-id: svn://svn.videolan.org/x264/trunk@88 df754926-b1dd-0310-bc7b-ec298dee348c

common/macroblock.c
common/macroblock.h
encoder/analyse.c

index 6324713aa22a3c053e1d7dd3406053c707805834..a2f176fc154c48f68392d5a85999df93b527f90c 100644 (file)
@@ -524,11 +524,24 @@ void x264_mb_load_mv_direct8x8( x264_t *h, int idx )
 }
 
 /* This just improves encoder performance, it's not part of the spec */
-void x264_mb_predict_mv_ref16x16( x264_t *h, int i_list, int i_ref, int mvc[4][2], int *i_mvc )
+void x264_mb_predict_mv_ref16x16( x264_t *h, int i_list, int i_ref, int mvc[5][2], int *i_mvc )
 {
     int16_t (*mvr)[2] = h->mb.mvr[i_list][i_ref];
-
     int i = 0;
+
+    /* temporal */
+    if( h->sh.i_type == SLICE_TYPE_B )
+    {
+        if( h->mb.cache.ref[i_list][x264_scan8[12]] == i_ref )
+        {
+            int16_t *mvp = h->mb.cache.mv[i_list][x264_scan8[12]];
+            mvc[i][0] = mvp[0];
+            mvc[i][1] = mvp[1];
+            i++;
+        }
+    }
+
+    /* spatial */
     if( h->mb.i_mb_x > 0 )
     {
         int i_mb_l = h->mb.i_mb_xy - 1;
index 806585ba4e89dc53cd36bfcb2e05ce3d0bafb3f9..ec0b0ae465d094ccf91f4465e3c7952cdaf4060b 100644 (file)
@@ -184,7 +184,7 @@ void x264_mb_load_mv_direct8x8( x264_t *h, int idx );
  *      set mvc with D_16x16 prediction.
  *      uses all neighbors, even those that didn't end up using this ref.
  *      h->mb. need only valid values from other blocks */
-void x264_mb_predict_mv_ref16x16( x264_t *h, int i_list, int i_ref, int mvc[4][2], int *i_mvc );
+void x264_mb_predict_mv_ref16x16( x264_t *h, int i_list, int i_ref, int mvc[5][2], int *i_mvc );
 
 
 int  x264_mb_predict_intra4x4_mode( x264_t *h, int idx );
index 3d98f41b9a80954a65a00e42197cc55de79a0631..7b0d6b3a73a37049d81d7609f3db0a8832751134 100644 (file)
@@ -794,6 +794,9 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
 
     x264_me_t m;
     int i_ref;
+    int mvc[5][2], i_mvc;
+    int i_fullpel_thresh = INT_MAX;
+    int *p_fullpel_thresh = h->i_ref0>1 ? &i_fullpel_thresh : NULL;
 
     /* 16x16 Search on all ref frame */
     m.i_pixel = PIXEL_16x16;
@@ -809,7 +812,8 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
         /* search with ref */
         m.p_fref = h->mb.pic.p_fref[0][i_ref][0];
         x264_mb_predict_mv_16x16( h, 0, i_ref, m.mvp );
-        x264_me_search( h, &m, NULL, 0 );
+        x264_mb_predict_mv_ref16x16( h, 0, i_ref, mvc, &i_mvc );
+        x264_me_search_ref( h, &m, mvc, i_mvc, p_fullpel_thresh );
 
         /* add ref cost */
         m.cost += m.lm * bs_size_te( h->sh.i_num_ref_idx_l0_active - 1, i_ref );
@@ -819,18 +823,24 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
             a->l0.i_ref = i_ref;
             a->l0.me16x16 = m;
         }
+
+        /* save mv for predicting neighbors */
+        h->mb.mvr[0][i_ref][h->mb.i_mb_xy][0] = m.mv[0];
+        h->mb.mvr[0][i_ref][h->mb.i_mb_xy][1] = m.mv[1];
     }
     /* subtract ref cost, so we don't have to add it for the other MB types */
     a->l0.me16x16.cost -= m.lm * bs_size_te( h->sh.i_num_ref_idx_l0_active - 1, a->l0.i_ref );
 
     /* ME for list 1 */
+    /* not using fullpel_thresh since we don't yet do more than 1 list 1 ref */
     a->l1.me16x16.cost = INT_MAX;
     for( i_ref = 0; i_ref < h->i_ref1; i_ref++ )
     {
         /* search with ref */
         m.p_fref = h->mb.pic.p_fref[1][i_ref][0];
         x264_mb_predict_mv_16x16( h, 1, i_ref, m.mvp );
-        x264_me_search( h, &m, NULL, 0 );
+        x264_mb_predict_mv_ref16x16( h, 1, i_ref, mvc, &i_mvc );
+        x264_me_search( h, &m, mvc, i_mvc );
 
         /* add ref cost */
         m.cost += m.lm * bs_size_te( h->sh.i_num_ref_idx_l1_active - 1, i_ref );
@@ -840,6 +850,10 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
             a->l1.i_ref = i_ref;
             a->l1.me16x16 = m;
         }
+
+        /* save mv for predicting neighbors */
+        h->mb.mvr[1][i_ref][h->mb.i_mb_xy][0] = m.mv[0];
+        h->mb.mvr[1][i_ref][h->mb.i_mb_xy][1] = m.mv[1];
     }
     /* subtract ref cost, so we don't have to add it for the other MB types */
     a->l1.me16x16.cost -= m.lm * bs_size_te( h->sh.i_num_ref_idx_l1_active - 1, a->l1.i_ref );