Commit 11ce8834 authored by Michael Niedermayer's avatar Michael Niedermayer

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
parent c5b1c10a
......@@ -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 */
......
......@@ -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
......
......@@ -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) {
......
......@@ -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;
......
......@@ -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) {
......
......@@ -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){
......
......@@ -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 */
......
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