ext/alsa/gstalsa.c: start clock on PAUSED=>PLAYING, not later
authorBenjamin Otte <otte@gnome.org>
Sat, 31 Jan 2004 17:19:21 +0000 (17:19 +0000)
committerBenjamin Otte <otte@gnome.org>
Sat, 31 Jan 2004 17:19:21 +0000 (17:19 +0000)
Original commit message from CVS:
2004-01-31  Benjamin Otte  <in7y118@public.uni-hamburg.de>

* ext/alsa/gstalsa.c: (gst_alsa_change_state), (gst_alsa_start):
start clock on PAUSED=>PLAYING, not later
* ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event):
extract correct time for different discont formats
(gst_alsa_sink_get_time):
don't segfault when no format is negotiated yet, just return 0
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_event),
(gst_ogg_demux_handle_event), (gst_ogg_demux_push),
(gst_ogg_pad_push):
handle flush and discont events correctly
* ext/vorbis/vorbisdec.c: (vorbis_dec_event), (vorbis_dec_chain):
handle discont events correctly

ChangeLog
ext/alsa/gstalsa.c
ext/alsa/gstalsasink.c
ext/ogg/gstoggdemux.c
ext/vorbis/vorbisdec.c

index 0ecaac1..94b685e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2004-01-31  Benjamin Otte  <in7y118@public.uni-hamburg.de>
+
+       * ext/alsa/gstalsa.c: (gst_alsa_change_state), (gst_alsa_start):
+         start clock on PAUSED=>PLAYING, not later
+       * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event):
+         extract correct time for different discont formats
+       (gst_alsa_sink_get_time):
+         don't segfault when no format is negotiated yet, just return 0
+       * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_event),
+       (gst_ogg_demux_handle_event), (gst_ogg_demux_push),
+       (gst_ogg_pad_push):
+         handle flush and discont events correctly
+       * ext/vorbis/vorbisdec.c: (vorbis_dec_event), (vorbis_dec_chain):
+         handle discont events correctly
+
 2004-01-31  Thomas Vander Stichele  <thomas at apestaart dot org>
 
        * gst-libs/gst/play/play.c: (gst_play_error_quark),
index b41765b..85b297e 100644 (file)
@@ -720,8 +720,8 @@ gst_alsa_change_state (GstElement *element)
         GST_ERROR_OBJECT (this, "Error unpausing sound: %s", snd_strerror (err));
         return GST_STATE_FAILURE;
       }
-      gst_alsa_clock_start (this->clock);
     }
+    gst_alsa_clock_start (this->clock);
     break;
   case GST_STATE_PLAYING_TO_PAUSED:
     if (GST_ALSA_CAPS_IS_SET (this, GST_ALSA_CAPS_PAUSE)) {
@@ -836,7 +836,7 @@ gst_alsa_start (GstAlsa *this)
       g_assert_not_reached ();
       break;
   }
-  gst_alsa_clock_start (this->clock);
+  /* gst_alsa_clock_start (this->clock); */
   return TRUE;
 }
 void
index 3c205cf..e82698d 100644 (file)
@@ -215,7 +215,16 @@ gst_alsa_sink_check_event (GstAlsaSink *sink, gint pad_nr)
          }
          if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &value)) {
            gst_element_set_time (GST_ELEMENT (this), value);
-          }
+          } else if (gst_event_discont_get_value (event, GST_FORMAT_DEFAULT, &value)) {
+           value = gst_alsa_samples_to_timestamp (this, value); 
+           gst_element_set_time (GST_ELEMENT (this), value);
+          } else if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &value)) {
+           value = gst_alsa_bytes_to_timestamp (this, value); 
+           gst_element_set_time (GST_ELEMENT (this), value);
+         } else {
+           GST_ERROR_OBJECT (this, "couldn't extract time from discont event. Bad things might happen!");
+         }
+
 
          break;
         }
@@ -471,7 +480,7 @@ gst_alsa_sink_get_time (GstAlsa *this)
 {
   snd_pcm_sframes_t delay;
   
-  if (snd_pcm_delay (this->handle, &delay) == 0) {
+  if (snd_pcm_delay (this->handle, &delay) == 0 && this->format) {
     return GST_SECOND * (GstClockTime) (this->transmitted > delay ? this->transmitted - delay : 0) / this->format->rate;
   } else {
     return 0;
index a24c250..c6c9a04 100644 (file)
@@ -61,15 +61,32 @@ typedef struct {
   ogg_stream_state     stream;
   guint64              offset; /* end offset of last buffer */
   guint64              known_offset; /* last known offset */
+  gint64               packetno; /* number of next expected packet */
+  
   guint64              length; /* length of stream or 0 */
-  glong                        pages;
+  glong                        pages; /* number of pages in stream or 0 */
+
+  guint                        flags;
 } GstOggPad;
 
+typedef enum {
+  GST_OGG_PAD_NEEDS_DISCONT    = (1 << 0),
+  GST_OGG_PAD_NEEDS_FLUSH      = (1 << 1)
+}
+GstOggPadFlags;
+
 /* all information needed for one ogg chain (relevant for chained bitstreams) */
 typedef struct {
   GSList *             pads; /* list of GstOggPad */
 } GstOggChain;
 #define CURRENT_CHAIN(ogg) (&g_array_index ((ogg)->chains, GstOggChain, (ogg)->current_chain))
+#define FOR_PAD_IN_CURRENT_CHAIN(ogg, _pad, ...) G_STMT_START{                 \
+  GSList *_walk;                                                               \
+  for (_walk = CURRENT_CHAIN (ogg)->pads; _walk; _walk = g_slist_next (_walk)) { \
+    GstOggPad *_pad = (GstOggPad *) _walk->data;                               \
+    __VA_ARGS__                                                                        \
+  }                                                                            \
+}G_STMT_END
 
 typedef enum {
   GST_OGG_FLAG_BOS = GST_ELEMENT_FLAG_LAST,
@@ -307,19 +324,19 @@ gst_ogg_demux_src_event (GstPad *pad, GstEvent *event)
   cur = gst_ogg_get_pad_by_pad (ogg, pad);
   /* FIXME: optimize this so events from inactive chains work? 
    * in theory there shouldn't be an exisiting pad for inactive chains */
-  if (cur == NULL) return FALSE;
+  if (cur == NULL) goto error;
   
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_SEEK:
     {
       gint64 offset;
       if (GST_EVENT_SEEK_FORMAT (event) != GST_FORMAT_DEFAULT)
-       break;
+       goto error;
       offset = GST_EVENT_SEEK_OFFSET (event);
       switch (GST_EVENT_SEEK_METHOD (event)) {
        case GST_SEEK_METHOD_END:
          if (cur->length == 0 || offset > 0)
-           goto out;
+           goto error;
          offset = cur->length + offset;
          break;
        case GST_SEEK_METHOD_CUR:
@@ -329,21 +346,23 @@ gst_ogg_demux_src_event (GstPad *pad, GstEvent *event)
          break;
        default:
          g_warning ("invalid seek method in seek event");
-         break;
+         goto error;
       }
-      g_print ("DEBUG: oggdemux: offset %lld, known %lld\n", offset, cur->known_offset);
       if (offset < cur->known_offset) {
-       GstEvent *restart = gst_event_new_seek (GST_FORMAT_BYTES | GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH, 0);
+       GstEvent *restart = gst_event_new_seek (GST_FORMAT_BYTES | GST_SEEK_METHOD_SET | GST_EVENT_SEEK_FLAGS (event), 0);
        if (!gst_pad_send_event (GST_PAD_PEER (ogg->sinkpad), restart))
-         break;
-      }
-      else {
-        GstEvent *flush = gst_event_new_flush ();
-       if (!gst_pad_send_event (GST_PAD_PEER (ogg->sinkpad), flush))
-         break;
+         goto error;
+      } else {
+       FOR_PAD_IN_CURRENT_CHAIN (ogg, pad,
+         if (GST_PAD_IS_USABLE (pad->pad))
+           gst_pad_push (pad->pad, GST_DATA (gst_event_new (GST_EVENT_FLUSH)));
+       );
       }
 
       GST_OGG_SET_STATE (ogg, GST_OGG_STATE_SEEK);
+      FOR_PAD_IN_CURRENT_CHAIN (ogg, pad,
+       pad->flags |= GST_OGG_PAD_NEEDS_DISCONT;
+      );
       GST_DEBUG_OBJECT (ogg, "initiating seeking to offset %"G_GUINT64_FORMAT, offset);
       ogg->seek_pad = cur; 
       ogg->seek_to = offset;
@@ -351,10 +370,12 @@ gst_ogg_demux_src_event (GstPad *pad, GstEvent *event)
       return TRUE;
     }
     default:
-      break;
+      return gst_pad_event_default (pad, event);
   }
 
-out:
+  g_assert_not_reached ();
+  
+error:
   gst_event_unref (event);
   return FALSE;
 }
@@ -386,6 +407,9 @@ gst_ogg_demux_handle_event (GstPad *pad, GstEvent *event)
       ogg_sync_reset (&ogg->sync);
       gst_event_unref (event);
       GST_FLAG_UNSET (ogg, GST_OGG_FLAG_WAIT_FOR_DISCONT);
+      FOR_PAD_IN_CURRENT_CHAIN (ogg, pad,
+       pad->flags |= GST_OGG_PAD_NEEDS_DISCONT;
+      );
       break;
     case GST_EVENT_EOS:
       if (ogg->state == GST_OGG_STATE_SETUP) {
@@ -648,14 +672,6 @@ br:
           GST_DEBUG_OBJECT (ogg, "ended seek at offset %"G_GUINT64_FORMAT" (requested  %"G_GUINT64_FORMAT, cur->known_offset, ogg->seek_to);
          ogg->seek_pad = NULL;
          ogg->seek_to = 0;
-         /* send discont everywhere */
-         for (walk = CURRENT_CHAIN (ogg)->pads; walk; walk = g_slist_next (walk)) {
-           GstOggPad *send = (GstOggPad *) walk->data;
-           GstEvent *event = gst_event_new_discontinuous (FALSE, 
-               GST_FORMAT_DEFAULT, send->known_offset);
-           if (GST_PAD_IS_USABLE (send->pad))
-             gst_pad_push (send->pad, GST_DATA (event));
-         }
        }
       }
       /* fallthrough */
@@ -696,7 +712,7 @@ gst_ogg_pad_push (GstOggDemux *ogg, GstOggPad *pad)
        gst_ogg_pad_reset (ogg, pad);
        break;
       case 1: {
-       /* only push data when plazing, not during seek or similar */
+       /* only push data when playing, not during seek or similar */
        if (ogg->state != GST_OGG_STATE_PLAY)
          continue;
        if (!pad->pad) {
@@ -720,6 +736,18 @@ gst_ogg_pad_push (GstOggDemux *ogg, GstOggPad *pad)
          gst_pad_set_active (pad->pad, TRUE);
          gst_element_add_pad (GST_ELEMENT (ogg), pad->pad);
        }
+       /* check for discont */
+       if (packet.packetno != pad->packetno++) {
+         pad->flags |= GST_OGG_PAD_NEEDS_DISCONT;
+         pad->packetno = packet.packetno + 1;
+       }
+       /* send discont if needed */
+       if ((pad->flags & GST_OGG_PAD_NEEDS_DISCONT) && GST_PAD_IS_USABLE (pad->pad)) {
+         GstEvent *event = gst_event_new_discontinuous (FALSE, 
+           GST_FORMAT_DEFAULT, pad->known_offset); /* FIXME: this might be wrong because we can only use the last known offset */
+         gst_pad_push (pad->pad, GST_DATA (event));
+         pad->flags &= (~GST_OGG_PAD_NEEDS_DISCONT);
+       };
        /* optimization: use a bufferpool containing the ogg packet? */
        buf = gst_pad_alloc_buffer (pad->pad, GST_BUFFER_OFFSET_NONE, packet.bytes);
        memcpy (buf->data, packet.packet, packet.bytes);
index 74c3f15..82cb749 100644 (file)
@@ -247,7 +247,7 @@ vorbis_dec_src_event (GstPad *pad, GstEvent *event)
 static void
 vorbis_dec_event (GstVorbisDec *dec, GstEvent *event)
 {
-  guint64 value;
+  guint64 value, time, bytes;
   
   GST_LOG_OBJECT (dec, "handling event");
   switch (GST_EVENT_TYPE (event)) {
@@ -259,12 +259,29 @@ vorbis_dec_event (GstVorbisDec *dec, GstEvent *event)
        GST_WARNING_OBJECT (dec, 
            "discont event didn't include offset, we might set it wrong now");
       }
-      dec->packetno = 3;
+      if (dec->packetno < 3) {
+       if (dec->granulepos != 0)
+         GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("can't handle discont before parsing first 3 packets"));
+       dec->packetno = 0;
+       gst_pad_push (dec->srcpad, GST_DATA (gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, (guint64) 0, 
+             GST_FORMAT_DEFAULT, (guint64) 0, GST_FORMAT_BYTES, (guint64) 0, 0)));
+      } else {
+       dec->packetno = 3;
+       /* if one of them works, all of them work */
+       if (vorbis_dec_from_granulepos (dec, GST_FORMAT_TIME, dec->granulepos, &time) &&
+           vorbis_dec_from_granulepos (dec, GST_FORMAT_DEFAULT, dec->granulepos, &value) &&
+           vorbis_dec_from_granulepos (dec, GST_FORMAT_BYTES, dec->granulepos, &bytes)) {
+         gst_pad_push (dec->srcpad, GST_DATA (gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time, 
+               GST_FORMAT_DEFAULT, value, GST_FORMAT_BYTES, bytes, 0)));
+       } else {
+         GST_ERROR_OBJECT (dec, "failed to parse data for DISCONT event, not sending any");
+       }
+      }
       break;
     default:
+      gst_pad_event_default (dec->sinkpad, event);
       break;
   }
-  gst_pad_event_default (dec->sinkpad, event);
 }
 
 static void
@@ -292,7 +309,7 @@ vorbis_dec_chain (GstPad *pad, GstData *data)
     if (packet.packet[0] / 2 != packet.packetno) {
       /* FIXME: just skip? */
       GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
-         (NULL), ("unexpected packet type %d", (gint) packet.packet[0]));
+         (NULL), ("unexpected packet type %d, expected %d", (gint) packet.packet[0], (gint) packet.packetno));
       gst_data_unref (data);
       return;
     }