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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With