seek.c 37.6 KB
Newer Older
1
#include <stdlib.h>
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
2
3
4
5
6
#include <glib.h>
#include <gtk/gtk.h>
#include <gst/gst.h>
#include <string.h>

7
static GList *seekable_pads = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
8
static GList *rate_pads = NULL;
9
static GList *seekable_elements = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
10
11

static GstElement *pipeline;
Wim Taymans's avatar
Wim Taymans committed
12
13
static gint64 position;
static gint64 duration;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
14
static GtkAdjustment *adjustment;
15
static GtkWidget *hscale;
16
static gboolean stats = FALSE;
17
18
static gboolean elem_seek = FALSE;
static gboolean verbose = FALSE;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
19
20

static guint update_id;
21
22
static guint seek_timeout_id = 0;
static gulong changed_id;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
23

Wim Taymans's avatar
Wim Taymans committed
24
//#define SOURCE "filesrc"
25
#define SOURCE "gnomevfssrc"
26
27
#define ASINK "alsasink"
//#define ASINK "osssink"
Wim Taymans's avatar
Wim Taymans committed
28
29
30
#define VSINK "xvimagesink"
//#define VSINK "ximagesink"
//#define VSINK "aasink"
31
//#define VSINK "cacasink"
32

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
33
34
#define UPDATE_INTERVAL 500

35
/* number of milliseconds to play for after a seek */
Wim Taymans's avatar
Wim Taymans committed
36
37
//#define SCRUB_TIME 250
//#define SCRUB
38

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
39
#define THREAD
40
#define PAD_SEEK
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
41
42
43

typedef struct
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
44
45
46
  const gchar *padname;
  GstPad *target;
  GstElement *bin;
47
48
}
dyn_link;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
49

50
static GstElement *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
51
gst_element_factory_make_or_warn (gchar * type, gchar * name)
52
53
54
55
{
  GstElement *element = gst_element_factory_make (type, name);

  if (!element) {
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
56
    g_warning ("Failed to create element %s of type %s", name, type);
57
58
59
60
61
  }

  return element;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
62
static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
63
dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
64
{
65
  dyn_link *connect = (dyn_link *) data;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
66

67
68
69
70
  if (connect->padname == NULL ||
      !strcmp (gst_pad_get_name (newpad), connect->padname)) {
    if (connect->bin)
      gst_bin_add (GST_BIN (pipeline), connect->bin);
71
    gst_pad_link (newpad, connect->target);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
72

73
    //seekable_pads = g_list_prepend (seekable_pads, newpad);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
74
75
76
77
78
    rate_pads = g_list_prepend (rate_pads, newpad);
  }
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
79
80
setup_dynamic_link (GstElement * element, const gchar * padname,
    GstPad * target, GstElement * bin)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
81
{
82
  dyn_link *connect;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
83

84
  connect = g_new0 (dyn_link, 1);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
85
86
87
  connect->padname = g_strdup (padname);
  connect->target = target;
  connect->bin = bin;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
88

89
  g_signal_connect (G_OBJECT (element), "pad-added", G_CALLBACK (dynamic_link),
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
90
      connect);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
91
92
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
93
94
static GstElement *
make_mod_pipeline (const gchar * location)
95
96
97
98
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
99

100
101
  pipeline = gst_pipeline_new ("app");

102
103
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("modplug", "decoder");
104
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
105
106
107
108
109
110
111
112
  //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);

113
114
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
115
116
117
118
119
120
121
122
123

  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
124
125
static GstElement *
make_dv_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
126
127
{
  GstElement *pipeline;
128
  GstElement *src, *demux, *decoder, *audiosink, *videosink;
129
  GstElement *a_queue, *v_queue;
Wim Taymans's avatar
Wim Taymans committed
130
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
131

Wim Taymans's avatar
Wim Taymans committed
132
133
134
  pipeline = gst_pipeline_new ("app");

  src = gst_element_factory_make_or_warn (SOURCE, "src");
135
  demux = gst_element_factory_make_or_warn ("dvdemux", "demuxer");
136
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
137
138
  decoder = gst_element_factory_make_or_warn ("ffdec_dvvideo", "decoder");
  videosink = gst_element_factory_make_or_warn ("xvimagesink", "v_sink");
139
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
140
  audiosink = gst_element_factory_make_or_warn ("alsasink", "a_sink");
Wim Taymans's avatar
Wim Taymans committed
141
142
143
144

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

  gst_bin_add (GST_BIN (pipeline), src);
145
  gst_bin_add (GST_BIN (pipeline), demux);
146
  gst_bin_add (GST_BIN (pipeline), a_queue);
Wim Taymans's avatar
Wim Taymans committed
147
  gst_bin_add (GST_BIN (pipeline), audiosink);
148
  gst_bin_add (GST_BIN (pipeline), v_queue);
149
  gst_bin_add (GST_BIN (pipeline), decoder);
Wim Taymans's avatar
Wim Taymans committed
150
151
  gst_bin_add (GST_BIN (pipeline), videosink);

152
  gst_element_link (src, demux);
153
  gst_element_link (a_queue, audiosink);
154
155
  gst_element_link (v_queue, decoder);
  gst_element_link (decoder, videosink);
Wim Taymans's avatar
Wim Taymans committed
156

157
158
159
160
  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);
161

162
163
  seekable = gst_element_get_pad (decoder, "src");
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Wim Taymans's avatar
Wim Taymans committed
164
165
166
167
168
  rate_pads = g_list_prepend (rate_pads, seekable);

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
169
170
static GstElement *
make_wav_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
171
172
173
174
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
175

Wim Taymans's avatar
Wim Taymans committed
176
177
  pipeline = gst_pipeline_new ("app");

178
179
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("wavparse", "decoder");
180
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
Wim Taymans's avatar
Wim Taymans committed
181
182
183
184
185
186
187
188
  //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);

189
190
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
Wim Taymans's avatar
Wim Taymans committed
191
192
193
194
195
196
197
198
199

  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
200
201
static GstElement *
make_flac_pipeline (const gchar * location)
202
203
204
205
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
206

207
208
  pipeline = gst_pipeline_new ("app");

209
210
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("flacdec", "decoder");
211
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
Wim Taymans's avatar
Wim Taymans committed
212
  g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
213
214
215
216
217
218
219

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

220
221
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
222
223
224
225
226
227
228
229
230

  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
231
232
static GstElement *
make_sid_pipeline (const gchar * location)
233
234
235
236
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
237

238
239
  pipeline = gst_pipeline_new ("app");

240
241
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("siddec", "decoder");
242
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
243
244
245
246
247
248
249
250
  //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);

251
252
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
253
254
255
256
257
258
259
260
261

  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
262
263
static GstElement *
make_parse_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
264
265
266
267
{
  GstElement *pipeline;
  GstElement *src, *parser, *fakesink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
268

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
269
270
  pipeline = gst_pipeline_new ("app");

271
272
273
  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
274
275
  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
276
277
278
279
280
281
282

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

283
284
  gst_element_link (src, parser);
  gst_element_link (parser, fakesink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
285
286

  seekable = gst_element_get_pad (parser, "src");
287
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
288
289
290
291
292
293
  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
294
295
static GstElement *
make_vorbis_pipeline (const gchar * location)
296
{
297
298
  GstElement *pipeline, *audio_bin;
  GstElement *src, *demux, *decoder, *convert, *audiosink;
299
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
300

301
302
  pipeline = gst_pipeline_new ("app");

303
  src = gst_element_factory_make_or_warn (SOURCE, "src");
304
305
306
  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");
307
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
Wim Taymans's avatar
Wim Taymans committed
308
  g_object_set (G_OBJECT (audiosink), "sync", TRUE, NULL);
309
310
311

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

312
313
  audio_bin = gst_bin_new ("a_decoder_bin");

314
  gst_bin_add (GST_BIN (pipeline), src);
315
316
317
318
319
  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);
320

321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
  gst_element_link (src, demux);
  gst_element_link (decoder, convert);
  gst_element_link (convert, audiosink);

  setup_dynamic_link (demux, NULL, gst_element_get_pad (decoder, "sink"), NULL);

  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;
  GstElement *queue;
  GstPad *seekable;

  pipeline = gst_pipeline_new ("app");

  src = gst_element_factory_make_or_warn (SOURCE, "src");
  demux = gst_element_factory_make_or_warn ("oggdemux", "demux");
  queue = gst_element_factory_make_or_warn ("queue", "queue");
  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
350
  videosink = gst_element_factory_make_or_warn (VSINK, "sink");
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369

  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 (pipeline), queue);
  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 (queue, decoder);
  gst_element_link (decoder, convert);
  gst_element_link (convert, videosink);

  setup_dynamic_link (demux, NULL, gst_element_get_pad (queue, "sink"), NULL);
370
371
372
373
374
375
376
377
378

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

379
380
381
382
383
384
385
386
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;
  GstElement *a_queue, *v_queue;
  GstPad *seekable;
Wim Taymans's avatar
Wim Taymans committed
387
  GstPad *pad;
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403

  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");
404
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
405

406
  gst_bin_add (GST_BIN (pipeline), audio_bin);
407
408
409
410
411
412

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

413
414
415
  gst_element_link (a_queue, a_decoder);
  gst_element_link (a_decoder, a_convert);
  gst_element_link (a_convert, audiosink);
416

Wim Taymans's avatar
Wim Taymans committed
417
418
419
  pad = gst_element_get_pad (a_queue, "sink");
  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
  gst_object_unref (GST_OBJECT_CAST (pad));
420
421
422

  setup_dynamic_link (demux, NULL, gst_element_get_pad (audio_bin, "sink"),
      NULL);
423
424
425
426
427
428

  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");
Wim Taymans's avatar
Wim Taymans committed
429
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
430
431

  gst_bin_add (GST_BIN (pipeline), video_bin);
432
433
434
435
436
437

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

438
  gst_element_link_many (v_queue, v_decoder, v_convert, videosink, NULL);
439

Wim Taymans's avatar
Wim Taymans committed
440
441
442
  pad = gst_element_get_pad (v_queue, "sink");
  gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
  gst_object_unref (GST_OBJECT_CAST (pad));
443
444
445

  setup_dynamic_link (demux, NULL, gst_element_get_pad (video_bin, "sink"),
      NULL);
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479

  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;
  GstPad *seekable;

  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");
480
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499

  gst_element_link (a_queue, a_decoder);
  gst_element_link (a_decoder, a_convert);
  gst_element_link (a_convert, audiosink);

  gst_bin_add (GST_BIN (audio_bin), a_queue);
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
  gst_bin_add (GST_BIN (audio_bin), a_convert);
  gst_bin_add (GST_BIN (audio_bin), audiosink);

  gst_bin_add (GST_BIN (pipeline), audio_bin);

  setup_dynamic_link (demux, NULL, gst_element_get_pad (a_queue, "sink"), NULL);

  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
500
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
  gst_element_link_many (v_queue, v_decoder, v_convert, videosink, NULL);

  gst_bin_add (GST_BIN (video_bin), v_queue);
  gst_bin_add (GST_BIN (video_bin), v_decoder);
  gst_bin_add (GST_BIN (video_bin), v_convert);
  gst_bin_add (GST_BIN (video_bin), videosink);

  gst_bin_add (GST_BIN (pipeline), video_bin);

  setup_dynamic_link (demux, NULL, gst_element_get_pad (v_queue, "sink"), NULL);

  seekable = gst_element_get_pad (a_decoder, "src");
  seekable_pads = g_list_prepend (seekable_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, seekable);
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink"));

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
521
522
static GstElement *
make_mp3_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
523
524
{
  GstElement *pipeline;
525
  GstElement *src, *decoder, *osssink, *queue;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
526
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
527

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
528
529
  pipeline = gst_pipeline_new ("app");

530
531
532
  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");
533
  osssink = gst_element_factory_make_or_warn (ASINK, "sink");
534

535
  seekable_elements = g_list_prepend (seekable_elements, osssink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
536
537

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

540
541
  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), decoder);
542
543
  gst_bin_add (GST_BIN (pipeline), queue);
  gst_bin_add (GST_BIN (pipeline), osssink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
544

545
546
  gst_element_link (src, decoder);
  gst_element_link (decoder, queue);
547
  gst_element_link (queue, osssink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
548

549
550
  seekable = gst_element_get_pad (queue, "src");
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
551
552
553
554
555
556
  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
557
558
static GstElement *
make_avi_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
559
560
561
{
  GstElement *pipeline, *audio_bin, *video_bin;
  GstElement *src, *demux, *a_decoder, *v_decoder, *audiosink, *videosink;
562
  GstElement *a_queue = NULL, *v_queue = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
563
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
564

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
565
566
  pipeline = gst_pipeline_new ("app");

567
  src = gst_element_factory_make_or_warn (SOURCE, "src");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
568
569
  g_object_set (G_OBJECT (src), "location", location, NULL);

570
  demux = gst_element_factory_make_or_warn ("avidemux", "demux");
571
  seekable_elements = g_list_prepend (seekable_elements, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
572
573
574

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), demux);
575
  gst_element_link (src, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
576
577

  audio_bin = gst_bin_new ("a_decoder_bin");
578
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
579
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
580
  //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
581
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
582
583
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
584
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
585
586
  gst_bin_add (GST_BIN (audio_bin), a_queue);
  gst_bin_add (GST_BIN (audio_bin), audiosink);
Wim Taymans's avatar
Wim Taymans committed
587
  gst_element_set_state (audio_bin, GST_STATE_PAUSED);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
588

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
589
  setup_dynamic_link (demux, "audio_00", gst_element_get_pad (a_decoder,
590
          "sink"), audio_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
591
592

  seekable = gst_element_get_pad (a_queue, "src");
593
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
594
  rate_pads = g_list_prepend (rate_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
595
596
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink"));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
597
598

  video_bin = gst_bin_new ("v_decoder_bin");
599
  //v_decoder = gst_element_factory_make_or_warn ("identity", "v_dec");
Wim Taymans's avatar
Wim Taymans committed
600
  //v_decoder = gst_element_factory_make_or_warn ("windec", "v_dec");
Wim Taymans's avatar
Wim Taymans committed
601
  v_decoder = gst_element_factory_make_or_warn ("ffmpegdecall", "v_dec");
602
  videosink = gst_element_factory_make_or_warn ("ximagesink", "v_sink");
603
  //videosink = gst_element_factory_make_or_warn ("fakesink", "v_sink");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
604
  //g_object_set (G_OBJECT (videosink), "sync", TRUE, NULL);
605
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
Wim Taymans's avatar
Wim Taymans committed
606
  //g_object_set (G_OBJECT (v_queue), "max_level", 10, NULL);
607
608
  gst_element_link (v_decoder, v_queue);
  gst_element_link (v_queue, videosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
609
  gst_bin_add (GST_BIN (video_bin), v_decoder);
610
611
  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
612

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

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
615
  setup_dynamic_link (demux, "video_00", gst_element_get_pad (v_decoder,
616
          "sink"), video_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
617
618

  seekable = gst_element_get_pad (v_queue, "src");
619
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
620
  rate_pads = g_list_prepend (rate_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
621
622
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (v_decoder, "sink"));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
623
624
625
626

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
627
628
static GstElement *
make_mpeg_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
629
630
{
  GstElement *pipeline, *audio_bin, *video_bin;
631
632
  GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter;
  GstElement *audiosink, *videosink;
633
  GstElement *a_queue, *v_queue;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
634
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
635

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
636
637
  pipeline = gst_pipeline_new ("app");

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

641
  demux = gst_element_factory_make_or_warn ("mpegdemux", "demux");
Wim Taymans's avatar
Wim Taymans committed
642
  g_object_set (G_OBJECT (demux), "sync", FALSE, NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
643

644
645
  seekable_elements = g_list_prepend (seekable_elements, demux);

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
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
652
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
653
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
654
  g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
655
656
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
657
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
658
659
  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
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");
671
  v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
Wim Taymans's avatar
Wim Taymans committed
672
  //g_object_set (G_OBJECT (video_thread), "priority", 2, NULL);
673
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
674
  v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter");
675
  videosink = gst_element_factory_make_or_warn ("ximagesink", "v_sink");
676
  gst_element_link_many (v_decoder, v_queue, v_filter, NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
677

678
  gst_element_link (v_filter, videosink);
679
680
  gst_bin_add_many (GST_BIN (video_bin), v_decoder, NULL);
  gst_bin_add_many (GST_BIN (video_bin), v_queue, v_filter, videosink, NULL);
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_mpegnt_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
696
697
698
699
{
  GstElement *pipeline, *audio_bin, *video_bin;
  GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter;
  GstElement *audiosink, *videosink;
700
  GstElement *a_queue;
Wim Taymans's avatar
Wim Taymans committed
701
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
702

Wim Taymans's avatar
Wim Taymans committed
703
704
705
706
707
708
709
710
711
712
713
714
  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);
715
  gst_element_link (src, demux);
Wim Taymans's avatar
Wim Taymans committed
716
717
718
719

  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");
720
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
Wim Taymans's avatar
Wim Taymans committed
721
722
  //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
  g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
723
724
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Wim Taymans's avatar
Wim Taymans committed
725
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
726
727
  gst_bin_add (GST_BIN (audio_bin), a_queue);
  gst_bin_add (GST_BIN (audio_bin), audiosink);
Wim Taymans's avatar
Wim Taymans committed
728

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
729
  setup_dynamic_link (demux, "audio_00", gst_element_get_pad (a_decoder,
730
          "sink"), audio_bin);
Wim Taymans's avatar
Wim Taymans committed
731
732
733
734

  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
735
736
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink"));
Wim Taymans's avatar
Wim Taymans committed
737
738
739

  video_bin = gst_bin_new ("v_decoder_bin");
  v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
740
  v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter");
741
  videosink = gst_element_factory_make_or_warn ("ximagesink", "v_sink");
742
  gst_element_link_many (v_decoder, v_filter, videosink, NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
743

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

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
746
  setup_dynamic_link (demux, "video_00", gst_element_get_pad (v_decoder,
747
          "sink"), video_bin);
Wim Taymans's avatar
Wim Taymans committed
748
749
750
751

  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
752
753
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (v_decoder, "sink"));
Wim Taymans's avatar
Wim Taymans committed
754
755
756
757

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
758
759
static GstElement *
make_playerbin_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
760
{
761
  GstElement *player;
762
763
764
765

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

766
  g_object_set (G_OBJECT (player), "uri", location, NULL);
767
768
769
770
771
772
773

  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
774
775
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
776
777
static gchar *
format_value (GtkScale * scale, gdouble value)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
778
{
779
780
781
782
783
784
785
  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
786

787
788
  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
789
790
791
792
793
794
}

typedef struct
{
  const gchar *name;
  const GstFormat format;
795
796
}
seek_format;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
797

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
798
799
800
801
802
803
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
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
};

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
822
823
      if (gst_pad_query_convert (pad, GST_FORMAT_TIME, GST_SECOND, &format,
              &value)) {
824
        g_print ("%s %13" G_GINT64_FORMAT " | ", seek_formats[i].name, value);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
825
      } else {
826
        g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
827
828
829
830
831
832
833
834
835
836
837
      }

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

    walk = g_list_next (walk);
  }
}

G_GNUC_UNUSED static void
838
839
840
841
842
843
844
845
846
847
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
848
      gint64 position, total;
849
850
851
      GstFormat format;

      format = seek_formats[i].format;
Wim Taymans's avatar
Wim Taymans committed
852
853
854
855

      if (gst_element_query_position (element, &format, &position, &total)) {
        g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ",
            seek_formats[i].name, position, total);
856
      } else {
Wim Taymans's avatar
Wim Taymans committed
857
858
        g_print ("%s %13.13s / %13.13s | ", seek_formats[i].name, "*NA*",
            "*NA*");
859
860
861
862
863
864
865
866
867
868
869
      }
      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
870
{
871
872
873
874
875
876
877
878
879
  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
880
      gint64 position, total;
881
882

      format = seek_formats[i].format;
Wim Taymans's avatar
Wim Taymans committed
883
884
885
886

      if (gst_pad_query_position (pad, &format, &position, &total)) {
        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
887
      } else {
Wim Taymans's avatar
Wim Taymans committed
888
889
        g_print ("%s %13.13s / %13.13s | ", seek_formats[i].name, "*NA*",
            "*NA*");
890
      }
Wim Taymans's avatar
Wim Taymans committed
891

892
      i++;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
893
    }
894
895
896
    g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad));

    walk = g_list_next (walk);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
897
898
899
900
  }
}

static gboolean
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
901
update_scale (gpointer data)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
902
903
{
  GstClock *clock;
Wim Taymans's avatar
Wim Taymans committed
904
  GstFormat format;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
905

Wim Taymans's avatar
Wim Taymans committed
906
  position = 0;
907
  duration = 0;
908
  clock = gst_pipeline_get_clock (GST_PIPELINE (pipeline));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
909

Wim Taymans's avatar
Wim Taymans committed
910
911
  format = GST_FORMAT_TIME;

912
913
914
  if (elem_seek) {
    if (seekable_elements) {
      GstElement *element = GST_ELEMENT (seekable_elements->data);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
915

Wim Taymans's avatar
Wim Taymans committed
916
      gst_element_query_position (element, &format, &position, &duration);
917
918
919
920
921
    }
  } else {
    if (seekable_pads) {
      GstPad *pad = GST_PAD (seekable_pads->data);

Wim Taymans's avatar
Wim Taymans committed
922
      gst_pad_query_position (pad, &format, &position, &duration);
923
    }
924
  }
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
925

926
  if (stats) {
927
    if (clock) {
David Schleef's avatar
David Schleef committed
928
929
      g_print ("clock:                  %13" G_GUINT64_FORMAT "  (%s)\n",
          position, gst_object_get_name (GST_OBJECT (clock)));
930
931
932
933
934
935
936
    }

    if (elem_seek) {
      query_positions_elems ();
    } else {
      query_positions_pads ();
    }
937
    query_rates ();
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
938
  }
939
940
  if (position >= duration)
    duration = position;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
941
942
943

  if (duration > 0) {
    gtk_adjustment_set_value (adjustment, position * 100.0 / duration);
944
    gtk_widget_queue_draw (hscale);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
945
946
  }

Wim Taymans's avatar
Wim Taymans committed
947
948
  gst_object_unref (clock);

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
949
950
951
  return TRUE;
}

952
static void do_seek (GtkWidget * widget);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
953

954
#ifdef SCRUB
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
955
static gboolean
956
end_scrub (GtkWidget * widget)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
957
958
{
  gst_element_set_state (pipeline, GST_STATE_PAUSED);
959
  seek_timeout_id = 0;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
960
961
962

  return FALSE;
}
963
#endif
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
964

965
966
static void
do_seek (GtkWidget * widget)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
967
968
{
  gint64 real = gtk_range_get_value (GTK_RANGE (widget)) * duration / 100;
969
  gboolean res = FALSE;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
970
  GstEvent *s_event;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
971

972
973
  if (!elem_seek) {
    GList *walk = seekable_pads;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
974

975
976
    while (walk) {
      GstPad *seekable = GST_PAD (walk->data);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
977

978
979
      g_print ("seek to %" GST_TIME_FORMAT " on pad %s:%s\n",
          GST_TIME_ARGS (real), GST_DEBUG_PAD_NAME (seekable));
980
981
982
983
984


      s_event = gst_event_new_seek (1.0,
          GST_FORMAT_TIME,
          GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, real, GST_SEEK_TYPE_NONE, 0);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
985

986
      res = gst_pad_send_event (seekable, s_event);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
987

988
989
990
991
      walk = g_list_next (walk);
    }
  } else {
    GList *walk = seekable_elements;
992

993
994
    while (walk) {
      GstElement *seekable = GST_ELEMENT (walk->data);
995

996
997
998
      g_print ("seek to %" GST_TIME_FORMAT " on element %s\n",
          GST_TIME_ARGS (real), GST_ELEMENT_NAME (seekable));

999
1000
      s_event = gst_event_new_seek (1.0,
          GST_FORMAT_TIME,