diff --git a/ChangeLog b/ChangeLog index 35020d8ae9..31e4e172b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2005-02-24 Wim Taymans + + * gst/elements/gstfakesrc.c: (gst_fakesrc_get_range_unlocked): + * gst/elements/gstidentity.c: (gst_identity_handle_buffer): + * gst/gstelement.c: (gst_element_get_state_func), + (gst_element_lost_state): + * gst/gstelement.h: + * gst/gstpipeline.c: (gst_pipeline_class_init), + (gst_pipeline_init), (gst_pipeline_set_property), + (gst_pipeline_get_property), (is_eos), (pipeline_bus_handler), + (gst_pipeline_change_state): + * gst/gstpipeline.h: + Convert timeout value in _get_state() to absolute time as + required by the _cond_wait(). + Add _lost_state() to GstElement when elements in PAUSED loose + the preroll after a flush. + Add properties to GstPipeline, one to adjust clock times and + another to configure a timeout for a possibly blocking operation. + Removed some old methods. + 2005-02-24 Andy Wingo * tests/bench-mass_elements.scm, tests/mass_elements.gnuplot: diff --git a/gst/elements/gstfakesrc.c b/gst/elements/gstfakesrc.c index 7ad57153cf..4877d07b5c 100644 --- a/gst/elements/gstfakesrc.c +++ b/gst/elements/gstfakesrc.c @@ -832,7 +832,7 @@ gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, if (src->datarate > 0) { time = (src->bytes_sent * GST_SECOND) / src->datarate; if (src->sync) { - gst_element_wait (GST_ELEMENT (src), time); + /* gst_element_wait (GST_ELEMENT (src), time); */ } GST_BUFFER_DURATION (buf) = diff --git a/gst/elements/gstidentity.c b/gst/elements/gstidentity.c index 4e45de44c6..2137fdcf9a 100644 --- a/gst/elements/gstidentity.c +++ b/gst/elements/gstidentity.c @@ -596,7 +596,7 @@ gst_identity_handle_buffer (GstIdentity * identity, GstBuffer * buf) if (identity->sync) { if (identity->clock) { - gst_element_wait (GST_ELEMENT (identity), time); + /* gst_element_wait (GST_ELEMENT (identity), time); */ } } diff --git a/gst/gstelement.c b/gst/gstelement.c index 65bbf3923d..7a0af14254 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -1588,9 +1588,20 @@ gst_element_get_state_func (GstElement * element, old_pending = GST_STATE_PENDING (element); if (old_pending != GST_STATE_VOID_PENDING) { + GTimeVal *timeval, abstimeout; + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "wait for pending"); + if (timeout) { + /* make timeout absolute */ + g_get_current_time (&abstimeout); + g_time_val_add (&abstimeout, + timeout->tv_sec * G_USEC_PER_SEC + timeout->tv_usec); + timeval = &abstimeout; + } else { + timeval = NULL; + } /* we have a pending state change, wait for it to complete */ - if (!GST_STATE_TIMED_WAIT (element, timeout)) { + if (!GST_STATE_TIMED_WAIT (element, timeval)) { GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "timeout"); /* timeout triggered */ ret = GST_STATE_ASYNC; @@ -1745,6 +1756,40 @@ gst_element_commit_state (GstElement * element) } } +/** + * gst_element_lost_state: + * @element: a #GstElement the state is lost of + * + * Brings the element to the lost state. The current state of the + * element is copied to the pending state so that any call to + * #gst_element_get_state() will return ASYNC. + * This is mostly used for elements that lost their preroll buffer + * in the PAUSED state after a flush, they become PAUSED again + * if a new preroll buffer is queued. + * This function can only be called when the element is currently + * not in error or an async state change. + * + * This function can only be called with the STATE_LOCK held. + * + * MT safe. + */ +void +gst_element_lost_state (GstElement * element) +{ + g_return_if_fail (GST_IS_ELEMENT (element)); + + if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING && + !GST_STATE_ERROR (element)) { + GstElementState current_state = GST_STATE (element); + + GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, + "lost state of %s", gst_element_state_get_name (current_state)); + + GST_STATE_PENDING (element) = current_state; + GST_STATE_ERROR (element) = FALSE; + } +} + /** * gst_element_set_state: * @element: a #GstElement to change state of. diff --git a/gst/gstelement.h b/gst/gstelement.h index 4c3e1eda64..48a9f61e3e 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -223,19 +223,19 @@ struct _GstElementClass guint32 pad_templ_cookie; /* signal callbacks */ - void (*state_change) (GstElement * element, GstElementState old, - GstElementState state); - void (*new_pad) (GstElement * element, GstPad * pad); - void (*pad_removed) (GstElement * element, GstPad * pad); - void (*no_more_pads) (GstElement * element); + void (*state_change) (GstElement * element, GstElementState old, + GstElementState state); + void (*new_pad) (GstElement * element, GstPad * pad); + void (*pad_removed) (GstElement * element, GstPad * pad); + void (*no_more_pads) (GstElement * element); /*< protected > */ /* vtable */ /* request/release pads */ GstPad *(*request_new_pad) (GstElement * element, GstPadTemplate * templ, - const gchar * name); - void (*release_pad) (GstElement * element, GstPad * pad); + const gchar * name); + void (*release_pad) (GstElement * element, GstPad * pad); /* state changes */ GstElementStateReturn (*get_state) (GstElement * element, GstElementState * state, @@ -243,17 +243,17 @@ struct _GstElementClass GstElementStateReturn (*change_state) (GstElement * element); /* manager */ - void (*set_manager) (GstElement * element, GstPipeline * pipeline); - void (*set_bus) (GstElement * element, GstBus * bus); - void (*set_scheduler) (GstElement * element, GstScheduler * scheduler); + void (*set_manager) (GstElement * element, GstPipeline * pipeline); + void (*set_bus) (GstElement * element, GstBus * bus); + void (*set_scheduler) (GstElement * element, GstScheduler * scheduler); /* set/get clocks */ - GstClock *(*get_clock) (GstElement * element); - void (*set_clock) (GstElement * element, GstClock * clock); + GstClock * (*get_clock) (GstElement * element); + void (*set_clock) (GstElement * element, GstClock * clock); /* index */ - GstIndex *(*get_index) (GstElement * element); - void (*set_index) (GstElement * element, GstIndex * index); + GstIndex * (*get_index) (GstElement * element); + void (*set_index) (GstElement * element, GstIndex * index); /* query/convert/events functions */ const GstEventMask *(*get_event_masks) (GstElement * element); @@ -295,11 +295,6 @@ gboolean gst_element_provides_clock (GstElement * element); GstClock *gst_element_get_clock (GstElement * element); void gst_element_set_clock (GstElement * element, GstClock * clock); -GstClockReturn gst_element_clock_wait (GstElement * element, - GstClockID id, GstClockTimeDiff * jitter); -GstClockTime gst_element_get_time (GstElement * element); -gboolean gst_element_wait (GstElement * element, GstClockTime timestamp); - /* indexes */ gboolean gst_element_is_indexable (GstElement * element); void gst_element_set_index (GstElement * element, GstIndex * index); @@ -365,6 +360,7 @@ GstElementStateReturn gst_element_set_state (GstElement * element, void gst_element_abort_state (GstElement * element); void gst_element_commit_state (GstElement * element); +void gst_element_lost_state (GstElement * element); /* factory management */ GstElementFactory *gst_element_get_factory (GstElement * element); diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index a2820cbc76..c2a8797520 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -40,10 +40,14 @@ enum LAST_SIGNAL }; +#define DEFAULT_DELAY 0 +#define DEFAULT_PLAY_TIMEOUT (2*GST_SECOND) enum { - ARG_0 - /* FILL ME */ + ARG_0, + ARG_DELAY, + ARG_PLAY_TIMEOUT, + /* FILL ME */ }; @@ -52,6 +56,10 @@ static void gst_pipeline_class_init (gpointer g_class, gpointer class_data); static void gst_pipeline_init (GTypeInstance * instance, gpointer g_class); static void gst_pipeline_dispose (GObject * object); +static void gst_pipeline_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_pipeline_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); static GstBusSyncReply pipeline_bus_handler (GstBus * bus, GstMessage * message, GstPipeline * pipeline); @@ -105,6 +113,19 @@ gst_pipeline_class_init (gpointer g_class, gpointer class_data) parent_class = g_type_class_peek_parent (klass); + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_pipeline_set_property); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_pipeline_get_property); + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DELAY, + g_param_spec_uint64 ("delay", "Delay", + "Expected delay needed for elements " + "to spin up to PLAYING in nanoseconds", 0, G_MAXUINT64, DEFAULT_DELAY, + G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PLAY_TIMEOUT, + g_param_spec_uint64 ("play-timeout", "Play Timeout", + "Max timeout for going " "to PLAYING in nanoseconds", 0, G_MAXUINT64, + DEFAULT_PLAY_TIMEOUT, G_PARAM_READWRITE)); + gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose); gstelement_class->change_state = @@ -134,7 +155,8 @@ gst_pipeline_init (GTypeInstance * instance, gpointer g_class) gst_bus_set_sync_handler (bus, (GstBusSyncHandler) pipeline_bus_handler, pipeline); pipeline->eosed = NULL; - pipeline->delay = 0; + pipeline->delay = DEFAULT_DELAY; + pipeline->play_timeout = DEFAULT_PLAY_TIMEOUT; /* we are our own manager */ GST_ELEMENT_MANAGER (pipeline) = pipeline; gst_element_set_bus (GST_ELEMENT (pipeline), bus); @@ -152,6 +174,52 @@ gst_pipeline_dispose (GObject * object) G_OBJECT_CLASS (parent_class)->dispose (object); } +static void +gst_pipeline_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstPipeline *pipeline = GST_PIPELINE (object); + + switch (prop_id) { + case ARG_DELAY: + GST_LOCK (pipeline); + pipeline->delay = g_value_get_uint64 (value); + GST_UNLOCK (pipeline); + break; + case ARG_PLAY_TIMEOUT: + GST_LOCK (pipeline); + pipeline->play_timeout = g_value_get_uint64 (value); + GST_UNLOCK (pipeline); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_pipeline_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstPipeline *pipeline = GST_PIPELINE (object); + + switch (prop_id) { + case ARG_DELAY: + GST_LOCK (pipeline); + g_value_set_uint64 (value, pipeline->delay); + GST_UNLOCK (pipeline); + break; + case ARG_PLAY_TIMEOUT: + GST_LOCK (pipeline); + g_value_set_uint64 (value, pipeline->play_timeout); + GST_UNLOCK (pipeline); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + static gboolean is_eos (GstPipeline * pipeline) { @@ -329,10 +397,24 @@ gst_pipeline_change_state (GstElement * element) break; } - /* we wait for async state changes ourselves */ + /* we wait for async state changes ourselves. + * FIXME this can block forever, better do this in a worker + * thread or use a timeout? */ if (result == GST_STATE_ASYNC) { + GTimeVal *timeval, timeout; + GST_STATE_UNLOCK (pipeline); - result = gst_element_get_state (element, NULL, NULL, NULL); + + GST_LOCK (pipeline); + if (pipeline->play_timeout > 0) { + GST_TIME_TO_TIMEVAL (pipeline->play_timeout, timeout); + timeval = &timeout; + } else { + timeval = NULL; + } + GST_UNLOCK (pipeline); + + result = gst_element_get_state (element, NULL, NULL, timeval); GST_STATE_LOCK (pipeline); } diff --git a/gst/gstpipeline.h b/gst/gstpipeline.h index 2568be12bd..c726a8f500 100644 --- a/gst/gstpipeline.h +++ b/gst/gstpipeline.h @@ -52,6 +52,7 @@ struct _GstPipeline { GstClock *fixed_clock; /* fixed clock if any */ GstClockTime stream_time; GstClockTime delay; + GstClockTime play_timeout; GList *eosed; /* list of elements that posted EOS */ diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c index 7ad57153cf..4877d07b5c 100644 --- a/plugins/elements/gstfakesrc.c +++ b/plugins/elements/gstfakesrc.c @@ -832,7 +832,7 @@ gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length, if (src->datarate > 0) { time = (src->bytes_sent * GST_SECOND) / src->datarate; if (src->sync) { - gst_element_wait (GST_ELEMENT (src), time); + /* gst_element_wait (GST_ELEMENT (src), time); */ } GST_BUFFER_DURATION (buf) = diff --git a/plugins/elements/gstidentity.c b/plugins/elements/gstidentity.c index 4e45de44c6..2137fdcf9a 100644 --- a/plugins/elements/gstidentity.c +++ b/plugins/elements/gstidentity.c @@ -596,7 +596,7 @@ gst_identity_handle_buffer (GstIdentity * identity, GstBuffer * buf) if (identity->sync) { if (identity->clock) { - gst_element_wait (GST_ELEMENT (identity), time); + /* gst_element_wait (GST_ELEMENT (identity), time); */ } }