Commit 7d35ba6b authored by Loren Merritt's avatar Loren Merritt

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
parent 0c641421
......@@ -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;
......
......@@ -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;
......
......@@ -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 */
......
......@@ -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;
......
......@@ -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) */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment