stuck on eos send to pipeline

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

stuck on eos send to pipeline

umit
Hi,

This is my first post to the mailing list so if something's wrong please let
me know.

I googled and searched mailing list for similar problems, tried lots of
things but could not find a solution to my problem.
I have a very simple pipeline as below:

videotestsrc ! tee name=t t. ! queue ! autovideosink

I know tee is not required here but this is a test app for my future
development.

I start, stop display and quit application via command line. When I run the
app, nothing is displayed initially as per my design. Problem is, when I try
to quit the app when it is not in displaying state, ending the app via 'q'
button not works. program is stuck on line:

gst_element_send_event(pipeline, gst_event_new_eos());

no eos message is received on message bus callback. My guess is something
goes wrong when I block tee_src pad.

To test, just run the app and press 'q' on command line. Can someone please
check?

Below is the code:



#include <gst/gst.h>

#include <iostream>
#include <thread>

using namespace std;

static gboolean
message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
{
    g_message ("get message %s", gst_structure_get_name
(gst_message_get_structure(message)));

    GMainLoop* loop = (GMainLoop*)user_data;
    switch (GST_MESSAGE_TYPE (message)) {
    case GST_MESSAGE_ERROR:{
        //
        cout << "error message received" << endl;
        break;
    }
    case GST_MESSAGE_WARNING:{
        //
        cout << "warning message received" << endl;
        break;
    }
    case GST_MESSAGE_EOS: {
        //
        cout << "eos message received" << endl;
        g_main_loop_quit (loop);
        break;
    }
    case GST_MESSAGE_ELEMENT: {
        //
        cout << "element message received" << endl;

        const GstStructure *s = gst_message_get_structure (message);

        if (gst_structure_has_name (s, "GstBinForwarded"))
        {
            GstMessage *forward_msg = NULL;

            gst_structure_get (s, "message", GST_TYPE_MESSAGE, &forward_msg,
NULL);
            if (GST_MESSAGE_TYPE (forward_msg) == GST_MESSAGE_EOS)
            {
                g_print ("EOS from element %s\n",
                        GST_OBJECT_NAME (GST_MESSAGE_SRC (forward_msg)));
                cout << "forwarded eos message received" << endl;
                g_main_loop_quit (loop);
            }
            gst_message_unref (forward_msg);
        }

        break;
    }
    default:
        break;
    }

    return TRUE;
}

// TODO: TEST:
GstPad *tee_pad;
GstPad *queue_pad;
GstElement *pipeline;
GstElement *queue;
GstElement *sink;
GstElement *tee;

static GstPadProbeReturn
event_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
{
    GST_INFO_OBJECT(pad, "event to pad");

    if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) != GST_EVENT_EOS)
        return GST_PAD_PROBE_PASS;

    gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info));

    gst_element_set_state(sink, GST_STATE_NULL);
    gst_element_set_state(queue, GST_STATE_NULL);

    gst_bin_remove_many(GST_BIN(pipeline), queue, sink, nullptr);

    return GST_PAD_PROBE_DROP;
}

static GstPadProbeReturn
pad_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
{
    GST_INFO_OBJECT(pad, "pad is blocked now");
    cout << "pad is blocked now" << endl;

    gst_pad_add_probe (queue_pad, (GstPadProbeType)(GST_PAD_PROBE_TYPE_BLOCK
|
                       GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM), event_probe_cb,
nullptr, nullptr);

    gst_pad_send_event(queue_pad, gst_event_new_eos());

    return GST_PAD_PROBE_OK;
}

// videotestsrc ! tee name=t t. ! queue ! autovideosink
int main(int argc, char *argv[])
{
    gst_init (&argc, &argv);

    gst_debug_set_default_threshold(GST_LEVEL_INFO);

    /*GstElement **/pipeline = gst_pipeline_new("test_pipeline");
    g_object_set (pipeline, "message-forward", TRUE, NULL);

    GstElement *src = gst_element_factory_make("videotestsrc", nullptr);
    //g_object_set (src, "is-live", TRUE, NULL);

    tee = gst_element_factory_make("tee", nullptr);
    queue = gst_element_factory_make("queue", nullptr);
    sink = gst_element_factory_make("autovideosink", nullptr);
    g_object_set (sink, "sync", false, NULL);

    if( !pipeline || !src || !tee || !queue || !sink ) {
        cout << "elements could not be created!" << endl;
        return -1;
    }

    // add only src & tee to pipeline
    gst_bin_add_many(GST_BIN(pipeline), src, tee, nullptr);
    // link src, tee
    if(!gst_element_link_many(src, tee, nullptr)) {
        cout << "src tee link error" << endl;
        return -1;
    }

    /*GstPad **/tee_pad = gst_element_get_request_pad(tee, "src_%u");
    /*GstPad **/queue_pad = gst_element_get_static_pad(queue, "sink");

    //gulong probe_id = 0;
    // block tee src pad:
    gulong probe_id = gst_pad_add_probe (tee_pad,
GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
                                         nullptr, nullptr, nullptr);
    gst_element_set_state (pipeline, GST_STATE_PLAYING);

    GMainLoop *loop = g_main_loop_new (NULL, FALSE);

    gst_bus_add_watch (GST_ELEMENT_BUS (pipeline), message_cb, loop);

    thread t([loop](){
        g_main_loop_run (loop);
    });

    while(true) {
        char c;
        cin >> c;
        if(c == 'r') {
            gst_bin_add_many(GST_BIN(pipeline), (GstElement*)gst_object_ref
(queue), (GstElement*)gst_object_ref (sink), nullptr);

            gst_element_sync_state_with_parent(queue);
            gst_element_sync_state_with_parent(sink);

            // link queue, sink
            if(!gst_element_link_many(tee, queue, sink, nullptr)) {
                cout << "tee queue sink link error" << endl;
                return -1;
            }

            gst_pad_remove_probe(tee_pad, probe_id);

            //probe_id = 0;
        } else if(c == 's') {
            probe_id = gst_pad_add_probe (tee_pad,
GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
                                          pad_probe_cb, nullptr, nullptr);
        } else if(c == 'q') {
            //gst_debug_set_default_threshold(GST_LEVEL_MAX);
            gst_element_send_event(pipeline, gst_event_new_eos());
            break;
        }
    }

    t.join();


    return 0;
}


Below is the command line output when I set debug threashold to max after
pressing 'q' to exit app:

0:00:02.132823400 13916 00000201FD013F90 DEBUG              GST_EVENT
gstevent.c:306:gst_event_new_custom: creating new event 00000201FD1F11C0 eos
28174
0:00:02.134604600 13916 00000201FD013F90 DEBUG       GST_ELEMENT_PADS
gstelement.c:1856:gst_element_send_event: send eos event on element
test_pipeline
0:00:02.135451500 13916 00000201FD013F90 DEBUG                    bin
gstbin.c:3133:gst_bin_send_event:<test_pipeline> Sending eos event to src
children
0:00:02.136695000 13916 00000201FD013F90 DEBUG             GST_STATES
gstbin.c:2030:bin_element_is_src:<test_pipeline> child tee0 is not src
0:00:02.137556600 13916 00000201FD013F90 DEBUG             GST_STATES
gstbin.c:2030:bin_element_is_src:<test_pipeline> child videotestsrc0 is src
0:00:02.138103500 13916 00000201FD013F90 TRACE        GST_REFCOUNTING
gstminiobject.c:355:gst_mini_object_ref: 00000201FD1F11C0 ref 1->2
0:00:02.138812400 13916 00000201FD013F90 DEBUG       GST_ELEMENT_PADS
gstelement.c:1856:gst_element_send_event: send eos event on element
videotestsrc0
0:00:02.140035900 13916 00000201FD013F90 DEBUG                basesrc
gstbasesrc.c:1786:gst_base_src_send_event:<videotestsrc0> handling event
00000201FD1F11C0 eos event: 00000201FD1F11C0, time 99:99:99.999999999,
seq-num 21, (NULL)
0:00:02.140539300 13916 00000201FD013F90 DEBUG                basesrc
gstbasesrc.c:3679:gst_base_src_set_flushing:<videotestsrc0> flushing 1        
<== stuck here



Thanks in advance,

Umit



--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel