diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2003-03-12 15:16:19 +0000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2003-03-12 15:16:19 +0000 |
commit | 14bea432f16d7c66f9099e427819028b6b4c3bdc (patch) | |
tree | c52726ce14a0265337b9deebd2214e2552d284b0 /libavcodec | |
parent | 586bc7553ca90dee507afd950de64bbd2c6a80b5 (diff) | |
download | ffmpeg-14bea432f16d7c66f9099e427819028b6b4c3bdc.tar.gz |
per context frame_rate_base, this should finally fix frame_rate related av sync issues
Originally committed as revision 1666 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/apiexample.c | 3 | ||||
-rw-r--r-- | libavcodec/avcodec.h | 29 | ||||
-rw-r--r-- | libavcodec/common.c | 2 | ||||
-rw-r--r-- | libavcodec/common.h | 2 | ||||
-rw-r--r-- | libavcodec/dv.c | 5 | ||||
-rw-r--r-- | libavcodec/h263.c | 12 | ||||
-rw-r--r-- | libavcodec/mpeg12.c | 37 | ||||
-rw-r--r-- | libavcodec/mpeg12data.h | 32 | ||||
-rw-r--r-- | libavcodec/mpegvideo.c | 4 | ||||
-rw-r--r-- | libavcodec/mpegvideo.h | 1 | ||||
-rw-r--r-- | libavcodec/msmpeg4.c | 2 | ||||
-rw-r--r-- | libavcodec/ratecontrol.c | 8 | ||||
-rw-r--r-- | libavcodec/utils.c | 64 | ||||
-rw-r--r-- | libavcodec/wmv2.c | 2 |
14 files changed, 152 insertions, 51 deletions
diff --git a/libavcodec/apiexample.c b/libavcodec/apiexample.c index 306be47f91..27ec8241e1 100644 --- a/libavcodec/apiexample.c +++ b/libavcodec/apiexample.c @@ -192,7 +192,8 @@ void video_encode_example(const char *filename) c->width = 352; c->height = 288; /* frames per second */ - c->frame_rate = 25 * FRAME_RATE_BASE; + c->frame_rate = 25; + c->frame_rate_base= 1; c->gop_size = 10; /* emit one intra frame every ten frames */ /* open it */ diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 0bae8dab4b..b10071da69 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -186,8 +186,6 @@ static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG, #define CODEC_CAP_PARSE_ONLY 0x0004 #define CODEC_CAP_TRUNCATED 0x0008 -#define FRAME_RATE_BASE 10010 - #define FF_COMMON_FRAME \ uint8_t *data[4];\ int linesize[4];\ @@ -321,6 +319,7 @@ typedef struct AVFrame { FF_COMMON_FRAME } AVFrame; +#define DEFAULT_FRAME_RATE_BASE 1001000 /** * main external api structure. @@ -375,13 +374,21 @@ typedef struct AVCodecContext { /* video only */ /** - * frames per sec multiplied by FRAME_RATE_BASE. + * frames per sec multiplied by frame_rate_base. * for variable fps this is the precission, so if the timestamps - * can be specified in msec precssion then this is 1000*FRAME_RATE_BASE + * can be specified in msec precssion then this is 1000*frame_rate_base * - encoding: MUST be set by user * - decoding: set by lavc. 0 or the frame_rate if available */ int frame_rate; + + /** + * frame_rate_base. + * for variable fps this is 1 + * - encoding: set by user. + * - decoding: set by lavc. + */ + int frame_rate_base; /** * width / height. @@ -1258,6 +1265,20 @@ void avcodec_register_all(void); void avcodec_flush_buffers(AVCodecContext *avctx); +/* misc usefull functions */ +/** + * reduce a fraction. + * this is usefull for framerate calculations + * @param max the maximum allowed for dst_nom & dst_den + * @return 1 if exact, 0 otherwise + */ +int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max); + +/** + * rescale a 64bit integer. + * a simple a*b/c isnt possible as it can overflow + */ +int64_t av_rescale(int64_t a, int b, int c); /** diff --git a/libavcodec/common.c b/libavcodec/common.c index 96d0afcbe5..0681953846 100644 --- a/libavcodec/common.c +++ b/libavcodec/common.c @@ -341,7 +341,7 @@ void free_vlc(VLC *vlc) av_free(vlc->table); } -int ff_gcd(int a, int b){ +int64_t ff_gcd(int64_t a, int64_t b){ if(b) return ff_gcd(b, a%b); else return a; } diff --git a/libavcodec/common.h b/libavcodec/common.h index 258302661a..b456af0f1b 100644 --- a/libavcodec/common.h +++ b/libavcodec/common.h @@ -876,7 +876,7 @@ static inline int clip(int a, int amin, int amax) /* math */ extern const uint8_t ff_sqrt_tab[128]; -int ff_gcd(int a, int b); +int64_t ff_gcd(int64_t a, int64_t b); static inline int ff_sqrt(int a) { diff --git a/libavcodec/dv.c b/libavcodec/dv.c index 9e89b3ac15..6d661f4cf4 100644 --- a/libavcodec/dv.c +++ b/libavcodec/dv.c @@ -537,16 +537,17 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, /* init size */ width = 720; if (dsf) { - avctx->frame_rate = 25 * FRAME_RATE_BASE; + avctx->frame_rate = 25; packet_size = PAL_FRAME_SIZE; height = 576; nb_dif_segs = 12; } else { - avctx->frame_rate = 30 * FRAME_RATE_BASE; + avctx->frame_rate = 30; packet_size = NTSC_FRAME_SIZE; height = 480; nb_dif_segs = 10; } + avctx->frame_rate_base= 1; /* NOTE: we only accept several full frames */ if (buf_size < packet_size) return -1; diff --git a/libavcodec/h263.c b/libavcodec/h263.c index 154a8e9233..356eb73364 100644 --- a/libavcodec/h263.c +++ b/libavcodec/h263.c @@ -164,8 +164,8 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number) s->gob_number = 0; put_bits(&s->pb, 22, 0x20); /* PSC */ - put_bits(&s->pb, 8, (((int64_t)s->picture_number * 30 * FRAME_RATE_BASE) / - s->frame_rate) & 0xff); + put_bits(&s->pb, 8, (((int64_t)s->picture_number * 30 * s->avctx->frame_rate_base) / + s->avctx->frame_rate) & 0xff); put_bits(&s->pb, 1, 1); /* marker */ put_bits(&s->pb, 1, 0); /* h263 id */ @@ -1587,16 +1587,16 @@ void ff_set_mpeg4_time(MpegEncContext * s, int picture_number){ int time_div, time_mod; if(s->pict_type==I_TYPE){ //we will encode a vol header - s->time_increment_resolution= s->frame_rate/ff_gcd(s->frame_rate, FRAME_RATE_BASE); - if(s->time_increment_resolution>=256*256) s->time_increment_resolution= 256*128; - + int dummy; + av_reduce(&s->time_increment_resolution, &dummy, s->avctx->frame_rate, s->avctx->frame_rate_base, (1<<16)-1); + s->time_increment_bits = av_log2(s->time_increment_resolution - 1) + 1; } if(s->current_picture.pts) s->time= (s->current_picture.pts*s->time_increment_resolution + 500*1000)/(1000*1000); else - s->time= picture_number*(int64_t)FRAME_RATE_BASE*s->time_increment_resolution/s->frame_rate; + s->time= av_rescale(picture_number*(int64_t)s->avctx->frame_rate_base, s->time_increment_resolution, s->avctx->frame_rate); time_div= s->time/s->time_increment_resolution; time_mod= s->time%s->time_increment_resolution; diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 6eb16c9dfc..65292ac430 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -203,8 +203,10 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) int i, dmin, d; s->frame_rate_index = 0; dmin = 0x7fffffff; - for(i=1;i<9;i++) { - d = abs(s->frame_rate - frame_rate_tab[i]); + for(i=1;i<14;i++) { + if(s->avctx->strict_std_compliance >= 0 && i>=9) break; + + d = abs(MPEG1_FRAME_RATE_BASE*(int64_t)s->avctx->frame_rate/s->avctx->frame_rate_base - frame_rate_tab[i]); if (d < dmin) { dmin = d; s->frame_rate_index = i; @@ -248,22 +250,22 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) /* time code : we must convert from the real frame rate to a fake mpeg frame rate in case of low frame rate */ fps = frame_rate_tab[s->frame_rate_index]; - time_code = (int64_t)s->fake_picture_number * FRAME_RATE_BASE; + time_code = (int64_t)s->fake_picture_number * MPEG1_FRAME_RATE_BASE; s->gop_picture_number = s->fake_picture_number; put_bits(&s->pb, 5, (uint32_t)((time_code / (fps * 3600)) % 24)); put_bits(&s->pb, 6, (uint32_t)((time_code / (fps * 60)) % 60)); put_bits(&s->pb, 1, 1); put_bits(&s->pb, 6, (uint32_t)((time_code / fps) % 60)); - put_bits(&s->pb, 6, (uint32_t)((time_code % fps) / FRAME_RATE_BASE)); + put_bits(&s->pb, 6, (uint32_t)((time_code % fps) / MPEG1_FRAME_RATE_BASE)); put_bits(&s->pb, 1, 1); /* closed gop */ put_bits(&s->pb, 1, 0); /* broken link */ } - if (s->frame_rate < (24 * FRAME_RATE_BASE) && s->picture_number > 0) { + if (s->avctx->frame_rate < (24 * s->avctx->frame_rate_base) && s->picture_number > 0) { /* insert empty P pictures to slow down to the desired frame rate. Each fake pictures takes about 20 bytes */ fps = frame_rate_tab[s->frame_rate_index]; - n = (((int64_t)s->picture_number * fps) / s->frame_rate) - 1; + n = av_rescale((int64_t)s->picture_number * s->avctx->frame_rate_base, fps, s->avctx->frame_rate) / MPEG1_FRAME_RATE_BASE - 1; while (s->fake_picture_number < n) { mpeg1_skip_picture(s, s->fake_picture_number - s->gop_picture_number); @@ -1638,8 +1640,13 @@ static void mpeg_decode_sequence_extension(MpegEncContext *s) s->low_delay = get_bits1(&s->gb); frame_rate_ext_n = get_bits(&s->gb, 2); frame_rate_ext_d = get_bits(&s->gb, 5); - if (frame_rate_ext_d >= 1) - s->frame_rate = (s->frame_rate * frame_rate_ext_n) / frame_rate_ext_d; + av_reduce( + &s->avctx->frame_rate, + &s->avctx->frame_rate_base, + frame_rate_tab[s->frame_rate_index] * (frame_rate_ext_n+1), + MPEG1_FRAME_RATE_BASE * (frame_rate_ext_d+1), + 1<<30); + dprintf("sequence extension\n"); s->mpeg2 = 1; s->avctx->sub_id = 2; /* indicates mpeg2 found */ @@ -1990,13 +1997,13 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, s->avctx = avctx; avctx->width = width; avctx->height = height; - if (s->frame_rate_index >= 9) { - /* at least give a valid frame rate (some old mpeg1 have this) */ - avctx->frame_rate = 25 * FRAME_RATE_BASE; - } else { - avctx->frame_rate = frame_rate_tab[s->frame_rate_index]; - } - s->frame_rate = avctx->frame_rate; + av_reduce( + &avctx->frame_rate, + &avctx->frame_rate_base, + frame_rate_tab[s->frame_rate_index], + MPEG1_FRAME_RATE_BASE, //FIXME store in allready reduced form + 1<<30 + ); avctx->bit_rate = s->bit_rate; if (MPV_common_init(s) < 0) diff --git a/libavcodec/mpeg12data.h b/libavcodec/mpeg12data.h index d18640d074..16d607067f 100644 --- a/libavcodec/mpeg12data.h +++ b/libavcodec/mpeg12data.h @@ -385,16 +385,28 @@ static const uint8_t mbMotionVectorTable[17][2] = { { 0xc, 10 }, }; -static const int frame_rate_tab[9] = { - 0, - 24000 * FRAME_RATE_BASE / 1001, - 24000 * FRAME_RATE_BASE / 1000, - 25000 * FRAME_RATE_BASE / 1000, - 30000 * FRAME_RATE_BASE / 1001, - 30000 * FRAME_RATE_BASE / 1000, - 50000 * FRAME_RATE_BASE / 1000, - 60000 * FRAME_RATE_BASE / 1001, - 60000 * FRAME_RATE_BASE / 1000, +#define MPEG1_FRAME_RATE_BASE 1001 + +static const int frame_rate_tab[16] = { + 0, + 24000, + 24024, + 25025, + 30000, + 30030, + 50050, + 60000, + 60060, + // Xing's 15fps: (9) + 15015, + // libmpeg3's "Unofficial economy rates": (10-13) + 5005, + 10010, + 12012, + 15015, + // random, just to avoid segfault !never encode these + 25025, + 25025, }; static const uint8_t non_linear_qscale[32] = { diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 2639817265..df1c15880f 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -504,7 +504,6 @@ int MPV_encode_init(AVCodecContext *avctx) s->bit_rate = avctx->bit_rate; s->bit_rate_tolerance = avctx->bit_rate_tolerance; - s->frame_rate = avctx->frame_rate; s->width = avctx->width; s->height = avctx->height; if(avctx->gop_size > 600){ @@ -557,7 +556,8 @@ int MPV_encode_init(AVCodecContext *avctx) switch(avctx->codec->id) { case CODEC_ID_MPEG1VIDEO: s->out_format = FMT_MPEG1; - avctx->delay=0; //FIXME not sure, should check the spec + s->low_delay= 0; //s->max_b_frames ? 0 : 1; + avctx->delay= s->low_delay ? 0 : (s->max_b_frames + 1); break; case CODEC_ID_MJPEG: s->out_format = FMT_MJPEG; diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 6a556a8cdd..51d57e9ad4 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -192,7 +192,6 @@ typedef struct MpegEncContext { /* the following parameters must be initialized before encoding */ int width, height;///< picture size. must be a multiple of 16 int gop_size; - int frame_rate; ///< number of frames per second int intra_only; ///< if true, only intra pictures are generated int bit_rate; ///< wanted bit rate int bit_rate_tolerance; ///< amount of +- bits (>0) diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c index acf52d8136..47f8d2bec6 100644 --- a/libavcodec/msmpeg4.c +++ b/libavcodec/msmpeg4.c @@ -435,7 +435,7 @@ void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number) void msmpeg4_encode_ext_header(MpegEncContext * s) { - put_bits(&s->pb, 5, s->frame_rate / FRAME_RATE_BASE); //yes 29.97 -> 29 + put_bits(&s->pb, 5, s->avctx->frame_rate / s->avctx->frame_rate_base); //yes 29.97 -> 29 put_bits(&s->pb, 11, FFMIN(s->bit_rate/1024, 2047)); diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index d7fe11100c..80213dc008 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -164,7 +164,7 @@ int ff_rate_control_init(MpegEncContext *s) bits= rce.i_tex_bits + rce.p_tex_bits; q= get_qscale(s, &rce, rcc->pass1_wanted_bits/rcc->pass1_rc_eq_output_sum, i); - rcc->pass1_wanted_bits+= s->bit_rate/(s->frame_rate / (double)FRAME_RATE_BASE); + rcc->pass1_wanted_bits+= s->bit_rate/(s->avctx->frame_rate / (double)s->avctx->frame_rate_base); } } @@ -197,7 +197,7 @@ static inline double bits2qp(RateControlEntry *rce, double bits){ static void update_rc_buffer(MpegEncContext *s, int frame_size){ RateControlContext *rcc= &s->rc_context; - const double fps= (double)s->frame_rate / FRAME_RATE_BASE; + const double fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base; const double buffer_size= s->avctx->rc_buffer_size; const double min_rate= s->avctx->rc_min_rate/fps; const double max_rate= s->avctx->rc_max_rate/fps; @@ -571,7 +571,7 @@ float ff_rate_estimate_qscale(MpegEncContext *s) get_qminmax(&qmin, &qmax, s, pict_type); - fps= (double)s->frame_rate / FRAME_RATE_BASE; + fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base; //printf("input_pic_num:%d pic_num:%d frame_rate:%d\n", s->input_picture_number, s->picture_number, s->frame_rate); /* update predictors */ if(picture_number>2){ @@ -698,7 +698,7 @@ static int init_pass2(MpegEncContext *s) { RateControlContext *rcc= &s->rc_context; int i; - double fps= (double)s->frame_rate / FRAME_RATE_BASE; + double fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base; double complexity[5]={0,0,0,0,0}; // aproximate bits at quant=1 double avg_quantizer[5]; uint64_t const_bits[5]={0,0,0,0,0}; // quantizer idependant bits diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 70de6ca13d..29efd04c38 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -236,7 +236,8 @@ void avcodec_get_context_defaults(AVCodecContext *s){ s->error_concealment= 3; s->error_resilience= 1; s->workaround_bugs= FF_BUG_AUTODETECT; - s->frame_rate = 25 * FRAME_RATE_BASE; + s->frame_rate_base= 1; + s->frame_rate = 25; s->gop_size= 50; s->me_method= ME_EPZS; s->get_buffer= avcodec_default_get_buffer; @@ -463,7 +464,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %dx%d, %0.2f fps", enc->width, enc->height, - (float)enc->frame_rate / FRAME_RATE_BASE); + (float)enc->frame_rate / enc->frame_rate_base); } if (encode) { snprintf(buf + strlen(buf), buf_size - strlen(buf), @@ -588,6 +589,65 @@ void avcodec_flush_buffers(AVCodecContext *avctx) } } +int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max){ + int exact=1, sign=0; + int64_t gcd, larger; + + assert(den != 0); + + if(den < 0){ + den= -den; + nom= -nom; + } + + if(nom < 0){ + nom= -nom; + sign= 1; + } + + for(;;){ //note is executed 1 or 2 times + gcd = ff_gcd(nom, den); + nom /= gcd; + den /= gcd; + + larger= FFMAX(nom, den); + + if(larger > max){ + int64_t div= (larger + max - 1) / max; + nom = (nom + div/2)/div; + den = (den + div/2)/div; + exact=0; + }else + break; + } + + if(sign) nom= -nom; + + *dst_nom = nom; + *dst_den = den; + + return exact; +} + +int64_t av_rescale(int64_t a, int b, int c){ + uint64_t h, l; + assert(c > 0); + assert(b >=0); + + if(a<0) return -av_rescale(-a, b, c); + + h= a>>32; + if(h==0) return a*b/c; + + l= a&0xFFFFFFFF; + l *= b; + h *= b; + + l += (h%c)<<32; + + return ((h/c)<<32) + l/c; +} + static int raw_encode_init(AVCodecContext *s) { return 0; diff --git a/libavcodec/wmv2.c b/libavcodec/wmv2.c index be8c71364f..96b6c8ca3b 100644 --- a/libavcodec/wmv2.c +++ b/libavcodec/wmv2.c @@ -66,7 +66,7 @@ static int encode_ext_header(Wmv2Context *w){ init_put_bits(&pb, s->avctx->extradata, s->avctx->extradata_size, NULL, NULL); - put_bits(&pb, 5, s->frame_rate / FRAME_RATE_BASE); //yes 29.97 -> 29 + put_bits(&pb, 5, s->avctx->frame_rate / s->avctx->frame_rate_base); //yes 29.97 -> 29 put_bits(&pb, 11, FFMIN(s->bit_rate/1024, 2047)); put_bits(&pb, 1, w->mspel_bit=1); |