From ebbcdc9ac0ea190748a1605bda86ce84466c8b4e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 27 Feb 2003 22:56:07 +0000 Subject: [PATCH] user specified motion estimation range limit h263 me range fixed (was smaller then needed) Originally committed as revision 1610 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/avcodec.h | 13 +++++-- libavcodec/motion_est.c | 78 ++++++++++++++++++++--------------------- libavcodec/mpegvideo.c | 36 +++++++++---------- 3 files changed, 67 insertions(+), 60 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 0ca39ab936..2d3cec0494 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -16,8 +16,8 @@ extern "C" { #define LIBAVCODEC_VERSION_INT 0x000406 #define LIBAVCODEC_VERSION "0.4.6" -#define LIBAVCODEC_BUILD 4658 -#define LIBAVCODEC_BUILD_STR "4658" +#define LIBAVCODEC_BUILD 4659 +#define LIBAVCODEC_BUILD_STR "4659" enum CodecID { CODEC_ID_NONE, @@ -971,6 +971,15 @@ typedef struct AVCodecContext { #define FF_DTG_AFD_16_9_SP_14_9 14 #define FF_DTG_AFD_SP_4_3 15 + int me_range; + /** + * Maximum motion estimation search range in subpel units. + * if 0 then no limit + * + * encoding: set by user. + * decoding: unused. + */ + } AVCodecContext; //void avcodec_getopt(AVCodecContext* avctx, const char* str, avc_config_t** config); diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c index d49003e20d..36226d203d 100644 --- a/libavcodec/motion_est.c +++ b/libavcodec/motion_est.c @@ -791,18 +791,18 @@ static inline void set_p_mv_tables(MpegEncContext * s, int mx, int my, int mv4) } } -static inline void get_limits(MpegEncContext *s, int *range, int *xmin, int *ymin, int *xmax, int *ymax, int f_code) +/** + * get fullpel ME search limits. + * @param range the approximate search range for the old ME code, unused for EPZS and newer + */ +static inline void get_limits(MpegEncContext *s, int *range, int *xmin, int *ymin, int *xmax, int *ymax) { - *range = 8 * (1 << (f_code - 1)); - /* XXX: temporary kludge to avoid overflow for msmpeg4 */ - if (s->out_format == FMT_H263 && !s->h263_msmpeg4) - *range *= 2; + if(s->avctx->me_range) *range= s->avctx->me_range >> 1; + else *range= 16; if (s->unrestricted_mv) { *xmin = -16; *ymin = -16; - if (s->h263_plus) - *range *= 2; if(s->avctx->codec->id!=CODEC_ID_MPEG4){ *xmax = s->mb_width*16; *ymax = s->mb_height*16; @@ -816,6 +816,8 @@ static inline void get_limits(MpegEncContext *s, int *range, int *xmin, int *ymi *xmax = s->mb_width*16 - 16; *ymax = s->mb_height*16 - 16; } + + //FIXME try to limit x/y min/max if me_range is set } static inline int h263_mv4_search(MpegEncContext *s, int xmin, int ymin, int xmax, int ymax, int mx, int my, int shift) @@ -982,7 +984,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, s->me.sub_penalty_factor= get_penalty_factor(s, s->avctx->me_sub_cmp); s->me.mb_penalty_factor = get_penalty_factor(s, s->avctx->mb_cmp); - get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, s->f_code); + get_limits(s, &range, &xmin, &ymin, &xmax, &ymax); rel_xmin= xmin - mb_x*16; rel_xmax= xmax - mb_x*16; rel_ymin= ymin - mb_y*16; @@ -1151,7 +1153,7 @@ int ff_pre_estimate_p_frame_motion(MpegEncContext * s, s->me.pre_penalty_factor = get_penalty_factor(s, s->avctx->me_pre_cmp); - get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, s->f_code); + get_limits(s, &range, &xmin, &ymin, &xmax, &ymax); rel_xmin= xmin - mb_x*16; rel_xmax= xmax - mb_x*16; rel_ymin= ymin - mb_y*16; @@ -1212,7 +1214,7 @@ static int ff_estimate_motion_b(MpegEncContext * s, s->me.sub_penalty_factor= get_penalty_factor(s, s->avctx->me_sub_cmp); s->me.mb_penalty_factor = get_penalty_factor(s, s->avctx->mb_cmp); - get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, f_code); + get_limits(s, &range, &xmin, &ymin, &xmax, &ymax); rel_xmin= xmin - mb_x*16; rel_xmax= xmax - mb_x*16; rel_ymin= ymin - mb_y*16; @@ -1583,10 +1585,14 @@ int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type) void ff_fix_long_p_mvs(MpegEncContext * s) { const int f_code= s->f_code; - int y; - uint8_t * fcode_tab= s->fcode_tab; -//int clip=0; -//int noclip=0; + int y, range; + + range = (((s->codec_id == CODEC_ID_MPEG1VIDEO) ? 8 : 16) << f_code); + + if(s->msmpeg4_version) range= 16; + + if(s->avctx->me_range && range > s->avctx->me_range) range= s->avctx->me_range; + /* clip / convert to intra 16x16 type MVs */ for(y=0; ymb_height; y++){ int x; @@ -1594,10 +1600,8 @@ void ff_fix_long_p_mvs(MpegEncContext * s) int i= y*s->mb_width; for(x=0; xmb_width; x++){ if(s->mb_type[i]&MB_TYPE_INTER){ - if( fcode_tab[s->p_mv_table[xy][0] + MAX_MV] > f_code - || fcode_tab[s->p_mv_table[xy][0] + MAX_MV] == 0 - || fcode_tab[s->p_mv_table[xy][1] + MAX_MV] > f_code - || fcode_tab[s->p_mv_table[xy][1] + MAX_MV] == 0 ){ + if( s->p_mv_table[xy][0] >=range || s->p_mv_table[xy][0] <-range + || s->p_mv_table[xy][1] >=range || s->p_mv_table[xy][1] <-range){ s->mb_type[i] &= ~MB_TYPE_INTER; s->mb_type[i] |= MB_TYPE_INTRA; s->p_mv_table[xy][0] = 0; @@ -1629,10 +1633,8 @@ void ff_fix_long_p_mvs(MpegEncContext * s) int mx= s->motion_val[ xy + off ][0]; int my= s->motion_val[ xy + off ][1]; - if( fcode_tab[mx + MAX_MV] > f_code - || fcode_tab[mx + MAX_MV] == 0 - || fcode_tab[my + MAX_MV] > f_code - || fcode_tab[my + MAX_MV] == 0 ){ + if( mx >=range || mx <-range + || my >=range || my <-range){ s->mb_type[i] &= ~MB_TYPE_INTER4V; s->mb_type[i] |= MB_TYPE_INTRA; } @@ -1648,34 +1650,30 @@ void ff_fix_long_p_mvs(MpegEncContext * s) void ff_fix_long_b_mvs(MpegEncContext * s, int16_t (*mv_table)[2], int f_code, int type) { int y; - uint8_t * fcode_tab= s->fcode_tab; // RAL: 8 in MPEG-1, 16 in MPEG-4 int range = (((s->codec_id == CODEC_ID_MPEG1VIDEO) ? 8 : 16) << f_code); + + if(s->avctx->me_range && range > s->avctx->me_range) range= s->avctx->me_range; /* clip / convert to intra 16x16 type MVs */ for(y=0; ymb_height; y++){ int x; int xy= (y+1)* (s->mb_width+2)+1; int i= y*s->mb_width; - for(x=0; xmb_width; x++) - { - if (s->mb_type[i] & type) // RAL: "type" test added... - { - if (fcode_tab[mv_table[xy][0] + MAX_MV] > f_code || fcode_tab[mv_table[xy][0] + MAX_MV] == 0) - { - if(mv_table[xy][0]>0) - mv_table[xy][0]= range-1; - else - mv_table[xy][0]= -range; + for(x=0; xmb_width; x++){ + if (s->mb_type[i] & type){ // RAL: "type" test added... + if( mv_table[xy][0] >=range || mv_table[xy][0] <-range + || mv_table[xy][1] >=range || mv_table[xy][1] <-range){ + + if(s->codec_id == CODEC_ID_MPEG1VIDEO && 0){ + }else{ + if (mv_table[xy][0] > range-1) mv_table[xy][0]= range-1; + else if(mv_table[xy][0] < -range ) mv_table[xy][0]= -range; + if (mv_table[xy][1] > range-1) mv_table[xy][1]= range-1; + else if(mv_table[xy][1] < -range ) mv_table[xy][1]= -range; } - if (fcode_tab[mv_table[xy][1] + MAX_MV] > f_code || fcode_tab[mv_table[xy][1] + MAX_MV] == 0) - { - if(mv_table[xy][1]>0) - mv_table[xy][1]= range-1; - else - mv_table[xy][1]= -range; - } + } } xy++; i++; diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 63aedd6765..cbf859c104 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -2993,29 +2993,29 @@ static void encode_picture(MpegEncContext *s, int picture_number) //printf("Scene change detected, encoding as I Frame %d %d\n", s->current_picture.mb_var_sum, s->current_picture.mc_mb_var_sum); } - if(s->pict_type==P_TYPE || s->pict_type==S_TYPE) { - s->f_code= ff_get_best_fcode(s, s->p_mv_table, MB_TYPE_INTER); + if(s->codec_id != CODEC_ID_H263P){ //FIXME use umvplus or something + if(s->pict_type==P_TYPE || s->pict_type==S_TYPE) { + s->f_code= ff_get_best_fcode(s, s->p_mv_table, MB_TYPE_INTER); - // RAL: Next call moved into that bloc - ff_fix_long_p_mvs(s); - } + ff_fix_long_p_mvs(s); + } - // RAL: All this bloc changed - if(s->pict_type==B_TYPE){ - int a, b; + if(s->pict_type==B_TYPE){ + int a, b; - a = ff_get_best_fcode(s, s->b_forw_mv_table, MB_TYPE_FORWARD); - b = ff_get_best_fcode(s, s->b_bidir_forw_mv_table, MB_TYPE_BIDIR); - s->f_code = FFMAX(a, b); + a = ff_get_best_fcode(s, s->b_forw_mv_table, MB_TYPE_FORWARD); + b = ff_get_best_fcode(s, s->b_bidir_forw_mv_table, MB_TYPE_BIDIR); + s->f_code = FFMAX(a, b); - a = ff_get_best_fcode(s, s->b_back_mv_table, MB_TYPE_BACKWARD); - b = ff_get_best_fcode(s, s->b_bidir_back_mv_table, MB_TYPE_BIDIR); - s->b_code = FFMAX(a, b); + a = ff_get_best_fcode(s, s->b_back_mv_table, MB_TYPE_BACKWARD); + b = ff_get_best_fcode(s, s->b_bidir_back_mv_table, MB_TYPE_BIDIR); + s->b_code = FFMAX(a, b); - ff_fix_long_b_mvs(s, s->b_forw_mv_table, s->f_code, MB_TYPE_FORWARD); - ff_fix_long_b_mvs(s, s->b_back_mv_table, s->b_code, MB_TYPE_BACKWARD); - ff_fix_long_b_mvs(s, s->b_bidir_forw_mv_table, s->f_code, MB_TYPE_BIDIR); - ff_fix_long_b_mvs(s, s->b_bidir_back_mv_table, s->b_code, MB_TYPE_BIDIR); + ff_fix_long_b_mvs(s, s->b_forw_mv_table, s->f_code, MB_TYPE_FORWARD); + ff_fix_long_b_mvs(s, s->b_back_mv_table, s->b_code, MB_TYPE_BACKWARD); + ff_fix_long_b_mvs(s, s->b_bidir_forw_mv_table, s->f_code, MB_TYPE_BIDIR); + ff_fix_long_b_mvs(s, s->b_bidir_back_mv_table, s->b_code, MB_TYPE_BIDIR); + } } if (s->fixed_qscale)