1 /* Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
3 * Permission is hereby granted, free of charge, to any person obtaining a
4 * copy of this software and associated documentation files (the "Software"),
5 * to deal in the Software without restriction, including without limitation
6 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 * and/or sell copies of the Software, and to permit persons to whom the
8 * Software is furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19 * DEALINGS IN THE SOFTWARE.
21 * Alternatively, the contents of this file may be used under the
22 * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
23 * which case the following provisions apply instead of the ones
26 * This library is free software; you can redistribute it and/or
27 * modify it under the terms of the GNU Library General Public
28 * License as published by the Free Software Foundation; either
29 * version 2 of the License, or (at your option) any later version.
31 * This library is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 * Library General Public License for more details.
36 * You should have received a copy of the GNU Library General Public
37 * License along with this library; if not, write to the
38 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
39 * Boston, MA 02111-1307, USA.
45 static GstElement
*pipeline
;
47 #define MAKE_ELEMENT(v,c,n) \
48 if ( ! (v = gst_element_factory_make (c, n) ) ) { \
49 g_print ("element could not be created: %s/%s\n", c, n); \
53 #define LINK_ELEMENTS(isdyn, src, sink) \
55 g_signal_connect (G_OBJECT (src), "pad-added", \
56 G_CALLBACK (dynamic_link), sink); \
58 if (!gst_element_link (src, sink)) { \
59 g_warning ("Failed to link elements: %s -> %s", \
60 GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink) ); \
65 #define ADD_AND_LINK(isdyn, pipe, src, sink) \
66 gst_bin_add(GST_BIN (pipe), sink); \
67 LINK_ELEMENTS(isdyn, src, sink);
70 dynamic_link (GstPadTemplate
* templ
, GstPad
* newpad
, gpointer data
) {
71 GstElement
*bin
= (GstElement
*) data
;
72 GstPad
*sink
= gst_element_get_pad (bin
, "sink");
74 if (gst_pad_can_link (newpad
, sink
)) {
75 gst_bin_add (GST_BIN (pipeline
), bin
);
76 gst_pad_link (newpad
, sink
);
81 play_file (const gchar
* filename
, const play_file_args
* args
)
83 GstStateChangeReturn sret
;
84 GstMessage
*msg
= NULL
;
87 g_print ("Trying to play %s ...\n", filename
);
88 g_print (" silent: %s\n", (args
->silent
?"Yes":"No"));
89 g_print (" is raw file: %s\n", (args
->israwfile
?"Yes":"No"));
90 g_print (" filter: %s\n", args
->filter_name
);
91 g_print (" param_name: %s\n", args
->param_name
);
92 g_print (" scale: %3.2f\n", args
->scale
);
93 g_print (" temp: %3.2f\n", args
->temp
);
94 g_print (" # buffers: %i\n", args
->num_buffers
);
95 g_print (" audio: %s\n", (args
->noaudio
?"No":"Yes"));
96 g_print (" video: %s\n", (args
->novideo
?"No":"Yes"));
98 pipeline
= gst_pipeline_new ("my-pipeline");
99 bus
= gst_pipeline_get_bus (GST_PIPELINE (pipeline
));
100 gst_object_unref (bus
);
102 GstElement
*source
, *decode
;
103 MAKE_ELEMENT(source
, "filesrc", "source");
104 g_object_set (G_OBJECT (source
), "location", filename
, NULL
);
105 if (args
->num_buffers
> 0) {
106 g_object_set (G_OBJECT (source
), "num_buffers", args
->num_buffers
, NULL
);
108 gst_bin_add (GST_BIN(pipeline
), source
);
110 MAKE_ELEMENT(decode
, "decodebin2", "decode");
111 ADD_AND_LINK(0, pipeline
, source
, decode
);
113 if (!args
->noaudio
) {
114 GstElement
*queue
, *format1
, *resample1
, *filter
, *format2
, *resample2
, *sink
;
115 MAKE_ELEMENT(queue
, "queue", "audio_queue");
116 MAKE_ELEMENT(format1
, "audioconvert", "format1");
117 MAKE_ELEMENT(resample1
, "audioresample", "resample1");
118 MAKE_ELEMENT(filter
, args
->filter_name
, "filter");
119 MAKE_ELEMENT(format2
, "audioconvert", "format2");
120 MAKE_ELEMENT(resample2
, "audioresample", "resample2");
121 MAKE_ELEMENT(sink
, "gconfaudiosink", "audio_sink");
123 if (args
->param_name
)
124 g_object_set (G_OBJECT (filter
), args
->param_name
, args
->scale
, NULL
);
126 GstElement
*subline
= gst_bin_new ("audioline");
128 gst_bin_add (GST_BIN(subline
), queue
);
129 ADD_AND_LINK(0, subline
, queue
, format1
);
130 ADD_AND_LINK(0, subline
, format1
, resample1
);
131 ADD_AND_LINK(0, subline
, resample1
, filter
);
132 ADD_AND_LINK(0, subline
, filter
, format2
);
133 ADD_AND_LINK(0, subline
, format2
, resample2
);
134 ADD_AND_LINK(0, subline
, resample2
, sink
);
136 GstPad
*ghostpad
= gst_element_get_pad (queue
, "sink");
137 gst_element_add_pad (subline
, gst_ghost_pad_new ("sink", ghostpad
));
138 gst_object_unref (ghostpad
);
140 gst_element_set_state (subline
, GST_STATE_PAUSED
);
142 LINK_ELEMENTS(1, decode
, subline
);
145 if (!args
->novideo
) {
146 GstElement
*queue
, *colorspace
, *sink
;
147 MAKE_ELEMENT(queue
, "queue", "video_queue");
148 MAKE_ELEMENT(colorspace
, "ffmpegcolorspace", "colorspace");
149 MAKE_ELEMENT(sink
, "gconfvideosink", "video_sink");
151 GstElement
*subline
= gst_bin_new ("videoline");
153 gst_bin_add (GST_BIN(subline
), queue
);
154 ADD_AND_LINK(0, subline
, queue
, colorspace
);
155 ADD_AND_LINK(0, subline
, colorspace
, sink
);
157 GstPad
*ghostpad
= gst_element_get_pad (queue
, "sink");
158 gst_element_add_pad (subline
, gst_ghost_pad_new ("sink", ghostpad
));
159 gst_object_unref (ghostpad
);
161 gst_element_set_state (subline
, GST_STATE_PLAYING
);
163 LINK_ELEMENTS(1, decode
, subline
);
167 gst_element_set_state (GST_ELEMENT (pipeline
), GST_STATE_PLAYING
);
168 g_print ("Hi there1.\n");
169 /* wait (blocks!) until state change either completes or fails */
170 sret
= gst_element_get_state (GST_ELEMENT (pipeline
), NULL
, NULL
, -1);
171 g_print ("Hi there2.\n");
173 case GST_STATE_CHANGE_FAILURE
:{
174 msg
= gst_bus_poll (bus
, GST_MESSAGE_ERROR
, 0);
175 goto got_error_message
;
177 case GST_STATE_CHANGE_SUCCESS
:{
180 g_print ("Playing ...\n");
183 GstFormat time_format
;
186 time_format
= GST_FORMAT_TIME
;
187 if (gst_element_query_duration (pipeline
, &time_format
, &dur
) &&
188 gst_element_query_position (pipeline
, &time_format
, &pos
)) {
189 g_print (" %" GST_TIME_FORMAT
" / %" GST_TIME_FORMAT
"\n",
190 GST_TIME_ARGS (pos
), GST_TIME_ARGS (dur
));
193 /* check if we finished or if there was an error,
194 * but don't wait/block if neither is the case */
195 msg
= gst_bus_poll (bus
, GST_MESSAGE_EOS
| GST_MESSAGE_ERROR
, 0);
197 if (msg
&& GST_MESSAGE_TYPE (msg
) == GST_MESSAGE_ERROR
)
198 goto got_error_message
;
200 if (msg
&& GST_MESSAGE_TYPE (msg
) == GST_MESSAGE_EOS
) {
201 g_print ("Finished.\n");
205 /* sleep for one second */
206 g_usleep (G_USEC_PER_SEC
* 1);
211 g_assert_not_reached ();
214 /* shut down and free everything */
215 gst_element_set_state (pipeline
, GST_STATE_NULL
);
216 gst_object_unref (pipeline
);
217 gst_object_unref (bus
);
225 gchar
*dbg_str
= NULL
;
227 gst_message_parse_error (msg
, &err
, &dbg_str
);
228 g_printerr ("FAILED to play %s: %s\n%s\n", filename
, err
->message
,
229 (dbg_str
) ? dbg_str
: "(no debugging information)");
232 gst_message_unref (msg
);
234 g_printerr ("FAILED to play %s: unknown error\n", filename
);
237 /* shut down and free everything */
238 gst_element_set_state (pipeline
, GST_STATE_NULL
);
239 gst_object_unref (pipeline
);
240 gst_object_unref (bus
);