From 7a88e2a76214d8d3d7c24d6d0a56cb0451011774 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 7 Mar 2006 16:21:02 +0000 Subject: [PATCH] docs/libs/gstreamer-libs-sections.txt: Added basesink new methods. Original commit message from CVS: * docs/libs/gstreamer-libs-sections.txt: Added basesink new methods. * gst/gstevent.c: * gst/gstevent.h: Docs updates. Flesh out the QoS docs. * libs/gst/base/gstadapter.c: Small doc clarification about ownership and flushing. * libs/gst/base/gstbasesink.c: (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_set_property), (gst_base_sink_get_property), (gst_base_sink_do_sync): * libs/gst/base/gstbasesink.h: Added new methods to allow subclass to control max-lateness and sync. Generate very basic QoS events based on last sync observation. Updated docs, fix typo, added some QoS blurb. * libs/gst/base/gstbasesrc.c: Remove obsolete _get_state() calls from docs. --- ChangeLog | 25 +++++ docs/libs/gstreamer-libs-sections.txt | 5 + gst/gstevent.c | 21 +++- gst/gstevent.h | 1 - libs/gst/base/gstadapter.c | 12 ++- libs/gst/base/gstbasesink.c | 140 ++++++++++++++++++++++---- libs/gst/base/gstbasesink.h | 6 ++ libs/gst/base/gstbasesrc.c | 4 +- 8 files changed, 182 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index f6ca69c1ff..adbb12d675 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2006-03-07 Wim Taymans + + * docs/libs/gstreamer-libs-sections.txt: + Added basesink new methods. + + * gst/gstevent.c: + * gst/gstevent.h: + Docs updates. Flesh out the QoS docs. + + * libs/gst/base/gstadapter.c: + Small doc clarification about ownership and flushing. + + * libs/gst/base/gstbasesink.c: (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_set_property), + (gst_base_sink_get_property), (gst_base_sink_do_sync): + * libs/gst/base/gstbasesink.h: + Added new methods to allow subclass to control max-lateness + and sync. + Generate very basic QoS events based on last sync observation. + Updated docs, fix typo, added some QoS blurb. + + * libs/gst/base/gstbasesrc.c: + Remove obsolete _get_state() calls from docs. + 2006-03-07 Wim Taymans * docs/libs/gstreamer-libs-sections.txt: diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt index 0403cc8328..4aa68b6155 100644 --- a/docs/libs/gstreamer-libs-sections.txt +++ b/docs/libs/gstreamer-libs-sections.txt @@ -159,6 +159,11 @@ GstBaseSink GST_BASE_SINK_PAD +gst_base_sink_set_sync +gst_base_sink_get_sync +gst_base_sink_set_max_lateness +gst_base_sink_get_max_lateness + GstBaseSinkClass GST_BASE_SINK diff --git a/gst/gstevent.c b/gst/gstevent.c index 0db8cee889..1df83f886f 100644 --- a/gst/gstevent.c +++ b/gst/gstevent.c @@ -615,17 +615,28 @@ gst_event_parse_buffer_size (GstEvent * event, GstFormat * format, * Allocate a new qos event with the given values. * The QOS event is generated in an element that wants an upstream * element to either reduce or increase its rate because of - * high/low CPU load. + * high/low CPU load or other resource usage such as network performance. * - * proportion is the requested adjustment in datarate, 1.0 is the normal + * @proportion is the requested adjustment in datarate, 1.0 is the normal * datarate, 0.75 means increase datarate by 75%, 1.5 is 150%. Negative * values request a slow down, so -0.75 means a decrease by 75%. * - * diff is the difference against the clock in stream time of the last + * @diff is the difference against the clock in stream time of the last * buffer that caused the element to generate the QOS event. * - * timestamp is the timestamp of the last buffer that cause the element - * to generate the QOS event. + * @timestamp is the timestamp of the last buffer that cause the element + * to generate the QOS event. + * + * The upstream element can use the @diff and @timestamp values to decide + * whether to process more buffers. All buffers with timestamp <= + * @timestamp + @diff will certainly arrive late in the sink as well. + * + * The @proportion value is generally computed based on more long + * term statistics about the stream quality and can be used in various ways + * such as lowering or increasing processing quality. + * + * The application can use general event probes to intercept the QoS + * event and implement custom application specific QoS handling. * * Returns: A new QOS event. */ diff --git a/gst/gstevent.h b/gst/gstevent.h index 0ec1d83d79..e12ab33675 100644 --- a/gst/gstevent.h +++ b/gst/gstevent.h @@ -378,7 +378,6 @@ void gst_event_parse_buffer_size (GstEvent *event, GstFormat *format, gint64 * gint64 *maxsize, gboolean *async); /* QOS events */ -/* FIXME: QOS events need to be fully specified and implemented */ GstEvent* gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff, GstClockTime timestamp); void gst_event_parse_qos (GstEvent *event, gdouble *proportion, GstClockTimeDiff *diff, diff --git a/libs/gst/base/gstadapter.c b/libs/gst/base/gstadapter.c index 6cd6cfef23..62cecf3cc0 100644 --- a/libs/gst/base/gstadapter.c +++ b/libs/gst/base/gstadapter.c @@ -67,6 +67,9 @@ * gst_adapter_clear(). Data should also be cleared or processed on EOS and * when changing state from #GST_STATE_PAUSED to #GST_STATE_READY. * + * Also check the GST_BUFFER_FLAG_DISCONT flag on the buffer. Some elements might + * need to clear the adapter after a discontinuity. + * * A last thing to note is that while GstAdapter is pretty optimized, * merging buffers still might be an operation that requires a memcpy() * operation, and this operation is not the fastest. Because of this, some @@ -76,11 +79,14 @@ * GstAdapter is not MT safe. All operations on an adapter must be serialized by * the caller. This is not normally a problem, however, as the normal use case * of GstAdapter is inside one pad's chain function, in which case access is - * serialized via the pad's stream lock. + * serialized via the pad's STREAM_LOCK. * - * Note that gst_adapter_push() takes ownership of the buffer passed. + * Note that gst_adapter_push() takes ownership of the buffer passed. Use + * gst_buffer_ref() before pushing it into the adapter if you still want to + * access the buffer later. The adapter will never modify the data in the + * buffer pushed in it. * - * Last reviewed on 2005-12-18 (0.10.0). + * Last reviewed on 2006-03-07 (0.10.4). */ #include diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index 92127f043b..8d1db0833b 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -30,7 +30,7 @@ * you, for example preroll, clock synchronization, state changes, activation in * push or pull mode, and queries. In most cases, when writing sink elements, * there is no need to implement class methods from #GstElement or to set - * functions on pads, because the #GstBaseSink infrastructure is sufficient. + * functions on pads, because the #GstBaseSink infrastructure should be sufficient. * * There is only support in GstBaseSink for one sink pad, which should be named * "sink". A sink implementation (subclass of GstBaseSink) should install a pad @@ -53,8 +53,8 @@ * #GstBaseSink will handle the prerolling correctly. This means that it will * return GST_STATE_CHANGE_ASYNC from a state change to PAUSED until the first buffer * arrives in this element. The base class will call the GstBaseSink::preroll - * vmethod with this preroll buffer and will then commit the state change to - * PAUSED. + * vmethod with this preroll buffer and will then commit the state change to the + * next asynchronously pending state. * * When the element is set to PLAYING, #GstBaseSink will synchronize on the clock * using the times returned from ::get_times. If this function returns @@ -88,7 +88,7 @@ * query will be forwarded upstream. * * The ::set_caps function will be called when the subclass should configure itself - * to precess a specific media type. + * to process a specific media type. * * The ::start and ::stop virtual methods will be called when resources should be * allocated. Any ::preroll, ::render and ::set_caps function will be called @@ -106,7 +106,16 @@ * operations they perform in the ::render method. This is mostly usefull when * the ::render method performs a blocking write on a file descripter. * - * Last reviewed on 2006-01-30 (0.10.3) + * The max-lateness property defines how the sink deals with buffers that arrive + * too late in the sink. A buffer arrives too late in the sink when the presentation + * time (as a combination of the last segment, buffer timestamp and element + * base_time) is before the current time of the clock. If the frame is later than + * max-lateness, the sink will drop the buffer and will generate a QoS event upstream. + * This feature is disabled if sync is disabled, the ::get-times method does not + * return a valid start time or max-lateness is set to -1 (the default). + * Subclasses can use gst_base_sink_set_max_lateness() to configure the max-lateness. + * + * Last reviewed on 2006-03-07 (0.10.4) */ #ifdef HAVE_CONFIG_H @@ -375,6 +384,95 @@ gst_base_sink_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } +/** + * gst_base_sink_set_sync: + * @sink: the sink + * @sync: the new sync value. + * + * Configures @sink to synchronize on the clock or not. When + * @sync is FALSE, incomming samples will be played as fast as + * possible. If @sync is TRUE, the timestamps of the incomming + * buffers will be used to schedule the exact render time of its + * contents. + * + * Since: 0.10.4 + */ +void +gst_base_sink_set_sync (GstBaseSink * sink, gboolean sync) +{ + GST_OBJECT_LOCK (sink); + sink->sync = sync; + GST_OBJECT_UNLOCK (sink); +} + +/** + * gst_base_sink_get_sync: + * @sink: the sink + * + * Checks if @sink is currently configured to synchronize against the + * clock. + * + * Returns: TRUE if the sink is configured to synchronize against the clock. + * + * Since: 0.10.4 + */ +gboolean +gst_base_sink_get_sync (GstBaseSink * sink) +{ + gboolean res; + + GST_OBJECT_LOCK (sink); + res = sink->sync; + GST_OBJECT_UNLOCK (sink); + + return res; +} + +/** + * gst_base_sink_set_max_lateness: + * @sink: the sink + * @max_lateness: the new max lateness value. + * + * Sets the new max lateness value to @max_lateness. This value is + * used to decide if a buffer should be dropped or not based on the + * buffer timestamp and the current clock time. A value of -1 means + * an unlimited time. + * + * Since: 0.10.4 + */ +void +gst_base_sink_set_max_lateness (GstBaseSink * sink, gint64 max_lateness) +{ + GST_OBJECT_LOCK (sink); + sink->abidata.ABI.max_lateness = max_lateness; + GST_OBJECT_UNLOCK (sink); +} + +/** + * gst_base_sink_get_max_lateness: + * @sink: the sink + * + * Gets the max lateness value. See gst_base_sink_set_max_lateness for + * more details. + * + * Returns: The maximum time in nanoseconds that a buffer can be late + * before it is dropped and not rendered. A value of -1 means an + * unlimited time. + * + * Since: 0.10.4 + */ +gint64 +gst_base_sink_get_max_lateness (GstBaseSink * sink) +{ + gint64 res; + + GST_OBJECT_LOCK (sink); + res = sink->abidata.ABI.max_lateness; + GST_OBJECT_UNLOCK (sink); + + return res; +} + static void gst_base_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -389,14 +487,10 @@ gst_base_sink_set_property (GObject * object, guint prop_id, GST_PAD_PREROLL_UNLOCK (sink->sinkpad); break; case PROP_SYNC: - GST_OBJECT_LOCK (sink); - sink->sync = g_value_get_boolean (value); - GST_OBJECT_UNLOCK (sink); + gst_base_sink_set_sync (sink, g_value_get_boolean (value)); break; case PROP_MAX_LATENESS: - GST_OBJECT_LOCK (sink); - sink->abidata.ABI.max_lateness = g_value_get_int64 (value); - GST_OBJECT_UNLOCK (sink); + gst_base_sink_set_max_lateness (sink, g_value_get_int64 (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -417,14 +511,10 @@ gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value, GST_PAD_PREROLL_UNLOCK (sink->sinkpad); break; case PROP_SYNC: - GST_OBJECT_LOCK (sink); - g_value_set_boolean (value, sink->sync); - GST_OBJECT_UNLOCK (sink); + g_value_set_boolean (value, gst_base_sink_get_sync (sink)); break; case PROP_MAX_LATENESS: - GST_OBJECT_LOCK (sink); - g_value_set_int64 (value, sink->abidata.ABI.max_lateness); - GST_OBJECT_UNLOCK (sink); + g_value_set_int64 (value, gst_base_sink_get_max_lateness (sink)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -432,6 +522,7 @@ gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value, } } + static GstCaps * gst_base_sink_get_caps (GstBaseSink * sink) { @@ -838,14 +929,23 @@ again: *late = FALSE; - if (basesink->abidata.ABI.max_lateness != -1) { - if (status == GST_CLOCK_EARLY + /* FIXME, update clock stats here and do some QoS */ + if (status == GST_CLOCK_EARLY) { + if (basesink->abidata.ABI.max_lateness != -1 && jitter > basesink->abidata.ABI.max_lateness) { - /* FIXME, update clock stats here and do some QoS */ + GstEvent *event; + GST_DEBUG_OBJECT (basesink, "late: jitter!! %" G_GINT64_FORMAT "\n", jitter); *late = TRUE; + + /* generate QoS event, FIXME, calculate decent proportion. */ + event = gst_event_new_qos (-1.0, jitter, start); + + /* send upstream */ + gst_pad_push_event (basesink->sinkpad, event); } + } else { } return GST_FLOW_OK; diff --git a/libs/gst/base/gstbasesink.h b/libs/gst/base/gstbasesink.h index 7945d39d2c..6bc093b95c 100644 --- a/libs/gst/base/gstbasesink.h +++ b/libs/gst/base/gstbasesink.h @@ -136,6 +136,12 @@ struct _GstBaseSinkClass { GType gst_base_sink_get_type(void); +void gst_base_sink_set_sync (GstBaseSink *sink, gboolean sync); +gboolean gst_base_sink_get_sync (GstBaseSink *sink); + +void gst_base_sink_set_max_lateness (GstBaseSink *sink, gint64 max_lateness); +gint64 gst_base_sink_get_max_lateness (GstBaseSink *sink); + G_END_DECLS #endif /* __GST_BASE_SINK_H__ */ diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index 2302792e1b..e20f308a0e 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -135,7 +135,6 @@ * ... * // stop recording * gst_element_set_state (audio_source, GST_STATE_NULL); - * gst_element_get_state (audio_source, NULL, NULL, -1); * gst_element_set_locked_state (audio_source, TRUE); * ... * @@ -146,13 +145,12 @@ * ... * // everything done - shut down pipeline * gst_element_set_state (pipeline, GST_STATE_NULL); - * gst_element_get_state (pipeline, NULL, NULL, -1); * gst_element_set_locked_state (audio_source, FALSE); * ... * * * - * Last reviewed on 2005-12-18 (0.10.0) + * Last reviewed on 2006-03-07 (0.10.4) * * */ -- 2.34.1