diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2002-03-22 23:22:08 +0000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2002-03-22 23:22:08 +0000 |
commit | 11ce88346b1ae4da21b581baf1b4eb784d842547 (patch) | |
tree | bffaf9c06980445db1dc0cf44399526faee72316 | |
parent | c5b1c10a0e1ed783674b24d787797ffba9bdffc0 (diff) | |
download | ffmpeg-11ce88346b1ae4da21b581baf1b4eb784d842547.tar.gz |
mpeg4 aspect_ratio_info in AVCodecContext (requested by alex)
experimental (& faster) motion estimation
squished a dirty uninitialized var bug
mpeg1 fcode>1 support
Originally committed as revision 349 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | libavcodec/avcodec.h | 1 | ||||
-rw-r--r-- | libavcodec/h263.c | 7 | ||||
-rw-r--r-- | libavcodec/h263dec.c | 1 | ||||
-rw-r--r-- | libavcodec/motion_est.c | 119 | ||||
-rw-r--r-- | libavcodec/mpeg12.c | 50 | ||||
-rw-r--r-- | libavcodec/mpegvideo.c | 7 | ||||
-rw-r--r-- | libavcodec/mpegvideo.h | 1 |
7 files changed, 173 insertions, 13 deletions
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index d3ddf92a78..15b8f900cc 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -81,6 +81,7 @@ typedef struct AVCodecContext { /* video only */ int frame_rate; /* frames per sec multiplied by FRAME_RATE_BASE */ int width, height; + int aspect_ratio_info; int gop_size; /* 0 = intra only */ int pix_fmt; /* pixel format, see PIX_FMT_xxx */ diff --git a/libavcodec/h263.c b/libavcodec/h263.c index 60baedb47f..c4110726ad 100644 --- a/libavcodec/h263.c +++ b/libavcodec/h263.c @@ -781,7 +781,10 @@ static void mpeg4_encode_vol_header(MpegEncContext * s) put_bits(&s->pb, 1, 1); /* is obj layer id= yes */ put_bits(&s->pb, 4, vo_ver_id); /* is obj layer ver id */ put_bits(&s->pb, 3, 1); /* is obj layer priority */ - put_bits(&s->pb, 4, 1); /* aspect ratio info= sqare pixel */ //FIXME real aspect + if(s->aspect_ratio_info) + put_bits(&s->pb, 4, s->aspect_ratio_info);/* aspect ratio info */ + else + put_bits(&s->pb, 4, 1); /* aspect ratio info= sqare pixel */ put_bits(&s->pb, 1, 0); /* vol control parameters= no */ put_bits(&s->pb, 2, RECT_SHAPE); /* vol shape= rectangle */ put_bits(&s->pb, 1, 1); /* marker bit */ @@ -2149,6 +2152,7 @@ int mpeg4_decode_picture_header(MpegEncContext * s) skip_bits(&s->gb, 8); //par_width skip_bits(&s->gb, 8); // par_height } + if(get_bits1(&s->gb)){ /* vol control parameter */ printf("vol control parameter not supported\n"); return -1; @@ -2388,7 +2392,6 @@ int mpeg4_decode_picture_header(MpegEncContext * s) //printf("b-code %d\n", s->b_code); } //printf("quant:%d fcode:%d\n", s->qscale, s->f_code); - if(!s->scalability){ if (s->shape!=RECT_SHAPE && s->pict_type!=I_TYPE) { skip_bits1(&s->gb); // vop shape coding type diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 8a80af6bb0..aa822800bd 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -123,6 +123,7 @@ static int h263_decode_frame(AVCodecContext *avctx, if (!s->context_initialized) { avctx->width = s->width; avctx->height = s->height; + avctx->aspect_ratio_info= s->aspect_ratio_info; if (MPV_common_init(s) < 0) return -1; } else if (s->width != avctx->width || s->height != avctx->height) { diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c index f1dfc9f9e8..dc9b3066d0 100644 --- a/libavcodec/motion_est.c +++ b/libavcodec/motion_est.c @@ -335,13 +335,15 @@ static int phods_motion_search(MpegEncContext * s, #define Z_THRESHOLD 256 #define CHECK_MV(x,y)\ +{\ d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\ d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\ if(d<dmin){\ best[0]=x;\ best[1]=y;\ dmin=d;\ - } + }\ +} #define CHECK_MV_DIR(x,y,new_dir)\ {\ @@ -355,6 +357,13 @@ static int phods_motion_search(MpegEncContext * s, }\ } +#define check(x,y,S,v)\ +if( (x)<(xmin<<(S)) ) printf("%d %d %d %d xmin" #v, (x), (y), s->mb_x, s->mb_y);\ +if( (x)>(xmax<<(S)) ) printf("%d %d %d %d xmax" #v, (x), (y), s->mb_x, s->mb_y);\ +if( (y)<(ymin<<(S)) ) printf("%d %d %d %d ymin" #v, (x), (y), s->mb_x, s->mb_y);\ +if( (y)>(ymax<<(S)) ) printf("%d %d %d %d ymax" #v, (x), (y), s->mb_x, s->mb_y);\ + + static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin, UINT8 *new_pic, UINT8 *old_pic, int pic_stride, int pred_x, int pred_y, UINT16 *mv_penalty, int quant, @@ -379,6 +388,91 @@ static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin, return dmin; } } + +/* for(;;){ + int d; + const int x= best[0]; + const int y= best[1]; + const int last_min=dmin; + if(x>xmin) CHECK_MV(x-1, y ) + if(y>xmin) CHECK_MV(x , y-1) + if(x<xmax) CHECK_MV(x+1, y ) + if(y<xmax) CHECK_MV(x , y+1) + if(x>xmin && y>ymin) CHECK_MV(x-1, y-1) + if(x>xmin && y<ymax) CHECK_MV(x-1, y+1) + if(x<xmax && y>ymin) CHECK_MV(x+1, y-1) + if(x<xmax && y<ymax) CHECK_MV(x+1, y+1) + if(x-1>xmin) CHECK_MV(x-2, y ) + if(y-1>xmin) CHECK_MV(x , y-2) + if(x+1<xmax) CHECK_MV(x+2, y ) + if(y+1<xmax) CHECK_MV(x , y+2) + if(x-1>xmin && y-1>ymin) CHECK_MV(x-2, y-2) + if(x-1>xmin && y+1<ymax) CHECK_MV(x-2, y+2) + if(x+1<xmax && y-1>ymin) CHECK_MV(x+2, y-2) + if(x+1<xmax && y+1<ymax) CHECK_MV(x+2, y+2) + if(dmin==last_min) return dmin; + } + */ +} + +static inline int snake_search(MpegEncContext * s, int *best, int dmin, + UINT8 *new_pic, UINT8 *old_pic, int pic_stride, + int pred_x, int pred_y, UINT16 *mv_penalty, int quant, + int xmin, int ymin, int xmax, int ymax, int shift) +{ + int dir=0; + int c=1; + static int x_dir[8]= {1,1,0,-1,-1,-1, 0, 1}; + static int y_dir[8]= {0,1,1, 1, 0,-1,-1,-1}; + int fails=0; + int last_d[2]={dmin, dmin}; + +/*static int good=0; +static int bad=0; +static int point=0; + +point++; +if(256*256*256*64%point==0) +{ + printf("%d %d %d\n", good, bad, point); +}*/ + + for(;;){ + int x= best[0]; + int y= best[1]; + int d; + x+=x_dir[dir]; + y+=y_dir[dir]; + if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){ + d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16); + d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant; + }else{ + d = dmin + 10000; //FIXME smarter boundary handling + } + if(d<dmin){ + best[0]=x; + best[1]=y; + dmin=d; + + if(last_d[1] - last_d[0] > last_d[0] - d) c= -c; + dir+=c; + + fails=0; +//good++; + last_d[1]=last_d[0]; + last_d[0]=d; + }else{ +//bad++; + if(fails){ + if(fails>=3) return dmin; + }else{ + c= -c; + } + dir+=c*2; + fails++; + } + dir&=7; + } } static int epzs_motion_search(MpegEncContext * s, @@ -397,8 +491,7 @@ static int epzs_motion_search(MpegEncContext * s, new_pic = s->new_picture[0] + pic_xy; old_pic = s->last_picture[0] + pic_xy; -//printf("%d %d %d %d\n", xmin, ymin, xmax, ymax); - + dmin = pix_abs16x16(new_pic, old_pic, pic_stride, 16); if(dmin<Z_THRESHOLD){ *mx_ptr= 0; @@ -424,13 +517,18 @@ static int epzs_motion_search(MpegEncContext * s, } CHECK_MV(P[0][0]>>shift, P[0][1]>>shift) - dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride, - pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift); +//check(best[0],best[1],0, b0) + if(s->full_search==ME_EPZS) + dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride, + pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift); + else + dmin= snake_search(s, best, dmin, new_pic, old_pic, pic_stride, + pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift); +//check(best[0],best[1],0, b1) *mx_ptr= best[0]; *my_ptr= best[1]; // printf("%d %d %d \n", best[0], best[1], dmin); - return dmin; } @@ -563,8 +661,8 @@ int estimate_motion(MpegEncContext * s, rel_ymax= ymax - s->mb_y*16; if(s->out_format == FMT_H263){ static const int off[4]= {2, 1, 1, -1}; - const int mot_stride = s->block_wrap[0]; - const int mot_xy = s->block_index[0]; + const int mot_stride = s->mb_width*2 + 2; + const int mot_xy = (s->mb_y*2 + 1)*mot_stride + s->mb_x*2 + 1; P[0][0] = s->motion_val[mot_xy ][0]; P[0][1] = s->motion_val[mot_xy ][1]; @@ -618,7 +716,8 @@ int estimate_motion(MpegEncContext * s, P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]); } } - dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax); + dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax); + mx+= s->mb_x*16; my+= s->mb_y*16; break; @@ -654,6 +753,8 @@ int estimate_motion(MpegEncContext * s, mx -= 16 * s->mb_x; my -= 16 * s->mb_y; } +// check(mx + 32*s->mb_x, my + 32*s->mb_y, 1, end) + *mx_ptr = mx; *my_ptr = my; return 0; diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 417f595644..fba90e7144 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -51,6 +51,9 @@ static int mpeg2_decode_block_intra(MpegEncContext *s, int n); static int mpeg_decode_motion(MpegEncContext *s, int fcode, int pred); +static UINT16 mv_penalty[MAX_FCODE][MAX_MV*2+1]; +static UINT8 fcode_tab[MAX_MV*2+1]; + static void put_header(MpegEncContext *s, int header) { align_put_bits(&s->pb); @@ -353,6 +356,53 @@ static void mpeg1_encode_motion(MpegEncContext *s, int val) } } +void mpeg1_encode_init(MpegEncContext *s) +{ + static int done=0; + if(!done){ + int f_code; + int mv; + + done=1; + for(f_code=1; f_code<=MAX_FCODE; f_code++){ + for(mv=-MAX_MV; mv<=MAX_MV; mv++){ + int len; + + if(mv==0) len= mbMotionVectorTable[0][1]; + else{ + int val, bit_size, range, code; + + bit_size = s->f_code - 1; + range = 1 << bit_size; + + val=mv; + if (val < 0) + val = -val; + val--; + code = (val >> bit_size) + 1; + if(code<17){ + len= mbMotionVectorTable[code][1] + 1 + bit_size; + }else{ + len= mbMotionVectorTable[16][1] + 2 + bit_size; + } + } + + mv_penalty[f_code][mv+MAX_MV]= len; + } + } + + + for(f_code=MAX_FCODE; f_code>0; f_code--){ + for(mv=-(8<<f_code); mv<(8<<f_code); mv++){ + fcode_tab[mv+MAX_MV]= f_code; + } + } + } + s->mv_penalty= mv_penalty; + + s->fcode_tab= fcode_tab; +} + static inline void encode_dc(MpegEncContext *s, int diff, int component) { if (component == 0) { diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 180addb6f6..9510ca1847 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -294,6 +294,7 @@ int MPV_encode_init(AVCodecContext *avctx) s->qcompress= avctx->qcompress; s->qblur= avctx->qblur; s->avctx = avctx; + s->aspect_ratio_info= avctx->aspect_ratio_info; if (s->gop_size <= 1) { s->intra_only = 1; @@ -377,6 +378,8 @@ int MPV_encode_init(AVCodecContext *avctx) if (s->out_format == FMT_H263) h263_encode_init(s); + else if (s->out_format == FMT_MPEG1) + mpeg1_encode_init(s); s->encoding = 1; @@ -1075,7 +1078,6 @@ static void encode_picture(MpegEncContext *s, int picture_number) /* Reset the average MB variance */ s->avg_mb_var = 0; s->mc_mb_var = 0; - /* Estimate motion for every MB */ for(mb_y=0; mb_y < s->mb_height; mb_y++) { for(mb_x=0; mb_x < s->mb_width; mb_x++) { @@ -1132,12 +1134,13 @@ static void encode_picture(MpegEncContext *s, int picture_number) for(i=MAX_FCODE; i>1; i--){ loose+= mv_num[i]; - if(loose > 4) break; + if(loose > 4) break; //FIXME this is pretty ineffective } s->f_code= i; }else{ s->f_code= 1; } + //printf("f_code %d ///\n", s->f_code); /* convert MBs with too long MVs to I-Blocks */ if(s->pict_type==P_TYPE){ diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 465b5ef3ab..1d0dd4f027 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -309,6 +309,7 @@ void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number); void mpeg1_encode_mb(MpegEncContext *s, DCTELEM block[6][64], int motion_x, int motion_y); +void mpeg1_encode_init(MpegEncContext *s); /* h263enc.c */ |