seek.c 41.9 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
8
9
GST_DEBUG_CATEGORY (seek_debug);
#define GST_CAT_DEFAULT (seek_debug)

10
static GList *seekable_pads = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
11
static GList *rate_pads = NULL;
12
static GList *seekable_elements = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
13

14
15
static gboolean accurate_seek = FALSE;
static gboolean keyframe_seek = FALSE;
16
static gboolean loop_seek = FALSE;
17

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
18
static GstElement *pipeline;
Wim Taymans's avatar
Wim Taymans committed
19
20
static gint64 position;
static gint64 duration;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
21
static GtkAdjustment *adjustment;
22
static GtkWidget *hscale;
23
static gboolean stats = FALSE;
24
25
static gboolean elem_seek = FALSE;
static gboolean verbose = FALSE;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
26

27
28
static GstState state;
static guint update_id = 0;
29
30
static guint seek_timeout_id = 0;
static gulong changed_id;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
31

Wim Taymans's avatar
Wim Taymans committed
32
//#define SOURCE "filesrc"
33
#define SOURCE "gnomevfssrc"
34
35
#define ASINK "alsasink"
//#define ASINK "osssink"
Wim Taymans's avatar
Wim Taymans committed
36
#define VSINK "xvimagesink"
37
//#define VSINK "sdlvideosink"
Wim Taymans's avatar
Wim Taymans committed
38
39
//#define VSINK "ximagesink"
//#define VSINK "aasink"
40
//#define VSINK "cacasink"
41

42
43
//#define UPDATE_INTERVAL 500
#define UPDATE_INTERVAL 100
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
44

45
/* number of milliseconds to play for after a seek */
Wim Taymans's avatar
Wim Taymans committed
46
47
//#define SCRUB_TIME 250
//#define SCRUB
48

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
49
#define THREAD
50
#define PAD_SEEK
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
51
52
53

typedef struct
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
54
55
56
  const gchar *padname;
  GstPad *target;
  GstElement *bin;
57
58
}
dyn_link;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
59

60
static GstElement *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
61
gst_element_factory_make_or_warn (gchar * type, gchar * name)
62
63
64
65
{
  GstElement *element = gst_element_factory_make (type, name);

  if (!element) {
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
66
    g_warning ("Failed to create element %s of type %s", name, type);
67
68
69
70
71
  }

  return element;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
72
static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
73
dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
74
{
75
  gchar *padname;
76
  dyn_link *connect = (dyn_link *) data;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
77

78
79
80
  padname = gst_pad_get_name (newpad);

  if (connect->padname == NULL || !strcmp (padname, connect->padname)) {
81
82
    if (connect->bin)
      gst_bin_add (GST_BIN (pipeline), connect->bin);
83
    gst_pad_link (newpad, connect->target);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
84

85
    //seekable_pads = g_list_prepend (seekable_pads, newpad);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
86
87
    rate_pads = g_list_prepend (rate_pads, newpad);
  }
88
  g_free (padname);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
89
90
91
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
92
93
setup_dynamic_link (GstElement * element, const gchar * padname,
    GstPad * target, GstElement * bin)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
94
{
95
  dyn_link *connect;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
96

97
  connect = g_new0 (dyn_link, 1);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
98
99
100
  connect->padname = g_strdup (padname);
  connect->target = target;
  connect->bin = bin;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
101

102
  g_signal_connect (G_OBJECT (element), "pad-added", G_CALLBACK (dynamic_link),
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
103
      connect);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
104
105
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
106
107
static GstElement *
make_mod_pipeline (const gchar * location)
108
109
110
111
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
112

113
114
  pipeline = gst_pipeline_new ("app");

115
116
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("modplug", "decoder");
117
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
118
119
120
121
122
123
124
125
  //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);

126
127
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
128
129
130
131
132
133
134
135
136

  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
137
138
static GstElement *
make_dv_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
139
140
{
  GstElement *pipeline;
141
  GstElement *src, *demux, *decoder, *audiosink, *videosink;
142
  GstElement *a_queue, *v_queue;
Wim Taymans's avatar
Wim Taymans committed
143
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
144

Wim Taymans's avatar
Wim Taymans committed
145
146
147
  pipeline = gst_pipeline_new ("app");

  src = gst_element_factory_make_or_warn (SOURCE, "src");
148
  demux = gst_element_factory_make_or_warn ("dvdemux", "demuxer");
149
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
150
151
  decoder = gst_element_factory_make_or_warn ("ffdec_dvvideo", "decoder");
  videosink = gst_element_factory_make_or_warn ("xvimagesink", "v_sink");
152
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
153
  audiosink = gst_element_factory_make_or_warn ("alsasink", "a_sink");
Wim Taymans's avatar
Wim Taymans committed
154
155
156
157

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

  gst_bin_add (GST_BIN (pipeline), src);
158
  gst_bin_add (GST_BIN (pipeline), demux);
159
  gst_bin_add (GST_BIN (pipeline), a_queue);
Wim Taymans's avatar
Wim Taymans committed
160
  gst_bin_add (GST_BIN (pipeline), audiosink);
161
  gst_bin_add (GST_BIN (pipeline), v_queue);
162
  gst_bin_add (GST_BIN (pipeline), decoder);
Wim Taymans's avatar
Wim Taymans committed
163
164
  gst_bin_add (GST_BIN (pipeline), videosink);

165
  gst_element_link (src, demux);
166
  gst_element_link (a_queue, audiosink);
167
168
  gst_element_link (v_queue, decoder);
  gst_element_link (decoder, videosink);
Wim Taymans's avatar
Wim Taymans committed
169

170
171
172
173
  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);
174

175
176
  seekable = gst_element_get_pad (decoder, "src");
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Wim Taymans's avatar
Wim Taymans committed
177
178
179
180
181
  rate_pads = g_list_prepend (rate_pads, seekable);

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
182
183
static GstElement *
make_wav_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
184
185
186
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
187

Wim Taymans's avatar
Wim Taymans committed
188
189
  pipeline = gst_pipeline_new ("app");

190
191
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("wavparse", "decoder");
192
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
Wim Taymans's avatar
Wim Taymans committed
193
194
195
196
197
198
199

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

200
  gst_element_link (src, decoder);
Wim Taymans's avatar
Wim Taymans committed
201

202
203
204
205
206
207
208
  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
209
210
211
212

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
213
214
static GstElement *
make_flac_pipeline (const gchar * location)
215
216
217
218
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
219

220
221
  pipeline = gst_pipeline_new ("app");

222
223
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("flacdec", "decoder");
224
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
Wim Taymans's avatar
Wim Taymans committed
225
  g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
226
227
228
229
230
231
232

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

233
234
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
235
236
237
238
239
240
241
242
243

  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
244
245
static GstElement *
make_sid_pipeline (const gchar * location)
246
247
248
249
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
250

251
252
  pipeline = gst_pipeline_new ("app");

253
254
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("siddec", "decoder");
255
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
256
257
258
259
260
261
262
263
  //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);

264
265
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
266
267
268
269
270
271
272
273
274

  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
275
276
static GstElement *
make_parse_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
277
278
279
280
{
  GstElement *pipeline;
  GstElement *src, *parser, *fakesink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
281

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
282
283
  pipeline = gst_pipeline_new ("app");

284
285
286
  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
287
288
  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
289
290
291
292
293
294
295

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

296
297
  gst_element_link (src, parser);
  gst_element_link (parser, fakesink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
298
299

  seekable = gst_element_get_pad (parser, "src");
300
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
301
302
303
304
305
306
  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
307
308
static GstElement *
make_vorbis_pipeline (const gchar * location)
309
{
310
311
  GstElement *pipeline, *audio_bin;
  GstElement *src, *demux, *decoder, *convert, *audiosink;
312
  GstPad *pad, *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
313

314
315
  pipeline = gst_pipeline_new ("app");

316
  src = gst_element_factory_make_or_warn (SOURCE, "src");
317
318
319
  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");
320
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
Wim Taymans's avatar
Wim Taymans committed
321
  g_object_set (G_OBJECT (audiosink), "sync", TRUE, NULL);
322
323
324

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

325
326
  audio_bin = gst_bin_new ("a_decoder_bin");

327
  gst_bin_add (GST_BIN (pipeline), src);
328
329
330
331
332
  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);
333

334
335
336
337
  gst_element_link (src, demux);
  gst_element_link (decoder, convert);
  gst_element_link (convert, audiosink);

338
339
340
341
342
343
  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);
344
345
346
347
348
349
350
351
352
353
354
355
356
357

  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;
358
  GstPad *pad, *seekable;
359
360
361
362
363
364
365

  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
366
  videosink = gst_element_factory_make_or_warn (VSINK, "sink");
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

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

383
384
385
386
387
388
  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);
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;
}

398
399
400
401
402
403
404
405
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
406
  GstPad *pad;
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

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

425
  gst_bin_add (GST_BIN (pipeline), audio_bin);
426
427
428
429
430
431

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

432
433
434
  gst_element_link (a_queue, a_decoder);
  gst_element_link (a_decoder, a_convert);
  gst_element_link (a_convert, audiosink);
435

Wim Taymans's avatar
Wim Taymans committed
436
437
  pad = gst_element_get_pad (a_queue, "sink");
  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
438
  gst_object_unref (pad);
439
440
441

  setup_dynamic_link (demux, NULL, gst_element_get_pad (audio_bin, "sink"),
      NULL);
442
443
444
445
446
447

  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
448
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
449
450

  gst_bin_add (GST_BIN (pipeline), video_bin);
451
452
453
454
455
456

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

457
  gst_element_link_many (v_queue, v_decoder, v_convert, videosink, NULL);
458

Wim Taymans's avatar
Wim Taymans committed
459
460
  pad = gst_element_get_pad (v_queue, "sink");
  gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
461
  gst_object_unref (pad);
462
463
464

  setup_dynamic_link (demux, NULL, gst_element_get_pad (video_bin, "sink"),
      NULL);
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481

  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;
482
  GstPad *seekable, *pad;
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498

  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");
499
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
500
501
502
503
504
505

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

506
507
508
509
  gst_element_link (a_queue, a_decoder);
  gst_element_link (a_decoder, a_convert);
  gst_element_link (a_convert, audiosink);

510
511
  gst_bin_add (GST_BIN (pipeline), audio_bin);

512
513
514
515
516
517
  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);
518
519
520
521
522
523

  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
524
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
525
526
527
528
529
530

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

531
532
  gst_element_link_many (v_queue, v_decoder, v_convert, videosink, NULL);

533
534
  gst_bin_add (GST_BIN (pipeline), video_bin);

535
536
537
538
539
540
  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);
541
542
543
544
545
546
547
548
549
550

  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
551
552
static GstElement *
make_mp3_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
553
554
{
  GstElement *pipeline;
555
  GstElement *src, *decoder, *osssink, *queue;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
556
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
557

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
558
559
  pipeline = gst_pipeline_new ("app");

560
561
562
  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");
563
  osssink = gst_element_factory_make_or_warn (ASINK, "sink");
564

565
  seekable_elements = g_list_prepend (seekable_elements, osssink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
566
567

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

570
571
  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), decoder);
572
573
  gst_bin_add (GST_BIN (pipeline), queue);
  gst_bin_add (GST_BIN (pipeline), osssink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
574

575
576
  gst_element_link (src, decoder);
  gst_element_link (decoder, queue);
577
  gst_element_link (queue, osssink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
578

579
580
  seekable = gst_element_get_pad (queue, "src");
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
581
582
583
584
585
586
  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
587
588
static GstElement *
make_avi_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
589
590
591
{
  GstElement *pipeline, *audio_bin, *video_bin;
  GstElement *src, *demux, *a_decoder, *v_decoder, *audiosink, *videosink;
592
  GstElement *a_queue = NULL, *v_queue = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
593
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
594

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
595
596
  pipeline = gst_pipeline_new ("app");

597
  src = gst_element_factory_make_or_warn (SOURCE, "src");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
598
599
  g_object_set (G_OBJECT (src), "location", location, NULL);

600
  demux = gst_element_factory_make_or_warn ("avidemux", "demux");
601
  seekable_elements = g_list_prepend (seekable_elements, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
602
603
604

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), demux);
605
  gst_element_link (src, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
606
607

  audio_bin = gst_bin_new ("a_decoder_bin");
608
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
609
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
610
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
611
612
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
613
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
614
615
  gst_bin_add (GST_BIN (audio_bin), a_queue);
  gst_bin_add (GST_BIN (audio_bin), audiosink);
Wim Taymans's avatar
Wim Taymans committed
616
  gst_element_set_state (audio_bin, GST_STATE_PAUSED);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
617

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
618
  setup_dynamic_link (demux, "audio_00", gst_element_get_pad (a_decoder,
619
          "sink"), audio_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
620
621

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

  video_bin = gst_bin_new ("v_decoder_bin");
Wim Taymans's avatar
Wim Taymans committed
628
  v_decoder = gst_element_factory_make_or_warn ("ffmpegdecall", "v_dec");
629
  videosink = gst_element_factory_make_or_warn ("ximagesink", "v_sink");
630
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
631
632
  gst_element_link (v_decoder, v_queue);
  gst_element_link (v_queue, videosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
633
  gst_bin_add (GST_BIN (video_bin), v_decoder);
634
635
  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
636

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

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
639
  setup_dynamic_link (demux, "video_00", gst_element_get_pad (v_decoder,
640
          "sink"), video_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
641
642

  seekable = gst_element_get_pad (v_queue, "src");
643
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
644
  rate_pads = g_list_prepend (rate_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
645
646
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (v_decoder, "sink"));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
647
648
649
650

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
651
652
static GstElement *
make_mpeg_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
653
654
{
  GstElement *pipeline, *audio_bin, *video_bin;
655
656
  GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter;
  GstElement *audiosink, *videosink;
657
  GstElement *a_queue, *v_queue;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
658
  GstPad *seekable;
659
  GstPad *pad;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
660

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
661
662
  pipeline = gst_pipeline_new ("app");

663
  src = gst_element_factory_make_or_warn (SOURCE, "src");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
664
665
  g_object_set (G_OBJECT (src), "location", location, NULL);

666
667
  //demux = gst_element_factory_make_or_warn ("mpegdemux", "demux");
  demux = gst_element_factory_make_or_warn ("flupsdemux", "demux");
668

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
669
670
  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), demux);
671
  gst_element_link (src, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
672
673

  audio_bin = gst_bin_new ("a_decoder_bin");
674
675
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
676
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
677
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
678
679
  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
680

681
682
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
683

684
685
686
687
688
689
690
691
  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
692
693

  video_bin = gst_bin_new ("v_decoder_bin");
694
695
  v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
696
  v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter");
697
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
698

699
700
701
702
703
704
705
  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);
706
  gst_element_link (v_filter, videosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
707

708
  gst_bin_add (GST_BIN (pipeline), video_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
709

710
711
712
713
714
715
716
717
  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");
718
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
719
  rate_pads = g_list_prepend (rate_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
720
721
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (v_decoder, "sink"));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
722
723
724
725

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
726
727
static GstElement *
make_mpegnt_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
728
729
730
731
{
  GstElement *pipeline, *audio_bin, *video_bin;
  GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter;
  GstElement *audiosink, *videosink;
732
  GstElement *a_queue;
Wim Taymans's avatar
Wim Taymans committed
733
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
734

Wim Taymans's avatar
Wim Taymans committed
735
736
737
738
739
740
741
742
743
744
745
746
  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);
747
  gst_element_link (src, demux);
Wim Taymans's avatar
Wim Taymans committed
748
749
750
751

  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");
752
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
Wim Taymans's avatar
Wim Taymans committed
753
754
  //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
  g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
755
756
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Wim Taymans's avatar
Wim Taymans committed
757
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
758
759
  gst_bin_add (GST_BIN (audio_bin), a_queue);
  gst_bin_add (GST_BIN (audio_bin), audiosink);
Wim Taymans's avatar
Wim Taymans committed
760

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
761
  setup_dynamic_link (demux, "audio_00", gst_element_get_pad (a_decoder,
762
          "sink"), audio_bin);
Wim Taymans's avatar
Wim Taymans committed
763
764
765
766

  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
767
768
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink"));
Wim Taymans's avatar
Wim Taymans committed
769
770
771

  video_bin = gst_bin_new ("v_decoder_bin");
  v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
772
  v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter");
773
  videosink = gst_element_factory_make_or_warn ("ximagesink", "v_sink");
774
  gst_element_link_many (v_decoder, v_filter, videosink, NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
775

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

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
778
  setup_dynamic_link (demux, "video_00", gst_element_get_pad (v_decoder,
779
          "sink"), video_bin);
Wim Taymans's avatar
Wim Taymans committed
780
781
782
783

  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
784
785
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_pad (v_decoder, "sink"));
Wim Taymans's avatar
Wim Taymans committed
786
787
788
789

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
790
791
static GstElement *
make_playerbin_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
792
{
793
  GstElement *player;
794
795
796
797

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

798
  g_object_set (G_OBJECT (player), "uri", location, NULL);
799
800
801
802
803
804
805

  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
806
807
}

808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
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;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
823
824
static gchar *
format_value (GtkScale * scale, gdouble value)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
825
{
826
827
828
829
830
831
832
  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
833

834
835
  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
836
837
838
839
840
841
}

typedef struct
{
  const gchar *name;
  const GstFormat format;
842
843
}
seek_format;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
844

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
845
846
847
848
849
850
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
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
};

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
869
870
      if (gst_pad_query_convert (pad, GST_FORMAT_TIME, GST_SECOND, &format,
              &value)) {
871
        g_print ("%s %13" G_GINT64_FORMAT " | ", seek_formats[i].name, value);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
872
      } else {
873
        g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
874
875
876
877
878
879
880
881
882
883
884
      }

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

    walk = g_list_next (walk);
  }
}

G_GNUC_UNUSED static void
885
886
887
888
889
890
891
892
893
894
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
895
      gint64 position, total;
896
897
898
      GstFormat format;

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

Wim Taymans's avatar
Wim Taymans committed
900
901
      if (gst_element_query_position (element, &format, &position) &&
          gst_element_query_duration (element, &format, &total)) {
Wim Taymans's avatar
Wim Taymans committed
902
903
        g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ",
            seek_formats[i].name, position, total);
904
      } else {
Wim Taymans's avatar
Wim Taymans committed
905
906
        g_print ("%s %13.13s / %13.13s | ", seek_formats[i].name, "*NA*",
            "*NA*");
907
908
909
910
911
912
913
914
915
916
917
      }
      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
918
{
919
920
921
922
923
924
925
926
927
  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
928
      gint64 position, total;
929
930

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

Wim Taymans's avatar
Wim Taymans committed
932
933
      if (gst_pad_query_position (pad, &format, &position) &&
          gst_pad_query_duration (pad, &format, &total)) {
Wim Taymans's avatar
Wim Taymans committed
934
935
        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
936
      } else {
Wim Taymans's avatar
Wim Taymans committed
937
938
        g_print ("%s %13.13s / %13.13s | ", seek_formats[i].name, "*NA*",
            "*NA*");
939
      }
Wim Taymans's avatar
Wim Taymans committed
940

941
      i++;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
942
    }
943
944
945
    g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad));

    walk = g_list_next (walk);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
946
947
948
949
  }
}

static gboolean
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
950
update_scale (gpointer data)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
951
{
Wim Taymans's avatar
Wim Taymans committed
952
  GstFormat format;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
953

Wim Taymans's avatar
Wim Taymans committed
954
  position = 0;
955
  duration = 0;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
956

Wim Taymans's avatar
Wim Taymans committed
957
958
  format = GST_FORMAT_TIME;

959
960
961
  if (elem_seek) {
    if (seekable_elements) {
      GstElement *element = GST_ELEMENT (seekable_elements->data);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
962

Wim Taymans's avatar
Wim Taymans committed
963
964
      gst_element_query_position (element, &format, &position);
      gst_element_query_duration (element, &format, &duration);
965
966
967
968
969
    }
  } else {
    if (seekable_pads) {
      GstPad *pad = GST_PAD (seekable_pads->data);

Wim Taymans's avatar
Wim Taymans committed
970
971
      gst_pad_query_position (pad, &format, &position);
      gst_pad_query_duration (pad, &format, &duration);
972
    }
973
  }
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
974

975
  if (stats) {
976
977
978
979
980
    if (elem_seek) {
      query_positions_elems ();
    } else {
      query_positions_pads ();
    }
981
    query_rates ();
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
982
  }
983
984
  if (position >= duration)
    duration = position;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
985
986
987

  if (duration > 0) {
    gtk_adjustment_set_value (adjustment, position * 100.0 / duration);
988
    gtk_widget_queue_draw (hscale);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
989
990
991
992
993
  }

  return TRUE;
}

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

996
#ifdef SCRUB
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
997
static gboolean
998
end_scrub (GtkWidget * widget)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
999
1000
{
  gst_element_set_state (pipeline, GST_STATE_PAUSED);
1001
  seek_timeout_id = 0;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1002
1003
1004

  return FALSE;
}
1005
#endif
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1006

1007
1008
static gboolean
send_event (GstEvent * event)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1009
{
1010
  gboolean res = FALSE;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1011

1012
1013
  if (!elem_seek) {
    GList *walk = seekable_pads;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1014

1015
1016
    while (walk) {
      GstPad *seekable = GST_PAD (walk->data);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1017

1018
      GST_DEBUG ("send event on pad %s:%s", GST_DEBUG_PAD_NAME (seekable));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1019

1020
1021
      gst_event_ref (event);
      res = gst_pad_send_event (seekable, event);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1022

1023
1024
1025
1026
      walk = g_list_next (walk);
    }
  } else {
    GList *walk = seekable_elements;
1027

1028
1029
    while (walk) {
      GstElement *seekable = GST_ELEMENT (walk->data);