aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2003-02-08 12:00:57 +0000
committerMichael Niedermayer <michaelni@gmx.at>2003-02-08 12:00:57 +0000
commit63b15e559ac725321ea7a5bc38c123da8cf7d764 (patch)
tree66e05b6308ca7b4a52e18c63e4b2d996a5e496e1
parent27efd8467a92a5ea2af49acabf451bf233d5184d (diff)
downloadffmpeg-63b15e559ac725321ea7a5bc38c123da8cf7d764.tar.gz
mpeg1 bframe encoding patch by (Raphaƫl LEGRAND) with some modifications by me
Originally committed as revision 1551 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--ffmpeg.c6
-rw-r--r--libavcodec/motion_est.c40
-rw-r--r--libavcodec/mpeg12.c167
-rw-r--r--libavcodec/mpegvideo.c34
-rw-r--r--libavcodec/mpegvideo.h1
5 files changed, 195 insertions, 53 deletions
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(fmin<score){
- score=fmin;
- type= MB_TYPE_FORWARD;
+ // RAL: No MB_TYPE_DIRECT in MPEG-1 video (only MPEG-4)
+ if (s->codec_id != CODEC_ID_MPEG1VIDEO && dmin <= score){
+ score = dmin;
+ type = MB_TYPE_DIRECT;
}
if(bmin<score){
score=bmin;
@@ -1643,21 +1644,32 @@ void ff_fix_long_b_mvs(MpegEncContext * s, int16_t (*mv_table)[2], int f_code, i
int y;
UINT8 * fcode_tab= s->fcode_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; y<s->mb_height; y++){
int x;
int xy= (y+1)* (s->mb_width+2)+1;
int i= y*s->mb_width;
- for(x=0; x<s->mb_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<<f_code)-1;
- else mv_table[xy][0]= -(16<<f_code);
+ for(x=0; x<s->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<<f_code)-1;
- else mv_table[xy][1]= -(16<<f_code);
}
xy++;
i++;
diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c
index 9c32aa493c..52ab5094de 100644
--- a/libavcodec/mpeg12.c
+++ b/libavcodec/mpeg12.c
@@ -50,7 +50,7 @@
static void mpeg1_encode_block(MpegEncContext *s,
DCTELEM *block,
int component);
-static void mpeg1_encode_motion(MpegEncContext *s, int val);
+static void mpeg1_encode_motion(MpegEncContext *s, int val, int f_or_b_code); // RAL: f_code parameter added
static void mpeg1_skip_picture(MpegEncContext *s, int pict_num);
static inline int mpeg1_decode_block_inter(MpegEncContext *s,
DCTELEM *block,
@@ -332,18 +332,27 @@ void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number)
/* mpeg1 picture header */
put_header(s, PICTURE_START_CODE);
/* temporal reference */
- put_bits(&s->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;