[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