gst/base/gstbasesink.*: Repost EOS message while going to PLAYING if still EOS.
authorWim Taymans <wim.taymans@gmail.com>
Sat, 8 Oct 2005 09:58:30 +0000 (09:58 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Sat, 8 Oct 2005 09:58:30 +0000 (09:58 +0000)
Original commit message from CVS:
* gst/base/gstbasesink.c: (gst_base_sink_preroll_queue_flush),
(gst_base_sink_handle_object), (gst_base_sink_event),
(gst_base_sink_wait), (gst_base_sink_handle_event),
(gst_base_sink_change_state):
* gst/base/gstbasesink.h:
Repost EOS message while going to PLAYING if still EOS.
Make sure that when receiving a FLUSH_START we don't attempt
to sync on the clock anymore.

ChangeLog
gst/base/gstbasesink.c
gst/base/gstbasesink.h
libs/gst/base/gstbasesink.c
libs/gst/base/gstbasesink.h

index a452475..a1b7049 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2005-10-08  Wim Taymans  <wim@fluendo.com>
 
+       * gst/base/gstbasesink.c: (gst_base_sink_preroll_queue_flush),
+       (gst_base_sink_handle_object), (gst_base_sink_event),
+       (gst_base_sink_wait), (gst_base_sink_handle_event),
+       (gst_base_sink_change_state):
+       * gst/base/gstbasesink.h:
+       Repost EOS message while going to PLAYING if still EOS.
+       Make sure that when receiving a FLUSH_START we don't attempt
+       to sync on the clock anymore.
+
+2005-10-08  Wim Taymans  <wim@fluendo.com>
+
        * tools/gst-launch.c: (event_loop):
        Better message printout.
 
index d2fc8c5..f70e66a 100644 (file)
@@ -432,6 +432,7 @@ gst_base_sink_preroll_queue_flush (GstBaseSink * basesink, GstPad * pad)
   }
   /* we can't have EOS anymore now */
   basesink->eos = FALSE;
+  basesink->eos_queued = FALSE;
   basesink->preroll_queued = 0;
   basesink->buffers_queued = 0;
   basesink->events_queued = 0;
@@ -461,6 +462,7 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
       case GST_EVENT_EOS:
         basesink->preroll_queued++;
         basesink->eos = TRUE;
+        basesink->eos_queued = TRUE;
         break;
       case GST_EVENT_NEWSEGMENT:
       {
@@ -475,6 +477,14 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
 
         basesink->have_newsegment = TRUE;
 
+        /* any other format with 0 also gives time 0, the other values are
+         * invalid as time though. */
+        if (format != GST_FORMAT_TIME && segment_start == 0) {
+          format = GST_FORMAT_TIME;
+          segment_stop = -1;
+          basesink->segment_base = -1;
+        }
+
         if (format != GST_FORMAT_TIME) {
           GST_DEBUG_OBJECT (basesink,
               "received non time %d NEW_SEGMENT %" G_GINT64_FORMAT
@@ -633,7 +643,7 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
     GST_STATE_UNLOCK (basesink);
 
     /* reacquire stream lock, pad could be flushing now */
-    /* FIXME in glib, if t==0, the lock is still taken... hmmm */
+    /* FIXME in glib, if t==0, the lock is still taken... hmmm.. bug #317802 */
     if (t > 0)
       GST_STREAM_LOCK_FULL (pad, t);
 
@@ -812,18 +822,19 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
       if (bclass->event)
         bclass->event (basesink, event);
 
+      GST_LOCK (basesink);
+      basesink->flushing = TRUE;
+      if (basesink->clock_id) {
+        gst_clock_id_unschedule (basesink->clock_id);
+      }
+      GST_UNLOCK (basesink);
+
       GST_PREROLL_LOCK (pad);
       /* we need preroll after the flush */
       GST_DEBUG_OBJECT (basesink, "flushing, need preroll after flush");
       basesink->need_preroll = TRUE;
       /* unlock from a possible state change/preroll */
       gst_base_sink_preroll_queue_flush (basesink, pad);
-
-      GST_LOCK (basesink);
-      if (basesink->clock_id) {
-        gst_clock_id_unschedule (basesink->clock_id);
-      }
-      GST_UNLOCK (basesink);
       GST_PREROLL_UNLOCK (pad);
 
       /* and we need to commit our state again on the next
@@ -843,6 +854,9 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
       /* now we are completely unblocked and the _chain method
        * will return */
       GST_STREAM_LOCK (pad);
+      GST_LOCK (basesink);
+      basesink->flushing = FALSE;
+      GST_UNLOCK (basesink);
       /* we need new segment info after the flush. */
       basesink->segment_start = -1;
       basesink->segment_stop = -1;
@@ -891,19 +905,27 @@ static GstClockReturn
 gst_base_sink_wait (GstBaseSink * basesink, GstClockTime time)
 {
   GstClockReturn ret;
+  GstClockID id;
+
+  /* no need to attempt a clock wait if we are flushing */
+  if (basesink->flushing) {
+    return GST_CLOCK_UNSCHEDULED;
+  }
 
   /* clock_id should be NULL outside of this function */
   g_assert (basesink->clock_id == NULL);
   g_assert (GST_CLOCK_TIME_IS_VALID (time));
 
-  basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock, time);
+  id = gst_clock_new_single_shot_id (basesink->clock, time);
 
+  basesink->clock_id = id;
   /* release the object lock while waiting */
   GST_UNLOCK (basesink);
-  ret = gst_clock_id_wait (basesink->clock_id, NULL);
-  GST_LOCK (basesink);
 
-  gst_clock_id_unref (basesink->clock_id);
+  ret = gst_clock_id_wait (id, NULL);
+
+  GST_LOCK (basesink);
+  gst_clock_id_unref (id);
   basesink->clock_id = NULL;
 
   return ret;
@@ -1056,6 +1078,7 @@ gst_base_sink_handle_event (GstBaseSink * basesink, GstEvent * event)
         GST_DEBUG_OBJECT (basesink, "Now posting EOS");
         gst_element_post_message (GST_ELEMENT (basesink),
             gst_message_new_eos (GST_OBJECT (basesink)));
+        basesink->eos_queued = FALSE;
       }
       GST_PREROLL_UNLOCK (basesink->sinkpad);
       break;
@@ -1413,7 +1436,6 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
       ret = GST_STATE_CHANGE_ASYNC;
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-    {
       GST_PREROLL_LOCK (basesink->sinkpad);
       /* if we have EOS, we should empty the queue now as there will
        * be no more data received in the chain function.
@@ -1421,7 +1443,17 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
        * we are pushing and syncing the buffers, better start a new
        * thread to do this. */
       if (basesink->eos) {
+        gboolean do_eos = !basesink->eos_queued;
+
         gst_base_sink_preroll_queue_empty (basesink, basesink->sinkpad);
+
+        /* need to post EOS message here if it was not in the preroll queue we
+         * just emptied. */
+        if (do_eos) {
+          GST_DEBUG_OBJECT (basesink, "Now posting EOS");
+          gst_element_post_message (GST_ELEMENT (basesink),
+              gst_message_new_eos (GST_OBJECT (basesink)));
+        }
       } else if (!basesink->have_preroll) {
         /* don't need preroll, but do queue a commit_state */
         GST_DEBUG_OBJECT (basesink,
@@ -1440,7 +1472,6 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
       }
       GST_PREROLL_UNLOCK (basesink->sinkpad);
       break;
-    }
     default:
       break;
   }
index 642e025..5baa7ba 100644 (file)
@@ -72,6 +72,7 @@ struct _GstBaseSink {
   gint          buffers_queued;
   gint          events_queued;
   gboolean       eos;
+  gboolean       eos_queued;
   gboolean       need_preroll;
   gboolean       have_preroll;
   gboolean       playing_async;
@@ -93,6 +94,7 @@ struct _GstBaseSink {
   GstClockID     clock_id;
   GstClockTime   end_time;
   gboolean       sync;
+  gboolean       flushing;
 
   /*< private >*/
   gpointer       _gst_reserved[GST_PADDING];
index d2fc8c5..f70e66a 100644 (file)
@@ -432,6 +432,7 @@ gst_base_sink_preroll_queue_flush (GstBaseSink * basesink, GstPad * pad)
   }
   /* we can't have EOS anymore now */
   basesink->eos = FALSE;
+  basesink->eos_queued = FALSE;
   basesink->preroll_queued = 0;
   basesink->buffers_queued = 0;
   basesink->events_queued = 0;
@@ -461,6 +462,7 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
       case GST_EVENT_EOS:
         basesink->preroll_queued++;
         basesink->eos = TRUE;
+        basesink->eos_queued = TRUE;
         break;
       case GST_EVENT_NEWSEGMENT:
       {
@@ -475,6 +477,14 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
 
         basesink->have_newsegment = TRUE;
 
+        /* any other format with 0 also gives time 0, the other values are
+         * invalid as time though. */
+        if (format != GST_FORMAT_TIME && segment_start == 0) {
+          format = GST_FORMAT_TIME;
+          segment_stop = -1;
+          basesink->segment_base = -1;
+        }
+
         if (format != GST_FORMAT_TIME) {
           GST_DEBUG_OBJECT (basesink,
               "received non time %d NEW_SEGMENT %" G_GINT64_FORMAT
@@ -633,7 +643,7 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
     GST_STATE_UNLOCK (basesink);
 
     /* reacquire stream lock, pad could be flushing now */
-    /* FIXME in glib, if t==0, the lock is still taken... hmmm */
+    /* FIXME in glib, if t==0, the lock is still taken... hmmm.. bug #317802 */
     if (t > 0)
       GST_STREAM_LOCK_FULL (pad, t);
 
@@ -812,18 +822,19 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
       if (bclass->event)
         bclass->event (basesink, event);
 
+      GST_LOCK (basesink);
+      basesink->flushing = TRUE;
+      if (basesink->clock_id) {
+        gst_clock_id_unschedule (basesink->clock_id);
+      }
+      GST_UNLOCK (basesink);
+
       GST_PREROLL_LOCK (pad);
       /* we need preroll after the flush */
       GST_DEBUG_OBJECT (basesink, "flushing, need preroll after flush");
       basesink->need_preroll = TRUE;
       /* unlock from a possible state change/preroll */
       gst_base_sink_preroll_queue_flush (basesink, pad);
-
-      GST_LOCK (basesink);
-      if (basesink->clock_id) {
-        gst_clock_id_unschedule (basesink->clock_id);
-      }
-      GST_UNLOCK (basesink);
       GST_PREROLL_UNLOCK (pad);
 
       /* and we need to commit our state again on the next
@@ -843,6 +854,9 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
       /* now we are completely unblocked and the _chain method
        * will return */
       GST_STREAM_LOCK (pad);
+      GST_LOCK (basesink);
+      basesink->flushing = FALSE;
+      GST_UNLOCK (basesink);
       /* we need new segment info after the flush. */
       basesink->segment_start = -1;
       basesink->segment_stop = -1;
@@ -891,19 +905,27 @@ static GstClockReturn
 gst_base_sink_wait (GstBaseSink * basesink, GstClockTime time)
 {
   GstClockReturn ret;
+  GstClockID id;
+
+  /* no need to attempt a clock wait if we are flushing */
+  if (basesink->flushing) {
+    return GST_CLOCK_UNSCHEDULED;
+  }
 
   /* clock_id should be NULL outside of this function */
   g_assert (basesink->clock_id == NULL);
   g_assert (GST_CLOCK_TIME_IS_VALID (time));
 
-  basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock, time);
+  id = gst_clock_new_single_shot_id (basesink->clock, time);
 
+  basesink->clock_id = id;
   /* release the object lock while waiting */
   GST_UNLOCK (basesink);
-  ret = gst_clock_id_wait (basesink->clock_id, NULL);
-  GST_LOCK (basesink);
 
-  gst_clock_id_unref (basesink->clock_id);
+  ret = gst_clock_id_wait (id, NULL);
+
+  GST_LOCK (basesink);
+  gst_clock_id_unref (id);
   basesink->clock_id = NULL;
 
   return ret;
@@ -1056,6 +1078,7 @@ gst_base_sink_handle_event (GstBaseSink * basesink, GstEvent * event)
         GST_DEBUG_OBJECT (basesink, "Now posting EOS");
         gst_element_post_message (GST_ELEMENT (basesink),
             gst_message_new_eos (GST_OBJECT (basesink)));
+        basesink->eos_queued = FALSE;
       }
       GST_PREROLL_UNLOCK (basesink->sinkpad);
       break;
@@ -1413,7 +1436,6 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
       ret = GST_STATE_CHANGE_ASYNC;
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-    {
       GST_PREROLL_LOCK (basesink->sinkpad);
       /* if we have EOS, we should empty the queue now as there will
        * be no more data received in the chain function.
@@ -1421,7 +1443,17 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
        * we are pushing and syncing the buffers, better start a new
        * thread to do this. */
       if (basesink->eos) {
+        gboolean do_eos = !basesink->eos_queued;
+
         gst_base_sink_preroll_queue_empty (basesink, basesink->sinkpad);
+
+        /* need to post EOS message here if it was not in the preroll queue we
+         * just emptied. */
+        if (do_eos) {
+          GST_DEBUG_OBJECT (basesink, "Now posting EOS");
+          gst_element_post_message (GST_ELEMENT (basesink),
+              gst_message_new_eos (GST_OBJECT (basesink)));
+        }
       } else if (!basesink->have_preroll) {
         /* don't need preroll, but do queue a commit_state */
         GST_DEBUG_OBJECT (basesink,
@@ -1440,7 +1472,6 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
       }
       GST_PREROLL_UNLOCK (basesink->sinkpad);
       break;
-    }
     default:
       break;
   }
index 642e025..5baa7ba 100644 (file)
@@ -72,6 +72,7 @@ struct _GstBaseSink {
   gint          buffers_queued;
   gint          events_queued;
   gboolean       eos;
+  gboolean       eos_queued;
   gboolean       need_preroll;
   gboolean       have_preroll;
   gboolean       playing_async;
@@ -93,6 +94,7 @@ struct _GstBaseSink {
   GstClockID     clock_id;
   GstClockTime   end_time;
   gboolean       sync;
+  gboolean       flushing;
 
   /*< private >*/
   gpointer       _gst_reserved[GST_PADDING];