Add method to allow sinks to specify additional delay between the sync times and...
authorWim Taymans <wim.taymans@gmail.com>
Fri, 20 Jun 2008 08:54:45 +0000 (08:54 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Fri, 20 Jun 2008 08:54:45 +0000 (08:54 +0000)
Original commit message from CVS:
* docs/libs/gstreamer-libs-sections.txt:
* libs/gst/base/gstbasesink.c: (gst_base_sink_init),
(gst_base_sink_query_latency), (gst_base_sink_set_render_delay),
(gst_base_sink_get_render_delay), (gst_base_sink_wait_eos),
(gst_base_sink_do_sync):
* libs/gst/base/gstbasesink.h:
* win32/common/libgstbase.def:
Add method to allow sinks to specify additional delay between the sync
times and the actual rendering of the data.
API: gst_base_sink_set_render_delay()
API: gst_base_sink_get_render_delay()

ChangeLog
docs/libs/gstreamer-libs-sections.txt
libs/gst/base/gstbasesink.c
libs/gst/base/gstbasesink.h
win32/common/libgstbase.def

index fadf5ce..487d72f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2008-06-20  Wim Taymans  <wim.taymans@collabora.co.uk>
+
+       * docs/libs/gstreamer-libs-sections.txt:
+       * libs/gst/base/gstbasesink.c: (gst_base_sink_init),
+       (gst_base_sink_query_latency), (gst_base_sink_set_render_delay),
+       (gst_base_sink_get_render_delay), (gst_base_sink_wait_eos),
+       (gst_base_sink_do_sync):
+       * libs/gst/base/gstbasesink.h:
+       * win32/common/libgstbase.def:
+       Add method to allow sinks to specify additional delay between the sync
+       times and the actual rendering of the data.
+       API: gst_base_sink_set_render_delay()
+       API: gst_base_sink_get_render_delay()
+
 2008-06-20  Jan Schmidt  <jan.schmidt@sun.com>
 
        * configure.ac:
index e9d13b1..f656d8b 100644 (file)
@@ -270,6 +270,8 @@ gst_base_sink_set_async_enabled
 gst_base_sink_is_async_enabled
 gst_base_sink_set_ts_offset
 gst_base_sink_get_ts_offset
+gst_base_sink_set_render_delay
+gst_base_sink_get_render_delay
 gst_base_sink_get_last_buffer
 
 GST_BASE_SINK_PAD
index 480c754..adf814c 100644 (file)
@@ -160,6 +160,7 @@ struct _GstBaseSinkPrivate
   gint qos_enabled;             /* ATOMIC */
   gboolean async_enabled;
   GstClockTimeDiff ts_offset;
+  GstClockTime render_delay;
 
   /* start, stop of current buffer, stream time, used to report position */
   GstClockTime current_sstart;
@@ -551,6 +552,7 @@ gst_base_sink_init (GstBaseSink * basesink, gpointer g_class)
   g_atomic_int_set (&priv->qos_enabled, DEFAULT_QOS);
   priv->async_enabled = DEFAULT_ASYNC;
   priv->ts_offset = DEFAULT_TS_OFFSET;
+  priv->render_delay = 0;
 
   GST_OBJECT_FLAG_SET (basesink, GST_ELEMENT_IS_SINK);
 }
@@ -899,7 +901,7 @@ gst_base_sink_query_latency (GstBaseSink * sink, gboolean * live,
     GstClockTime * max_latency)
 {
   gboolean l, us_live, res, have_latency;
-  GstClockTime min, max;
+  GstClockTime min, max, render_delay;
   GstQuery *query;
   GstClockTime us_min, us_max;
 
@@ -907,6 +909,7 @@ gst_base_sink_query_latency (GstBaseSink * sink, gboolean * live,
   GST_OBJECT_LOCK (sink);
   l = sink->sync;
   have_latency = sink->priv->have_latency;
+  render_delay = sink->priv->render_delay;
   GST_OBJECT_UNLOCK (sink);
 
   /* assume no latency */
@@ -931,6 +934,13 @@ gst_base_sink_query_latency (GstBaseSink * sink, gboolean * live,
         min = us_min;
         max = us_max;
       }
+      if (l) {
+        /* we need to add the render delay if we are live */
+        if (min != -1)
+          min += render_delay;
+        if (max != -1)
+          max += render_delay;
+      }
     }
     gst_query_unref (query);
   } else {
@@ -965,6 +975,60 @@ gst_base_sink_query_latency (GstBaseSink * sink, gboolean * live,
   return res;
 }
 
+/**
+ * gst_base_sink_set_render_delay:
+ * @sink: a #GstBaseSink
+ * @delay: the new delay
+ *
+ * Set the render delay in @sink to @delay. The render delay is the time 
+ * between actual rendering of a buffer and its synchronisation time. Some
+ * devices might delay media rendering which can be compensated for with this
+ * function. 
+ *
+ * After calling this function, this sink will report additional latency and
+ * other sinks will adjust their latency to delay the rendering of their media.
+ *
+ * This function is usually called by subclasses.
+ *
+ * Since: 0.10.21
+ */
+void
+gst_base_sink_set_render_delay (GstBaseSink * sink, GstClockTime delay)
+{
+  g_return_if_fail (GST_IS_BASE_SINK (sink));
+
+  GST_OBJECT_LOCK (sink);
+  sink->priv->render_delay = delay;
+  GST_LOG_OBJECT (sink, "set render delay to %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (delay));
+  GST_OBJECT_UNLOCK (sink);
+}
+
+/**
+ * gst_base_sink_get_render_delay:
+ * @sink: a #GstBaseSink
+ *
+ * Get the render delay of @sink. see gst_base_sink_set_render_delay() for more
+ * information about the render delay.
+ *
+ * Returns: the render delay of @sink.
+ *
+ * Since: 0.10.21
+ */
+GstClockTime
+gst_base_sink_get_render_delay (GstBaseSink * sink)
+{
+  GstClockTimeDiff res;
+
+  g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0);
+
+  GST_OBJECT_LOCK (sink);
+  res = sink->priv->render_delay;
+  GST_OBJECT_UNLOCK (sink);
+
+  return res;
+}
+
 static void
 gst_base_sink_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
@@ -1611,7 +1675,7 @@ gst_base_sink_wait_eos (GstBaseSink * sink, GstClockTime time,
     GST_DEBUG_OBJECT (sink, "possibly waiting for clock to reach %"
         GST_TIME_FORMAT, GST_TIME_ARGS (time));
 
-    /* compensate for latency and ts_offset. We don't adjust for device latency
+    /* compensate for latency and ts_offset. We don't adjust for render delay
      * because we don't interact with the device on EOS normally. */
     stime = gst_base_sink_adjust_time (sink, time);
 
@@ -1733,13 +1797,24 @@ again:
   if (!do_sync)
     goto done;
 
+  /* adjust for latency */
+  stime = gst_base_sink_adjust_time (basesink, rstart);
+
+  /* adjust for render-delay, avoid underflows */
+  if (stime != -1) {
+    if (stime > priv->render_delay)
+      stime -= priv->render_delay;
+    else
+      stime = 0;
+  }
+
   /* preroll done, we can sync since we are in PLAYING now. */
   GST_DEBUG_OBJECT (basesink, "possibly waiting for clock to reach %"
-      GST_TIME_FORMAT, GST_TIME_ARGS (rstart));
+      GST_TIME_FORMAT ", adjusted %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (rstart), GST_TIME_ARGS (stime));
 
-  /* this function will return immediatly if start == -1, no clock
+  /* This function will return immediatly if start == -1, no clock
    * or sync is disabled with GST_CLOCK_BADTIME. */
-  stime = gst_base_sink_adjust_time (basesink, rstart);
   status = gst_base_sink_wait_clock (basesink, stime, &jitter);
 
   GST_DEBUG_OBJECT (basesink, "clock returned %d", status);
index 7fdf8e3..b6a8b3d 100644 (file)
@@ -217,6 +217,11 @@ gboolean   gst_base_sink_query_latency     (GstBaseSink *sink, gboolean *live, gboole
                                                 GstClockTime *min_latency, GstClockTime *max_latency);
 GstClockTime   gst_base_sink_get_latency       (GstBaseSink *sink);
 
+/* render delay */
+void           gst_base_sink_set_render_delay  (GstBaseSink *sink, GstClockTime delay);
+GstClockTime    gst_base_sink_get_render_delay         (GstBaseSink *sink);
+
+
 GstClockReturn  gst_base_sink_wait_clock        (GstBaseSink * basesink, GstClockTime time,
                                                  GstClockTimeDiff * jitter);
 GstFlowReturn   gst_base_sink_wait_eos          (GstBaseSink *sink, GstClockTime time,
index 0acd0e6..d9e4145 100644 (file)
@@ -10,6 +10,7 @@ EXPORTS
        gst_adapter_push
        gst_adapter_take
        gst_adapter_take_buffer
+       gst_base_sink_get_render_delay
        gst_base_sink_get_last_buffer
        gst_base_sink_get_latency
        gst_base_sink_get_max_lateness
@@ -20,6 +21,7 @@ EXPORTS
        gst_base_sink_is_qos_enabled
        gst_base_sink_query_latency
        gst_base_sink_set_async_enabled
+       gst_base_sink_set_render_delay
        gst_base_sink_set_max_lateness
        gst_base_sink_set_qos_enabled
        gst_base_sink_set_sync