ext/vorbis/vorbisdec.*: Vorbis streams can be embedded in other container formats...
authorTim-Philipp Müller <tim@centricular.net>
Thu, 20 Oct 2005 16:01:43 +0000 (16:01 +0000)
committerTim-Philipp Müller <tim@centricular.net>
Thu, 20 Oct 2005 16:01:43 +0000 (16:01 +0000)
Original commit message from CVS:
* ext/vorbis/vorbisdec.c: (vorbis_dec_sink_event),
(vorbis_handle_data_packet), (vorbis_dec_chain),
(vorbis_dec_change_state):
* ext/vorbis/vorbisdec.h:
Vorbis streams can be embedded in other container formats
than ogg, container formats where the demuxer might set
timestamps on encoded vorbis buffers instead of those silly
granulepos thingies. In short: make vorbisdec handle
timestamps on incoming buffers as well.

ChangeLog
ext/vorbis/vorbisdec.c
ext/vorbis/vorbisdec.h

index 24672bca93bc4ee1f722c5f8c58ce36728457a11..9c04b8f0bd7c4ee8db28c4a806449c4fd7f04178 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2005-10-20  Tim-Philipp Müller  <tim at centricular dot net>
+
+       * ext/vorbis/vorbisdec.c: (vorbis_dec_sink_event),
+       (vorbis_handle_data_packet), (vorbis_dec_chain),
+       (vorbis_dec_change_state):
+       * ext/vorbis/vorbisdec.h:
+         Vorbis streams can be embedded in other container formats
+         than ogg, container formats where the demuxer might set 
+         timestamps on encoded vorbis buffers instead of those silly 
+         granulepos thingies. In short: make vorbisdec handle 
+         timestamps on incoming buffers as well.
+
 2005-10-20  Wim Taymans  <wim@fluendo.com>
 
        * gst/playback/gstplaybasebin.c: (group_destroy),
index 9f9651d0ce9436698c2f08d6cdb69c119268f0e7..d4e2e19668a0a87e7426dd04b343556df76c73e9 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "vorbisdec.h"
 #include <string.h>
+#include <gst/audio/audio.h>
 #include <gst/tag/tag.h>
 #include <gst/audio/multichannel.h>
 
@@ -452,6 +453,9 @@ vorbis_dec_sink_event (GstPad * pad, GstEvent * event)
       dec->segment_base = base;
 
       dec->granulepos = -1;
+      dec->cur_timestamp = GST_CLOCK_TIME_NONE;
+      dec->prev_timestamp = GST_CLOCK_TIME_NONE;
+
 #ifdef HAVE_VORBIS_SYNTHESIS_RESTART
       vorbis_synthesis_restart (&dec->vd);
 #endif
@@ -791,6 +795,18 @@ vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet)
   }
   GST_BUFFER_DURATION (out) = sample_count * GST_SECOND / vd->vi.rate;
 
+  if (vd->cur_timestamp != GST_CLOCK_TIME_NONE) {
+    GST_BUFFER_TIMESTAMP (out) = vd->cur_timestamp;
+    GST_DEBUG ("cur_timestamp: %" GST_TIME_FORMAT " + %" GST_TIME_FORMAT " = % "
+        GST_TIME_FORMAT, GST_TIME_ARGS (vd->cur_timestamp),
+        GST_TIME_ARGS (GST_BUFFER_DURATION (out)),
+        GST_TIME_ARGS (vd->cur_timestamp + GST_BUFFER_DURATION (out)));
+    vd->cur_timestamp += GST_BUFFER_DURATION (out);
+    GST_BUFFER_OFFSET (out) = GST_CLOCK_TIME_TO_FRAMES (vd->cur_timestamp,
+        vd->vi.rate);
+    GST_BUFFER_OFFSET_END (out) = GST_BUFFER_OFFSET (out) + sample_count;
+  }
+
   if (vd->granulepos != -1)
     vd->granulepos += sample_count;
 
@@ -847,6 +863,21 @@ vorbis_dec_chain (GstPad * pad, GstBuffer * buffer)
     GST_ELEMENT_ERROR (vd, STREAM, DECODE, (NULL), ("empty buffer received"));
     return GST_FLOW_ERROR;
   }
+
+  /* only ogg has granulepos, demuxers of other container formats 
+   * might provide us with timestamps instead (e.g. matroskademux) */
+  if (GST_BUFFER_OFFSET_END (buffer) == GST_BUFFER_OFFSET_NONE &&
+      GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE) {
+    /* we might get multiple consecutive buffers with the same timestamp */
+    if (GST_BUFFER_TIMESTAMP (buffer) != vd->prev_timestamp) {
+      vd->cur_timestamp = GST_BUFFER_TIMESTAMP (buffer);
+      vd->prev_timestamp = GST_BUFFER_TIMESTAMP (buffer);
+    }
+  } else {
+    vd->cur_timestamp = GST_CLOCK_TIME_NONE;
+    vd->prev_timestamp = GST_CLOCK_TIME_NONE;
+  }
+
   /* make ogg_packet out of the buffer */
   packet.packet = GST_BUFFER_DATA (buffer);
   packet.bytes = GST_BUFFER_SIZE (buffer);
@@ -860,8 +891,8 @@ vorbis_dec_chain (GstPad * pad, GstBuffer * buffer)
    */
   packet.e_o_s = 0;
 
-  GST_DEBUG_OBJECT (vd, "vorbis granule: %" G_GUINT64_FORMAT,
-      packet.granulepos);
+  GST_DEBUG_OBJECT (vd, "vorbis granule: %" G_GINT64_FORMAT,
+      (gint64) packet.granulepos);
 
   /* switch depending on packet type */
   if (packet.packet[0] & 1) {
@@ -874,8 +905,8 @@ vorbis_dec_chain (GstPad * pad, GstBuffer * buffer)
     result = vorbis_handle_data_packet (vd, &packet);
   }
 
-  GST_DEBUG_OBJECT (vd, "offset end: %" G_GUINT64_FORMAT,
-      GST_BUFFER_OFFSET_END (buffer));
+  GST_DEBUG_OBJECT (vd, "offset end: %" G_GINT64_FORMAT,
+      (gint64) GST_BUFFER_OFFSET_END (buffer));
 
 done:
   gst_buffer_unref (buffer);
@@ -897,6 +928,8 @@ vorbis_dec_change_state (GstElement * element, GstStateChange transition)
       vorbis_info_init (&vd->vi);
       vorbis_comment_init (&vd->vc);
       vd->initialized = FALSE;
+      vd->cur_timestamp = GST_CLOCK_TIME_NONE;
+      vd->prev_timestamp = GST_CLOCK_TIME_NONE;
       vd->granulepos = -1;
       vd->packetno = 0;
       break;
index 6ca7fd378a3b446317583d437e0bc258e5198e4d..4c0136690befaf0928ea85408f994b0995e6e33a 100644 (file)
@@ -63,6 +63,9 @@ struct _GstVorbisDec {
   gint64  segment_start;
   gint64  segment_stop;
   gint64  segment_base;
+
+  GstClockTime          cur_timestamp; /* only used with non-ogg container formats */
+  GstClockTime          prev_timestamp; /* only used with non-ogg container formats */
 };
 
 struct _GstVorbisDecClass {