9

I have a Qt application which does GStreamer-related stuff in a separate thread. Although I think I've followed the rules for setting up signal callbacks, the callback function I've specified doesn't seem to be being called.

The callback function follows, all it attempts to do is log something to the console for debugging:

static gboolean Cb(GstBus *bus, GstMessage *msg, gpointer data)
{
    std::cout << "g_sig, bus = " << (void*)bus
              << ", msg = "      << (void*)msg
              << ", data = "     << (void*)data
              << std::endl;
    return TRUE;
}

The sequence I am using to start and monitor the stream (a live RTSP/H.264 feed from an IP camera) is:

GstElement *playBin = gst_parse_launch("<gstreamer pipeline>");
GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(playBin));
gst_bus_add_signal_watch(bus);
g_signal_connect(bus, "message::state-changed", (GCallback)Cb, NULL);
gst_element_set_state(playBin, GST_STATE_PLAYING);

GMainLoop *mainLoop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(mainLoop);

Now the stream is actually playing (the video appears) so I'm assuming there's no issue there. However, I expect that a status change message should be posted when the pipeline starts playing. This doesn't appear to be happening since I'm not seeing the output from Cb().

I get no output even when I also catch the message::eos, message::error and message::element signals as well.

I'm not sure that this would be a problem but, just in case, the code above is slightly simplified. There are actually two streams being played so the first snippet of code above happens twice, once for each playbin (the sequence is accurate for each, I just saw no need to complicate the code unnecessarily).

Then the main loop is created and run.

As stated, I'm seeing no output from the callback function, so where are my messages going?

Addendum: For what it's worth, I've also tried the gst_bus_add_watch method to capture all messages rather than specific signals, but still nothing shows up. I should also mention that, being a Qt application, I have no gtk_init in the code - I simply call gst_init from the main thread.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 1
    I assume you are checking the return values of all called functions (especially of g_signal_connect) in real code? – Silicomancer Nov 25 '16 at 23:00
  • It's possible stdout is being redirected for some reason. Have you tried placing in a breakpoint in the `Cb()` function? – MrEricSir Nov 27 '16 at 02:38
  • I had the same issue. I think the problem comes from Gstreamer running in a thread. This helped me to solve my problem: http://gstreamer-devel.966125.n4.nabble.com/When-not-using-the-default-GMainContext-td972735.html – Elieva Jul 02 '20 at 14:45

1 Answers1

6

My knowledge of gstreamer is limited, I messed around with it long time ago.

I made a little test, and this seems to work:

#include <stdio.h>
#include <gstreamer-1.0/gst/gst.h>

static gboolean Cb(GstBus *bus, GstMessage *msg, gpointer data)
{
        printf("g_sig, bus = %x, msg = %s, data = %x\n",
          bus,
          gst_message_type_get_name(GST_MESSAGE_TYPE(msg)),
          data);

        return TRUE;
}

int main(int argc, char *argv[]) {
        GstElement *pipeline;
        GstBus *bus;
        GstMessage *msg;

        /* Initialize GStreamer */
        gst_init (&argc, &argv);

        /* Build the pipeline */
        pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);

        /* Wait until error or EOS */
        bus = gst_element_get_bus (pipeline);

        /* use the sync signal handler to link elements while the pipeline is still
         * doing the state change */
        gst_bus_set_sync_handler (bus, gst_bus_sync_signal_handler, pipeline, NULL);
        g_object_connect (bus, "signal::sync-message::state-changed", G_CALLBACK (Cb), pipeline, NULL);

        /* Start playing */
        gst_element_set_state (pipeline, GST_STATE_PLAYING);

        msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

        /* Free resources */
        if (msg != NULL)
                gst_message_unref (msg);

        gst_object_unref (bus);
        gst_element_set_state (pipeline, GST_STATE_NULL);
        gst_object_unref (pipeline);

        return 0;
}

But while message::state-changed:

A message has been posted on the bus. This signal is emitted from a GSource added to the mainloop. this signal will only be emitted when there is a mainloop running.

signal::sync-message::state-changed instead:

A message has been posted on the bus. This signal is emitted from the thread that posted the message so one has to be careful with locking.

So sync-message is emitted also outside the mainloop.

The docs for both signals.

Marcs
  • 3,768
  • 5
  • 33
  • 42
  • I am not sure this answer helped OP, but as there are no comments mentioned otherwise , I am awarding bounty to your answer. Thanks for your great effort. – R__raki__ Dec 01 '16 at 11:55