vorbisdec: report to 0.11
[platform/upstream/gstreamer.git] / ext / vorbis / gstvorbisdec.c
1 /* GStreamer
2  * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /**
21  * SECTION:element-vorbisdec
22  * @see_also: vorbisenc, oggdemux
23  *
24  * This element decodes a Vorbis stream to raw float audio.
25  * <ulink url="http://www.vorbis.com/">Vorbis</ulink> is a royalty-free
26  * audio codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
27  * Foundation</ulink>.
28  *
29  * <refsect2>
30  * <title>Example pipelines</title>
31  * |[
32  * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink
33  * ]| Decode an Ogg/Vorbis. To create an Ogg/Vorbis file refer to the documentation of vorbisenc.
34  * </refsect2>
35  *
36  * Last reviewed on 2006-03-01 (0.10.4)
37  */
38
39 #ifdef HAVE_CONFIG_H
40 #  include "config.h"
41 #endif
42
43 #include "gstvorbisdec.h"
44 #include <string.h>
45 #include <gst/audio/audio.h>
46 #include <gst/tag/tag.h>
47 #include <gst/audio/multichannel.h>
48
49 #include "gstvorbiscommon.h"
50
51 GST_DEBUG_CATEGORY_EXTERN (vorbisdec_debug);
52 #define GST_CAT_DEFAULT vorbisdec_debug
53
54 static GstStaticPadTemplate vorbis_dec_src_factory =
55 GST_STATIC_PAD_TEMPLATE ("src",
56     GST_PAD_SRC,
57     GST_PAD_ALWAYS,
58     GST_VORBIS_DEC_SRC_CAPS);
59
60 static GstStaticPadTemplate vorbis_dec_sink_factory =
61 GST_STATIC_PAD_TEMPLATE ("sink",
62     GST_PAD_SINK,
63     GST_PAD_ALWAYS,
64     GST_STATIC_CAPS ("audio/x-vorbis")
65     );
66
67 #define gst_vorbis_dec_parent_class parent_class
68 G_DEFINE_TYPE (GstVorbisDec, gst_vorbis_dec, GST_TYPE_AUDIO_DECODER);
69
70 static void vorbis_dec_finalize (GObject * object);
71
72 static gboolean vorbis_dec_start (GstAudioDecoder * dec);
73 static gboolean vorbis_dec_stop (GstAudioDecoder * dec);
74 static GstFlowReturn vorbis_dec_handle_frame (GstAudioDecoder * dec,
75     GstBuffer * buffer);
76 static void vorbis_dec_flush (GstAudioDecoder * dec, gboolean hard);
77
78 static void
79 gst_vorbis_dec_class_init (GstVorbisDecClass * klass)
80 {
81   GstPadTemplate *src_template, *sink_template;
82   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
83   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
84   GstAudioDecoderClass *base_class = GST_AUDIO_DECODER_CLASS (klass);
85
86   gobject_class->finalize = vorbis_dec_finalize;
87
88   src_template = gst_static_pad_template_get (&vorbis_dec_src_factory);
89   gst_element_class_add_pad_template (element_class, src_template);
90
91   sink_template = gst_static_pad_template_get (&vorbis_dec_sink_factory);
92   gst_element_class_add_pad_template (element_class, sink_template);
93
94   gst_element_class_set_details_simple (element_class,
95       "Vorbis audio decoder", "Codec/Decoder/Audio",
96       GST_VORBIS_DEC_DESCRIPTION,
97       "Benjamin Otte <otte@gnome.org>, Chris Lord <chris@openedhand.com>");
98
99   base_class->start = GST_DEBUG_FUNCPTR (vorbis_dec_start);
100   base_class->stop = GST_DEBUG_FUNCPTR (vorbis_dec_stop);
101   base_class->handle_frame = GST_DEBUG_FUNCPTR (vorbis_dec_handle_frame);
102   base_class->flush = GST_DEBUG_FUNCPTR (vorbis_dec_flush);
103 }
104
105 static void
106 gst_vorbis_dec_init (GstVorbisDec * dec)
107 {
108 }
109
110 static void
111 vorbis_dec_finalize (GObject * object)
112 {
113   /* Release any possibly allocated libvorbis data.
114    * _clear functions can safely be called multiple times
115    */
116   GstVorbisDec *vd = GST_VORBIS_DEC (object);
117
118 #ifndef USE_TREMOLO
119   vorbis_block_clear (&vd->vb);
120 #endif
121   vorbis_dsp_clear (&vd->vd);
122   vorbis_comment_clear (&vd->vc);
123   vorbis_info_clear (&vd->vi);
124
125   G_OBJECT_CLASS (parent_class)->finalize (object);
126 }
127
128 static void
129 gst_vorbis_dec_reset (GstVorbisDec * dec)
130 {
131   if (dec->taglist)
132     gst_tag_list_free (dec->taglist);
133   dec->taglist = NULL;
134 }
135
136 static gboolean
137 vorbis_dec_start (GstAudioDecoder * dec)
138 {
139   GstVorbisDec *vd = GST_VORBIS_DEC (dec);
140
141   GST_DEBUG_OBJECT (dec, "start");
142   vorbis_info_init (&vd->vi);
143   vorbis_comment_init (&vd->vc);
144   vd->initialized = FALSE;
145   gst_vorbis_dec_reset (vd);
146
147   return TRUE;
148 }
149
150 static gboolean
151 vorbis_dec_stop (GstAudioDecoder * dec)
152 {
153   GstVorbisDec *vd = GST_VORBIS_DEC (dec);
154
155   GST_DEBUG_OBJECT (dec, "stop");
156   vd->initialized = FALSE;
157 #ifndef USE_TREMOLO
158   vorbis_block_clear (&vd->vb);
159 #endif
160   vorbis_dsp_clear (&vd->vd);
161   vorbis_comment_clear (&vd->vc);
162   vorbis_info_clear (&vd->vi);
163   gst_vorbis_dec_reset (vd);
164
165   return TRUE;
166 }
167
168 #if 0
169 static gboolean
170 vorbis_dec_src_event (GstPad * pad, GstEvent * event)
171 {
172   gboolean res = TRUE;
173   GstVorbisDec *dec;
174
175   dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
176
177   switch (GST_EVENT_TYPE (event)) {
178     case GST_EVENT_SEEK:
179     {
180       GstFormat format, tformat;
181       gdouble rate;
182       GstEvent *real_seek;
183       GstSeekFlags flags;
184       GstSeekType cur_type, stop_type;
185       gint64 cur, stop;
186       gint64 tcur, tstop;
187       guint32 seqnum;
188
189       gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
190           &stop_type, &stop);
191       seqnum = gst_event_get_seqnum (event);
192       gst_event_unref (event);
193
194       /* First bring the requested format to time */
195       tformat = GST_FORMAT_TIME;
196       if (!(res = vorbis_dec_convert (pad, format, cur, &tformat, &tcur)))
197         goto convert_error;
198       if (!(res = vorbis_dec_convert (pad, format, stop, &tformat, &tstop)))
199         goto convert_error;
200
201       /* then seek with time on the peer */
202       real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
203           flags, cur_type, tcur, stop_type, tstop);
204       gst_event_set_seqnum (real_seek, seqnum);
205
206       res = gst_pad_push_event (dec->sinkpad, real_seek);
207       break;
208     }
209     default:
210       res = gst_pad_push_event (dec->sinkpad, event);
211       break;
212   }
213 done:
214   gst_object_unref (dec);
215
216   return res;
217
218   /* ERRORS */
219 convert_error:
220   {
221     GST_DEBUG_OBJECT (dec, "cannot convert start/stop for seek");
222     goto done;
223   }
224 }
225 #endif
226
227 static GstFlowReturn
228 vorbis_handle_identification_packet (GstVorbisDec * vd)
229 {
230   GstCaps *caps;
231   GstAudioInfo info;
232
233   gst_audio_info_set_format (&info, GST_VORBIS_AUDIO_FORMAT, vd->vi.rate,
234       vd->vi.channels);
235
236   switch (info.channels) {
237     case 1:
238     case 2:
239       /* nothing */
240       break;
241     case 3:
242     case 4:
243     case 5:
244     case 6:
245     case 7:
246     case 8:
247     {
248       const GstAudioChannelPosition *pos;
249       gint i;
250
251       pos = gst_vorbis_channel_positions[info.channels - 1];
252       for (i = 0; i < info.channels; i++)
253         info.position[i] = pos[i];
254       break;
255     }
256     default:{
257       gint i, max_pos = MAX (info.channels, 64);
258
259       GST_ELEMENT_WARNING (vd, STREAM, DECODE,
260           (NULL), ("Using NONE channel layout for more than 8 channels"));
261       for (i = 0; i < max_pos; i++)
262         info.position[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
263       break;
264     }
265   }
266
267   caps = gst_audio_info_to_caps (&info);
268   gst_audio_decoder_set_outcaps (GST_AUDIO_DECODER (vd), caps);
269   gst_caps_unref (caps);
270
271   vd->info = info;
272   /* select a copy_samples function, this way we can have specialized versions
273    * for mono/stereo and avoid the depth switch in tremor case */
274   vd->copy_samples = get_copy_sample_func (info.channels);
275
276   return GST_FLOW_OK;
277 }
278
279 static GstFlowReturn
280 vorbis_handle_comment_packet (GstVorbisDec * vd, ogg_packet * packet)
281 {
282   guint bitrate = 0;
283   gchar *encoder = NULL;
284   GstTagList *list, *old_list;
285   guint8 *data;
286   gsize size;
287
288   GST_DEBUG_OBJECT (vd, "parsing comment packet");
289
290   data = gst_ogg_packet_data (packet);
291   size = gst_ogg_packet_size (packet);
292
293   list =
294       gst_tag_list_from_vorbiscomment (data, size, (guint8 *) "\003vorbis", 7,
295       &encoder);
296
297   old_list = vd->taglist;
298   vd->taglist = gst_tag_list_merge (vd->taglist, list, GST_TAG_MERGE_REPLACE);
299
300   if (old_list)
301     gst_tag_list_free (old_list);
302   gst_tag_list_free (list);
303
304   if (!vd->taglist) {
305     GST_ERROR_OBJECT (vd, "couldn't decode comments");
306     vd->taglist = gst_tag_list_new ();
307   }
308   if (encoder) {
309     if (encoder[0])
310       gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
311           GST_TAG_ENCODER, encoder, NULL);
312     g_free (encoder);
313   }
314   gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
315       GST_TAG_ENCODER_VERSION, vd->vi.version,
316       GST_TAG_AUDIO_CODEC, "Vorbis", NULL);
317   if (vd->vi.bitrate_nominal > 0 && vd->vi.bitrate_nominal <= 0x7FFFFFFF) {
318     gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
319         GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL);
320     bitrate = vd->vi.bitrate_nominal;
321   }
322   if (vd->vi.bitrate_upper > 0 && vd->vi.bitrate_upper <= 0x7FFFFFFF) {
323     gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
324         GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL);
325     if (!bitrate)
326       bitrate = vd->vi.bitrate_upper;
327   }
328   if (vd->vi.bitrate_lower > 0 && vd->vi.bitrate_lower <= 0x7FFFFFFF) {
329     gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
330         GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL);
331     if (!bitrate)
332       bitrate = vd->vi.bitrate_lower;
333   }
334   if (bitrate) {
335     gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
336         GST_TAG_BITRATE, (guint) bitrate, NULL);
337   }
338
339   if (vd->initialized) {
340     gst_element_found_tags_for_pad (GST_ELEMENT_CAST (vd),
341         GST_AUDIO_DECODER_SRC_PAD (vd), vd->taglist);
342     vd->taglist = NULL;
343   } else {
344     /* Only post them as messages for the time being. *
345      * They will be pushed on the pad once the decoder is initialized */
346     gst_element_post_message (GST_ELEMENT_CAST (vd),
347         gst_message_new_tag (GST_OBJECT (vd), gst_tag_list_copy (vd->taglist)));
348   }
349
350   return GST_FLOW_OK;
351 }
352
353 static GstFlowReturn
354 vorbis_handle_type_packet (GstVorbisDec * vd)
355 {
356   gint res;
357
358   g_assert (vd->initialized == FALSE);
359
360 #ifdef USE_TREMOLO
361   if (G_UNLIKELY ((res = vorbis_dsp_init (&vd->vd, &vd->vi))))
362     goto synthesis_init_error;
363 #else
364   if (G_UNLIKELY ((res = vorbis_synthesis_init (&vd->vd, &vd->vi))))
365     goto synthesis_init_error;
366
367   if (G_UNLIKELY ((res = vorbis_block_init (&vd->vd, &vd->vb))))
368     goto block_init_error;
369 #endif
370
371   vd->initialized = TRUE;
372
373   if (vd->taglist) {
374     /* The tags have already been sent on the bus as messages. */
375     gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (vd),
376         gst_event_new_tag (vd->taglist));
377     vd->taglist = NULL;
378   }
379   return GST_FLOW_OK;
380
381   /* ERRORS */
382 synthesis_init_error:
383   {
384     GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
385         (NULL), ("couldn't initialize synthesis (%d)", res));
386     return GST_FLOW_ERROR;
387   }
388 block_init_error:
389   {
390     GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
391         (NULL), ("couldn't initialize block (%d)", res));
392     return GST_FLOW_ERROR;
393   }
394 }
395
396 static GstFlowReturn
397 vorbis_handle_header_packet (GstVorbisDec * vd, ogg_packet * packet)
398 {
399   GstFlowReturn res;
400   gint ret;
401
402   GST_DEBUG_OBJECT (vd, "parsing header packet");
403
404   /* Packetno = 0 if the first byte is exactly 0x01 */
405   packet->b_o_s = ((gst_ogg_packet_data (packet))[0] == 0x1) ? 1 : 0;
406
407 #ifdef USE_TREMELO
408   if ((ret = vorbis_dsp_headerin (&vd->vi, &vd->vc, packet)))
409 #else
410   if ((ret = vorbis_synthesis_headerin (&vd->vi, &vd->vc, packet)))
411 #endif
412     goto header_read_error;
413
414   switch ((gst_ogg_packet_data (packet))[0]) {
415     case 0x01:
416       res = vorbis_handle_identification_packet (vd);
417       break;
418     case 0x03:
419       res = vorbis_handle_comment_packet (vd, packet);
420       break;
421     case 0x05:
422       res = vorbis_handle_type_packet (vd);
423       break;
424     default:
425       /* ignore */
426       g_warning ("unknown vorbis header packet found");
427       res = GST_FLOW_OK;
428       break;
429   }
430
431   /* consumer header packet/frame */
432   gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (vd), NULL, 1);
433
434   return res;
435
436   /* ERRORS */
437 header_read_error:
438   {
439     GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
440         (NULL), ("couldn't read header packet (%d)", ret));
441     return GST_FLOW_ERROR;
442   }
443 }
444
445 static GstFlowReturn
446 vorbis_dec_handle_header_buffer (GstVorbisDec * vd, GstBuffer * buffer)
447 {
448   ogg_packet *packet;
449   ogg_packet_wrapper packet_wrapper;
450   GstFlowReturn ret;
451
452   gst_ogg_packet_wrapper_map (&packet_wrapper, buffer);
453   packet = gst_ogg_packet_from_wrapper (&packet_wrapper);
454
455   ret = vorbis_handle_header_packet (vd, packet);
456
457   gst_ogg_packet_wrapper_unmap (&packet_wrapper, buffer);
458
459   return ret;
460 }
461
462 #define MIN_NUM_HEADERS 3
463 static GstFlowReturn
464 vorbis_dec_handle_header_caps (GstVorbisDec * vd)
465 {
466   GstFlowReturn result = GST_FLOW_OK;
467   GstCaps *caps;
468   GstStructure *s = NULL;
469   const GValue *array = NULL;
470
471   caps = gst_pad_get_current_caps (GST_AUDIO_DECODER_SINK_PAD (vd));
472   if (caps)
473     s = gst_caps_get_structure (caps, 0);
474   if (s)
475     array = gst_structure_get_value (s, "streamheader");
476
477   if (caps)
478     gst_caps_unref (caps);
479
480   if (array && (gst_value_array_get_size (array) >= MIN_NUM_HEADERS)) {
481     const GValue *value = NULL;
482     GstBuffer *buf = NULL;
483     gint i = 0;
484
485     while (result == GST_FLOW_OK) {
486       value = gst_value_array_get_value (array, i);
487       buf = gst_value_get_buffer (value);
488       if (!buf)
489         goto null_buffer;
490       result = vorbis_dec_handle_header_buffer (vd, buf);
491       i++;
492     }
493   } else
494     goto array_error;
495
496 done:
497   return (result != GST_FLOW_OK ? GST_FLOW_NOT_NEGOTIATED : GST_FLOW_OK);
498
499   /* ERRORS */
500 array_error:
501   {
502     GST_WARNING_OBJECT (vd, "streamheader array not found");
503     result = GST_FLOW_ERROR;
504     goto done;
505   }
506 null_buffer:
507   {
508     GST_WARNING_OBJECT (vd, "streamheader with null buffer received");
509     result = GST_FLOW_ERROR;
510     goto done;
511   }
512 }
513
514
515 static GstFlowReturn
516 vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet,
517     GstClockTime timestamp, GstClockTime duration)
518 {
519 #ifdef USE_TREMELO
520   vorbis_sample_t *pcm;
521 #else
522   vorbis_sample_t **pcm;
523 #endif
524   guint sample_count;
525   GstBuffer *out = NULL;
526   GstFlowReturn result;
527   guint8 *data;
528   gsize size;
529
530   if (G_UNLIKELY (!vd->initialized)) {
531     result = vorbis_dec_handle_header_caps (vd);
532     if (result != GST_FLOW_OK)
533       goto not_initialized;
534   }
535
536   /* normal data packet */
537   /* FIXME, we can skip decoding if the packet is outside of the
538    * segment, this is however not very trivial as we need a previous
539    * packet to decode the current one so we must be carefull not to
540    * throw away too much. For now we decode everything and clip right
541    * before pushing data. */
542
543 #ifdef USE_TREMELO
544   if (G_UNLIKELY (vorbis_dsp_synthesis (&vd->vb, packet, 1)))
545     goto could_not_read;
546 #else
547   if (G_UNLIKELY (vorbis_synthesis (&vd->vb, packet)))
548     goto could_not_read;
549
550   if (G_UNLIKELY (vorbis_synthesis_blockin (&vd->vd, &vd->vb) < 0))
551     goto not_accepted;
552 #endif
553
554   /* assume all goes well here */
555   result = GST_FLOW_OK;
556
557   /* count samples ready for reading */
558 #ifdef USE_TREMOLO
559   if ((sample_count = vorbis_dsp_pcmout (&vd->vd, NULL, 0)) == 0)
560 #else
561   if ((sample_count = vorbis_synthesis_pcmout (&vd->vd, NULL)) == 0)
562     goto done;
563 #endif
564
565   size = sample_count * vd->info.bpf;
566   GST_LOG_OBJECT (vd, "%d samples ready for reading, size %d", sample_count,
567       size);
568
569   /* alloc buffer for it */
570   out = gst_buffer_new_allocate (NULL, size, 0);
571
572   data = gst_buffer_map (out, NULL, NULL, GST_MAP_WRITE);
573   /* get samples ready for reading now, should be sample_count */
574 #ifdef USE_TREMOLO
575   if (G_UNLIKELY (vorbis_dsp_pcmout (&vd->vd, data, sample_count) !=
576           sample_count))
577 #else
578   if (G_UNLIKELY (vorbis_synthesis_pcmout (&vd->vd, &pcm) != sample_count))
579 #endif
580     goto wrong_samples;
581
582 #ifndef USE_TREMOLO
583   /* copy samples in buffer */
584   vd->copy_samples ((vorbis_sample_t *) data, pcm,
585       sample_count, vd->info.channels);
586 #endif
587
588   GST_LOG_OBJECT (vd, "setting output size to %d", size);
589   gst_buffer_unmap (out, data, size);
590
591 done:
592   /* whether or not data produced, consume one frame and advance time */
593   result = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (vd), out, 1);
594
595 #ifdef USE_TREMOLO
596   vorbis_dsp_read (&vd->vd, sample_count);
597 #else
598   vorbis_synthesis_read (&vd->vd, sample_count);
599 #endif
600
601   return result;
602
603   /* ERRORS */
604 not_initialized:
605   {
606     GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
607         (NULL), ("no header sent yet"));
608     return GST_FLOW_NOT_NEGOTIATED;
609   }
610 could_not_read:
611   {
612     GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
613         (NULL), ("couldn't read data packet"));
614     return GST_FLOW_ERROR;
615   }
616 not_accepted:
617   {
618     GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
619         (NULL), ("vorbis decoder did not accept data packet"));
620     return GST_FLOW_ERROR;
621   }
622 wrong_samples:
623   {
624     gst_buffer_unref (out);
625     GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
626         (NULL), ("vorbis decoder reported wrong number of samples"));
627     return GST_FLOW_ERROR;
628   }
629 }
630
631 static GstFlowReturn
632 vorbis_dec_handle_frame (GstAudioDecoder * dec, GstBuffer * buffer)
633 {
634   ogg_packet *packet;
635   ogg_packet_wrapper packet_wrapper;
636   GstFlowReturn result = GST_FLOW_OK;
637   GstVorbisDec *vd = GST_VORBIS_DEC (dec);
638
639   /* no draining etc */
640   if (G_UNLIKELY (!buffer))
641     return GST_FLOW_OK;
642
643   GST_LOG_OBJECT (vd, "got buffer %p", buffer);
644   /* make ogg_packet out of the buffer */
645   gst_ogg_packet_wrapper_map (&packet_wrapper, buffer);
646   packet = gst_ogg_packet_from_wrapper (&packet_wrapper);
647   /* set some more stuff */
648   packet->granulepos = -1;
649   packet->packetno = 0;         /* we don't care */
650   /* EOS does not matter, it is used in vorbis to implement clipping the last
651    * block of samples based on the granulepos. We clip based on segments. */
652   packet->e_o_s = 0;
653
654   GST_LOG_OBJECT (vd, "decode buffer of size %ld", packet->bytes);
655
656   /* error out on empty header packets, but just skip empty data packets */
657   if (G_UNLIKELY (packet->bytes == 0)) {
658     if (vd->initialized)
659       goto empty_buffer;
660     else
661       goto empty_header;
662   }
663
664   /* switch depending on packet type */
665   if ((gst_ogg_packet_data (packet))[0] & 1) {
666     if (vd->initialized) {
667       GST_WARNING_OBJECT (vd, "Already initialized, so ignoring header packet");
668       goto done;
669     }
670     result = vorbis_handle_header_packet (vd, packet);
671   } else {
672     GstClockTime timestamp, duration;
673
674     timestamp = GST_BUFFER_TIMESTAMP (buffer);
675     duration = GST_BUFFER_DURATION (buffer);
676
677     result = vorbis_handle_data_packet (vd, packet, timestamp, duration);
678   }
679
680 done:
681   GST_LOG_OBJECT (vd, "unmap buffer %p", buffer);
682   gst_ogg_packet_wrapper_unmap (&packet_wrapper, buffer);
683
684   return result;
685
686 empty_buffer:
687   {
688     /* don't error out here, just ignore the buffer, it's invalid for vorbis
689      * but not fatal. */
690     GST_WARNING_OBJECT (vd, "empty buffer received, ignoring");
691     result = GST_FLOW_OK;
692     goto done;
693   }
694
695 /* ERRORS */
696 empty_header:
697   {
698     GST_ELEMENT_ERROR (vd, STREAM, DECODE, (NULL), ("empty header received"));
699     result = GST_FLOW_ERROR;
700     goto done;
701   }
702 }
703
704 static void
705 vorbis_dec_flush (GstAudioDecoder * dec, gboolean hard)
706 {
707   GstVorbisDec *vd = GST_VORBIS_DEC (dec);
708
709 #ifdef HAVE_VORBIS_SYNTHESIS_RESTART
710   vorbis_synthesis_restart (&vd->vd);
711 #endif
712
713   if (hard)
714     gst_vorbis_dec_reset (vd);
715 }