#include #include /* * Global objects are usually a bad thing. For the purpose of this * example, we will use them, however. */ /* create elements */ GstElement *pipeline, *audio_bin, *video_bin; GstElement *src, *demux, *a_decoder, *a_convert, *v_decoder, *v_convert; GstElement *audiosink, *videosink,*a_demux, *v_demux; GstElement *a_queue, *v_queue; GstPad *seekable, *pad; static GList *seekable_pads = NULL; static GList *rate_pads = NULL; static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data) { GMainLoop *loop = (GMainLoop *) data; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: g_print ("End-of-stream\n"); g_main_loop_quit (loop); break; case GST_MESSAGE_ERROR: { gchar *debug; GError *err; gst_message_parse_error (msg, &err, &debug); g_free (debug); g_print ("Error: %s\n", err->message); g_error_free (err); g_main_loop_quit (loop); break; } default: break; } return TRUE; } static void new_pad (GstElement *element, GstPad *pad, gpointer data) { GstPad *sinkpad; /* We can now link this pad with the video decoder */ g_print ("Dynamic pad created, linking parser/decoder\n"); sinkpad = gst_element_get_pad (a_decoder, "sink"); gst_pad_link (pad, sinkpad); gst_object_unref (sinkpad); } typedef struct { const gchar *padname; GstPad *target; GstElement *bin; } dyn_link; static GstElement * gst_element_factory_make_or_warn (gchar * type, gchar * name) { GstElement *element = gst_element_factory_make (type, name); if (!element) { g_warning ("Failed to create element %s of type %s", name, type); } return element; } static void dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data) { gchar *padname; dyn_link *connect = (dyn_link *) data; padname = gst_pad_get_name (newpad); if (connect->padname == NULL || !strcmp (padname, connect->padname)) { if (connect->bin) gst_bin_add (GST_BIN (pipeline), connect->bin); gst_pad_link (newpad, connect->target); //seekable_pads = g_list_prepend (seekable_pads, newpad); rate_pads = g_list_prepend (rate_pads, newpad); } g_free (padname); } static void setup_dynamic_link(GstElement * element, const gchar * padname, GstPad * target, GstElement * bin) { dyn_link *connect; connect = g_new0 (dyn_link, 1); connect->padname = g_strdup (padname); connect->target = target; connect->bin = bin; g_signal_connect (G_OBJECT (element), "pad-added", G_CALLBACK (dynamic_link),connect); } int main (int argc, char *argv[]) { GMainLoop *loop; GstBus *bus; /* initialize GStreamer */ gst_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); /* check input arguments */ if (argc != 2) { g_print ("Usage: %s \n", argv[0]); return -1; } pipeline = gst_pipeline_new ("Video-player"); src = gst_element_factory_make_or_warn ("filesrc", "src"); g_object_set (G_OBJECT (src), "location", argv[1], NULL); demux = gst_element_factory_make_or_warn ("avidemux", "demux"); gst_bin_add (GST_BIN (pipeline), src); gst_bin_add (GST_BIN (pipeline), demux); gst_element_link (src, demux); audio_bin = gst_bin_new("a_decoder_bin"); // a_demux = gst_element_factory_make_or_warn("demux.audio_00 ", "a_demux"); a_queue = gst_element_factory_make_or_warn("queue", "a_queue"); a_decoder = gst_element_factory_make_or_warn("ffdec_mp3", "a_dec"); a_convert = gst_element_factory_make_or_warn("audioconvert", "a_convert"); audiosink = gst_element_factory_make_or_warn("directsoundsink", "a_sink"); // gst_bin_add (GST_BIN (audio_bin), a_demux); gst_bin_add (GST_BIN (audio_bin), a_queue); gst_bin_add (GST_BIN (audio_bin), a_decoder); gst_bin_add (GST_BIN (audio_bin), a_convert); gst_bin_add (GST_BIN (audio_bin), audiosink); //gst_element_link (a_demux, a_queue); gst_element_link (a_queue, a_decoder); gst_element_link (a_decoder, a_convert); gst_element_link (a_convert, audiosink); gst_bin_add (GST_BIN (pipeline), audio_bin); pad = gst_element_get_pad (a_queue, "sink"); gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad)); gst_object_unref (pad); setup_dynamic_link (demux, NULL, gst_element_get_pad (audio_bin, "sink"),NULL); video_bin = gst_bin_new ("v_decoder_bin"); //v_demux = gst_element_factory_make_or_warn("demux.video_00 ", "v_demux"); v_queue = gst_element_factory_make_or_warn("queue", "v_queue"); v_decoder = gst_element_factory_make_or_warn("ffdec_h264", "v_dec"); v_convert = gst_element_factory_make_or_warn("ffmpegcolorspace", "v_convert"); videosink = gst_element_factory_make_or_warn("directdrawsink", "v_sink"); //gst_bin_add (GST_BIN (audio_bin), v_demux); gst_bin_add (GST_BIN (video_bin), v_queue); gst_bin_add (GST_BIN (video_bin), v_decoder); gst_bin_add (GST_BIN (video_bin), v_convert); gst_bin_add (GST_BIN (video_bin), videosink); gst_element_link_many (v_queue, v_decoder, v_convert, videosink, NULL); gst_bin_add (GST_BIN (pipeline), video_bin); pad = gst_element_get_pad (v_queue, "sink"); gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad)); gst_object_unref (pad); setup_dynamic_link (demux, NULL, gst_element_get_pad (video_bin, "sink"), NULL); seekable = gst_element_get_pad (a_decoder, "src"); seekable_pads = g_list_prepend (seekable_pads, seekable); rate_pads = g_list_prepend (rate_pads, seekable); rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink")); if(!pipeline || !audio_bin || !video_bin || !src || !demux || !a_decoder || !a_convert || !v_decoder || !v_convert || !audiosink || !videosink || !a_queue || !v_queue) { g_print ("One element could not be created\n"); return -1; } /* set filename property on the file source. Also add a message * handler. */ g_object_set (G_OBJECT (src), "location", argv[1], NULL); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); gst_bus_add_watch (bus, bus_call, loop); gst_object_unref (bus); /* link together - note that we cannot link the parser and * decoder yet, becuse the parser uses dynamic pads. For that, * we set a pad-added signal handler. */ // g_signal_connect (parser, "pad-added", G_CALLBACK (new_pad), NULL); /* Now set to playing and iterate. */ g_print ("Setting to PLAYING\n"); gst_element_set_state (pipeline, GST_STATE_PLAYING); g_print ("Running\n"); g_main_loop_run (loop); /* clean up nicely */ g_print ("Returned, stopping playback\n"); gst_element_set_state (pipeline, GST_STATE_NULL); g_print ("Deleting pipeline\n"); gst_object_unref (GST_OBJECT (pipeline)); return 0; }