paxdiablo
paxdiablo

Reputation: 882078

GStreamer appears to be not calling my callbacks

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.

Upvotes: 9

Views: 4672

Answers (1)

Marcs
Marcs

Reputation: 3838

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.

Upvotes: 6

Related Questions