seek.c 86.5 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
/* 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.
 */
23 24 25 26 27

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

28
#include <stdlib.h>
29
#include <math.h>
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
30 31 32 33 34
#include <glib.h>
#include <gtk/gtk.h>
#include <gst/gst.h>
#include <string.h>

35
#ifdef HAVE_X
36
#include <gdk/gdkx.h>
37
#endif
38 39
#include <gst/interfaces/xoverlay.h>

40
GST_DEBUG_CATEGORY_STATIC (seek_debug);
41 42
#define GST_CAT_DEFAULT (seek_debug)

43 44 45 46 47 48 49 50 51 52 53 54 55 56
/* 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"

57
#define FILL_INTERVAL 100
58 59 60 61 62 63 64 65 66 67
//#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

68 69
#define DEFAULT_VIDEO_HEIGHT 300

70

71
static GList *seekable_pads = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
72
static GList *rate_pads = NULL;
73
static GList *seekable_elements = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
74

75 76
static gboolean accurate_seek = FALSE;
static gboolean keyframe_seek = FALSE;
77
static gboolean loop_seek = FALSE;
78
static gboolean flush_seek = TRUE;
79 80
static gboolean scrub = TRUE;
static gboolean play_scrub = FALSE;
81
static gboolean skip_seek = FALSE;
82
static gdouble rate = 1.0;
83

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
84
static GstElement *pipeline;
85 86
static gint pipeline_type;
static const gchar *pipeline_spec;
87 88
static gint64 position = -1;
static gint64 duration = -1;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
89
static GtkAdjustment *adjustment;
90 91
static GtkWidget *hscale, *statusbar;
static guint status_id = 0;
92
static gboolean stats = FALSE;
93 94
static gboolean elem_seek = FALSE;
static gboolean verbose = FALSE;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
95

96 97
static gboolean is_live = FALSE;
static gboolean buffering = FALSE;
98 99
static GstBufferingMode mode;
static gint64 buffering_left;
100
static GstState state = GST_STATE_NULL;
101
static guint update_id = 0;
102 103
static guint seek_timeout_id = 0;
static gulong changed_id;
104
static guint fill_id = 0;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
105

106
static gint n_video = 0, n_audio = 0, n_text = 0;
107
static gboolean need_streams = TRUE;
108
static GtkWidget *video_combo, *audio_combo, *text_combo, *vis_combo;
109
static GtkWidget *vis_checkbox, *video_checkbox, *audio_checkbox;
110
static GtkWidget *text_checkbox, *mute_checkbox, *volume_spinbutton;
111
static GtkWidget *skip_checkbox, *video_window;
Wim Taymans's avatar
Wim Taymans committed
112 113 114
static GtkWidget *rate_spinbutton;

static GStaticMutex state_mutex = G_STATIC_MUTEX_INIT;
115

116
static GtkWidget *format_combo, *step_amount_spinbutton, *step_rate_spinbutton;
Wim Taymans's avatar
Wim Taymans committed
117 118 119
static GtkWidget *shuttle_checkbox, *step_button;
static GtkWidget *shuttle_hscale;
static GtkAdjustment *shuttle_adjustment;
120 121

static GList *paths = NULL, *l = NULL;
122

123 124 125 126 127 128 129 130 131
/* we keep an array of the visualisation entries so that we can easily switch
 * with the combo box index. */
typedef struct
{
  GstElementFactory *factory;
} VisEntry;

static GArray *vis_entries;

132
static void clear_streams (GstElement * pipeline);
133 134
static void volume_notify_cb (GstElement * pipeline, GParamSpec * arg,
    gpointer user_dat);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
135

136
/* pipeline construction */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
137 138 139

typedef struct
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
140 141 142
  const gchar *padname;
  GstPad *target;
  GstElement *bin;
143 144
}
dyn_link;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
145

146
static GstElement *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
147
gst_element_factory_make_or_warn (gchar * type, gchar * name)
148 149 150 151
{
  GstElement *element = gst_element_factory_make (type, name);

  if (!element) {
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
152
    g_warning ("Failed to create element %s of type %s", name, type);
153 154 155 156 157
  }

  return element;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
158
static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
159
dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
160
{
161
  gchar *padname;
162
  dyn_link *connect = (dyn_link *) data;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
163

164 165 166
  padname = gst_pad_get_name (newpad);

  if (connect->padname == NULL || !strcmp (padname, connect->padname)) {
167 168
    if (connect->bin)
      gst_bin_add (GST_BIN (pipeline), connect->bin);
169
    gst_pad_link (newpad, connect->target);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
170

171
    //seekable_pads = g_list_prepend (seekable_pads, newpad);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
172 173
    rate_pads = g_list_prepend (rate_pads, newpad);
  }
174
  g_free (padname);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
175 176 177
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
178 179
setup_dynamic_link (GstElement * element, const gchar * padname,
    GstPad * target, GstElement * bin)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
180
{
181
  dyn_link *connect;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
182

183
  connect = g_new0 (dyn_link, 1);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
184 185 186
  connect->padname = g_strdup (padname);
  connect->target = target;
  connect->bin = bin;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
187

188
  g_signal_connect (G_OBJECT (element), "pad-added", G_CALLBACK (dynamic_link),
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
189
      connect);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
190 191
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
192 193
static GstElement *
make_mod_pipeline (const gchar * location)
194 195 196 197
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
198

199 200
  pipeline = gst_pipeline_new ("app");

201 202
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("modplug", "decoder");
203
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
204 205 206 207 208 209 210 211
  //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);

212 213
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
214

215
  seekable = gst_element_get_static_pad (decoder, "src");
216 217
  seekable_pads = g_list_prepend (seekable_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, seekable);
218 219
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink"));
220 221 222 223

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
224 225
static GstElement *
make_dv_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
226 227
{
  GstElement *pipeline;
228
  GstElement *src, *demux, *decoder, *audiosink, *videosink;
229
  GstElement *a_queue, *v_queue;
Wim Taymans's avatar
Wim Taymans committed
230
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
231

Wim Taymans's avatar
Wim Taymans committed
232 233 234
  pipeline = gst_pipeline_new ("app");

  src = gst_element_factory_make_or_warn (SOURCE, "src");
235
  demux = gst_element_factory_make_or_warn ("dvdemux", "demuxer");
236
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
237
  decoder = gst_element_factory_make_or_warn ("ffdec_dvvideo", "decoder");
238
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
239
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
240
  audiosink = gst_element_factory_make_or_warn ("alsasink", "a_sink");
Wim Taymans's avatar
Wim Taymans committed
241 242 243 244

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

  gst_bin_add (GST_BIN (pipeline), src);
245
  gst_bin_add (GST_BIN (pipeline), demux);
246
  gst_bin_add (GST_BIN (pipeline), a_queue);
Wim Taymans's avatar
Wim Taymans committed
247
  gst_bin_add (GST_BIN (pipeline), audiosink);
248
  gst_bin_add (GST_BIN (pipeline), v_queue);
249
  gst_bin_add (GST_BIN (pipeline), decoder);
Wim Taymans's avatar
Wim Taymans committed
250 251
  gst_bin_add (GST_BIN (pipeline), videosink);

252
  gst_element_link (src, demux);
253
  gst_element_link (a_queue, audiosink);
254 255
  gst_element_link (v_queue, decoder);
  gst_element_link (decoder, videosink);
Wim Taymans's avatar
Wim Taymans committed
256

257 258 259 260
  setup_dynamic_link (demux, "video", gst_element_get_static_pad (v_queue,
          "sink"), NULL);
  setup_dynamic_link (demux, "audio", gst_element_get_static_pad (a_queue,
          "sink"), NULL);
261

262
  seekable = gst_element_get_static_pad (decoder, "src");
263
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Wim Taymans's avatar
Wim Taymans committed
264 265 266 267 268
  rate_pads = g_list_prepend (rate_pads, seekable);

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
269 270
static GstElement *
make_wav_pipeline (const gchar * location)
Wim Taymans's avatar
Wim Taymans committed
271 272 273
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
274

Wim Taymans's avatar
Wim Taymans committed
275 276
  pipeline = gst_pipeline_new ("app");

277 278
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("wavparse", "decoder");
279
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
Wim Taymans's avatar
Wim Taymans committed
280 281 282 283 284 285 286

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

287
  gst_element_link (src, decoder);
Wim Taymans's avatar
Wim Taymans committed
288

289 290
  setup_dynamic_link (decoder, "src", gst_element_get_static_pad (audiosink,
          "sink"), NULL);
291 292 293 294 295

  seekable_elements = g_list_prepend (seekable_elements, audiosink);

  /* force element seeking on this pipeline */
  elem_seek = TRUE;
Wim Taymans's avatar
Wim Taymans committed
296 297 298 299

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
300 301
static GstElement *
make_flac_pipeline (const gchar * location)
302 303 304 305
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
306

307 308
  pipeline = gst_pipeline_new ("app");

309 310
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("flacdec", "decoder");
311
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
Wim Taymans's avatar
Wim Taymans committed
312
  g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
313 314 315 316 317 318 319

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

320 321
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
322

323
  seekable = gst_element_get_static_pad (decoder, "src");
324 325
  seekable_pads = g_list_prepend (seekable_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, seekable);
326 327
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink"));
328 329 330 331

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
332 333
static GstElement *
make_sid_pipeline (const gchar * location)
334 335 336 337
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
338

339 340
  pipeline = gst_pipeline_new ("app");

341 342
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("siddec", "decoder");
343
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
344 345 346 347 348 349 350 351
  //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);

352 353
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
354

355
  seekable = gst_element_get_static_pad (decoder, "src");
356 357
  seekable_pads = g_list_prepend (seekable_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, seekable);
358 359
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink"));
360 361 362 363

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
364 365
static GstElement *
make_parse_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
366 367 368 369
{
  GstElement *pipeline;
  GstElement *src, *parser, *fakesink;
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
370

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
371 372
  pipeline = gst_pipeline_new ("app");

373 374 375
  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
376 377
  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
378 379 380 381 382 383 384

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

385 386
  gst_element_link (src, parser);
  gst_element_link (parser, fakesink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
387

388
  seekable = gst_element_get_static_pad (parser, "src");
389
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
390
  rate_pads = g_list_prepend (rate_pads, seekable);
391 392
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_static_pad (parser, "sink"));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
393 394 395 396

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
397 398
static GstElement *
make_vorbis_pipeline (const gchar * location)
399
{
400 401
  GstElement *pipeline, *audio_bin;
  GstElement *src, *demux, *decoder, *convert, *audiosink;
402
  GstPad *pad, *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
403

404 405
  pipeline = gst_pipeline_new ("app");

406
  src = gst_element_factory_make_or_warn (SOURCE, "src");
407 408 409
  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");
410
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
Wim Taymans's avatar
Wim Taymans committed
411
  g_object_set (G_OBJECT (audiosink), "sync", TRUE, NULL);
412 413 414

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

415 416
  audio_bin = gst_bin_new ("a_decoder_bin");

417
  gst_bin_add (GST_BIN (pipeline), src);
418 419 420 421 422
  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);
423

424 425 426 427
  gst_element_link (src, demux);
  gst_element_link (decoder, convert);
  gst_element_link (convert, audiosink);

428
  pad = gst_element_get_static_pad (decoder, "sink");
429 430 431
  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
  gst_object_unref (pad);

432 433
  setup_dynamic_link (demux, NULL, gst_element_get_static_pad (audio_bin,
          "sink"), NULL);
434

435
  seekable = gst_element_get_static_pad (decoder, "src");
436 437
  seekable_pads = g_list_prepend (seekable_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, seekable);
438 439
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink"));
440 441 442 443 444 445 446 447 448

  return pipeline;
}

static GstElement *
make_theora_pipeline (const gchar * location)
{
  GstElement *pipeline, *video_bin;
  GstElement *src, *demux, *decoder, *convert, *videosink;
449
  GstPad *pad, *seekable;
450 451 452 453 454 455 456

  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
457
  videosink = gst_element_factory_make_or_warn (VSINK, "sink");
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473

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

474
  pad = gst_element_get_static_pad (decoder, "sink");
475 476 477
  gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
  gst_object_unref (pad);

478 479
  setup_dynamic_link (demux, NULL, gst_element_get_static_pad (video_bin,
          "sink"), NULL);
480

481
  seekable = gst_element_get_static_pad (decoder, "src");
482 483
  seekable_pads = g_list_prepend (seekable_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, seekable);
484 485
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink"));
486 487 488 489

  return pipeline;
}

490 491 492 493 494 495
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;
496
  GstElement *a_queue, *v_queue, *v_scale;
497
  GstPad *seekable;
Wim Taymans's avatar
Wim Taymans committed
498
  GstPad *pad;
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514

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

517
  gst_bin_add (GST_BIN (pipeline), audio_bin);
518 519 520 521 522 523

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

524 525 526
  gst_element_link (a_queue, a_decoder);
  gst_element_link (a_decoder, a_convert);
  gst_element_link (a_convert, audiosink);
527

528
  pad = gst_element_get_static_pad (a_queue, "sink");
Wim Taymans's avatar
Wim Taymans committed
529
  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
530
  gst_object_unref (pad);
531

532 533
  setup_dynamic_link (demux, NULL, gst_element_get_static_pad (audio_bin,
          "sink"), NULL);
534 535 536 537 538 539

  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");
540
  v_scale = gst_element_factory_make_or_warn ("videoscale", "v_scale");
Wim Taymans's avatar
Wim Taymans committed
541
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
542 543

  gst_bin_add (GST_BIN (pipeline), video_bin);
544 545 546 547

  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);
548
  gst_bin_add (GST_BIN (video_bin), v_scale);
549 550
  gst_bin_add (GST_BIN (video_bin), videosink);

551 552
  gst_element_link_many (v_queue, v_decoder, v_convert, v_scale, videosink,
      NULL);
553

554
  pad = gst_element_get_static_pad (v_queue, "sink");
Wim Taymans's avatar
Wim Taymans committed
555
  gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
556
  gst_object_unref (pad);
557

558 559
  setup_dynamic_link (demux, NULL, gst_element_get_static_pad (video_bin,
          "sink"), NULL);
560

561
  seekable = gst_element_get_static_pad (a_decoder, "src");
562 563 564
  seekable_pads = g_list_prepend (seekable_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, seekable);
  rate_pads =
565 566
      g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder,
          "sink"));
567 568 569 570 571 572 573 574 575 576 577

  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;
578
  GstPad *seekable, *pad;
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594

  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");
595
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
596 597 598 599 600 601

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

602 603 604 605
  gst_element_link (a_queue, a_decoder);
  gst_element_link (a_decoder, a_convert);
  gst_element_link (a_convert, audiosink);

606 607
  gst_bin_add (GST_BIN (pipeline), audio_bin);

608
  pad = gst_element_get_static_pad (a_queue, "sink");
609 610 611
  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
  gst_object_unref (pad);

612 613
  setup_dynamic_link (demux, NULL, gst_element_get_static_pad (audio_bin,
          "sink"), NULL);
614 615 616 617 618 619

  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
620
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
621 622 623 624 625 626

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

627 628
  gst_element_link_many (v_queue, v_decoder, v_convert, videosink, NULL);

629 630
  gst_bin_add (GST_BIN (pipeline), video_bin);

631
  pad = gst_element_get_static_pad (v_queue, "sink");
632 633 634
  gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad));
  gst_object_unref (pad);

635 636
  setup_dynamic_link (demux, NULL, gst_element_get_static_pad (video_bin,
          "sink"), NULL);
637

638
  seekable = gst_element_get_static_pad (a_decoder, "src");
639 640 641
  seekable_pads = g_list_prepend (seekable_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, seekable);
  rate_pads =
642 643
      g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder,
          "sink"));
644 645 646 647

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
648 649
static GstElement *
make_mp3_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
650 651
{
  GstElement *pipeline;
652
  GstElement *src, *parser, *decoder, *audiosink, *queue;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
653
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
654

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
655 656
  pipeline = gst_pipeline_new ("app");

657
  src = gst_element_factory_make_or_warn (SOURCE, "src");
658
  parser = gst_element_factory_make_or_warn ("mp3parse", "parse");
659 660
  decoder = gst_element_factory_make_or_warn ("mad", "dec");
  queue = gst_element_factory_make_or_warn ("queue", "queue");
661
  audiosink = gst_element_factory_make_or_warn (ASINK, "sink");
662

663
  seekable_elements = g_list_prepend (seekable_elements, audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
664 665

  g_object_set (G_OBJECT (src), "location", location, NULL);
666
  //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
667

668
  gst_bin_add (GST_BIN (pipeline), src);
669
  gst_bin_add (GST_BIN (pipeline), parser);
670
  gst_bin_add (GST_BIN (pipeline), decoder);
671
  gst_bin_add (GST_BIN (pipeline), queue);
672
  gst_bin_add (GST_BIN (pipeline), audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
673

674 675
  gst_element_link (src, parser);
  gst_element_link (parser, decoder);
676
  gst_element_link (decoder, queue);
677
  gst_element_link (queue, audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
678

679
  seekable = gst_element_get_static_pad (queue, "src");
680
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
681
  rate_pads = g_list_prepend (rate_pads, seekable);
682 683
  rate_pads =
      g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink"));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
684 685 686 687

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
688 689
static GstElement *
make_avi_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
690 691 692
{
  GstElement *pipeline, *audio_bin, *video_bin;
  GstElement *src, *demux, *a_decoder, *v_decoder, *audiosink, *videosink;
693
  GstElement *a_queue = NULL, *v_queue = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
694
  GstPad *seekable;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
695

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
696 697
  pipeline = gst_pipeline_new ("app");

698
  src = gst_element_factory_make_or_warn (SOURCE, "src");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
699 700
  g_object_set (G_OBJECT (src), "location", location, NULL);

701
  demux = gst_element_factory_make_or_warn ("avidemux", "demux");
702
  seekable_elements = g_list_prepend (seekable_elements, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
703 704 705

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), demux);
706
  gst_element_link (src, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
707 708

  audio_bin = gst_bin_new ("a_decoder_bin");
709
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
710
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
711
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
712 713
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
714
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
715 716
  gst_bin_add (GST_BIN (audio_bin), a_queue);
  gst_bin_add (GST_BIN (audio_bin), audiosink);
Wim Taymans's avatar
Wim Taymans committed
717
  gst_element_set_state (audio_bin, GST_STATE_PAUSED);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
718

719
  setup_dynamic_link (demux, "audio_00", gst_element_get_static_pad (a_decoder,
720
          "sink"), audio_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
721

722
  seekable = gst_element_get_static_pad (a_queue, "src");
723
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
724
  rate_pads = g_list_prepend (rate_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
725
  rate_pads =
726 727
      g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder,
          "sink"));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
728 729

  video_bin = gst_bin_new ("v_decoder_bin");
Wim Taymans's avatar
Wim Taymans committed
730
  v_decoder = gst_element_factory_make_or_warn ("ffmpegdecall", "v_dec");
731
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
732
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
733 734
  gst_element_link (v_decoder, v_queue);
  gst_element_link (v_queue, videosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
735
  gst_bin_add (GST_BIN (video_bin), v_decoder);
736 737
  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
738

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

741
  setup_dynamic_link (demux, "video_00", gst_element_get_static_pad (v_decoder,
742
          "sink"), video_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
743

744
  seekable = gst_element_get_static_pad (v_queue, "src");
745
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
746
  rate_pads = g_list_prepend (rate_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
747
  rate_pads =
748 749
      g_list_prepend (rate_pads, gst_element_get_static_pad (v_decoder,
          "sink"));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
750 751 752 753

  return pipeline;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
754 755
static GstElement *
make_mpeg_pipeline (const gchar * location)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
756 757
{
  GstElement *pipeline, *audio_bin, *video_bin;
758 759
  GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter;
  GstElement *audiosink, *videosink;
760
  GstElement *a_queue, *v_queue;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
761
  GstPad *seekable;
762
  GstPad *pad;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
763

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
764 765
  pipeline = gst_pipeline_new ("app");

766
  src = gst_element_factory_make_or_warn (SOURCE, "src");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
767 768
  g_object_set (G_OBJECT (src), "location", location, NULL);

769 770
  //demux = gst_element_factory_make_or_warn ("mpegdemux", "demux");
  demux = gst_element_factory_make_or_warn ("flupsdemux", "demux");
771

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
772 773
  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), demux);
774
  gst_element_link (src, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
775 776

  audio_bin = gst_bin_new ("a_decoder_bin");
777 778
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
779
  audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
780
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
781 782
  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
783

784 785
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
786

787 788
  gst_bin_add (GST_BIN (pipeline), audio_bin);

789
  pad = gst_element_get_static_pad (a_decoder, "sink");
790 791 792
  gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad));
  gst_object_unref (pad);

793
  setup_dynamic_link (demux, "audio_c0", gst_element_get_static_pad (audio_bin,
794
          "sink"), NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
795 796

  video_bin = gst_bin_new ("v_decoder_bin");
797 798
  v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
799
  v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter");
800
  videosink = gst_element_factory_make_or_warn (VSINK, "v_sink");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
801

802 803 804 805 806 807 808
  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);
809
  gst_element_link (v_filter, videosink);