mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 14:26:43 +00:00
pad: call new callbacks set in the block callback
Keep track of when a new callback is installed in the callback and call the new callback in that case. Add unit test for checking pad blocking. Fixes #573823.
This commit is contained in:
parent
646a746965
commit
da0060d3aa
3 changed files with 131 additions and 25 deletions
11
gst/gstpad.c
11
gst/gstpad.c
|
@ -1022,6 +1022,7 @@ gst_pad_set_blocked_async_full (GstPad * pad, gboolean blocked,
|
||||||
pad->block_callback = callback;
|
pad->block_callback = callback;
|
||||||
pad->block_data = user_data;
|
pad->block_data = user_data;
|
||||||
pad->block_destroy_data = destroy_data;
|
pad->block_destroy_data = destroy_data;
|
||||||
|
pad->abidata.ABI.block_callback_called = FALSE;
|
||||||
if (!callback) {
|
if (!callback) {
|
||||||
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for block");
|
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for block");
|
||||||
GST_PAD_BLOCK_WAIT (pad);
|
GST_PAD_BLOCK_WAIT (pad);
|
||||||
|
@ -1039,6 +1040,7 @@ gst_pad_set_blocked_async_full (GstPad * pad, gboolean blocked,
|
||||||
pad->block_callback = callback;
|
pad->block_callback = callback;
|
||||||
pad->block_data = user_data;
|
pad->block_data = user_data;
|
||||||
pad->block_destroy_data = destroy_data;
|
pad->block_destroy_data = destroy_data;
|
||||||
|
pad->abidata.ABI.block_callback_called = FALSE;
|
||||||
|
|
||||||
GST_PAD_BLOCK_BROADCAST (pad);
|
GST_PAD_BLOCK_BROADCAST (pad);
|
||||||
if (!callback) {
|
if (!callback) {
|
||||||
|
@ -3786,9 +3788,12 @@ handle_pad_block (GstPad * pad)
|
||||||
* all taken when calling this function. */
|
* all taken when calling this function. */
|
||||||
gst_object_ref (pad);
|
gst_object_ref (pad);
|
||||||
|
|
||||||
|
while (GST_PAD_IS_BLOCKED (pad)) {
|
||||||
|
do {
|
||||||
/* we either have a callback installed to notify the block or
|
/* we either have a callback installed to notify the block or
|
||||||
* some other thread is doing a GCond wait. */
|
* some other thread is doing a GCond wait. */
|
||||||
callback = pad->block_callback;
|
callback = pad->block_callback;
|
||||||
|
pad->abidata.ABI.block_callback_called = TRUE;
|
||||||
if (callback) {
|
if (callback) {
|
||||||
/* there is a callback installed, call it. We release the
|
/* there is a callback installed, call it. We release the
|
||||||
* lock so that the callback can do something usefull with the
|
* lock so that the callback can do something usefull with the
|
||||||
|
@ -3806,11 +3811,15 @@ handle_pad_block (GstPad * pad)
|
||||||
* if any. */
|
* if any. */
|
||||||
GST_PAD_BLOCK_BROADCAST (pad);
|
GST_PAD_BLOCK_BROADCAST (pad);
|
||||||
}
|
}
|
||||||
|
} while (pad->abidata.ABI.block_callback_called == FALSE
|
||||||
|
&& GST_PAD_IS_BLOCKED (pad));
|
||||||
|
|
||||||
/* OBJECT_LOCK could have been released when we did the callback, which
|
/* OBJECT_LOCK could have been released when we did the callback, which
|
||||||
* then could have made the pad unblock so we need to check the blocking
|
* then could have made the pad unblock so we need to check the blocking
|
||||||
* condition again. */
|
* condition again. */
|
||||||
while (GST_PAD_IS_BLOCKED (pad)) {
|
if (!GST_PAD_IS_BLOCKED (pad))
|
||||||
|
break;
|
||||||
|
|
||||||
/* now we block the streaming thread. It can be unlocked when we
|
/* now we block the streaming thread. It can be unlocked when we
|
||||||
* deactivate the pad (which will also set the FLUSHING flag) or
|
* deactivate the pad (which will also set the FLUSHING flag) or
|
||||||
* when the pad is unblocked. A flushing event will also unblock
|
* when the pad is unblocked. A flushing event will also unblock
|
||||||
|
|
|
@ -633,7 +633,12 @@ struct _GstPad {
|
||||||
GDestroyNotify block_destroy_data;
|
GDestroyNotify block_destroy_data;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
gboolean block_callback_called;
|
||||||
|
} ABI;
|
||||||
gpointer _gst_reserved[GST_PADDING - 2];
|
gpointer _gst_reserved[GST_PADDING - 2];
|
||||||
|
} abidata;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstPadClass {
|
struct _GstPadClass {
|
||||||
|
|
|
@ -809,6 +809,97 @@ GST_START_TEST (test_block_async_full_destroy_dispose)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
unblock_async_no_flush_cb (GstPad * pad, gboolean blocked, gpointer user_data)
|
||||||
|
{
|
||||||
|
gboolean *bool_user_data = (gboolean *) user_data;
|
||||||
|
|
||||||
|
/* here we should have blocked == 1 unblocked == 0 */
|
||||||
|
|
||||||
|
fail_unless (blocked == FALSE);
|
||||||
|
|
||||||
|
fail_unless (bool_user_data[0] == TRUE);
|
||||||
|
fail_unless (bool_user_data[1] == TRUE);
|
||||||
|
fail_unless (bool_user_data[2] == FALSE);
|
||||||
|
|
||||||
|
bool_user_data[2] = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
unblock_async_not_called (GstPad * pad, gboolean blocked, gpointer user_data)
|
||||||
|
{
|
||||||
|
g_warn_if_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
block_async_second_no_flush (GstPad * pad, gboolean blocked, gpointer user_data)
|
||||||
|
{
|
||||||
|
gboolean *bool_user_data = (gboolean *) user_data;
|
||||||
|
|
||||||
|
fail_unless (blocked == TRUE);
|
||||||
|
|
||||||
|
fail_unless (bool_user_data[0] == TRUE);
|
||||||
|
fail_unless (bool_user_data[1] == FALSE);
|
||||||
|
fail_unless (bool_user_data[2] == FALSE);
|
||||||
|
|
||||||
|
bool_user_data[1] = TRUE;
|
||||||
|
|
||||||
|
fail_unless (gst_pad_set_blocked_async (pad, FALSE, unblock_async_no_flush_cb,
|
||||||
|
user_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
block_async_first_no_flush (GstPad * pad, gboolean blocked, gpointer user_data)
|
||||||
|
{
|
||||||
|
static int n_calls = 0;
|
||||||
|
gboolean *bool_user_data = (gboolean *) user_data;
|
||||||
|
|
||||||
|
fail_unless (blocked == TRUE);
|
||||||
|
|
||||||
|
if (++n_calls > 1)
|
||||||
|
/* we expect this callback to be called only once */
|
||||||
|
g_warn_if_reached ();
|
||||||
|
|
||||||
|
*bool_user_data = blocked;
|
||||||
|
|
||||||
|
fail_unless (bool_user_data[0] == TRUE);
|
||||||
|
fail_unless (bool_user_data[1] == FALSE);
|
||||||
|
fail_unless (bool_user_data[2] == FALSE);
|
||||||
|
|
||||||
|
fail_unless (gst_pad_set_blocked_async (pad, FALSE, unblock_async_not_called,
|
||||||
|
NULL));
|
||||||
|
|
||||||
|
/* replace block_async_first with block_async_second so next time the pad is
|
||||||
|
* blocked the latter should be called */
|
||||||
|
fail_unless (gst_pad_set_blocked_async (pad, TRUE,
|
||||||
|
block_async_second_no_flush, user_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_START_TEST (test_block_async_replace_callback_no_flush)
|
||||||
|
{
|
||||||
|
GstPad *pad;
|
||||||
|
gboolean bool_user_data[3] = { FALSE, FALSE, FALSE };
|
||||||
|
|
||||||
|
pad = gst_pad_new ("src", GST_PAD_SRC);
|
||||||
|
fail_unless (pad != NULL);
|
||||||
|
gst_pad_set_active (pad, TRUE);
|
||||||
|
|
||||||
|
fail_unless (gst_pad_set_blocked_async (pad, TRUE, block_async_first_no_flush,
|
||||||
|
bool_user_data));
|
||||||
|
|
||||||
|
gst_pad_push (pad, gst_buffer_new ());
|
||||||
|
fail_unless (bool_user_data[0] == TRUE);
|
||||||
|
fail_unless (bool_user_data[1] == TRUE);
|
||||||
|
fail_unless (bool_user_data[2] == TRUE);
|
||||||
|
|
||||||
|
gst_object_unref (pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
gst_pad_suite (void)
|
gst_pad_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -837,6 +928,7 @@ gst_pad_suite (void)
|
||||||
#endif
|
#endif
|
||||||
tcase_add_test (tc_chain, test_block_async_full_destroy);
|
tcase_add_test (tc_chain, test_block_async_full_destroy);
|
||||||
tcase_add_test (tc_chain, test_block_async_full_destroy_dispose);
|
tcase_add_test (tc_chain, test_block_async_full_destroy_dispose);
|
||||||
|
tcase_add_test (tc_chain, test_block_async_replace_callback_no_flush);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue