[gst-devel] how to link multiple filesinks to a output-selector before playing pipeline
Stefan Kost
ensonic at hora-obscura.de
Sun Nov 21 14:04:59 CET 2010
Am 20.11.2010 09:42, schrieb shuyufu:
>
> Hi guys,
>
> I was trying to create a pipeline like this
> filesink
> /
> filesrc -- output-selector
> \
> filesink
>
> But, I can't link both filesinks to the output-selector before the pipeline
> is PLAYED.
There is a catch, please look at the example in:
gst-plugins-bad/tests/icles/output-selector-test.c
The 2nd sink is blocking on preroll. Dunno if output-selector should/could do
something to make it preroll. The example uses a live-src as a trick.
>
> However, I can link a single filesink to the output-selector and then link
> another after the state of pipleline is PLAYING of course.
>
> I use gst-launch to verify this issue but it stucked also. My command like
> this,
> gst-launch filesrc location=/dev/zero ! output-selector name=selector
> selector. ! filesink location=a.dat selector. ! filesink location=b.dat
>
this one works:
gst-launch fakesrc is-live=true ! output-selector name=selector selector. !
fakesink selector. ! fakesink
Stefan
> In the last part of this post is the source code for your reference.
>
> I have tried to google this issue but nothing found. Is there anybody know
> what's wrong to my pipeline (code)?
>
> Thanks for your time and sorry for my poor writing.
>
> #include <gst/gst.h>
>
> GstElement *pipeline = NULL;
> GstElement *file_src = NULL;
> GstElement *output_selector = NULL;
> GstElement *file_sink_a = NULL;
> GstElement *file_sink_b = NULL;
> GstPad *srcpad_a = NULL;
> GstPad *srcpad_b = NULL;
>
> static gboolean switch_file_a (gpointer data);
> static gboolean switch_file_b (gpointer data);
>
> static gboolean switch_file_a (gpointer data)
> {
> g_object_set(G_OBJECT(output_selector), "active-pad", srcpad_a, NULL);
>
> g_timeout_add(5 * 1000, (switch_file_b), NULL);
>
> return FALSE;
> }
>
> static gboolean switch_file_b (gpointer data)
> {
> g_object_set(G_OBJECT(output_selector), "active-pad", srcpad_b, NULL);
>
> g_timeout_add(5 * 1000, (switch_file_a), NULL);
>
> return FALSE;
> }
>
> static gboolean create_file_b (gpointer data)
> {
> GstPad *sinkpad = NULL;
> GstPadLinkReturn link_ret;
>
> gst_bin_add_many (GST_BIN (pipeline), file_sink_b, NULL);
>
> gst_element_set_state (file_sink_b, GST_STATE_PLAYING);
>
> srcpad_b = gst_element_get_request_pad(output_selector, "src%d");
> sinkpad = gst_element_get_static_pad(file_sink_b, "sink");
> link_ret = gst_pad_link(srcpad_b, sinkpad);
> if (GST_PAD_LINK_FAILED(link_ret)) {
> g_print("linking filesink_b failed %d\n", link_ret);
> }
> gst_object_unref(GST_OBJECT(sinkpad));
>
> g_timeout_add(5 * 1000, switch_file_b, NULL);
>
> return FALSE;
> }
>
> static gboolean message_handler (GstBus *bus, GstMessage *message, gpointer
> data)
> {
> switch (GST_MESSAGE_TYPE (message))
> {
> case GST_MESSAGE_STATE_CHANGED:
> {
> GstState old_state, new_state;
>
> gst_message_parse_state_changed(message, &old_state, &new_state,
> NULL);
>
> g_print("Element %s changed state from %s to %s.\n",
> GST_OBJECT_NAME(message->src),
> gst_element_state_get_name(old_state),
> gst_element_state_get_name(new_state));
> if (g_strcmp0("my-pipeline", GST_OBJECT_NAME(message->src)) == 0
> && new_state == GST_STATE_PLAYING)
> {
> create_file_b(NULL);
> return FALSE;
> }
> break;
> }
> default:
> break;
> }
>
> return TRUE;
> }
>
> int main (int argc, char** argv)
> {
> GMainLoop *loop = NULL;
> GOptionContext *ctx = NULL;
> GError *err = NULL;
> GstBus *bus = NULL;
> GstPad *sinkpad = NULL;
> GstPadLinkReturn link_ret;
>
> if (!g_thread_supported ())
> g_thread_init (NULL);
>
> ctx = g_option_context_new (" output-selector test application");
> g_option_context_add_group (ctx, gst_init_get_option_group ());
> if (!g_option_context_parse (ctx, &argc, &argv, &err))
> {
> g_print ("Failed to initialize: %s\n", err->message);
> g_error_free (err);
> return 1;
> }
>
> loop = g_main_loop_new (NULL, FALSE);
>
> pipeline = gst_pipeline_new ("my-pipeline");
>
> bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
> gst_bus_add_watch(bus, message_handler, NULL);
> gst_object_unref(bus);
>
> file_src = gst_element_factory_make ("filesrc", NULL);
> g_object_set (G_OBJECT (file_src), "location", "/dev/zero", NULL);
>
> output_selector = gst_element_factory_make ("output-selector", NULL);
>
> file_sink_a = gst_element_factory_make ("filesink", NULL);
> g_object_set (G_OBJECT (file_sink_a), "location", "/home/bobby/a.dat",
> NULL);
>
> file_sink_b = gst_element_factory_make ("filesink", NULL);
> g_object_set (G_OBJECT (file_sink_b), "location", "/home/bobby/b.dat",
> NULL);
>
> gst_bin_add_many (GST_BIN (pipeline), file_src, output_selector,
> file_sink_a, file_sink_b, NULL);
>
> srcpad_a = gst_element_get_request_pad (output_selector, "src%d");
> sinkpad = gst_element_get_static_pad (file_sink_a, "sink");
> link_ret = gst_pad_link (srcpad_a, sinkpad);
> if (GST_PAD_LINK_FAILED (link_ret))
> {
> g_error ("linking filesink_a fail\n");
> }
> gst_object_unref (GST_OBJECT (sinkpad));
>
> srcpad_b = gst_element_get_request_pad (output_selector, "src%d");
> sinkpad = gst_element_get_static_pad (file_sink_b, "sink");
> link_ret = gst_pad_link (srcpad_b, sinkpad);
> if (GST_PAD_LINK_FAILED (link_ret))
> {
> g_error ("linking filesink_b fail\n");
> }
> gst_object_unref (GST_OBJECT (sinkpad));
>
> gst_element_link_many (file_src, output_selector, NULL);
>
> gst_element_set_state (pipeline, GST_STATE_PLAYING);
>
> g_main_loop_run (loop);
>
> return 0;
> }
More information about the gstreamer-devel
mailing list