mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
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
This commit is contained in:
parent
c5b1c10a0e
commit
11ce88346b
@ -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 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user