GstThread *thread;
GstElementStateReturn ret;
gint transition;
- gboolean is_self;
+ gboolean is_self, reverting = FALSE;
g_return_val_if_fail (GST_IS_THREAD (element), GST_STATE_FAILURE);
/* boolean to check if we called the state change in the same thread as
* the iterate thread */
is_self = (thread == gst_thread_get_current ());
+ transition = GST_STATE_TRANSITION (element);
+revert:
GST_LOG_OBJECT (thread, "grabbing lock");
g_mutex_lock (thread->lock);
/* do not try to grab the lock if this method is called from the
* same thread as the iterate thread, the lock might be held and we
* might deadlock */
- if (!is_self)
+ if (!is_self && !reverting)
g_mutex_lock (thread->iterate_lock);
- transition = GST_STATE_TRANSITION (element);
-
switch (transition) {
- case GST_STATE_NULL_TO_READY:
+ case GST_STATE_NULL_TO_READY:{
+ GError *err = NULL;
+
/* create the thread */
GST_FLAG_UNSET (thread, GST_THREAD_STATE_REAPING);
GST_LOG_OBJECT (element, "grabbing lock");
thread->thread_id = g_thread_create_full (gst_thread_main_loop,
- thread, STACK_SIZE, FALSE, TRUE, thread->priority, NULL);
+ thread, STACK_SIZE, FALSE, TRUE, thread->priority, &err);
if (!thread->thread_id) {
- GST_ERROR_OBJECT (element, "g_thread_create_full failed");
+ GST_ERROR_OBJECT (element, "g_thread_create_full failed: %s",
+ err->message);
+ g_error_free (err);
goto error_out;
}
GST_LOG_OBJECT (element, "GThread created");
/* wait for it to 'spin up' */
g_cond_wait (thread->cond, thread->lock);
break;
+ }
case GST_STATE_READY_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_PLAYING:
GST_LOG_OBJECT (thread, "unlocking lock");
g_mutex_unlock (thread->lock);
- if (GST_ELEMENT_CLASS (parent_class)->change_state) {
+ if (reverting) {
+ goto error_out_unlocked;
+ } else if (GST_ELEMENT_CLASS (parent_class)->change_state) {
ret = GST_ELEMENT_CLASS (parent_class)->change_state (GST_ELEMENT (thread));
+ if (ret == GST_STATE_FAILURE) {
+ reverting = TRUE;
+ transition = ((transition & 0xff) << 8) | (transition >> 8);
+ goto revert;
+ }
} else {
ret = GST_STATE_SUCCESS;
}
g_mutex_unlock (thread->lock);
+error_out_unlocked:
if (!is_self)
g_mutex_unlock (thread->iterate_lock);