seek.c 51.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/* GStreamer
 *
 * seek.c: seeking sample application
 *
 * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
 *               2006 Stefan Kost <ensonic@users.sf.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
/* FIXME: remove #if 0 code
 * FIXME: is the flush_seek part after sending the seek still needed?
 *
 */
27
#include <stdlib.h>
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
28
29
30
31
32
#include <glib.h>
#include <gtk/gtk.h>
#include <gst/gst.h>
#include <string.h>

33
GST_DEBUG_CATEGORY_STATIC (seek_debug);
34
35
#define GST_CAT_DEFAULT (seek_debug)

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/* configuration */

//#define SOURCE "filesrc"
#define SOURCE "gnomevfssrc"

#define ASINK "alsasink"
//#define ASINK "osssink"

#define VSINK "xvimagesink"
//#define VSINK "sdlvideosink"
//#define VSINK "ximagesink"
//#define VSINK "aasink"
//#define VSINK "cacasink"

//#define UPDATE_INTERVAL 500
//#define UPDATE_INTERVAL 100
#define UPDATE_INTERVAL 10

/* number of milliseconds to play for after a seek */
#define SCRUB_TIME 100

/* timeout for gst_element_get_state() after a seek */
#define SEEK_TIMEOUT 40 * GST_MSECOND


61
static GList *seekable_pads = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
62
static GList *rate_pads = NULL;
63
static GList *seekable_elements = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
64

65
66
static gboolean accurate_seek = FALSE;
static gboolean keyframe_seek = FALSE;
67
static gboolean loop_seek = FALSE;
68
static gboolean flush_seek = TRUE;
69
70
static gboolean scrub = TRUE;
static gboolean play_scrub = FALSE;
71
static gdouble rate = 1.0;
72

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
73
static GstElement *pipeline;
74
75
static gint pipeline_type;
static const gchar *pipeline_spec;
76
77
static gint64 position = -1;
static gint64 duration = -1;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
78
static GtkAdjustment *adjustment;
79
static GtkWidget *hscale;
80
static gboolean stats = FALSE;
81
82
static gboolean elem_seek = FALSE;
static gboolean verbose = FALSE;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
83

84
static GstState state = GST_STATE_NULL;
85
static guint update_id = 0;
86
87
static guint seek_timeout_id = 0;
static gulong changed_id;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
88
89


90
/* pipeline construction */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
91
92
93

typedef struct
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
94
95
96
  const gchar *padname;
  GstPad *target;
  GstElement *bin;
97
98
}
dyn_link;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
99

100
static GstElement *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
101
gst_element_factory_make_or_warn (gchar * type, gchar * name)
102
103
104
105
{
  GstElement *element = gst_element_factory_make (type, name);

  if (!element) {
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
106
    g_warning ("Failed to create element %s of type %s", name, type);
107
108
109
110
111
  }

  return element;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
112
static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
113
dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
114
{
115
  gchar *padname;
116
  dyn_link *connect = (dyn_link *) data;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
117

118
119
120
  padname = gst_pad_get_name (newpad);

  if (connect->padname == NULL || !strcmp (padname, connect->padname)) {
121
122
    if (connect->bin)
      gst_bin_add (GST_BIN (pipeline), connect->bin);
123
    gst_pad_link (newpad, connect->target);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
124

125
    //seekable_pads = g_list_prepend (seekable_pads, newpad);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
126
127
    rate_pads = g_list_prepend (rate_pads, newpad);
  }
128
  g_free (padname);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
129
130
131
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
132
133
setup_dynamic_link (GstElement * element, const gchar * padname,
    GstPad * target, GstElement * bin)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
134
{
135
  dyn_link *connect;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
136

137
  connect = g_new0 (dyn_link, 1);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
138
139
140
  connect->padname = g_strdup (padname);
  connect->target = target;
  connect->bin = bin;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
141

142
  g_signal_connect (G_OBJECT (element), "pad-added", G_CALLBACK (dynamic_link),
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
143
      connect);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
144
145
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
146
147
static GstElement *
make_mod_pipeline (const gchar * location)
148
149
150
151
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
152

153
154
  pipeline = gst_pipeline_new ("app");

155
156
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("modplug", "decoder");
157
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
158
159
160
161
162
163
164
165
  //g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);

  g_object_set (G_OBJECT (src), "location", location, NULL);

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), decoder);
  gst_bin_add (GST_BIN (pipeline), audiosink);

166
167
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
168
169
170
171
172
173
174
175
176

  seekable = gst_element_get_pad (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 (decoder, "sink"));

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
177
178
static GstElement *
make_dv_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
179
180
{
  GstElement *pipeline;
181
  GstElement *src, *demux, *decoder, *audiosink, *videosink;
182
  GstElement *a_queue, *v_queue;
Wim Taymans's avatar
Wim Taymans committed
183
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
184

Wim Taymans's avatar
Wim Taymans committed
185
186
187
  pipeline = gst_pipeline_new ("app");

  src = gst_element_factory_make_or_warn (SOURCE, "src");
188
  demux = gst_element_factory_make_or_warn ("dvdemux", "demuxer");
189
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
190
  decoder = gst_element_factory_make_or_warn ("ffdec_dvvideo", "decoder");
191
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
192
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
193
  audiosink = gst_element_factory_make_or_warn ("alsasink", "a_sink");
Wim Taymans's avatar
Wim Taymans committed
194
195
196
197

  g_object_set (G_OBJECT (src), "location", location, NULL);

  gst_bin_add (GST_BIN (pipeline), src);
198
  gst_bin_add (GST_BIN (pipeline), demux);
199
  gst_bin_add (GST_BIN (pipeline), a_queue);
Wim Taymans's avatar
Wim Taymans committed
200
  gst_bin_add (GST_BIN (pipeline), audiosink);
201
  gst_bin_add (GST_BIN (pipeline), v_queue);
202
  gst_bin_add (GST_BIN (pipeline), decoder);
Wim Taymans's avatar
Wim Taymans committed
203
204
  gst_bin_add (GST_BIN (pipeline), videosink);

205
  gst_element_link (src, demux);
206
  gst_element_link (a_queue, audiosink);
207
208
  gst_element_link (v_queue, decoder);
  gst_element_link (decoder, videosink);
Wim Taymans's avatar
Wim Taymans committed
209

210
211
212
213
  setup_dynamic_link (demux, "video", gst_element_get_pad (v_queue, "sink"),
      NULL);
  setup_dynamic_link (demux, "audio", gst_element_get_pad (a_queue, "sink"),
      NULL);
214

215
216
  seekable = gst_element_get_pad (decoder, "src");
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Wim Taymans's avatar
Wim Taymans committed
217
218
219
220
221
  rate_pads = g_list_prepend (rate_pads, seekable);

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
222
223
static GstElement *
make_wav_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
224
225
226
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
227

Wim Taymans's avatar
Wim Taymans committed
228
229
  pipeline = gst_pipeline_new ("app");

230
231
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("wavparse", "decoder");
232
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
Wim Taymans's avatar
Wim Taymans committed
233
234
235
236
237
238
239

  g_object_set (G_OBJECT (src), "location", location, NULL);

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), decoder);
  gst_bin_add (GST_BIN (pipeline), audiosink);

240
  gst_element_link (src, decoder);
Wim Taymans's avatar
Wim Taymans committed
241

242
243
244
245
246
247
248
  setup_dynamic_link (decoder, "src", gst_element_get_pad (audiosink, "sink"),
      NULL);

  seekable_elements = g_list_prepend (seekable_elements, audiosink);

  /* force element seeking on this pipeline */
  elem_seek = TRUE;
Wim Taymans's avatar
Wim Taymans committed
249
250
251
252

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
253
254
static GstElement *
make_flac_pipeline (const gchar * location)
255
256
257
258
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
259

260
261
  pipeline = gst_pipeline_new ("app");

262
263
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("flacdec", "decoder");
264
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
Wim Taymans's avatar
Wim Taymans committed
265
  g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
266
267
268
269
270
271
272

  g_object_set (G_OBJECT (src), "location", location, NULL);

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), decoder);
  gst_bin_add (GST_BIN (pipeline), audiosink);

273
274
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
275
276
277
278
279
280
281
282
283

  seekable = gst_element_get_pad (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 (decoder, "sink"));

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
284
285
static GstElement *
make_sid_pipeline (const gchar * location)
286
287
288
289
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
290

291
292
  pipeline = gst_pipeline_new ("app");

293
294
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("siddec", "decoder");
295
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
296
297
298
299
300
301
302
303
  //g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);

  g_object_set (G_OBJECT (src), "location", location, NULL);

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), decoder);
  gst_bin_add (GST_BIN (pipeline), audiosink);

304
305
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
306
307
308
309
310
311
312
313
314

  seekable = gst_element_get_pad (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 (decoder, "sink"));

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
315
316
static GstElement *
make_parse_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
317
318
319
320
{
  GstElement *pipeline;
  GstElement *src, *parser, *fakesink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
321

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
322
323
  pipeline = gst_pipeline_new ("app");

324
325
326
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  parser = gst_element_factory_make_or_warn ("mpegparse", "parse");
  fakesink = gst_element_factory_make_or_warn ("fakesink", "sink");
Wim Taymans's avatar
Wim Taymans committed
327
328
  g_object_set (G_OBJECT (fakesink), "silent", TRUE, NULL);
  g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
329
330
331
332
333
334
335

  g_object_set (G_OBJECT (src), "location", location, NULL);

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), parser);
  gst_bin_add (GST_BIN (pipeline), fakesink);

336
337
  gst_element_link (src, parser);
  gst_element_link (parser, fakesink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
338
339

  seekable = gst_element_get_pad (parser, "src");
340
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
341
342
343
344
345
346
  rate_pads = g_list_prepend (rate_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (parser, "sink"));

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
347
348
static GstElement *
make_vorbis_pipeline (const gchar * location)
349
{
350
351
  GstElement *pipeline, *audio_bin;
  GstElement *src, *demux, *decoder, *convert, *audiosink;
352
  GstPad *pad, *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
353

354
355
  pipeline = gst_pipeline_new ("app");

356
  src = gst_element_factory_make_or_warn (SOURCE, "src");
357
358
359
  demux = gst_element_factory_make_or_warn ("oggdemux", "demux");
  decoder = gst_element_factory_make_or_warn ("vorbisdec", "decoder");
  convert = gst_element_factory_make_or_warn ("audioconvert", "convert");
360
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
Wim Taymans's avatar
Wim Taymans committed
361
  g_object_set (G_OBJECT (audiosink), "sync", TRUE, NULL);
362
363
364

  g_object_set (G_OBJECT (src), "location", location, NULL);

365
366
  audio_bin = gst_bin_new ("a_decoder_bin");

367
  gst_bin_add (GST_BIN (pipeline), src);
368
369
370
371
372
  gst_bin_add (GST_BIN (pipeline), demux);
  gst_bin_add (GST_BIN (audio_bin), decoder);
  gst_bin_add (GST_BIN (audio_bin), convert);
  gst_bin_add (GST_BIN (audio_bin), audiosink);
  gst_bin_add (GST_BIN (pipeline), audio_bin);
373

374
375
376
377
  gst_element_link (src, demux);
  gst_element_link (decoder, convert);
  gst_element_link (convert, audiosink);

378
379
380
381
382
383
  pad = gst_element_get_pad (decoder, "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);
384
385
386
387
388
389
390
391
392
393
394
395
396
397

  seekable = gst_element_get_pad (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 (decoder, "sink"));

  return pipeline;
}

static GstElement *
make_theora_pipeline (const gchar * location)
{
  GstElement *pipeline, *video_bin;
  GstElement *src, *demux, *decoder, *convert, *videosink;
398
  GstPad *pad, *seekable;
399
400
401
402
403
404
405

  pipeline = gst_pipeline_new ("app");

  src = gst_element_factory_make_or_warn (SOURCE, "src");
  demux = gst_element_factory_make_or_warn ("oggdemux", "demux");
  decoder = gst_element_factory_make_or_warn ("theoradec", "decoder");
  convert = gst_element_factory_make_or_warn ("ffmpegcolorspace", "convert");
Wim Taymans's avatar
Wim Taymans committed
406
  videosink = gst_element_factory_make_or_warn (VSINK, "sink");
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

  g_object_set (G_OBJECT (src), "location", location, NULL);

  video_bin = gst_bin_new ("v_decoder_bin");

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), demux);
  gst_bin_add (GST_BIN (video_bin), decoder);
  gst_bin_add (GST_BIN (video_bin), convert);
  gst_bin_add (GST_BIN (video_bin), videosink);
  gst_bin_add (GST_BIN (pipeline), video_bin);

  gst_element_link (src, demux);
  gst_element_link (decoder, convert);
  gst_element_link (convert, videosink);

423
424
425
426
427
428
  pad = gst_element_get_pad (decoder, "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);
429
430
431
432
433
434
435
436
437

  seekable = gst_element_get_pad (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 (decoder, "sink"));

  return pipeline;
}

438
439
440
441
442
443
static GstElement *
make_vorbis_theora_pipeline (const gchar * location)
{
  GstElement *pipeline, *audio_bin, *video_bin;
  GstElement *src, *demux, *a_decoder, *a_convert, *v_decoder, *v_convert;
  GstElement *audiosink, *videosink;
444
  GstElement *a_queue, *v_queue, *v_scale;
445
  GstPad *seekable;
Wim Taymans's avatar
Wim Taymans committed
446
  GstPad *pad;
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462

  pipeline = gst_pipeline_new ("app");

  src = gst_element_factory_make_or_warn (SOURCE, "src");
  g_object_set (G_OBJECT (src), "location", location, NULL);

  demux = gst_element_factory_make_or_warn ("oggdemux", "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_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
  a_decoder = gst_element_factory_make_or_warn ("vorbisdec", "a_dec");
  a_convert = gst_element_factory_make_or_warn ("audioconvert", "a_convert");
463
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
464

465
  gst_bin_add (GST_BIN (pipeline), audio_bin);
466
467
468
469
470
471

  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);

472
473
474
  gst_element_link (a_queue, a_decoder);
  gst_element_link (a_decoder, a_convert);
  gst_element_link (a_convert, audiosink);
475

Wim Taymans's avatar
Wim Taymans committed
476
477
  pad = gst_element_get_pad (a_queue, "sink");
  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
478
  gst_object_unref (pad);
479
480
481

  setup_dynamic_link (demux, NULL, gst_element_get_pad (audio_bin, "sink"),
      NULL);
482
483
484
485
486
487

  video_bin = gst_bin_new ("v_decoder_bin");
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
  v_decoder = gst_element_factory_make_or_warn ("theoradec", "v_dec");
  v_convert =
      gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_convert");
488
  v_scale = gst_element_factory_make_or_warn ("videoscale", "v_scale");
Wim Taymans's avatar
Wim Taymans committed
489
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
490
491

  gst_bin_add (GST_BIN (pipeline), video_bin);
492
493
494
495

  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);
496
  gst_bin_add (GST_BIN (video_bin), v_scale);
497
498
  gst_bin_add (GST_BIN (video_bin), videosink);

499
500
  gst_element_link_many (v_queue, v_decoder, v_convert, v_scale, videosink,
      NULL);
501

Wim Taymans's avatar
Wim Taymans committed
502
503
  pad = gst_element_get_pad (v_queue, "sink");
  gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
504
  gst_object_unref (pad);
505
506
507

  setup_dynamic_link (demux, NULL, gst_element_get_pad (video_bin, "sink"),
      NULL);
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524

  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"));

  return pipeline;
}

static GstElement *
make_avi_msmpeg4v3_mp3_pipeline (const gchar * location)
{
  GstElement *pipeline, *audio_bin, *video_bin;
  GstElement *src, *demux, *a_decoder, *a_convert, *v_decoder, *v_convert;
  GstElement *audiosink, *videosink;
  GstElement *a_queue, *v_queue;
525
  GstPad *seekable, *pad;
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541

  pipeline = gst_pipeline_new ("app");

  src = gst_element_factory_make_or_warn (SOURCE, "src");
  g_object_set (G_OBJECT (src), "location", location, 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_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
  a_convert = gst_element_factory_make_or_warn ("audioconvert", "a_convert");
542
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
543
544
545
546
547
548

  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);

549
550
551
552
  gst_element_link (a_queue, a_decoder);
  gst_element_link (a_decoder, a_convert);
  gst_element_link (a_convert, audiosink);

553
554
  gst_bin_add (GST_BIN (pipeline), audio_bin);

555
556
557
558
559
560
  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);
561
562
563
564
565
566

  video_bin = gst_bin_new ("v_decoder_bin");
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
  v_decoder = gst_element_factory_make_or_warn ("ffdec_msmpeg4", "v_dec");
  v_convert =
      gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_convert");
Wim Taymans's avatar
Wim Taymans committed
567
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
568
569
570
571
572
573

  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);

574
575
  gst_element_link_many (v_queue, v_decoder, v_convert, videosink, NULL);

576
577
  gst_bin_add (GST_BIN (pipeline), video_bin);

578
579
580
581
582
583
  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);
584
585
586
587
588
589
590
591
592
593

  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"));

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
594
595
static GstElement *
make_mp3_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
596
597
{
  GstElement *pipeline;
598
  GstElement *src, *decoder, *osssink, *queue;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
599
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
600

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
601
602
  pipeline = gst_pipeline_new ("app");

603
604
605
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("mad", "dec");
  queue = gst_element_factory_make_or_warn ("queue", "queue");
606
  osssink = gst_element_factory_make_or_warn (ASINK, "sink");
607

608
  seekable_elements = g_list_prepend (seekable_elements, osssink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
609
610

  g_object_set (G_OBJECT (src), "location", location, NULL);
611
  //g_object_set (G_OBJECT (osssink), "fragment", 0x00180008, NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
612

613
614
  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), decoder);
615
616
  gst_bin_add (GST_BIN (pipeline), queue);
  gst_bin_add (GST_BIN (pipeline), osssink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
617

618
619
  gst_element_link (src, decoder);
  gst_element_link (decoder, queue);
620
  gst_element_link (queue, osssink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
621

622
623
  seekable = gst_element_get_pad (queue, "src");
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
624
625
626
627
628
629
  rate_pads = g_list_prepend (rate_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (decoder, "sink"));

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
630
631
static GstElement *
make_avi_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
632
633
634
{
  GstElement *pipeline, *audio_bin, *video_bin;
  GstElement *src, *demux, *a_decoder, *v_decoder, *audiosink, *videosink;
635
  GstElement *a_queue = NULL, *v_queue = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
636
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
637

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
638
639
  pipeline = gst_pipeline_new ("app");

640
  src = gst_element_factory_make_or_warn (SOURCE, "src");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
641
642
  g_object_set (G_OBJECT (src), "location", location, NULL);

643
  demux = gst_element_factory_make_or_warn ("avidemux", "demux");
644
  seekable_elements = g_list_prepend (seekable_elements, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
645
646
647

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), demux);
648
  gst_element_link (src, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
649
650

  audio_bin = gst_bin_new ("a_decoder_bin");
651
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
652
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
653
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
654
655
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
656
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
657
658
  gst_bin_add (GST_BIN (audio_bin), a_queue);
  gst_bin_add (GST_BIN (audio_bin), audiosink);
Wim Taymans's avatar
Wim Taymans committed
659
  gst_element_set_state (audio_bin, GST_STATE_PAUSED);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
660

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
661
  setup_dynamic_link (demux, "audio_00", gst_element_get_pad (a_decoder,
662
          "sink"), audio_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
663
664

  seekable = gst_element_get_pad (a_queue, "src");
665
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
666
  rate_pads = g_list_prepend (rate_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
667
668
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink"));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
669
670

  video_bin = gst_bin_new ("v_decoder_bin");
Wim Taymans's avatar
Wim Taymans committed
671
  v_decoder = gst_element_factory_make_or_warn ("ffmpegdecall", "v_dec");
672
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
673
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
674
675
  gst_element_link (v_decoder, v_queue);
  gst_element_link (v_queue, videosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
676
  gst_bin_add (GST_BIN (video_bin), v_decoder);
677
678
  gst_bin_add (GST_BIN (video_bin), v_queue);
  gst_bin_add (GST_BIN (video_bin), videosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
679

Wim Taymans's avatar
Wim Taymans committed
680
  gst_element_set_state (video_bin, GST_STATE_PAUSED);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
681

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
682
  setup_dynamic_link (demux, "video_00", gst_element_get_pad (v_decoder,
683
          "sink"), video_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
684
685

  seekable = gst_element_get_pad (v_queue, "src");
686
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
687
  rate_pads = g_list_prepend (rate_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
688
689
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (v_decoder, "sink"));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
690
691
692
693

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
694
695
static GstElement *
make_mpeg_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
696
697
{
  GstElement *pipeline, *audio_bin, *video_bin;
698
699
  GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter;
  GstElement *audiosink, *videosink;
700
  GstElement *a_queue, *v_queue;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
701
  GstPad *seekable;
702
  GstPad *pad;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
703

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
704
705
  pipeline = gst_pipeline_new ("app");

706
  src = gst_element_factory_make_or_warn (SOURCE, "src");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
707
708
  g_object_set (G_OBJECT (src), "location", location, NULL);

709
710
  //demux = gst_element_factory_make_or_warn ("mpegdemux", "demux");
  demux = gst_element_factory_make_or_warn ("flupsdemux", "demux");
711

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
712
713
  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), demux);
714
  gst_element_link (src, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
715
716

  audio_bin = gst_bin_new ("a_decoder_bin");
717
718
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
719
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
720
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
721
722
  gst_bin_add (GST_BIN (audio_bin), a_queue);
  gst_bin_add (GST_BIN (audio_bin), audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
723

724
725
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
726

727
728
729
730
731
732
733
734
  gst_bin_add (GST_BIN (pipeline), audio_bin);

  pad = gst_element_get_pad (a_decoder, "sink");
  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
  gst_object_unref (pad);

  setup_dynamic_link (demux, "audio_c0", gst_element_get_pad (audio_bin,
          "sink"), NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
735
736

  video_bin = gst_bin_new ("v_decoder_bin");
737
738
  v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
739
  v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter");
740
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
741

742
743
744
745
746
747
748
  gst_bin_add (GST_BIN (video_bin), v_decoder);
  gst_bin_add (GST_BIN (video_bin), v_queue);
  gst_bin_add (GST_BIN (video_bin), v_filter);
  gst_bin_add (GST_BIN (video_bin), videosink);

  gst_element_link (v_decoder, v_queue);
  gst_element_link (v_queue, v_filter);
749
  gst_element_link (v_filter, videosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
750

751
  gst_bin_add (GST_BIN (pipeline), video_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
752

753
754
755
756
757
758
759
760
  pad = gst_element_get_pad (v_decoder, "sink");
  gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
  gst_object_unref (pad);

  setup_dynamic_link (demux, "video_e0", gst_element_get_pad (video_bin,
          "sink"), NULL);

  seekable = gst_element_get_pad (v_filter, "src");
761
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
762
  rate_pads = g_list_prepend (rate_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
763
764
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (v_decoder, "sink"));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
765
766
767
768

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
769
770
static GstElement *
make_mpegnt_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
771
772
773
774
{
  GstElement *pipeline, *audio_bin, *video_bin;
  GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter;
  GstElement *audiosink, *videosink;
775
  GstElement *a_queue;
Wim Taymans's avatar
Wim Taymans committed
776
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
777

Wim Taymans's avatar
Wim Taymans committed
778
779
780
781
782
783
784
785
786
787
788
789
  pipeline = gst_pipeline_new ("app");

  src = gst_element_factory_make_or_warn (SOURCE, "src");
  g_object_set (G_OBJECT (src), "location", location, NULL);

  demux = gst_element_factory_make_or_warn ("mpegdemux", "demux");
  //g_object_set (G_OBJECT (demux), "sync", TRUE, NULL);

  seekable_elements = g_list_prepend (seekable_elements, demux);

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), demux);
790
  gst_element_link (src, demux);
Wim Taymans's avatar
Wim Taymans committed
791
792
793
794

  audio_bin = gst_bin_new ("a_decoder_bin");
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
795
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
Wim Taymans's avatar
Wim Taymans committed
796
797
  //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
  g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
798
799
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Wim Taymans's avatar
Wim Taymans committed
800
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
801
802
  gst_bin_add (GST_BIN (audio_bin), a_queue);
  gst_bin_add (GST_BIN (audio_bin), audiosink);
Wim Taymans's avatar
Wim Taymans committed
803

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
804
  setup_dynamic_link (demux, "audio_00", gst_element_get_pad (a_decoder,
805
          "sink"), audio_bin);
Wim Taymans's avatar
Wim Taymans committed
806
807
808
809

  seekable = gst_element_get_pad (a_queue, "src");
  seekable_pads = g_list_prepend (seekable_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
810
811
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink"));
Wim Taymans's avatar
Wim Taymans committed
812
813
814

  video_bin = gst_bin_new ("v_decoder_bin");
  v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
815
  v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter");
816
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
817
  gst_element_link_many (v_decoder, v_filter, videosink, NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
818

Wim Taymans's avatar
Wim Taymans committed
819
820
  gst_bin_add_many (GST_BIN (video_bin), v_decoder, v_filter, videosink, NULL);

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
821
  setup_dynamic_link (demux, "video_00", gst_element_get_pad (v_decoder,
822
          "sink"), video_bin);
Wim Taymans's avatar
Wim Taymans committed
823
824
825
826

  seekable = gst_element_get_pad (v_decoder, "src");
  seekable_pads = g_list_prepend (seekable_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
827
828
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (v_decoder, "sink"));
Wim Taymans's avatar
Wim Taymans committed
829
830
831
832

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
833
834
static GstElement *
make_playerbin_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
835
{
836
  GstElement *player;
837
838
839
840

  player = gst_element_factory_make ("playbin", "player");
  g_assert (player);

841
  g_object_set (G_OBJECT (player), "uri", location, NULL);
842
843
844
845
846
847
848

  seekable_elements = g_list_prepend (seekable_elements, player);

  /* force element seeking on this pipeline */
  elem_seek = TRUE;

  return player;
Wim Taymans's avatar
Wim Taymans committed
849
850
}

851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
static GstElement *
make_playerbin2_pipeline (const gchar * location)
{
  GstElement *player;

  player = gst_element_factory_make ("playbin2", "player");
  g_assert (player);

  g_object_set (G_OBJECT (player), "uri", location, NULL);

  seekable_elements = g_list_prepend (seekable_elements, player);

  /* force element seeking on this pipeline */
  elem_seek = TRUE;

  return player;
}

869
#ifndef GST_DISABLE_PARSE
870
871
872
873
874
875
876
877
878
879
880
881
882
883
static GstElement *
make_parselaunch_pipeline (const gchar * description)
{
  GstElement *pipeline;
  GError *error;

  pipeline = gst_parse_launch (description, &error);

  seekable_elements = g_list_prepend (seekable_elements, pipeline);

  elem_seek = TRUE;

  return pipeline;
}
884
#endif
885

886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
typedef struct
{
  gchar *name;
  GstElement *(*func) (const gchar * location);
}
Pipeline;

static Pipeline pipelines[] = {
  {"mp3", make_mp3_pipeline},
  {"avi", make_avi_pipeline},
  {"mpeg1", make_mpeg_pipeline},
  {"mpegparse", make_parse_pipeline},
  {"vorbis", make_vorbis_pipeline},
  {"theora", make_theora_pipeline},
  {"ogg/v/t", make_vorbis_theora_pipeline},
  {"avi/msmpeg4v3/mp3", make_avi_msmpeg4v3_mp3_pipeline},
  {"sid", make_sid_pipeline},
  {"flac", make_flac_pipeline},
  {"wav", make_wav_pipeline},
  {"mod", make_mod_pipeline},
  {"dv", make_dv_pipeline},
  {"mpeg1nothreads", make_mpegnt_pipeline},
  {"playerbin", make_playerbin_pipeline},
#ifndef GST_DISABLE_PARSE
  {"parse-launch", make_parselaunch_pipeline},
#endif
912
  {"playerbin2", make_playerbin2_pipeline},
913
914
915
916
917
918
919
  {NULL, NULL},
};

#define NUM_TYPES       ((sizeof (pipelines) / sizeof (Pipeline)) - 1)

/* ui callbacks and helpers */

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
920
921
static gchar *
format_value (GtkScale * scale, gdouble value)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
922
{
923
924
925
926
927
928
929
  gint64 real;
  gint64 seconds;
  gint64 subseconds;

  real = value * duration / 100;
  seconds = (gint64) real / GST_SECOND;
  subseconds = (gint64) real / (GST_SECOND / 100);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
930

931
932
  return g_strdup_printf ("%02" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT ":%02"
      G_GINT64_FORMAT, seconds / 60, seconds % 60, subseconds % 100);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
933
934
935
936
937
938
}

typedef struct
{
  const gchar *name;
  const GstFormat format;
939
940
}
seek_format;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
941

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
942
943
944
945
946
947
static seek_format seek_formats[] = {
  {"tim", GST_FORMAT_TIME},
  {"byt", GST_FORMAT_BYTES},
  {"buf", GST_FORMAT_BUFFERS},
  {"def", GST_FORMAT_DEFAULT},
  {NULL, 0},
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
};

G_GNUC_UNUSED static void
query_rates (void)
{
  GList *walk = rate_pads;

  while (walk) {
    GstPad *pad = GST_PAD (walk->data);
    gint i = 0;

    g_print ("rate/sec  %8.8s: ", GST_PAD_NAME (pad));
    while (seek_formats[i].name) {
      gint64 value;
      GstFormat format;

      format = seek_formats[i].format;

Wim Taymans's avatar
Wim Taymans committed
966
967
      if (gst_pad_query_convert (pad, GST_FORMAT_TIME, GST_SECOND, &format,
              &value)) {
968
        g_print ("%s %13" G_GINT64_FORMAT " | ", seek_formats[i].name, value);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
969
      } else {
970
        g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
971
972
973
974
975
976
977
978
979
980
981
      }

      i++;
    }
    g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad));

    walk = g_list_next (walk);
  }
}

G_GNUC_UNUSED static void
982
983
984
985
986
987
988
989
990
991
query_positions_elems ()
{
  GList *walk = seekable_elements;

  while (walk) {
    GstElement *element = GST_ELEMENT (walk->data);
    gint i = 0;

    g_print ("positions %8.8s: ", GST_ELEMENT_NAME (element));
    while (seek_formats[i].name) {
Wim Taymans's avatar
Wim Taymans committed
992
      gint64 position, total;
993
994
995
      GstFormat format;

      format = seek_formats[i].format;
Wim Taymans's avatar
Wim Taymans committed
996

Wim Taymans's avatar
Wim Taymans committed
997
998
      if (gst_element_query_position (element, &format, &position) &&
          gst_element_query_duration (element, &format, &total)) {
Wim Taymans's avatar
Wim Taymans committed
999
1000
        g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ",
            seek_formats[i].name, position, total);
1001
      } else {
Wim Taymans's avatar
Wim Taymans committed
1002
1003
        g_print ("%s %13.13s / %13.13s | ", seek_formats[i].name, "*NA*",
            "*NA*");
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
      }
      i++;
    }
    g_print (" %s\n", GST_ELEMENT_NAME (element));

    walk = g_list_next (walk);
  }
}

G_GNUC_UNUSED static void
query_positions_pads ()
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1015
{
1016
1017
1018
1019
1020
1021
1022
1023
1024
  GList *walk = seekable_pads;

  while (walk) {
    GstPad *pad = GST_PAD (walk->data);
    gint i = 0;

    g_print ("positions %8.8s: ", GST_PAD_NAME (pad));
    while (seek_formats[i].name) {
      GstFormat format;
Wim Taymans's avatar
Wim Taymans committed
1025
      gint64 position, total;
1026
1027

      format = seek_formats[i].format;
Wim Taymans's avatar
Wim Taymans committed
1028

Wim Taymans's avatar
Wim Taymans committed
1029
1030
      if (gst_pad_query_position (pad, &format, &position) &&
          gst_pad_query_duration (pad, &format, &total)) {
Wim Taymans's avatar
Wim Taymans committed
1031
1032
        g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ",
            seek_formats[i].name, position, total);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1033
      } else {
Wim Taymans's avatar
Wim Taymans committed
1034
1035
        g_print ("%s %13.13s / %13.13s | ", seek_formats[i].name, "*NA*",
            "*NA*");
1036
      }
Wim Taymans's avatar
Wim Taymans committed
1037

1038
      i++;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1039
    }
1040
1041
1042
    g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad));

    walk = g_list_next (walk);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1043
1044
1045
  }
}

1046
1047
1048
1049
1050
1051
1052
1053
static gboolean start_seek (GtkWidget * widget, GdkEventButton * event,
    gpointer user_data);
static gboolean stop_seek (GtkWidget * widget, GdkEventButton * event,
    gpointer user_data);

static void
set_scale (gdouble value)
{
1054
1055
1056
1057
  g_signal_handlers_block_by_func (hscale, (void *) start_seek,
      (void *) pipeline);
  g_signal_handlers_block_by_func (hscale, (void *) stop_seek,
      (void *) pipeline);
1058
  gtk_adjustment_set_value (adjustment, value);
1059
1060
1061
1062
  g_signal_handlers_unblock_by_func (hscale, (void *) start_seek,
      (void *) pipeline);
  g_signal_handlers_unblock_by_func (hscale, (void *) stop_seek,
      (void *) pipeline);
1063
1064
1065
  gtk_widget_queue_draw (hscale);
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1066
static gboolean
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1067
update_scale (gpointer data)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1068
{
1069
  GstFormat format = GST_FORMAT_TIME;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1070

1071
1072
  //position = 0;
  //duration = 0;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1073

1074
1075
1076
  if (elem_seek) {
    if (seekable_elements) {
      GstElement *element = GST_ELEMENT (seekable_elements->data);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1077

Wim Taymans's avatar
Wim Taymans committed
1078
1079
      gst_element_query_position (element, &format, &position);
      gst_element_query_duration (element, &format, &duration);
1080
1081
1082
1083
1084
    }
  } else {
    if (seekable_pads) {
      GstPad *pad = GST_PAD (seekable_pads->data);

Wim Taymans's avatar
Wim Taymans committed
1085
1086
      gst_pad_query_position (pad, &format, &position);
      gst_pad_query_duration (pad, &format, &duration);
1087
    }
1088
  }
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1089

1090
  if (stats) {
1091
1092
1093
1094
1095
    if (elem_seek) {
      query_positions_elems ();
    } else {
      query_positions_pads ();
    }
1096
    query_rates ();
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1097
  }
1098
1099
  if (position >= duration)
    duration = position;