seek.c 27.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
static GList *seekable_pads = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
8
static GList *rate_pads = NULL;
9
static GList *seekable_elements = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
10 11

static GstElement *pipeline;
12
static guint64 duration;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
13
static GtkAdjustment *adjustment;
14
static gboolean stats = FALSE;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
15 16 17

static guint update_id;

18 19
//#define SOURCE "gnomevfssrc"
#define SOURCE "filesrc"
20

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
21 22 23
#define UPDATE_INTERVAL 500

#define THREAD
24
#define PAD_SEEK
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
25 26 27 28 29 30

typedef struct
{
  const gchar 	*padname;
  GstPad 	*target;
  GstElement 	*bin;
31
} dyn_link;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
32

33 34 35 36 37 38 39 40 41 42 43 44 45
static GstElement *
gst_element_factory_make_or_warn (gchar *type, gchar *name)
{
  GstElement *element = gst_element_factory_make (type, name);

  if (!element) {
    g_warning ("Failed to create element %s of type %s",
	       name, type);
  }

  return element;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
46
static void
47
dynamic_link (GstPadTemplate *templ, GstPad *newpad, gpointer data)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
48
{
49
  dyn_link *connect = (dyn_link *) data;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
50 51 52 53

  if (!strcmp (gst_pad_get_name (newpad), connect->padname)) {
    gst_element_set_state (pipeline, GST_STATE_PAUSED);
    gst_bin_add (GST_BIN (pipeline), connect->bin);
54
    gst_pad_link (newpad, connect->target);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
55 56
    gst_element_set_state (pipeline, GST_STATE_PLAYING);

57
    seekable_pads = g_list_prepend (seekable_pads, newpad);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
58 59 60 61 62
    rate_pads = g_list_prepend (rate_pads, newpad);
  }
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
63
setup_dynamic_link (GstElement *element, const gchar *padname, GstPad *target, GstElement *bin)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
64
{
65
  dyn_link *connect;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
66

67
  connect = g_new0 (dyn_link, 1);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
68 69 70 71
  connect->padname 	= g_strdup (padname);
  connect->target 	= target;
  connect->bin 		= bin;

72
  g_signal_connect (G_OBJECT (element), "new_pad", G_CALLBACK (dynamic_link), connect);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
73 74
}

75 76 77 78 79 80 81 82 83
static GstElement*
make_mod_pipeline (const gchar *location) 
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
  
  pipeline = gst_pipeline_new ("app");

84 85 86
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("modplug", "decoder");
  audiosink = gst_element_factory_make_or_warn ("osssink", "sink");
87 88 89 90 91 92 93 94
  //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);

95 96
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
97 98 99 100 101 102 103 104 105

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

Wim Taymans's avatar
Wim Taymans committed
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
static GstElement*
make_dv_pipeline (const gchar *location) 
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink, *videosink;
  GstPad *seekable;
  
  pipeline = gst_pipeline_new ("app");

  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("dvdec", "decoder");
  videosink = gst_element_factory_make_or_warn ("xvideosink", "v_sink");
  audiosink = gst_element_factory_make_or_warn ("osssink", "a_sink");
  //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);
  gst_bin_add (GST_BIN (pipeline), videosink);

128 129 130
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
  gst_element_link (decoder, videosink);
Wim Taymans's avatar
Wim Taymans committed
131 132 133 134 135 136 137 138 139 140 141 142

  seekable = gst_element_get_pad (decoder, "video");
  seekable_pads = g_list_prepend (seekable_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, seekable);
  seekable = gst_element_get_pad (decoder, "audio");
  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;
}

Wim Taymans's avatar
Wim Taymans committed
143 144 145 146 147 148 149 150 151
static GstElement*
make_wav_pipeline (const gchar *location) 
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
  
  pipeline = gst_pipeline_new ("app");

152 153 154
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("wavparse", "decoder");
  audiosink = gst_element_factory_make_or_warn ("osssink", "sink");
Wim Taymans's avatar
Wim Taymans committed
155 156 157 158 159 160 161 162
  //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);

163 164
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
Wim Taymans's avatar
Wim Taymans committed
165 166 167 168 169 170 171 172 173

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

174 175 176 177 178 179 180 181 182
static GstElement*
make_flac_pipeline (const gchar *location) 
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
  
  pipeline = gst_pipeline_new ("app");

183 184 185
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("flacdec", "decoder");
  audiosink = gst_element_factory_make_or_warn ("osssink", "sink");
Wim Taymans's avatar
Wim Taymans committed
186
  g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
187 188 189 190 191 192 193

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

194 195
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213

  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_sid_pipeline (const gchar *location) 
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
  
  pipeline = gst_pipeline_new ("app");

214 215 216
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("siddec", "decoder");
  audiosink = gst_element_factory_make_or_warn ("osssink", "sink");
217 218 219 220 221 222 223 224
  //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);

225 226
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
227 228 229 230 231 232 233 234 235

  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
236 237 238 239 240 241 242 243 244
static GstElement*
make_parse_pipeline (const gchar *location) 
{
  GstElement *pipeline;
  GstElement *src, *parser, *fakesink;
  GstPad *seekable;
  
  pipeline = gst_pipeline_new ("app");

245 246 247
  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
248 249
  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
250 251 252 253 254 255 256

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

257 258
  gst_element_link (src, parser);
  gst_element_link (parser, fakesink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
259 260

  seekable = gst_element_get_pad (parser, "src");
261
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
262 263 264 265 266 267
  rate_pads = g_list_prepend (rate_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (parser, "sink"));

  return pipeline;
}

268 269 270 271 272 273 274 275 276
static GstElement*
make_vorbis_pipeline (const gchar *location) 
{
  GstElement *pipeline;
  GstElement *src, *decoder, *audiosink;
  GstPad *seekable;
  
  pipeline = gst_pipeline_new ("app");

277 278 279
  src = gst_element_factory_make_or_warn (SOURCE, "src");
  decoder = gst_element_factory_make_or_warn ("vorbisfile", "decoder");
  audiosink = gst_element_factory_make_or_warn ("osssink", "sink");
Wim Taymans's avatar
Wim Taymans committed
280
  g_object_set (G_OBJECT (audiosink), "sync", TRUE, NULL);
281 282 283 284 285 286 287

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

288 289
  gst_element_link (src, decoder);
  gst_element_link (decoder, audiosink);
290 291 292 293 294 295 296 297 298

  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
299 300 301 302
static GstElement*
make_mp3_pipeline (const gchar *location) 
{
  GstElement *pipeline;
303
  GstElement *src, *decoder, *osssink, *queue, *audio_thread;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
304 305 306 307
  GstPad *seekable;
  
  pipeline = gst_pipeline_new ("app");

308 309 310 311
  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");
  osssink = gst_element_factory_make_or_warn ("osssink", "sink");
312 313 314 315

  audio_thread = gst_thread_new ("a_decoder_thread");

  seekable_elements = g_list_prepend (seekable_elements, osssink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
316 317 318 319

  g_object_set (G_OBJECT (src), "location", location, NULL);
  g_object_set (G_OBJECT (osssink), "fragment", 0x00180008, NULL);

320 321 322 323 324
  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), decoder);
  gst_bin_add (GST_BIN (audio_thread), queue);
  gst_bin_add (GST_BIN (audio_thread), osssink);
  gst_bin_add (GST_BIN (pipeline), audio_thread);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
325

326 327 328
  gst_element_link (src, decoder);
  gst_element_link (decoder, queue);
  gst_element_link (queue, osssink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
329

330 331
  seekable = gst_element_get_pad (queue, "src");
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
  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_avi_pipeline (const gchar *location) 
{
  GstElement *pipeline, *audio_bin, *video_bin;
  GstElement *src, *demux, *a_decoder, *v_decoder, *audiosink, *videosink;
  GstElement *a_queue = NULL, *audio_thread = NULL, *v_queue = NULL, *video_thread = NULL;
  GstPad *seekable;
  
  pipeline = gst_pipeline_new ("app");

348
  src = gst_element_factory_make_or_warn (SOURCE, "src");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
349 350
  g_object_set (G_OBJECT (src), "location", location, NULL);

351
  demux = gst_element_factory_make_or_warn ("avidemux", "demux");
352
  seekable_elements = g_list_prepend (seekable_elements, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
353 354 355

  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), demux);
356
  gst_element_link (src, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
357 358

  audio_bin = gst_bin_new ("a_decoder_bin");
359
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
360
  audio_thread = gst_thread_new ("a_decoder_thread");
361
  audiosink = gst_element_factory_make_or_warn ("osssink", "a_sink");
362
  //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
363
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
364 365
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
366 367 368 369
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
  gst_bin_add (GST_BIN (audio_bin), audio_thread);
  gst_bin_add (GST_BIN (audio_thread), a_queue);
  gst_bin_add (GST_BIN (audio_thread), audiosink);
Wim Taymans's avatar
Wim Taymans committed
370
  gst_element_set_state (audio_bin, GST_STATE_PAUSED);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
371

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
372
  setup_dynamic_link (demux, "audio_00", gst_element_get_pad (a_decoder, "sink"), audio_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
373 374

  seekable = gst_element_get_pad (a_queue, "src");
375
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
376 377 378 379
  rate_pads = g_list_prepend (rate_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink"));

  video_bin = gst_bin_new ("v_decoder_bin");
380
  //v_decoder = gst_element_factory_make_or_warn ("identity", "v_dec");
Wim Taymans's avatar
Wim Taymans committed
381
  //v_decoder = gst_element_factory_make_or_warn ("windec", "v_dec");
Wim Taymans's avatar
Wim Taymans committed
382
  v_decoder = gst_element_factory_make_or_warn ("ffmpegdecall", "v_dec");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
383
  video_thread = gst_thread_new ("v_decoder_thread");
384 385
  videosink = gst_element_factory_make_or_warn ("xvideosink", "v_sink");
  //videosink = gst_element_factory_make_or_warn ("fakesink", "v_sink");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
386
  //g_object_set (G_OBJECT (videosink), "sync", TRUE, NULL);
387
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
Wim Taymans's avatar
Wim Taymans committed
388
  //g_object_set (G_OBJECT (v_queue), "max_level", 10, NULL);
389 390
  gst_element_link (v_decoder, v_queue);
  gst_element_link (v_queue, videosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
391 392 393 394 395
  gst_bin_add (GST_BIN (video_bin), v_decoder);
  gst_bin_add (GST_BIN (video_bin), video_thread);
  gst_bin_add (GST_BIN (video_thread), v_queue);
  gst_bin_add (GST_BIN (video_thread), videosink);

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

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
398
  setup_dynamic_link (demux, "video_00", gst_element_get_pad (v_decoder, "sink"), video_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
399 400

  seekable = gst_element_get_pad (v_queue, "src");
401
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
402 403 404 405 406 407 408 409 410 411
  rate_pads = g_list_prepend (rate_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (v_decoder, "sink"));

  return pipeline;
}

static GstElement*
make_mpeg_pipeline (const gchar *location) 
{
  GstElement *pipeline, *audio_bin, *video_bin;
412 413
  GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter;
  GstElement *audiosink, *videosink;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
414 415 416 417 418
  GstElement *a_queue, *audio_thread, *v_queue, *video_thread;
  GstPad *seekable;
  
  pipeline = gst_pipeline_new ("app");

419
  src = gst_element_factory_make_or_warn (SOURCE, "src");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
420 421
  g_object_set (G_OBJECT (src), "location", location, NULL);

422
  demux = gst_element_factory_make_or_warn ("mpegdemux", "demux");
Wim Taymans's avatar
Wim Taymans committed
423
  g_object_set (G_OBJECT (demux), "sync", FALSE, NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
424

425 426
  seekable_elements = g_list_prepend (seekable_elements, demux);

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
427 428
  gst_bin_add (GST_BIN (pipeline), src);
  gst_bin_add (GST_BIN (pipeline), demux);
429
  gst_element_link (src, demux);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
430 431

  audio_bin = gst_bin_new ("a_decoder_bin");
432
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
433
  audio_thread = gst_thread_new ("a_decoder_thread");
434 435
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
  audiosink = gst_element_factory_make_or_warn ("osssink", "a_sink");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
436
  g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
437 438
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
439 440 441 442 443
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
  gst_bin_add (GST_BIN (audio_bin), audio_thread);
  gst_bin_add (GST_BIN (audio_thread), a_queue);
  gst_bin_add (GST_BIN (audio_thread), audiosink);

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
444
  setup_dynamic_link (demux, "audio_00", gst_element_get_pad (a_decoder, "sink"), audio_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
445 446

  seekable = gst_element_get_pad (a_queue, "src");
447
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
448 449 450 451
  rate_pads = g_list_prepend (rate_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (a_decoder, "sink"));

  video_bin = gst_bin_new ("v_decoder_bin");
452
  v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
453
  video_thread = gst_thread_new ("v_decoder_thread");
Wim Taymans's avatar
Wim Taymans committed
454
  //g_object_set (G_OBJECT (video_thread), "priority", 2, NULL);
455 456 457
  v_queue = gst_element_factory_make_or_warn ("queue", "v_queue");
  v_filter = gst_element_factory_make_or_warn ("colorspace", "v_filter");
  videosink = gst_element_factory_make_or_warn ("xvideosink", "v_sink");
458
  gst_element_link_many (v_decoder, v_queue, v_filter, NULL);
459
  
460
  gst_element_link (v_filter, videosink);
461
  gst_bin_add_many (GST_BIN (video_bin), v_decoder, video_thread, NULL);
462
  gst_bin_add_many (GST_BIN (video_thread), v_queue, v_filter, videosink, NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
463

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
464
  setup_dynamic_link (demux, "video_00", gst_element_get_pad (v_decoder, "sink"), video_bin);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
465 466

  seekable = gst_element_get_pad (v_queue, "src");
467
  seekable_pads = g_list_prepend (seekable_pads, seekable);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
468 469 470 471 472 473
  rate_pads = g_list_prepend (rate_pads, seekable);
  rate_pads = g_list_prepend (rate_pads, gst_element_get_pad (v_decoder, "sink"));

  return pipeline;
}

Wim Taymans's avatar
Wim Taymans committed
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
static GstElement*
make_mpegnt_pipeline (const gchar *location) 
{
  GstElement *pipeline, *audio_bin, *video_bin;
  GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter;
  GstElement *audiosink, *videosink;
  GstElement *a_queue, *audio_thread;
  GstPad *seekable;
  
  pipeline = gst_pipeline_new ("app");

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

  demux = gst_element_factory_make_or_warn ("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);
495
  gst_element_link (src, demux);
Wim Taymans's avatar
Wim Taymans committed
496 497 498 499 500 501 502 503

  audio_bin = gst_bin_new ("a_decoder_bin");
  a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec");
  audio_thread = gst_thread_new ("a_decoder_thread");
  a_queue = gst_element_factory_make_or_warn ("queue", "a_queue");
  audiosink = gst_element_factory_make_or_warn ("osssink", "a_sink");
  //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL);
  g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
504 505
  gst_element_link (a_decoder, a_queue);
  gst_element_link (a_queue, audiosink);
Wim Taymans's avatar
Wim Taymans committed
506 507 508 509 510
  gst_bin_add (GST_BIN (audio_bin), a_decoder);
  gst_bin_add (GST_BIN (audio_bin), audio_thread);
  gst_bin_add (GST_BIN (audio_thread), a_queue);
  gst_bin_add (GST_BIN (audio_thread), audiosink);

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
511
  setup_dynamic_link (demux, "audio_00", gst_element_get_pad (a_decoder, "sink"), audio_bin);
Wim Taymans's avatar
Wim Taymans committed
512 513 514 515 516 517 518 519 520 521

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

  video_bin = gst_bin_new ("v_decoder_bin");
  v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec");
  v_filter = gst_element_factory_make_or_warn ("colorspace", "v_filter");
  videosink = gst_element_factory_make_or_warn ("xvideosink", "v_sink");
522
  gst_element_link_many (v_decoder, v_filter, videosink, NULL);
Wim Taymans's avatar
Wim Taymans committed
523 524 525
  
  gst_bin_add_many (GST_BIN (video_bin), v_decoder, v_filter, videosink, NULL);

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
526
  setup_dynamic_link (demux, "video_00", gst_element_get_pad (v_decoder, "sink"), video_bin);
Wim Taymans's avatar
Wim Taymans committed
527 528 529 530 531 532 533 534 535

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

  return pipeline;
}

Wim Taymans's avatar
Wim Taymans committed
536 537 538 539 540 541
static GstElement*
make_playerbin_pipeline (const gchar *location) 
{
  return NULL;
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
542 543 544 545
static gchar*
format_value (GtkScale *scale,
	      gdouble   value)
{
546 547 548 549 550 551 552
  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
553

554
  return g_strdup_printf ("%02lld:%02lld:%02lld",
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
                          seconds/60, 
			  seconds%60, 
			  subseconds%100);
}

typedef struct
{
  const gchar *name;
  const GstFormat format;
} seek_format;

static seek_format seek_formats[] = 
{
  { "tim",  GST_FORMAT_TIME    },
  { "byt",  GST_FORMAT_BYTES   },
  { "buf",  GST_FORMAT_BUFFERS },
  { "def",  GST_FORMAT_DEFAULT },
  { NULL, 0 }, 
};

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;

      if (gst_pad_convert (pad, GST_FORMAT_TIME, GST_SECOND, 
		           &format, &value)) 
      {
594
        g_print ("%s %13lld | ", seek_formats[i].name, value);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
595 596
      }
      else {
597
        g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
598 599 600 601 602 603 604 605 606 607 608
      }

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

    walk = g_list_next (walk);
  }
}

G_GNUC_UNUSED static void
609
query_durations ()
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
610
{
611 612 613 614 615 616 617 618 619 620 621 622 623
  GList *walk = seekable_pads;

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

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

      format = seek_formats[i].format;
Wim Taymans's avatar
Wim Taymans committed
624
      res = gst_pad_query (pad, GST_QUERY_TOTAL, &format, &value);
625 626 627 628 629 630 631
      if (res) {
        g_print ("%s %13lld | ", seek_formats[i].name, value);
      }
      else {
        g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*");
      }
      i++;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
632
    }
633 634 635
    g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad));
  
    walk = g_list_next (walk);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
636 637 638 639
  }
}

G_GNUC_UNUSED static void
640
query_positions ()
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
641
{
642 643 644 645 646 647 648 649 650 651 652 653 654
  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) {
      gboolean res;
      gint64 value;
      GstFormat format;

      format = seek_formats[i].format;
Wim Taymans's avatar
Wim Taymans committed
655
      res = gst_pad_query (pad, GST_QUERY_POSITION, &format, &value);
656 657 658 659 660 661 662
      if (res) {
        g_print ("%s %13lld | ", seek_formats[i].name, value);
      }
      else {
        g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*");
      }
      i++;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
663
    }
664 665 666
    g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad));

    walk = g_list_next (walk);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
667 668 669 670 671 672 673
  }
}

static gboolean
update_scale (gpointer data) 
{
  GstClock *clock;
674 675
  guint64 position;
  GstFormat format = GST_FORMAT_TIME;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
676

677
  duration = 0;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
678 679
  clock = gst_bin_get_clock (GST_BIN (pipeline));

680 681
  if (seekable_pads) {
    GstPad *pad = GST_PAD (seekable_pads->data);
Wim Taymans's avatar
Wim Taymans committed
682
    gst_pad_query (pad, GST_QUERY_TOTAL, &format, &duration);
683 684
  }
  position = gst_clock_get_time (clock);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
685

686 687 688 689 690
  if (stats) {
    g_print ("clock:                  %13llu  (%s)\n", position, gst_object_get_name (GST_OBJECT (clock)));
    query_durations ();
    query_positions ();
    query_rates ();
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727
  }

  if (duration > 0) {
    gtk_adjustment_set_value (adjustment, position * 100.0 / duration);
  }

  return TRUE;
}

static gboolean
iterate (gpointer data)
{
  gboolean res;

  res = gst_bin_iterate (GST_BIN (data));
  if (!res) {
    gtk_timeout_remove (update_id);
    g_print ("stopping iterations\n");
  }
  return res;
}

static gboolean
start_seek (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
{
  gst_element_set_state (pipeline, GST_STATE_PAUSED);
  gtk_timeout_remove (update_id);

  return FALSE;
}

static gboolean
stop_seek (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
{
  gint64 real = gtk_range_get_value (GTK_RANGE (widget)) * duration / 100;
  gboolean res;
  GstEvent *s_event;
728 729
#ifdef PAD_SEEK
  GList *walk = seekable_pads;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
730 731 732 733 734 735 736 737 738 739 740 741 742

  while (walk) {
    GstPad *seekable = GST_PAD (walk->data);

    g_print ("seek to %lld on pad %s:%s\n", real, GST_DEBUG_PAD_NAME (seekable));
    s_event = gst_event_new_seek (GST_FORMAT_TIME |
			   	  GST_SEEK_METHOD_SET |
				  GST_SEEK_FLAG_FLUSH, real);

    res = gst_pad_send_event (seekable, s_event);

    walk = g_list_next (walk);
  }
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758
#else
  GList *walk = seekable_elements;

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

    g_print ("seek to %lld on element %s\n", real, gst_element_get_name (seekable));
    s_event = gst_event_new_seek (GST_FORMAT_TIME |
			   	  GST_SEEK_METHOD_SET |
				  GST_SEEK_FLAG_FLUSH, real);

    res = gst_element_send_event (seekable, s_event);

    walk = g_list_next (walk);
  }
#endif
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
759 760 761 762 763 764 765 766 767 768 769

  gst_element_set_state (pipeline, GST_STATE_PLAYING);
  gtk_idle_add ((GtkFunction) iterate, pipeline);
  update_id = gtk_timeout_add (UPDATE_INTERVAL, (GtkFunction) update_scale, pipeline);

  return FALSE;
}

static void
play_cb (GtkButton * button, gpointer data)
{
770 771 772 773 774
  if (gst_element_get_state (pipeline) != GST_STATE_PLAYING) {
    gst_element_set_state (pipeline, GST_STATE_PLAYING);
    gtk_idle_add ((GtkFunction) iterate, pipeline);
    update_id = gtk_timeout_add (UPDATE_INTERVAL, (GtkFunction) update_scale, pipeline);
  }
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
775 776 777 778 779
}

static void
pause_cb (GtkButton * button, gpointer data)
{
780 781 782 783
  if (gst_element_get_state (pipeline) != GST_STATE_PAUSED) {
    gst_element_set_state (pipeline, GST_STATE_PAUSED);
    gtk_timeout_remove (update_id);
  }
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
784 785 786 787 788
}

static void
stop_cb (GtkButton * button, gpointer data)
{
789 790 791 792
  if (gst_element_get_state (pipeline) != GST_STATE_READY) {
    gst_element_set_state (pipeline, GST_STATE_READY);
    gtk_timeout_remove (update_id);
  }
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
793 794
}

Wim Taymans's avatar
Wim Taymans committed
795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831
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 	}, 
  { "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 },
  { NULL, NULL},
};

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

static void
print_usage (int argc, char **argv)
{
  gint i;

  g_print ("usage: %s <type> <filename>\n", argv[0]);
  g_print ("   possible types:\n");

  for (i = 0; i < NUM_TYPES; i++) {
    g_print ("     %d = %s\n", i, pipelines[i].name);
  }
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
832 833 834 835 836 837
int
main (int argc, char **argv)
{
  GtkWidget *window, *hbox, *vbox, 
            *play_button, *pause_button, *stop_button, 
	    *hscale;
838
  struct poptOption options[] = {
Wim Taymans's avatar
Wim Taymans committed
839 840
    { "stats",  's',  POPT_ARG_NONE|POPT_ARGFLAG_STRIP,   &stats,   0,
           "Show pad stats", NULL },
841 842
    POPT_TABLEEND
  };
Wim Taymans's avatar
Wim Taymans committed
843
  gint type;
844 845
	        
  gst_init_with_popt_table (&argc, &argv, options);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
846 847 848
  gtk_init (&argc, &argv);

  if (argc != 3) {
Wim Taymans's avatar
Wim Taymans committed
849 850 851 852 853 854 855 856
    print_usage (argc, argv);
    exit (-1);
  }

  type = atoi (argv[1]);

  if (type < 0 || type >= NUM_TYPES) {
    print_usage (argc, argv);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
857 858 859
    exit (-1);
  }

Wim Taymans's avatar
Wim Taymans committed
860 861
  pipeline = pipelines[type].func (argv[2]);
  g_assert (pipeline);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
862 863 864 865 866 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

  /* initialize gui elements ... */
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  hbox = gtk_hbox_new (FALSE, 0);
  vbox = gtk_vbox_new (FALSE, 0);
  play_button = gtk_button_new_with_label ("play");
  pause_button = gtk_button_new_with_label ("pause");
  stop_button = gtk_button_new_with_label ("stop");

  adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.00, 100.0, 0.1, 1.0, 1.0));
  hscale = gtk_hscale_new (adjustment);
  gtk_scale_set_digits (GTK_SCALE (hscale), 2);
  gtk_range_set_update_policy (GTK_RANGE (hscale), GTK_UPDATE_CONTINUOUS);

  gtk_signal_connect(GTK_OBJECT(hscale),
                             "button_press_event", G_CALLBACK (start_seek), pipeline);
  gtk_signal_connect(GTK_OBJECT(hscale),
                             "button_release_event", G_CALLBACK (stop_seek), pipeline);
  gtk_signal_connect(GTK_OBJECT(hscale),
                             "format_value", G_CALLBACK (format_value), pipeline);

  /* do the packing stuff ... */
  gtk_window_set_default_size (GTK_WINDOW (window), 96, 96);
  gtk_container_add (GTK_CONTAINER (window), vbox);
  gtk_container_add (GTK_CONTAINER (vbox), hbox);
  gtk_box_pack_start (GTK_BOX (hbox), play_button, FALSE, FALSE, 2);
  gtk_box_pack_start (GTK_BOX (hbox), pause_button, FALSE, FALSE, 2);
  gtk_box_pack_start (GTK_BOX (hbox), stop_button, FALSE, FALSE, 2);
  gtk_box_pack_start (GTK_BOX (vbox), hscale, TRUE, TRUE, 2);

  /* connect things ... */
  g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK (play_cb), pipeline);
  g_signal_connect (G_OBJECT (pause_button), "clicked", G_CALLBACK (pause_cb), pipeline);
  g_signal_connect (G_OBJECT (stop_button), "clicked", G_CALLBACK (stop_cb), pipeline);
  g_signal_connect (G_OBJECT (window), "delete_event", gtk_main_quit, NULL);

  /* show the gui. */
  gtk_widget_show_all (window);

Wim Taymans's avatar
Wim Taymans committed
901 902 903
  g_signal_connect (pipeline, "deep_notify", G_CALLBACK (gst_element_default_deep_notify), NULL);
  g_signal_connect (pipeline, "error", G_CALLBACK (gst_element_default_error), NULL);

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
904 905
  gtk_main ();

Wim Taymans's avatar
Wim Taymans committed
906 907
  gst_element_set_state (pipeline, GST_STATE_NULL);

908 909
  //gst_object_unref (GST_OBJECT (pipeline));

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
910 911 912 913
  //g_mem_chunk_info();

  return 0;
}