diff --git a/ffmpeg.c b/ffmpeg.c index 7288fc99e6..d7a1480e1d 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -2234,10 +2234,6 @@ void opt_output_file(const char *filename) if (b_frames) { - if (codec_id != CODEC_ID_MPEG4) { - fprintf(stderr, "\nB frames encoding only supported by MPEG-4.\n"); - exit(1); - } video_enc->max_b_frames = b_frames; video_enc->b_frame_strategy = 0; video_enc->b_quant_factor = 2.0; @@ -2775,7 +2771,7 @@ int main(int argc, char **argv) const char *opt, *arg; const OptionDef *po; INT64 ti; - + av_register_all(); /* detect if invoked as player */ diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c index 89f814b924..5814cb33cf 100644 --- a/libavcodec/motion_est.c +++ b/libavcodec/motion_est.c @@ -1493,12 +1493,13 @@ void ff_estimate_b_frame_motion(MpegEncContext * s, fbmin= bidir_refine(s, mb_x, mb_y) + penalty_factor; //printf("%d %d %d %d\n", dmin, fmin, bmin, fbmin); { - int score= dmin; - type=MB_TYPE_DIRECT; + int score= fmin; + type = MB_TYPE_FORWARD; - if(fmincodec_id != CODEC_ID_MPEG1VIDEO && dmin <= score){ + score = dmin; + type = MB_TYPE_DIRECT; } if(bminfcode_tab; + // RAL: 8 in MPEG-1, 16 in MPEG-4 + int range = (((s->codec_id == CODEC_ID_MPEG1VIDEO) ? 8 : 16) << f_code); + /* clip / convert to intra 16x16 type MVs */ for(y=0; ymb_height; y++){ int x; int xy= (y+1)* (s->mb_width+2)+1; int i= y*s->mb_width; - for(x=0; xmb_width; x++){ - if( fcode_tab[mv_table[xy][0] + MAX_MV] > f_code - || fcode_tab[mv_table[xy][0] + MAX_MV] == 0){ - if(mv_table[xy][0]>0) mv_table[xy][0]= (16<mb_width; x++) + { + if (s->mb_type[i] & type) // RAL: "type" test added... + { + if (fcode_tab[mv_table[xy][0] + MAX_MV] > f_code || fcode_tab[mv_table[xy][0] + MAX_MV] == 0) + { + if(mv_table[xy][0]>0) + mv_table[xy][0]= range-1; + else + mv_table[xy][0]= -range; + } + if (fcode_tab[mv_table[xy][1] + MAX_MV] > f_code || fcode_tab[mv_table[xy][1] + MAX_MV] == 0) + { + if(mv_table[xy][1]>0) + mv_table[xy][1]= range-1; + else + mv_table[xy][1]= -range; } - if( fcode_tab[mv_table[xy][1] + MAX_MV] > f_code - || fcode_tab[mv_table[xy][1] + MAX_MV] == 0){ - if(mv_table[xy][1]>0) mv_table[xy][1]= (16<pb, 10, (s->fake_picture_number - + + // RAL: s->picture_number instead of s->fake_picture_number + put_bits(&s->pb, 10, (s->picture_number - s->gop_picture_number) & 0x3ff); s->fake_picture_number++; put_bits(&s->pb, 3, s->pict_type); put_bits(&s->pb, 16, 0xffff); /* non constant bit rate */ - if (s->pict_type == P_TYPE) { + // RAL: Forward f_code also needed for B frames + if (s->pict_type == P_TYPE || s->pict_type == B_TYPE) { put_bits(&s->pb, 1, 0); /* half pel coordinates */ put_bits(&s->pb, 3, s->f_code); /* forward_f_code */ } + // RAL: Backward f_code necessary for B frames + if (s->pict_type == B_TYPE) { + put_bits(&s->pb, 1, 0); /* half pel coordinates */ + put_bits(&s->pb, 3, s->b_code); /* backward_f_code */ + } + put_bits(&s->pb, 1, 0); /* extra bit picture */ /* only one slice */ @@ -368,10 +377,11 @@ void mpeg1_encode_mb(MpegEncContext *s, cbp |= 1 << (5 - i); } - /* skip macroblock, except if first or last macroblock of a slice */ - if ((cbp | motion_x | motion_y) == 0 && - (!((mb_x | mb_y) == 0 || - (mb_x == s->mb_width - 1 && mb_y == s->mb_height - 1)))) { + // RAL: Skipped macroblocks for B frames... + if (cbp == 0 && (!((mb_x | mb_y) == 0 || (mb_x == s->mb_width - 1 && mb_y == s->mb_height - 1))) && + ((s->pict_type == P_TYPE && (motion_x | motion_y) == 0) || + (s->pict_type == B_TYPE && s->mv_dir == s->last_mv_dir && (((s->mv_dir & MV_DIR_FORWARD) ? ((s->mv[0][0][0] - s->last_mv[0][0][0])|(s->mv[0][0][1] - s->last_mv[0][0][1])) : 0) | + ((s->mv_dir & MV_DIR_BACKWARD) ? ((s->mv[1][0][0] - s->last_mv[1][0][0])|(s->mv[1][0][1] - s->last_mv[1][0][1])) : 0)) == 0))) { s->mb_incr++; s->qscale -= s->dquant; s->skip_count++; @@ -398,18 +408,19 @@ void mpeg1_encode_mb(MpegEncContext *s, } s->misc_bits+= get_bits_diff(s); s->i_count++; - } else { - if (s->mb_intra) { - if(s->dquant && cbp){ - put_bits(&s->pb, 6, 0x01); - put_bits(&s->pb, 5, s->qscale); - }else{ - put_bits(&s->pb, 5, 0x03); - s->qscale -= s->dquant; - } - s->misc_bits+= get_bits_diff(s); - s->i_count++; - } else { + } else if (s->mb_intra) { + if(s->dquant && cbp){ + put_bits(&s->pb, 6, 0x01); + put_bits(&s->pb, 5, s->qscale); + }else{ + put_bits(&s->pb, 5, 0x03); + s->qscale -= s->dquant; + } + s->misc_bits+= get_bits_diff(s); + s->i_count++; + s->last_mv[0][0][0] = + s->last_mv[0][0][1] = 0; + } else if (s->pict_type == P_TYPE) { if (cbp != 0) { if (motion_x == 0 && motion_y == 0) { if(s->dquant){ @@ -428,21 +439,106 @@ void mpeg1_encode_mb(MpegEncContext *s, put_bits(&s->pb, 1, 1); /* motion + cbp */ } s->misc_bits+= get_bits_diff(s); - mpeg1_encode_motion(s, motion_x - s->last_mv[0][0][0]); - mpeg1_encode_motion(s, motion_y - s->last_mv[0][0][1]); + mpeg1_encode_motion(s, motion_x - s->last_mv[0][0][0], s->f_code); // RAL: f_code parameter added + mpeg1_encode_motion(s, motion_y - s->last_mv[0][0][1], s->f_code); // RAL: f_code parameter added s->mv_bits+= get_bits_diff(s); put_bits(&s->pb, mbPatTable[cbp - 1][1], mbPatTable[cbp - 1][0]); } } else { put_bits(&s->pb, 3, 1); /* motion only */ - mpeg1_encode_motion(s, motion_x - s->last_mv[0][0][0]); - mpeg1_encode_motion(s, motion_y - s->last_mv[0][0][1]); + mpeg1_encode_motion(s, motion_x - s->last_mv[0][0][0], s->f_code); // RAL: f_code parameter added + mpeg1_encode_motion(s, motion_y - s->last_mv[0][0][1], s->f_code); // RAL: f_code parameter added s->qscale -= s->dquant; s->mv_bits+= get_bits_diff(s); } s->f_count++; + } else + { // RAL: All the following bloc added for B frames: + if (cbp != 0) + { // With coded bloc pattern + if (s->mv_dir == (MV_DIR_FORWARD | MV_DIR_BACKWARD)) + { // Bi-directional motion + if (s->dquant) + { // With QScale + put_bits(&s->pb, 5, 2); + put_bits(&s->pb, 5, s->qscale); + } + else // Without QScale + put_bits(&s->pb, 2, 3); + s->misc_bits += get_bits_diff(s); + mpeg1_encode_motion(s, s->mv[0][0][0] - s->last_mv[0][0][0], s->f_code); + mpeg1_encode_motion(s, s->mv[0][0][1] - s->last_mv[0][0][1], s->f_code); + mpeg1_encode_motion(s, s->mv[1][0][0] - s->last_mv[1][0][0], s->b_code); + mpeg1_encode_motion(s, s->mv[1][0][1] - s->last_mv[1][0][1], s->b_code); + s->b_count++; + s->f_count++; + s->mv_bits += get_bits_diff(s); + put_bits(&s->pb, mbPatTable[cbp - 1][1], mbPatTable[cbp - 1][0]); + } + else if (s->mv_dir == MV_DIR_BACKWARD) + { // Backward motion + if (s->dquant) + { // With QScale + put_bits(&s->pb, 6, 2); + put_bits(&s->pb, 5, s->qscale); + } + else // Without QScale + put_bits(&s->pb, 3, 3); + s->misc_bits += get_bits_diff(s); + mpeg1_encode_motion(s, motion_x - s->last_mv[1][0][0], s->b_code); + mpeg1_encode_motion(s, motion_y - s->last_mv[1][0][1], s->b_code); + s->b_count++; + s->mv_bits += get_bits_diff(s); + put_bits(&s->pb, mbPatTable[cbp - 1][1], mbPatTable[cbp - 1][0]); + } + else if (s->mv_dir == MV_DIR_FORWARD) + { // Forward motion + if (s->dquant) + { // With QScale + put_bits(&s->pb, 6, 3); + put_bits(&s->pb, 5, s->qscale); + } + else // Without QScale + put_bits(&s->pb, 4, 3); + s->misc_bits += get_bits_diff(s); + mpeg1_encode_motion(s, motion_x - s->last_mv[0][0][0], s->f_code); + mpeg1_encode_motion(s, motion_y - s->last_mv[0][0][1], s->f_code); + s->f_count++; + s->mv_bits += get_bits_diff(s); + put_bits(&s->pb, mbPatTable[cbp - 1][1], mbPatTable[cbp - 1][0]); + } + } + else + { // No coded bloc pattern + if (s->mv_dir == (MV_DIR_FORWARD | MV_DIR_BACKWARD)) + { // Bi-directional motion + put_bits(&s->pb, 2, 2); /* backward & forward motion */ + mpeg1_encode_motion(s, s->mv[0][0][0] - s->last_mv[0][0][0], s->f_code); + mpeg1_encode_motion(s, s->mv[0][0][1] - s->last_mv[0][0][1], s->f_code); + mpeg1_encode_motion(s, s->mv[1][0][0] - s->last_mv[1][0][0], s->b_code); + mpeg1_encode_motion(s, s->mv[1][0][1] - s->last_mv[1][0][1], s->b_code); + s->b_count++; + s->f_count++; + } + else if (s->mv_dir == MV_DIR_BACKWARD) + { // Backward motion + put_bits(&s->pb, 3, 2); /* backward motion only */ + mpeg1_encode_motion(s, motion_x - s->last_mv[1][0][0], s->b_code); + mpeg1_encode_motion(s, motion_y - s->last_mv[1][0][1], s->b_code); + s->b_count++; + } + else if (s->mv_dir == MV_DIR_FORWARD) + { // Forward motion + put_bits(&s->pb, 4, 2); /* forward motion only */ + mpeg1_encode_motion(s, motion_x - s->last_mv[0][0][0], s->f_code); + mpeg1_encode_motion(s, motion_y - s->last_mv[0][0][1], s->f_code); + s->f_count++; + } + s->qscale -= s->dquant; + s->mv_bits += get_bits_diff(s); + } + // End of bloc from RAL } - } for(i=0;i<6;i++) { if (cbp & (1 << (5 - i))) { mpeg1_encode_block(s, block[i], i); @@ -454,11 +550,22 @@ void mpeg1_encode_mb(MpegEncContext *s, else s->p_tex_bits+= get_bits_diff(s); } - s->last_mv[0][0][0] = motion_x; - s->last_mv[0][0][1] = motion_y; + + // RAL: By this: + if (s->mv_dir & MV_DIR_FORWARD) + { + s->last_mv[0][0][0]= s->mv[0][0][0]; + s->last_mv[0][0][1]= s->mv[0][0][1]; + } + if (s->mv_dir & MV_DIR_BACKWARD) + { + s->last_mv[1][0][0]= s->mv[1][0][0]; + s->last_mv[1][0][1]= s->mv[1][0][1]; + } } -static void mpeg1_encode_motion(MpegEncContext *s, int val) +// RAL: Parameter added: f_or_b_code +static void mpeg1_encode_motion(MpegEncContext *s, int val, int f_or_b_code) { int code, bit_size, l, m, bits, range, sign; @@ -469,7 +576,7 @@ static void mpeg1_encode_motion(MpegEncContext *s, int val) mbMotionVectorTable[0][1], mbMotionVectorTable[0][0]); } else { - bit_size = s->f_code - 1; + bit_size = f_or_b_code - 1; range = 1 << bit_size; /* modulo encoding */ l = 16 * range; @@ -492,9 +599,13 @@ static void mpeg1_encode_motion(MpegEncContext *s, int val) bits = val & (range - 1); sign = 1; } + + assert(code > 0 && code <= 16); + put_bits(&s->pb, mbMotionVectorTable[code][1], mbMotionVectorTable[code][0]); + put_bits(&s->pb, 1, sign); if (bit_size > 0) { put_bits(&s->pb, bit_size, bits); diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 15bd0249b0..34687d735e 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -2872,7 +2872,8 @@ static void encode_picture(MpegEncContext *s, int picture_number) #ifdef CONFIG_RISKY /* we need to initialize some time vars before we can encode b-frames */ - if (s->h263_pred && !s->h263_msmpeg4) + // RAL: Condition added for MPEG1VIDEO + if (s->codec_id == CODEC_ID_MPEG1VIDEO || (s->h263_pred && !s->h263_msmpeg4)) ff_set_mpeg4_time(s, s->picture_number); #endif @@ -2965,12 +2966,24 @@ static void encode_picture(MpegEncContext *s, int picture_number) //printf("Scene change detected, encoding as I Frame %d %d\n", s->current_picture.mb_var_sum, s->current_picture.mc_mb_var_sum); } - if(s->pict_type==P_TYPE || s->pict_type==S_TYPE) + if(s->pict_type==P_TYPE || s->pict_type==S_TYPE) { s->f_code= ff_get_best_fcode(s, s->p_mv_table, MB_TYPE_INTER); + + // RAL: Next call moved into that bloc ff_fix_long_p_mvs(s); + } + + // RAL: All this bloc changed if(s->pict_type==B_TYPE){ - s->f_code= ff_get_best_fcode(s, s->b_forw_mv_table, MB_TYPE_FORWARD); - s->b_code= ff_get_best_fcode(s, s->b_back_mv_table, MB_TYPE_BACKWARD); + int a, b; + + a = ff_get_best_fcode(s, s->b_forw_mv_table, MB_TYPE_FORWARD); + b = ff_get_best_fcode(s, s->b_bidir_forw_mv_table, MB_TYPE_BIDIR); + s->f_code = FFMAX(a, b); + + a = ff_get_best_fcode(s, s->b_back_mv_table, MB_TYPE_BACKWARD); + b = ff_get_best_fcode(s, s->b_bidir_back_mv_table, MB_TYPE_BIDIR); + s->b_code = FFMAX(a, b); ff_fix_long_b_mvs(s, s->b_forw_mv_table, s->f_code, MB_TYPE_FORWARD); ff_fix_long_b_mvs(s, s->b_back_mv_table, s->b_code, MB_TYPE_BACKWARD); @@ -3064,6 +3077,10 @@ static void encode_picture(MpegEncContext *s, int picture_number) s->mb_incr = 1; s->last_mv[0][0][0] = 0; s->last_mv[0][0][1] = 0; + s->last_mv[1][0][0] = 0; + s->last_mv[1][0][1] = 0; + + s->last_mv_dir = 0; #ifdef CONFIG_RISKY if (s->codec_id==CODEC_ID_H263 || s->codec_id==CODEC_ID_H263P) @@ -3227,7 +3244,7 @@ static void encode_picture(MpegEncContext *s, int picture_number) &dmin, &next_block, mx, my); } if(mb_type&MB_TYPE_INTRA){ - s->mv_dir = MV_DIR_FORWARD; + s->mv_dir = 0; s->mv_type = MV_TYPE_16X16; s->mb_intra= 1; s->mv[0][0][0] = 0; @@ -3348,7 +3365,7 @@ static void encode_picture(MpegEncContext *s, int picture_number) switch(mb_type){ case MB_TYPE_INTRA: - s->mv_dir = MV_DIR_FORWARD; + s->mv_dir = 0; s->mb_intra= 1; motion_x= s->mv[0][0][0] = 0; motion_y= s->mv[0][0][1] = 0; @@ -3405,8 +3422,13 @@ static void encode_picture(MpegEncContext *s, int picture_number) motion_x=motion_y=0; //gcc warning fix printf("illegal MB type\n"); } + encode_mb(s, motion_x, motion_y); + + // RAL: Update last macrobloc type + s->last_mv_dir = s->mv_dir; } + /* clean the MV table in IPS frames for direct mode in B frames */ if(s->mb_intra /* && I,P,S_TYPE */){ s->p_mv_table[xy][0]=0; diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 7ecc6fd38c..91a4525785 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -508,6 +508,7 @@ typedef struct MpegEncContext { /* Mpeg1 specific */ int fake_picture_number; /* picture number at the bitstream frame rate */ int gop_picture_number; /* index of the first picture of a GOP based on fake_pic_num & mpeg1 specific */ + int last_mv_dir; /* last mv_dir, used for b frame encoding */ /* MPEG2 specific - I wish I had not to support this mess. */ int progressive_sequence;