State change hangs if pipeline was changed in PAUSED

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

State change hangs if pipeline was changed in PAUSED

Alexey Chernov
Hello,

I've already posted a couple of questions here concerning my case with
duplicated video stream. Now it works quite right but some strange
behavior still exists.

When I change the pipeline while it's in PAUSED state and then try to
resume it (setting state PLAYING with gst_element_set_state) it never
continues to play anymore. gst_element_set_state() returns
GST_STATE_CHANGE_ASYNC and gst_element_get_state() (as in
documentation) waits for change to complete forever.

Here's a test program:

#include <glib.h>
#include <gst/gst.h>

GstElement *_pipeline, *_fakesink, *_remotesink, *_mpoint, *_queue1,
*_queue2, *_videobin, *_pipe, *gdppay;

void create_pipeline_bin()
{
        GstElement *tee, *queue1, *queue2, *valve, *xvimagesink, *audiosink;

        _pipeline      = gst_element_factory_make("playbin",  NULL);

        tee = gst_element_factory_make("tee",  NULL);
        xvimagesink   = gst_element_factory_make("ximagesink", NULL);

        GstPad* pad;

        _videobin = gst_bin_new("videobin");
        _queue1 = queue1 = gst_element_factory_make("queue", NULL);
        _queue2 = queue2 = gst_element_factory_make("queue", NULL);
        valve                   = gst_element_factory_make("valve", NULL);

        _fakesink = gst_element_factory_make("fakesink", NULL);
        audiosink               = gst_element_factory_make("fakesink", NULL);

        gst_object_ref(_fakesink);

        _mpoint = valve;

        gst_bin_add_many(GST_BIN(_videobin), tee, queue1, queue2, valve,
xvimagesink, _fakesink, NULL);

        gst_element_link_many(tee, queue1, xvimagesink, NULL);
        gst_element_link_many(tee, queue2, valve, _fakesink, NULL);
        pad = gst_element_get_static_pad (tee, "sink");
        gst_element_add_pad (_videobin, gst_ghost_pad_new ("sink", pad));
        gst_object_unref (GST_OBJECT (pad));

        g_object_set(G_OBJECT (_pipeline), "uri", "file:///home/alex/test.mp4", NULL);
        g_object_set(G_OBJECT (_pipeline), "video-sink", _videobin, NULL);
        g_object_set(G_OBJECT (_pipeline), "audio-sink", audiosink, NULL);

        gst_element_set_state (_pipeline, GST_STATE_PLAYING);
}

void create_remote_bin()
{
                GstElement *videomixer, *ffmpegcolorspace;
                GstPad* pad;

                videomixer = gst_element_factory_make("videomixer",  NULL);
                ffmpegcolorspace = gst_element_factory_make("ffmpegcolorspace",  NULL);
                _pipe = gst_element_factory_make("xvimagesink",  NULL);

                _remotesink = gst_bin_new("vmixerbin");
                gst_bin_add_many(GST_BIN(_remotesink), videomixer, ffmpegcolorspace,
_pipe, NULL);
                gst_element_link_many(videomixer, ffmpegcolorspace, _pipe, NULL);
                pad = gst_element_get_request_pad (videomixer, "sink_%d");
                gst_element_add_pad (_remotesink, gst_ghost_pad_new ("sink", pad));
                gst_object_unref (GST_OBJECT (pad));

                gst_object_ref(_remotesink);
}

void connect_remote_client()
{
        if (_remotesink && _mpoint && _videobin)
        {
                GstState state = GST_STATE(_pipeline);

                gst_element_unlink(_mpoint, _fakesink);
                gst_bin_remove(GST_BIN(_videobin), _fakesink);
                gst_element_set_state (_fakesink, GST_STATE_NULL);

                gst_bin_add(GST_BIN(_videobin), _remotesink);
                gst_element_link(_mpoint, _remotesink);

                gst_element_sync_state_with_parent(_remotesink);

                gst_element_set_state (_pipeline, state);
        }
}

void disconnect_remote_client()
{
        if (_remotesink && _mpoint && _videobin && _fakesink)
        {
                GstState state = GST_STATE(_pipeline);
                gst_element_unlink(_mpoint, _remotesink);
                gst_bin_remove(GST_BIN(_videobin), _remotesink);
                gst_element_set_state (_remotesink, GST_STATE_NULL);

                gst_bin_add(GST_BIN(_videobin), _fakesink);
                gst_element_link(_mpoint, _fakesink);

                gst_element_sync_state_with_parent(_fakesink);

                gst_element_set_state (_pipeline, state);
        }
}

void pause_pipeline()
{
        gst_element_set_state(_pipeline, GST_STATE_PAUSED);
}

void play_pipeline()
{
        gst_element_set_state(_pipeline, GST_STATE_PLAYING);
}

gboolean connect_callback(gpointer)
{
        connect_remote_client();
        return FALSE;
}

gboolean disconnect_callback(gpointer)
{
        disconnect_remote_client();
        return FALSE;
}

gboolean pause_callback(gpointer)
{
        pause_pipeline();
        return FALSE;
}

gboolean play_callback(gpointer)
{
        play_pipeline();
        return FALSE;
}

int main(int argc, char *argv[])
{
        GMainLoop* loop = g_main_loop_new (NULL, FALSE);
        gst_init(&argc, &argv);

        create_remote_bin();
        create_pipeline_bin();

        g_timeout_add(7000, connect_callback, NULL);
        g_timeout_add(16000, pause_callback, NULL);
        g_timeout_add(17000, disconnect_callback, NULL);
        g_timeout_add(18000, play_callback, NULL);

        g_main_loop_run (loop);
        return 0;
}

Second xvimagesink connects successfully in 7 secs after start. Then
in 16 sec the pipeline is set to PAUSED and in 17 sec second video
sink is disconnected. But in 18 sec pipeline doesn't want to get to
PLAYING state anymore.
No messages is posted to output after trying to set the pipeline
PLAYING state, even on DEBUG log level. One certain message is posted
before it:

GST_STATES gstelement.c:2515:gst_element_set_state_func:<playbin0>
element was busy with async state change

I should also notice that if I make pipeline changes in PLAYING state
everything work flawlessly.

Is it bug in GStreamer or should I make state change any other way?

------------------------------------------------------------------------------
What happens now with your Lotus Notes apps - do you make another costly
upgrade, or settle for being marooned without product support? Time to move
off Lotus Notes and onto the cloud with Force.com, apps are easier to build,
use, and manage than apps on traditional platforms. Sign up for the Lotus
Notes Migration Kit to learn more. http://p.sf.net/sfu/salesforce-d2d
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel