From 84ec4caaa46051c329594ce57534c693ba5225f8 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 30 Aug 2007 17:50:54 +0000 Subject: [PATCH] docs/libs/gstreamer-libs-sections.txt: Add new methods to docs. Original commit message from CVS: * docs/libs/gstreamer-libs-sections.txt: Add new methods to docs. * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init), (gst_base_sink_init), (gst_base_sink_set_ts_offset), (gst_base_sink_get_ts_offset), (gst_base_sink_set_property), (gst_base_sink_get_property), (gst_base_sink_wait_clock): * libs/gst/base/gstbasesink.h: Add ts-offset property to fine-tune the synchronisation. API: GstBaseSink::ts-offset property API: gst_base_sink_set_ts_offset() API: gst_base_sink_get_ts_offset() --- ChangeLog | 15 +++++ docs/libs/gstreamer-libs-sections.txt | 6 +- libs/gst/base/gstbasesink.c | 83 ++++++++++++++++++++++++++- libs/gst/base/gstbasesink.h | 4 ++ 4 files changed, 106 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ec0513dcc..8f85fda63a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2007-08-30 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + Add new methods to docs. + + * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init), + (gst_base_sink_init), (gst_base_sink_set_ts_offset), + (gst_base_sink_get_ts_offset), (gst_base_sink_set_property), + (gst_base_sink_get_property), (gst_base_sink_wait_clock): + * libs/gst/base/gstbasesink.h: + Add ts-offset property to fine-tune the synchronisation. + API: GstBaseSink::ts-offset property + API: gst_base_sink_set_ts_offset() + API: gst_base_sink_get_ts_offset() + 2007-08-29 Wim Taymans * libs/gst/base/gstbasesink.c: (gst_base_sink_class_init), diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt index 21dd3ad028..1639a2a3a4 100644 --- a/docs/libs/gstreamer-libs-sections.txt +++ b/docs/libs/gstreamer-libs-sections.txt @@ -262,8 +262,12 @@ gst_base_sink_set_sync gst_base_sink_get_sync gst_base_sink_set_max_lateness gst_base_sink_get_max_lateness -gst_base_sink_is_qos_enabled gst_base_sink_set_qos_enabled +gst_base_sink_is_qos_enabled +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_PAD diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index 88327a6969..ef8eb90e87 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -159,6 +159,7 @@ struct _GstBaseSinkPrivate { gint qos_enabled; /* ATOMIC */ gboolean async_enabled; + GstClockTimeDiff ts_offset; /* start, stop of current buffer, stream time, used to report position */ GstClockTime current_sstart; @@ -227,6 +228,7 @@ struct _GstBaseSinkPrivate #define DEFAULT_MAX_LATENESS -1 #define DEFAULT_QOS FALSE #define DEFAULT_ASYNC TRUE +#define DEFAULT_TS_OFFSET 0 enum { @@ -235,7 +237,8 @@ enum PROP_SYNC, PROP_MAX_LATENESS, PROP_QOS, - PROP_ASYNC + PROP_ASYNC, + PROP_TS_OFFSET }; static GstElementClass *parent_class = NULL; @@ -363,6 +366,19 @@ gst_base_sink_class_init (GstBaseSinkClass * klass) g_object_class_install_property (gobject_class, PROP_ASYNC, g_param_spec_boolean ("async", "Async", "Go asynchronously to PAUSED", DEFAULT_ASYNC, G_PARAM_READWRITE)); + /** + * GstBaseSink:ts-offset + * + * Controls the final synchronisation, a negative value will render the buffer + * earlier while a positive value delays playback. This property can be + * used to fix synchronisation in bad files. + * + * Since: 0.10.15 + */ + g_object_class_install_property (gobject_class, PROP_TS_OFFSET, + g_param_spec_int64 ("ts-offset", "TS Offset", + "Timestamp offset in nanoseconds", G_MININT64, G_MAXINT64, + DEFAULT_TS_OFFSET, G_PARAM_READWRITE)); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_base_sink_change_state); @@ -514,6 +530,7 @@ gst_base_sink_init (GstBaseSink * basesink, gpointer g_class) basesink->abidata.ABI.max_lateness = DEFAULT_MAX_LATENESS; gst_atomic_int_set (&priv->qos_enabled, DEFAULT_QOS); priv->async_enabled = DEFAULT_ASYNC; + priv->ts_offset = DEFAULT_TS_OFFSET; GST_OBJECT_FLAG_SET (basesink, GST_ELEMENT_IS_SINK); } @@ -716,6 +733,52 @@ gst_base_sink_is_async_enabled (GstBaseSink * sink) return res; } +/** + * gst_base_sink_set_ts_offset: + * @sink: the sink + * @offset: the new offset + * + * Adjust the synchronisation of @sink with @offset. A negative value will + * render buffers earlier than their timestamp. A positive value will delay + * rendering. This function can be used to fix playback of badly timestamped + * buffers. + * + * Since: 0.10.15 + */ +void +gst_base_sink_set_ts_offset (GstBaseSink * sink, GstClockTimeDiff offset) +{ + g_return_if_fail (GST_IS_BASE_SINK (sink)); + + GST_OBJECT_LOCK (sink); + sink->priv->ts_offset = offset; + GST_OBJECT_UNLOCK (sink); +} + +/** + * gst_base_sink_get_ts_offset: + * @sink: the sink + * + * Get the synchronisation offset of @sink. + * + * Returns: The synchronisation offset. + * + * Since: 0.10.15 + */ +GstClockTimeDiff +gst_base_sink_get_ts_offset (GstBaseSink * sink) +{ + GstClockTimeDiff res; + + g_return_val_if_fail (GST_IS_BASE_SINK (sink), 0); + + GST_OBJECT_LOCK (sink); + res = sink->priv->ts_offset; + GST_OBJECT_UNLOCK (sink); + + return res; +} + /** * gst_base_sink_get_latency: * @sink: the sink @@ -845,6 +908,9 @@ gst_base_sink_set_property (GObject * object, guint prop_id, case PROP_ASYNC: gst_base_sink_set_async_enabled (sink, g_value_get_boolean (value)); break; + case PROP_TS_OFFSET: + gst_base_sink_set_ts_offset (sink, g_value_get_int64 (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -875,6 +941,9 @@ gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value, case PROP_ASYNC: g_value_set_boolean (value, gst_base_sink_is_async_enabled (sink)); break; + case PROP_TS_OFFSET: + g_value_set_int64 (value, gst_base_sink_get_ts_offset (sink)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1247,6 +1316,7 @@ gst_base_sink_wait_clock (GstBaseSink * basesink, GstClockTime time, GstClockID id; GstClockReturn ret; GstClock *clock; + GstClockTimeDiff ts_offset; if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) goto invalid_time; @@ -1262,6 +1332,17 @@ gst_base_sink_wait_clock (GstBaseSink * basesink, GstClockTime time, time += GST_ELEMENT_CAST (basesink)->base_time; time += basesink->priv->latency; + /* apply offset, be carefull for underflows */ + ts_offset = basesink->priv->ts_offset; + if (ts_offset < 0) { + ts_offset = -ts_offset; + if (ts_offset < time) + time -= ts_offset; + else + time = 0; + } else + time += ts_offset; + id = gst_clock_new_single_shot_id (clock, time); GST_OBJECT_UNLOCK (basesink); diff --git a/libs/gst/base/gstbasesink.h b/libs/gst/base/gstbasesink.h index 000f17948d..438adf4ad4 100644 --- a/libs/gst/base/gstbasesink.h +++ b/libs/gst/base/gstbasesink.h @@ -205,6 +205,10 @@ gboolean gst_base_sink_is_qos_enabled (GstBaseSink *sink); void gst_base_sink_set_async_enabled (GstBaseSink *sink, gboolean enabled); gboolean gst_base_sink_is_async_enabled (GstBaseSink *sink); +/* tuning synchronisation */ +void gst_base_sink_set_ts_offset (GstBaseSink *sink, GstClockTimeDiff offset); +GstClockTimeDiff gst_base_sink_get_ts_offset (GstBaseSink *sink); + /* latency */ gboolean gst_base_sink_query_latency (GstBaseSink *sink, gboolean *live, gboolean *upstream_live, GstClockTime *min_latency, GstClockTime *max_latency);