changeset 85:25062c9b1f86 libavformat

per context frame_rate_base, this should finally fix frame_rate related av sync issues
author michaelni
date Wed, 12 Mar 2003 15:16:19 +0000
parents 0068a6902911
children 66845d76f6a0
files asf.c avformat.h avidec.c avienc.c dv1394.c ffm.c gif.c gifdec.c grab.c img.c mov.c raw.c rm.c rtp.c swf.c utils.c yuv4mpeg.c
diffstat 17 files changed, 92 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/asf.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/asf.c	Wed Mar 12 15:16:19 2003 +0000
@@ -621,8 +621,7 @@
         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;
--- a/avformat.h	Wed Mar 12 01:35:47 2003 +0000
+++ b/avformat.h	Wed Mar 12 15:16:19 2003 +0000
@@ -77,6 +77,7 @@
 
 typedef struct AVFormatParameters {
     int frame_rate;
+    int frame_rate_base;
     int sample_rate;
     int channels;
     int width;
@@ -159,6 +160,7 @@
     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 @@
 #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, 
--- a/avidec.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/avidec.c	Wed Mar 12 15:16:19 2003 +0000
@@ -133,12 +133,16 @@
                 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;
--- a/avienc.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/avienc.c	Wed Mar 12 15:16:19 2003 +0000
@@ -218,7 +218,7 @@
     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 @@
     
     /* stream list */
     for(i=0;i<n;i++) {
-        int gcd;
-    
         list2 = start_tag(pb, "LIST");
         put_tag(pb, "strl");
     
@@ -262,10 +260,8 @@
             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 */
--- a/dv1394.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/dv1394.c	Wed Mar 12 15:16:19 2003 +0000
@@ -138,7 +138,8 @@
     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;
--- a/ffm.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/ffm.c	Wed Mar 12 15:16:19 2003 +0000
@@ -140,8 +140,6 @@
 
     /* 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 @@
         /* 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 @@
     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 @@
     /* 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 @@
         /* 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);
--- a/gif.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/gif.c	Wed Mar 12 15:16:19 2003 +0000
@@ -296,7 +296,7 @@
     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 @@
     } 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 @@
     /* 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);
 
--- a/gifdec.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/gifdec.c	Wed Mar 12 15:16:19 2003 +0000
@@ -535,7 +535,8 @@
 
     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;
--- a/grab.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/grab.c	Wed Mar 12 15:16:19 2003 +0000
@@ -31,6 +31,7 @@
     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 @@
     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 @@
     
     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 @@
 
     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 @@
     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 @@
     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;
--- a/img.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/img.c	Wed Mar 12 15:16:19 2003 +0000
@@ -124,10 +124,13 @@
     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 @@
         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;
     }
--- a/mov.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/mov.c	Wed Mar 12 15:16:19 2003 +0000
@@ -686,7 +686,8 @@
             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 @@
         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
--- a/raw.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/raw.c	Wed Mar 12 15:16:19 2003 +0000
@@ -61,7 +61,8 @@
             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 @@
     /* 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;
--- a/rm.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/rm.c	Wed Mar 12 15:16:19 2003 +0000
@@ -306,7 +306,7 @@
             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 @@
                     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);
--- a/rtp.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/rtp.c	Wed Mar 12 15:16:19 2003 +0000
@@ -560,9 +560,8 @@
         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 @@
             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;
--- a/swf.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/swf.c	Wed Mar 12 15:16:19 2003 +0000
@@ -194,7 +194,7 @@
     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 @@
         /* 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 @@
                                       (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 @@
         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);
--- a/utils.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/utils.c	Wed Mar 12 15:16:19 2003 +0000
@@ -614,10 +614,12 @@
 #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 @@
     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 @@
         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 @@
     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
--- a/yuv4mpeg.c	Wed Mar 12 01:35:47 2003 +0000
+++ b/yuv4mpeg.c	Wed Mar 12 15:16:19 2003 +0000
@@ -26,7 +26,7 @@
 {
     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 @@
     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 @@
         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",