Add or remove elements to (from) a tee dynamically
trinitonadam
trinitonadam at gmail.com
Thu Dec 24 08:33:51 PST 2015
OK, thanks
I tried this formula and I got the following error:
ERROR: from element /GstPipeline:pipeline0/GstAlsaSrc:alsasrc0: Internal
data flow error.
Additional debug info:
gstbasesrc.c(2943): gst_base_src_loop ():
/GstPipeline:pipeline0/GstAlsaSrc:alsasrc0:
streaming task paused, reason not-linked (-1)
static GstElement *pipeline;
static GstElement *src, *tee;
typedef struct
{
GstPad *teepad;
GstElement *queue;
GstElement *level;
GstElement *sink;
gboolean removing;
} Listen;
typedef struct
{
GstPad *teepad;
GstElement *queue;
GstElement *level;
GstElement *sink;
gboolean removing;
} Record;
static gboolean
message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
{
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ERROR:{
GError *err = NULL;
gchar *name, *debug = NULL;
name = gst_object_get_path_string (message->src);
gst_message_parse_error (message, &err, &debug);
g_printerr ("ERROR: from element %s: %s\n", name, err->message);
if (debug != NULL)
g_printerr ("Additional debug info:\n%s\n", debug);
g_error_free (err);
g_free (debug);
g_free (name);
g_main_loop_quit (loop);
break;
}
case GST_MESSAGE_WARNING:{
GError *err = NULL;
gchar *name, *debug = NULL;
name = gst_object_get_path_string (message->src);
gst_message_parse_warning (message, &err, &debug);
g_printerr ("ERROR: from element %s: %s\n", name, err->message);
if (debug != NULL)
g_printerr ("Additional debug info:\n%s\n", debug);
g_error_free (err);
g_free (debug);
g_free (name);
break;
}
case GST_MESSAGE_EOS:
g_print ("Got EOS\n");
g_main_loop_quit (loop);
break;
default:
break;
}
return TRUE;
}
static GstPadProbeReturn
record_pad_unlink_cb (GstPad * pad, GstPadProbeInfo * info, gpointer
user_data)
{
Record *record = user_data;
GstPad *sinkpad;
if (!g_atomic_int_compare_and_exchange (&record->removing, FALSE, TRUE))
return GST_PAD_PROBE_OK;
sinkpad = gst_element_get_static_pad (record->queue, "sink");
gst_pad_unlink (record->teepad, sinkpad);
gst_object_unref (sinkpad);
gst_bin_remove (GST_BIN (pipeline), record->queue);
gst_bin_remove (GST_BIN (pipeline), record->level);
gst_bin_remove (GST_BIN (pipeline), record->sink);
gst_element_set_state (record->sink, GST_STATE_NULL);
gst_element_set_state (record->level, GST_STATE_NULL);
gst_element_set_state (record->queue, GST_STATE_NULL);
gst_object_unref (record->queue);
gst_object_unref (record->level);
gst_object_unref (record->sink);
gst_element_release_request_pad (tee, record->teepad);
gst_object_unref (record->teepad);
g_print ("removed\n");
return GST_PAD_PROBE_REMOVE;
}
static void
record_pad_added_cb (GstElement * element, GstPad * pad, gpointer user_data)
{
GstCaps *caps;
GstStructure *s;
const gchar *name;
caps = gst_pad_get_current_caps (pad);
s = gst_caps_get_structure (caps, 0);
name = gst_structure_get_name (s);
if (strcmp (name, "audio/x-raw") == 0) {
GstPad *sinkpad, *teepad;
GstElement *queue, *level, *sink;
GstPadTemplate *templ;
sinkpad = gst_element_get_static_pad (src, "sink");
if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK) {
g_printerr ("Failed to link src with conv\n");
gst_object_unref (sinkpad);
g_main_loop_quit (loop);
return;
}
gst_object_unref (sinkpad);
templ = gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (tee),
"src_%u");
teepad = gst_element_request_pad (tee, templ, NULL, NULL);
queue = gst_element_factory_make ("queue", NULL);
level = gst_element_factory_make ("level", NULL);
sink = gst_element_factory_make ("filesink", NULL);
gst_bin_add_many (GST_BIN (pipeline), queue, level, sink, NULL);
gst_element_link_many (queue, level, sink, NULL);
sinkpad = gst_element_get_static_pad (queue, "sink");
gst_pad_link (teepad, sinkpad);
gst_object_unref (sinkpad);
}
gst_caps_unref (caps);
g_timeout_add_seconds (1, record_pad_unlink_cb, NULL);
}
static GstPadProbeReturn
listen_pad_unlink_cb (GstPad * pad, GstPadProbeInfo * info, gpointer
user_data)
{
Listen *listen = user_data;
GstPad *sinkpad;
if (!g_atomic_int_compare_and_exchange (&listen->removing, FALSE, TRUE))
return GST_PAD_PROBE_OK;
sinkpad = gst_element_get_static_pad (listen->queue, "sink");
gst_pad_unlink (listen->teepad, sinkpad);
gst_object_unref (sinkpad);
gst_bin_remove (GST_BIN (pipeline), listen->queue);
gst_bin_remove (GST_BIN (pipeline), listen->convert);
gst_bin_remove (GST_BIN (pipeline), listen->resample);
gst_bin_remove (GST_BIN (pipeline), listen->sink);
gst_element_set_state (listen->sink, GST_STATE_NULL);
gst_element_set_state (listen->convert, GST_STATE_NULL);
gst_element_set_state (listen->resample, GST_STATE_NULL);
gst_element_set_state (listen->queue, GST_STATE_NULL);
gst_object_unref (listen->queue);
gst_object_unref (listen->convert);
gst_object_unref (listen->resample);
gst_object_unref (listen->sink);
gst_element_release_request_pad (tee, listen->teepad);
gst_object_unref (listen->teepad);
g_print ("removed\n");
return GST_PAD_PROBE_REMOVE;
}
static void
listen_pad_added_cb (GstElement * element, GstPad * pad, gpointer user_data)
{
GstCaps *caps;
GstStructure *s;
const gchar *name;
caps = gst_pad_get_current_caps (pad);
s = gst_caps_get_structure (caps, 0);
name = gst_structure_get_name (s);
if (strcmp (name, "audio/x-raw") == 0) {
GstPad *sinkpad, *teepad;
GstElement *queue, *convert, *resample, *sink;
GstPadTemplate *templ;
sinkpad = gst_element_get_static_pad (src, "sink");
if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK) {
g_printerr ("Failed to link src with conv\n");
gst_object_unref (sinkpad);
g_main_loop_quit (loop);
return;
}
gst_object_unref (sinkpad);
templ = gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (tee),
"src_%u");
teepad = gst_element_request_pad (tee, templ, NULL, NULL);
queue = gst_element_factory_make ("queue", NULL);
convert = gst_element_factory_make ("audioconvert", NULL);
resample = gst_element_factory_make ("audioresample", NULL);
sink = gst_element_factory_make ("alsasink", NULL);
gst_bin_add_many (GST_BIN (pipeline), queue, convert, resample, sink,
NULL);
gst_element_link_many (queue, convert, resample, sink, NULL);
sinkpad = gst_element_get_static_pad (queue, "sink");
gst_pad_link (teepad, sinkpad);
gst_object_unref (sinkpad);
}
gst_caps_unref (caps);
}
void create_pipeline(void)
{
pipeline = gst_pipeline_new (NULL);
src = gst_element_factory_make ("alsasrc", NULL);
tee = gst_element_factory_make ("tee", NULL);
if (!pipeline || !src || !tee) {
g_error ("Failed to create elements");
return;
}
gst_bin_add_many (GST_BIN (pipeline), src, tee, NULL);
if (!gst_element_link_many (src, tee, NULL)) {
g_error ("Failed to link elements");
return;
}
g_signal_connect (src, "pad-added", G_CALLBACK (listen_pad_added_cb),
NULL);
g_signal_connect (src, "pad-added", G_CALLBACK (record_pad_added_cb),
NULL);
g_object_set (sink, "device", "hw:1", NULL);
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_signal_watch (bus);
g_signal_connect (G_OBJECT (bus), "message", G_CALLBACK (message_cb),
NULL);
gst_object_unref (GST_OBJECT (bus));
gst_element_set_state (pipeline, GST_STATE_PLAYING);
}
What mistake I made in this code?
--
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/Add-or-remove-elements-to-from-a-tee-dynamically-tp4675008p4675019.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.
More information about the gstreamer-devel
mailing list