From 7d35ba6bf080610d8f144f4270e961c69ba14f1c Mon Sep 17 00:00:00 2001 From: Loren Merritt <pengvado@videolan.org> Date: Tue, 19 Apr 2005 08:45:36 +0000 Subject: [PATCH] Allow manual selection of fullpel ME method. New method: Exhaustive search. based on a patch by Tuukka Toivonen. git-svn-id: svn://svn.videolan.org/x264/trunk@211 df754926-b1dd-0310-bc7b-ec298dee348c --- common/common.c | 2 ++ encoder/encoder.c | 8 ++++++++ encoder/me.c | 46 ++++++++++++++++++++++++++++++---------------- x264.c | 29 +++++++++++++++++++++++++++++ x264.h | 7 ++++++- 5 files changed, 75 insertions(+), 17 deletions(-) diff --git a/common/common.c b/common/common.c index a586c39d..4bce6563 100644 --- a/common/common.c +++ b/common/common.c @@ -105,6 +105,8 @@ void x264_param_default( x264_param_t *param ) 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; diff --git a/encoder/encoder.c b/encoder/encoder.c index cceb8e0a..39c5f1cf 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -390,6 +390,14 @@ x264_t *x264_encoder_open ( x264_param_t *param ) h->param.i_cabac_init_idc = x264_clip3( h->param.i_cabac_init_idc, -1, 2 ); + if( h->param.analyse.i_me_method != X264_ME_DIA && + h->param.analyse.i_me_method != X264_ME_HEX && + h->param.analyse.i_me_method != X264_ME_ESA ) + h->param.analyse.i_me_method = X264_ME_HEX; + if( h->param.analyse.i_me_range < 2 ) + h->param.analyse.i_me_range = 2; + if( h->param.analyse.i_me_range > 16 && h->param.analyse.i_me_method != X264_ME_ESA ) + h->param.analyse.i_me_range = 16; h->param.analyse.i_subpel_refine = x264_clip3( h->param.analyse.i_subpel_refine, 1, 5 ); if( h->param.analyse.inter & X264_ANALYSE_PSUB8x8 ) h->param.analyse.inter |= X264_ANALYSE_PSUB16x16; diff --git a/encoder/me.c b/encoder/me.c index d343b2ac..d5e6d2bf 100644 --- a/encoder/me.c +++ b/encoder/me.c @@ -60,6 +60,7 @@ static void refine_subpel( x264_t *h, x264_me_t *m, int hpel_iters, int qpel_ite 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; @@ -99,13 +100,27 @@ void x264_me_search_ref( x264_t *h, x264_me_t *m, int (*mvc)[2], int i_mvc, int COST_MV( 0, 0 ); - if( h->mb.i_subpel_refine >= 2 ) - { + switch( h->param.analyse.i_me_method ) { + 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; + 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,21 +144,20 @@ void x264_me_search_ref( x264_t *h, x264_me_t *m, int (*mvc)[2], int i_mvc, int COST_MV( omx+1, omy-1 ); COST_MV( omx+1, omy ); COST_MV( omx+1, omy+1 ); - } - else - { - /* diamond search */ - for( i_iter = 0; i_iter < 16; i_iter++ ) + break; + case X264_ME_ESA: { - 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; + const int min_x = X264_MAX( bmx - i_me_range, mv_x_min-8); + const int min_y = X264_MAX( bmy - i_me_range, mv_y_min-8); + const int max_x = X264_MIN( bmx + i_me_range, mv_x_max+8); + const int max_y = X264_MIN( bmy + i_me_range, mv_y_max+8); + for( omy = min_y; omy <= max_y; omy++ ) + for( omx = min_x; omx <= max_x; omx++ ) + { + COST_MV( omx, omy ); + } } + break; } /* -> qpel mv */ diff --git a/x264.c b/x264.c index 3ffb9c11..dfe0b9e5 100644 --- a/x264.c +++ b/x264.c @@ -205,6 +205,11 @@ static void Help( x264_param_t *defaults ) " --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" + " - dia: diamond search, radius 1 (fast)\n" + " - hex: hexagonal search, radius 2\n" + " - esa: exhaustive search algorithm (slow)\n" + " --merange <integer> Maximum motion vector search range [%d]\n" " -m, --subme <integer> Subpixel motion estimation quality: 1=fast, 5=best. [%d]\n" " --no-chroma-me Ignore chroma in motion estimation\n" "\n" @@ -255,6 +260,10 @@ static void Help( x264_param_t *defaults ) defaults->rc.f_qcompress, defaults->rc.f_complexity_blur, defaults->rc.f_qblur, + defaults->analyse.i_me_method==X264_ME_DIA ? "dia" + : defaults->analyse.i_me_method==X264_ME_HEX ? "hex" + : defaults->analyse.i_me_method==X264_ME_ESA ? "esa" : NULL, + defaults->analyse.i_me_range, defaults->analyse.i_subpel_refine ); } @@ -323,6 +332,8 @@ static int Parse( int argc, char **argv, #define OPT_NO_CABAC 282 #define OPT_AUD 283 #define OPT_PROGRESS 284 +#define OPT_ME 285 +#define OPT_MERANGE 286 static struct option long_options[] = { @@ -351,6 +362,8 @@ static int Parse( int argc, char **argv, { "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 }, @@ -529,6 +542,22 @@ static int Parse( int argc, char **argv, case 'w': param->analyse.b_weighted_bipred = 1; break; + case OPT_ME: + 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 if( strstr( optarg, "esa" ) ) + param->analyse.i_me_method = X264_ME_ESA; + 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; diff --git a/x264.h b/x264.h index f7d9d181..8d61ad6c 100644 --- a/x264.h +++ b/x264.h @@ -26,7 +26,7 @@ #include <stdarg.h> -#define X264_BUILD 22 +#define X264_BUILD 23 /* x264_t: * opaque handler for decoder and encoder */ @@ -54,6 +54,9 @@ typedef struct x264_t x264_t; #define X264_DIRECT_PRED_NONE 0 #define X264_DIRECT_PRED_SPATIAL 1 #define X264_DIRECT_PRED_TEMPORAL 2 +#define X264_ME_DIA 0 +#define X264_ME_HEX 1 +#define X264_ME_ESA 2 /* Colorspace type */ @@ -140,6 +143,8 @@ typedef struct 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 (from predicted mv) */ 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) */ -- 2.40.0