[x264-devel] commit: Use low-resolution lookahead motion vectors as an extra predictor ( Jason Garrett-Glaser )

git version control git at videolan.org
Wed Sep 17 09:56:53 CEST 2008


x264 | branch: master | Jason Garrett-Glaser <darkshikari at gmail.com> | Wed Sep 17 00:33:37 2008 -0700| [6d4af8d257162ac8881a0f96d9552eb928328d95] | committer: Jason Garrett-Glaser 

Use low-resolution lookahead motion vectors as an extra predictor
Improves quality considerably (0-5%) in 1pass/CRF mode, especially with lower --me values and complex motion.
Reverses the order of lowres lookahead search to improve the usefulness of the extra predictors.

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

 common/macroblock.c |    9 ++++++++-
 encoder/analyse.c   |    4 ++--
 encoder/slicetype.c |   29 ++++++++++++++++-------------
 3 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/common/macroblock.c b/common/macroblock.c
index f194ede..115ae4e 100644
--- a/common/macroblock.c
+++ b/common/macroblock.c
@@ -416,7 +416,7 @@ 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, int16_t mvc[8][2], int *i_mvc )
+void x264_mb_predict_mv_ref16x16( x264_t *h, int i_list, int i_ref, int16_t mvc[9][2], int *i_mvc )
 {
     int16_t (*mvr)[2] = h->mb.mvr[i_list][i_ref];
     int i = 0;
@@ -433,6 +433,13 @@ void x264_mb_predict_mv_ref16x16( x264_t *h, int i_list, int i_ref, int16_t mvc[
         SET_MVP( h->mb.cache.mv[i_list][x264_scan8[12]] );
     }
 
+    if( i_ref == 0 && h->frames.b_have_lowres )
+    {
+        int16_t (*lowres_mv)[2] = i_list ? h->fenc->lowres_mvs[1][h->fref1[0]->i_frame-h->fenc->i_frame-1]
+                                         : h->fenc->lowres_mvs[0][h->fenc->i_frame-h->fref0[0]->i_frame-1];
+        if( lowres_mv[0][0] != 0x7fff ) *(uint32_t*)mvc[i++] = (*(uint32_t*)lowres_mv[h->mb.i_mb_xy]*2)&0xfffeffff;
+    }
+
     /* spatial predictors */
     if( h->mb.i_neighbour & MB_LEFT )
     {
diff --git a/encoder/analyse.c b/encoder/analyse.c
index 2a294ff..ecbaf4e 100644
--- a/encoder/analyse.c
+++ b/encoder/analyse.c
@@ -1016,7 +1016,7 @@ static void x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a )
 {
     x264_me_t m;
     int i_ref, i_mvc;
-    DECLARE_ALIGNED_4( int16_t mvc[7][2] );
+    DECLARE_ALIGNED_4( int16_t mvc[8][2] );
     int i_halfpel_thresh = INT_MAX;
     int *p_halfpel_thresh = h->mb.pic.i_fref[0]>1 ? &i_halfpel_thresh : NULL;
 
@@ -1493,7 +1493,7 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
 
     x264_me_t m;
     int i_ref, i_mvc;
-    DECLARE_ALIGNED_4( int16_t mvc[8][2] );
+    DECLARE_ALIGNED_4( int16_t mvc[9][2] );
     int i_halfpel_thresh = INT_MAX;
     int *p_halfpel_thresh = h->mb.pic.i_fref[0]>1 ? &i_halfpel_thresh : NULL;
 
diff --git a/encoder/slicetype.c b/encoder/slicetype.c
index fd06d41..04034f1 100644
--- a/encoder/slicetype.c
+++ b/encoder/slicetype.c
@@ -150,16 +150,17 @@ static int x264_slicetype_mb_cost( x264_t *h, x264_mb_analysis_t *a,
 
         if( do_search[l] )
         {
+            /* Reverse-order MV prediction. */
 #define MVC(mv) { *(uint32_t*)mvc[i_mvc] = *(uint32_t*)mv; i_mvc++; }
-            if( i_mb_x > 0 )
-                MVC(fenc_mv[-1]);
-            if( i_mb_y > 0 )
+            if( i_mb_x < h->sps->i_mb_width - 1 )
+                MVC(fenc_mv[1]);
+            if( i_mb_y < h->sps->i_mb_height - 1 )
             {
-                MVC(fenc_mv[-i_mb_stride]);
-                if( i_mb_x < h->sps->i_mb_width - 1 )
-                    MVC(fenc_mv[-i_mb_stride+1]);
+                MVC(fenc_mv[i_mb_stride]);
                 if( i_mb_x > 0 )
-                    MVC(fenc_mv[-i_mb_stride-1]);
+                    MVC(fenc_mv[i_mb_stride-1]);
+                if( i_mb_x < h->sps->i_mb_width - 1 )
+                    MVC(fenc_mv[i_mb_stride+1]);
             }
 #undef MVC
             x264_median_mv( m[l].mvp, mvc[0], mvc[1], mvc[2] );
@@ -288,20 +289,22 @@ static int x264_slicetype_frame_cost( x264_t *h, x264_mb_analysis_t *a,
         if( p1 != p0 )
             dist_scale_factor = ( ((b-p0) << 8) + ((p1-p0) >> 1) ) / (p1-p0);
 
+        /* Lowres lookahead goes backwards because the MVs are used as predictors in the main encode. */
+        /* This considerably improves MV prediction overall. */
         if( h->sps->i_mb_width <= 2 || h->sps->i_mb_height <= 2 )
         {
-            for( h->mb.i_mb_y = 0; h->mb.i_mb_y < h->sps->i_mb_height; h->mb.i_mb_y++ )
-                for( h->mb.i_mb_x = 0; h->mb.i_mb_x < h->sps->i_mb_width; h->mb.i_mb_x++ )
+            for( h->mb.i_mb_y = h->sps->i_mb_height - 1; h->mb.i_mb_y >= 0 ; h->mb.i_mb_y-- )
+                for( h->mb.i_mb_x = h->sps->i_mb_width - 1; h->mb.i_mb_x >= 0 ; h->mb.i_mb_x-- )
                     i_score += x264_slicetype_mb_cost( h, a, frames, p0, p1, b, dist_scale_factor, do_search );
         }
         /* the edge mbs seem to reduce the predictive quality of the
          * whole frame's score, but are needed for a spatial distribution. */
         else if( h->param.rc.i_vbv_buffer_size )
         {
-            for( h->mb.i_mb_y = 0; h->mb.i_mb_y < h->sps->i_mb_height; h->mb.i_mb_y++ )
+            for( h->mb.i_mb_y = h->sps->i_mb_height - 1; h->mb.i_mb_y >= 0; h->mb.i_mb_y-- )
             {
                 row_satd[ h->mb.i_mb_y ] = 0;
-                for( h->mb.i_mb_x = 0; h->mb.i_mb_x < h->sps->i_mb_width; h->mb.i_mb_x++ )
+                for( h->mb.i_mb_x = h->sps->i_mb_width - 1; h->mb.i_mb_x >= 0; h->mb.i_mb_x-- )
                 {
                     int i_mb_cost = x264_slicetype_mb_cost( h, a, frames, p0, p1, b, dist_scale_factor, do_search );
                     int i_mb_cost_aq = i_mb_cost;
@@ -323,8 +326,8 @@ static int x264_slicetype_frame_cost( x264_t *h, x264_mb_analysis_t *a,
         }
         else
         {
-            for( h->mb.i_mb_y = 1; h->mb.i_mb_y < h->sps->i_mb_height - 1; h->mb.i_mb_y++ )
-                for( h->mb.i_mb_x = 1; h->mb.i_mb_x < h->sps->i_mb_width - 1; h->mb.i_mb_x++ )
+            for( h->mb.i_mb_y = h->sps->i_mb_height - 2; h->mb.i_mb_y > 0; h->mb.i_mb_y-- )
+                for( h->mb.i_mb_x = h->sps->i_mb_width - 2; h->mb.i_mb_x > 0; h->mb.i_mb_x-- )
                 {
                     int i_mb_cost = x264_slicetype_mb_cost( h, a, frames, p0, p1, b, dist_scale_factor, do_search );
                     int i_mb_cost_aq = i_mb_cost;



More information about the x264-devel mailing list