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:
Wim Taymans 2005-01-12 18:54:42 +00:00
parent faeeed3dba
commit 83156b4a9d
4 changed files with 104 additions and 66 deletions

View file

@ -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>
* configure.ac:

View file

@ -53,7 +53,7 @@ GType _gst_bin_type = 0;
static void gst_bin_dispose (GObject * object);
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);
#ifndef GST_DISABLE_INDEX
@ -645,12 +645,12 @@ gst_bin_iterate_sinks (GstBin * bin)
*
* MT safe
*/
static gboolean
static GstElementStateReturn
gst_bin_get_state (GstElement * element, GstElementState * state,
GstElementState * pending, GTimeVal * timeout)
{
GstBin *bin = GST_BIN (element);
gboolean ret;
GstElementStateReturn ret;
GList *children;
guint32 children_cookie;
@ -661,7 +661,7 @@ gst_bin_get_state (GstElement * element, GstElementState * state,
* is still busy with its state change. */
GST_LOCK (bin);
restart:
ret = TRUE;
ret = GST_STATE_SUCCESS;
children = bin->children;
children_cookie = bin->children_cookie;
while (children) {
@ -670,13 +670,14 @@ restart:
gst_object_ref (GST_OBJECT_CAST (child));
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);
gst_object_unref (GST_OBJECT_CAST (child));
if (!ret) {
/* some child is still busy, return FALSE */
if (ret != GST_STATE_SUCCESS) {
/* some child is still busy or in error, we can report that
* right away. */
goto done;
}
/* now grab the lock to iterate to the next child */
@ -692,9 +693,18 @@ restart:
done:
/* now we can take the state lock */
GST_STATE_LOCK (bin);
if (ret) {
/* no async children, we can commit the state */
gst_element_commit_state (element);
switch (ret) {
case GST_STATE_SUCCESS:
/* 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 */

View file

@ -66,7 +66,7 @@ static void gst_element_base_class_finalize (gpointer g_class);
static void gst_element_dispose (GObject * object);
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);
static void gst_element_set_manager_func (GstElement * element,
GstPipeline * manager);
@ -1559,11 +1559,11 @@ gst_element_sync_state_with_parent (GstElement * element)
}
/* MT safe */
static gboolean
static GstElementStateReturn
gst_element_get_state_func (GstElement * element,
GstElementState * state, GstElementState * pending, GTimeVal * timeout)
{
gboolean ret = FALSE;
GstElementStateReturn ret = GST_STATE_FAILURE;
GstElementState old_pending;
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);
if (pending)
*pending = GST_STATE_PENDING (element);
ret = FALSE;
ret = GST_STATE_ASYNC;
} else {
/* could be success or failure, we could check here if the
* state is equal to the old pending state */
/* could be success or failure */
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
@ -1591,7 +1595,7 @@ gst_element_get_state_func (GstElement * element,
*state = GST_STATE (element);
if (pending)
*pending = GST_STATE_VOID_PENDING;
ret = TRUE;
ret = GST_STATE_SUCCESS;
}
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.
* Can be NULL.
* @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
* if the element is still performing a state change.
* For elements that performed an ASYNC state change, as reported by
* #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.
*/
gboolean
GstElementStateReturn
gst_element_get_state (GstElement * element,
GstElementState * state, GstElementState * pending, GTimeVal * timeout)
{
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);
@ -1652,14 +1665,14 @@ gst_element_abort_state (GstElement * 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);
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
"aborting state from %s to %s", gst_element_state_get_name (old_state),
gst_element_state_get_name (pending));
GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
GST_STATE_ERROR (element) = TRUE;
GST_STATE_BROADCAST (element);
}
@ -1726,6 +1739,9 @@ gst_element_set_state (GstElement * element, GstElementState state)
/* get the element state lock */
GST_STATE_LOCK (element);
/* clear the error flag */
GST_STATE_ERROR (element) = FALSE;
/* start with the current state */
current = GST_STATE (element);
@ -1749,17 +1765,11 @@ gst_element_set_state (GstElement * element, GstElementState state)
/* set the pending state variable */
GST_STATE_PENDING (element) = pending;
if (pending != state) {
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
"intermediate: setting state from %s to %s",
gst_element_state_get_name (current),
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));
}
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
"%s: setting state from %s to %s",
(pending != state ? "intermediate" : "final"),
gst_element_state_get_name (current),
gst_element_state_get_name (pending));
/* call the state change function so it can set the state */
if (oclass->change_state)

View file

@ -66,6 +66,7 @@ struct _GstElementDetails
*/
#define GST_STATE(obj) (GST_ELEMENT(obj)->current_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> */
#define GST_STATE_TRANSITION(obj) ((GST_STATE(obj)<<8) | GST_STATE_PENDING(obj))
@ -173,32 +174,34 @@ struct _GstElement
/*< public > *//* with STATE_LOCK */
/* element state */
GMutex *state_lock;
GCond *state_cond;
guint8 current_state;
guint8 pending_state;
GMutex *state_lock;
GCond *state_cond;
guint8 current_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 */
/* element manager */
GstPipeline *manager;
GstBus *bus;
GstPipeline *manager;
GstBus *bus;
GstScheduler *scheduler;
/* private pointer for the scheduler */
gpointer sched_private;
gpointer sched_private;
/* allocated clock */
GstClock *clock;
GstClockTimeDiff base_time; /* NULL/READY: 0 - PAUSED: current time - PLAYING: difference to clock */
GstClock *clock;
GstClockTimeDiff base_time; /* NULL/READY: 0 - PAUSED: current time - PLAYING: difference to clock */
/* element pads, these lists can only be iterated while holding
* the LOCK or checking the cookie after each LOCK. */
guint16 numpads;
GList *pads;
guint16 numsrcpads;
GList *srcpads;
guint16 numsinkpads;
GList *sinkpads;
guint32 pads_cookie;
guint16 numpads;
GList *pads;
guint16 numsrcpads;
GList *srcpads;
guint16 numsinkpads;
GList *sinkpads;
guint32 pads_cookie;
/*< private > */
gpointer _gst_reserved[GST_PADDING];
@ -236,9 +239,9 @@ struct _GstElementClass
void (*release_pad) (GstElement * element, GstPad * pad);
/* state changes */
gboolean (*get_state) (GstElement * element, GstElementState * state,
GstElementState * pending, GTimeVal * timeout);
GstElementStateReturn (*change_state) (GstElement * element);
GstElementStateReturn (*get_state) (GstElement * element, GstElementState * state,
GstElementState * pending, GTimeVal * timeout);
GstElementStateReturn (*change_state) (GstElement * element);
/* manager */
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);
/* state management */
gboolean gst_element_is_locked_state (GstElement * element);
gboolean gst_element_set_locked_state (GstElement * element,
gboolean locked_state);
gboolean gst_element_sync_state_with_parent (GstElement * element);
gboolean gst_element_is_locked_state (GstElement * element);
gboolean gst_element_set_locked_state (GstElement * element,
gboolean locked_state);
gboolean gst_element_sync_state_with_parent (GstElement * element);
gboolean gst_element_get_state (GstElement * element, GstElementState * state,
GstElementState * pending, GTimeVal * timeout);
GstElementStateReturn gst_element_set_state (GstElement * element,
GstElementState state);
GstElementStateReturn gst_element_get_state (GstElement * element,
GstElementState * state,
GstElementState * pending,
GTimeVal * timeout);
GstElementStateReturn gst_element_set_state (GstElement * element,
GstElementState state);
void gst_element_abort_state (GstElement * element);
void gst_element_commit_state (GstElement * element);
void gst_element_abort_state (GstElement * element);
void gst_element_commit_state (GstElement * element);
/* factory management */
GstElementFactory *gst_element_get_factory (GstElement * element);