vorbisdec.c 39.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* GStreamer
 * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
 *
 * 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.
 */

Wim Taymans's avatar
Wim Taymans committed
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
 * SECTION:element-vorbisdec
 * @short_description: a decoder that decodes Vorbis to raw audio
 * @see_also: vorbisenc, oggdemux
 *
 * <refsect2>
 * <para>
 * This element decodes a Vorbis stream to raw float audio.
 * <ulink url="http://www.vorbis.com/">Vorbis</ulink> is a royalty-free
 * audio codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
 * Foundation</ulink>.
 * </para>
 * <title>Example pipelines</title>
 * <para>
 * <programlisting>
 * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink
 * </programlisting>
 * Decode an Ogg/Vorbis. To create an Ogg/Vorbis file refer to the documentation of vorbisenc.
 * </para>
 * </refsect2>
 *
 * Last reviewed on 2006-03-01 (0.10.4)
 */

44
45
46
47
48
49
#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include "vorbisdec.h"
#include <string.h>
50
#include <gst/audio/audio.h>
51
#include <gst/tag/tag.h>
Ronald S. Bultje's avatar
Ronald S. Bultje committed
52
#include <gst/audio/multichannel.h>
53

54
55
56
GST_DEBUG_CATEGORY_EXTERN (vorbisdec_debug);
#define GST_CAT_DEFAULT vorbisdec_debug

Stefan Kost's avatar
Stefan Kost committed
57
static const GstElementDetails vorbis_dec_details =
j^'s avatar
j^ committed
58
GST_ELEMENT_DETAILS ("Vorbis audio decoder",
59
60
61
    "Codec/Decoder/Audio",
    "decode raw vorbis streams to float audio",
    "Benjamin Otte <in7y118@public.uni-hamburg.de>");
62
63

static GstStaticPadTemplate vorbis_dec_src_factory =
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
64
65
66
67
GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("audio/x-raw-float, "
68
69
        "rate = (int) [ 1, MAX ], "
        "channels = (int) [ 1, 256 ], " "endianness = (int) BYTE_ORDER, "
70
/* no ifdef in macros, please
71
72
73
#ifdef GST_VORBIS_DEC_SEQUENTIAL
      "layout = \"sequential\", "
#endif
74
*/
Wim Taymans's avatar
Wim Taymans committed
75
        "width = (int) 32")
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
76
    );
77
78

static GstStaticPadTemplate vorbis_dec_sink_factory =
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
79
80
81
82
83
GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("audio/x-vorbis")
    );
84
85

GST_BOILERPLATE (GstVorbisDec, gst_vorbis_dec, GstElement, GST_TYPE_ELEMENT);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
86

87
static void vorbis_dec_finalize (GObject * object);
88
89
static gboolean vorbis_dec_sink_event (GstPad * pad, GstEvent * event);
static GstFlowReturn vorbis_dec_chain (GstPad * pad, GstBuffer * buffer);
90
91
static GstFlowReturn vorbis_dec_chain_forward (GstVorbisDec * vd,
    gboolean discont, GstBuffer * buffer);
92
93
static GstStateChangeReturn vorbis_dec_change_state (GstElement * element,
    GstStateChange transition);
Wim Taymans's avatar
Wim Taymans committed
94

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
95
static gboolean vorbis_dec_src_event (GstPad * pad, GstEvent * event);
Wim Taymans's avatar
Wim Taymans committed
96
static gboolean vorbis_dec_src_query (GstPad * pad, GstQuery * query);
97
98
99
static gboolean vorbis_dec_convert (GstPad * pad,
    GstFormat src_format, gint64 src_value,
    GstFormat * dest_format, gint64 * dest_value);
100

Wim Taymans's avatar
Wim Taymans committed
101
static gboolean vorbis_dec_sink_query (GstPad * pad, GstQuery * query);
102
103
104
105
106

static void
gst_vorbis_dec_base_init (gpointer g_class)
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
Johan Dahlin's avatar
Johan Dahlin committed
107
108
109
110
111
112
113
  GstPadTemplate *src_template, *sink_template;

  src_template = gst_static_pad_template_get (&vorbis_dec_src_factory);
  gst_element_class_add_pad_template (element_class, src_template);

  sink_template = gst_static_pad_template_get (&vorbis_dec_sink_factory);
  gst_element_class_add_pad_template (element_class, sink_template);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
114

115
116
117
118
  gst_element_class_set_details (element_class, &vorbis_dec_details);
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
119
gst_vorbis_dec_class_init (GstVorbisDecClass * klass)
120
{
121
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
122
123
  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);

124
  gobject_class->finalize = vorbis_dec_finalize;
125

126
  gstelement_class->change_state = GST_DEBUG_FUNCPTR (vorbis_dec_change_state);
127
128
}

129
130
131
132
133
static const GstQueryType *
vorbis_get_query_types (GstPad * pad)
{
  static const GstQueryType vorbis_dec_src_query_types[] = {
    GST_QUERY_POSITION,
134
135
    GST_QUERY_DURATION,
    GST_QUERY_CONVERT,
136
137
138
139
140
141
    0
  };

  return vorbis_dec_src_query_types;
}

142
static void
143
gst_vorbis_dec_init (GstVorbisDec * dec, GstVorbisDecClass * g_class)
144
{
145
146
  dec->sinkpad = gst_pad_new_from_static_template (&vorbis_dec_sink_factory,
      "sink");
Johan Dahlin's avatar
Johan Dahlin committed
147

148
149
150
151
152
153
  gst_pad_set_event_function (dec->sinkpad,
      GST_DEBUG_FUNCPTR (vorbis_dec_sink_event));
  gst_pad_set_chain_function (dec->sinkpad,
      GST_DEBUG_FUNCPTR (vorbis_dec_chain));
  gst_pad_set_query_function (dec->sinkpad,
      GST_DEBUG_FUNCPTR (vorbis_dec_sink_query));
154
155
  gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);

156
157
  dec->srcpad = gst_pad_new_from_static_template (&vorbis_dec_src_factory,
      "src");
Johan Dahlin's avatar
Johan Dahlin committed
158

159
160
161
162
163
164
  gst_pad_set_event_function (dec->srcpad,
      GST_DEBUG_FUNCPTR (vorbis_dec_src_event));
  gst_pad_set_query_type_function (dec->srcpad,
      GST_DEBUG_FUNCPTR (vorbis_get_query_types));
  gst_pad_set_query_function (dec->srcpad,
      GST_DEBUG_FUNCPTR (vorbis_dec_src_query));
165
  gst_pad_use_fixed_caps (dec->srcpad);
166
  gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
Wim Taymans's avatar
Wim Taymans committed
167
168

  dec->queued = NULL;
169
170
  dec->pendingevents = NULL;
  dec->taglist = NULL;
171
172
}

173
static void
174
vorbis_dec_finalize (GObject * object)
175
{
176
  /* Release any possibly allocated libvorbis data.
177
178
179
180
181
182
183
184
   * _clear functions can safely be called multiple times
   */
  GstVorbisDec *vd = GST_VORBIS_DEC (object);

  vorbis_block_clear (&vd->vb);
  vorbis_dsp_clear (&vd->vd);
  vorbis_comment_clear (&vd->vc);
  vorbis_info_clear (&vd->vi);
185
186

  G_OBJECT_CLASS (parent_class)->finalize (object);
187
188
}

189
190
191
192
193
194
195
196
197
static void
gst_vorbis_dec_reset (GstVorbisDec * dec)
{
  dec->cur_timestamp = GST_CLOCK_TIME_NONE;
  dec->prev_timestamp = GST_CLOCK_TIME_NONE;
  dec->granulepos = -1;
  dec->discont = TRUE;
  gst_segment_init (&dec->segment, GST_FORMAT_TIME);

198
  g_list_foreach (dec->queued, (GFunc) gst_mini_object_unref, NULL);
199
200
  g_list_free (dec->queued);
  dec->queued = NULL;
201
202
203
204
205
206
207
  g_list_foreach (dec->gather, (GFunc) gst_mini_object_unref, NULL);
  g_list_free (dec->gather);
  dec->gather = NULL;
  g_list_foreach (dec->decode, (GFunc) gst_mini_object_unref, NULL);
  g_list_free (dec->decode);
  dec->decode = NULL;
  g_list_foreach (dec->pendingevents, (GFunc) gst_mini_object_unref, NULL);
208
209
210
211
212
213
  g_list_free (dec->pendingevents);
  dec->pendingevents = NULL;

  if (dec->taglist)
    gst_tag_list_free (dec->taglist);
  dec->taglist = NULL;
214
215
216
}


217
static gboolean
218
219
220
vorbis_dec_convert (GstPad * pad,
    GstFormat src_format, gint64 src_value,
    GstFormat * dest_format, gint64 * dest_value)
221
{
222
223
224
  gboolean res = TRUE;
  GstVorbisDec *dec;
  guint64 scale = 1;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
225

Wim Taymans's avatar
Wim Taymans committed
226
227
228
229
230
  if (src_format == *dest_format) {
    *dest_value = src_value;
    return TRUE;
  }

231
232
  dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));

233
  if (!dec->initialized)
234
235
    goto no_header;

236
237
  if (dec->sinkpad == pad &&
      (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES))
238
    goto no_format;
239

240
  switch (src_format) {
241
    case GST_FORMAT_TIME:
242
243
244
245
      switch (*dest_format) {
        case GST_FORMAT_BYTES:
          scale = sizeof (float) * dec->vi.channels;
        case GST_FORMAT_DEFAULT:
246
247
248
          *dest_value =
              scale * gst_util_uint64_scale_int (src_value, dec->vi.rate,
              GST_SECOND);
249
250
251
252
253
          break;
        default:
          res = FALSE;
      }
      break;
254
    case GST_FORMAT_DEFAULT:
255
256
257
258
259
      switch (*dest_format) {
        case GST_FORMAT_BYTES:
          *dest_value = src_value * sizeof (float) * dec->vi.channels;
          break;
        case GST_FORMAT_TIME:
260
          *dest_value =
261
              gst_util_uint64_scale_int (src_value, GST_SECOND, dec->vi.rate);
262
263
264
265
266
          break;
        default:
          res = FALSE;
      }
      break;
267
    case GST_FORMAT_BYTES:
268
269
270
271
272
      switch (*dest_format) {
        case GST_FORMAT_DEFAULT:
          *dest_value = src_value / (sizeof (float) * dec->vi.channels);
          break;
        case GST_FORMAT_TIME:
273
          *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND,
274
              dec->vi.rate * sizeof (float) * dec->vi.channels);
275
276
277
278
279
          break;
        default:
          res = FALSE;
      }
      break;
280
    default:
281
      res = FALSE;
282
  }
283
284
done:
  gst_object_unref (dec);
285

286
  return res;
287
288
289
290
291
292
293
294
295
296
297
298
299
300

  /* ERRORS */
no_header:
  {
    GST_DEBUG_OBJECT (dec, "no header packets received");
    res = FALSE;
    goto done;
  }
no_format:
  {
    GST_DEBUG_OBJECT (dec, "formats unsupported");
    res = FALSE;
    goto done;
  }
301
}
302
303

static gboolean
Wim Taymans's avatar
Wim Taymans committed
304
vorbis_dec_src_query (GstPad * pad, GstQuery * query)
305
{
Wim Taymans's avatar
Wim Taymans committed
306
  GstVorbisDec *dec;
307
  gboolean res = FALSE;
Wim Taymans's avatar
Wim Taymans committed
308

309
  dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
Wim Taymans's avatar
Wim Taymans committed
310
311
312
313

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_POSITION:
    {
314
315
316
      gint64 granulepos, value;
      GstFormat my_format, format;
      gint64 time;
Wim Taymans's avatar
Wim Taymans committed
317

318
      /* we start from the last seen granulepos */
Wim Taymans's avatar
Wim Taymans committed
319
320
      granulepos = dec->granulepos;

Wim Taymans's avatar
Wim Taymans committed
321
      gst_query_parse_position (query, &format, NULL);
Wim Taymans's avatar
Wim Taymans committed
322

323
324
325
      /* and convert to the final format in two steps with time as the
       * intermediate step */
      my_format = GST_FORMAT_TIME;
Wim Taymans's avatar
Wim Taymans committed
326
      if (!(res =
327
328
              vorbis_dec_convert (pad, GST_FORMAT_DEFAULT, granulepos,
                  &my_format, &time)))
Wim Taymans's avatar
Wim Taymans committed
329
330
        goto error;

331
      /* correct for the segment values */
332
333
334
335
336
337
338
339
      time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time);

      GST_LOG_OBJECT (dec,
          "query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time));

      /* and convert to the final format */
      if (!(res = vorbis_dec_convert (pad, my_format, time, &format, &value)))
        goto error;
340

Wim Taymans's avatar
Wim Taymans committed
341
      gst_query_set_position (query, format, value);
Wim Taymans's avatar
Wim Taymans committed
342
343

      GST_LOG_OBJECT (dec,
344
          "query %p: we return %lld (format %u)", query, value, format);
Wim Taymans's avatar
Wim Taymans committed
345
346
347

      break;
    }
Wim Taymans's avatar
Wim Taymans committed
348
349
    case GST_QUERY_DURATION:
    {
350
351
352
      GstPad *peer;

      if (!(peer = gst_pad_get_peer (dec->sinkpad))) {
353
354
355
356
        GST_WARNING_OBJECT (dec, "sink pad %" GST_PTR_FORMAT " is not linked",
            dec->sinkpad);
        goto error;
      }
357
358
359
360

      res = gst_pad_query (peer, query);
      gst_object_unref (peer);
      if (!res)
Wim Taymans's avatar
Wim Taymans committed
361
        goto error;
362

Wim Taymans's avatar
Wim Taymans committed
363
364
      break;
    }
Wim Taymans's avatar
Wim Taymans committed
365
366
367
368
369
370
371
372
373
374
375
376
377
    case GST_QUERY_CONVERT:
    {
      GstFormat src_fmt, dest_fmt;
      gint64 src_val, dest_val;

      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
      if (!(res =
              vorbis_dec_convert (pad, src_fmt, src_val, &dest_fmt, &dest_val)))
        goto error;
      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
      break;
    }
    default:
378
      res = gst_pad_query_default (pad, query);
Wim Taymans's avatar
Wim Taymans committed
379
380
      break;
  }
381
382
383
done:
  gst_object_unref (dec);

Wim Taymans's avatar
Wim Taymans committed
384
  return res;
385

386
  /* ERRORS */
Wim Taymans's avatar
Wim Taymans committed
387
388
error:
  {
389
    GST_WARNING_OBJECT (dec, "error handling query");
390
    goto done;
391
  }
Wim Taymans's avatar
Wim Taymans committed
392
}
393

Wim Taymans's avatar
Wim Taymans committed
394
395
396
397
398
399
static gboolean
vorbis_dec_sink_query (GstPad * pad, GstQuery * query)
{
  GstVorbisDec *dec;
  gboolean res;

400
  dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
401

Wim Taymans's avatar
Wim Taymans committed
402
403
404
405
406
407
408
409
410
411
412
413
414
415
  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_CONVERT:
    {
      GstFormat src_fmt, dest_fmt;
      gint64 src_val, dest_val;

      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
      if (!(res =
              vorbis_dec_convert (pad, src_fmt, src_val, &dest_fmt, &dest_val)))
        goto error;
      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
      break;
    }
    default:
416
      res = gst_pad_query_default (pad, query);
Wim Taymans's avatar
Wim Taymans committed
417
418
      break;
  }
419
420
421
422

done:
  gst_object_unref (dec);

Wim Taymans's avatar
Wim Taymans committed
423
  return res;
424
425
426
427
428
429
430

  /* ERRORS */
error:
  {
    GST_DEBUG_OBJECT (dec, "error converting value");
    goto done;
  }
431
432
}

433
static gboolean
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
434
vorbis_dec_src_event (GstPad * pad, GstEvent * event)
435
436
{
  gboolean res = TRUE;
437
438
439
  GstVorbisDec *dec;

  dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
440
441

  switch (GST_EVENT_TYPE (event)) {
442
443
    case GST_EVENT_SEEK:
    {
444
445
446
447
448
449
450
451
452
453
      GstFormat format, tformat;
      gdouble rate;
      GstEvent *real_seek;
      GstSeekFlags flags;
      GstSeekType cur_type, stop_type;
      gint64 cur, stop;
      gint64 tcur, tstop;

      gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
          &stop_type, &stop);
454
      gst_event_unref (event);
455
456
457
458
459
460
461
462
463

      /* we have to ask our peer to seek to time here as we know
       * nothing about how to generate a granulepos from the src
       * formats or anything.
       *
       * First bring the requested format to time
       */
      tformat = GST_FORMAT_TIME;
      if (!(res = vorbis_dec_convert (pad, format, cur, &tformat, &tcur)))
464
        goto convert_error;
465
      if (!(res = vorbis_dec_convert (pad, format, stop, &tformat, &tstop)))
466
        goto convert_error;
467
468
469
470
471

      /* then seek with time on the peer */
      real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
          flags, cur_type, tcur, stop_type, tstop);

472
      res = gst_pad_push_event (dec->sinkpad, real_seek);
473

474
475
476
      break;
    }
    default:
477
      res = gst_pad_push_event (dec->sinkpad, event);
478
479
      break;
  }
480
481
done:
  gst_object_unref (dec);
482
483

  return res;
484

485
  /* ERRORS */
486
convert_error:
487
488
489
490
  {
    GST_DEBUG_OBJECT (dec, "cannot convert start/stop for seek");
    goto done;
  }
491
}
492

493
494
static gboolean
vorbis_dec_sink_event (GstPad * pad, GstEvent * event)
495
{
496
  gboolean ret = FALSE;
497
498
  GstVorbisDec *dec;

Wim Taymans's avatar
Wim Taymans committed
499
  dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
500

501
502
  GST_LOG_OBJECT (dec, "handling event");
  switch (GST_EVENT_TYPE (event)) {
Wim Taymans's avatar
Wim Taymans committed
503
504
505
    case GST_EVENT_EOS:
      ret = gst_pad_push_event (dec->srcpad, event);
      break;
506
507
508
509
    case GST_EVENT_FLUSH_START:
      ret = gst_pad_push_event (dec->srcpad, event);
      break;
    case GST_EVENT_FLUSH_STOP:
510
511
512
513
514
      /* here we must clean any state in the decoder */
#ifdef HAVE_VORBIS_SYNTHESIS_RESTART
      vorbis_synthesis_restart (&dec->vd);
#endif
      gst_vorbis_dec_reset (dec);
515
516
      ret = gst_pad_push_event (dec->srcpad, event);
      break;
517
    case GST_EVENT_NEWSEGMENT:
518
519
    {
      GstFormat format;
520
      gdouble rate, arate;
Wim Taymans's avatar
Wim Taymans committed
521
      gint64 start, stop, time;
522
      gboolean update;
523

524
525
      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
          &start, &stop, &time);
526

527
      /* we need time for now */
528
529
530
      if (format != GST_FORMAT_TIME)
        goto newseg_wrong_format;

531
532
533
534
535
536
      GST_DEBUG_OBJECT (dec,
          "newsegment: update %d, rate %g, arate %g, start %" GST_TIME_FORMAT
          ", stop %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT,
          update, rate, arate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
          GST_TIME_ARGS (time));

537
      /* now configure the values */
538
539
      gst_segment_set_newsegment_full (&dec->segment, update,
          rate, arate, format, start, stop, time);
540

541
542
543
544
545
546
547
548
      if (dec->initialized)
        /* and forward */
        ret = gst_pad_push_event (dec->srcpad, event);
      else {
        /* store it to send once we're initialized */
        dec->pendingevents = g_list_append (dec->pendingevents, event);
        ret = TRUE;
      }
549
      break;
550
    }
551
    default:
Wim Taymans's avatar
Wim Taymans committed
552
      ret = gst_pad_push_event (dec->srcpad, event);
553
554
      break;
  }
555
done:
Wim Taymans's avatar
Wim Taymans committed
556
557
  gst_object_unref (dec);

558
  return ret;
559

560
561
562
  /* ERRORS */
newseg_wrong_format:
  {
563
    GST_DEBUG_OBJECT (dec, "received non TIME newsegment");
564
565
    goto done;
  }
566
567
}

568
static GstFlowReturn
569
vorbis_handle_identification_packet (GstVorbisDec * vd)
570
571
572
573
574
575
576
577
578
579
{
  GstCaps *caps;
  const GstAudioChannelPosition *pos = NULL;

  switch (vd->vi.channels) {
    case 1:
    case 2:
      /* nothing */
      break;
    case 3:{
580
      static const GstAudioChannelPosition pos3[] = {
581
582
583
584
585
586
587
588
        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT
      };
      pos = pos3;
      break;
    }
    case 4:{
589
      static const GstAudioChannelPosition pos4[] = {
590
591
592
593
594
595
596
597
598
        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT
      };
      pos = pos4;
      break;
    }
    case 5:{
599
      static const GstAudioChannelPosition pos5[] = {
600
601
602
603
604
605
606
607
608
609
        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT
      };
      pos = pos5;
      break;
    }
    case 6:{
610
      static const GstAudioChannelPosition pos6[] = {
611
612
613
614
615
616
617
618
619
620
        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
        GST_AUDIO_CHANNEL_POSITION_LFE
      };
      pos = pos6;
      break;
    }
621
622
    default:
      goto channel_count_error;
623
  }
624
625
626
627
628
629

  caps = gst_caps_new_simple ("audio/x-raw-float",
      "rate", G_TYPE_INT, vd->vi.rate,
      "channels", G_TYPE_INT, vd->vi.channels,
      "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);

630
631
632
633
634
635
636
  if (pos) {
    gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
  }
  gst_pad_set_caps (vd->srcpad, caps);
  gst_caps_unref (caps);

  return GST_FLOW_OK;
637
638
639
640
641
642
643
644

  /* ERROR */
channel_count_error:
  {
    GST_ELEMENT_ERROR (vd, STREAM, NOT_IMPLEMENTED, (NULL),
        ("Unsupported channel count %d", vd->vi.channels));
    return GST_FLOW_ERROR;
  }
645
646
}

647
648
649
650
651
static GstFlowReturn
vorbis_handle_comment_packet (GstVorbisDec * vd, ogg_packet * packet)
{
  guint bitrate = 0;
  gchar *encoder = NULL;
652
  GstTagList *list;
653
654
655
656
657
658
659
  GstBuffer *buf;

  GST_DEBUG_OBJECT (vd, "parsing comment packet");

  buf = gst_buffer_new_and_alloc (packet->bytes);
  GST_BUFFER_DATA (buf) = packet->packet;

660
  list =
661
      gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\003vorbis", 7,
662
663
664
      &encoder);

  vd->taglist = gst_tag_list_merge (vd->taglist, list, GST_TAG_MERGE_REPLACE);
665

666
  gst_tag_list_free (list);
667
668
  gst_buffer_unref (buf);

669
  if (!vd->taglist) {
670
    GST_ERROR_OBJECT (vd, "couldn't decode comments");
671
    vd->taglist = gst_tag_list_new ();
672
673
  }
  if (encoder) {
674
    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
675
676
677
        GST_TAG_ENCODER, encoder, NULL);
    g_free (encoder);
  }
678
  gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
679
680
681
      GST_TAG_ENCODER_VERSION, vd->vi.version,
      GST_TAG_AUDIO_CODEC, "Vorbis", NULL);
  if (vd->vi.bitrate_nominal > 0) {
682
    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
683
684
685
686
        GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL);
    bitrate = vd->vi.bitrate_nominal;
  }
  if (vd->vi.bitrate_upper > 0) {
687
    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
688
689
690
691
692
        GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL);
    if (!bitrate)
      bitrate = vd->vi.bitrate_upper;
  }
  if (vd->vi.bitrate_lower > 0) {
693
    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
694
695
696
697
698
        GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL);
    if (!bitrate)
      bitrate = vd->vi.bitrate_lower;
  }
  if (bitrate) {
699
    gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
700
701
702
        GST_TAG_BITRATE, (guint) bitrate, NULL);
  }

703
704
705
706
  if (vd->initialized) {
    gst_element_found_tags_for_pad (GST_ELEMENT_CAST (vd), vd->srcpad,
        vd->taglist);
    vd->taglist = NULL;
707
708
709
710
711
  } else {
    /* Only post them as messages for the time being. *
     * They will be pushed on the pad once the decoder is initialized */
    gst_element_post_message (GST_ELEMENT_CAST (vd),
        gst_message_new_tag (GST_OBJECT (vd), gst_tag_list_copy (vd->taglist)));
712
  }
713
714
715
716
717
718
719

  return GST_FLOW_OK;
}

static GstFlowReturn
vorbis_handle_type_packet (GstVorbisDec * vd)
{
720
721
  GList *walk;

722
723
  g_assert (vd->initialized == FALSE);

724
725
726
727
  vorbis_synthesis_init (&vd->vd, &vd->vi);
  vorbis_block_init (&vd->vd, &vd->vb);
  vd->initialized = TRUE;

728
729
730
731
732
733
734
735
  if (vd->pendingevents) {
    for (walk = vd->pendingevents; walk; walk = g_list_next (walk))
      gst_pad_push_event (vd->srcpad, GST_EVENT_CAST (walk->data));
    g_list_free (vd->pendingevents);
    vd->pendingevents = NULL;
  }

  if (vd->taglist) {
736
737
    /* The tags have already been sent on the bus as messages. */
    gst_pad_push_event (vd->srcpad, gst_event_new_tag (vd->taglist));
738
739
740
    vd->taglist = NULL;
  }

741
742
743
  return GST_FLOW_OK;
}

744
745
746
747
748
static GstFlowReturn
vorbis_handle_header_packet (GstVorbisDec * vd, ogg_packet * packet)
{
  GstFlowReturn res;

749
  GST_DEBUG_OBJECT (vd, "parsing header packet");
750
751
752
753
754
755
756

  /* Packetno = 0 if the first byte is exactly 0x01 */
  packet->b_o_s = (packet->packet[0] == 0x1) ? 1 : 0;

  if (vorbis_synthesis_headerin (&vd->vi, &vd->vc, packet))
    goto header_read_error;

757
758
  switch (packet->packet[0]) {
    case 0x01:
759
760
      res = vorbis_handle_identification_packet (vd);
      break;
761
    case 0x03:
762
763
      res = vorbis_handle_comment_packet (vd, packet);
      break;
764
    case 0x05:
765
      res = vorbis_handle_type_packet (vd);
766
767
768
      break;
    default:
      /* ignore */
769
      g_warning ("unknown vorbis header packet found");
770
771
772
773
774
775
776
777
778
779
780
781
782
783
      res = GST_FLOW_OK;
      break;
  }
  return res;

  /* ERRORS */
header_read_error:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
        (NULL), ("couldn't read header packet"));
    return GST_FLOW_ERROR;
  }
}

784
785
/* These samples can be outside of the float -1.0 -- 1.0 range, this
 * is allowed, downstream elements are supposed to clip */
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
static void
copy_samples (float *out, float **in, guint samples, gint channels)
{
  gint i, j;

#ifdef GST_VORBIS_DEC_SEQUENTIAL
  for (i = 0; i < channels; i++) {
    memcpy (out, in[i], samples * sizeof (float));
    out += samples;
  }
#else
  for (j = 0; j < samples; j++) {
    for (i = 0; i < channels; i++) {
      *out++ = in[i][j];
    }
  }
#endif
}

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
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
/* clip output samples to the segment boundaries
 */
static gboolean
vorbis_do_clip (GstVorbisDec * dec, GstBuffer * buf)
{
  gint64 start, stop, cstart, cstop, diff;

  start = GST_BUFFER_TIMESTAMP (buf);
  stop = start + GST_BUFFER_DURATION (buf);

  if (!gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
          start, stop, &cstart, &cstop))
    goto clipped;

  /* see if some clipping happened */
  diff = cstart - start;
  if (diff > 0) {
    GST_BUFFER_TIMESTAMP (buf) = cstart;
    GST_BUFFER_DURATION (buf) -= diff;

    /* bring clipped time to samples */
    diff = gst_util_uint64_scale_int (diff, dec->vi.rate, GST_SECOND);
    /* samples to bytes */
    diff *= (sizeof (float) * dec->vi.channels);
    GST_DEBUG_OBJECT (dec, "clipping start to %" GST_TIME_FORMAT " %"
        G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
    GST_BUFFER_DATA (buf) += diff;
    GST_BUFFER_SIZE (buf) -= diff;
  }
  diff = stop - cstop;
  if (diff > 0) {
    GST_BUFFER_DURATION (buf) -= diff;

    /* bring clipped time to samples and then to bytes */
    diff = gst_util_uint64_scale_int (diff, dec->vi.rate, GST_SECOND);
    diff *= (sizeof (float) * dec->vi.channels);
    GST_DEBUG_OBJECT (dec, "clipping stop to %" GST_TIME_FORMAT " %"
        G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstop), diff);
    GST_BUFFER_SIZE (buf) -= diff;
  }

  return FALSE;

  /* dropped buffer */
clipped:
  {
    GST_DEBUG_OBJECT (dec, "clipped buffer");
    gst_buffer_unref (buf);
    return TRUE;
  }
}

Wim Taymans's avatar
Wim Taymans committed
857
static GstFlowReturn
858
vorbis_dec_push_forward (GstVorbisDec * dec, GstBuffer * buf)
Wim Taymans's avatar
Wim Taymans committed
859
860
861
862
863
864
865
866
867
{
  GstFlowReturn result;
  gint64 outoffset = GST_BUFFER_OFFSET (buf);

  if (outoffset == -1) {
    dec->queued = g_list_append (dec->queued, buf);
    GST_DEBUG_OBJECT (dec, "queued buffer");
    result = GST_FLOW_OK;
  } else {
868
    if (G_UNLIKELY (dec->queued)) {
Wim Taymans's avatar
Wim Taymans committed
869
      gint64 size;
870
      GstClockTime ts;
Wim Taymans's avatar
Wim Taymans committed
871
872
873
      GList *walk;

      GST_DEBUG_OBJECT (dec, "first buffer with offset %lld", outoffset);
874
      ts = gst_util_uint64_scale_int (outoffset, GST_SECOND, dec->vi.rate);
Wim Taymans's avatar
Wim Taymans committed
875
876

      size = g_list_length (dec->queued);
877
878
      /* we walk the queued up list in reverse, and set the buffer fields
       * calculating backwards */
Wim Taymans's avatar
Wim Taymans committed
879
880
881
882
883
884
885
886
      for (walk = g_list_last (dec->queued); walk;
          walk = g_list_previous (walk)) {
        GstBuffer *buffer = GST_BUFFER (walk->data);

        outoffset -=
            GST_BUFFER_SIZE (buffer) / (sizeof (float) * dec->vi.channels);

        GST_BUFFER_OFFSET (buffer) = outoffset;
887
        GST_BUFFER_TIMESTAMP (buffer) =
888
            gst_util_uint64_scale_int (outoffset, GST_SECOND, dec->vi.rate);
889
890
891
        GST_BUFFER_DURATION (buffer) = GST_CLOCK_DIFF (GST_BUFFER_TIMESTAMP
            (buffer), ts);
        ts = GST_BUFFER_TIMESTAMP (buffer);
892
        GST_DEBUG_OBJECT (dec, "patch buffer %" G_GUINT64_FORMAT
893
894
895
896
            ", offset %" G_GUINT64_FORMAT ", timestamp %" GST_TIME_FORMAT
            ", duration %" GST_TIME_FORMAT, size, outoffset,
            GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
            GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
Wim Taymans's avatar
Wim Taymans committed
897
898
899
900
901
        size--;
      }
      for (walk = dec->queued; walk; walk = g_list_next (walk)) {
        GstBuffer *buffer = GST_BUFFER (walk->data);

902
903
904
905
906
        /* clips or returns FALSE with buffer unreffed when completely
         * clipped */
        if (vorbis_do_clip (dec, buffer))
          continue;

907
908
909
910
        if (dec->discont) {
          GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
          dec->discont = FALSE;
        }
911
        /* ignore the result */
Wim Taymans's avatar
Wim Taymans committed
912
913
914
915
916
        gst_pad_push (dec->srcpad, buffer);
      }
      g_list_free (dec->queued);
      dec->queued = NULL;
    }
917
918
919
920
921

    /* clip */
    if (vorbis_do_clip (dec, buf))
      return GST_FLOW_OK;

922
923
924
925
    if (dec->discont) {
      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
      dec->discont = FALSE;
    }
926

Wim Taymans's avatar
Wim Taymans committed
927
928
929
930
931
932
    result = gst_pad_push (dec->srcpad, buf);
  }

  return result;
}

933
934
935
936
937
938
939
940
941
942
static GstFlowReturn
vorbis_dec_push_reverse (GstVorbisDec * dec, GstBuffer * buf)
{
  GstFlowReturn result = GST_FLOW_OK;

  dec->queued = g_list_prepend (dec->queued, buf);

  return result;
}

943
944
945
946
947
static GstFlowReturn
vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet)
{
  float **pcm;
  guint sample_count;
948
  GstBuffer *out;
949
  GstFlowReturn result;
950
  GstClockTime timestamp = -1, nextts;
951
  gint size;
952
953
954
955

  if (!vd->initialized)
    goto not_initialized;

956
957
958
959
960
961
962
963
  /* FIXME, we should queue undecoded packets here until we get
   * a timestamp, then we reverse timestamp the queued packets and
   * clip them, then we decode only the ones we want and don't
   * keep decoded data in memory.
   * Ideally, of course, the demuxer gives us a valid timestamp on
   * the first packet.
   */

964
  /* normal data packet */
965
966
967
968
969
  /* FIXME, we can skip decoding if the packet is outside of the
   * segment, this is however not very trivial as we need a previous
   * packet to decode the current one so we must be carefull not to
   * throw away too much. For now we decode everything and clip right
   * before pushing data. */
970
  if (G_UNLIKELY (vorbis_synthesis (&vd->vb, packet)))
971
972
    goto could_not_read;

973
  if (G_UNLIKELY (vorbis_synthesis_blockin (&vd->vd, &vd->vb) < 0))
974
975
    goto not_accepted;

976
977
  /* assume all goes well here */
  result = GST_FLOW_OK;
978

979
980
981
  /* count samples ready for reading */
  if ((sample_count = vorbis_synthesis_pcmout (&vd->vd, NULL)) == 0)
    goto done;
982

983
  GST_LOG_OBJECT (vd, "%d samples ready for reading", sample_count);
984
985
  size = sample_count * vd->vi.channels * sizeof (float);

986
  /* alloc buffer for it */
Andy Wingo's avatar
Andy Wingo committed
987
988
  result =
      gst_pad_alloc_buffer_and_set_caps (vd->srcpad, GST_BUFFER_OFFSET_NONE,
989
      size, GST_PAD_CAPS (vd->srcpad), &out);
990
  if (G_UNLIKELY (result != GST_FLOW_OK))
991
    goto done;
992

993
  /* get samples ready for reading now, should be sample_count */
994
  if (G_UNLIKELY ((vorbis_synthesis_pcmout (&vd->vd, &pcm)) != sample_count))
995
    goto wrong_samples;
996

997
998
999
  /* copy samples in buffer */
  copy_samples ((float *) GST_BUFFER_DATA (out), pcm, sample_count,
      vd->vi.channels);
1000

1001
  GST_BUFFER_SIZE (out) = size;
1002

Wim Taymans's avatar
Wim Taymans committed
1003
  /* this should not overflow */
1004
1005
  GST_BUFFER_DURATION (out) = sample_count * GST_SECOND / vd->vi.rate;

1006
1007
1008
  if (packet->granulepos != -1)
    vd->granulepos = packet->granulepos - sample_count;

1009
  if (vd->cur_timestamp != GST_CLOCK_TIME_NONE) {
1010
    /* we have incoming timestamps */
1011
    timestamp = vd->cur_timestamp;
1012
    GST_DEBUG_OBJECT (vd,
Tim-Philipp Müller's avatar
Tim-Philipp Müller committed
1013
        "cur_timestamp: %" GST_TIME_FORMAT " + %" GST_TIME_FORMAT " = %"
1014
1015
1016
1017
1018
1019
1020
        GST_TIME_FORMAT, GST_TIME_ARGS (vd->cur_timestamp),
        GST_TIME_ARGS (GST_BUFFER_DURATION (out)),
        GST_TIME_ARGS (vd->cur_timestamp + GST_BUFFER_DURATION (out)));
    vd->cur_timestamp += GST_BUFFER_DURATION (out);
    GST_BUFFER_OFFSET (out) = GST_CLOCK_TIME_TO_FRAMES (vd->cur_timestamp,
        vd->vi.rate);
    GST_BUFFER_OFFSET_END (out) = GST_BUFFER_OFFSET (out) + sample_count;
1021
  } else {
1022
    /* we have incoming granulepos */
1023
1024
    GST_BUFFER_OFFSET (out) = vd->granulepos;
    if (vd->granulepos != -1) {
1025
      GST_DEBUG_OBJECT (vd, "granulepos: %" G_GINT64_FORMAT, vd->granulepos);
1026
      GST_BUFFER_OFFSET_END (out) = vd->granulepos + sample_count;
1027
      timestamp =
1028
          gst_util_uint64_scale_int (vd->granulepos, GST_SECOND, vd->vi.rate);
1029
1030
1031
      nextts =
          gst_util_uint64_scale_int (vd->granulepos + sample_count,
          GST_SECOND, vd->vi.rate);
1032
1033
1034
      GST_DEBUG_OBJECT (vd, "corresponding timestamp %" GST_TIME_FORMAT,
          GST_TIME_ARGS (timestamp));
      /* calculate a nano-second accurate duration */
1035
      GST_BUFFER_DURATION (out) = GST_CLOCK_DIFF (timestamp, nextts);
1036
1037
      GST_DEBUG_OBJECT (vd, "set duration %" GST_TIME_FORMAT,
          GST_TIME_ARGS (GST_BUFFER_DURATION (out)));
1038
    } else {
1039
      timestamp = -1;
1040
    }
1041
  }
1042
  GST_BUFFER_TIMESTAMP (out) = timestamp;
1043

1044
1045
  if (vd->granulepos != -1)
    vd->granulepos += sample_count;
1046

1047
1048
1049
1050
  if (vd->segment.rate >= 0.0)
    result = vorbis_dec_push_forward (vd, out);
  else
    result = vorbis_dec_push_reverse (vd, out);
1051
1052

done:
1053
1054
  vorbis_synthesis_read (&vd->vd, sample_count);

1055
  GST_DEBUG_OBJECT (vd,
1056
      "decoded %ld bytes into %d samples, ts %" GST_TIME_FORMAT, packet->bytes,
1057
1058
      sample_count, GST_TIME_ARGS (timestamp));

Wim Taymans's avatar
Wim Taymans committed
1059
1060
1061
1062
  /* granulepos is the last sample in the packet */
  if (packet->granulepos != -1)
    vd->granulepos = packet->granulepos;

1063
1064
1065
1066
1067
1068
  return result;

  /* ERRORS */
not_initialized:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
1069
        (NULL), ("no header sent yet"));
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
    return GST_FLOW_ERROR;
  }
could_not_read:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
        (NULL), ("couldn't read data packet"));
    return GST_FLOW_ERROR;
  }
not_accepted:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
        (NULL), ("vorbis decoder did not accept data packet"));
    return GST_FLOW_ERROR;
  }
1084
1085
1086
1087
1088
1089
1090
wrong_samples:
  {
    gst_buffer_unref (out);
    GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
        (NULL), ("vorbis decoder reported wrong number of samples"));
    return GST_FLOW_ERROR;
  }
1091
1092
}

1093
static GstFlowReturn
1094
vorbis_dec_decode_buffer (GstVorbisDec * vd, GstBuffer * buffer)
1095
{
1096
1097
  ogg_packet packet;
  GstFlowReturn result = GST_FLOW_OK;
1098
1099
  GstClockTime timestamp;
  guint64 offset_end;
1100

1101
1102
1103
  timestamp = GST_BUFFER_TIMESTAMP (buffer);
  offset_end = GST_BUFFER_OFFSET_END (buffer);

1104
1105
  /* only ogg has granulepos, demuxers of other container formats 
   * might provide us with timestamps instead (e.g. matroskademux) */
1106
  if (offset_end == GST_BUFFER_OFFSET_NONE && timestamp != GST_CLOCK_TIME_NONE) {
1107
    /* we might get multiple consecutive buffers with the same timestamp */
1108
1109
1110
    if (timestamp != vd->prev_timestamp) {
      vd->cur_timestamp = timestamp;
      vd->prev_timestamp = timestamp;
1111
1112
1113
1114
1115
1116
    }
  } else {
    vd->cur_timestamp = GST_CLOCK_TIME_NONE;
    vd->prev_timestamp = GST_CLOCK_TIME_NONE;
  }

1117
  /* make ogg_packet out of the buffer */
1118
1119
  packet.packet = GST_BUFFER_DATA (buffer);
  packet.bytes = GST_BUFFER_SIZE (buffer);
1120
  packet.granulepos = offset_end;
1121
  packet.packetno = 0;          /* we don't care */
1122
  /*
1123
1124
   * FIXME. Is there anyway to know that this is the last packet and
   * set e_o_s??
1125
1126
   * Yes there is, keep one packet at all times and only push out when
   * you receive a new one.  Implement this.
1127
   */
1128
  packet.e_o_s = 0;