summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gst/gstpad.c11
-rw-r--r--tests/check/gst/gstpad.c78
2 files changed, 88 insertions, 1 deletions
diff --git a/gst/gstpad.c b/gst/gstpad.c
index f0eea1490..f42a0f94f 100644
--- a/gst/gstpad.c
+++ b/gst/gstpad.c
@@ -3270,6 +3270,7 @@ probe_hook_marshal (GHook * hook, ProbeMarshall * data)
GstPadProbeType type, flags;
GstPadProbeCallback callback;
GstPadProbeReturn ret;
+ gpointer original_data;
/* if we have called this callback, do nothing */
if (PROBE_COOKIE (hook) == data->cookie) {
@@ -3283,6 +3284,7 @@ probe_hook_marshal (GHook * hook, ProbeMarshall * data)
flags = hook->flags >> G_HOOK_FLAG_USER_SHIFT;
type = info->type;
+ original_data = info->data;
/* one of the data types for non-idle probes */
if ((type & GST_PAD_PROBE_TYPE_IDLE) == 0
@@ -3321,6 +3323,12 @@ probe_hook_marshal (GHook * hook, ProbeMarshall * data)
GST_OBJECT_LOCK (pad);
+ if (original_data != NULL && info->data == NULL) {
+ GST_DEBUG_OBJECT (pad, "data item in pad probe info was dropped");
+ info->type = GST_PAD_PROBE_TYPE_INVALID;
+ data->dropped = TRUE;
+ }
+
switch (ret) {
case GST_PAD_PROBE_REMOVE:
/* remove the probe */
@@ -4265,7 +4273,8 @@ probe_stopped:
GST_OBJECT_UNLOCK (pad);
pad->ABI.abi.last_flowret =
ret == GST_FLOW_CUSTOM_SUCCESS ? GST_FLOW_OK : ret;
- gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
+ if (data != NULL)
+ gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
switch (ret) {
case GST_FLOW_CUSTOM_SUCCESS:
diff --git a/tests/check/gst/gstpad.c b/tests/check/gst/gstpad.c
index 625fec07b..dbd4ab917 100644
--- a/tests/check/gst/gstpad.c
+++ b/tests/check/gst/gstpad.c
@@ -1191,6 +1191,83 @@ GST_START_TEST (test_pad_probe_remove)
GST_END_TEST;
+typedef struct
+{
+ gulong probe_id;
+ GstPad *probe_pad;
+ GThread *thread;
+} BlockReplaceProbeHelper;
+
+static gpointer
+unblock_probe_thread (gpointer user_data)
+{
+ BlockReplaceProbeHelper *helper = user_data;
+
+ GST_INFO_OBJECT (helper->probe_pad, "removing probe to unblock pad");
+ gst_pad_remove_probe (helper->probe_pad, helper->probe_id);
+ return NULL;
+}
+
+static GstPadProbeReturn
+block_and_replace_buffer_probe_cb (GstPad * pad, GstPadProbeInfo * info,
+ gpointer user_data)
+{
+ BlockReplaceProbeHelper *helper = user_data;
+
+ GST_INFO_OBJECT (pad, "about to block pad, replacing buffer");
+
+ /* we want to block, but also drop this buffer */
+ gst_buffer_unref (GST_BUFFER (info->data));
+ info->data = NULL;
+
+ helper->thread =
+ g_thread_new ("gst-pad-test-thread", unblock_probe_thread, helper);
+
+ return GST_PAD_PROBE_OK;
+}
+
+GST_START_TEST (test_pad_probe_block_and_drop_buffer)
+{
+ BlockReplaceProbeHelper helper;
+ GstFlowReturn flow;
+ GstPad *src, *sink;
+
+ src = gst_pad_new ("src", GST_PAD_SRC);
+ gst_pad_set_active (src, TRUE);
+ sink = gst_pad_new ("sink", GST_PAD_SINK);
+ gst_pad_set_chain_function (sink, gst_check_chain_func);
+ gst_pad_set_active (sink, TRUE);
+
+ fail_unless (gst_pad_push_event (src,
+ gst_event_new_stream_start ("test")) == TRUE);
+ fail_unless (gst_pad_push_event (src,
+ gst_event_new_segment (&dummy_segment)) == TRUE);
+
+ fail_unless_equals_int (gst_pad_link (src, sink), GST_PAD_LINK_OK);
+
+ helper.probe_id = gst_pad_add_probe (src,
+ GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER,
+ block_and_replace_buffer_probe_cb, &helper, NULL);
+ helper.probe_pad = src;
+
+ /* push a buffer so the events are propagated downstream */
+ flow = gst_pad_push (src, gst_buffer_new ());
+
+ g_thread_join (helper.thread);
+
+ fail_unless_equals_int (flow, GST_FLOW_OK);
+
+ /* no buffer should have made it through to the sink pad, and especially
+ * not a NULL pointer buffer */
+ fail_if (buffers && buffers->data == NULL);
+ fail_unless (buffers == NULL);
+
+ gst_object_unref (src);
+ gst_object_unref (sink);
+}
+
+GST_END_TEST;
+
static GstPadProbeReturn
probe_block_a (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
{
@@ -2085,6 +2162,7 @@ gst_pad_suite (void)
tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_blocking);
tcase_add_test (tc_chain, test_pad_probe_remove);
tcase_add_test (tc_chain, test_pad_probe_block_add_remove);
+ tcase_add_test (tc_chain, test_pad_probe_block_and_drop_buffer);
tcase_add_test (tc_chain, test_pad_probe_flush_events);
tcase_add_test (tc_chain, test_queue_src_caps_notify_linked);
tcase_add_test (tc_chain, test_queue_src_caps_notify_not_linked);