stuck on eos send to pipeline

umit sivrumit at yahoo.com
Thu Aug 22 11:39:49 UTC 2019


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/


More information about the gstreamer-devel mailing list