I'm trying to use GStreamer to play MP4 video from a file. I have managed to play the file using playbin2 and from the command prompt using:
gst-launch filesrc location=bbb.mp4 ! decodebin2 ! autovideosink
I am expecting in the future that I will need to create more complicated pipelines and hence why I'm attempting to 'program' the pipeline. In my program I am attempting to replicate the pipeline above, however I have an issue which I suspect is related to connecting the dynamic or "sometimes" source pad of decodebin2 to the autovideo sink. I am using these elements only to keep things as simple as possible.
static void on_new_decoded_pad(GstElement* object, GstPad* arg0, gboolean arg1, gpointer user_data) { // dynamically connect decoderbin2 src pad to autovideosink sink pad } static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data) { // handle bus messages } int main(int argc, char *argv[]) { GMainLoop *loop; GstElement *pipeline, *source, *decodebin, *videosink; GstBus *bus; gst_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); pipeline = gst_pipeline_new ("pipeline"); source = gst_element_factory_make("filesrc", "source"); decodebin = gst_element_factory_make("decodebin2", "decodebin"); videosink = gst_element_factory_make("autovideosink", "videosink"); /* check elements were created successfully */ if (!pipeline || !source || !decodebin || !videosink) { // Failed to create element. Exit Program return -1; } /* apply properties to elements before adding to pipeline */ gchar * filename = "bbb.mp4"; g_object_set(G_OBJECT(source), "location", filename, NULL); /* add a message handler */ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); gst_bus_add_watch (bus, bus_call, loop); gst_object_unref (bus); /* add elements to pipeline (and bin if necessary) before linking them */ gst_bin_add_many(GST_BIN (pipeline), source, decodebin, videosink, NULL); gst_element_link_pads(source, "src", decodebin, "sink"); /* decodebins src pad is a sometimes pad - it gets created dynamically */ g_signal_connect(decodebin, "new-decoded-pad", G_CALLBACK(on_new_decoded_pad), videosink); /* run pipeline */ gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING); g_main_loop_run(loop); gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL); gst_object_unref (pipeline); return 0; }
What I expect to happen when I run this program, is for the on_new_decoded_pad to get called via a call back function, which is set in the line:
g_signal_connect(decodebin, "new-decoded-pad", G_CALLBACK(on_new_decoded_pad), videosink);
and would allow me to connect the pads appropriately. But it never gets called. In fact the program seems to pass through entirely and then just exit (the main loop does nothing).
I'd really appreciate it if someone could point out what I've done wrong with regards to the callback or explain what else needs to be done in order for this example to play mp4 using the provided elements.
Regards.