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

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

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

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

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

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

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

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

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


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

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

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

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


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

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

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

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

  return element;
}

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

118 119 120
  padname = gst_pad_get_name (newpad);

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

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

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

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

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

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

153 154
  pipeline = gst_pipeline_new ("app");

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

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

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

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

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

  return pipeline;
}

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

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

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

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

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

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

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

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

  return pipeline;
}

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

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

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

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

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

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

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

  seekable_elements = g_list_prepend (seekable_elements, audiosink);

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

  return pipeline;
}

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

260 261
  pipeline = gst_pipeline_new ("app");

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

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

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

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

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

  return pipeline;
}

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

291 292
  pipeline = gst_pipeline_new ("app");

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

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

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

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

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

  return pipeline;
}

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

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

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

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

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

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

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

  return pipeline;
}

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

354 355
  pipeline = gst_pipeline_new ("app");

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

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

365 366
  audio_bin = gst_bin_new ("a_decoder_bin");

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

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

378 379 380 381 382 383
  pad = gst_element_get_pad (decoder, "sink");
  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
  gst_object_unref (pad);

  setup_dynamic_link (demux, NULL, gst_element_get_pad (audio_bin, "sink"),
      NULL);
384 385 386 387 388 389 390 391 392 393 394 395 396 397

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

  return pipeline;
}

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

  pipeline = gst_pipeline_new ("app");

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

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

  video_bin = gst_bin_new ("v_decoder_bin");

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

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

423 424 425 426 427 428
  pad = gst_element_get_pad (decoder, "sink");
  gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
  gst_object_unref (pad);

  setup_dynamic_link (demux, NULL, gst_element_get_pad (video_bin, "sink"),
      NULL);
429 430 431 432 433 434 435 436 437

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

  return pipeline;
}

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

  pipeline = gst_pipeline_new ("app");

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

  demux = gst_element_factory_make_or_warn ("oggdemux", "demux");

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), demux);
  gst_element_link (src, demux);

  audio_bin = gst_bin_new ("a_decoder_bin");
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
  a_decoder = gst_element_factory_make_or_warn ("vorbisdec", "a_dec");
  a_convert = gst_element_factory_make_or_warn ("audioconvert", "a_convert");
463
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
464

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

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

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

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

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

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

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

  gst_bin_add (GST_BIN (video_bin), v_queue);
  gst_bin_add (GST_BIN (video_bin), v_decoder);
  gst_bin_add (GST_BIN (video_bin), v_convert);
496
  gst_bin_add (GST_BIN (video_bin), v_scale);
497 498
  gst_bin_add (GST_BIN (video_bin), videosink);

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

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

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

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

  return pipeline;
}

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

  pipeline = gst_pipeline_new ("app");

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

  demux = gst_element_factory_make_or_warn ("avidemux", "demux");

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), demux);
  gst_element_link (src, demux);

  audio_bin = gst_bin_new ("a_decoder_bin");
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
  a_convert = gst_element_factory_make_or_warn ("audioconvert", "a_convert");
542
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
543 544 545 546 547 548

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

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

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

555 556 557 558 559 560
  pad = gst_element_get_pad (a_queue, "sink");
  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
  gst_object_unref (pad);

  setup_dynamic_link (demux, NULL, gst_element_get_pad (audio_bin, "sink"),
      NULL);
561 562 563 564 565 566

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

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

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

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

578 579 580 581 582 583
  pad = gst_element_get_pad (v_queue, "sink");
  gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
  gst_object_unref (pad);

  setup_dynamic_link (demux, NULL, gst_element_get_pad (video_bin, "sink"),
      NULL);
584 585 586 587 588 589 590 591 592 593

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

  return pipeline;
}

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

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

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

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

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

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

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

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

  return pipeline;
}

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

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

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

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

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

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

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

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

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

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

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

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

  return pipeline;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return pipeline;
}

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

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

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

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

  seekable_elements = g_list_prepend (seekable_elements, demux);

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

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

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

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

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

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

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

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

  return pipeline;
}

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

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

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

  seekable_elements = g_list_prepend (seekable_elements, player);

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

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

851
#ifndef GST_DISABLE_PARSE
852 853 854 855 856 857 858 859 860 861 862 863 864 865
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;
}
866
#endif
867

868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
typedef struct
{
  gchar *name;
  GstElement *(*func) (const gchar * location);
}
Pipeline;

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

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

/* ui callbacks and helpers */

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
901 902
static gchar *
format_value (GtkScale * scale, gdouble value)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
903
{
904 905 906 907 908 909 910
  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
911

912 913
  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
914 915 916 917 918 919
}

typedef struct
{
  const gchar *name;
  const GstFormat format;
920 921
}
seek_format;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
922

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
923 924 925 926