From af728740a306355b5479cef20fdf8fd94f685c1f Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 31 Dec 2004 10:44:46 +0000 Subject: [PATCH] Clock updates, remove deprecated methods, simplify operations. Original commit message from CVS: * gst/gstbin.c: (gst_bin_set_index), (gst_bin_set_clock), (gst_bin_set_bus), (gst_bin_set_scheduler), (gst_bin_add_func), (gst_bin_iterate_elements), (gst_bin_change_state), (gst_bin_get_by_name_recurse_up): * gst/gstbuffer.c: (gst_buffer_default_copy): * gst/gstbuffer.h: * gst/gstclock.c: (gst_clock_init), (gst_clock_get_time), (gst_clock_set_time_adjust): * gst/gstclock.h: * gst/gstelement.h: * gst/gstevent.h: * gst/gstinfo.h: * gst/gstpipeline.c: (is_eos), (pipeline_bus_handler), (gst_pipeline_change_state): * gst/gstpipeline.h: * gst/gstsystemclock.c: (gst_system_clock_wait): * gst/gstutils.c: (gst_element_finish_preroll), (gst_element_get_compatible_pad_filtered), (gst_element_link_pads_filtered), (gst_element_unlink): * gst/registries/gstxmlregistry.c: (gst_xml_registry_parse_element_factory), (gst_xml_registry_end_element): * libs/gst/dataprotocol/dataprotocol.c: (gst_dp_header_from_buffer): Clock updates, remove deprecated methods, simplify operations. Fix clocking and time management in GstPipeline. Preroll also occurs when going from playing to paused. --- ChangeLog | 30 +++++++ gst/gstbin.c | 4 +- gst/gstbuffer.c | 2 +- gst/gstbuffer.h | 2 +- gst/gstclock.c | 127 +++++---------------------- gst/gstclock.h | 32 ++++--- gst/gstelement.h | 5 ++ gst/gstevent.h | 19 ++-- gst/gstinfo.h | 9 -- gst/gstpipeline.c | 30 ++++++- gst/gstpipeline.h | 2 + gst/gstsystemclock.c | 15 ++-- gst/gstutils.c | 2 +- gst/registries/gstxmlregistry.c | 6 +- libs/gst/dataprotocol/dataprotocol.c | 2 +- 15 files changed, 131 insertions(+), 156 deletions(-) diff --git a/ChangeLog b/ChangeLog index 31558d0d3e..d9fdea75d5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2004-12-31 Wim Taymans + + * gst/gstbin.c: (gst_bin_set_index), (gst_bin_set_clock), + (gst_bin_set_bus), (gst_bin_set_scheduler), (gst_bin_add_func), + (gst_bin_iterate_elements), (gst_bin_change_state), + (gst_bin_get_by_name_recurse_up): + * gst/gstbuffer.c: (gst_buffer_default_copy): + * gst/gstbuffer.h: + * gst/gstclock.c: (gst_clock_init), (gst_clock_get_time), + (gst_clock_set_time_adjust): + * gst/gstclock.h: + * gst/gstelement.h: + * gst/gstevent.h: + * gst/gstinfo.h: + * gst/gstpipeline.c: (is_eos), (pipeline_bus_handler), + (gst_pipeline_change_state): + * gst/gstpipeline.h: + * gst/gstsystemclock.c: (gst_system_clock_wait): + * gst/gstutils.c: (gst_element_finish_preroll), + (gst_element_get_compatible_pad_filtered), + (gst_element_link_pads_filtered), (gst_element_unlink): + * gst/registries/gstxmlregistry.c: + (gst_xml_registry_parse_element_factory), + (gst_xml_registry_end_element): + * libs/gst/dataprotocol/dataprotocol.c: + (gst_dp_header_from_buffer): + Clock updates, remove deprecated methods, simplify operations. + Fix clocking and time management in GstPipeline. + Preroll also occurs when going from playing to paused. + 2004-12-29 Wim Taymans * gst/elements/gstfakesrc.c: (gst_fakesrc_loop), diff --git a/gst/gstbin.c b/gst/gstbin.c index c2bccbabda..ce658a80a9 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -745,8 +745,8 @@ gst_bin_change_state (GstElement * element) if (GST_FLAG_IS_SET (qelement, GST_ELEMENT_LOCKED_STATE)) goto next_element; - /* FIXME handle delayed elements like src and loop based - * elements */ + + qelement->base_time = element->base_time; ret = gst_element_set_state (qelement, pending); switch (ret) { case GST_STATE_SUCCESS: diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 20c647e961..bb09754e59 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -136,7 +136,7 @@ gst_buffer_default_copy (GstBuffer * buffer) GST_CAT_LOG (GST_CAT_BUFFER, "copy %p to %p", buffer, copy); /* copy relevant flags */ - flags = GST_DATA_FLAG_SHIFT (GST_BUFFER_KEY_UNIT) | + flags = GST_DATA_FLAG_SHIFT (GST_BUFFER_PREROLL) | GST_DATA_FLAG_SHIFT (GST_BUFFER_IN_CAPS) | GST_DATA_FLAG_SHIFT (GST_BUFFER_DELTA_UNIT); flags = GST_BUFFER_FLAGS (buffer) & flags; diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h index f9e8ab4dce..ea92cb2151 100644 --- a/gst/gstbuffer.h +++ b/gst/gstbuffer.h @@ -97,7 +97,7 @@ typedef enum { GST_BUFFER_SUBBUFFER = GST_DATA_FLAG_LAST, GST_BUFFER_ORIGINAL, /* original data, not copied, not currently used */ GST_BUFFER_DONTFREE, /* buffer data is managed by somebody else and cannot be freeed */ - GST_BUFFER_KEY_UNIT, /* sync point in the stream, DEPRECATED, use DELTA_UNIT for non-KEY_UNIT buffers */ + GST_BUFFER_PREROLL, /* sample should not be displayed */ GST_BUFFER_DISCONT, /* buffer is first after discontinuity in the stream */ GST_BUFFER_IN_CAPS, /* buffer is also part of caps */ GST_BUFFER_GAP, /* buffer has been created to fill a gap in the stream */ diff --git a/gst/gstclock.c b/gst/gstclock.c index bd29182093..bb422d01f5 100644 --- a/gst/gstclock.c +++ b/gst/gstclock.c @@ -251,6 +251,7 @@ gst_clock_id_wait_async (GstClockID id, return res; } +#if 0 static void gst_clock_reschedule_func (GstClockEntry * entry) { @@ -258,6 +259,7 @@ gst_clock_reschedule_func (GstClockEntry * entry) gst_clock_id_unlock ((GstClockID) entry); } +#endif /** * gst_clock_id_unschedule: @@ -396,7 +398,7 @@ gst_clock_class_init (GstClockClass * klass) static void gst_clock_init (GstClock * clock) { - clock->start_time = 0; + clock->adjust = 0; clock->last_time = 0; clock->entries = NULL; clock->flags = 0; @@ -417,42 +419,6 @@ gst_clock_dispose (GObject * object) G_OBJECT_CLASS (parent_class)->dispose (object); } -/** - * gst_clock_set_speed - * @clock: a #GstClock to modify - * @speed: the speed to set on the clock - * - * Sets the speed on the given clock. 1.0 is the default - * speed. - * - * Returns: the new speed of the clock. - */ -gdouble -gst_clock_set_speed (GstClock * clock, gdouble speed) -{ - g_return_val_if_fail (GST_IS_CLOCK (clock), 0.0); - - GST_WARNING_OBJECT (clock, "called deprecated function"); - return 1.0; -} - -/** - * gst_clock_get_speed - * @clock: a #GstClock to query - * - * Gets the speed of the given clock. - * - * Returns: the speed of the clock. - */ -gdouble -gst_clock_get_speed (GstClock * clock) -{ - g_return_val_if_fail (GST_IS_CLOCK (clock), 0.0); - - GST_WARNING_OBJECT (clock, "called deprecated function"); - return 1.0; -} - /** * gst_clock_set_resolution * @clock: The clock set the resolution on @@ -502,72 +468,6 @@ gst_clock_get_resolution (GstClock * clock) return G_GINT64_CONSTANT (1); } -/** - * gst_clock_set_active - * @clock: a #GstClock to set state of - * @active: flag indicating if the clock should be activated (TRUE) or deactivated - * - * Activates or deactivates the clock based on the active parameter. - * As soon as the clock is activated, the time will start ticking. - */ -void -gst_clock_set_active (GstClock * clock, gboolean active) -{ - g_return_if_fail (GST_IS_CLOCK (clock)); - - GST_ERROR_OBJECT (clock, "called deprecated function that does nothing now."); - - return; -} - -/** - * gst_clock_is_active - * @clock: a #GstClock to query - * - * Checks if the given clock is active. - * - * Returns: TRUE if the clock is active. - */ -gboolean -gst_clock_is_active (GstClock * clock) -{ - g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE); - - GST_WARNING_OBJECT (clock, "called deprecated function."); - - return TRUE; -} - -/** - * gst_clock_reset - * @clock: a #GstClock to reset - * - * Reset the clock to time 0. - */ -void -gst_clock_reset (GstClock * clock) -{ - GstClockTime time = G_GINT64_CONSTANT (0); - GstClockClass *cclass; - - g_return_if_fail (GST_IS_CLOCK (clock)); - - GST_ERROR_OBJECT (clock, "called deprecated function."); - - cclass = GST_CLOCK_GET_CLASS (clock); - - if (cclass->get_internal_time) { - time = cclass->get_internal_time (clock); - } - - GST_LOCK (clock); - //clock->active = FALSE; - clock->start_time = time; - clock->last_time = G_GINT64_CONSTANT (0); - g_list_foreach (clock->entries, (GFunc) gst_clock_reschedule_func, NULL); - GST_UNLOCK (clock); -} - /** * gst_clock_get_time * @clock: a #GstClock to query @@ -588,7 +488,7 @@ gst_clock_get_time (GstClock * clock) cclass = GST_CLOCK_GET_CLASS (clock); if (cclass->get_internal_time) { - ret = cclass->get_internal_time (clock) - clock->start_time; + ret = cclass->get_internal_time (clock) + clock->adjust; } /* make sure the time is increasing, else return last_time */ if ((gint64) ret < (gint64) clock->last_time) { @@ -600,6 +500,25 @@ gst_clock_get_time (GstClock * clock) return ret; } +/** + * gst_clock_set_time_adjust + * @clock: a #GstClock to adjust + * @adjust: the adjust value + * + * Adjusts the current time of the clock with the adjust value. + * A positive value moves the clock forwards and a backwards value + * moves it backwards. Note that _get_time() always returns + * increasing values so when you move the clock backwards, _get_time() + * will report the previous value until the clock catches up. + */ +void +gst_clock_set_time_adjust (GstClock * clock, GstClockTime adjust) +{ + g_return_if_fail (GST_IS_CLOCK (clock)); + + clock->adjust = adjust; +} + /** * gst_clock_get_next_id * @clock: The clock to query diff --git a/gst/gstclock.h b/gst/gstclock.h index 842c23d240..83eb1d9e76 100644 --- a/gst/gstclock.h +++ b/gst/gstclock.h @@ -63,6 +63,14 @@ G_STMT_START { \ (ts).tv_usec = ((t) - (ts).tv_sec * GST_SECOND) / GST_NSECOND; \ } G_STMT_END +/* timestamp debugging macros */ +#define GST_TIME_FORMAT "u:%02u:%02u.%09u" +#define GST_TIME_ARGS(t) \ + (guint) ((t) / (GST_SECOND * 60 * 60)), \ + (guint) (((t) / (GST_SECOND * 60)) % 60), \ + (guint) (((t) / GST_SECOND) % 60), \ + (guint) ((t) % GST_SECOND) + #define GST_CLOCK_ENTRY_TRACE_NAME "GstClockEntry" typedef struct _GstClockEntry GstClockEntry; @@ -132,15 +140,15 @@ struct _GstClock { /*< public >*/ GstClockFlags flags; - /*< protected >*/ - GstClockTime start_time; + /*< protected >*/ /* with LOCK */ + GstClockTime adjust; GstClockTime last_time; - - /*< private >*/ - guint64 resolution; GList *entries; GMutex *active_mutex; GCond *active_cond; + + /*< private >*/ + guint64 resolution; gboolean stats; gpointer _gst_reserved[GST_PADDING]; @@ -151,9 +159,6 @@ struct _GstClockClass { /*< protected >*/ /* vtable */ - gdouble (*change_speed) (GstClock *clock, - gdouble oldspeed, gdouble newspeed); - gdouble (*get_speed) (GstClock *clock); guint64 (*change_resolution) (GstClock *clock, guint64 old_resolution, guint64 new_resolution); guint64 (*get_resolution) (GstClock *clock); @@ -172,20 +177,12 @@ struct _GstClockClass { GType gst_clock_get_type (void); -gdouble gst_clock_set_speed (GstClock *clock, gdouble speed); -gdouble gst_clock_get_speed (GstClock *clock); - guint64 gst_clock_set_resolution (GstClock *clock, guint64 resolution); guint64 gst_clock_get_resolution (GstClock *clock); -void gst_clock_set_active (GstClock *clock, gboolean active); -gboolean gst_clock_is_active (GstClock *clock); -void gst_clock_reset (GstClock *clock); -gboolean gst_clock_handle_discont (GstClock *clock, guint64 time); - GstClockTime gst_clock_get_time (GstClock *clock); +void gst_clock_set_time_adjust (GstClock *clock, GstClockTime adjust); -GstClockID gst_clock_get_next_id (GstClock *clock); /* creating IDs that can be used to get notifications */ GstClockID gst_clock_new_single_shot_id (GstClock *clock, @@ -193,6 +190,7 @@ GstClockID gst_clock_new_single_shot_id (GstClock *clock, GstClockID gst_clock_new_periodic_id (GstClock *clock, GstClockTime start_time, GstClockTime interval); +GstClockID gst_clock_get_next_id (GstClock *clock); /* operations on IDs */ GstClockTime gst_clock_id_get_time (GstClockID id); diff --git a/gst/gstelement.h b/gst/gstelement.h index be3f088102..e351da539e 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -434,5 +434,10 @@ GstElement *gst_element_factory_create (GstElementFactory * factory, GstElement *gst_element_factory_make (const gchar * factoryname, const gchar * name); +void __gst_element_factory_add_pad_template (GstElementFactory *elementfactory, + GstPadTemplate *templ); +void __gst_element_factory_add_interface (GstElementFactory *elementfactory, + const gchar *interfacename); + G_END_DECLS #endif /* __GST_ELEMENT_H__ */ diff --git a/gst/gstevent.h b/gst/gstevent.h index 5cf3e898b8..333f57c1df 100644 --- a/gst/gstevent.h +++ b/gst/gstevent.h @@ -38,16 +38,15 @@ typedef enum { GST_EVENT_UNKNOWN = 0, GST_EVENT_EOS = 1, GST_EVENT_FLUSH = 2, - GST_EVENT_CAPS = 3, - GST_EVENT_DISCONTINUOUS = 4, - GST_EVENT_QOS = 5, - GST_EVENT_SEEK = 6, - GST_EVENT_SEEK_SEGMENT = 7, - GST_EVENT_SEGMENT_DONE = 8, - GST_EVENT_SIZE = 9, - GST_EVENT_RATE = 10, - GST_EVENT_NAVIGATION = 11, - GST_EVENT_TAG = 12 + GST_EVENT_DISCONTINUOUS = 3, + GST_EVENT_QOS = 4, + GST_EVENT_SEEK = 5, + GST_EVENT_SEEK_SEGMENT = 6, + GST_EVENT_SEGMENT_DONE = 7, + GST_EVENT_SIZE = 8, + GST_EVENT_RATE = 9, + GST_EVENT_NAVIGATION = 10, + GST_EVENT_TAG = 11 } GstEventType; #define GST_EVENT_TRACE_NAME "GstEvent" diff --git a/gst/gstinfo.h b/gst/gstinfo.h index 62c28a004b..0113a405f8 100644 --- a/gst/gstinfo.h +++ b/gst/gstinfo.h @@ -825,15 +825,6 @@ GST_LOG (const char *format, ...) void gst_debug_print_stack_trace (void); -/* timestamp debugging macros */ -/* FIXME 0.9: move into the correct header (gstclock.h) */ -#define GST_TIME_FORMAT "u:%02u:%02u.%09u" -#define GST_TIME_ARGS(t) \ - (guint) ((t) / (GST_SECOND * 60 * 60)), \ - (guint) (((t) / (GST_SECOND * 60)) % 60), \ - (guint) (((t) / GST_SECOND) % 60), \ - (guint) ((t) % GST_SECOND) - G_END_DECLS #endif /* __GSTINFO_H__ */ diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index 1d0dab1b3a..a9b19abbda 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -269,8 +269,9 @@ gst_pipeline_change_state (GstElement * element) { GstElementStateReturn result = GST_STATE_SUCCESS; GstPipeline *pipeline = GST_PIPELINE (element); + gint transition = GST_STATE_TRANSITION (element); - switch (GST_STATE_TRANSITION (element)) { + switch (transition) { case GST_STATE_NULL_TO_READY: gst_scheduler_setup (GST_ELEMENT_SCHEDULER (pipeline)); break; @@ -280,8 +281,13 @@ gst_pipeline_change_state (GstElement * element) break; case GST_STATE_PAUSED_TO_PLAYING: if (element->clock) { - element->base_time = gst_clock_get_time (element->clock); + /* we set time slightly ahead because of context switches */ + pipeline->start_time = + gst_clock_get_time (element->clock) + 10 * GST_MSECOND; + element->base_time = pipeline->start_time - pipeline->stream_time; } + GST_DEBUG ("stream_time=%" G_GUINT64_FORMAT ", start_time=%" + G_GUINT64_FORMAT, pipeline->stream_time, pipeline->start_time); break; case GST_STATE_PLAYING_TO_PAUSED: case GST_STATE_PAUSED_TO_READY: @@ -291,6 +297,26 @@ gst_pipeline_change_state (GstElement * element) result = GST_ELEMENT_CLASS (parent_class)->change_state (element); + switch (transition) { + case GST_STATE_READY_TO_PAUSED: + pipeline->stream_time = 0; + break; + case GST_STATE_PAUSED_TO_PLAYING: + break; + case GST_STATE_PLAYING_TO_PAUSED: + if (element->clock) { + pipeline->stream_time = gst_clock_get_time (element->clock) - + element->base_time; + } + GST_DEBUG ("stream_time=%" G_GUINT64_FORMAT ", start_time=%" + G_GUINT64_FORMAT, pipeline->stream_time, pipeline->start_time); + break; + case GST_STATE_PAUSED_TO_READY: + break; + case GST_STATE_READY_TO_NULL: + break; + } + /* we wait for async state changes ourselves */ if (result == GST_STATE_ASYNC) { GST_STATE_UNLOCK (pipeline); diff --git a/gst/gstpipeline.h b/gst/gstpipeline.h index 830b4e18dd..a058892803 100644 --- a/gst/gstpipeline.h +++ b/gst/gstpipeline.h @@ -49,6 +49,8 @@ struct _GstPipeline { GstBin bin; GstClock *fixed_clock; /* fixed clock if any */ + GstClockTime start_time; + GstClockTime stream_time; GList *eosed; /* list of elements that posted EOS */ diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c index c633232187..5252d78a48 100644 --- a/gst/gstsystemclock.c +++ b/gst/gstsystemclock.c @@ -191,19 +191,24 @@ gst_system_clock_wait (GstClock * clock, GstClockEntry * entry) current = gst_clock_get_time (clock); diff = GST_CLOCK_ENTRY_TIME (entry) - current; - target = gst_system_clock_get_internal_time (clock) + diff; + target = GST_CLOCK_ENTRY_TIME (entry); - GST_CAT_DEBUG (GST_CAT_CLOCK, "real_target %" G_GUINT64_FORMAT - " target %" G_GUINT64_FORMAT - " now %" G_GUINT64_FORMAT, target, GST_CLOCK_ENTRY_TIME (entry), current); + GST_CAT_DEBUG (GST_CAT_CLOCK, "real_target %" GST_TIME_FORMAT + " target %" GST_TIME_FORMAT + " now %" GST_TIME_FORMAT + " diff %" G_GINT64_FORMAT, + GST_TIME_ARGS (target), + GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry)), + GST_TIME_ARGS (current), diff); - if (((gint64) target) > 0) { + if (diff > 0) { GTimeVal tv; GST_TIME_TO_TIMEVAL (target, tv); g_mutex_lock (sysclock->mutex); g_cond_timed_wait (sysclock->cond, sysclock->mutex, &tv); g_mutex_unlock (sysclock->mutex); + res = entry->status; } else { res = GST_CLOCK_ENTRY_EARLY; diff --git a/gst/gstutils.c b/gst/gstutils.c index c6dbc8ffcf..edeaa957c8 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -395,7 +395,7 @@ gst_element_finish_preroll (GstElement * element, GMutex * streamlock) /* grab state change lock */ GST_STATE_LOCK (element); /* if we are going to PAUSED, we can commit the state change */ - if (GST_STATE_TRANSITION (element) == GST_STATE_READY_TO_PAUSED) { + if (GST_STATE_PENDING (element) == GST_STATE_PAUSED) { gst_element_commit_state (GST_ELEMENT (element)); } /* if we are paused we need to wait for playing to continue */ diff --git a/gst/registries/gstxmlregistry.c b/gst/registries/gstxmlregistry.c index b7f624acbd..396ea1359e 100644 --- a/gst/registries/gstxmlregistry.c +++ b/gst/registries/gstxmlregistry.c @@ -814,7 +814,7 @@ gst_xml_registry_parse_element_factory (GMarkupParseContext * context, } else if (!strcmp (tag, "interface")) { gchar *tmp = g_strndup (text, text_len); - //__gst_element_factory_add_interface (factory, tmp); + __gst_element_factory_add_interface (factory, tmp); g_free (tmp); } @@ -1040,8 +1040,8 @@ gst_xml_registry_end_element (GMarkupParseContext * context, xmlregistry->name_template = NULL; xmlregistry->caps = NULL; - //__gst_element_factory_add_pad_template (GST_ELEMENT_FACTORY - // (xmlregistry->current_feature), template); + __gst_element_factory_add_pad_template (GST_ELEMENT_FACTORY + (xmlregistry->current_feature), template); xmlregistry->state = GST_XML_REGISTRY_FEATURE; xmlregistry->parser = gst_xml_registry_parse_element_factory; } diff --git a/libs/gst/dataprotocol/dataprotocol.c b/libs/gst/dataprotocol/dataprotocol.c index 398ae117ac..eadef1aceb 100644 --- a/libs/gst/dataprotocol/dataprotocol.c +++ b/libs/gst/dataprotocol/dataprotocol.c @@ -188,7 +188,7 @@ gst_dp_header_from_buffer (const GstBuffer * buffer, GstDPHeaderFlag flags, /* data flags */ /* we only copy KEY_UNIT,DELTA_UNIT and IN_CAPS flags */ - flags_mask = GST_DATA_FLAG_SHIFT (GST_BUFFER_KEY_UNIT) | + flags_mask = GST_DATA_FLAG_SHIFT (GST_BUFFER_PREROLL) | GST_DATA_FLAG_SHIFT (GST_BUFFER_IN_CAPS) | GST_DATA_FLAG_SHIFT (GST_BUFFER_DELTA_UNIT);