7 GST_DEBUG_CATEGORY (seek_debug);
8 #define GST_CAT_DEFAULT (seek_debug)
10 static GList *seekable_pads = NULL;
11 static GList *rate_pads = NULL;
12 static GList *seekable_elements = NULL;
14 static GstElement *pipeline;
15 static gint64 position;
16 static gint64 duration;
17 static GtkAdjustment *adjustment;
18 static GtkWidget *hscale;
19 static gboolean stats = FALSE;
20 static gboolean elem_seek = FALSE;
21 static gboolean verbose = FALSE;
23 static GstState state;
24 static guint update_id = 0;
25 static guint seek_timeout_id = 0;
26 static gulong changed_id;
28 //#define SOURCE "filesrc"
29 #define SOURCE "gnomevfssrc"
30 #define ASINK "alsasink"
31 //#define ASINK "osssink"
32 #define VSINK "xvimagesink"
33 //#define VSINK "ximagesink"
34 //#define VSINK "aasink"
35 //#define VSINK "cacasink"
37 #define UPDATE_INTERVAL 500
39 /* number of milliseconds to play for after a seek */
40 //#define SCRUB_TIME 250
55 gst_element_factory_make_or_warn (gchar * type, gchar * name)
57 GstElement *element = gst_element_factory_make (type, name);
60 g_warning ("Failed to create element %s of type %s", name, type);
67 dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data)
69 dyn_link *connect = (dyn_link *) data;
71 if (connect->padname == NULL ||
72 !strcmp (gst_pad_get_name (newpad), connect->padname)) {
74 gst_bin_add (GST_BIN (pipeline), connect->bin);
75 gst_pad_link (newpad, connect->target);
77 //seekable_pads = g_list_prepend (seekable_pads, newpad);
78 rate_pads = g_list_prepend (rate_pads, newpad);
83 setup_dynamic_link (GstElement * element, const gchar * padname,
84 GstPad * target, GstElement * bin)
88 connect = g_new0 (dyn_link, 1);
89 connect->padname = g_strdup (padname);
90 connect->target = target;
93 g_signal_connect (G_OBJECT (element), "pad-added", G_CALLBACK (dynamic_link),
98 make_mod_pipeline (const gchar * location)
100 GstElement *pipeline;
101 GstElement *src, *decoder, *audiosink;
104 pipeline = gst_pipeline_new ("app");
106 src = gst_element_factory_make_or_warn (SOURCE, "src");
107 decoder = gst_element_factory_make_or_warn ("modplug", "decoder");
108 audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
109 //g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
111 g_object_set (G_OBJECT (src), "location", location, NULL);
113 gst_bin_add (GST_BIN (pipeline), src);
114 gst_bin_add (GST_BIN (pipeline), decoder);
115 gst_bin_add (GST_BIN (pipeline), audiosink);
117 gst_element_link (src, decoder);
118 gst_element_link (decoder, audiosink);
120 seekable = gst_element_get_pad (decoder, "src");
121 seekable_pads = g_list_prepend (seekable_pads, seekable);
122 rate_pads = g_list_prepend (rate_pads, seekable);
123 rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (decoder, "sink"));
129 make_dv_pipeline (const gchar * location)
131 GstElement *pipeline;
132 GstElement *src, *demux, *decoder, *audiosink, *videosink;
133 GstElement *a_queue, *v_queue;
136 pipeline = gst_pipeline_new ("app");
138 src = gst_element_factory_make_or_warn (SOURCE, "src");
139 demux = gst_element_factory_make_or_warn ("dvdemux", "demuxer");
140 v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
141 decoder = gst_element_factory_make_or_warn ("ffdec_dvvideo", "decoder");
142 videosink = gst_element_factory_make_or_warn ("xvimagesink", "v_sink");
143 a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
144 audiosink = gst_element_factory_make_or_warn ("alsasink", "a_sink");
146 g_object_set (G_OBJECT (src), "location", location, NULL);
148 gst_bin_add (GST_BIN (pipeline), src);
149 gst_bin_add (GST_BIN (pipeline), demux);
150 gst_bin_add (GST_BIN (pipeline), a_queue);
151 gst_bin_add (GST_BIN (pipeline), audiosink);
152 gst_bin_add (GST_BIN (pipeline), v_queue);
153 gst_bin_add (GST_BIN (pipeline), decoder);
154 gst_bin_add (GST_BIN (pipeline), videosink);
156 gst_element_link (src, demux);
157 gst_element_link (a_queue, audiosink);
158 gst_element_link (v_queue, decoder);
159 gst_element_link (decoder, videosink);
161 setup_dynamic_link (demux, "video", gst_element_get_pad (v_queue, "sink"),
163 setup_dynamic_link (demux, "audio", gst_element_get_pad (a_queue, "sink"),
166 seekable = gst_element_get_pad (decoder, "src");
167 seekable_pads = g_list_prepend (seekable_pads, seekable);
168 rate_pads = g_list_prepend (rate_pads, seekable);
174 make_wav_pipeline (const gchar * location)
176 GstElement *pipeline;
177 GstElement *src, *decoder, *audiosink;
179 pipeline = gst_pipeline_new ("app");
181 src = gst_element_factory_make_or_warn (SOURCE, "src");
182 decoder = gst_element_factory_make_or_warn ("wavparse", "decoder");
183 audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
185 g_object_set (G_OBJECT (src), "location", location, NULL);
187 gst_bin_add (GST_BIN (pipeline), src);
188 gst_bin_add (GST_BIN (pipeline), decoder);
189 gst_bin_add (GST_BIN (pipeline), audiosink);
191 gst_element_link (src, decoder);
193 setup_dynamic_link (decoder, "src", gst_element_get_pad (audiosink, "sink"),
196 seekable_elements = g_list_prepend (seekable_elements, audiosink);
198 /* force element seeking on this pipeline */
205 make_flac_pipeline (const gchar * location)
207 GstElement *pipeline;
208 GstElement *src, *decoder, *audiosink;
211 pipeline = gst_pipeline_new ("app");
213 src = gst_element_factory_make_or_warn (SOURCE, "src");
214 decoder = gst_element_factory_make_or_warn ("flacdec", "decoder");
215 audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
216 g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
218 g_object_set (G_OBJECT (src), "location", location, NULL);
220 gst_bin_add (GST_BIN (pipeline), src);
221 gst_bin_add (GST_BIN (pipeline), decoder);
222 gst_bin_add (GST_BIN (pipeline), audiosink);
224 gst_element_link (src, decoder);
225 gst_element_link (decoder, audiosink);
227 seekable = gst_element_get_pad (decoder, "src");
228 seekable_pads = g_list_prepend (seekable_pads, seekable);
229 rate_pads = g_list_prepend (rate_pads, seekable);
230 rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (decoder, "sink"));
236 make_sid_pipeline (const gchar * location)
238 GstElement *pipeline;
239 GstElement *src, *decoder, *audiosink;
242 pipeline = gst_pipeline_new ("app");
244 src = gst_element_factory_make_or_warn (SOURCE, "src");
245 decoder = gst_element_factory_make_or_warn ("siddec", "decoder");
246 audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
247 //g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
249 g_object_set (G_OBJECT (src), "location", location, NULL);
251 gst_bin_add (GST_BIN (pipeline), src);
252 gst_bin_add (GST_BIN (pipeline), decoder);
253 gst_bin_add (GST_BIN (pipeline), audiosink);
255 gst_element_link (src, decoder);
256 gst_element_link (decoder, audiosink);
258 seekable = gst_element_get_pad (decoder, "src");
259 seekable_pads = g_list_prepend (seekable_pads, seekable);
260 rate_pads = g_list_prepend (rate_pads, seekable);
261 rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (decoder, "sink"));
267 make_parse_pipeline (const gchar * location)
269 GstElement *pipeline;
270 GstElement *src, *parser, *fakesink;
273 pipeline = gst_pipeline_new ("app");
275 src = gst_element_factory_make_or_warn (SOURCE, "src");
276 parser = gst_element_factory_make_or_warn ("mpegparse", "parse");
277 fakesink = gst_element_factory_make_or_warn ("fakesink", "sink");
278 g_object_set (G_OBJECT (fakesink), "silent", TRUE, NULL);
279 g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
281 g_object_set (G_OBJECT (src), "location", location, NULL);
283 gst_bin_add (GST_BIN (pipeline), src);
284 gst_bin_add (GST_BIN (pipeline), parser);
285 gst_bin_add (GST_BIN (pipeline), fakesink);
287 gst_element_link (src, parser);
288 gst_element_link (parser, fakesink);
290 seekable = gst_element_get_pad (parser, "src");
291 seekable_pads = g_list_prepend (seekable_pads, seekable);
292 rate_pads = g_list_prepend (rate_pads, seekable);
293 rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (parser, "sink"));
299 make_vorbis_pipeline (const gchar * location)
301 GstElement *pipeline, *audio_bin;
302 GstElement *src, *demux, *decoder, *convert, *audiosink;
303 GstPad *pad, *seekable;
305 pipeline = gst_pipeline_new ("app");
307 src = gst_element_factory_make_or_warn (SOURCE, "src");
308 demux = gst_element_factory_make_or_warn ("oggdemux", "demux");
309 decoder = gst_element_factory_make_or_warn ("vorbisdec", "decoder");
310 convert = gst_element_factory_make_or_warn ("audioconvert", "convert");
311 audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
312 g_object_set (G_OBJECT (audiosink), "sync", TRUE, NULL);
314 g_object_set (G_OBJECT (src), "location", location, NULL);
316 audio_bin = gst_bin_new ("a_decoder_bin");
318 gst_bin_add (GST_BIN (pipeline), src);
319 gst_bin_add (GST_BIN (pipeline), demux);
320 gst_bin_add (GST_BIN (audio_bin), decoder);
321 gst_bin_add (GST_BIN (audio_bin), convert);
322 gst_bin_add (GST_BIN (audio_bin), audiosink);
323 gst_bin_add (GST_BIN (pipeline), audio_bin);
325 gst_element_link (src, demux);
326 gst_element_link (decoder, convert);
327 gst_element_link (convert, audiosink);
329 pad = gst_element_get_pad (decoder, "sink");
330 gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
331 gst_object_unref (pad);
333 setup_dynamic_link (demux, NULL, gst_element_get_pad (audio_bin, "sink"),
336 seekable = gst_element_get_pad (decoder, "src");
337 seekable_pads = g_list_prepend (seekable_pads, seekable);
338 rate_pads = g_list_prepend (rate_pads, seekable);
339 rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (decoder, "sink"));
345 make_theora_pipeline (const gchar * location)
347 GstElement *pipeline, *video_bin;
348 GstElement *src, *demux, *decoder, *convert, *videosink;
349 GstPad *pad, *seekable;
351 pipeline = gst_pipeline_new ("app");
353 src = gst_element_factory_make_or_warn (SOURCE, "src");
354 demux = gst_element_factory_make_or_warn ("oggdemux", "demux");
355 decoder = gst_element_factory_make_or_warn ("theoradec", "decoder");
356 convert = gst_element_factory_make_or_warn ("ffmpegcolorspace", "convert");
357 videosink = gst_element_factory_make_or_warn (VSINK, "sink");
359 g_object_set (G_OBJECT (src), "location", location, NULL);
361 video_bin = gst_bin_new ("v_decoder_bin");
363 gst_bin_add (GST_BIN (pipeline), src);
364 gst_bin_add (GST_BIN (pipeline), demux);
365 gst_bin_add (GST_BIN (video_bin), decoder);
366 gst_bin_add (GST_BIN (video_bin), convert);
367 gst_bin_add (GST_BIN (video_bin), videosink);
368 gst_bin_add (GST_BIN (pipeline), video_bin);
370 gst_element_link (src, demux);
371 gst_element_link (decoder, convert);
372 gst_element_link (convert, videosink);
374 pad = gst_element_get_pad (decoder, "sink");
375 gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
376 gst_object_unref (pad);
378 setup_dynamic_link (demux, NULL, gst_element_get_pad (video_bin, "sink"),
381 seekable = gst_element_get_pad (decoder, "src");
382 seekable_pads = g_list_prepend (seekable_pads, seekable);
383 rate_pads = g_list_prepend (rate_pads, seekable);
384 rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (decoder, "sink"));
390 make_vorbis_theora_pipeline (const gchar * location)
392 GstElement *pipeline, *audio_bin, *video_bin;
393 GstElement *src, *demux, *a_decoder, *a_convert, *v_decoder, *v_convert;
394 GstElement *audiosink, *videosink;
395 GstElement *a_queue, *v_queue;
399 pipeline = gst_pipeline_new ("app");
401 src = gst_element_factory_make_or_warn (SOURCE, "src");
402 g_object_set (G_OBJECT (src), "location", location, NULL);
404 demux = gst_element_factory_make_or_warn ("oggdemux", "demux");
406 gst_bin_add (GST_BIN (pipeline), src);
407 gst_bin_add (GST_BIN (pipeline), demux);
408 gst_element_link (src, demux);
410 audio_bin = gst_bin_new ("a_decoder_bin");
411 a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
412 a_decoder = gst_element_factory_make_or_warn ("vorbisdec", "a_dec");
413 a_convert = gst_element_factory_make_or_warn ("audioconvert", "a_convert");
414 audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
416 gst_bin_add (GST_BIN (pipeline), audio_bin);
418 gst_bin_add (GST_BIN (audio_bin), a_queue);
419 gst_bin_add (GST_BIN (audio_bin), a_decoder);
420 gst_bin_add (GST_BIN (audio_bin), a_convert);
421 gst_bin_add (GST_BIN (audio_bin), audiosink);
423 gst_element_link (a_queue, a_decoder);
424 gst_element_link (a_decoder, a_convert);
425 gst_element_link (a_convert, audiosink);
427 pad = gst_element_get_pad (a_queue, "sink");
428 gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
429 gst_object_unref (pad);
431 setup_dynamic_link (demux, NULL, gst_element_get_pad (audio_bin, "sink"),
434 video_bin = gst_bin_new ("v_decoder_bin");
435 v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
436 v_decoder = gst_element_factory_make_or_warn ("theoradec", "v_dec");
438 gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_convert");
439 videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
441 gst_bin_add (GST_BIN (pipeline), video_bin);
443 gst_bin_add (GST_BIN (video_bin), v_queue);
444 gst_bin_add (GST_BIN (video_bin), v_decoder);
445 gst_bin_add (GST_BIN (video_bin), v_convert);
446 gst_bin_add (GST_BIN (video_bin), videosink);
448 gst_element_link_many (v_queue, v_decoder, v_convert, videosink, NULL);
450 pad = gst_element_get_pad (v_queue, "sink");
451 gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
452 gst_object_unref (pad);
454 setup_dynamic_link (demux, NULL, gst_element_get_pad (video_bin, "sink"),
457 seekable = gst_element_get_pad (a_decoder, "src");
458 seekable_pads = g_list_prepend (seekable_pads, seekable);
459 rate_pads = g_list_prepend (rate_pads, seekable);
461 g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink"));
467 make_avi_msmpeg4v3_mp3_pipeline (const gchar * location)
469 GstElement *pipeline, *audio_bin, *video_bin;
470 GstElement *src, *demux, *a_decoder, *a_convert, *v_decoder, *v_convert;
471 GstElement *audiosink, *videosink;
472 GstElement *a_queue, *v_queue;
473 GstPad *seekable, *pad;
475 pipeline = gst_pipeline_new ("app");
477 src = gst_element_factory_make_or_warn (SOURCE, "src");
478 g_object_set (G_OBJECT (src), "location", location, NULL);
480 demux = gst_element_factory_make_or_warn ("avidemux", "demux");
482 gst_bin_add (GST_BIN (pipeline), src);
483 gst_bin_add (GST_BIN (pipeline), demux);
484 gst_element_link (src, demux);
486 audio_bin = gst_bin_new ("a_decoder_bin");
487 a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
488 a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
489 a_convert = gst_element_factory_make_or_warn ("audioconvert", "a_convert");
490 audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
492 gst_bin_add (GST_BIN (audio_bin), a_queue);
493 gst_bin_add (GST_BIN (audio_bin), a_decoder);
494 gst_bin_add (GST_BIN (audio_bin), a_convert);
495 gst_bin_add (GST_BIN (audio_bin), audiosink);
497 gst_element_link (a_queue, a_decoder);
498 gst_element_link (a_decoder, a_convert);
499 gst_element_link (a_convert, audiosink);
501 gst_bin_add (GST_BIN (pipeline), audio_bin);
503 pad = gst_element_get_pad (a_queue, "sink");
504 gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
505 gst_object_unref (pad);
507 setup_dynamic_link (demux, NULL, gst_element_get_pad (audio_bin, "sink"),
510 video_bin = gst_bin_new ("v_decoder_bin");
511 v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
512 v_decoder = gst_element_factory_make_or_warn ("ffdec_msmpeg4", "v_dec");
514 gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_convert");
515 videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
517 gst_bin_add (GST_BIN (video_bin), v_queue);
518 gst_bin_add (GST_BIN (video_bin), v_decoder);
519 gst_bin_add (GST_BIN (video_bin), v_convert);
520 gst_bin_add (GST_BIN (video_bin), videosink);
522 gst_element_link_many (v_queue, v_decoder, v_convert, videosink, NULL);
524 gst_bin_add (GST_BIN (pipeline), video_bin);
526 pad = gst_element_get_pad (v_queue, "sink");
527 gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
528 gst_object_unref (pad);
530 setup_dynamic_link (demux, NULL, gst_element_get_pad (video_bin, "sink"),
533 seekable = gst_element_get_pad (a_decoder, "src");
534 seekable_pads = g_list_prepend (seekable_pads, seekable);
535 rate_pads = g_list_prepend (rate_pads, seekable);
537 g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink"));
543 make_mp3_pipeline (const gchar * location)
545 GstElement *pipeline;
546 GstElement *src, *decoder, *osssink, *queue;
549 pipeline = gst_pipeline_new ("app");
551 src = gst_element_factory_make_or_warn (SOURCE, "src");
552 decoder = gst_element_factory_make_or_warn ("mad", "dec");
553 queue = gst_element_factory_make_or_warn ("queue", "queue");
554 osssink = gst_element_factory_make_or_warn (ASINK, "sink");
556 seekable_elements = g_list_prepend (seekable_elements, osssink);
558 g_object_set (G_OBJECT (src), "location", location, NULL);
559 //g_object_set (G_OBJECT (osssink), "fragment", 0x00180008, NULL);
561 gst_bin_add (GST_BIN (pipeline), src);
562 gst_bin_add (GST_BIN (pipeline), decoder);
563 gst_bin_add (GST_BIN (pipeline), queue);
564 gst_bin_add (GST_BIN (pipeline), osssink);
566 gst_element_link (src, decoder);
567 gst_element_link (decoder, queue);
568 gst_element_link (queue, osssink);
570 seekable = gst_element_get_pad (queue, "src");
571 seekable_pads = g_list_prepend (seekable_pads, seekable);
572 rate_pads = g_list_prepend (rate_pads, seekable);
573 rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (decoder, "sink"));
579 make_avi_pipeline (const gchar * location)
581 GstElement *pipeline, *audio_bin, *video_bin;
582 GstElement *src, *demux, *a_decoder, *v_decoder, *audiosink, *videosink;
583 GstElement *a_queue = NULL, *v_queue = NULL;
586 pipeline = gst_pipeline_new ("app");
588 src = gst_element_factory_make_or_warn (SOURCE, "src");
589 g_object_set (G_OBJECT (src), "location", location, NULL);
591 demux = gst_element_factory_make_or_warn ("avidemux", "demux");
592 seekable_elements = g_list_prepend (seekable_elements, demux);
594 gst_bin_add (GST_BIN (pipeline), src);
595 gst_bin_add (GST_BIN (pipeline), demux);
596 gst_element_link (src, demux);
598 audio_bin = gst_bin_new ("a_decoder_bin");
599 a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
600 audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
601 //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
602 a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
603 gst_element_link (a_decoder, a_queue);
604 gst_element_link (a_queue, audiosink);
605 gst_bin_add (GST_BIN (audio_bin), a_decoder);
606 gst_bin_add (GST_BIN (audio_bin), a_queue);
607 gst_bin_add (GST_BIN (audio_bin), audiosink);
608 gst_element_set_state (audio_bin, GST_STATE_PAUSED);
610 setup_dynamic_link (demux, "audio_00", gst_element_get_pad (a_decoder,
613 seekable = gst_element_get_pad (a_queue, "src");
614 seekable_pads = g_list_prepend (seekable_pads, seekable);
615 rate_pads = g_list_prepend (rate_pads, seekable);
617 g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink"));
619 video_bin = gst_bin_new ("v_decoder_bin");
620 //v_decoder = gst_element_factory_make_or_warn ("identity", "v_dec");
621 //v_decoder = gst_element_factory_make_or_warn ("windec", "v_dec");
622 v_decoder = gst_element_factory_make_or_warn ("ffmpegdecall", "v_dec");
623 videosink = gst_element_factory_make_or_warn ("ximagesink", "v_sink");
624 //videosink = gst_element_factory_make_or_warn ("fakesink", "v_sink");
625 //g_object_set (G_OBJECT (videosink), "sync", TRUE, NULL);
626 v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
627 //g_object_set (G_OBJECT (v_queue), "max_level", 10, NULL);
628 gst_element_link (v_decoder, v_queue);
629 gst_element_link (v_queue, videosink);
630 gst_bin_add (GST_BIN (video_bin), v_decoder);
631 gst_bin_add (GST_BIN (video_bin), v_queue);
632 gst_bin_add (GST_BIN (video_bin), videosink);
634 gst_element_set_state (video_bin, GST_STATE_PAUSED);
636 setup_dynamic_link (demux, "video_00", gst_element_get_pad (v_decoder,
639 seekable = gst_element_get_pad (v_queue, "src");
640 seekable_pads = g_list_prepend (seekable_pads, seekable);
641 rate_pads = g_list_prepend (rate_pads, seekable);
643 g_list_prepend (rate_pads, gst_element_get_pad (v_decoder, "sink"));
649 make_mpeg_pipeline (const gchar * location)
651 GstElement *pipeline, *audio_bin, *video_bin;
652 GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter;
653 GstElement *audiosink, *videosink;
654 GstElement *a_queue, *v_queue;
657 pipeline = gst_pipeline_new ("app");
659 src = gst_element_factory_make_or_warn (SOURCE, "src");
660 g_object_set (G_OBJECT (src), "location", location, NULL);
662 demux = gst_element_factory_make_or_warn ("mpegdemux", "demux");
663 g_object_set (G_OBJECT (demux), "sync", FALSE, NULL);
665 seekable_elements = g_list_prepend (seekable_elements, demux);
667 gst_bin_add (GST_BIN (pipeline), src);
668 gst_bin_add (GST_BIN (pipeline), demux);
669 gst_element_link (src, demux);
671 audio_bin = gst_bin_new ("a_decoder_bin");
672 a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
673 a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
674 audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
675 //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
676 gst_element_link (a_decoder, a_queue);
677 gst_element_link (a_queue, audiosink);
678 gst_bin_add (GST_BIN (audio_bin), a_decoder);
679 gst_bin_add (GST_BIN (audio_bin), a_queue);
680 gst_bin_add (GST_BIN (audio_bin), audiosink);
682 setup_dynamic_link (demux, "audio_00", gst_element_get_pad (a_decoder,
685 seekable = gst_element_get_pad (a_queue, "src");
686 seekable_pads = g_list_prepend (seekable_pads, seekable);
687 rate_pads = g_list_prepend (rate_pads, seekable);
689 g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink"));
691 video_bin = gst_bin_new ("v_decoder_bin");
692 v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
693 //g_object_set (G_OBJECT (video_thread), "priority", 2, NULL);
694 v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
695 v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter");
696 videosink = gst_element_factory_make_or_warn ("ximagesink", "v_sink");
697 gst_element_link_many (v_decoder, v_queue, v_filter, NULL);
699 gst_element_link (v_filter, videosink);
700 gst_bin_add_many (GST_BIN (video_bin), v_decoder, NULL);
701 gst_bin_add_many (GST_BIN (video_bin), v_queue, v_filter, videosink, NULL);
703 setup_dynamic_link (demux, "video_00", gst_element_get_pad (v_decoder,
706 seekable = gst_element_get_pad (v_queue, "src");
707 seekable_pads = g_list_prepend (seekable_pads, seekable);
708 rate_pads = g_list_prepend (rate_pads, seekable);
710 g_list_prepend (rate_pads, gst_element_get_pad (v_decoder, "sink"));
716 make_mpegnt_pipeline (const gchar * location)
718 GstElement *pipeline, *audio_bin, *video_bin;
719 GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter;
720 GstElement *audiosink, *videosink;
724 pipeline = gst_pipeline_new ("app");
726 src = gst_element_factory_make_or_warn (SOURCE, "src");
727 g_object_set (G_OBJECT (src), "location", location, NULL);
729 demux = gst_element_factory_make_or_warn ("mpegdemux", "demux");
730 //g_object_set (G_OBJECT (demux), "sync", TRUE, NULL);
732 seekable_elements = g_list_prepend (seekable_elements, demux);
734 gst_bin_add (GST_BIN (pipeline), src);
735 gst_bin_add (GST_BIN (pipeline), demux);
736 gst_element_link (src, demux);
738 audio_bin = gst_bin_new ("a_decoder_bin");
739 a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
740 a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
741 audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
742 //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
743 g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
744 gst_element_link (a_decoder, a_queue);
745 gst_element_link (a_queue, audiosink);
746 gst_bin_add (GST_BIN (audio_bin), a_decoder);
747 gst_bin_add (GST_BIN (audio_bin), a_queue);
748 gst_bin_add (GST_BIN (audio_bin), audiosink);
750 setup_dynamic_link (demux, "audio_00", gst_element_get_pad (a_decoder,
753 seekable = gst_element_get_pad (a_queue, "src");
754 seekable_pads = g_list_prepend (seekable_pads, seekable);
755 rate_pads = g_list_prepend (rate_pads, seekable);
757 g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink"));
759 video_bin = gst_bin_new ("v_decoder_bin");
760 v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
761 v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter");
762 videosink = gst_element_factory_make_or_warn ("ximagesink", "v_sink");
763 gst_element_link_many (v_decoder, v_filter, videosink, NULL);
765 gst_bin_add_many (GST_BIN (video_bin), v_decoder, v_filter, videosink, NULL);
767 setup_dynamic_link (demux, "video_00", gst_element_get_pad (v_decoder,
770 seekable = gst_element_get_pad (v_decoder, "src");
771 seekable_pads = g_list_prepend (seekable_pads, seekable);
772 rate_pads = g_list_prepend (rate_pads, seekable);
774 g_list_prepend (rate_pads, gst_element_get_pad (v_decoder, "sink"));
780 make_playerbin_pipeline (const gchar * location)
784 player = gst_element_factory_make ("playbin", "player");
787 g_object_set (G_OBJECT (player), "uri", location, NULL);
789 seekable_elements = g_list_prepend (seekable_elements, player);
791 /* force element seeking on this pipeline */
798 format_value (GtkScale * scale, gdouble value)
804 real = value * duration / 100;
805 seconds = (gint64) real / GST_SECOND;
806 subseconds = (gint64) real / (GST_SECOND / 100);
808 return g_strdup_printf ("%02" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT ":%02"
809 G_GINT64_FORMAT, seconds / 60, seconds % 60, subseconds % 100);
815 const GstFormat format;
819 static seek_format seek_formats[] = {
820 {"tim", GST_FORMAT_TIME},
821 {"byt", GST_FORMAT_BYTES},
822 {"buf", GST_FORMAT_BUFFERS},
823 {"def", GST_FORMAT_DEFAULT},
827 G_GNUC_UNUSED static void
830 GList *walk = rate_pads;
833 GstPad *pad = GST_PAD (walk->data);
836 g_print ("rate/sec %8.8s: ", GST_PAD_NAME (pad));
837 while (seek_formats[i].name) {
841 format = seek_formats[i].format;
843 if (gst_pad_query_convert (pad, GST_FORMAT_TIME, GST_SECOND, &format,
845 g_print ("%s %13" G_GINT64_FORMAT " | ", seek_formats[i].name, value);
847 g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*");
852 g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad));
854 walk = g_list_next (walk);
858 G_GNUC_UNUSED static void
859 query_positions_elems ()
861 GList *walk = seekable_elements;
864 GstElement *element = GST_ELEMENT (walk->data);
867 g_print ("positions %8.8s: ", GST_ELEMENT_NAME (element));
868 while (seek_formats[i].name) {
869 gint64 position, total;
872 format = seek_formats[i].format;
874 if (gst_element_query_position (element, &format, &position, &total)) {
875 g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ",
876 seek_formats[i].name, position, total);
878 g_print ("%s %13.13s / %13.13s | ", seek_formats[i].name, "*NA*",
883 g_print (" %s\n", GST_ELEMENT_NAME (element));
885 walk = g_list_next (walk);
889 G_GNUC_UNUSED static void
890 query_positions_pads ()
892 GList *walk = seekable_pads;
895 GstPad *pad = GST_PAD (walk->data);
898 g_print ("positions %8.8s: ", GST_PAD_NAME (pad));
899 while (seek_formats[i].name) {
901 gint64 position, total;
903 format = seek_formats[i].format;
905 if (gst_pad_query_position (pad, &format, &position, &total)) {
906 g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ",
907 seek_formats[i].name, position, total);
909 g_print ("%s %13.13s / %13.13s | ", seek_formats[i].name, "*NA*",
915 g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad));
917 walk = g_list_next (walk);
922 update_scale (gpointer data)
929 format = GST_FORMAT_TIME;
932 if (seekable_elements) {
933 GstElement *element = GST_ELEMENT (seekable_elements->data);
935 gst_element_query_position (element, &format, &position, &duration);
939 GstPad *pad = GST_PAD (seekable_pads->data);
941 gst_pad_query_position (pad, &format, &position, &duration);
947 query_positions_elems ();
949 query_positions_pads ();
953 if (position >= duration)
957 gtk_adjustment_set_value (adjustment, position * 100.0 / duration);
958 gtk_widget_queue_draw (hscale);
964 static void do_seek (GtkWidget * widget);
968 end_scrub (GtkWidget * widget)
970 gst_element_set_state (pipeline, GST_STATE_PAUSED);
978 do_seek (GtkWidget * widget)
980 gint64 real = gtk_range_get_value (GTK_RANGE (widget)) * duration / 100;
981 gboolean res = FALSE;
985 GList *walk = seekable_pads;
988 GstPad *seekable = GST_PAD (walk->data);
990 GST_DEBUG ("seek to %" GST_TIME_FORMAT " on pad %s:%s",
991 GST_TIME_ARGS (real), GST_DEBUG_PAD_NAME (seekable));
993 s_event = gst_event_new_seek (1.0,
995 GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, real, GST_SEEK_TYPE_NONE, 0);
997 res = gst_pad_send_event (seekable, s_event);
999 walk = g_list_next (walk);
1002 GList *walk = seekable_elements;
1005 GstElement *seekable = GST_ELEMENT (walk->data);
1007 GST_DEBUG ("seek to %" GST_TIME_FORMAT " on element %s",
1008 GST_TIME_ARGS (real), GST_ELEMENT_NAME (seekable));
1010 s_event = gst_event_new_seek (1.0,
1012 GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, real, GST_SEEK_TYPE_NONE, 0);
1014 res = gst_element_send_event (seekable, s_event);
1016 walk = g_list_next (walk);
1021 gst_pipeline_set_new_stream_time (GST_PIPELINE (pipeline), 0);
1022 gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
1025 g_print ("seek failed\n");
1029 seek_cb (GtkWidget * widget)
1032 /* If the timer hasn't expired yet, then the pipeline is running */
1033 if (seek_timeout_id != 0) {
1034 gst_element_set_state (pipeline, GST_STATE_PAUSED);
1041 gst_element_set_state (pipeline, GST_STATE_PLAYING);
1043 if (seek_timeout_id == 0) {
1045 g_timeout_add (SCRUB_TIME, (GSourceFunc) end_scrub, widget);
1051 set_update_scale (gboolean active)
1054 if (update_id == 0) {
1056 g_timeout_add (UPDATE_INTERVAL, (GtkFunction) update_scale, pipeline);
1060 g_source_remove (update_id);
1067 start_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
1069 if (state == GST_STATE_PLAYING)
1070 gst_element_set_state (pipeline, GST_STATE_PAUSED);
1072 set_update_scale (FALSE);
1074 if (changed_id == 0) {
1075 changed_id = gtk_signal_connect (GTK_OBJECT (hscale),
1076 "value_changed", G_CALLBACK (seek_cb), pipeline);
1083 stop_seek (GtkWidget * widget, gpointer user_data)
1085 g_signal_handler_disconnect (GTK_OBJECT (hscale), changed_id);
1087 if (seek_timeout_id != 0) {
1088 g_source_remove (seek_timeout_id);
1089 seek_timeout_id = 0;
1090 /* Still scrubbing, so the pipeline is already playing */
1092 if (state == GST_STATE_PLAYING)
1093 gst_element_set_state (pipeline, GST_STATE_PLAYING);
1096 set_update_scale (TRUE);
1102 play_cb (GtkButton * button, gpointer data)
1104 GstStateChangeReturn ret;
1106 if (state != GST_STATE_PLAYING) {
1107 g_print ("PLAY pipeline\n");
1108 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
1109 if (ret == GST_STATE_CHANGE_FAILURE)
1112 set_update_scale (TRUE);
1113 state = GST_STATE_PLAYING;
1119 g_print ("PLAY failed\n");
1124 pause_cb (GtkButton * button, gpointer data)
1126 GstStateChangeReturn ret;
1128 if (state != GST_STATE_PAUSED) {
1129 g_print ("PAUSE pipeline\n");
1130 ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
1131 if (ret == GST_STATE_CHANGE_FAILURE)
1134 set_update_scale (FALSE);
1135 state = GST_STATE_PAUSED;
1141 g_print ("PAUSE failed\n");
1146 stop_cb (GtkButton * button, gpointer data)
1148 GstStateChangeReturn ret;
1150 if (state != GST_STATE_READY) {
1151 g_print ("READY pipeline\n");
1152 ret = gst_element_set_state (pipeline, GST_STATE_READY);
1153 if (ret == GST_STATE_CHANGE_FAILURE)
1156 gtk_adjustment_set_value (adjustment, 0.0);
1157 set_update_scale (FALSE);
1159 state = GST_STATE_READY;
1165 g_print ("READY failed\n");
1170 message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
1172 const GstStructure *s;
1174 s = gst_message_get_structure (message);
1175 g_print ("message from \"%s\" (%s): ",
1176 GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))),
1177 gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
1181 sstr = gst_structure_to_string (s);
1182 g_print ("%s\n", sstr);
1185 g_print ("no message details\n");
1193 GstElement *(*func) (const gchar * location);
1197 static Pipeline pipelines[] = {
1198 {"mp3", make_mp3_pipeline},
1199 {"avi", make_avi_pipeline},
1200 {"mpeg1", make_mpeg_pipeline},
1201 {"mpegparse", make_parse_pipeline},
1202 {"vorbis", make_vorbis_pipeline},
1203 {"theora", make_theora_pipeline},
1204 {"ogg/v/t", make_vorbis_theora_pipeline},
1205 {"avi/msmpeg4v3/mp3", make_avi_msmpeg4v3_mp3_pipeline},
1206 {"sid", make_sid_pipeline},
1207 {"flac", make_flac_pipeline},
1208 {"wav", make_wav_pipeline},
1209 {"mod", make_mod_pipeline},
1210 {"dv", make_dv_pipeline},
1211 {"mpeg1nothreads", make_mpegnt_pipeline},
1212 {"playerbin", make_playerbin_pipeline},
1216 #define NUM_TYPES ((sizeof (pipelines) / sizeof (Pipeline)) - 1)
1219 print_usage (int argc, char **argv)
1223 g_print ("usage: %s <type> <filename>\n", argv[0]);
1224 g_print (" possible types:\n");
1226 for (i = 0; i < NUM_TYPES; i++) {
1227 g_print (" %d = %s\n", i, pipelines[i].name);
1232 main (int argc, char **argv)
1234 GtkWidget *window, *hbox, *vbox, *play_button, *pause_button, *stop_button;
1235 GOptionEntry options[] = {
1236 {"stats", 's', 0, G_OPTION_ARG_NONE, &stats,
1237 "Show pad stats", NULL},
1238 {"elem", 'e', 0, G_OPTION_ARG_NONE, &elem_seek,
1239 "Seek on elements instead of pads", NULL},
1240 {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
1241 "Verbose properties", NULL},
1245 GOptionContext *ctx;
1248 ctx = g_option_context_new ("seek");
1249 g_option_context_add_main_entries (ctx, options, NULL);
1250 g_option_context_add_group (ctx, gst_init_get_option_group ());
1252 if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
1253 g_print ("Error initializing: %s\n", err->message);
1257 GST_DEBUG_CATEGORY_INIT (seek_debug, "seek", 0, "seek example");
1259 gtk_init (&argc, &argv);
1262 print_usage (argc, argv);
1266 type = atoi (argv[1]);
1268 if (type < 0 || type >= NUM_TYPES) {
1269 print_usage (argc, argv);
1273 pipeline = pipelines[type].func (argv[2]);
1274 g_assert (pipeline);
1276 /* initialize gui elements ... */
1277 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1278 hbox = gtk_hbox_new (FALSE, 0);
1279 vbox = gtk_vbox_new (FALSE, 0);
1280 play_button = gtk_button_new_with_label ("play");
1281 pause_button = gtk_button_new_with_label ("pause");
1282 stop_button = gtk_button_new_with_label ("stop");
1285 GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.00, 100.0, 0.1, 1.0, 1.0));
1286 hscale = gtk_hscale_new (adjustment);
1287 gtk_scale_set_digits (GTK_SCALE (hscale), 2);
1288 gtk_range_set_update_policy (GTK_RANGE (hscale), GTK_UPDATE_CONTINUOUS);
1290 gtk_signal_connect (GTK_OBJECT (hscale),
1291 "button_press_event", G_CALLBACK (start_seek), pipeline);
1292 gtk_signal_connect (GTK_OBJECT (hscale),
1293 "button_release_event", G_CALLBACK (stop_seek), pipeline);
1294 gtk_signal_connect (GTK_OBJECT (hscale),
1295 "format_value", G_CALLBACK (format_value), pipeline);
1297 /* do the packing stuff ... */
1298 gtk_window_set_default_size (GTK_WINDOW (window), 250, 96);
1299 gtk_container_add (GTK_CONTAINER (window), vbox);
1300 gtk_container_add (GTK_CONTAINER (vbox), hbox);
1301 gtk_box_pack_start (GTK_BOX (hbox), play_button, FALSE, FALSE, 2);
1302 gtk_box_pack_start (GTK_BOX (hbox), pause_button, FALSE, FALSE, 2);
1303 gtk_box_pack_start (GTK_BOX (hbox), stop_button, FALSE, FALSE, 2);
1304 gtk_box_pack_start (GTK_BOX (vbox), hscale, TRUE, TRUE, 2);
1306 /* connect things ... */
1307 g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK (play_cb),
1309 g_signal_connect (G_OBJECT (pause_button), "clicked", G_CALLBACK (pause_cb),
1311 g_signal_connect (G_OBJECT (stop_button), "clicked", G_CALLBACK (stop_cb),
1313 g_signal_connect (G_OBJECT (window), "delete_event", gtk_main_quit, NULL);
1316 gtk_widget_show_all (window);
1319 g_signal_connect (pipeline, "deep_notify",
1320 G_CALLBACK (gst_object_default_deep_notify), NULL);
1325 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
1326 gst_bus_add_signal_watch (bus);
1328 // g_signal_connect (bus, "message::state-changed", (GCallback) message_received, pipeline);
1329 g_signal_connect (bus, "message::new-clock", (GCallback) message_received,
1331 g_signal_connect (bus, "message::error", (GCallback) message_received,
1333 g_signal_connect (bus, "message::warning", (GCallback) message_received,
1335 g_signal_connect (bus, "message::eos", (GCallback) message_received,
1340 g_print ("NULL pipeline\n");
1341 gst_element_set_state (pipeline, GST_STATE_NULL);
1343 g_print ("free pipeline\n");
1344 gst_object_unref (pipeline);