mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 23:06:49 +00:00
tee: Add allow-not-linked property
This property avoids not linked error when all the pads are unlinked or when there are no source pads. This is useful in dynamic pipelines where it can happen that for a short time there are no pads at all or all downstream pads are not linked yet. https://bugzilla.gnome.org/show_bug.cgi?id=746436
This commit is contained in:
parent
5b6ab53e7f
commit
3e8e0a7065
3 changed files with 123 additions and 4 deletions
|
@ -84,6 +84,7 @@ gst_tee_pull_mode_get_type (void)
|
|||
#define DEFAULT_PROP_SILENT TRUE
|
||||
#define DEFAULT_PROP_LAST_MESSAGE NULL
|
||||
#define DEFAULT_PULL_MODE GST_TEE_PULL_MODE_NEVER
|
||||
#define DEFAULT_PROP_ALLOW_NOT_LINKED FALSE
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -94,6 +95,7 @@ enum
|
|||
PROP_LAST_MESSAGE,
|
||||
PROP_PULL_MODE,
|
||||
PROP_ALLOC_PAD,
|
||||
PROP_ALLOW_NOT_LINKED,
|
||||
};
|
||||
|
||||
static GstStaticPadTemplate tee_src_template =
|
||||
|
@ -265,6 +267,23 @@ gst_tee_class_init (GstTeeClass * klass)
|
|||
g_object_class_install_property (gobject_class, PROP_ALLOC_PAD,
|
||||
pspec_alloc_pad);
|
||||
|
||||
/**
|
||||
* GstTee:allow-not-linked
|
||||
*
|
||||
* This property makes sink pad return GST_FLOW_OK even if there are no
|
||||
* source pads or any of them is linked.
|
||||
*
|
||||
* This is useful to avoid errors when you have a dynamic pipeline and during
|
||||
* a reconnection you can have all the pads unlinked or removed.
|
||||
*
|
||||
* Since: 1.6
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_ALLOW_NOT_LINKED,
|
||||
g_param_spec_boolean ("allow-not-linked", "Allow not linked",
|
||||
"Return GTS_FLOW_OK even if there are not source pads or all are "
|
||||
"unlinked", DEFAULT_PROP_ALLOW_NOT_LINKED,
|
||||
G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gst_element_class_set_static_metadata (gstelement_class,
|
||||
"Tee pipe fitting",
|
||||
"Generic",
|
||||
|
@ -487,6 +506,9 @@ gst_tee_set_property (GObject * object, guint prop_id, const GValue * value,
|
|||
GST_OBJECT_UNLOCK (pad);
|
||||
break;
|
||||
}
|
||||
case PROP_ALLOW_NOT_LINKED:
|
||||
tee->allow_not_linked = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -520,6 +542,9 @@ gst_tee_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_ALLOC_PAD:
|
||||
g_value_set_object (value, tee->allocpad);
|
||||
break;
|
||||
case PROP_ALLOW_NOT_LINKED:
|
||||
g_value_set_boolean (value, tee->allow_not_linked);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -636,6 +661,10 @@ gst_tee_handle_data (GstTee * tee, gpointer data, gboolean is_list)
|
|||
|
||||
gst_object_unref (pad);
|
||||
|
||||
if (ret == GST_FLOW_NOT_LINKED && tee->allow_not_linked) {
|
||||
ret = GST_FLOW_OK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -643,7 +672,11 @@ gst_tee_handle_data (GstTee * tee, gpointer data, gboolean is_list)
|
|||
g_list_foreach (pads, (GFunc) clear_pads, tee);
|
||||
|
||||
restart:
|
||||
cret = GST_FLOW_NOT_LINKED;
|
||||
if (tee->allow_not_linked) {
|
||||
cret = GST_FLOW_OK;
|
||||
} else {
|
||||
cret = GST_FLOW_NOT_LINKED;
|
||||
}
|
||||
pads = GST_ELEMENT_CAST (tee)->srcpads;
|
||||
cookie = GST_ELEMENT_CAST (tee)->pads_cookie;
|
||||
|
||||
|
@ -709,13 +742,23 @@ restart:
|
|||
/* ERRORS */
|
||||
no_pads:
|
||||
{
|
||||
GST_DEBUG_OBJECT (tee, "there are no pads, return not-linked");
|
||||
ret = GST_FLOW_NOT_LINKED;
|
||||
goto error;
|
||||
if (tee->allow_not_linked) {
|
||||
GST_DEBUG_OBJECT (tee, "there are no pads, dropping %s",
|
||||
is_list ? "buffer-list" : "buffer");
|
||||
ret = GST_FLOW_OK;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (tee, "there are no pads, return not-linked");
|
||||
ret = GST_FLOW_NOT_LINKED;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
error:
|
||||
{
|
||||
GST_DEBUG_OBJECT (tee, "received error %s", gst_flow_get_name (ret));
|
||||
goto end;
|
||||
}
|
||||
end:
|
||||
{
|
||||
GST_OBJECT_UNLOCK (tee);
|
||||
gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
|
||||
return ret;
|
||||
|
|
|
@ -79,6 +79,8 @@ struct _GstTee {
|
|||
GstPadMode sink_mode;
|
||||
GstTeePullMode pull_mode;
|
||||
GstPad *pull_pad;
|
||||
|
||||
gboolean allow_not_linked;
|
||||
};
|
||||
|
||||
struct _GstTeeClass {
|
||||
|
|
|
@ -625,6 +625,79 @@ GST_START_TEST (test_request_pads)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_allow_not_linked)
|
||||
{
|
||||
GstElement *tee;
|
||||
GstPad *src1, *src2;
|
||||
GstBuffer *buffer;
|
||||
GstPad *srcpad;
|
||||
GstCaps *caps;
|
||||
GstSegment segment;
|
||||
|
||||
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
caps = gst_caps_new_empty_simple ("test/test");
|
||||
|
||||
tee = gst_check_setup_element ("tee");
|
||||
fail_unless (tee);
|
||||
g_object_set (tee, "allow-not-linked", TRUE, NULL);
|
||||
|
||||
srcpad = gst_check_setup_src_pad (tee, &srctemplate);
|
||||
gst_pad_set_active (srcpad, TRUE);
|
||||
|
||||
gst_pad_push_event (srcpad, gst_event_new_stream_start ("test"));
|
||||
gst_segment_init (&segment, GST_FORMAT_BYTES);
|
||||
gst_pad_push_event (srcpad, gst_event_new_stream_start ("test"));
|
||||
gst_pad_set_caps (srcpad, caps);
|
||||
gst_caps_unref (caps);
|
||||
gst_pad_push_event (srcpad, gst_event_new_segment (&segment));
|
||||
|
||||
fail_unless (gst_element_set_state (tee,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
|
||||
|
||||
buffer = gst_buffer_new ();
|
||||
fail_unless (buffer);
|
||||
|
||||
fail_unless (gst_pad_push (srcpad, gst_buffer_ref (buffer)) == GST_FLOW_OK);
|
||||
|
||||
src1 = gst_element_get_request_pad (tee, "src_%u");
|
||||
|
||||
fail_unless (gst_pad_push (srcpad, gst_buffer_ref (buffer)) == GST_FLOW_OK);
|
||||
|
||||
src2 = gst_element_get_request_pad (tee, "src_%u");
|
||||
|
||||
fail_unless (gst_pad_push (srcpad, gst_buffer_ref (buffer)) == GST_FLOW_OK);
|
||||
|
||||
g_object_set (tee, "allow-not-linked", FALSE, NULL);
|
||||
|
||||
fail_unless (gst_pad_push (srcpad,
|
||||
gst_buffer_ref (buffer)) == GST_FLOW_NOT_LINKED);
|
||||
|
||||
gst_element_release_request_pad (tee, src1);
|
||||
|
||||
fail_unless (gst_pad_push (srcpad,
|
||||
gst_buffer_ref (buffer)) == GST_FLOW_NOT_LINKED);
|
||||
|
||||
gst_element_release_request_pad (tee, src2);
|
||||
g_object_unref (src1);
|
||||
g_object_unref (src2);
|
||||
|
||||
fail_unless (gst_pad_push (srcpad,
|
||||
gst_buffer_ref (buffer)) == GST_FLOW_NOT_LINKED);
|
||||
|
||||
gst_pad_set_active (srcpad, FALSE);
|
||||
gst_check_teardown_src_pad (tee);
|
||||
gst_check_teardown_element (tee);
|
||||
|
||||
fail_if (buffer->mini_object.refcount != 1);
|
||||
gst_buffer_unref (buffer);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
tee_suite (void)
|
||||
{
|
||||
|
@ -642,6 +715,7 @@ tee_suite (void)
|
|||
tcase_add_test (tc_chain, test_internal_links);
|
||||
tcase_add_test (tc_chain, test_flow_aggregation);
|
||||
tcase_add_test (tc_chain, test_request_pads);
|
||||
tcase_add_test (tc_chain, test_allow_not_linked);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue