[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