gst/base/gstbasetransform.c: Debug changes.

Original commit message from CVS:
2005-08-17  Andy Wingo  <wingo@pobox.com>

* gst/base/gstbasetransform.c: Debug changes.

* gst/gstutils.h:
* gst/gstutils.c (gst_bin_watch_for_state_change): Add function to
ensure bins post state change messages. A bit of a hack but I can't
think of a way to avoid it.

* check/gst/gstbin.c (test_watch_for_state_change): Added test.
This commit is contained in:
Andy Wingo 2005-08-17 16:33:27 +00:00
parent ecbae942c5
commit c5e2202f20
8 changed files with 189 additions and 8 deletions

View file

@ -1,3 +1,14 @@
2005-08-17 Andy Wingo <wingo@pobox.com>
* gst/base/gstbasetransform.c: Debug changes.
* gst/gstutils.h:
* gst/gstutils.c (gst_bin_watch_for_state_change): Add function to
ensure bins post state change messages. A bit of a hack but I can't
think of a way to avoid it.
* check/gst/gstbin.c (test_watch_for_state_change): Added test.
2005-08-16 Andy Wingo <wingo@pobox.com>
* gst/base/gstadapter.h:

View file

@ -270,6 +270,68 @@ GST_START_TEST (test_message_state_changed_children)
GST_END_TEST;
GST_START_TEST (test_watch_for_state_change)
{
GstElement *src, *sink, *bin;
GstBus *bus;
bin = gst_element_factory_make ("bin", NULL);
fail_unless (bin != NULL, "Could not create bin");
src = gst_element_factory_make ("fakesrc", NULL);
fail_if (src == NULL, "Could not create fakesrc");
sink = gst_element_factory_make ("fakesink", NULL);
fail_if (sink == NULL, "Could not create fakesink");
gst_bin_add (GST_BIN (bin), sink);
gst_bin_add (GST_BIN (bin), src);
fail_unless (gst_element_link (src, sink), "could not link src and sink");
bus = GST_ELEMENT_BUS (bin);
/* change state, spawning two times three messages, minus one async */
fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED)
== GST_STATE_ASYNC);
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);
fail_unless (gst_bus_have_pending (bus) == FALSE,
"Unexpected messages on bus");
fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING)
== GST_STATE_SUCCESS);
pop_messages (bus, 3);
/* 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));
pop_messages (bus, 3);
fail_unless (gst_bus_have_pending (bus) == FALSE,
"Unexpected messages on bus");
/* setting bin to NULL flushes the bus automatically */
fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL)
== GST_STATE_SUCCESS);
/* clean up */
gst_object_unref (bin);
}
GST_END_TEST;
/* adding an element with linked pads to a bin unlinks the
* pads */
GST_START_TEST (test_add_linked)
@ -331,6 +393,7 @@ gst_bin_suite (void)
tcase_add_test (tc_chain, test_message_state_changed);
tcase_add_test (tc_chain, test_message_state_changed_child);
tcase_add_test (tc_chain, test_message_state_changed_children);
tcase_add_test (tc_chain, test_watch_for_state_change);
tcase_add_test (tc_chain, test_add_linked);
return s;

View file

@ -215,8 +215,6 @@ gst_base_transform_transform_caps (GstBaseTransform * trans, GstPad * pad,
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
GST_DEBUG_OBJECT (trans, "from: %" GST_PTR_FORMAT, caps);
/* if there is a custom transform function, use this */
if (klass->transform_caps) {
GstCaps *temp;
@ -230,10 +228,10 @@ gst_base_transform_transform_caps (GstBaseTransform * trans, GstPad * pad,
GstCaps *nth;
nth = gst_caps_copy_nth (caps, i);
GST_DEBUG_OBJECT (trans, " from: %" GST_PTR_FORMAT, nth);
GST_DEBUG_OBJECT (trans, "from[%d]: %" GST_PTR_FORMAT, i, nth);
temp = klass->transform_caps (trans, pad, nth);
gst_caps_unref (nth);
GST_DEBUG_OBJECT (trans, " to : %" GST_PTR_FORMAT, temp);
GST_DEBUG_OBJECT (trans, " to[%d]: %" GST_PTR_FORMAT, i, temp);
gst_caps_append (ret, temp);
}

View file

@ -1073,6 +1073,7 @@ clear_queue (GQueue * queue, gboolean unref)
if (unref)
gst_object_unref (p);
}
static void
remove_all_from_queue (GQueue * queue, gpointer elem, gboolean unref)
{

View file

@ -1785,6 +1785,52 @@ gst_bin_remove_many (GstBin * bin, GstElement * element_1, ...)
va_end (args);
}
static void
get_state_func (GstElement * element, gpointer unused)
{
GstElementStateReturn ret = GST_STATE_ASYNC;
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
"new thread waiting on state change");
/* wait indefinitely */
while (ret == GST_STATE_ASYNC)
ret = gst_element_get_state (element, NULL, NULL, NULL);
gst_object_unref (element);
}
/**
* gst_bin_watch_for_state_change:
* @bin: the bin to watch for state changes
*
* Spawns a thread calling gst_element_get_state on @bin with infinite timeout.
*
* In practice this is done because if a bin returns GST_STATE_ASYNC from a
* state change it will not commit its state until someone calls
* gst_element_get_state on it. Thus having another thread checking the bin's
* state will ensure that a state-changed message gets posted on the bus
* eventually.
*
* This function is admittedly a bit of a hack. Bins should always post
* messages. However this behavior was broken out into this function to avoid
* spawning threads when scrubbing, when the bin's state is changing quickly and
* asynchronously.
*/
void
gst_bin_watch_for_state_change (GstBin * bin)
{
static GThreadPool *pool = NULL;
static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
g_static_mutex_lock (&mutex);
if (pool == NULL)
pool = g_thread_pool_new ((GFunc) get_state_func, NULL, -1, FALSE, NULL);
g_static_mutex_unlock (&mutex);
g_thread_pool_push (pool, gst_object_ref (bin), NULL);
}
static void
gst_element_populate_std_props (GObjectClass * klass, const gchar * prop_name,
guint arg_id, GParamFlags flags)

View file

@ -302,6 +302,7 @@ 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);

View file

@ -215,8 +215,6 @@ gst_base_transform_transform_caps (GstBaseTransform * trans, GstPad * pad,
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
GST_DEBUG_OBJECT (trans, "from: %" GST_PTR_FORMAT, caps);
/* if there is a custom transform function, use this */
if (klass->transform_caps) {
GstCaps *temp;
@ -230,10 +228,10 @@ gst_base_transform_transform_caps (GstBaseTransform * trans, GstPad * pad,
GstCaps *nth;
nth = gst_caps_copy_nth (caps, i);
GST_DEBUG_OBJECT (trans, " from: %" GST_PTR_FORMAT, nth);
GST_DEBUG_OBJECT (trans, "from[%d]: %" GST_PTR_FORMAT, i, nth);
temp = klass->transform_caps (trans, pad, nth);
gst_caps_unref (nth);
GST_DEBUG_OBJECT (trans, " to : %" GST_PTR_FORMAT, temp);
GST_DEBUG_OBJECT (trans, " to[%d]: %" GST_PTR_FORMAT, i, temp);
gst_caps_append (ret, temp);
}

View file

@ -270,6 +270,68 @@ GST_START_TEST (test_message_state_changed_children)
GST_END_TEST;
GST_START_TEST (test_watch_for_state_change)
{
GstElement *src, *sink, *bin;
GstBus *bus;
bin = gst_element_factory_make ("bin", NULL);
fail_unless (bin != NULL, "Could not create bin");
src = gst_element_factory_make ("fakesrc", NULL);
fail_if (src == NULL, "Could not create fakesrc");
sink = gst_element_factory_make ("fakesink", NULL);
fail_if (sink == NULL, "Could not create fakesink");
gst_bin_add (GST_BIN (bin), sink);
gst_bin_add (GST_BIN (bin), src);
fail_unless (gst_element_link (src, sink), "could not link src and sink");
bus = GST_ELEMENT_BUS (bin);
/* change state, spawning two times three messages, minus one async */
fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED)
== GST_STATE_ASYNC);
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);
fail_unless (gst_bus_have_pending (bus) == FALSE,
"Unexpected messages on bus");
fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING)
== GST_STATE_SUCCESS);
pop_messages (bus, 3);
/* 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));
pop_messages (bus, 3);
fail_unless (gst_bus_have_pending (bus) == FALSE,
"Unexpected messages on bus");
/* setting bin to NULL flushes the bus automatically */
fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL)
== GST_STATE_SUCCESS);
/* clean up */
gst_object_unref (bin);
}
GST_END_TEST;
/* adding an element with linked pads to a bin unlinks the
* pads */
GST_START_TEST (test_add_linked)
@ -331,6 +393,7 @@ gst_bin_suite (void)
tcase_add_test (tc_chain, test_message_state_changed);
tcase_add_test (tc_chain, test_message_state_changed_child);
tcase_add_test (tc_chain, test_message_state_changed_children);
tcase_add_test (tc_chain, test_watch_for_state_change);
tcase_add_test (tc_chain, test_add_linked);
return s;