mpeg4 interlaced decoding support (not completly implemented/tested due to lack of samples)

Originally committed as revision 870 to svn://svn.ffmpeg.org/ffmpeg/trunk
pull/126/head
Michael Niedermayer 23 years ago
parent e769f0535e
commit fd7db0fddf
  1. 126
      libavcodec/h263.c
  2. 16
      libavcodec/mpegvideo.c

@ -1746,6 +1746,8 @@ void h263_decode_init_vlc(MpegEncContext *s)
&mb_type_b_tab[0][1], 2, 1, &mb_type_b_tab[0][1], 2, 1,
&mb_type_b_tab[0][0], 2, 1); &mb_type_b_tab[0][0], 2, 1);
} }
s->progressive_sequence=1; // set to most likely for the case of incomplete headers
} }
int h263_decode_gob_header(MpegEncContext *s) int h263_decode_gob_header(MpegEncContext *s)
@ -2426,7 +2428,37 @@ static int mpeg4_decode_partitioned_mb(MpegEncContext *s,
return 0; return 0;
} }
#if 0
static inline void decode_interlaced_info(MpegEncContext *s, int cbp, int mb_type){
s->mv_type= 0;
if(!s->progressive_sequence){
if(cbp || s->mb_intra)
s->interlaced_dct= get_bits1(&s->gb);
if(!s->mb_intra){
if( s->pict_type==P_TYPE //FIXME check that 4MV is forbidden
|| (s->pict_type==S_TYPE && s->vol_sprite_usage==GMC_SPRITE && !s->mcsel)
|| (s->pict_type==B_TYPE && mb_type!=0) ){
if(get_bits1(&s->gb)){
s->mv_type= MV_TYPE_FIELD;
if( s->pict_type==P_TYPE
|| (s->pict_type==B_TYPE && mb_type!=2)){
s->field_select[0][0]= get_bits1(&s->gb);
s->field_select[0][1]= get_bits1(&s->gb);
}
if(s->pict_type==B_TYPE && mb_type!=3){
s->field_select[1][0]= get_bits1(&s->gb);
s->field_select[1][1]= get_bits1(&s->gb);
}
}else
s->mv_type= 0;
}
}
}
}
#endif
int h263_decode_mb(MpegEncContext *s, int h263_decode_mb(MpegEncContext *s,
DCTELEM block[6][64]) DCTELEM block[6][64])
@ -2507,55 +2539,75 @@ int h263_decode_mb(MpegEncContext *s,
s->qscale = 31; s->qscale = 31;
h263_dc_scale(s); h263_dc_scale(s);
} }
if((!s->progressive_sequence) && (cbp || s->workaround_bugs==2))
s->interlaced_dct= get_bits1(&s->gb);
s->mv_dir = MV_DIR_FORWARD; s->mv_dir = MV_DIR_FORWARD;
if ((cbpc & 16) == 0) { if ((cbpc & 16) == 0) {
PRINT_MB_TYPE("P"); if(s->mcsel){
/* 16x16 motion prediction */
s->mv_type = MV_TYPE_16X16;
h263_pred_motion(s, 0, &pred_x, &pred_y);
if (s->umvplus_dec)
mx = h263p_decode_umotion(s, pred_x);
else if(!s->mcsel)
mx = h263_decode_motion(s, pred_x, s->f_code);
else {
const int a= s->sprite_warping_accuracy; const int a= s->sprite_warping_accuracy;
PRINT_MB_TYPE("G");
/* 16x16 global motion prediction */
s->mv_type = MV_TYPE_16X16;
// int l = (1 << (s->f_code - 1)) * 32; // int l = (1 << (s->f_code - 1)) * 32;
if(s->divx_version==500 && s->divx_build==413){ if(s->divx_version==500 && s->divx_build==413){
mx = s->sprite_offset[0][0] / (1<<(a-s->quarter_sample)); mx = s->sprite_offset[0][0] / (1<<(a-s->quarter_sample));
my = s->sprite_offset[0][1] / (1<<(a-s->quarter_sample));
}else{ }else{
mx = RSHIFT(s->sprite_offset[0][0], a-s->quarter_sample); mx = RSHIFT(s->sprite_offset[0][0], a-s->quarter_sample);
my = RSHIFT(s->sprite_offset[0][1], a-s->quarter_sample);
} }
// if (mx < -l) mx= -l, printf("C"); // int l = (1 << (s->f_code - 1)) * 32;
// else if (mx >= l) mx= l-1, printf("C"); s->mv[0][0][0] = mx;
s->mv[0][0][1] = my;
}else if((!s->progressive_sequence) && get_bits1(&s->gb)){
PRINT_MB_TYPE("f");
/* 16x8 field motion prediction */
s->mv_type= MV_TYPE_FIELD;
s->field_select[0][0]= get_bits1(&s->gb);
s->field_select[0][1]= get_bits1(&s->gb);
h263_pred_motion(s, 0, &pred_x, &pred_y);
for(i=0; i<2; i++){
mx = h263_decode_motion(s, pred_x, s->f_code);
if (mx >= 0xffff)
return -1;
my = h263_decode_motion(s, pred_y/2, s->f_code);
if (my >= 0xffff)
return -1;
s->mv[0][i][0] = mx;
s->mv[0][i][1] = my*2;
} }
}else{
PRINT_MB_TYPE("P");
/* 16x16 motion prediction */
s->mv_type = MV_TYPE_16X16;
h263_pred_motion(s, 0, &pred_x, &pred_y);
if (s->umvplus_dec)
mx = h263p_decode_umotion(s, pred_x);
else
mx = h263_decode_motion(s, pred_x, s->f_code);
if (mx >= 0xffff) if (mx >= 0xffff)
return -1; return -1;
if (s->umvplus_dec) if (s->umvplus_dec)
my = h263p_decode_umotion(s, pred_y); my = h263p_decode_umotion(s, pred_y);
else if(!s->mcsel) else
my = h263_decode_motion(s, pred_y, s->f_code); my = h263_decode_motion(s, pred_y, s->f_code);
else{
const int a= s->sprite_warping_accuracy;
// int l = (1 << (s->f_code - 1)) * 32;
if(s->divx_version==500 && s->divx_build==413){
my = s->sprite_offset[0][1] / (1<<(a-s->quarter_sample));
}else{
my = RSHIFT(s->sprite_offset[0][1], a-s->quarter_sample);
}
// if (my < -l) my= -l, printf("C");
// else if (my >= l) my= l-1, printf("C");
}
if (my >= 0xffff) if (my >= 0xffff)
return -1; return -1;
s->mv[0][0][0] = mx; s->mv[0][0][0] = mx;
s->mv[0][0][1] = my; s->mv[0][0][1] = my;
/*fprintf(stderr, "\n MB %d", (s->mb_y * s->mb_width) + s->mb_x);
fprintf(stderr, "\n\tmvx: %d\t\tpredx: %d", mx, pred_x);
fprintf(stderr, "\n\tmvy: %d\t\tpredy: %d", my, pred_y);*/
if (s->umvplus_dec && (mx - pred_x) == 1 && (my - pred_y) == 1) if (s->umvplus_dec && (mx - pred_x) == 1 && (my - pred_y) == 1)
skip_bits1(&s->gb); /* Bit stuffing to prevent PSC */ skip_bits1(&s->gb); /* Bit stuffing to prevent PSC */
}
} else { } else {
PRINT_MB_TYPE("4"); PRINT_MB_TYPE("4");
s->mv_type = MV_TYPE_8X8; s->mv_type = MV_TYPE_8X8;
@ -2614,9 +2666,6 @@ int h263_decode_mb(MpegEncContext *s,
s->mv[0][0][1] = 0; s->mv[0][0][1] = 0;
s->mv[1][0][0] = 0; s->mv[1][0][0] = 0;
s->mv[1][0][1] = 0; s->mv[1][0][1] = 0;
//FIXME is this correct?
/* s->last_mv[0][0][0]=
s->last_mv[0][0][1]=0;*/
PRINT_MB_TYPE("s"); PRINT_MB_TYPE("s");
return 0; return 0;
} }
@ -2637,6 +2686,7 @@ int h263_decode_mb(MpegEncContext *s,
h263_dc_scale(s); h263_dc_scale(s);
} }
} }
// decode_interlaced_info(s, cbp, mb_type);
}else{ }else{
mb_type=4; //like 0 but no vectors coded mb_type=4; //like 0 but no vectors coded
cbp=0; cbp=0;
@ -2682,6 +2732,7 @@ int h263_decode_mb(MpegEncContext *s,
s->mv[1][0][0] = s->mv[1][0][0] =
s->mv[1][0][1] = 1000;*/ s->mv[1][0][1] = 1000;*/
break; break;
//FIXME additional MVs for interlaced stuff
case 1: case 1:
s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD; s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD;
mx = h263_decode_motion(s, s->last_mv[0][0][0], s->f_code); mx = h263_decode_motion(s, s->last_mv[0][0][0], s->f_code);
@ -2741,6 +2792,8 @@ intra:
s->qscale = 31; s->qscale = 31;
h263_dc_scale(s); h263_dc_scale(s);
} }
if(!s->progressive_sequence)
s->interlaced_dct= get_bits1(&s->gb);
/* decode each block */ /* decode each block */
if (s->h263_pred) { if (s->h263_pred) {
@ -3606,7 +3659,7 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
} }
} }
if(get_bits1(&s->gb)) printf("interlaced not supported\n"); /* interlaced */ s->progressive_sequence= get_bits1(&s->gb)^1;
if(!get_bits1(&s->gb)) printf("OBMC not supported (very likely buggy encoder)\n"); /* OBMC Disable */ if(!get_bits1(&s->gb)) printf("OBMC not supported (very likely buggy encoder)\n"); /* OBMC Disable */
if (vo_ver_id == 1) { if (vo_ver_id == 1) {
s->vol_sprite_usage = get_bits1(&s->gb); /* vol_sprite_usage */ s->vol_sprite_usage = get_bits1(&s->gb); /* vol_sprite_usage */
@ -3763,11 +3816,6 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
printf("This file was encoded with DivX%d Build%d\n", ver, build); printf("This file was encoded with DivX%d Build%d\n", ver, build);
if(ver==500 && build==413){ if(ver==500 && build==413){
printf("WARNING: this version of DivX is not MPEG4 compatible, trying to workaround these bugs...\n"); printf("WARNING: this version of DivX is not MPEG4 compatible, trying to workaround these bugs...\n");
#if 0
}else{
printf("hmm, i havnt seen that version of divx yet, lets assume they fixed these bugs ...\n"
"using mpeg4 decoder, if it fails contact the developers (of ffmpeg)\n");
#endif
} }
} }
} }
@ -3851,7 +3899,11 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
int t; int t;
t=get_bits(&s->gb, 3); /* intra dc VLC threshold */ t=get_bits(&s->gb, 3); /* intra dc VLC threshold */
//printf("threshold %d\n", t); //printf("threshold %d\n", t);
//FIXME interlaced specific bits if(!s->progressive_sequence){
s->top_field_first= get_bits1(&s->gb);
s->alternate_scan= get_bits1(&s->gb);
//printf("top:%d alt:%d\n", s->top_field_first, s->alternate_scan);
}
} }
if(s->pict_type == S_TYPE && (s->vol_sprite_usage==STATIC_SPRITE || s->vol_sprite_usage==GMC_SPRITE)){ if(s->pict_type == S_TYPE && (s->vol_sprite_usage==STATIC_SPRITE || s->vol_sprite_usage==GMC_SPRITE)){

@ -600,6 +600,7 @@ int MPV_encode_end(AVCodecContext *avctx)
} }
/* draw the edges of width 'w' of an image of size width, height */ /* draw the edges of width 'w' of an image of size width, height */
//FIXME check that this is ok for mpeg4 interlaced
static void draw_edges_c(UINT8 *buf, int wrap, int width, int height, int w) static void draw_edges_c(UINT8 *buf, int wrap, int width, int height, int w)
{ {
UINT8 *ptr, *last_line; UINT8 *ptr, *last_line;
@ -1452,18 +1453,25 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
/* update motion predictor, not for B-frames as they need the motion_val from the last P/S-Frame */ /* update motion predictor, not for B-frames as they need the motion_val from the last P/S-Frame */
if (s->out_format == FMT_H263 && s->pict_type!=B_TYPE) { //FIXME move into h263.c if possible, format specific stuff shouldnt be here if (s->out_format == FMT_H263 && s->pict_type!=B_TYPE) { //FIXME move into h263.c if possible, format specific stuff shouldnt be here
int motion_x, motion_y;
const int wrap = s->block_wrap[0]; const int wrap = s->block_wrap[0];
const int xy = s->block_index[0]; const int xy = s->block_index[0];
if(s->mv_type == MV_TYPE_8X8){
s->non_b_mv4_table[xy]=1;
} else {
int motion_x, motion_y;
if (s->mb_intra) { if (s->mb_intra) {
motion_x = 0; motion_x = 0;
motion_y = 0; motion_y = 0;
goto motion_init;
} else if (s->mv_type == MV_TYPE_16X16) { } else if (s->mv_type == MV_TYPE_16X16) {
motion_x = s->mv[0][0][0]; motion_x = s->mv[0][0][0];
motion_y = s->mv[0][0][1]; motion_y = s->mv[0][0][1];
motion_init: } else /*if (s->mv_type == MV_TYPE_FIELD)*/ {
motion_x = s->mv[0][0][0] + s->mv[0][1][0];
motion_y = s->mv[0][0][1] + s->mv[0][1][1];
motion_x = (motion_x>>1) | (motion_x&1);
motion_y = (motion_y>>1) | (motion_y&1);
}
/* no update if 8X8 because it has been done during parsing */ /* no update if 8X8 because it has been done during parsing */
s->motion_val[xy][0] = motion_x; s->motion_val[xy][0] = motion_x;
s->motion_val[xy][1] = motion_y; s->motion_val[xy][1] = motion_y;
@ -1474,8 +1482,6 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
s->motion_val[xy + 1 + wrap][0] = motion_x; s->motion_val[xy + 1 + wrap][0] = motion_x;
s->motion_val[xy + 1 + wrap][1] = motion_y; s->motion_val[xy + 1 + wrap][1] = motion_y;
s->non_b_mv4_table[xy]=0; s->non_b_mv4_table[xy]=0;
} else { /* 8X8 */
s->non_b_mv4_table[xy]=1;
} }
} }

Loading…
Cancel
Save