From 6624a8de123bd37e70f678c6d91bd1dfff915a4e Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 20 Jun 2008 08:54:45 +0000 Subject: [PATCH] Add method to allow sinks to specify additional delay between the sync times and the actual rendering of the data. 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 | 14 ++++++ docs/libs/gstreamer-libs-sections.txt | 2 + libs/gst/base/gstbasesink.c | 85 ++++++++++++++++++++++++++++++++--- libs/gst/base/gstbasesink.h | 5 +++ win32/common/libgstbase.def | 2 + 5 files changed, 103 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index fadf5ce..487d72f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-06-20 Wim Taymans + + * 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 * configure.ac: diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt index e9d13b1..f656d8b 100644 --- a/docs/libs/gstreamer-libs-sections.txt +++ b/docs/libs/gstreamer-libs-sections.txt @@ -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 diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index 480c754..adf814c 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -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); diff --git a/libs/gst/base/gstbasesink.h b/libs/gst/base/gstbasesink.h index 7fdf8e3..b6a8b3d 100644 --- a/libs/gst/base/gstbasesink.h +++ b/libs/gst/base/gstbasesink.h @@ -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, diff --git a/win32/common/libgstbase.def b/win32/common/libgstbase.def index 0acd0e6..d9e4145 100644 --- a/win32/common/libgstbase.def +++ b/win32/common/libgstbase.def @@ -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 -- 2.7.4