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/ _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
May I ask why you would like to use gst_parse_launch for this? Yes, it's
probably possible, but it seems either way you need to hold references to certain elements or pads. I'd wager that it's better to programmatically create elements and save references to them in an array, especially for this amount of manipulation. -- Sent from: http://gstreamer-devel.966125.n4.nabble.com/ _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
Hi @gotsring,
Short answer legacy and time. I am trying to get the go ahead to remove the dependency on gst_parse_launch but will need a considerable amount of time to remove, refactor and learn everything that is needed to construct the pipelines fully using the gstreamer api. So still would like to know how to use gst_parse_launch in the event I don't have enough time to re-implement. regards, Nick gotsring wrote > May I ask why you would like to use gst_parse_launch for this? Yes, it's > probably possible, but it seems either way you need to hold references to > certain elements or pads. > > I'd wager that it's better to programmatically create elements and save > references to them in an array, especially for this amount of > manipulation. -- Sent from: http://gstreamer-devel.966125.n4.nabble.com/ _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
Tee and interleave both have request pads, meaning you can just request a new
pad without necessarily pre-allocating them. So for example, if you find the interleave element, you can request a new sink pad using gst_element_get_request_pad(interleave, "sink_%u") Wasn't quite sure what your intended use case is, but I altered the example code to create a pipeline that's not completely linked, and then grabs references to interleave and the volume elements to finish linking everything together before playing. dynamic_interleave_link.cpp <http://gstreamer-devel.966125.n4.nabble.com/file/t379531/dynamic_interleave_link.cpp> I also noticed just now that interleave has a channel-positions property to (I think) rearrange which inputs map to which channel. Maybe this is useful to you? https://gstreamer.freedesktop.org/documentation/interleave/interleave.html?gi-language=c#interleave:channel-positions Hope this helps! -- Sent from: http://gstreamer-devel.966125.n4.nabble.com/ _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
Free forum by Nabble | Edit this page |