mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
interlaced mpeg4 b frame decoding
Originally committed as revision 936 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
1c73a3fbf2
commit
bea669e57c
@ -1331,7 +1331,7 @@ void ff_set_mpeg4_time(MpegEncContext * s, int picture_number){
|
||||
time_mod= s->time%s->time_increment_resolution;
|
||||
|
||||
if(s->pict_type==B_TYPE){
|
||||
s->bp_time= s->last_non_b_time - s->time;
|
||||
s->pb_time= s->pp_time - (s->last_non_b_time - s->time);
|
||||
}else{
|
||||
s->last_time_base= s->time_base;
|
||||
s->time_base= time_div;
|
||||
@ -2828,35 +2828,107 @@ int h263_decode_mb(MpegEncContext *s,
|
||||
h263_dc_scale(s);
|
||||
}
|
||||
}
|
||||
// decode_interlaced_info(s, cbp, mb_type);
|
||||
s->mv_type= MV_TYPE_16X16; //might be changed to 8X8 or FIELD later
|
||||
|
||||
if(!s->progressive_sequence){
|
||||
if(cbp)
|
||||
s->interlaced_dct= get_bits1(&s->gb);
|
||||
|
||||
if(mb_type!=MB_TYPE_B_DIRECT){
|
||||
if(get_bits1(&s->gb)){
|
||||
s->mv_type= MV_TYPE_FIELD;
|
||||
|
||||
if(mb_type!=MB_TYPE_B_BACKW){
|
||||
s->field_select[0][0]= get_bits1(&s->gb); //FIXME move down
|
||||
s->field_select[0][1]= get_bits1(&s->gb);
|
||||
}
|
||||
if(mb_type!=MB_TYPE_B_FORW){
|
||||
s->field_select[1][0]= get_bits1(&s->gb);
|
||||
s->field_select[1][1]= get_bits1(&s->gb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
mb_type=4; //like 0 but no vectors coded
|
||||
s->mv_type= MV_TYPE_16X16; //might be changed to 8X8 later
|
||||
mb_type=4; //like MB_TYPE_B_DIRECT but no vectors coded
|
||||
cbp=0;
|
||||
}
|
||||
s->mv_type = MV_TYPE_16X16; // we'll switch to 8x8 only if the last P frame had 8x8 for this MB and mb_type=0 here
|
||||
mx=my=0; //for case 4, we could put this to the mb_type=4 but than gcc compains about uninitalized mx/my
|
||||
switch(mb_type)
|
||||
{
|
||||
case 0: /* direct */
|
||||
|
||||
mx=my=0;
|
||||
if(mb_type==MB_TYPE_B_DIRECT){
|
||||
mx = h263_decode_motion(s, 0, 1);
|
||||
my = h263_decode_motion(s, 0, 1);
|
||||
case 4: /* direct with mx=my=0 */
|
||||
}
|
||||
|
||||
if(s->mv_type==MV_TYPE_16X16){
|
||||
if(mb_type==MB_TYPE_B_FORW || mb_type==MB_TYPE_B_BIDIR){
|
||||
s->mv_dir = MV_DIR_FORWARD;
|
||||
mx = h263_decode_motion(s, s->last_mv[0][0][0], s->f_code);
|
||||
my = h263_decode_motion(s, s->last_mv[0][0][1], s->f_code);
|
||||
s->last_mv[0][1][0]= s->last_mv[0][0][0]= s->mv[0][0][0] = mx;
|
||||
s->last_mv[0][1][1]= s->last_mv[0][0][1]= s->mv[0][0][1] = my;
|
||||
}else
|
||||
s->mv_dir = 0;
|
||||
|
||||
if(mb_type==MB_TYPE_B_BACKW || mb_type==MB_TYPE_B_BIDIR){
|
||||
s->mv_dir |= MV_DIR_BACKWARD;
|
||||
mx = h263_decode_motion(s, s->last_mv[1][0][0], s->b_code);
|
||||
my = h263_decode_motion(s, s->last_mv[1][0][1], s->b_code);
|
||||
s->last_mv[1][1][0]= s->last_mv[1][0][0]= s->mv[1][0][0] = mx;
|
||||
s->last_mv[1][1][1]= s->last_mv[1][0][1]= s->mv[1][0][1] = my;
|
||||
}
|
||||
if(mb_type!=4 && mb_type!=MB_TYPE_B_DIRECT)
|
||||
PRINT_MB_TYPE(mb_type==MB_TYPE_B_FORW ? "F" : (mb_type==MB_TYPE_B_BACKW ? "B" : "T"));
|
||||
}else{
|
||||
/* MV_TYPE_FIELD */
|
||||
if(mb_type==MB_TYPE_B_FORW || mb_type==MB_TYPE_B_BIDIR){
|
||||
s->mv_dir = MV_DIR_FORWARD;
|
||||
for(i=0; i<2; i++){
|
||||
mx = h263_decode_motion(s, s->last_mv[0][i][0] , s->f_code);
|
||||
my = h263_decode_motion(s, s->last_mv[0][i][1]/2, s->f_code);
|
||||
s->last_mv[0][i][0]= s->mv[0][i][0] = mx;
|
||||
s->last_mv[0][i][1]= (s->mv[0][i][1] = my)*2;
|
||||
}
|
||||
}else
|
||||
s->mv_dir = 0;
|
||||
|
||||
if(mb_type==MB_TYPE_B_BACKW || mb_type==MB_TYPE_B_BIDIR){
|
||||
s->mv_dir |= MV_DIR_BACKWARD;
|
||||
for(i=0; i<2; i++){
|
||||
mx = h263_decode_motion(s, s->last_mv[1][i][0] , s->b_code);
|
||||
my = h263_decode_motion(s, s->last_mv[1][i][1]/2, s->b_code);
|
||||
s->last_mv[1][i][0]= s->mv[1][i][0] = mx;
|
||||
s->last_mv[1][i][1]= (s->mv[1][i][1] = my)*2;
|
||||
}
|
||||
}
|
||||
if(mb_type!=4 && mb_type!=MB_TYPE_B_DIRECT)
|
||||
PRINT_MB_TYPE(mb_type==MB_TYPE_B_FORW ? "f" : (mb_type==MB_TYPE_B_BACKW ? "b" : "t"));
|
||||
}
|
||||
|
||||
if(mb_type==4 || mb_type==MB_TYPE_B_DIRECT){
|
||||
int mb_index= s->mb_x + s->mb_y*s->mb_width;
|
||||
int i;
|
||||
|
||||
s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT;
|
||||
xy= s->block_index[0];
|
||||
time_pp= s->pp_time;
|
||||
time_pb= time_pp - s->bp_time;
|
||||
//if(time_pp>3000 )printf("%d %d ", time_pp, time_pb);
|
||||
time_pb= s->pb_time;
|
||||
|
||||
//FIXME avoid divides
|
||||
switch(s->co_located_type_table[mb_index]){
|
||||
case 0:
|
||||
s->mv[0][0][0] = s->motion_val[xy][0]*time_pb/time_pp + mx;
|
||||
s->mv[0][0][1] = s->motion_val[xy][1]*time_pb/time_pp + my;
|
||||
s->mv[1][0][0] = mx ? s->mv[0][0][0] - s->motion_val[xy][0]
|
||||
: s->motion_val[xy][0]*(time_pb - time_pp)/time_pp;
|
||||
s->mv[1][0][1] = my ? s->mv[0][0][1] - s->motion_val[xy][1]
|
||||
: s->motion_val[xy][1]*(time_pb - time_pp)/time_pp;
|
||||
if(s->non_b_mv4_table[xy]){
|
||||
int i;
|
||||
PRINT_MB_TYPE(mb_type==4 ? "D" : "S");
|
||||
break;
|
||||
case CO_LOCATED_TYPE_4MV:
|
||||
s->mv_type = MV_TYPE_8X8;
|
||||
for(i=1; i<4; i++){
|
||||
for(i=0; i<4; i++){
|
||||
xy= s->block_index[i];
|
||||
s->mv[0][i][0] = s->motion_val[xy][0]*time_pb/time_pp + mx;
|
||||
s->mv[0][i][1] = s->motion_val[xy][1]*time_pb/time_pp + my;
|
||||
@ -2866,45 +2938,30 @@ int h263_decode_mb(MpegEncContext *s,
|
||||
: s->motion_val[xy][1]*(time_pb - time_pp)/time_pp;
|
||||
}
|
||||
PRINT_MB_TYPE("4");
|
||||
break;
|
||||
case CO_LOCATED_TYPE_FIELDMV:
|
||||
s->mv_type = MV_TYPE_FIELD;
|
||||
for(i=0; i<2; i++){
|
||||
if(s->top_field_first){
|
||||
time_pp= s->pp_field_time - s->field_select_table[mb_index][i] + i;
|
||||
time_pb= s->pb_field_time - s->field_select_table[mb_index][i] + i;
|
||||
}else{
|
||||
PRINT_MB_TYPE(mb_type==4 ? "D" : "S");
|
||||
time_pp= s->pp_field_time + s->field_select_table[mb_index][i] - i;
|
||||
time_pb= s->pb_field_time + s->field_select_table[mb_index][i] - i;
|
||||
}
|
||||
/* s->mv[0][0][0] =
|
||||
s->mv[0][0][1] =
|
||||
s->mv[1][0][0] =
|
||||
s->mv[1][0][1] = 1000;*/
|
||||
s->mv[0][i][0] = s->field_mv_table[mb_index][i][0]*time_pb/time_pp + mx;
|
||||
s->mv[0][i][1] = s->field_mv_table[mb_index][i][1]*time_pb/time_pp + my;
|
||||
s->mv[1][i][0] = mx ? s->mv[0][i][0] - s->field_mv_table[mb_index][i][0]
|
||||
: s->field_mv_table[mb_index][i][0]*(time_pb - time_pp)/time_pp;
|
||||
s->mv[1][i][1] = my ? s->mv[0][i][1] - s->field_mv_table[mb_index][i][1]
|
||||
: s->field_mv_table[mb_index][i][1]*(time_pb - time_pp)/time_pp;
|
||||
}
|
||||
PRINT_MB_TYPE("=");
|
||||
break;
|
||||
//FIXME additional MVs for interlaced stuff
|
||||
case 1:
|
||||
s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD;
|
||||
mx = h263_decode_motion(s, s->last_mv[0][0][0], s->f_code);
|
||||
my = h263_decode_motion(s, s->last_mv[0][0][1], s->f_code);
|
||||
s->last_mv[0][0][0]= s->mv[0][0][0] = mx;
|
||||
s->last_mv[0][0][1]= s->mv[0][0][1] = my;
|
||||
}
|
||||
}
|
||||
|
||||
mx = h263_decode_motion(s, s->last_mv[1][0][0], s->b_code);
|
||||
my = h263_decode_motion(s, s->last_mv[1][0][1], s->b_code);
|
||||
s->last_mv[1][0][0]= s->mv[1][0][0] = mx;
|
||||
s->last_mv[1][0][1]= s->mv[1][0][1] = my;
|
||||
PRINT_MB_TYPE("i");
|
||||
break;
|
||||
case 2:
|
||||
s->mv_dir = MV_DIR_BACKWARD;
|
||||
mx = h263_decode_motion(s, s->last_mv[1][0][0], s->b_code);
|
||||
my = h263_decode_motion(s, s->last_mv[1][0][1], s->b_code);
|
||||
s->last_mv[1][0][0]= s->mv[1][0][0] = mx;
|
||||
s->last_mv[1][0][1]= s->mv[1][0][1] = my;
|
||||
PRINT_MB_TYPE("B");
|
||||
break;
|
||||
case 3:
|
||||
s->mv_dir = MV_DIR_FORWARD;
|
||||
mx = h263_decode_motion(s, s->last_mv[0][0][0], s->f_code);
|
||||
my = h263_decode_motion(s, s->last_mv[0][0][1], s->f_code);
|
||||
s->last_mv[0][0][0]= s->mv[0][0][0] = mx;
|
||||
s->last_mv[0][0][1]= s->mv[0][0][1] = my;
|
||||
PRINT_MB_TYPE("F");
|
||||
break;
|
||||
default:
|
||||
if(mb_type<0 || mb_type>4){
|
||||
printf("illegal MB_type\n");
|
||||
return -1;
|
||||
}
|
||||
@ -3793,6 +3850,7 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
|
||||
skip_bits1(&s->gb); /* marker */
|
||||
|
||||
s->time_increment_resolution = get_bits(&s->gb, 16);
|
||||
|
||||
s->time_increment_bits = av_log2(s->time_increment_resolution - 1) + 1;
|
||||
if (s->time_increment_bits < 1)
|
||||
s->time_increment_bits = 1;
|
||||
@ -4005,15 +4063,28 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
|
||||
s->last_time_base= s->time_base;
|
||||
s->time_base+= time_incr;
|
||||
s->time= s->time_base*s->time_increment_resolution + time_increment;
|
||||
if(s->time < s->last_non_b_time && s->workaround_bugs==3){
|
||||
fprintf(stderr, "header is not mpeg4 compatible, broken encoder, trying to workaround\n");
|
||||
s->time_base++;
|
||||
s->time+= s->time_increment_resolution;
|
||||
}
|
||||
s->pp_time= s->time - s->last_non_b_time;
|
||||
s->last_non_b_time= s->time;
|
||||
}else{
|
||||
s->time= (s->last_time_base + time_incr)*s->time_increment_resolution + time_increment;
|
||||
s->bp_time= s->last_non_b_time - s->time;
|
||||
if(s->pp_time <=s->bp_time){
|
||||
s->pb_time= s->pp_time - (s->last_non_b_time - s->time);
|
||||
if(s->pp_time <=s->pb_time || s->pp_time <= s->pp_time - s->pb_time || s->pp_time<=0){
|
||||
// printf("messed up order, seeking?, skiping current b frame\n");
|
||||
return FRAME_SKIPED;
|
||||
}
|
||||
|
||||
if(s->t_frame==0) s->t_frame= s->time - s->last_time_base;
|
||||
if(s->t_frame==0) s->t_frame=1; // 1/0 protection
|
||||
//printf("%Ld %Ld %d %d\n", s->last_non_b_time, s->time, s->pp_time, s->t_frame); fflush(stdout);
|
||||
s->pp_field_time= ( ROUNDED_DIV(s->last_non_b_time, s->t_frame)
|
||||
- ROUNDED_DIV(s->last_non_b_time - s->pp_time, s->t_frame))*2;
|
||||
s->pb_field_time= ( ROUNDED_DIV(s->time, s->t_frame)
|
||||
- ROUNDED_DIV(s->last_non_b_time - s->pp_time, s->t_frame))*2;
|
||||
}
|
||||
|
||||
s->avctx->pts= s->time*1000LL*1000LL / s->time_increment_resolution;
|
||||
@ -4028,8 +4099,8 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
|
||||
/* vop coded */
|
||||
if (get_bits1(&s->gb) != 1)
|
||||
goto redo;
|
||||
//printf("time %d %d %d || %d %d %d\n", s->time_increment_bits, s->time_increment, s->time_base,
|
||||
//s->time, s->last_non_b_time[0], s->last_non_b_time[1]);
|
||||
//printf("time %d %d %d || %Ld %Ld %Ld\n", s->time_increment_bits, s->time_increment_resolution, s->time_base,
|
||||
//s->time, s->last_non_b_time, s->last_non_b_time - s->pp_time);
|
||||
if (s->shape != BIN_ONLY_SHAPE && ( s->pict_type == P_TYPE
|
||||
|| (s->pict_type == S_TYPE && s->vol_sprite_usage==GMC_SPRITE))) {
|
||||
/* rounding type for motion estimation */
|
||||
@ -4101,9 +4172,12 @@ int mpeg4_decode_picture_header(MpegEncContext * s)
|
||||
s->b_code = get_bits(&s->gb, 3);
|
||||
}else
|
||||
s->b_code=1;
|
||||
|
||||
//printf("qpuant:%d fcode:%d bcode:%d type:%d size:%d pro:%d alt:%d\n",
|
||||
// s->qscale, s->f_code, s->b_code, s->pict_type, s->gb.size,s->progressive_sequence, s->alternate_scan);
|
||||
#if 0
|
||||
printf("qp:%d fc:%d bc:%d type:%s size:%d pro:%d alt:%d qpel:%d part:%d resync:%d\n",
|
||||
s->qscale, s->f_code, s->b_code,
|
||||
s->pict_type == I_TYPE ? "I" : (s->pict_type == P_TYPE ? "P" : (s->pict_type == B_TYPE ? "B" : "S")),
|
||||
s->gb.size,s->progressive_sequence, s->alternate_scan, s->quarter_sample, s->data_partitioning, s->resync_marker);
|
||||
#endif
|
||||
if(!s->scalability){
|
||||
if (s->shape!=RECT_SHAPE && s->pict_type!=I_TYPE) {
|
||||
skip_bits1(&s->gb); // vop shape coding type
|
||||
|
@ -1391,8 +1391,8 @@ static inline int direct_search(MpegEncContext * s,
|
||||
const int motion_px= s->p_mv_table[mot_xy][0];
|
||||
const int motion_py= s->p_mv_table[mot_xy][1];
|
||||
const int time_pp= s->pp_time;
|
||||
const int time_bp= s->bp_time;
|
||||
const int time_pb= time_pp - time_bp;
|
||||
const int time_pb= s->pb_time;
|
||||
const int time_bp= time_pp - time_pb;
|
||||
int bx, by;
|
||||
int mx, my, mx2, my2;
|
||||
uint8_t *ref_picture= s->me_scratchpad - (mb_x - 1 + (mb_y - 1)*s->linesize)*16;
|
||||
|
@ -17,6 +17,10 @@
|
||||
#define MOTION_MARKER 0x1F001
|
||||
#define DC_MARKER 0x6B001
|
||||
|
||||
#define MB_TYPE_B_DIRECT 0
|
||||
#define MB_TYPE_B_BIDIR 1
|
||||
#define MB_TYPE_B_BACKW 2
|
||||
#define MB_TYPE_B_FORW 3
|
||||
|
||||
/* dc encoding for mpeg4 */
|
||||
const UINT8 DCtab_lum[13][2] =
|
||||
|
@ -259,9 +259,13 @@ int MPV_common_init(MpegEncContext *s)
|
||||
/* MV prediction */
|
||||
size = (2 * s->mb_width + 2) * (2 * s->mb_height + 2);
|
||||
CHECKED_ALLOCZ(s->motion_val, size * 2 * sizeof(INT16));
|
||||
}
|
||||
|
||||
/* 4mv direct mode decoding table */
|
||||
CHECKED_ALLOCZ(s->non_b_mv4_table, size * sizeof(UINT8))
|
||||
if(s->codec_id==CODEC_ID_MPEG4){
|
||||
/* 4mv and interlaced direct mode decoding tables */
|
||||
CHECKED_ALLOCZ(s->co_located_type_table, s->mb_num * sizeof(UINT8))
|
||||
CHECKED_ALLOCZ(s->field_mv_table, s->mb_num*2*2 * sizeof(INT16))
|
||||
CHECKED_ALLOCZ(s->field_select_table, s->mb_num*2* sizeof(INT8))
|
||||
}
|
||||
|
||||
if (s->h263_pred || s->h263_plus) {
|
||||
@ -350,7 +354,9 @@ void MPV_common_end(MpegEncContext *s)
|
||||
av_freep(&s->tex_pb_buffer);
|
||||
av_freep(&s->pb2_buffer);
|
||||
av_freep(&s->edge_emu_buffer);
|
||||
av_freep(&s->non_b_mv4_table);
|
||||
av_freep(&s->co_located_type_table);
|
||||
av_freep(&s->field_mv_table);
|
||||
av_freep(&s->field_select_table);
|
||||
av_freep(&s->avctx->stats_out);
|
||||
av_freep(&s->ac_stats);
|
||||
|
||||
@ -1466,20 +1472,32 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
|
||||
|
||||
const int wrap = s->block_wrap[0];
|
||||
const int xy = s->block_index[0];
|
||||
const int mb_index= s->mb_x + s->mb_y*s->mb_width;
|
||||
if(s->mv_type == MV_TYPE_8X8){
|
||||
s->non_b_mv4_table[xy]=1;
|
||||
s->co_located_type_table[mb_index]= CO_LOCATED_TYPE_4MV;
|
||||
} else {
|
||||
int motion_x, motion_y;
|
||||
if (s->mb_intra) {
|
||||
motion_x = 0;
|
||||
motion_y = 0;
|
||||
if(s->co_located_type_table)
|
||||
s->co_located_type_table[mb_index]= 0;
|
||||
} else if (s->mv_type == MV_TYPE_16X16) {
|
||||
motion_x = s->mv[0][0][0];
|
||||
motion_y = s->mv[0][0][1];
|
||||
if(s->co_located_type_table)
|
||||
s->co_located_type_table[mb_index]= 0;
|
||||
} else /*if (s->mv_type == MV_TYPE_FIELD)*/ {
|
||||
int i;
|
||||
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);
|
||||
for(i=0; i<2; i++){
|
||||
s->field_mv_table[mb_index][i][0]= s->mv[0][i][0];
|
||||
s->field_mv_table[mb_index][i][1]= s->mv[0][i][1];
|
||||
s->field_select_table[mb_index][i]= s->field_select[0][i];
|
||||
}
|
||||
s->co_located_type_table[mb_index]= CO_LOCATED_TYPE_FIELDMV;
|
||||
}
|
||||
/* no update if 8X8 because it has been done during parsing */
|
||||
s->motion_val[xy][0] = motion_x;
|
||||
@ -1490,7 +1508,6 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
|
||||
s->motion_val[xy + wrap][1] = motion_y;
|
||||
s->motion_val[xy + 1 + wrap][0] = motion_x;
|
||||
s->motion_val[xy + 1 + wrap][1] = motion_y;
|
||||
s->non_b_mv4_table[xy]=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,7 +339,9 @@ typedef struct MpegEncContext {
|
||||
INT64 time; /* time of current frame */
|
||||
INT64 last_non_b_time;
|
||||
UINT16 pp_time; /* time distance between the last 2 p,s,i frames */
|
||||
UINT16 bp_time; /* time distance between the last b and p,s,i frame */
|
||||
UINT16 pb_time; /* time distance between the last b and p,s,i frame */
|
||||
UINT16 pp_field_time;
|
||||
UINT16 pb_field_time; /* like above, just for interlaced */
|
||||
int shape;
|
||||
int vol_sprite_usage;
|
||||
int sprite_width;
|
||||
@ -377,7 +379,12 @@ typedef struct MpegEncContext {
|
||||
uint8_t *tex_pb_buffer;
|
||||
uint8_t *pb2_buffer;
|
||||
int mpeg_quant;
|
||||
INT8 *non_b_mv4_table;
|
||||
#define CO_LOCATED_TYPE_4MV 1
|
||||
#define CO_LOCATED_TYPE_FIELDMV 2
|
||||
INT8 *co_located_type_table; /* 4mv & field_mv info for next b frame */
|
||||
INT16 (*field_mv_table)[2][2]; /* used for interlaced b frame decoding */
|
||||
INT8 (*field_select_table)[2]; /* wtf, no really another table for interlaced b frames */
|
||||
int t_frame; /* time distance of first I -> B, used for interlaced b frames */
|
||||
|
||||
/* divx specific, used to workaround (many) bugs in divx5 */
|
||||
int divx_version;
|
||||
|
Loading…
Reference in New Issue
Block a user