how to link multiple filesinks to a output-selector before playing pipeline

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

how to link multiple filesinks to a output-selector before playing pipeline

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.

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

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;
}
Reply | Threaded
Open this post in threaded view
|

Re: how to link multiple filesinks to a output-selector before playing pipeline

Stefan Sauer
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;
> }


------------------------------------------------------------------------------
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2 & L3.
Spend less time writing and  rewriting code and more time creating great
experiences on the web. Be a part of the beta today
http://p.sf.net/sfu/msIE9-sfdev2dev
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: how to link multiple filesinks to a output-selector before playing pipeline

shuyufu
Hi,

It works.

Thank you very much