From ac162b0f782ce2dae0bdf654caf40645ed35374f Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 20 Jul 2006 10:42:21 +0000 Subject: [PATCH] gst/playback/test.c: Example of a small audio/video player using decodebin. Original commit message from CVS: * gst/playback/test.c: (gen_video_element), (gen_audio_element), (cb_newpad), (main): Example of a small audio/video player using decodebin. --- ChangeLog | 6 ++ gst/playback/test.c | 168 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 116 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2226e1e..b272f76 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2006-07-20 Wim Taymans + + * gst/playback/test.c: (gen_video_element), (gen_audio_element), + (cb_newpad), (main): + Example of a small audio/video player using decodebin. + 2006-07-20 Stefan Kost * gst-libs/gst/riff/riff-ids.h: diff --git a/gst/playback/test.c b/gst/playback/test.c index 31df582..6344145 100644 --- a/gst/playback/test.c +++ b/gst/playback/test.c @@ -1,5 +1,6 @@ /* GStreamer * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2006> Wim Taymans * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,12 +22,15 @@ #endif #include +static GMainLoop *loop; + static GstElement * gen_video_element () { GstElement *element; GstElement *conv; GstElement *sink; + GstPad *pad; element = gst_bin_new ("vbin"); conv = gst_element_factory_make ("ffmpegcolorspace", "conv"); @@ -36,8 +40,9 @@ gen_video_element () gst_bin_add (GST_BIN (element), sink); gst_element_link_pads (conv, "src", sink, "sink"); - gst_element_add_pad (element, - gst_ghost_pad_new ("sink", gst_element_get_pad (conv, "sink"))); + pad = gst_element_get_pad (conv, "sink"); + gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); return element; } @@ -48,6 +53,7 @@ gen_audio_element () GstElement *element; GstElement *conv; GstElement *sink; + GstPad *pad; element = gst_bin_new ("abin"); conv = gst_element_factory_make ("audioconvert", "conv"); @@ -57,83 +63,129 @@ gen_audio_element () gst_bin_add (GST_BIN (element), sink); gst_element_link_pads (conv, "src", sink, "sink"); - gst_element_add_pad (element, - gst_ghost_pad_new ("sink", gst_element_get_pad (conv, "sink"))); + pad = gst_element_get_pad (conv, "sink"); + gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); return element; } +static void +cb_newpad (GstElement * decodebin, GstPad * pad, gboolean last, gpointer data) +{ + GstCaps *caps; + GstStructure *str; + GstPad *sinkpad; + GstElement *sink; + GstElement *pipeline; + const gchar *name; + GstStateChangeReturn ret; + GstPadLinkReturn lret; + + /* check media type */ + caps = gst_pad_get_caps (pad); + str = gst_caps_get_structure (caps, 0); + + name = gst_structure_get_name (str); + g_print ("name: %s\n", name); + + if (g_strrstr (name, "audio")) { + sink = gen_audio_element (); + } else if (g_strrstr (name, "video")) { + sink = gen_video_element (); + } else { + sink = NULL; + } + gst_caps_unref (caps); + + if (sink) { + pipeline = GST_ELEMENT_CAST (data); + + /* add new sink to the pipeline */ + gst_bin_add (GST_BIN_CAST (pipeline), sink); + + /* set the new sink tp PAUSED as well */ + ret = gst_element_set_state (sink, GST_STATE_PAUSED); + if (ret == GST_STATE_CHANGE_FAILURE) + goto state_error; + + /* get the ghostpad of the sink bin */ + sinkpad = gst_element_get_pad (sink, "sink"); + + /* link'n'play */ + lret = gst_pad_link (pad, sinkpad); + if (lret != GST_PAD_LINK_OK) + goto link_failed; + + gst_object_unref (sinkpad); + } + return; + + /* ERRORS */ +state_error: + { + gst_bin_remove (GST_BIN_CAST (pipeline), sink); + g_warning ("could not change state of new sink (%d)", ret); + return; + } +link_failed: + { + g_warning ("could not link pad and sink (%d)", lret); + return; + } +} + gint main (gint argc, gchar * argv[]) { - GstElement *player; + GstElement *pipeline, *filesrc, *decodebin; GstStateChangeReturn res; - gint streams; - GList *streaminfo; - GList *s; gst_init (&argc, &argv); - player = gst_element_factory_make ("playbin", "player"); - g_assert (player); + pipeline = gst_pipeline_new ("pipeline"); + + filesrc = gst_element_factory_make ("filesrc", "filesrc"); + g_assert (filesrc); + decodebin = gst_element_factory_make ("decodebin", "decodebin"); + g_assert (decodebin); + + g_signal_connect (G_OBJECT (decodebin), "new-decoded-pad", + G_CALLBACK (cb_newpad), pipeline); - g_object_set (G_OBJECT (player), "uri", argv[1], NULL); + gst_bin_add_many (GST_BIN (pipeline), filesrc, decodebin, NULL); + gst_element_link (filesrc, decodebin); - res = gst_element_set_state (player, GST_STATE_PAUSED); - if (res != GST_STATE_CHANGE_SUCCESS) { + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + exit (-1); + } + g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); + + /* set to paused, decodebin will autoplug and signal new_pad callbacks */ + res = gst_element_set_state (pipeline, GST_STATE_PAUSED); + if (res == GST_STATE_CHANGE_FAILURE) { g_print ("could not pause\n"); return -1; } - /* get info about the stream */ - g_print ("stream info:\n"); - g_object_get (G_OBJECT (player), "nstreams", &streams, NULL); - g_print (" number of streams: %d\n", streams); - g_object_get (G_OBJECT (player), "stream-info", &streaminfo, NULL); - - for (s = streaminfo; s; s = g_list_next (s)) { - GObject *obj = G_OBJECT (s->data); - int type; - GstPad *srcpad, *sinkpad; - GstElement *sink; - gboolean res; - - g_object_get (obj, "type", &type, NULL); - g_print (" type: %d\n", type); - g_object_get (obj, "pad", &srcpad, NULL); - g_print (" pad: %p\n", srcpad); - - if (type == 1) { - sink = gen_audio_element (); - } else if (type == 2) { - sink = gen_video_element (); - } else { - g_warning ("unknown stream found"); - continue; - } - - gst_bin_add (GST_BIN (player), sink); - sinkpad = gst_element_get_pad (sink, "sink"); - res = gst_pad_link (srcpad, sinkpad); - if (!res) { - GstCaps *caps; - gchar *capsstr; - - caps = gst_pad_get_caps (srcpad); - capsstr = gst_caps_to_string (caps); - g_warning ("could not link %s", capsstr); - g_free (capsstr); - gst_caps_unref (caps); - } - //g_signal_emit_by_name (G_OBJECT (player), "link_stream", obj, sinkpad); + /* wait for paused to complete */ + res = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + if (res == GST_STATE_CHANGE_FAILURE) { + g_print ("could not pause\n"); + return -1; } - /* set effects sinks */ - res = gst_element_set_state (player, GST_STATE_PLAYING); - if (res != GST_STATE_CHANGE_SUCCESS) { + /* play, now all the sinks are added to the pipeline and are prerolled and + * ready to play. */ + res = gst_element_set_state (pipeline, GST_STATE_PLAYING); + if (res == GST_STATE_CHANGE_FAILURE) { g_print ("could not play\n"); return -1; } - //gst_main (); + + /* go in the mainloop now */ + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); return 0; } -- 2.7.4