[SCM] libav/experimental: per context frame_rate_base, this should finally fix frame_rate related av sync issues

siretart at users.alioth.debian.org siretart at users.alioth.debian.org
Sun Jun 30 15:35:37 UTC 2013


The following commit has been merged in the experimental branch:
commit 14bea432f16d7c66f9099e427819028b6b4c3bdc
Author: Michael Niedermayer <michaelni at gmx.at>
Date:   Wed Mar 12 15:16:19 2003 +0000

    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

diff --git a/ffmpeg.c b/ffmpeg.c
index 602ce2a..aa21dcd 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -90,7 +90,8 @@ static int frame_topBand  = 0;
 static int frame_bottomBand = 0;
 static int frame_leftBand  = 0;
 static int frame_rightBand = 0;
-static int frame_rate = 25 * FRAME_RATE_BASE;
+static int frame_rate = 25;
+static int frame_rate_base = 1;
 static int video_bit_rate = 200*1000;
 static int video_bit_rate_tolerance = 4000*1000;
 static int video_qscale = 0;
@@ -746,7 +747,7 @@ static void do_video_stats(AVFormatContext *os, AVOutputStream *ost,
         if (ti1 < 0.01)
             ti1 = 0.01;
     
-        bitrate = (double)(frame_size * 8) * enc->frame_rate / FRAME_RATE_BASE / 1000.0;
+        bitrate = (double)(frame_size * 8) * enc->frame_rate / enc->frame_rate_base / 1000.0;
         avg_bitrate = (double)(total_size * 8) / ti1 / 1000.0;
         fprintf(fvstats, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
             (double)total_size / 1024, ti1, bitrate, avg_bitrate);
@@ -974,6 +975,7 @@ static int av_encode(AVFormatContext **output_files,
                 break;
             case CODEC_TYPE_VIDEO:
                 codec->frame_rate = icodec->frame_rate;
+                codec->frame_rate_base = icodec->frame_rate_base;
                 codec->width = icodec->width;
                 codec->height = icodec->height;
                 break;
@@ -1361,7 +1363,7 @@ static int av_encode(AVFormatContext **output_files,
 
             /* frame rate emulation */
             if (ist->st->codec.rate_emu) {
-                int64_t pts = ((int64_t) ist->frame * FRAME_RATE_BASE * 1000000) / (ist->st->codec.frame_rate);
+                int64_t pts = av_rescale((int64_t) ist->frame * ist->st->codec.frame_rate_base, 1000000, ist->st->codec.frame_rate);
                 int64_t now = av_gettime() - ist->start;
                 if (pts > now)
                     usleep(pts - now);
@@ -1673,7 +1675,9 @@ static void opt_debug(const char *arg)
 
 static void opt_frame_rate(const char *arg)
 {
-    frame_rate = (int)(strtod(arg, 0) * FRAME_RATE_BASE);
+    frame_rate_base = DEFAULT_FRAME_RATE_BASE; //FIXME not optimal
+    frame_rate = (int)(strtod(arg, 0) * frame_rate_base + 0.5);
+    //FIXME parse fractions 
 }
 
 
@@ -2051,7 +2055,7 @@ static void opt_input_file(const char *filename)
 {
     AVFormatContext *ic;
     AVFormatParameters params, *ap = ¶ms;
-    int err, i, ret, rfps;
+    int err, i, ret, rfps, rfps_base;
 
     if (!strcmp(filename, "-"))
         filename = "pipe:";
@@ -2061,6 +2065,7 @@ static void opt_input_file(const char *filename)
     ap->sample_rate = audio_sample_rate;
     ap->channels = audio_channels;
     ap->frame_rate = frame_rate;
+    ap->frame_rate_base = frame_rate_base;
     ap->width = frame_width;
     ap->height = frame_height;
     ap->image_format = image_format;
@@ -2092,7 +2097,8 @@ static void opt_input_file(const char *filename)
         case CODEC_TYPE_VIDEO:
             frame_height = enc->height;
             frame_width = enc->width;
-            rfps = ic->streams[i]->r_frame_rate;
+            rfps      = ic->streams[i]->r_frame_rate;
+            rfps_base = ic->streams[i]->r_frame_rate_base;
             enc->workaround_bugs = workaround_bugs;
             enc->error_resilience = error_resilience; 
             enc->error_concealment = error_concealment; 
@@ -2106,13 +2112,15 @@ static void opt_input_file(const char *filename)
             if(bitexact)
                 enc->flags|= CODEC_FLAG_BITEXACT;
 
-            if (enc->frame_rate != rfps) {
+            assert(enc->frame_rate_base == rfps_base); // should be true for now
+            if (enc->frame_rate != rfps) { 
                 fprintf(stderr,"\nSeems that stream %d comes from film source: %2.2f->%2.2f\n",
-                    i, (float)enc->frame_rate / FRAME_RATE_BASE,
-                    (float)rfps / FRAME_RATE_BASE);
+                    i, (float)enc->frame_rate / enc->frame_rate_base,
+                    (float)rfps / rfps_base);
             }
             /* update the current frame rate to match the stream frame rate */
-            frame_rate = rfps;
+            frame_rate      = rfps;
+            frame_rate_base = rfps_base;
 
             enc->rate_emu = rate_emu;
             break;
@@ -2241,6 +2249,7 @@ static void opt_output_file(const char *filename)
                 video_enc->bit_rate = video_bit_rate;
                 video_enc->bit_rate_tolerance = video_bit_rate_tolerance;
                 video_enc->frame_rate = frame_rate; 
+                video_enc->frame_rate_base = frame_rate_base; 
                 
                 video_enc->width = frame_width;
                 video_enc->height = frame_height;
@@ -2492,8 +2501,12 @@ static void prepare_grab(void)
                     vp->width = enc->width;
                 if (enc->height > vp->height)
                     vp->height = enc->height;
-                if (enc->frame_rate > vp->frame_rate)
-                    vp->frame_rate = enc->frame_rate;
+                
+                assert(enc->frame_rate_base == DEFAULT_FRAME_RATE_BASE);
+                if (enc->frame_rate > vp->frame_rate){
+                    vp->frame_rate      = enc->frame_rate;
+                    vp->frame_rate_base = enc->frame_rate_base;
+                }
                 has_video = 1;
                 break;
             default:
@@ -2517,7 +2530,8 @@ static void prepare_grab(void)
             exit(1);
         }
         /* by now video grab has one stream */
-        ic->streams[0]->r_frame_rate = vp->frame_rate;
+        ic->streams[0]->r_frame_rate      = vp->frame_rate;
+        ic->streams[0]->r_frame_rate_base = vp->frame_rate_base;
         input_files[nb_input_files] = ic;
         dump_format(ic, nb_input_files, "", 0);
         nb_input_files++;
diff --git a/ffserver.c b/ffserver.c
index ee560e2..73e61e5 100644
--- a/ffserver.c
+++ b/ffserver.c
@@ -1725,7 +1725,7 @@ static void compute_stats(HTTPContext *c)
                 case CODEC_TYPE_VIDEO:
                     type = "video";
                     sprintf(parameters, "%dx%d, q=%d-%d, fps=%d", st->codec.width, st->codec.height,
-                                st->codec.qmin, st->codec.qmax, st->codec.frame_rate / FRAME_RATE_BASE);
+                                st->codec.qmin, st->codec.qmax, st->codec.frame_rate / st->codec.frame_rate_base);
                     break;
                 default:
                     av_abort();
@@ -1950,7 +1950,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
                                          (int64_t)s->pts_num * st->codec.sample_rate);
                             break;
                         case CODEC_TYPE_VIDEO:
-                            st->pts_incr = (int64_t)s->pts_den * FRAME_RATE_BASE;
+                            st->pts_incr = (int64_t)s->pts_den * st->codec.frame_rate_base;
                             av_frac_init(&st->pts, st->pts.val, 0,
                                          (int64_t)s->pts_num * st->codec.frame_rate);
                             break;
@@ -2018,7 +2018,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
                                      (int64_t)s->pts_num * st->codec.sample_rate);
                         break;
                     case CODEC_TYPE_VIDEO:
-                        st->pts_incr = (int64_t)s->pts_den * FRAME_RATE_BASE;
+                        st->pts_incr = (int64_t)s->pts_den * st->codec.frame_rate_base;
                         av_frac_init(&st->pts, st->pts.val, 0,
                                      (int64_t)s->pts_num * st->codec.frame_rate);
                         break;
@@ -3219,6 +3219,7 @@ static int add_av_stream(FFStream *feed, AVStream *st)
                 if (av1->width == av->width &&
                     av1->height == av->height &&
                     av1->frame_rate == av->frame_rate &&
+                    av1->frame_rate_base == av->frame_rate_base &&
                     av1->gop_size == av->gop_size)
                     goto found;
                 break;
@@ -3406,6 +3407,7 @@ static void build_feed_streams(void)
                                 matches = 0;
                             } else if (ccf->codec_type == CODEC_TYPE_VIDEO) {
                                 if (CHECK_CODEC(frame_rate) ||
+                                    CHECK_CODEC(frame_rate_base) ||
                                     CHECK_CODEC(width) ||
                                     CHECK_CODEC(height)) {
                                     printf("Codec width, height and framerate do not match for stream %d\n", i);
@@ -3553,8 +3555,10 @@ static void add_codec(FFStream *stream, AVCodecContext *av)
     case CODEC_TYPE_VIDEO:
         if (av->bit_rate == 0)
             av->bit_rate = 64000;
-        if (av->frame_rate == 0)
-            av->frame_rate = 5 * FRAME_RATE_BASE;
+        if (av->frame_rate == 0){
+            av->frame_rate = 5;
+            av->frame_rate_base = 1;
+        }
         if (av->width == 0 || av->height == 0) {
             av->width = 160;
             av->height = 128;
@@ -4017,7 +4021,8 @@ static int parse_ffconfig(const char *filename)
         } else if (!strcasecmp(cmd, "VideoFrameRate")) {
             get_arg(arg, sizeof(arg), &p);
             if (stream) {
-                video_enc.frame_rate = (int)(strtod(arg, NULL) * FRAME_RATE_BASE);
+                video_enc.frame_rate_base= DEFAULT_FRAME_RATE_BASE;
+                video_enc.frame_rate = (int)(strtod(arg, NULL) * video_enc.frame_rate_base);
             }
         } else if (!strcasecmp(cmd, "VideoGopSize")) {
             get_arg(arg, sizeof(arg), &p);
diff --git a/libavcodec/apiexample.c b/libavcodec/apiexample.c
index 306be47..27ec824 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 0bae8da..b10071d 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 96d0afc..0681953 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 2583026..b456af0 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 9e89b3a..6d661f4 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 154a8e9..356eb73 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 6eb16c9..65292ac 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 d18640d..16d6070 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 2639817..df1c158 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 6a556a8..51d57e9 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 acf52d8..47f8d2b 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 d7fe111..80213dc 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 70de6ca..29efd04 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 be8c713..96b6c8c 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);
diff --git a/libavformat/asf.c b/libavformat/asf.c
index b9cd71e..c2a3318 100644
--- a/libavformat/asf.c
+++ b/libavformat/asf.c
@@ -621,8 +621,7 @@ static int asf_write_packet(AVFormatContext *s, int stream_index,
         duration = (codec->frame_number * codec->frame_size * int64_t_C(10000000)) /
             codec->sample_rate;
     } else {
-        duration = codec->frame_number *
-            ((int64_t_C(10000000) * FRAME_RATE_BASE) / codec->frame_rate);
+        duration = av_rescale(codec->frame_number * codec->frame_rate_base, 10000000, codec->frame_rate);
     }
     if (duration > asf->duration)
         asf->duration = duration;
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index f9d435a..287bb80 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -77,6 +77,7 @@ typedef struct AVProbeData {
 
 typedef struct AVFormatParameters {
     int frame_rate;
+    int frame_rate_base;
     int sample_rate;
     int channels;
     int width;
@@ -159,6 +160,7 @@ typedef struct AVStream {
     int id;       /* format specific stream id */
     AVCodecContext codec; /* codec context */
     int r_frame_rate;     /* real frame rate of the stream */
+    int r_frame_rate_base;/* real frame rate base of the stream */
     uint64_t time_length; /* real length of the stream in miliseconds */
     void *priv_data;
     /* internal data used in av_find_stream_info() */
@@ -332,8 +334,6 @@ extern AVOutputFormat yuv4mpegpipe_oformat;
 #define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
 #define MKBETAG(a,b,c,d) (d | (c << 8) | (b << 16) | (a << 24))
 
-int av_gcd(int a, int b);
-
 void av_register_input_format(AVInputFormat *format);
 void av_register_output_format(AVOutputFormat *format);
 AVOutputFormat *guess_stream_format(const char *short_name, 
diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 6d23f07..bec8c77 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -133,12 +133,16 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
                 scale= get_le32(pb); /* scale */
                 rate= get_le32(pb); /* rate */
 
-                if(scale && rate)
-                    st->codec.frame_rate= (rate * (uint64_t)FRAME_RATE_BASE + scale/2) / scale;
-                else if(frame_period)
-                    st->codec.frame_rate = (1000000LL * FRAME_RATE_BASE + frame_period/2) / frame_period;
-                else
-                    st->codec.frame_rate = 25 * FRAME_RATE_BASE;
+                if(scale && rate){
+                    st->codec.frame_rate = rate;
+                    st->codec.frame_rate_base= scale;
+                }else if(frame_period){
+                    st->codec.frame_rate = 1000000;
+                    st->codec.frame_rate_base= frame_period;
+                }else{
+                    st->codec.frame_rate = 25;
+                    st->codec.frame_rate_base = 1;
+                }
                 
                 url_fskip(pb, size - 7 * 4);
                 break;
diff --git a/libavformat/avienc.c b/libavformat/avienc.c
index 2f36801..f885d65 100644
--- a/libavformat/avienc.c
+++ b/libavformat/avienc.c
@@ -218,7 +218,7 @@ static int avi_write_header(AVFormatContext *s)
     nb_frames = 0;
 
     if(video_enc){
-    put_le32(pb, (uint32_t)(int64_t_C(1000000) * FRAME_RATE_BASE / video_enc->frame_rate));
+        put_le32(pb, (uint32_t)(int64_t_C(1000000) * video_enc->frame_rate_base / video_enc->frame_rate));
     } else {
 	put_le32(pb, 0);
     }
@@ -244,8 +244,6 @@ static int avi_write_header(AVFormatContext *s)
     
     /* stream list */
     for(i=0;i<n;i++) {
-        int gcd;
-    
         list2 = start_tag(pb, "LIST");
         put_tag(pb, "strl");
     
@@ -262,10 +260,8 @@ static int avi_write_header(AVFormatContext *s)
             put_le16(pb, 0); /* language */
             put_le32(pb, 0); /* initial frame */
             
-            gcd= av_gcd(stream->frame_rate, FRAME_RATE_BASE);
-            
-            put_le32(pb, FRAME_RATE_BASE / gcd); /* scale */
-            put_le32(pb, stream->frame_rate / gcd); /* rate */
+            put_le32(pb, stream->frame_rate_base); /* scale */
+            put_le32(pb, stream->frame_rate); /* rate */
 
             put_le32(pb, 0); /* start */
             avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */
diff --git a/libavformat/dv1394.c b/libavformat/dv1394.c
index 7048c34..31d583c 100644
--- a/libavformat/dv1394.c
+++ b/libavformat/dv1394.c
@@ -138,7 +138,8 @@ static int dv1394_read_header(AVFormatContext * context, AVFormatParameters * ap
     vst->codec.codec_id   = CODEC_ID_DVVIDEO;
     vst->codec.width      = dv->width;
     vst->codec.height     = dv->height;
-    vst->codec.frame_rate = dv->frame_rate * FRAME_RATE_BASE;
+    vst->codec.frame_rate = dv->frame_rate;
+    vst->codec.frame_rate_base = 1;
     vst->codec.bit_rate   = 25000000;  /* Consumer DV is 25Mbps */
 
     ast->codec.codec_type = CODEC_TYPE_AUDIO;
diff --git a/libavformat/ffm.c b/libavformat/ffm.c
index f261567..de2ea6b 100644
--- a/libavformat/ffm.c
+++ b/libavformat/ffm.c
@@ -140,8 +140,6 @@ static int ffm_write_header(AVFormatContext *s)
 
     /* list of streams */
     for(i=0;i<s->nb_streams;i++) {
-        int gcd;
-    
         st = s->streams[i];
         fst = av_mallocz(sizeof(FFMStream));
         if (!fst)
@@ -158,9 +156,8 @@ static int ffm_write_header(AVFormatContext *s)
         /* specific info */
         switch(codec->codec_type) {
         case CODEC_TYPE_VIDEO:
-            gcd= av_gcd(FRAME_RATE_BASE, codec->frame_rate);
-            put_be32(pb, FRAME_RATE_BASE / gcd);
-            put_be32(pb, codec->frame_rate / gcd);
+            put_be32(pb, codec->frame_rate_base);
+            put_be32(pb, codec->frame_rate);
             put_be16(pb, codec->width);
             put_be16(pb, codec->height);
             put_be16(pb, codec->gop_size);
@@ -229,7 +226,7 @@ static int ffm_write_packet(AVFormatContext *s, int stream_index,
     if (st->codec.codec_type == CODEC_TYPE_AUDIO) {
         duration = ((float)st->codec.frame_size / st->codec.sample_rate * 1000000.0);
     } else {
-        duration = (1000000.0 * FRAME_RATE_BASE / (float)st->codec.frame_rate);
+        duration = (1000000.0 * st->codec.frame_rate_base / (float)st->codec.frame_rate);
     }
 
     pts = fst->pts;
@@ -394,7 +391,6 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
     /* read each stream */
     for(i=0;i<s->nb_streams;i++) {
         char rc_eq_buf[128];
-        int rate, scale;
 
         st = av_mallocz(sizeof(AVStream));
         if (!st)
@@ -416,9 +412,8 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
         /* specific info */
         switch(codec->codec_type) {
         case CODEC_TYPE_VIDEO:
-            scale= get_be32(pb);
-            rate= get_be32(pb);
-            codec->frame_rate = (rate * (int64_t)FRAME_RATE_BASE) / scale;
+            codec->frame_rate_base = get_be32(pb);
+            codec->frame_rate = get_be32(pb);
             codec->width = get_be16(pb);
             codec->height = get_be16(pb);
             codec->gop_size = get_be16(pb);
diff --git a/libavformat/gif.c b/libavformat/gif.c
index 47b32ef..1df8827 100644
--- a/libavformat/gif.c
+++ b/libavformat/gif.c
@@ -296,7 +296,7 @@ static int gif_write_header(AVFormatContext *s)
     GIFContext *gif = s->priv_data;
     ByteIOContext *pb = &s->pb;
     AVCodecContext *enc, *video_enc;
-    int i, width, height, rate;
+    int i, width, height/*, rate*/;
 
 /* XXX: do we reject audio streams or just ignore them ?
     if(s->nb_streams > 1)
@@ -318,7 +318,7 @@ static int gif_write_header(AVFormatContext *s)
     } else {
         width = video_enc->width;
         height = video_enc->height;
-        rate = video_enc->frame_rate;
+//        rate = video_enc->frame_rate;
     }
 
     /* XXX: is it allowed ? seems to work so far... */
@@ -351,7 +351,7 @@ static int gif_write_video(AVFormatContext *s,
     /* XXX: should use delay, in order to be more accurate */
     /* instead of using the same rounded value each time */
     /* XXX: don't even remember if I really use it for now */
-    jiffies = (70*FRAME_RATE_BASE/enc->frame_rate) - 1;
+    jiffies = (70*enc->frame_rate_base/enc->frame_rate) - 1;
 
     put_le16(pb, jiffies);
 
diff --git a/libavformat/gifdec.c b/libavformat/gifdec.c
index b827845..0ee59bc 100644
--- a/libavformat/gifdec.c
+++ b/libavformat/gifdec.c
@@ -535,7 +535,8 @@ static int gif_read_header(AVFormatContext * s1,
 
     st->codec.codec_type = CODEC_TYPE_VIDEO;
     st->codec.codec_id = CODEC_ID_RAWVIDEO;
-    st->codec.frame_rate = 5 * FRAME_RATE_BASE;
+    st->codec.frame_rate = 5;
+    st->codec.frame_rate_base = 1;
     /* XXX: check if screen size is always valid */
     st->codec.width = s->screen_width;
     st->codec.height = s->screen_height;
diff --git a/libavformat/grab.c b/libavformat/grab.c
index 7b8a1bc..3a99704 100644
--- a/libavformat/grab.c
+++ b/libavformat/grab.c
@@ -31,6 +31,7 @@ typedef struct {
     int use_mmap;
     int width, height;
     int frame_rate;
+    int frame_rate_base;
     int64_t time_frame;
     int frame_size;
     struct video_capability video_cap;
@@ -59,7 +60,7 @@ static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
     AVStream *st;
     int width, height;
     int video_fd, frame_size;
-    int ret, frame_rate;
+    int ret, frame_rate, frame_rate_base;
     int desired_palette;
     struct video_audio audio;
     const char *video_device;
@@ -69,7 +70,8 @@ static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
     
     width = ap->width;
     height = ap->height;
-    frame_rate = ap->frame_rate;
+    frame_rate      = ap->frame_rate;
+    frame_rate_base = ap->frame_rate_base;
 
     st = av_new_stream(s1, 0);
     if (!st)
@@ -77,7 +79,8 @@ static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
 
     s->width = width;
     s->height = height;
-    s->frame_rate = frame_rate;
+    s->frame_rate      = frame_rate;
+    s->frame_rate_base = frame_rate_base;
 
     video_device = ap->device;
     if (!video_device)
@@ -240,7 +243,8 @@ static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
     st->codec.codec_id = CODEC_ID_RAWVIDEO;
     st->codec.width = width;
     st->codec.height = height;
-    st->codec.frame_rate = frame_rate;
+    st->codec.frame_rate      = frame_rate;
+    st->codec.frame_rate_base = frame_rate_base;
     
     av_set_pts_info(s1, 48, 1, 1000000); /* 48 bits pts in us */
 
@@ -283,7 +287,7 @@ static int grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
     VideoData *s = s1->priv_data;
     int64_t curtime, delay;
     struct timespec ts;
-    int64_t per_frame = (int64_t_C(1000000) * FRAME_RATE_BASE) / s->frame_rate;
+    int64_t per_frame = (int64_t_C(1000000) * s->frame_rate_base) / s->frame_rate;
 
     /* Calculate the time of the next frame */
     s->time_frame += per_frame;
diff --git a/libavformat/img.c b/libavformat/img.c
index 178cee8..36e501f 100644
--- a/libavformat/img.c
+++ b/libavformat/img.c
@@ -124,10 +124,13 @@ static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
     st->codec.pix_fmt = s->pix_fmt;
     s->img_size = avpicture_get_size(s->pix_fmt, s->width, s->height);
 
-    if (!ap || !ap->frame_rate)
-        st->codec.frame_rate = 25 * FRAME_RATE_BASE;
-    else
-        st->codec.frame_rate = ap->frame_rate;
+    if (!ap || !ap->frame_rate){
+        st->codec.frame_rate      = 25;
+        st->codec.frame_rate_base = 1;
+    }else{
+        st->codec.frame_rate      = ap->frame_rate;
+        st->codec.frame_rate_base = ap->frame_rate_base;
+    }
     
     return 0;
  fail1:
@@ -182,7 +185,7 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
         av_free_packet(pkt);
         return -EIO; /* signal EOF */
     } else {
-        pkt->pts = ((int64_t)s->img_number * s1->pts_den * FRAME_RATE_BASE) / (s1->streams[0]->codec.frame_rate * s1->pts_num);
+        pkt->pts = av_rescale((int64_t)s->img_number * s1->streams[0]->codec.frame_rate_base, s1->pts_den, s1->streams[0]->codec.frame_rate) / s1->pts_num;
         s->img_number++;
         return 0;
     }
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 0e43c54..fe99673 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -686,7 +686,8 @@ static int parse_stsd(const MOVParseTableEntry *parse_table, ByteIOContext *pb,
             get_be16(pb); /* depth */
             get_be16(pb); /* colortable id */
             
-            st->codec.frame_rate = 25 * FRAME_RATE_BASE;
+            st->codec.frame_rate      = 25;
+            st->codec.frame_rate_base = 1;
             
             size -= (16+8*4+2+32+2*2);
             while (size >= 8) {
@@ -932,9 +933,8 @@ printf("track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
         sample_duration = get_be32(pb);
 
         if (!i && st->codec.codec_type==CODEC_TYPE_VIDEO) {
-            st->codec.frame_rate = FRAME_RATE_BASE * c->streams[c->total_streams]->time_scale;
-            if (sample_duration)
-                st->codec.frame_rate /= sample_duration;
+            st->codec.frame_rate_base = sample_duration ? sample_duration : 1;
+            st->codec.frame_rate = c->streams[c->total_streams]->time_scale;
 #ifdef DEBUG
             printf("VIDEO FRAME RATE= %i (sd= %i)\n", st->codec.frame_rate, sample_duration);
 #endif
diff --git a/libavformat/raw.c b/libavformat/raw.c
index f32f5eb..a1dcf87 100644
--- a/libavformat/raw.c
+++ b/libavformat/raw.c
@@ -61,7 +61,8 @@ static int raw_read_header(AVFormatContext *s, AVFormatParameters *ap)
             st->codec.channels = ap->channels;
             break;
         case CODEC_TYPE_VIDEO:
-            st->codec.frame_rate = ap->frame_rate;
+            st->codec.frame_rate      = ap->frame_rate;
+            st->codec.frame_rate_base = ap->frame_rate_base;
             st->codec.width = ap->width;
             st->codec.height = ap->height;
             break;
@@ -151,9 +152,11 @@ static int video_read_header(AVFormatContext *s,
     /* for mpeg4 specify it too (most mpeg4 streams dont have the fixed_vop_rate set ...)*/
     if (st->codec.codec_id == CODEC_ID_MJPEG || st->codec.codec_id == CODEC_ID_MPEG4) {
         if (ap) {
-            st->codec.frame_rate = ap->frame_rate;
+            st->codec.frame_rate      = ap->frame_rate;
+            st->codec.frame_rate_base = ap->frame_rate_base;
         } else {
-            st->codec.frame_rate = 25 * FRAME_RATE_BASE;
+            st->codec.frame_rate      = 25;
+            st->codec.frame_rate_base = 1;
         }
     }
     return 0;
diff --git a/libavformat/rm.c b/libavformat/rm.c
index f5ae3a3..47b510b 100644
--- a/libavformat/rm.c
+++ b/libavformat/rm.c
@@ -306,7 +306,7 @@ static int rm_write_header(AVFormatContext *s)
             break;
         case CODEC_TYPE_VIDEO:
             rm->video_stream = stream;
-            stream->frame_rate = (float)codec->frame_rate / (float)FRAME_RATE_BASE;
+            stream->frame_rate = (float)codec->frame_rate / (float)codec->frame_rate_base;
             /* XXX: dummy values */
             stream->packet_max_size = 4096;
             stream->nb_packets = 0;
@@ -582,7 +582,8 @@ static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)
                     goto fail1;
                 st->codec.width = get_be16(pb);
                 st->codec.height = get_be16(pb);
-                st->codec.frame_rate = get_be16(pb) * FRAME_RATE_BASE;
+                st->codec.frame_rate_base= 1;
+                st->codec.frame_rate = get_be16(pb) * st->codec.frame_rate_base;
                 st->codec.codec_type = CODEC_TYPE_VIDEO;
                 get_be32(pb);
                 get_be16(pb);
diff --git a/libavformat/rtp.c b/libavformat/rtp.c
index 87d28a3..45372b4 100644
--- a/libavformat/rtp.c
+++ b/libavformat/rtp.c
@@ -560,9 +560,8 @@ static void rtp_send_mpegvideo(AVFormatContext *s1,
         q += len;
 
         /* 90 KHz time stamp */
-        /* XXX: overflow */
         s->timestamp = s->base_timestamp + 
-            (s->cur_timestamp * 90000LL * FRAME_RATE_BASE) / st->codec.frame_rate;
+            av_rescale((int64_t)s->cur_timestamp * st->codec.frame_rate_base, 90000, st->codec.frame_rate);
         rtp_send_data(s1, s->buf, q - s->buf);
 
         buf1 += len;
@@ -586,9 +585,8 @@ static void rtp_send_raw(AVFormatContext *s1,
             len = size;
 
         /* 90 KHz time stamp */
-        /* XXX: overflow */
         s->timestamp = s->base_timestamp + 
-            (s->cur_timestamp * 90000LL * FRAME_RATE_BASE) / st->codec.frame_rate;
+            av_rescale((int64_t)s->cur_timestamp * st->codec.frame_rate_base, 90000, st->codec.frame_rate);
         rtp_send_data(s1, buf1, len);
 
         buf1 += len;
diff --git a/libavformat/swf.c b/libavformat/swf.c
index 9b86b58..60d931e 100644
--- a/libavformat/swf.c
+++ b/libavformat/swf.c
@@ -194,7 +194,7 @@ static int swf_write_header(AVFormatContext *s)
     AVCodecContext *enc, *audio_enc, *video_enc;
     PutBitContext p;
     uint8_t buf1[256];
-    int i, width, height, rate;
+    int i, width, height, rate, rate_base;
 
     swf = av_malloc(sizeof(SWFContext));
     if (!swf)
@@ -215,11 +215,13 @@ static int swf_write_header(AVFormatContext *s)
         /* currenty, cannot work correctly if audio only */
         width = 320;
         height = 200;
-        rate = 10 * FRAME_RATE_BASE;
+        rate = 10;
+        rate_base= 1;
     } else {
         width = video_enc->width;
         height = video_enc->height;
         rate = video_enc->frame_rate;
+        rate_base = video_enc->frame_rate_base;
     }
 
     put_tag(pb, "FWS");
@@ -228,9 +230,9 @@ static int swf_write_header(AVFormatContext *s)
                                       (will be patched if not streamed) */ 
 
     put_swf_rect(pb, 0, width, 0, height);
-    put_le16(pb, (rate * 256) / FRAME_RATE_BASE); /* frame rate */
+    put_le16(pb, (rate * 256) / rate_base); /* frame rate */
     swf->duration_pos = url_ftell(pb);
-    put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / FRAME_RATE_BASE)); /* frame count */
+    put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
     
     /* define a shape with the jpeg inside */
 
@@ -305,7 +307,7 @@ static int swf_write_header(AVFormatContext *s)
         put_swf_tag(s, TAG_STREAMHEAD);
         put_byte(&s->pb, 0);
         put_byte(&s->pb, v);
-        put_le16(&s->pb, (audio_enc->sample_rate * FRAME_RATE_BASE) / rate);  /* avg samples per frame */
+        put_le16(&s->pb, (audio_enc->sample_rate * rate_base) / rate);  /* avg samples per frame */
         
         
         put_swf_end_tag(s);
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 5642894..1c1c406 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -614,10 +614,12 @@ int av_find_stream_info(AVFormatContext *ic)
 #endif
                         /* stop after 40 frames */
                         if (st->codec_info_nb_real_frames >= 40) {
-                            st->r_frame_rate = (st->codec.frame_rate * 
-                                                st->codec_info_nb_real_frames) /
-                                (st->codec_info_nb_real_frames + 
-                                 (st->codec_info_nb_repeat_frames >> 1));
+                            av_reduce(
+                                &st->r_frame_rate,
+                                &st->r_frame_rate_base,
+                                (int64_t)st->codec.frame_rate * st->codec_info_nb_real_frames,
+                                st->codec_info_nb_real_frames + (st->codec_info_nb_repeat_frames >> 1),
+                                1<<30);
                             goto close_codec;
                         }
                     } else {
@@ -645,8 +647,10 @@ int av_find_stream_info(AVFormatContext *ic)
     for(i=0;i<ic->nb_streams;i++) {
         st = ic->streams[i];
         if (st->codec.codec_type == CODEC_TYPE_VIDEO) {
-            if (!st->r_frame_rate)
-                st->r_frame_rate = st->codec.frame_rate;
+            if (!st->r_frame_rate){
+                st->r_frame_rate      = st->codec.frame_rate;
+                st->r_frame_rate_base = st->codec.frame_rate_base;
+            }
         }
     }
 
@@ -820,7 +824,7 @@ int av_write_frame(AVFormatContext *s, int stream_index, const uint8_t *buf,
         break;
     case CODEC_TYPE_VIDEO:
         av_frac_add(&st->pts, 
-                    (int64_t)s->pts_den * FRAME_RATE_BASE);
+                    (int64_t)s->pts_den * st->codec.frame_rate_base);
         break;
     default:
         break;
@@ -1316,11 +1320,6 @@ void av_frac_add(AVFrac *f, int64_t incr)
     f->num = num;
 }
 
-int av_gcd(int a, int b){
-    if(b) return av_gcd(b, a%b);
-    else  return a;
-}
-
 /**
  * register a new image format
  * @param img_fmt Image format descriptor
diff --git a/libavformat/yuv4mpeg.c b/libavformat/yuv4mpeg.c
index 1659ca7..2cdaf9b 100644
--- a/libavformat/yuv4mpeg.c
+++ b/libavformat/yuv4mpeg.c
@@ -26,7 +26,7 @@ static int yuv4_write_header(AVFormatContext *s)
 {
     AVStream *st;
     int width, height;
-    int raten, rated, aspectn, aspectd, fps, fps1, n;
+    int raten, rated, aspectn, aspectd, fps, fps1, n, gcd;
     char buf[Y4M_LINE_MAX+1];
 
     if (s->nb_streams != 1)
@@ -35,9 +35,13 @@ static int yuv4_write_header(AVFormatContext *s)
     st = s->streams[0];
     width = st->codec.width;
     height = st->codec.height;
-    
+
+#if 1
+    //this is identical to the code below for exact fps
+    av_reduce(&raten, &rated, st->codec.frame_rate, st->codec.frame_rate_base, (1UL<<31)-1);
+#else
     fps = st->codec.frame_rate;
-    fps1 = (((float)fps / FRAME_RATE_BASE) * 1000);
+    fps1 = (((float)fps / st->codec.frame_rate_base) * 1000);
    
    /* Sorry about this messy code, but mpeg2enc is very picky about
     * the framerates it accepts. */
@@ -75,13 +79,17 @@ static int yuv4_write_header(AVFormatContext *s)
         rated = 1;
         break;
     default:
-        raten = fps1; /* this setting should work, but often doesn't */
-        rated = 1000;
+        raten = st->codec.frame_rate; /* this setting should work, but often doesn't */
+        rated = st->codec.frame_rate_base;
+        gcd= av_gcd(raten, rated);
+        raten /= gcd;
+        rated /= gcd;
         break;
     }
+#endif
     
     aspectn = 1;
-    aspectd = 1;	/* ffmpeg always uses a 1:1 aspect ratio */
+    aspectd = 1;	/* ffmpeg always uses a 1:1 aspect ratio */ //FIXME not true anymore
 
     /* construct stream header, if this is the first frame */
     n = snprintf(buf, sizeof(buf), "%s W%d H%d F%d:%d I%s A%d:%d\n",

-- 
Libav/FFmpeg packaging



More information about the pkg-multimedia-commits mailing list