mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-15 22:01:27 +00:00
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:
parent
cea03c1e53
commit
47eb83ff1c
9 changed files with 173 additions and 29 deletions
20
ChangeLog
20
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -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) =
|
||||
|
|
|
@ -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); */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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) =
|
||||
|
|
|
@ -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); */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue