oggdec: Set dts when known
authorDavid Conrad <lessen42@gmail.com>
Mon, 11 Jan 2010 05:51:09 +0000 (05:51 +0000)
committerDavid Conrad <lessen42@gmail.com>
Mon, 11 Jan 2010 05:51:09 +0000 (05:51 +0000)
Originally committed as revision 21134 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavformat/oggdec.c
libavformat/oggdec.h
libavformat/oggparsedirac.c
libavformat/oggparsetheora.c

index 33b453c..26a6af2 100644 (file)
@@ -119,6 +119,7 @@ ogg_reset (struct ogg * ogg)
         os->psize = 0;
         os->granule = -1;
         os->lastpts = AV_NOPTS_VALUE;
+        os->lastdts = AV_NOPTS_VALUE;
         os->nsegs = 0;
         os->segp = 0;
     }
@@ -428,16 +429,18 @@ ogg_get_headers (AVFormatContext * s)
 }
 
 static uint64_t
-ogg_gptopts (AVFormatContext * s, int i, uint64_t gp)
+ogg_gptopts (AVFormatContext * s, int i, uint64_t gp, int64_t *dts)
 {
     struct ogg *ogg = s->priv_data;
     struct ogg_stream *os = ogg->streams + i;
     uint64_t pts = AV_NOPTS_VALUE;
 
     if(os->codec->gptopts){
-        pts = os->codec->gptopts(s, i, gp);
+        pts = os->codec->gptopts(s, i, gp, dts);
     } else {
         pts = gp;
+        if (dts)
+            *dts = pts;
     }
 
     return pts;
@@ -474,7 +477,7 @@ ogg_get_length (AVFormatContext * s)
 
     if (idx != -1){
         s->streams[idx]->duration =
-            ogg_gptopts (s, idx, ogg->streams[idx].granule);
+            ogg_gptopts (s, idx, ogg->streams[idx].granule, NULL);
     }
 
     ogg->size = size;
@@ -534,12 +537,16 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
         pkt->pts = os->lastpts;
         os->lastpts = AV_NOPTS_VALUE;
     }
+    if (os->lastdts != AV_NOPTS_VALUE) {
+        pkt->dts = os->lastdts;
+        os->lastdts = AV_NOPTS_VALUE;
+    }
     if (os->page_end) {
         if (os->granule != -1LL) {
             if (os->codec && os->codec->granule_is_start)
-                pkt->pts    = ogg_gptopts(s, idx, os->granule);
+                pkt->pts    = ogg_gptopts(s, idx, os->granule, &pkt->dts);
             else
-                os->lastpts = ogg_gptopts(s, idx, os->granule);
+                os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
             os->granule = -1LL;
         } else
             av_log(s, AV_LOG_WARNING, "Packet is missing granule\n");
@@ -579,7 +586,7 @@ ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
     while (url_ftell(bc) < pos_limit && !ogg_read_page (s, &i)) {
         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
             ogg->streams[i].codec && i == stream_index) {
-            pts = ogg_gptopts(s, i, ogg->streams[i].granule);
+            pts = ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
             // FIXME: this is the position of the packet after the one with above
             // pts.
             *pos_arg = url_ftell(bc);
index 4db3fa6..7c677a1 100644 (file)
@@ -40,7 +40,12 @@ struct ogg_codec {
      */
     int (*header)(AVFormatContext *, int);
     int (*packet)(AVFormatContext *, int);
-    uint64_t (*gptopts)(AVFormatContext *, int, uint64_t);
+    /**
+     * Translate a granule into a timestamp.
+     * Will set dts if non-null and known.
+     * @return pts
+     */
+    uint64_t (*gptopts)(AVFormatContext *, int, uint64_t, int64_t *dts);
     /**
      * 1 if granule is the start time of the associated packet.
      * 0 if granule is the end time of the associated packet.
@@ -60,6 +65,7 @@ struct ogg_stream {
     uint32_t seq;
     uint64_t granule;
     int64_t lastpts;
+    int64_t lastdts;
     int flags;
     const struct ogg_codec *codec;
     int header;
index fc1a193..5a907ec 100644 (file)
@@ -47,7 +47,8 @@ static int dirac_header(AVFormatContext *s, int idx)
 }
 
 // various undocument things: granule is signed (only for dirac!)
-static uint64_t dirac_gptopts(AVFormatContext *s, int idx, int64_t gp)
+static uint64_t dirac_gptopts(AVFormatContext *s, int idx, int64_t gp,
+                              int64_t *dts_out)
 {
     struct ogg *ogg = s->priv_data;
     struct ogg_stream *os = ogg->streams + idx;
@@ -59,6 +60,9 @@ static uint64_t dirac_gptopts(AVFormatContext *s, int idx, int64_t gp)
     if (!dist)
         os->pflags |= PKT_FLAG_KEY;
 
+    if (dts_out)
+        *dts_out = dts;
+
     return pts;
 }
 
@@ -79,7 +83,8 @@ static int old_dirac_header(AVFormatContext *s, int idx)
     return 1;
 }
 
-static uint64_t old_dirac_gptopts(AVFormatContext *s, int idx, uint64_t gp)
+static uint64_t old_dirac_gptopts(AVFormatContext *s, int idx, uint64_t gp,
+                                  int64_t *dts)
 {
     struct ogg *ogg = s->priv_data;
     struct ogg_stream *os = ogg->streams + idx;
index 0d74116..8b35a47 100644 (file)
@@ -123,7 +123,7 @@ theora_header (AVFormatContext * s, int idx)
 }
 
 static uint64_t
-theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp)
+theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, int64_t *dts)
 {
     struct ogg *ogg = ctx->priv_data;
     struct ogg_stream *os = ogg->streams + idx;
@@ -137,6 +137,9 @@ theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp)
     if(!pframe)
         os->pflags |= PKT_FLAG_KEY;
 
+    if (dts)
+        *dts = iframe + pframe;
+
     return iframe + pframe;
 }