Commit 2153c459 authored by Wim Taymans's avatar Wim Taymans

check/: Check fixes, use API as stated in design docs, remove hacks.

Original commit message from CVS:
* check/Makefile.am:
* check/generic/states.c: (GST_START_TEST):
* check/gst/gstbin.c: (GST_START_TEST):
* check/gst/gstpipeline.c: (GST_START_TEST), (gst_pipeline_suite):
* check/states/sinks.c: (GST_START_TEST):
* check/states/sinks2.c: (GST_START_TEST), (gst_object_suite),
(main):
Check fixes, use API as stated in design docs, remove hacks.

* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
(gst_base_sink_change_state):
Catch stopping our task while we're shutting down.

* gst/gstbin.c: (gst_bin_init), (gst_bin_add_func),
(gst_bin_remove_func), (gst_bin_get_state_func),
(gst_bin_recalc_state), (gst_bin_change_state_func),
(bin_bus_handler):
* gst/gstbin.h:
* gst/gstelement.c: (gst_element_init),
(gst_element_get_state_func), (gst_element_abort_state),
(gst_element_commit_state), (gst_element_lost_state),
(gst_element_set_state), (gst_element_change_state),
(gst_element_change_state_func):
* gst/gstelement.h:
New state change algorithm (see #318116)

* gst/gstpipeline.c: (gst_pipeline_class_init),
(gst_pipeline_init), (gst_pipeline_set_property),
(gst_pipeline_get_property), (do_pipeline_seek),
(gst_pipeline_change_state), (gst_pipeline_provide_clock_func):
* gst/gstpipeline.h:
Remove crude state change hacks.

* gst/gstutils.h:
Remove crude hacks.

* tools/gst-launch.c: (main):
Fixes for state change. Needs some more work to fully use the
new stuff.
parent b77f6b0e
2005-10-10 Wim Taymans <wim@fluendo.com>
* check/Makefile.am:
* check/generic/states.c: (GST_START_TEST):
* check/gst/gstbin.c: (GST_START_TEST):
* check/gst/gstpipeline.c: (GST_START_TEST), (gst_pipeline_suite):
* check/states/sinks.c: (GST_START_TEST):
* check/states/sinks2.c: (GST_START_TEST), (gst_object_suite),
(main):
Check fixes, use API as stated in design docs, remove hacks.
* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
(gst_base_sink_change_state):
Catch stopping our task while we're shutting down.
* gst/gstbin.c: (gst_bin_init), (gst_bin_add_func),
(gst_bin_remove_func), (gst_bin_get_state_func),
(gst_bin_recalc_state), (gst_bin_change_state_func),
(bin_bus_handler):
* gst/gstbin.h:
* gst/gstelement.c: (gst_element_init),
(gst_element_get_state_func), (gst_element_abort_state),
(gst_element_commit_state), (gst_element_lost_state),
(gst_element_set_state), (gst_element_change_state),
(gst_element_change_state_func):
* gst/gstelement.h:
New state change algorithm (see #318116)
* gst/gstpipeline.c: (gst_pipeline_class_init),
(gst_pipeline_init), (gst_pipeline_set_property),
(gst_pipeline_get_property), (do_pipeline_seek),
(gst_pipeline_change_state), (gst_pipeline_provide_clock_func):
* gst/gstpipeline.h:
Remove crude state change hacks.
* gst/gstutils.h:
Remove crude hacks.
* tools/gst-launch.c: (main):
Fixes for state change. Needs some more work to fully use the
new stuff.
2005-10-10 Andy Wingo <wingo@pobox.com>
* tests/Makefile.am (noinst_PROGRAMS): No more init.c.
......
......@@ -54,6 +54,7 @@ check_PROGRAMS = \
pipelines/simple_launch_lines \
pipelines/cleanup \
states/sinks \
states/sinks2 \
gst-libs/controller \
gst-libs/gdp
......
......@@ -42,8 +42,7 @@ GST_START_TEST (test_state_changes)
gst_element_set_state (element, GST_STATE_READY);
gst_element_set_state (element, GST_STATE_PAUSED);
gst_element_set_state (element, GST_STATE_PLAYING);
/* Sleep to give any pad tasks time to start */
g_usleep (0.2 * G_USEC_PER_SEC);
gst_element_set_state (element, GST_STATE_PAUSED);
gst_element_set_state (element, GST_STATE_READY);
gst_element_set_state (element, GST_STATE_NULL);
......@@ -52,6 +51,7 @@ GST_START_TEST (test_state_changes)
gst_element_set_state (element, GST_STATE_PLAYING);
gst_element_set_state (element, GST_STATE_PAUSED);
gst_element_set_state (element, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (element));
}
gst_task_cleanup_all ();
......
......@@ -262,7 +262,7 @@ GST_START_TEST (test_message_state_changed_children)
/* change state to PAUSED, spawning three messages */
GST_DEBUG ("setting pipeline to PAUSED");
ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
fail_unless (ret == GST_STATE_CHANGE_ASYNC);
ret =
gst_element_get_state (GST_ELEMENT (pipeline), &current, &pending, NULL);
fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
......@@ -364,19 +364,13 @@ GST_START_TEST (test_watch_for_state_change)
fail_unless (gst_element_link (src, sink), "could not link src and sink");
/* change state, spawning two times three messages, minus one async */
/* change state, spawning two times three messages */
ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
fail_unless (ret == GST_STATE_CHANGE_ASYNC);
ret = gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, NULL);
fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
pop_messages (bus, 5);
fail_unless (gst_bus_have_pending (bus) == FALSE,
"Unexpected messages on bus");
gst_bin_watch_for_state_change (GST_BIN (bin));
/* should get the bin's state change message now */
pop_messages (bus, 1);
pop_messages (bus, 6);
fail_unless (gst_bus_have_pending (bus) == FALSE,
"Unexpected messages on bus");
......@@ -388,8 +382,7 @@ GST_START_TEST (test_watch_for_state_change)
/* this one might return either SUCCESS or ASYNC, likely SUCCESS */
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
gst_bin_watch_for_state_change (GST_BIN (bin));
gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, NULL);
pop_messages (bus, 3);
......@@ -482,6 +475,7 @@ GST_START_TEST (test_children_state_change_order_flagged_sink)
{
GstElement *src, *identity, *sink, *pipeline;
GstStateChangeReturn ret;
GstState current, pending;
GstBus *bus;
pipeline = gst_pipeline_new (NULL);
......@@ -506,7 +500,12 @@ GST_START_TEST (test_children_state_change_order_flagged_sink)
/* (1) Test state change with fakesink being a regular sink */
ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
fail_if (ret != GST_STATE_CHANGE_ASYNC,
"State change to PLAYING did not return ASYNC");
ret = gst_element_get_state (pipeline, &current, &pending, NULL);
fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
fail_if (current != GST_STATE_PLAYING, "State change to PLAYING failed");
fail_if (pending != GST_STATE_VOID_PENDING, "State change to PLAYING failed");
/* NULL => READY */
ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 101);
......@@ -602,7 +601,7 @@ GST_START_TEST (test_children_state_change_order_semi_sink)
GST_FLAG_UNSET (sink, GST_ELEMENT_IS_SINK); /* <======== */
ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
fail_if (ret != GST_STATE_CHANGE_ASYNC, "State change to PLAYING not ASYNC");
ret = gst_element_get_state (pipeline, &current, &pending, NULL);
fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
fail_if (current != GST_STATE_PLAYING, "State change to PLAYING failed");
......
......@@ -28,7 +28,6 @@ GST_START_TEST (test_async_state_change_empty)
pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
fail_unless (pipeline != NULL, "Could not create pipeline");
g_object_set (G_OBJECT (pipeline), "play-timeout", 0LL, NULL);
fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
GST_STATE_PLAYING), GST_STATE_CHANGE_SUCCESS);
......@@ -45,7 +44,6 @@ GST_START_TEST (test_async_state_change_fake_ready)
pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
fail_unless (pipeline != NULL, "Could not create pipeline");
g_object_set (G_OBJECT (pipeline), "play-timeout", 0LL, NULL);
src = gst_element_factory_make ("fakesrc", NULL);
sink = gst_element_factory_make ("fakesink", NULL);
......@@ -71,7 +69,6 @@ GST_START_TEST (test_async_state_change_fake)
pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
fail_unless (pipeline != NULL, "Could not create pipeline");
g_object_set (G_OBJECT (pipeline), "play-timeout", 0LL, NULL);
src = gst_element_factory_make ("fakesrc", NULL);
sink = gst_element_factory_make ("fakesink", NULL);
......@@ -81,7 +78,7 @@ GST_START_TEST (test_async_state_change_fake)
bus = gst_pipeline_get_bus (pipeline);
fail_unless_equals_int (gst_element_set_state_async (GST_ELEMENT (pipeline),
fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
GST_STATE_PLAYING), GST_STATE_CHANGE_ASYNC);
while (!done) {
......@@ -98,7 +95,6 @@ GST_START_TEST (test_async_state_change_fake)
}
}
g_object_set (G_OBJECT (pipeline), "play-timeout", 3 * GST_SECOND, NULL);
fail_unless_equals_int (gst_element_set_state (GST_ELEMENT (pipeline),
GST_STATE_NULL), GST_STATE_CHANGE_SUCCESS);
......@@ -175,7 +171,6 @@ GST_START_TEST (test_bus)
pipeline = gst_pipeline_new (NULL);
fail_unless (pipeline != NULL, "Could not create pipeline");
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
g_object_set (pipeline, "play-timeout", 0LL, NULL);
src = gst_element_factory_make ("fakesrc", NULL);
fail_unless (src != NULL);
......@@ -193,7 +188,7 @@ GST_START_TEST (test_bus)
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline after add_watch", 1);
ASSERT_OBJECT_REFCOUNT (bus, "bus after add_watch", 3);
gst_element_set_state_async (pipeline, GST_STATE_PLAYING);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
loop = g_main_loop_new (NULL, FALSE);
GST_DEBUG ("going into main loop");
g_main_loop_run (loop);
......@@ -207,9 +202,6 @@ GST_START_TEST (test_bus)
/* cleanup */
GST_DEBUG ("cleanup");
/* current semantics require us to go step by step; this will change */
gst_element_set_state (pipeline, GST_STATE_PAUSED);
gst_element_set_state (pipeline, GST_STATE_READY);
gst_element_set_state (pipeline, GST_STATE_NULL);
fail_unless (gst_element_get_state (pipeline, &current, NULL, NULL) ==
GST_STATE_CHANGE_SUCCESS);
......@@ -238,6 +230,8 @@ gst_pipeline_suite (void)
Suite *s = suite_create ("GstPipeline");
TCase *tc_chain = tcase_create ("pipeline tests");
tcase_set_timeout (tc_chain, 0);
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_async_state_change_empty);
tcase_add_test (tc_chain, test_async_state_change_fake_ready);
......
......@@ -42,7 +42,7 @@ GST_START_TEST (test_sink)
ret = gst_element_get_state (sink, &current, &pending, &tv);
fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not changing state async");
fail_unless (current == GST_STATE_PAUSED, "bad current state");
fail_unless (current == GST_STATE_READY, "bad current state");
fail_unless (pending == GST_STATE_PLAYING, "bad pending state");
ret = gst_element_set_state (sink, GST_STATE_PAUSED);
......@@ -81,6 +81,7 @@ GST_START_TEST (test_src_sink)
gst_object_unref (sinkpad);
ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
ret = gst_element_get_state (pipeline, NULL, NULL, NULL);
fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
......@@ -139,8 +140,7 @@ GST_START_TEST (test_livesrc_remove)
ret = gst_element_get_state (pipeline, &current, &pending, &tv);
fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not async");
fail_unless (current == GST_STATE_PAUSED, "not paused");
fail_unless (pending == GST_STATE_VOID_PENDING, "not playing");
fail_unless (pending == GST_STATE_PAUSED, "not paused");
}
GST_END_TEST
......
/* GStreamer
*
* unit test for sinks
*
* Copyright (C) <2005> Wim Taymans <wim at fluendo dot com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <gst/check/gstcheck.h>
/* a sink should go ASYNC to PAUSE and PLAYING. */
GST_START_TEST (test_sink)
{
GstElement *sink, *src;
GstStateChangeReturn ret;
GstState current, pending;
GTimeVal tv;
sink = gst_element_factory_make ("fakesink", "sink");
ret = gst_element_set_state (sink, GST_STATE_PLAYING);
fail_unless (ret == GST_STATE_CHANGE_ASYNC, "no async state return");
GST_TIME_TO_TIMEVAL ((GstClockTime) 0, tv);
ret = gst_element_get_state (sink, &current, &pending, &tv);
fail_unless (ret == GST_STATE_CHANGE_ASYNC, "not changing state async");
fail_unless (current == GST_STATE_READY, "bad current state");
fail_unless (pending == GST_STATE_PLAYING, "bad pending state");
src = gst_element_factory_make ("fakesrc", "src");
gst_element_link (src, sink);
ret = gst_element_set_state (src, GST_STATE_PLAYING);
fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "no success state return");
/* now wait for final state */
ret = gst_element_get_state (sink, &current, &pending, NULL);
fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to change state");
fail_unless (current == GST_STATE_PLAYING, "bad current state");
fail_unless (pending == GST_STATE_VOID_PENDING, "bad pending state");
ret = gst_element_set_state (sink, GST_STATE_NULL);
fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null");
ret = gst_element_set_state (src, GST_STATE_NULL);
fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "failed to go to null");
gst_object_unref (sink);
gst_object_unref (src);
}
GST_END_TEST
/* test: try changing state of sinks */
Suite * gst_object_suite (void)
{
Suite *s = suite_create ("Sinks");
TCase *tc_chain = tcase_create ("general");
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_sink);
return s;
}
int
main (int argc, char **argv)
{
int nf;
Suite *s = gst_object_suite ();
SRunner *sr = srunner_create (s);
gst_check_init (&argc, &argv);
srunner_run_all (sr, CK_NORMAL);
nf = srunner_ntests_failed (sr);
srunner_free (sr);
return nf;
}
......@@ -622,6 +622,7 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
if (length == 1) {
gint t;
GstTask *task;
basesink->have_preroll = TRUE;
/* we are prerolling */
......@@ -636,8 +637,21 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
g_warning ("STREAM_LOCK should have been locked !!");
}
/* now we commit our state */
GST_STATE_LOCK (basesink);
/* now we commit our state, this will also automatically proceed to
* the next pending state. */
/* FIXME */
if ((task = GST_PAD_TASK (pad))) {
while (!GST_STATE_TRYLOCK (basesink)) {
GST_DEBUG_OBJECT (basesink,
"state change happening, checking shutdown");
GST_LOCK (pad);
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
goto task_stopped;
GST_UNLOCK (pad);
}
} else {
GST_STATE_LOCK (basesink);
}
GST_DEBUG_OBJECT (basesink, "commit state");
gst_element_commit_state (GST_ELEMENT (basesink));
GST_STATE_UNLOCK (basesink);
......@@ -742,6 +756,12 @@ playing_async:
return ret;
}
task_stopped:
{
GST_UNLOCK (pad);
GST_DEBUG_OBJECT (basesink, "task is stopped");
return GST_FLOW_WRONG_STATE;
}
flushing:
{
GST_UNLOCK (pad);
......@@ -1514,7 +1534,8 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
* we need to wait for a preroll */
GST_DEBUG_OBJECT (basesink, "have_preroll: %d, EOS: %d",
basesink->have_preroll, basesink->eos);
if (!basesink->have_preroll && !basesink->eos) {
if (!basesink->have_preroll && !basesink->eos
&& GST_STATE_PENDING (basesink) == GST_STATE_PAUSED) {
GST_DEBUG_OBJECT (basesink, "PLAYING to PAUSED, need preroll to TRUE");
basesink->need_preroll = TRUE;
ret = GST_STATE_CHANGE_ASYNC;
......
This diff is collapsed.
......@@ -92,6 +92,8 @@ struct _GstBin {
GstBus *child_bus; /* Bus we set on our children */
GList *eosed; /* list of elements that posted EOS */
gboolean polling;
gboolean state_dirty;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
......
This diff is collapsed.
......@@ -93,6 +93,14 @@ typedef enum {
*/
#define GST_STATE(obj) (GST_ELEMENT(obj)->current_state)
/**
* GST_STATE_NEXT:
* @obj: Element to return the next state for.
*
* This macro returns the next state of the element.
*/
#define GST_STATE_NEXT(obj) (GST_ELEMENT(obj)->next_state)
/**
* GST_STATE_PENDING:
* @obj: Element to return the pending state for.
......@@ -100,28 +108,21 @@ typedef enum {
* This macro returns the currently pending state of the element.
*/
#define GST_STATE_PENDING(obj) (GST_ELEMENT(obj)->pending_state)
#define GST_STATE_FINAL(obj) (GST_ELEMENT(obj)->final_state)
#define GST_STATE_ERROR(obj) (GST_ELEMENT(obj)->state_error)
#define GST_STATE_NO_PREROLL(obj) (GST_ELEMENT(obj)->no_preroll)
#ifndef GST_DEBUG_STATE_CHANGE
#define GST_STATE_CHANGE(obj) ((1<<(GST_STATE(obj)+8)) | 1<<GST_STATE_PENDING(obj))
#else
inline GstStateChange
_gst_element_get_state_change (GstElement *e)
{
if (e->state < GST_STATE_NULL || e->state > GST_STATE_PLAYING)
g_assert_not_reached ();
if (e->pending_state < GST_STATE_NULL || e->pending_state > GST_STATE_PLAYING)
g_assert_not_reached ();
if (e->state - e->pending_state != 1 && e->pending_state - e->state != 1)
g_assert_not_reached ();
return (1<<(GST_STATE(obj)+8)) | 1<<GST_STATE_PENDING(obj);
}
#define GST_STATE_CHANGE(obj) _gst_element_get_state_change(obj)
#endif
/* FIXME: How to deal with lost_state ? */
/**
* GST_STATE_RETURN:
* @obj: Element to return the last state result for.
*
* This macro returns the last state change return value.
*/
#define GST_STATE_RETURN(obj) (GST_ELEMENT(obj)->last_return)
#define GST_SIGN(val) ((val) < 0 ? -1 : ((val) > 0 ? 1 : 0))
#define GST_STATE_GET_NEXT(cur,pending) ((cur)+GST_SIGN ((gint)(pending)-(gint)(cur)))
#define GST_STATE_TRANSITION(cur,next) (((cur)<<3)|(next))
#define GST_STATE_TRANSITION_CURRENT(trans) ((trans)>>3)
#define GST_STATE_TRANSITION_NEXT(trans) ((trans)&0x7)
/**
* GstStateChange:
* @GST_STATE_CHANGE_NULL_TO_READY : state change from NULL to READY
......@@ -133,12 +134,12 @@ _gst_element_get_state_change (GstElement *e)
*/
typedef enum /*< flags=0 >*/
{
GST_STATE_CHANGE_NULL_TO_READY = 1<<(GST_STATE_NULL+8) | 1<<GST_STATE_READY,
GST_STATE_CHANGE_READY_TO_PAUSED = 1<<(GST_STATE_READY+8) | 1<<GST_STATE_PAUSED,
GST_STATE_CHANGE_PAUSED_TO_PLAYING = 1<<(GST_STATE_PAUSED+8) | 1<<GST_STATE_PLAYING,
GST_STATE_CHANGE_PLAYING_TO_PAUSED = 1<<(GST_STATE_PLAYING+8) | 1<<GST_STATE_PAUSED,
GST_STATE_CHANGE_PAUSED_TO_READY = 1<<(GST_STATE_PAUSED+8) | 1<<GST_STATE_READY,
GST_STATE_CHANGE_READY_TO_NULL = 1<<(GST_STATE_READY+8) | 1<<GST_STATE_NULL
GST_STATE_CHANGE_NULL_TO_READY = (GST_STATE_NULL<<3) | GST_STATE_READY,
GST_STATE_CHANGE_READY_TO_PAUSED = (GST_STATE_READY<<3) | GST_STATE_PAUSED,
GST_STATE_CHANGE_PAUSED_TO_PLAYING = (GST_STATE_PAUSED<<3) | GST_STATE_PLAYING,
GST_STATE_CHANGE_PLAYING_TO_PAUSED = (GST_STATE_PLAYING<<3) | GST_STATE_PAUSED,
GST_STATE_CHANGE_PAUSED_TO_READY = (GST_STATE_PAUSED<<3) | GST_STATE_READY,
GST_STATE_CHANGE_READY_TO_NULL = (GST_STATE_READY<<3) | GST_STATE_NULL
} GstStateChange;
/**
......@@ -156,6 +157,7 @@ typedef enum
GST_ELEMENT_LOCKED_STATE = GST_OBJECT_FLAG_LAST,
GST_ELEMENT_IS_SINK,
GST_ELEMENT_UNPARENTING,
GST_ELEMENT_CHANGING_STATE,
GST_ELEMENT_FLAG_LAST = GST_OBJECT_FLAG_LAST + 16
} GstElementFlags;
......@@ -295,15 +297,11 @@ struct _GstElement
/* element state */
GStaticRecMutex *state_lock;
GCond *state_cond;
guint8 current_state;
guint8 pending_state;
guint8 final_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. */
gboolean no_preroll; /* Flag is set when the element cannot
* preroll */
GstState current_state;
GstState next_state;
GstState pending_state;
GstStateChangeReturn last_return;
/*< public >*/ /* with LOCK */
GstBus *bus;
......@@ -491,7 +489,7 @@ GstStateChangeReturn gst_element_get_state (GstElement * element,
GstStateChangeReturn gst_element_set_state (GstElement *element, GstState state);
void gst_element_abort_state (GstElement * element);
void gst_element_commit_state (GstElement * element);
GstStateChangeReturn gst_element_commit_state (GstElement * element);
void gst_element_lost_state (GstElement * element);
/* factory management */
......
......@@ -60,12 +60,11 @@ enum
};
#define DEFAULT_DELAY 0
#define DEFAULT_PLAY_TIMEOUT (2*GST_SECOND)
enum
{
PROP_0,
PROP_DELAY,
PROP_PLAY_TIMEOUT,
/* FILL ME */
};
......@@ -141,10 +140,6 @@ gst_pipeline_class_init (gpointer g_class, gpointer class_data)
"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), PROP_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);
......@@ -162,7 +157,6 @@ gst_pipeline_init (GTypeInstance * instance, gpointer g_class)
GstBus *bus;
pipeline->delay = DEFAULT_DELAY;
pipeline->play_timeout = DEFAULT_PLAY_TIMEOUT;
bus = g_object_new (gst_bus_get_type (), NULL);
gst_element_set_bus (GST_ELEMENT_CAST (pipeline), bus);
......@@ -192,9 +186,6 @@ gst_pipeline_set_property (GObject * object, guint prop_id,
case PROP_DELAY:
pipeline->delay = g_value_get_uint64 (value);
break;
case PROP_PLAY_TIMEOUT:
pipeline->play_timeout = g_value_get_uint64 (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
......@@ -213,9 +204,6 @@ gst_pipeline_get_property (GObject * object, guint prop_id,
case PROP_DELAY:
g_value_set_uint64 (value, pipeline->delay);
break;
case PROP_PLAY_TIMEOUT:
g_value_set_uint64 (value, pipeline->play_timeout);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
......@@ -246,8 +234,9 @@ do_pipeline_seek (GstElement * element, GstEvent * event)
gst_element_get_state (element, &state, NULL, &timeout);
was_playing = state == GST_STATE_PLAYING;
if (was_playing)
if (was_playing) {
gst_element_set_state (element, GST_STATE_PAUSED);
}
}
res = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
......@@ -255,10 +244,9 @@ do_pipeline_seek (GstElement * element, GstEvent * event)
if (flush && res) {
/* need to reset the stream time to 0 after a flushing seek */
gst_pipeline_set_new_stream_time (GST_PIPELINE (element), 0);
if (was_playing) {
if (was_playing)
/* and continue playing */
gst_element_set_state (element, GST_STATE_PLAYING);
}
}
return res;
}
......@@ -306,7 +294,6 @@ gst_pipeline_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
GstPipeline *pipeline = GST_PIPELINE (element);
GstClockTime play_timeout;
GstClock *clock;
switch (transition) {
......@@ -400,40 +387,6 @@ gst_pipeline_change_state (GstElement * element, GstStateChange transition)
GST_UNLOCK (element);
break;
}
if (result == GST_STATE_CHANGE_ASYNC) {
GST_LOCK (pipeline);
play_timeout = pipeline->play_timeout;
GST_UNLOCK (pipeline);
} else {
play_timeout = 0;
}
/* we wait for async state changes ourselves when we are in an
* intermediate state. */
if (play_timeout > 0) {
GTimeVal *timeval, timeout;
GST_STATE_UNLOCK (pipeline);
if (play_timeout == G_MAXUINT64) {
timeval = NULL;
} else {
GST_TIME_TO_TIMEVAL (play_timeout, timeout);
timeval = &timeout;
}
result = gst_element_get_state (element, NULL, NULL, timeval);
if (result == GST_STATE_CHANGE_ASYNC) {
GST_WARNING_OBJECT (pipeline,
"timeout in PREROLL, forcing next state change");
g_warning ("timeout in PREROLL, forcing next state change");
result = GST_STATE_CHANGE_SUCCESS;
}
GST_STATE_LOCK (pipeline);
}
return result;
}
......
......@@ -59,7 +59,6 @@ struct _GstPipeline {
GstClock *fixed_clock; /* fixed clock if any */
GstClockTime stream_time;
GstClockTime delay;
GstClockTime play_timeout;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
......
......@@ -497,8 +497,6 @@ void gst_element_unlink_pads (GstElement *src, const
gboolean gst_element_link_pads_filtered (GstElement * src, const gchar * srcpadname,
GstElement * dest, const gchar * destpadname,
GstCaps *filter);
GstStateChangeReturn gst_element_set_state_async (GstElement * element, GstState state);
/* util elementfactory functions */
gboolean gst_element_factory_can_src_caps(GstElementFactory *factory, const GstCaps *caps);
gboolean gst_element_factory_can_sink_caps(GstElementFactory *factory, const GstCaps *caps);
......@@ -536,7 +534,6 @@ gboolean gst_pad_query_convert (GstPad *pad, GstFormat
/* bin functions */
void gst_bin_add_many (GstBin *bin, GstElement *element_1, ...);
void gst_bin_remove_many (GstBin *bin, GstElement *element_1, ...);
void gst_bin_watch_for_state_change (GstBin *bin);
/* buffer functions */
GstBuffer * gst_buffer_merge (GstBuffer * buf1, GstBuffer * buf2);
......
......@@ -622,6 +622,7 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
if (length == 1) {
gint t;
GstTask *task;
basesink->have_preroll = TRUE;
/* we are prerolling */
......@@ -636,8 +637,21 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
g_warning ("STREAM_LOCK should have been locked !!");
}
/* now we commit our state */
GST_STATE_LOCK (basesink);
/* now we commit our state, this will also automatically proceed to
* the next pending state. */
/* FIXME */
if ((task = GST_PAD_TASK (pad))) {
while (!GST_STATE_TRYLOCK (basesink)) {
GST_DEBUG_OBJECT (basesink,
"state change happening, checking shutdown");
GST_LOCK (pad);
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
goto task_stopped;
GST_UNLOCK (pad);
}
} else {
GST_STATE_LOCK (basesink);