1 /* GStreamer
2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 #include <gst/gst.h>
24
25 #include <stdlib.h>
26
27 static GMainLoop *loop;
28
29 static GstElement *
gen_video_element(void)30 gen_video_element (void)
31 {
32 GstElement *element;
33 GstElement *conv;
34 GstElement *sink;
35 GstPad *pad;
36
37 element = gst_bin_new ("vbin");
38 conv = gst_element_factory_make ("videoconvert", "conv");
39 sink = gst_element_factory_make (DEFAULT_VIDEOSINK, "sink");
40 g_assert (sink);
41
42 gst_bin_add (GST_BIN (element), conv);
43 gst_bin_add (GST_BIN (element), sink);
44 gst_element_link_pads (conv, "src", sink, "sink");
45
46 pad = gst_element_get_static_pad (conv, "sink");
47 gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
48 gst_object_unref (pad);
49
50 return element;
51 }
52
53 static GstElement *
gen_audio_element(void)54 gen_audio_element (void)
55 {
56 GstElement *element;
57 GstElement *conv;
58 GstElement *sink;
59 GstPad *pad;
60
61 element = gst_bin_new ("abin");
62 conv = gst_element_factory_make ("audioconvert", "conv");
63 sink = gst_element_factory_make (DEFAULT_AUDIOSINK, "sink");
64 g_assert (sink);
65
66 gst_bin_add (GST_BIN (element), conv);
67 gst_bin_add (GST_BIN (element), sink);
68 gst_element_link_pads (conv, "src", sink, "sink");
69
70 pad = gst_element_get_static_pad (conv, "sink");
71 gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
72 gst_object_unref (pad);
73
74 return element;
75 }
76
77 static void
pad_added_cb(GstElement * decodebin,GstPad * pad,gpointer data)78 pad_added_cb (GstElement * decodebin, GstPad * pad, gpointer data)
79 {
80 GstCaps *caps;
81 GstStructure *str;
82 GstPad *sinkpad;
83 GstElement *sink;
84 GstElement *pipeline;
85 const gchar *name;
86 GstStateChangeReturn ret;
87 GstPadLinkReturn lret;
88
89 /* check media type */
90 caps = gst_pad_query_caps (pad, NULL);
91 str = gst_caps_get_structure (caps, 0);
92
93 name = gst_structure_get_name (str);
94 g_print ("name: %s\n", name);
95
96 if (g_strrstr (name, "audio")) {
97 sink = gen_audio_element ();
98 } else if (g_strrstr (name, "video")) {
99 sink = gen_video_element ();
100 } else {
101 sink = NULL;
102 }
103 gst_caps_unref (caps);
104
105 if (sink) {
106 pipeline = GST_ELEMENT_CAST (data);
107
108 /* add new sink to the pipeline */
109 gst_bin_add (GST_BIN_CAST (pipeline), sink);
110
111 /* set the new sink tp PAUSED as well */
112 ret = gst_element_set_state (sink, GST_STATE_PAUSED);
113 if (ret == GST_STATE_CHANGE_FAILURE)
114 goto state_error;
115
116 /* get the ghostpad of the sink bin */
117 sinkpad = gst_element_get_static_pad (sink, "sink");
118
119 /* link'n'play */
120 lret = gst_pad_link (pad, sinkpad);
121 if (lret != GST_PAD_LINK_OK)
122 goto link_failed;
123
124 gst_object_unref (sinkpad);
125 }
126 return;
127
128 /* ERRORS */
129 state_error:
130 {
131 gst_bin_remove (GST_BIN_CAST (pipeline), sink);
132 g_warning ("could not change state of new sink (%d)", ret);
133 return;
134 }
135 link_failed:
136 {
137 g_warning ("could not link pad and sink (%d)", lret);
138 return;
139 }
140 }
141
142 static void
error_eos_cb(GstBus * bus,GstMessage * msg,GMainLoop * main_loop)143 error_eos_cb (GstBus * bus, GstMessage * msg, GMainLoop * main_loop)
144 {
145 g_main_loop_quit (main_loop);
146 }
147
148 gint
main(gint argc,gchar * argv[])149 main (gint argc, gchar * argv[])
150 {
151 GstElement *pipeline, *filesrc, *decodebin;
152 GstStateChangeReturn res;
153 GstBus *bus;
154
155 gst_init (&argc, &argv);
156
157 pipeline = gst_pipeline_new ("pipeline");
158
159 filesrc = gst_element_factory_make ("filesrc", "filesrc");
160 g_assert (filesrc);
161 decodebin = gst_element_factory_make ("decodebin", "decodebin");
162 g_assert (decodebin);
163
164 loop = g_main_loop_new (NULL, TRUE);
165 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
166 gst_bus_add_signal_watch (bus);
167
168 g_signal_connect (bus, "message::eos", G_CALLBACK (error_eos_cb), loop);
169 g_signal_connect (bus, "message::error", G_CALLBACK (error_eos_cb), loop);
170
171 g_signal_connect (G_OBJECT (decodebin), "pad-added",
172 G_CALLBACK (pad_added_cb), pipeline);
173
174 gst_bin_add_many (GST_BIN (pipeline), filesrc, decodebin, NULL);
175 gst_element_link (filesrc, decodebin);
176
177 if (argc < 2) {
178 g_print ("usage: %s <uri>\n", argv[0]);
179 exit (-1);
180 }
181
182 if (!g_str_has_prefix (argv[1], "file://")) {
183 g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
184 } else {
185 g_object_set (G_OBJECT (filesrc), "location", argv[1] + 7, NULL);
186 }
187
188 /* set to paused, decodebin will autoplug and signal new_pad callbacks */
189 res = gst_element_set_state (pipeline, GST_STATE_PAUSED);
190 if (res == GST_STATE_CHANGE_FAILURE) {
191 g_print ("could not pause\n");
192 return -1;
193 }
194 /* wait for paused to complete */
195 res = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
196 if (res == GST_STATE_CHANGE_FAILURE) {
197 g_print ("could not pause\n");
198 return -1;
199 }
200
201 /* play, now all the sinks are added to the pipeline and are prerolled and
202 * ready to play. */
203 res = gst_element_set_state (pipeline, GST_STATE_PLAYING);
204 if (res == GST_STATE_CHANGE_FAILURE) {
205 g_print ("could not play\n");
206 return -1;
207 }
208
209 /* go in the mainloop now */
210 g_main_loop_run (loop);
211
212 return 0;
213 }
214