How to dynamically link to tee after pipeline started using gst_parse_launch
Nick_law
nicholas at umantec.net
Tue Mar 2 11:34:12 UTC 2021
Good afternoon all,
Thanks to @gotsring in this post
http://gstreamer-devel.966125.n4.nabble.com/Is-it-possible-to-dynamically-update-tee-sink-interleave-src-td4696637.html
I have learnt how to unlink and relink pads in a pipeline.
What I would like to do now is start a pipeline with audiotestsrcs connected
to a Fakesink and once the pipeline is started then link the audiotestsrcs
using tees to the corresponding interleave pads.
I am unsure if this is even possible using gst_parse_launch but I am hoping
someone is able to lead me in a direction where I can get access to
interleave and tee pads without having them linked in the original parse
launch string.
I can see that the tee plugin has a num-src-pads property which would allow
to specify the number of pads needed but thereafter I don't know how to
access them. The main problem being that I would hope a tee src pad doesn't
need to be defined with a named pad in the string.
It would also be nice to be able to access individual interleave pads
without creating named pads as well.
i.e i.src_2 or t2_src3 etc just from the named tee and interleave values.
The main idea is to be able to create a multichannel (16 channels +)
pipeline that initially outputs 0 until audio sources are mapped to the
desired channels.
I have a current broken example that shows a little of what I'm trying to do
but obviously missing some core concepts:
```
gst_init(NULL, NULL);
GError* err = NULL;
std::stringstream gst_parse;
//audiotestsrc needed the is-live=true flag added to allow for remapping
and continued playout.
//Currently unsure how that would react with a file player (wavparse and
rawaudioparse)
gst_parse << "interleave name=i ! audioconvert ! wavenc ! filesink
location=test.wav ";
gst_parse << "audiotestsrc is-live=true ! tee name=t1 ";
gst_parse << "audiotestsrc is-live=true wave=2 ! tee name=t2 ";
gst_parse << "audiotestsrc is-live=true wave=4 ! tee name=t3 "; //Silent
wave used as Fakesrc
gst_parse << "t3. ! queue ! volume name=out0 volume=1.0 ! i. ";
gst_parse << "t3. ! queue ! volume name=out1 volume=1.0 ! i. ";
gst_parse << "t3. ! queue ! volume name=out2 volume=1.0 ! i. ";
gst_parse << "t3. ! queue ! volume name=out3 volume=1.0 ! i. ";
gst_parse << "t1. ! queue ! volume name=vol0 volume=1.0 ! fakesink ";
//Ideally this is not needed to start pipeline
gst_parse << "t2. ! queue ! volume name=vol1 volume=1.0 ! fakesink ";
GstElement* pipeline = gst_parse_launch(gst_parse.str().c_str(), &err);
if (err != NULL) {
g_print("Pipeline failed to be created! You did a bad parse!\n");
g_printerr("Error: %s\n", err->message);
return -1;
}
// Get elements by name
GstElement* out0 = gst_bin_get_by_name(GST_BIN(pipeline), "out0");
GstElement* out1 = gst_bin_get_by_name(GST_BIN(pipeline), "out1");
GstElement* out2 = gst_bin_get_by_name(GST_BIN(pipeline), "out2");
GstElement* out3 = gst_bin_get_by_name(GST_BIN(pipeline), "out3");
GstElement* vol0 = gst_bin_get_by_name(GST_BIN(pipeline), "vol0");//Again
ideally not needed
GstElement* vol1 = gst_bin_get_by_name(GST_BIN(pipeline), "vol1");
if (
!out0 ||
!out1 ||
!out2 ||
!out3 ||
!vol0 ||
!vol1) {
g_print("Error getting bins!\n");
return -1;
}
// Get their the sink and src pads that need to be unlinked and re-linked
GstPad* out0_sink_pad = gst_element_get_static_pad(out0, "sink"); //sink
side is where the fakesrc silent wave is conected
GstPad* out1_sink_pad = gst_element_get_static_pad(out1, "sink");
GstPad* out2_sink_pad = gst_element_get_static_pad(out2, "sink");
GstPad* out3_sink_pad = gst_element_get_static_pad(out3, "sink");
GstPad* vol0_src_pad = gst_element_get_static_pad(vol0, "src"); //src side
is where the Fakesink is connected
GstPad* vol1_src_pad = gst_element_get_static_pad(vol1, "src");
if (
!out0_sink_pad ||
!out1_sink_pad ||
!out2_sink_pad ||
!out3_sink_pad ||
!vol0_src_pad ||
!vol1_src_pad) {
g_print("Error getting src pads!\n");
return -1;
}
// I'm not sure that pad order is guaranteed when the pipeline is
constructed,
// meaning interleave pad sink1 might be connected to vol0 instead of vol1
// So, get pads based on peers! peers are the element that the pad is
connected to.
GstPad* fakesrc0_pad = gst_pad_get_peer(out0_sink_pad);
GstPad* fakesrc1_pad = gst_pad_get_peer(out1_sink_pad);
GstPad* fakesrc2_pad = gst_pad_get_peer(out2_sink_pad);
GstPad* fakesrc3_pad = gst_pad_get_peer(out3_sink_pad);
GstPad* fakesink0_pad = gst_pad_get_peer(vol0_src_pad);
GstPad* fakesink1_pad = gst_pad_get_peer(vol1_src_pad);
if (!fakesrc0_pad ||
!fakesrc1_pad ||
!fakesrc2_pad ||
!fakesrc3_pad ||
!fakesink0_pad ||
!fakesink1_pad) {
g_print("Error getting peer pads!\n");
return -1;
}
// Play for a bit
g_print("Playing...\n");
gst_element_set_state(pipeline, GST_STATE_PLAYING);
GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL,
"playing_orig");
g_usleep(2000000);
// Swap around pads
g_print("Rearranging pads...\n");
gst_element_set_state(pipeline, GST_STATE_PAUSED);
gboolean good = TRUE;
good &= gst_pad_unlink(fakesrc0_pad, out0_sink_pad);
good &= gst_pad_unlink(fakesrc1_pad, out1_sink_pad);
good &= gst_pad_unlink(fakesrc2_pad, out2_sink_pad);
good &= gst_pad_unlink(fakesrc3_pad, out3_sink_pad);
good &= gst_pad_unlink(vol0_src_pad, fakesink0_pad);
good &= gst_pad_unlink(vol1_src_pad, fakesink1_pad);
if (!good) {
g_print("Pad unlink was not good!");
REQUIRE(0);
}
// This is where I am unsure how to relink to a tee that hasn't got
a named pad in the original parse launch string.
// The relink won't work as the vol*_src_pads are being relinked to
more than one pad.
good &= gst_pad_link(vol0_src_pad, out0_sink_pad) == GST_PAD_LINK_OK;
good &= gst_pad_link(vol1_src_pad, out1_sink_pad) == GST_PAD_LINK_OK;
good &= gst_pad_link(vol0_src_pad, out2_sink_pad) == GST_PAD_LINK_OK;
good &= gst_pad_link(vol1_src_pad, out3_sink_pad) == GST_PAD_LINK_OK;
//It seems that you MUST reconnect the fakesinks and Fakesrcs or the relink
doesn't play out
good &= gst_pad_link(fakesrc0_pad, fakesink0_pad) == GST_PAD_LINK_OK;
good &= gst_pad_link(fakesrc1_pad, fakesink1_pad) == GST_PAD_LINK_OK;
good &= gst_pad_link(fakesrc2_pad, fakesink0_pad) == GST_PAD_LINK_OK;
good &= gst_pad_link(fakesrc3_pad, fakesink1_pad) == GST_PAD_LINK_OK;
if (!good) {
g_print("Pad relink was not good!");
REQUIRE(0);
}
// Play some more
g_print("Playing more...\n");
gst_element_set_state(pipeline, GST_STATE_PLAYING);
GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL,
"playing_swapped");
g_usleep(2000000);
g_print("Stopping...\n");
//TODO: test this with the hanging fifo issue and see if that stops
gstreamer from hanging
gst_element_send_event(pipeline, gst_event_new_eos());
gst_element_set_state(pipeline, GST_STATE_NULL);
g_print("Done.\n");
```
I hope I have explained my problem clearly and that someone can help?
Thanks so much,
Nick
--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
More information about the gstreamer-devel
mailing list