[x264-devel] patch: switch to select ME method & range

Tuukka Toivonen tuukkat at ee.oulu.fi
Thu Mar 17 11:14:03 CET 2005


Here's a patch that adds two new switches:

+             "      --me <string>           Integer pixel motion estimation method [\"%s\"]\n"
+             "                                  - esa: exhaustive search algorithm (aka full search)\n"
+             "                                  - dia: diamond search\n"
+             "                                  - hex: hexagonal search\n"
+             "      --merange <integer>     Maximum motion vector search range [%d]\n"

It also adds new motion estimation method, exhaustive search algorithm 
(ESA).

With the patch, --subme no more selects between diamond/hexagonal 
integer pixel search as it used to be.

I'm not sure if you find this patch useful, as ESA is not so celebrated 
algorithm... but this could make a base for easy experimenting of different
ME methods. Also, ESA _does_ improve the encoding quality reducing bitrate 
at constant quality in average 4% [1], at low bitrates, making x264 pretty 
much on par with JM. It's just a bit slow.

Let me know what you think of it.

[1] I tested it with 6 standard CIF sequences, largest reduction was 10% 
with Stefan, worst case was something like 0.5% bitrate increase with
Mobile and calendar. I'm still running tests with larger videos.
At lowest bitrate I used QP=36 where the largest savings were obtained.
-------------- next part --------------
Index: encoder/me.c
===================================================================
--- encoder/me.c	(revision 177)
+++ encoder/me.c	(working copy)
@@ -60,6 +60,7 @@
 void x264_me_search_ref( x264_t *h, x264_me_t *m, int (*mvc)[2], int i_mvc, int *p_fullpel_thresh )
 {
     const int i_pixel = m->i_pixel;
+    const unsigned int i_me_range = h->param.analyse.i_me_range;
     const int b_chroma_me = h->mb.b_chroma_me && i_pixel <= PIXEL_8x8;
     int bmx, bmy, bcost;
     int omx, omy;
@@ -74,7 +75,6 @@
     const int16_t *p_cost_mvx = m->p_cost_mv - m->mvp[0];
     const int16_t *p_cost_mvy = m->p_cost_mv - m->mvp[1];
 
-
     /* init with mvp */
     /* XXX: We don't need to clamp because the way diamond work, we will
      * never go outside padded picture, and predict mv won't compute vector
@@ -99,13 +99,39 @@
     
     COST_MV( 0, 0 );
 
-    if( h->mb.i_subpel_refine >= 2 )
-    {
+    switch( h->param.analyse.i_me_method ) {
+    case X264_ME_ESA: {
+            const int min_x = X264_MAX(-i_me_range + bmx, mv_x_min);
+            const int min_y = X264_MAX(-i_me_range + bmy, mv_y_min);
+            const int max_x = X264_MIN( i_me_range + bmx, mv_x_max);
+            const int max_y = X264_MIN( i_me_range + bmy, mv_y_max);
+            for (omy=min_y; omy<=max_y; omy++) for (omx=min_x; omx<=max_x; omx++)
+            {
+                COST_MV( omx, omy );
+            }
+        }
+        break;
+    case X264_ME_DIA:
+        /* diamond search */
+        for( i_iter = 0; i_iter < i_me_range; i_iter++ )
+        {
+            omx = bmx;
+            omy = bmy;
+            COST_MV( omx  , omy-1 );
+            COST_MV( omx  , omy+1 );
+            COST_MV( omx-1, omy   );
+            COST_MV( omx+1, omy   );
+            if( bmx == omx && bmy == omy )
+                break;
+        }
+        break;
+    default:
+    case X264_ME_HEX:
         /* hexagon search */
         /* Don't need to test mv_range each time, we won't go outside picture+padding */
         omx = bmx;
         omy = bmy;
-        for( i_iter = 0; i_iter < 8; i_iter++ )
+        for( i_iter = 0; i_iter < i_me_range/2; i_iter++ )
         {
             COST_MV( omx-2, omy   );
             COST_MV( omx-1, omy+2 );
@@ -129,22 +155,8 @@
         COST_MV( omx+1, omy-1 );
         COST_MV( omx+1, omy   );
         COST_MV( omx+1, omy+1 );
+        break;
     }
-    else
-    {
-        /* diamond search */
-        for( i_iter = 0; i_iter < 16; i_iter++ )
-        {
-            omx = bmx;
-            omy = bmy;
-            COST_MV( omx  , omy-1 );
-            COST_MV( omx  , omy+1 );
-            COST_MV( omx-1, omy   );
-            COST_MV( omx+1, omy   );
-            if( bmx == omx && bmy == omy )
-                break;
-        }
-    }
 
     /* -> qpel mv */
     m->mv[0] = bmx << 2;
Index: x264.c
===================================================================
--- x264.c	(revision 177)
+++ x264.c	(working copy)
@@ -169,6 +169,11 @@
              "      --direct <string>       Direct MV prediction mode [\"temporal\"]\n"
              "                                  - none, spatial, temporal\n"
              "  -w, --weightb               Weighted prediction for B-frames\n"
+             "      --me <string>           Integer pixel motion estimation method [\"%s\"]\n"
+             "                                  - esa: exhaustive search algorithm (aka full search)\n"
+             "                                  - dia: diamond search\n"
+             "                                  - hex: hexagonal search\n"
+             "      --merange <integer>     Maximum motion vector search range [%d]\n"
              "  -m, --subme <integer>       Subpixel motion estimation quality: 1=fast, 5=best. [%d]\n"
              "\n"
              "      --level <integer>       Specify IDC level\n"
@@ -205,6 +210,10 @@
             defaults->rc.f_qcompress,
             defaults->rc.f_complexity_blur,
             defaults->rc.f_qblur,
+            defaults->analyse.i_me_method==X264_ME_ESA ? "esa" :
+              defaults->analyse.i_me_method==X264_ME_DIA ? "dia" :
+              defaults->analyse.i_me_method==X264_ME_HEX ? "hex" : NULL,
+            defaults->analyse.i_me_range,
             defaults->analyse.i_subpel_refine
            );
 }
@@ -263,6 +272,8 @@
 #define OPT_CHROMA_QP 280
 #define OPT_NO_CHROMA_ME 281
 #define OPT_NO_CABAC 282
+#define OPT_ME 283
+#define OPT_MERANGE 284
 
         static struct option long_options[] =
         {
@@ -291,6 +302,8 @@
             { "analyse", required_argument, NULL, 'A' },
             { "direct",  required_argument, NULL, OPT_DIRECT },
             { "weightb", no_argument,       NULL, 'w' },
+            { "me",      required_argument, NULL, OPT_ME },
+            { "merange", required_argument, NULL, OPT_MERANGE },
             { "subme",   required_argument, NULL, 'm' },
             { "no-chroma-me", no_argument,  NULL, OPT_NO_CHROMA_ME },
             { "level",   required_argument, NULL, OPT_LEVEL },
@@ -451,6 +464,22 @@
             case 'w':
                 param->analyse.b_weighted_bipred = 1;
                 break;
+            case OPT_ME:
+                if( strstr( optarg, "esa" ) )
+                    param->analyse.i_me_method = X264_ME_ESA;
+                else if( strstr( optarg, "dia" ) )
+                    param->analyse.i_me_method = X264_ME_DIA;
+                else if( strstr( optarg, "hex" ) )
+                    param->analyse.i_me_method = X264_ME_HEX;
+                else
+                {
+                    fprintf( stderr, "bad me method `%s'\n", optarg );
+                    return -1;
+                }
+                break;
+            case OPT_MERANGE:
+                param->analyse.i_me_range = atoi(optarg);
+                break;
             case 'm':
                 param->analyse.i_subpel_refine = atoi(optarg);
                 break;
Index: common/common.c
===================================================================
--- common/common.c	(revision 177)
+++ common/common.c	(working copy)
@@ -105,6 +105,8 @@
     param->analyse.intra = X264_ANALYSE_I4x4;
     param->analyse.inter = X264_ANALYSE_I4x4 | X264_ANALYSE_PSUB16x16 | X264_ANALYSE_BSUB16x16;
     param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_TEMPORAL;
+    param->analyse.i_me_method = X264_ME_HEX;
+    param->analyse.i_me_range = 16;
     param->analyse.i_subpel_refine = 5;
     param->analyse.b_chroma_me = 1;
     param->analyse.i_mv_range = 512;
Index: x264.h
===================================================================
--- x264.h	(revision 177)
+++ x264.h	(working copy)
@@ -54,6 +54,9 @@
 #define X264_DIRECT_PRED_NONE        0
 #define X264_DIRECT_PRED_SPATIAL     1
 #define X264_DIRECT_PRED_TEMPORAL    2
+#define X264_ME_ESA                  0
+#define X264_ME_DIA                  1
+#define X264_ME_HEX                  2
 
 /* Colorspace type
  */
@@ -140,6 +143,8 @@
         unsigned int inter;     /* inter flags */
 
         int          i_direct_mv_pred; /* spatial vs temporal mv prediction */
+        int          i_me_method; /* motion estimation algorithm to use (X264_ME_*) */
+        int          i_me_range; /* integer pixel motion estimation search range (not just upper limit as i_mv_range) */
         int          i_subpel_refine; /* subpixel motion estimation quality */
         int          b_chroma_me; /* chroma ME for subpel and mode decision in P-frames */
         int          i_mv_range; /* maximum length of a mv (in pixels) */


More information about the x264-devel mailing list