mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-29 13:11:06 +00:00
gst/: Patch state changes according to design document.
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_get_state), (gst_bin_change_state), (gst_bin_get_by_name_recurse_up): * gst/gstelement.c: (gst_element_add_pad), (gst_element_remove_pad), (gst_element_get_state_func), (gst_element_get_state), (gst_element_abort_state), (gst_element_set_state), (gst_element_pads_activate): * gst/gstelement.h: Patch state changes according to design document.
This commit is contained in:
parent
faeeed3dba
commit
83156b4a9d
4 changed files with 104 additions and 66 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
||||||
|
2005-01-12 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* 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_get_state),
|
||||||
|
(gst_bin_change_state), (gst_bin_get_by_name_recurse_up):
|
||||||
|
* gst/gstelement.c: (gst_element_add_pad),
|
||||||
|
(gst_element_remove_pad), (gst_element_get_state_func),
|
||||||
|
(gst_element_get_state), (gst_element_abort_state),
|
||||||
|
(gst_element_set_state), (gst_element_pads_activate):
|
||||||
|
* gst/gstelement.h:
|
||||||
|
Patch state changes according to design document.
|
||||||
|
|
||||||
2005-01-11 Wim Taymans <wim@fluendo.com>
|
2005-01-11 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* configure.ac:
|
* configure.ac:
|
||||||
|
|
30
gst/gstbin.c
30
gst/gstbin.c
|
@ -53,7 +53,7 @@ GType _gst_bin_type = 0;
|
||||||
static void gst_bin_dispose (GObject * object);
|
static void gst_bin_dispose (GObject * object);
|
||||||
|
|
||||||
static GstElementStateReturn gst_bin_change_state (GstElement * element);
|
static GstElementStateReturn gst_bin_change_state (GstElement * element);
|
||||||
static gboolean gst_bin_get_state (GstElement * element,
|
static GstElementStateReturn gst_bin_get_state (GstElement * element,
|
||||||
GstElementState * state, GstElementState * pending, GTimeVal * timeout);
|
GstElementState * state, GstElementState * pending, GTimeVal * timeout);
|
||||||
|
|
||||||
#ifndef GST_DISABLE_INDEX
|
#ifndef GST_DISABLE_INDEX
|
||||||
|
@ -645,12 +645,12 @@ gst_bin_iterate_sinks (GstBin * bin)
|
||||||
*
|
*
|
||||||
* MT safe
|
* MT safe
|
||||||
*/
|
*/
|
||||||
static gboolean
|
static GstElementStateReturn
|
||||||
gst_bin_get_state (GstElement * element, GstElementState * state,
|
gst_bin_get_state (GstElement * element, GstElementState * state,
|
||||||
GstElementState * pending, GTimeVal * timeout)
|
GstElementState * pending, GTimeVal * timeout)
|
||||||
{
|
{
|
||||||
GstBin *bin = GST_BIN (element);
|
GstBin *bin = GST_BIN (element);
|
||||||
gboolean ret;
|
GstElementStateReturn ret;
|
||||||
GList *children;
|
GList *children;
|
||||||
guint32 children_cookie;
|
guint32 children_cookie;
|
||||||
|
|
||||||
|
@ -661,7 +661,7 @@ gst_bin_get_state (GstElement * element, GstElementState * state,
|
||||||
* is still busy with its state change. */
|
* is still busy with its state change. */
|
||||||
GST_LOCK (bin);
|
GST_LOCK (bin);
|
||||||
restart:
|
restart:
|
||||||
ret = TRUE;
|
ret = GST_STATE_SUCCESS;
|
||||||
children = bin->children;
|
children = bin->children;
|
||||||
children_cookie = bin->children_cookie;
|
children_cookie = bin->children_cookie;
|
||||||
while (children) {
|
while (children) {
|
||||||
|
@ -670,13 +670,14 @@ restart:
|
||||||
gst_object_ref (GST_OBJECT_CAST (child));
|
gst_object_ref (GST_OBJECT_CAST (child));
|
||||||
GST_UNLOCK (bin);
|
GST_UNLOCK (bin);
|
||||||
|
|
||||||
/* ret is false if some child is still performing the state change */
|
/* ret is ASYNC if some child is still performing the state change */
|
||||||
ret = gst_element_get_state (child, NULL, NULL, timeout);
|
ret = gst_element_get_state (child, NULL, NULL, timeout);
|
||||||
|
|
||||||
gst_object_unref (GST_OBJECT_CAST (child));
|
gst_object_unref (GST_OBJECT_CAST (child));
|
||||||
|
|
||||||
if (!ret) {
|
if (ret != GST_STATE_SUCCESS) {
|
||||||
/* some child is still busy, return FALSE */
|
/* some child is still busy or in error, we can report that
|
||||||
|
* right away. */
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* now grab the lock to iterate to the next child */
|
/* now grab the lock to iterate to the next child */
|
||||||
|
@ -692,9 +693,18 @@ restart:
|
||||||
done:
|
done:
|
||||||
/* now we can take the state lock */
|
/* now we can take the state lock */
|
||||||
GST_STATE_LOCK (bin);
|
GST_STATE_LOCK (bin);
|
||||||
if (ret) {
|
switch (ret) {
|
||||||
/* no async children, we can commit the state */
|
case GST_STATE_SUCCESS:
|
||||||
gst_element_commit_state (element);
|
/* we can commit the state */
|
||||||
|
gst_element_commit_state (element);
|
||||||
|
break;
|
||||||
|
case GST_STATE_FAILURE:
|
||||||
|
/* some element failed, abort the state change */
|
||||||
|
gst_element_abort_state (element);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* other cases are just passed along */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* and report the state if needed */
|
/* and report the state if needed */
|
||||||
|
|
|
@ -66,7 +66,7 @@ static void gst_element_base_class_finalize (gpointer g_class);
|
||||||
static void gst_element_dispose (GObject * object);
|
static void gst_element_dispose (GObject * object);
|
||||||
|
|
||||||
static GstElementStateReturn gst_element_change_state (GstElement * element);
|
static GstElementStateReturn gst_element_change_state (GstElement * element);
|
||||||
static gboolean gst_element_get_state_func (GstElement * element,
|
static GstElementStateReturn gst_element_get_state_func (GstElement * element,
|
||||||
GstElementState * state, GstElementState * pending, GTimeVal * timeout);
|
GstElementState * state, GstElementState * pending, GTimeVal * timeout);
|
||||||
static void gst_element_set_manager_func (GstElement * element,
|
static void gst_element_set_manager_func (GstElement * element,
|
||||||
GstPipeline * manager);
|
GstPipeline * manager);
|
||||||
|
@ -1559,11 +1559,11 @@ gst_element_sync_state_with_parent (GstElement * element)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MT safe */
|
/* MT safe */
|
||||||
static gboolean
|
static GstElementStateReturn
|
||||||
gst_element_get_state_func (GstElement * element,
|
gst_element_get_state_func (GstElement * element,
|
||||||
GstElementState * state, GstElementState * pending, GTimeVal * timeout)
|
GstElementState * state, GstElementState * pending, GTimeVal * timeout)
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
GstElementStateReturn ret = GST_STATE_FAILURE;
|
||||||
GstElementState old_pending;
|
GstElementState old_pending;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
|
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
|
||||||
|
@ -1578,10 +1578,14 @@ gst_element_get_state_func (GstElement * element,
|
||||||
*state = GST_STATE (element);
|
*state = GST_STATE (element);
|
||||||
if (pending)
|
if (pending)
|
||||||
*pending = GST_STATE_PENDING (element);
|
*pending = GST_STATE_PENDING (element);
|
||||||
ret = FALSE;
|
ret = GST_STATE_ASYNC;
|
||||||
} else {
|
} else {
|
||||||
/* could be success or failure, we could check here if the
|
/* could be success or failure */
|
||||||
* state is equal to the old pending state */
|
if (old_pending == GST_STATE (element)) {
|
||||||
|
ret = GST_STATE_SUCCESS;
|
||||||
|
} else {
|
||||||
|
ret = GST_STATE_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* if nothing is pending anymore we can return TRUE and
|
/* if nothing is pending anymore we can return TRUE and
|
||||||
|
@ -1591,7 +1595,7 @@ gst_element_get_state_func (GstElement * element,
|
||||||
*state = GST_STATE (element);
|
*state = GST_STATE (element);
|
||||||
if (pending)
|
if (pending)
|
||||||
*pending = GST_STATE_VOID_PENDING;
|
*pending = GST_STATE_VOID_PENDING;
|
||||||
ret = TRUE;
|
ret = GST_STATE_SUCCESS;
|
||||||
}
|
}
|
||||||
GST_STATE_UNLOCK (element);
|
GST_STATE_UNLOCK (element);
|
||||||
|
|
||||||
|
@ -1605,23 +1609,32 @@ gst_element_get_state_func (GstElement * element,
|
||||||
* @pending: a pointer to #GstElementState to hold the pending state.
|
* @pending: a pointer to #GstElementState to hold the pending state.
|
||||||
* Can be NULL.
|
* Can be NULL.
|
||||||
* @timeout: a #GTimeVal to specify the timeout for an async
|
* @timeout: a #GTimeVal to specify the timeout for an async
|
||||||
* state change.
|
* state change or NULL for infinite timeout.
|
||||||
*
|
*
|
||||||
* Gets the state of the element.
|
* Gets the state of the element.
|
||||||
*
|
*
|
||||||
* Returns: TRUE if the element has no more pending state, FALSE
|
* For elements that performed an ASYNC state change, as reported by
|
||||||
* if the element is still performing a state change.
|
* #gst_element_set_state(), this function will block up to the
|
||||||
|
* specified timeout value for the state change to complete.
|
||||||
|
* If the element completes the state change or goes into
|
||||||
|
* an error, this function returns immediatly with a return value of
|
||||||
|
* GST_STATE_SUCCESS or GST_STATE_FAILURE respectively.
|
||||||
|
*
|
||||||
|
* Returns: GST_STATE_SUCCESS if the element has no more pending state and
|
||||||
|
* the last state change succeeded, GST_STATE_ASYNC
|
||||||
|
* if the element is still performing a state change or
|
||||||
|
* GST_STATE_FAILURE if the last state change failed.
|
||||||
*
|
*
|
||||||
* MT safe.
|
* MT safe.
|
||||||
*/
|
*/
|
||||||
gboolean
|
GstElementStateReturn
|
||||||
gst_element_get_state (GstElement * element,
|
gst_element_get_state (GstElement * element,
|
||||||
GstElementState * state, GstElementState * pending, GTimeVal * timeout)
|
GstElementState * state, GstElementState * pending, GTimeVal * timeout)
|
||||||
{
|
{
|
||||||
GstElementClass *oclass;
|
GstElementClass *oclass;
|
||||||
gboolean result = FALSE;
|
GstElementStateReturn result = GST_STATE_FAILURE;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
|
g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
|
||||||
|
|
||||||
oclass = GST_ELEMENT_GET_CLASS (element);
|
oclass = GST_ELEMENT_GET_CLASS (element);
|
||||||
|
|
||||||
|
@ -1652,14 +1665,14 @@ gst_element_abort_state (GstElement * element)
|
||||||
|
|
||||||
pending = GST_STATE_PENDING (element);
|
pending = GST_STATE_PENDING (element);
|
||||||
|
|
||||||
if (pending != GST_STATE_VOID_PENDING) {
|
if (pending != GST_STATE_VOID_PENDING && !GST_STATE_ERROR (element)) {
|
||||||
GstElementState old_state = GST_STATE (element);
|
GstElementState old_state = GST_STATE (element);
|
||||||
|
|
||||||
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
|
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
|
||||||
"aborting state from %s to %s", gst_element_state_get_name (old_state),
|
"aborting state from %s to %s", gst_element_state_get_name (old_state),
|
||||||
gst_element_state_get_name (pending));
|
gst_element_state_get_name (pending));
|
||||||
|
|
||||||
GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
|
GST_STATE_ERROR (element) = TRUE;
|
||||||
|
|
||||||
GST_STATE_BROADCAST (element);
|
GST_STATE_BROADCAST (element);
|
||||||
}
|
}
|
||||||
|
@ -1726,6 +1739,9 @@ gst_element_set_state (GstElement * element, GstElementState state)
|
||||||
/* get the element state lock */
|
/* get the element state lock */
|
||||||
GST_STATE_LOCK (element);
|
GST_STATE_LOCK (element);
|
||||||
|
|
||||||
|
/* clear the error flag */
|
||||||
|
GST_STATE_ERROR (element) = FALSE;
|
||||||
|
|
||||||
/* start with the current state */
|
/* start with the current state */
|
||||||
current = GST_STATE (element);
|
current = GST_STATE (element);
|
||||||
|
|
||||||
|
@ -1749,17 +1765,11 @@ gst_element_set_state (GstElement * element, GstElementState state)
|
||||||
/* set the pending state variable */
|
/* set the pending state variable */
|
||||||
GST_STATE_PENDING (element) = pending;
|
GST_STATE_PENDING (element) = pending;
|
||||||
|
|
||||||
if (pending != state) {
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
"%s: setting state from %s to %s",
|
||||||
"intermediate: setting state from %s to %s",
|
(pending != state ? "intermediate" : "final"),
|
||||||
gst_element_state_get_name (current),
|
gst_element_state_get_name (current),
|
||||||
gst_element_state_get_name (pending));
|
gst_element_state_get_name (pending));
|
||||||
} else {
|
|
||||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
|
||||||
"final: setting state from %s to %s",
|
|
||||||
gst_element_state_get_name (current),
|
|
||||||
gst_element_state_get_name (pending));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* call the state change function so it can set the state */
|
/* call the state change function so it can set the state */
|
||||||
if (oclass->change_state)
|
if (oclass->change_state)
|
||||||
|
|
|
@ -66,6 +66,7 @@ struct _GstElementDetails
|
||||||
*/
|
*/
|
||||||
#define GST_STATE(obj) (GST_ELEMENT(obj)->current_state)
|
#define GST_STATE(obj) (GST_ELEMENT(obj)->current_state)
|
||||||
#define GST_STATE_PENDING(obj) (GST_ELEMENT(obj)->pending_state)
|
#define GST_STATE_PENDING(obj) (GST_ELEMENT(obj)->pending_state)
|
||||||
|
#define GST_STATE_ERROR(obj) (GST_ELEMENT(obj)->state_error)
|
||||||
|
|
||||||
/* Note: using 8 bit shift mostly "just because", it leaves us enough room to grow <g> */
|
/* Note: using 8 bit shift mostly "just because", it leaves us enough room to grow <g> */
|
||||||
#define GST_STATE_TRANSITION(obj) ((GST_STATE(obj)<<8) | GST_STATE_PENDING(obj))
|
#define GST_STATE_TRANSITION(obj) ((GST_STATE(obj)<<8) | GST_STATE_PENDING(obj))
|
||||||
|
@ -173,32 +174,34 @@ struct _GstElement
|
||||||
|
|
||||||
/*< public > *//* with STATE_LOCK */
|
/*< public > *//* with STATE_LOCK */
|
||||||
/* element state */
|
/* element state */
|
||||||
GMutex *state_lock;
|
GMutex *state_lock;
|
||||||
GCond *state_cond;
|
GCond *state_cond;
|
||||||
guint8 current_state;
|
guint8 current_state;
|
||||||
guint8 pending_state;
|
guint8 pending_state;
|
||||||
|
gboolean state_error; /* flag is set when the element has an error in the last state
|
||||||
|
change. it is cleared when doing another state change. */
|
||||||
|
|
||||||
/*< public > *//* with LOCK */
|
/*< public > *//* with LOCK */
|
||||||
/* element manager */
|
/* element manager */
|
||||||
GstPipeline *manager;
|
GstPipeline *manager;
|
||||||
GstBus *bus;
|
GstBus *bus;
|
||||||
GstScheduler *scheduler;
|
GstScheduler *scheduler;
|
||||||
/* private pointer for the scheduler */
|
/* private pointer for the scheduler */
|
||||||
gpointer sched_private;
|
gpointer sched_private;
|
||||||
|
|
||||||
/* allocated clock */
|
/* allocated clock */
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
GstClockTimeDiff base_time; /* NULL/READY: 0 - PAUSED: current time - PLAYING: difference to clock */
|
GstClockTimeDiff base_time; /* NULL/READY: 0 - PAUSED: current time - PLAYING: difference to clock */
|
||||||
|
|
||||||
/* element pads, these lists can only be iterated while holding
|
/* element pads, these lists can only be iterated while holding
|
||||||
* the LOCK or checking the cookie after each LOCK. */
|
* the LOCK or checking the cookie after each LOCK. */
|
||||||
guint16 numpads;
|
guint16 numpads;
|
||||||
GList *pads;
|
GList *pads;
|
||||||
guint16 numsrcpads;
|
guint16 numsrcpads;
|
||||||
GList *srcpads;
|
GList *srcpads;
|
||||||
guint16 numsinkpads;
|
guint16 numsinkpads;
|
||||||
GList *sinkpads;
|
GList *sinkpads;
|
||||||
guint32 pads_cookie;
|
guint32 pads_cookie;
|
||||||
|
|
||||||
/*< private > */
|
/*< private > */
|
||||||
gpointer _gst_reserved[GST_PADDING];
|
gpointer _gst_reserved[GST_PADDING];
|
||||||
|
@ -236,9 +239,9 @@ struct _GstElementClass
|
||||||
void (*release_pad) (GstElement * element, GstPad * pad);
|
void (*release_pad) (GstElement * element, GstPad * pad);
|
||||||
|
|
||||||
/* state changes */
|
/* state changes */
|
||||||
gboolean (*get_state) (GstElement * element, GstElementState * state,
|
GstElementStateReturn (*get_state) (GstElement * element, GstElementState * state,
|
||||||
GstElementState * pending, GTimeVal * timeout);
|
GstElementState * pending, GTimeVal * timeout);
|
||||||
GstElementStateReturn (*change_state) (GstElement * element);
|
GstElementStateReturn (*change_state) (GstElement * element);
|
||||||
|
|
||||||
/* manager */
|
/* manager */
|
||||||
void (*set_manager) (GstElement * element, GstPipeline * pipeline);
|
void (*set_manager) (GstElement * element, GstPipeline * pipeline);
|
||||||
|
@ -353,18 +356,20 @@ void gst_element_message_full (GstElement * element, GstMessageType type,
|
||||||
const gchar * function, gint line);
|
const gchar * function, gint line);
|
||||||
|
|
||||||
/* state management */
|
/* state management */
|
||||||
gboolean gst_element_is_locked_state (GstElement * element);
|
gboolean gst_element_is_locked_state (GstElement * element);
|
||||||
gboolean gst_element_set_locked_state (GstElement * element,
|
gboolean gst_element_set_locked_state (GstElement * element,
|
||||||
gboolean locked_state);
|
gboolean locked_state);
|
||||||
gboolean gst_element_sync_state_with_parent (GstElement * element);
|
gboolean gst_element_sync_state_with_parent (GstElement * element);
|
||||||
|
|
||||||
gboolean gst_element_get_state (GstElement * element, GstElementState * state,
|
GstElementStateReturn gst_element_get_state (GstElement * element,
|
||||||
GstElementState * pending, GTimeVal * timeout);
|
GstElementState * state,
|
||||||
GstElementStateReturn gst_element_set_state (GstElement * element,
|
GstElementState * pending,
|
||||||
GstElementState state);
|
GTimeVal * timeout);
|
||||||
|
GstElementStateReturn gst_element_set_state (GstElement * element,
|
||||||
|
GstElementState state);
|
||||||
|
|
||||||
void gst_element_abort_state (GstElement * element);
|
void gst_element_abort_state (GstElement * element);
|
||||||
void gst_element_commit_state (GstElement * element);
|
void gst_element_commit_state (GstElement * element);
|
||||||
|
|
||||||
/* factory management */
|
/* factory management */
|
||||||
GstElementFactory *gst_element_get_factory (GstElement * element);
|
GstElementFactory *gst_element_get_factory (GstElement * element);
|
||||||
|
|
Loading…
Reference in a new issue