gst/: Convert timeout value in _get_state() to absolute time as required by the _cond_wait().

Original commit message from CVS:
* 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.
This commit is contained in:
Wim Taymans 2005-02-24 14:27:54 +00:00
parent cea03c1e53
commit 47eb83ff1c
9 changed files with 173 additions and 29 deletions

View file

@ -1,3 +1,23 @@
2005-02-24 Wim Taymans <wim@fluendo.com>
* 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 <wingo@pobox.com>
* tests/bench-mass_elements.scm, tests/mass_elements.gnuplot:

View file

@ -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) =

View file

@ -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); */
}
}

View file

@ -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.

View file

@ -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);

View file

@ -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);
}

View file

@ -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 */

View file

@ -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) =

View file

@ -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); */
}
}