Commit ebbcdc9a authored by Michael Niedermayer's avatar Michael Niedermayer
Browse files

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
parent 3a13f6bd
......@@ -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);
......
......@@ -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; y<s->mb_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; x<s->mb_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; y<s->mb_height; y++){
int x;
int xy= (y+1)* (s->mb_width+2)+1;
int i= y*s->mb_width;
for(x=0; x<s->mb_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; x<s->mb_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++;
......
......@@ -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)
......
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