AV synchronisation API
authorFabrice Bellard <fabrice@bellard.org>
Mon, 21 Oct 2002 15:54:49 +0000 (15:54 +0000)
committerFabrice Bellard <fabrice@bellard.org>
Mon, 21 Oct 2002 15:54:49 +0000 (15:54 +0000)
Originally committed as revision 1054 to svn://svn.ffmpeg.org/ffmpeg/trunk

libav/avformat.h
libav/utils.c

index 2fb64e4..d8679d1 100644 (file)
@@ -14,7 +14,7 @@
 #define AV_NOPTS_VALUE 0
 
 typedef struct AVPacket {
-    INT64 pts;
+    INT64 pts; /* presentation time stamp in stream units (set av_set_pts_info) */
     UINT8 *data;
     int size;
     int stream_index;
@@ -28,6 +28,19 @@ int av_new_packet(AVPacket *pkt, int size);
 void av_free_packet(AVPacket *pkt);
 
 /*************************************************/
+/* fractional numbers for exact pts handling */
+
+/* the exact value of the fractional number is: 'val + num / den'. num
+   is assumed to be such as 0 <= num < den */
+typedef struct AVFrac {
+    INT64 val, num, den; 
+} AVFrac;
+
+void av_frac_init(AVFrac *f, INT64 val, INT64 num, INT64 den);
+void av_frac_add(AVFrac *f, INT64 incr);
+void av_frac_set(AVFrac *f, INT64 val);
+
+/*************************************************/
 /* input/output formats */
 
 struct AVFormatContext;
@@ -151,6 +164,9 @@ typedef struct AVFormatContext {
     char copyright[512];
     char comment[512];
     int flags; /* format specific flags */
+    /* private data for pts handling (do not modify directly) */
+    int pts_wrap_bits; /* number of bits in pts (used for wrapping control) */
+    int pts_num, pts_den; /* value to convert to seconds */
     /* This buffer is only needed when packets were already buffered but
        not decoded, for example to get the codec parameters in mpeg
        streams */
@@ -276,6 +292,8 @@ int av_find_stream_info(AVFormatContext *ic);
 int av_read_packet(AVFormatContext *s, AVPacket *pkt);
 void av_close_input_file(AVFormatContext *s);
 AVStream *av_new_stream(AVFormatContext *s, int id);
+void av_set_pts_info(AVFormatContext *s, int pts_wrap_bits,
+                     int pts_num, int pts_den);
 
 /* media file output */
 int av_write_header(AVFormatContext *s);
index 18e125e..89c32be 100644 (file)
@@ -153,7 +153,7 @@ int av_new_packet(AVPacket *pkt, int size)
         return AVERROR_NOMEM;
     pkt->size = size;
     /* sane state */
-    pkt->pts = 0;
+    pkt->pts = AV_NOPTS_VALUE;
     pkt->stream_index = 0;
     pkt->flags = 0;
     return 0;
@@ -356,6 +356,9 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
         goto fail;
     }
 
+    /* default pts settings is MPEG like */
+    av_set_pts_info(ic, 33, 1, 90000);
+
     /* check filename in case of an image number is expected */
     if (ic->iformat->flags & AVFMT_NEEDNUMBER) {
         if (filename_number_test(ic->filename) < 0) { 
@@ -695,6 +698,8 @@ int av_write_header(AVFormatContext *s)
     s->priv_data = av_mallocz(s->oformat->priv_data_size);
     if (!s->priv_data)
         return AVERROR_NOMEM;
+    /* default pts settings is MPEG like */
+    av_set_pts_info(s, 33, 1, 90000);
     return s->oformat->write_header(s);
 }
 
@@ -829,11 +834,15 @@ static time_t mktimegm(struct tm *tm)
     return t;
 }
 
-/* syntax:
- *  [YYYY-MM-DD]{T| }HH[:MM[:SS[.m...]]][Z] . 
- *  [YYYYMMDD]{T| }HH[MM[SS[.m...]]][Z] . 
+/* Syntax:
+ * - If not a duration:
+ *  [{YYYY-MM-DD|YYYYMMDD}]{T| }{HH[:MM[:SS[.m...]]][Z]|HH[MM[SS[.m...]]][Z]}
  * Time is localtime unless Z is suffixed to the end. In this case GMT
- * Return the date in micro seconds since 1970 */
+ * Return the date in micro seconds since 1970 
+ * - If duration:
+ *  HH[:MM[:SS[.m...]]]
+ *  S+[.m...]
+ */
 INT64 parse_date(const char *datestr, int duration)
 {
     const char *p;
@@ -849,19 +858,21 @@ INT64 parse_date(const char *datestr, int duration)
         "%H%M%S",
     };
     const char *q;
-    int is_utc;
+    int is_utc, len;
     char lastch;
     time_t now = time(0);
 
-    lastch = datestr[strlen(datestr)-1];
-
+    len = strlen(datestr);
+    if (len > 0)
+        lastch = datestr[len - 1];
+    else
+        lastch = '\0';
     is_utc = (lastch == 'z' || lastch == 'Z');
 
     memset(&dt, 0, sizeof(dt));
 
     p = datestr;
-    q = 0;
-
+    q = NULL;
     if (!duration) {
         for (i = 0; i < sizeof(date_fmt) / sizeof(date_fmt[0]); i++) {
             q = strptime(p, date_fmt[i], &dt);
@@ -883,12 +894,19 @@ INT64 parse_date(const char *datestr, int duration)
 
         if (*p == 'T' || *p == 't' || *p == ' ')
             p++;
-    }
 
-    for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) {
-        q = strptime(p, time_fmt[i], &dt);
-        if (q) {
-            break;
+        for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) {
+            q = strptime(p, time_fmt[i], &dt);
+            if (q) {
+                break;
+            }
+        }
+    } else {
+        q = strptime(p, time_fmt[0], &dt);
+        if (!q) {
+            dt.tm_sec = strtol(p, (char **)&q, 10);
+            dt.tm_min = 0;
+            dt.tm_hour = 0;
         }
     }
 
@@ -1022,35 +1040,6 @@ int get_frame_filename(char *buf, int buf_size,
     return -1;
 }
 
-static int gcd(INT64 a, INT64 b)
-{
-    INT64 c;
-
-    while (1) {
-        c = a % b;
-        if (c == 0)
-            return b;
-        a = b;
-        b = c;
-    }
-}
-
-void ticker_init(Ticker *tick, INT64 inrate, INT64 outrate)
-{
-    int g;
-
-    g = gcd(inrate, outrate);
-    inrate /= g;
-    outrate /= g;
-
-    tick->value = -outrate/2;
-
-    tick->inrate = inrate;
-    tick->outrate = outrate;
-    tick->div = tick->outrate / tick->inrate;
-    tick->mod = tick->outrate % tick->inrate;
-}
-
 /**
  *
  * Print on stdout a nice hexa dump of a buffer
@@ -1134,3 +1123,74 @@ void url_split(char *proto, int proto_size,
     pstrcpy(path, path_size, p);
 }
 
+/**
+ * Set the pts for a given stream
+ * @param s stream 
+ * @param pts_wrap_bits number of bits effectively used by the pts
+ *        (used for wrap control, 33 is the value for MPEG) 
+ * @param pts_num numerator to convert to seconds (MPEG: 1) 
+ * @param pts_den denominator to convert to seconds (MPEG: 90000)
+ */
+void av_set_pts_info(AVFormatContext *s, int pts_wrap_bits,
+                     int pts_num, int pts_den)
+{
+    s->pts_wrap_bits = pts_wrap_bits;
+    s->pts_num = pts_num;
+    s->pts_den = pts_den;
+}
+
+/* fraction handling */
+
+/**
+ * f = val + (num / den) + 0.5. 'num' is normalized so that it is such
+ * as 0 <= num < den.
+ *
+ * @param f fractional number
+ * @param val integer value
+ * @param num must be >= 0
+ * @param den must be >= 1 
+ */
+void av_frac_init(AVFrac *f, INT64 val, INT64 num, INT64 den)
+{
+    num += (den >> 1);
+    if (num >= den) {
+        val += num / den;
+        num = num % den;
+    }
+    f->val = val;
+    f->num = num;
+    f->den = den;
+}
+
+/* set f to (val + 0.5) */
+void av_frac_set(AVFrac *f, INT64 val)
+{
+    f->val = val;
+    f->num = f->den >> 1;
+}
+
+/**
+ * Fractionnal addition to f: f = f + (incr / f->den)
+ *
+ * @param f fractional number
+ * @param incr increment, can be positive or negative
+ */
+void av_frac_add(AVFrac *f, INT64 incr)
+{
+    INT64 num, den;
+
+    num = f->num + incr;
+    den = f->den;
+    if (num < 0) {
+        f->val += num / den;
+        num = num % den;
+        if (num < 0) {
+            num += den;
+            f->val--;
+        }
+    } else if (num >= den) {
+        f->val += num / den;
+        num = num % den;
+    }
+    f->num = num;
+}