docs/design/part-seeking.txt: Some small additions.
authorWim Taymans <wim.taymans@gmail.com>
Thu, 21 Jul 2005 17:22:13 +0000 (17:22 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Thu, 21 Jul 2005 17:22:13 +0000 (17:22 +0000)
Original commit message from CVS:
* docs/design/part-seeking.txt:
Some small additions.

* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
(gst_base_sink_get_times), (gst_base_sink_do_sync),
(gst_base_sink_activate_push), (gst_base_sink_activate_pull):
* gst/base/gstbasesink.h:
discont values are gint64, handle the math correctly.

* gst/base/gstbasesrc.c: (gst_base_src_loop):
Make the basesrc report error if the source pad is not linked.

* gst/gstqueue.c: (gst_queue_link_src), (gst_queue_chain),
(gst_queue_loop), (gst_queue_handle_src_query),
(gst_queue_src_activate_push):
Make queue collect data even if the srcpad is not linked.
Start pushing out data as soon as it is linked.

* gst/gstutils.c: (gst_element_unlink), (gst_flow_get_name):
* gst/gstutils.h:
Added gst_flow_get_name() to ease error reporting.

12 files changed:
ChangeLog
docs/design/part-seeking.txt
gst/base/gstbasesink.c
gst/base/gstbasesink.h
gst/base/gstbasesrc.c
gst/gstqueue.c
gst/gstutils.c
gst/gstutils.h
libs/gst/base/gstbasesink.c
libs/gst/base/gstbasesink.h
libs/gst/base/gstbasesrc.c
plugins/elements/gstqueue.c

index 684298d..465226d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2005-07-21  Wim Taymans  <wim@fluendo.com>
+
+       * docs/design/part-seeking.txt:
+       Some small additions.
+
+       * gst/base/gstbasesink.c: (gst_base_sink_handle_object),
+       (gst_base_sink_get_times), (gst_base_sink_do_sync),
+       (gst_base_sink_activate_push), (gst_base_sink_activate_pull):
+       * gst/base/gstbasesink.h:
+       discont values are gint64, handle the math correctly.
+
+       * gst/base/gstbasesrc.c: (gst_base_src_loop):
+       Make the basesrc report error if the source pad is not linked.
+
+       * gst/gstqueue.c: (gst_queue_link_src), (gst_queue_chain),
+       (gst_queue_loop), (gst_queue_handle_src_query),
+       (gst_queue_src_activate_push):
+       Make queue collect data even if the srcpad is not linked.
+       Start pushing out data as soon as it is linked.
+
+       * gst/gstutils.c: (gst_element_unlink), (gst_flow_get_name):
+       * gst/gstutils.h:
+       Added gst_flow_get_name() to ease error reporting.
+
 2005-07-20  Wim Taymans  <wim@fluendo.com>
 
        * gst/gstmessage.c: (gst_message_new_segment_start),
index b2c81c4..c8c8367 100644 (file)
@@ -2,7 +2,7 @@ Seeking
 -------
 
 Seeking in GStreamer means configuring the pipeline for playback of the
-media between a certain start and stop time.
+media between a certain start and stop time, called a segment.
 
 Different kinds of seeking exist:
 
@@ -30,6 +30,10 @@ earliest element in the pipeline, typically a demuxer. After receiving
 the message, the application can reconnect the pipeline or issue other
 seek events in the pipeline.
 
+The seek can also  change the playback speed of the configured segment.
+A speed of 1.0 is normal speed, 2.0 is double speed. Negative values
+mean backward playback.
+
 
 Generating seeking events
 -------------------------
index 815bc4b..3d2197d 100644 (file)
@@ -472,8 +472,7 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
         /* the discont event is needed to bring the buffer timestamps to the
          * stream time */
         if (!gst_event_discont_get_value (event, GST_FORMAT_TIME,
-                (gint64 *) & basesink->discont_start,
-                (gint64 *) & basesink->discont_stop)) {
+                &basesink->discont_start, &basesink->discont_stop)) {
           basesink->discont_start = 0;
           basesink->discont_stop = 0;
         }
@@ -730,15 +729,26 @@ gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
 
   timestamp = GST_BUFFER_TIMESTAMP (buffer);
   if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+    GstClockTimeDiff diff;
+
     /* bring timestamp to stream time using last
      * discont offset. */
-    timestamp -= basesink->discont_start;
+    if ((diff = timestamp - basesink->discont_start) < 0)
+      goto too_late;
+
     /* get duration to calculate end time */
     duration = GST_BUFFER_DURATION (buffer);
     if (GST_CLOCK_TIME_IS_VALID (duration)) {
-      *end = timestamp + duration;
+      *end = diff + duration;
     }
-    *start = timestamp;
+    *start = diff;
+  }
+  return;
+
+too_late:
+  {
+    *start = GST_CLOCK_TIME_NONE;
+    *end = GST_CLOCK_TIME_NONE;
   }
 }
 
index c7fc83e..c9b2ffa 100644 (file)
@@ -67,8 +67,8 @@ struct _GstBaseSink {
   GstClockTime   end_time;
 
   gboolean      have_discont;
-  GstClockTime  discont_start;
-  GstClockTime  discont_stop;
+  GstClockTimeDiff      discont_start;
+  GstClockTimeDiff      discont_stop;
 
   gboolean       eos;
   gboolean       need_preroll;
index cdacbd0..77b1e20 100644 (file)
@@ -702,11 +702,11 @@ pause:
   {
     GST_DEBUG_OBJECT (src, "pausing task");
     gst_pad_pause_task (pad);
-    if (GST_FLOW_IS_FATAL (ret)) {
+    if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
       /* for fatal errors we post an error message */
       GST_ELEMENT_ERROR (src, STREAM, STOPPED,
-          ("streaming stopped, reason %d", ret),
-          ("streaming stopped, reason %d", ret));
+          ("streaming stopped, reason %s", gst_flow_get_name (ret)),
+          ("streaming stopped, reason %s", gst_flow_get_name (ret)));
       gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
     }
     return;
index 971d4c4..74bbd70 100644 (file)
@@ -29,6 +29,7 @@
 #include "gstevent.h"
 #include "gstinfo.h"
 #include "gsterror.h"
+#include "gstutils.h"
 
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -406,10 +407,28 @@ static GstPadLinkReturn
 gst_queue_link_src (GstPad * pad, GstPad * peer)
 {
   GstPadLinkReturn result = GST_PAD_LINK_OK;
+  GstQueue *queue;
+
+  queue = GST_QUEUE (gst_pad_get_parent (pad));
+
+  GST_DEBUG ("queue linking source pad");
 
-  /* FIXME, see if we need to push or get pulled */
-  if (GST_PAD_LINKFUNC (peer))
+  if (GST_PAD_LINKFUNC (peer)) {
     result = GST_PAD_LINKFUNC (peer) (peer, pad);
+  }
+
+  if (GST_PAD_LINK_SUCCESSFUL (result)) {
+    GST_QUEUE_MUTEX_LOCK (queue);
+    if (queue->srcresult == GST_FLOW_OK) {
+      gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
+      GST_DEBUG ("starting task as pad is linked");
+    } else {
+      GST_DEBUG ("not starting task reason %s",
+          gst_flow_get_name (queue->srcresult));
+    }
+    GST_QUEUE_MUTEX_UNLOCK (queue);
+  }
+  gst_object_unref (queue);
 
   return result;
 }
@@ -673,9 +692,10 @@ out_unref:
 out_flushing:
   {
     GstFlowReturn ret = queue->srcresult;
+    const gchar *flowname = gst_flow_get_name (ret);
 
     GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-        "exit because task paused, reason:  %d", ret);
+        "exit because task paused, reason: %s", flowname);
     GST_QUEUE_MUTEX_UNLOCK (queue);
 
     gst_buffer_unref (buffer);
@@ -746,13 +766,18 @@ restart:
     /* can opt to check for srcresult here but the push should
      * return an error value that is more accurate */
     if (result != GST_FLOW_OK) {
+      const gchar *flowname;
+
+      flowname = gst_flow_get_name (result);
+
       queue->srcresult = result;
       if (GST_FLOW_IS_FATAL (result)) {
         GST_ELEMENT_ERROR (queue, STREAM, STOPPED,
-            ("streaming stopped, reason %d", result),
-            ("streaming stopped, reason %d", result));
+            ("streaming stopped, reason %s", flowname),
+            ("streaming stopped, reason %s", flowname));
         gst_pad_push_event (queue->srcpad, gst_event_new (GST_EVENT_EOS));
       }
+      GST_DEBUG ("pausing queue, reason %s", flowname);
       gst_pad_pause_task (queue->srcpad);
     }
   } else {
@@ -760,6 +785,7 @@ restart:
       /* all incomming data is now unexpected */
       queue->srcresult = GST_FLOW_UNEXPECTED;
       /* and we don't need to process anymore */
+      GST_DEBUG ("pausing queue, we're EOS now");
       gst_pad_pause_task (queue->srcpad);
       restart = FALSE;
     }
@@ -780,8 +806,10 @@ restart:
 
 out_flushing:
   {
+    const gchar *flowname = gst_flow_get_name (queue->srcresult);
+
     GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-        "exit because task paused, reason:  %d", queue->srcresult);
+        "exit because task paused, reason:  %s", flowname);
     GST_QUEUE_MUTEX_UNLOCK (queue);
 
     return;
@@ -890,7 +918,13 @@ gst_queue_src_activate_push (GstPad * pad, gboolean active)
   if (active) {
     GST_QUEUE_MUTEX_LOCK (queue);
     queue->srcresult = GST_FLOW_OK;
-    result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
+    /* we do not start the task yet if the pad is not connected */
+    if (gst_pad_is_linked (pad))
+      result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
+    else {
+      GST_DEBUG ("not starting task as pad is not linked");
+      result = TRUE;
+    }
     GST_QUEUE_MUTEX_UNLOCK (queue);
   } else {
     /* step 1, unblock chain and loop functions */
index 2ef1b2a..e8bfc64 100644 (file)
@@ -1672,6 +1672,41 @@ gst_pad_get_parent_element (GstPad * pad)
 }
 
 /**
+ * gst_flow_get_name:
+ * @state: a #GstFlowReturn to get the name of.
+ *
+ * Gets a string representing the given flow return.
+ *
+ * Returns: a string with the name of the flow return.
+ */
+G_CONST_RETURN gchar *
+gst_flow_get_name (GstFlowReturn ret)
+{
+  switch (ret) {
+    case GST_FLOW_RESEND:
+      return "need to resend buffer";
+    case GST_FLOW_OK:
+      return "OK";
+      /* expected failures */
+    case GST_FLOW_NOT_LINKED:
+      return "pad not linked";
+    case GST_FLOW_WRONG_STATE:
+      return "pad in wrong state";
+      /* error cases */
+    case GST_FLOW_UNEXPECTED:
+      return "unexpected data on pad";
+    case GST_FLOW_NOT_NEGOTIATED:
+      return "pad not negotiated";
+    case GST_FLOW_ERROR:
+      return "fatal error occured";
+    case GST_FLOW_NOT_SUPPORTED:
+      return "unsupported function called";
+    default:
+      return "unknown error";
+  }
+}
+
+/**
  * gst_object_default_error:
  * @object: a #GObject that signalled the error.
  * @orig: the #GstObject that initiated the error.
index 048753c..e4d0eca 100644 (file)
@@ -280,6 +280,10 @@ gboolean           gst_pad_proxy_setcaps           (GstPad * pad, GstCaps * caps);
 
 GstElement*            gst_pad_get_parent_element      (GstPad *pad);
 
+/* flow */
+G_CONST_RETURN gchar*   gst_flow_get_name                      (GstFlowReturn ret);
+
+
 /* util query functions */
 gboolean                gst_pad_query_position          (GstPad *pad, GstFormat *format,
                                                         gint64 *cur, gint64 *end);
index 815bc4b..3d2197d 100644 (file)
@@ -472,8 +472,7 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
         /* the discont event is needed to bring the buffer timestamps to the
          * stream time */
         if (!gst_event_discont_get_value (event, GST_FORMAT_TIME,
-                (gint64 *) & basesink->discont_start,
-                (gint64 *) & basesink->discont_stop)) {
+                &basesink->discont_start, &basesink->discont_stop)) {
           basesink->discont_start = 0;
           basesink->discont_stop = 0;
         }
@@ -730,15 +729,26 @@ gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
 
   timestamp = GST_BUFFER_TIMESTAMP (buffer);
   if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+    GstClockTimeDiff diff;
+
     /* bring timestamp to stream time using last
      * discont offset. */
-    timestamp -= basesink->discont_start;
+    if ((diff = timestamp - basesink->discont_start) < 0)
+      goto too_late;
+
     /* get duration to calculate end time */
     duration = GST_BUFFER_DURATION (buffer);
     if (GST_CLOCK_TIME_IS_VALID (duration)) {
-      *end = timestamp + duration;
+      *end = diff + duration;
     }
-    *start = timestamp;
+    *start = diff;
+  }
+  return;
+
+too_late:
+  {
+    *start = GST_CLOCK_TIME_NONE;
+    *end = GST_CLOCK_TIME_NONE;
   }
 }
 
index c7fc83e..c9b2ffa 100644 (file)
@@ -67,8 +67,8 @@ struct _GstBaseSink {
   GstClockTime   end_time;
 
   gboolean      have_discont;
-  GstClockTime  discont_start;
-  GstClockTime  discont_stop;
+  GstClockTimeDiff      discont_start;
+  GstClockTimeDiff      discont_stop;
 
   gboolean       eos;
   gboolean       need_preroll;
index cdacbd0..77b1e20 100644 (file)
@@ -702,11 +702,11 @@ pause:
   {
     GST_DEBUG_OBJECT (src, "pausing task");
     gst_pad_pause_task (pad);
-    if (GST_FLOW_IS_FATAL (ret)) {
+    if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
       /* for fatal errors we post an error message */
       GST_ELEMENT_ERROR (src, STREAM, STOPPED,
-          ("streaming stopped, reason %d", ret),
-          ("streaming stopped, reason %d", ret));
+          ("streaming stopped, reason %s", gst_flow_get_name (ret)),
+          ("streaming stopped, reason %s", gst_flow_get_name (ret)));
       gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
     }
     return;
index 971d4c4..74bbd70 100644 (file)
@@ -29,6 +29,7 @@
 #include "gstevent.h"
 #include "gstinfo.h"
 #include "gsterror.h"
+#include "gstutils.h"
 
 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -406,10 +407,28 @@ static GstPadLinkReturn
 gst_queue_link_src (GstPad * pad, GstPad * peer)
 {
   GstPadLinkReturn result = GST_PAD_LINK_OK;
+  GstQueue *queue;
+
+  queue = GST_QUEUE (gst_pad_get_parent (pad));
+
+  GST_DEBUG ("queue linking source pad");
 
-  /* FIXME, see if we need to push or get pulled */
-  if (GST_PAD_LINKFUNC (peer))
+  if (GST_PAD_LINKFUNC (peer)) {
     result = GST_PAD_LINKFUNC (peer) (peer, pad);
+  }
+
+  if (GST_PAD_LINK_SUCCESSFUL (result)) {
+    GST_QUEUE_MUTEX_LOCK (queue);
+    if (queue->srcresult == GST_FLOW_OK) {
+      gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
+      GST_DEBUG ("starting task as pad is linked");
+    } else {
+      GST_DEBUG ("not starting task reason %s",
+          gst_flow_get_name (queue->srcresult));
+    }
+    GST_QUEUE_MUTEX_UNLOCK (queue);
+  }
+  gst_object_unref (queue);
 
   return result;
 }
@@ -673,9 +692,10 @@ out_unref:
 out_flushing:
   {
     GstFlowReturn ret = queue->srcresult;
+    const gchar *flowname = gst_flow_get_name (ret);
 
     GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-        "exit because task paused, reason:  %d", ret);
+        "exit because task paused, reason: %s", flowname);
     GST_QUEUE_MUTEX_UNLOCK (queue);
 
     gst_buffer_unref (buffer);
@@ -746,13 +766,18 @@ restart:
     /* can opt to check for srcresult here but the push should
      * return an error value that is more accurate */
     if (result != GST_FLOW_OK) {
+      const gchar *flowname;
+
+      flowname = gst_flow_get_name (result);
+
       queue->srcresult = result;
       if (GST_FLOW_IS_FATAL (result)) {
         GST_ELEMENT_ERROR (queue, STREAM, STOPPED,
-            ("streaming stopped, reason %d", result),
-            ("streaming stopped, reason %d", result));
+            ("streaming stopped, reason %s", flowname),
+            ("streaming stopped, reason %s", flowname));
         gst_pad_push_event (queue->srcpad, gst_event_new (GST_EVENT_EOS));
       }
+      GST_DEBUG ("pausing queue, reason %s", flowname);
       gst_pad_pause_task (queue->srcpad);
     }
   } else {
@@ -760,6 +785,7 @@ restart:
       /* all incomming data is now unexpected */
       queue->srcresult = GST_FLOW_UNEXPECTED;
       /* and we don't need to process anymore */
+      GST_DEBUG ("pausing queue, we're EOS now");
       gst_pad_pause_task (queue->srcpad);
       restart = FALSE;
     }
@@ -780,8 +806,10 @@ restart:
 
 out_flushing:
   {
+    const gchar *flowname = gst_flow_get_name (queue->srcresult);
+
     GST_CAT_LOG_OBJECT (queue_dataflow, queue,
-        "exit because task paused, reason:  %d", queue->srcresult);
+        "exit because task paused, reason:  %s", flowname);
     GST_QUEUE_MUTEX_UNLOCK (queue);
 
     return;
@@ -890,7 +918,13 @@ gst_queue_src_activate_push (GstPad * pad, gboolean active)
   if (active) {
     GST_QUEUE_MUTEX_LOCK (queue);
     queue->srcresult = GST_FLOW_OK;
-    result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
+    /* we do not start the task yet if the pad is not connected */
+    if (gst_pad_is_linked (pad))
+      result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
+    else {
+      GST_DEBUG ("not starting task as pad is not linked");
+      result = TRUE;
+    }
     GST_QUEUE_MUTEX_UNLOCK (queue);
   } else {
     /* step 1, unblock chain and loop functions */