456cc624bec65730b6fb25de4639b3a3c5291e8e
[platform/upstream/gstreamer.git] / ext / opus / gstopusdec.c
1 /* GStreamer
2  * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
3  * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
4  * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
5  * Copyright (C) 2011-2012 Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 /*
24  * Based on the speexdec element.
25  */
26
27 /**
28  * SECTION:element-opusdec
29  * @see_also: opusenc, oggdemux
30  *
31  * This element decodes a OPUS stream to raw integer audio.
32  *
33  * <refsect2>
34  * <title>Example pipelines</title>
35  * |[
36  * gst-launch -v filesrc location=opus.ogg ! oggdemux ! opusdec ! audioconvert ! audioresample ! alsasink
37  * ]| Decode an Ogg/Opus file. To create an Ogg/Opus file refer to the documentation of opusenc.
38  * </refsect2>
39  */
40
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44
45 #include <math.h>
46 #include <string.h>
47 #include "gstopusheader.h"
48 #include "gstopuscommon.h"
49 #include "gstopusdec.h"
50
51 GST_DEBUG_CATEGORY_STATIC (opusdec_debug);
52 #define GST_CAT_DEFAULT opusdec_debug
53
54 static GstStaticPadTemplate opus_dec_src_factory =
55 GST_STATIC_PAD_TEMPLATE ("src",
56     GST_PAD_SRC,
57     GST_PAD_ALWAYS,
58     GST_STATIC_CAPS ("audio/x-raw, "
59         "format = (string) { " GST_AUDIO_NE (S16) " }, "
60         "layout = (string) interleaved, "
61         "rate = (int) { 48000, 24000, 16000, 12000, 8000 }, "
62         "channels = (int) [ 1, 8 ] ")
63     );
64
65 static GstStaticPadTemplate opus_dec_sink_factory =
66 GST_STATIC_PAD_TEMPLATE ("sink",
67     GST_PAD_SINK,
68     GST_PAD_ALWAYS,
69     GST_STATIC_CAPS ("audio/x-opus")
70     );
71
72 G_DEFINE_TYPE (GstOpusDec, gst_opus_dec, GST_TYPE_AUDIO_DECODER);
73
74 #define DB_TO_LINEAR(x) pow (10., (x) / 20.)
75
76 #define DEFAULT_USE_INBAND_FEC FALSE
77 #define DEFAULT_APPLY_GAIN TRUE
78
79 enum
80 {
81   PROP_0,
82   PROP_USE_INBAND_FEC,
83   PROP_APPLY_GAIN
84 };
85
86
87 static GstFlowReturn gst_opus_dec_parse_header (GstOpusDec * dec,
88     GstBuffer * buf);
89 static gboolean gst_opus_dec_start (GstAudioDecoder * dec);
90 static gboolean gst_opus_dec_stop (GstAudioDecoder * dec);
91 static GstFlowReturn gst_opus_dec_handle_frame (GstAudioDecoder * dec,
92     GstBuffer * buffer);
93 static gboolean gst_opus_dec_set_format (GstAudioDecoder * bdec,
94     GstCaps * caps);
95 static void gst_opus_dec_get_property (GObject * object, guint prop_id,
96     GValue * value, GParamSpec * pspec);
97 static void gst_opus_dec_set_property (GObject * object, guint prop_id,
98     const GValue * value, GParamSpec * pspec);
99
100
101 static void
102 gst_opus_dec_class_init (GstOpusDecClass * klass)
103 {
104   GObjectClass *gobject_class;
105   GstAudioDecoderClass *adclass;
106   GstElementClass *element_class;
107
108   gobject_class = (GObjectClass *) klass;
109   adclass = (GstAudioDecoderClass *) klass;
110   element_class = (GstElementClass *) klass;
111
112   gobject_class->set_property = gst_opus_dec_set_property;
113   gobject_class->get_property = gst_opus_dec_get_property;
114
115   adclass->start = GST_DEBUG_FUNCPTR (gst_opus_dec_start);
116   adclass->stop = GST_DEBUG_FUNCPTR (gst_opus_dec_stop);
117   adclass->handle_frame = GST_DEBUG_FUNCPTR (gst_opus_dec_handle_frame);
118   adclass->set_format = GST_DEBUG_FUNCPTR (gst_opus_dec_set_format);
119
120   gst_element_class_add_pad_template (element_class,
121       gst_static_pad_template_get (&opus_dec_src_factory));
122   gst_element_class_add_pad_template (element_class,
123       gst_static_pad_template_get (&opus_dec_sink_factory));
124   gst_element_class_set_static_metadata (element_class, "Opus audio decoder",
125       "Codec/Decoder/Audio",
126       "decode opus streams to audio",
127       "Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>");
128   g_object_class_install_property (gobject_class, PROP_USE_INBAND_FEC,
129       g_param_spec_boolean ("use-inband-fec", "Use in-band FEC",
130           "Use forward error correction if available", DEFAULT_USE_INBAND_FEC,
131           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
132
133   g_object_class_install_property (gobject_class, PROP_APPLY_GAIN,
134       g_param_spec_boolean ("apply-gain", "Apply gain",
135           "Apply gain if any is specified in the header", DEFAULT_APPLY_GAIN,
136           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
137
138   GST_DEBUG_CATEGORY_INIT (opusdec_debug, "opusdec", 0,
139       "opus decoding element");
140 }
141
142 static void
143 gst_opus_dec_reset (GstOpusDec * dec)
144 {
145   dec->packetno = 0;
146   if (dec->state) {
147     opus_multistream_decoder_destroy (dec->state);
148     dec->state = NULL;
149   }
150
151   gst_buffer_replace (&dec->streamheader, NULL);
152   gst_buffer_replace (&dec->vorbiscomment, NULL);
153   gst_buffer_replace (&dec->last_buffer, NULL);
154   dec->primed = FALSE;
155
156   dec->pre_skip = 0;
157   dec->r128_gain = 0;
158   dec->sample_rate = 0;
159   dec->n_channels = 0;
160 }
161
162 static void
163 gst_opus_dec_init (GstOpusDec * dec)
164 {
165   dec->use_inband_fec = FALSE;
166   dec->apply_gain = DEFAULT_APPLY_GAIN;
167
168   gst_opus_dec_reset (dec);
169 }
170
171 static gboolean
172 gst_opus_dec_start (GstAudioDecoder * dec)
173 {
174   GstOpusDec *odec = GST_OPUS_DEC (dec);
175
176   gst_opus_dec_reset (odec);
177
178   /* we know about concealment */
179   gst_audio_decoder_set_plc_aware (dec, TRUE);
180
181   if (odec->use_inband_fec) {
182     gst_audio_decoder_set_latency (dec, 2 * GST_MSECOND + GST_MSECOND / 2,
183         120 * GST_MSECOND);
184   }
185
186   return TRUE;
187 }
188
189 static gboolean
190 gst_opus_dec_stop (GstAudioDecoder * dec)
191 {
192   GstOpusDec *odec = GST_OPUS_DEC (dec);
193
194   gst_opus_dec_reset (odec);
195
196   return TRUE;
197 }
198
199 static double
200 gst_opus_dec_get_r128_gain (gint16 r128_gain)
201 {
202   return r128_gain / (double) (1 << 8);
203 }
204
205 static double
206 gst_opus_dec_get_r128_volume (gint16 r128_gain)
207 {
208   return DB_TO_LINEAR (gst_opus_dec_get_r128_gain (r128_gain));
209 }
210
211 static void
212 gst_opus_dec_negotiate (GstOpusDec * dec, const GstAudioChannelPosition * pos)
213 {
214   GstCaps *caps = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (dec));
215   GstStructure *s;
216   GstAudioInfo info;
217
218   if (caps) {
219     caps = gst_caps_truncate (caps);
220     caps = gst_caps_make_writable (caps);
221     s = gst_caps_get_structure (caps, 0);
222     gst_structure_fixate_field_nearest_int (s, "rate", 48000);
223     gst_structure_get_int (s, "rate", &dec->sample_rate);
224     gst_structure_fixate_field_nearest_int (s, "channels", dec->n_channels);
225     gst_structure_get_int (s, "channels", &dec->n_channels);
226     gst_caps_unref (caps);
227   } else {
228     dec->sample_rate = 48000;
229   }
230
231   GST_INFO_OBJECT (dec, "Negotiated %d channels, %d Hz", dec->n_channels,
232       dec->sample_rate);
233
234   /* pass valid order to audio info */
235   if (pos) {
236     memcpy (dec->opus_pos, pos, sizeof (pos[0]) * dec->n_channels);
237     gst_audio_channel_positions_to_valid_order (dec->opus_pos, dec->n_channels);
238   }
239
240   /* set up source format */
241   gst_audio_info_init (&info);
242   gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16,
243       dec->sample_rate, dec->n_channels, pos ? dec->opus_pos : NULL);
244   gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (dec), &info);
245
246   /* but we still need the opus order for later reordering */
247   if (pos) {
248     memcpy (dec->opus_pos, pos, sizeof (pos[0]) * dec->n_channels);
249     gst_audio_channel_positions_to_valid_order (dec->opus_pos, dec->n_channels);
250   } else {
251     dec->opus_pos[0] = GST_AUDIO_CHANNEL_POSITION_INVALID;
252   }
253
254   dec->info = info;
255 }
256
257 static GstFlowReturn
258 gst_opus_dec_parse_header (GstOpusDec * dec, GstBuffer * buf)
259 {
260   const guint8 *data;
261   GstAudioChannelPosition pos[64];
262   const GstAudioChannelPosition *posn = NULL;
263   GstMapInfo map;
264
265   if (!gst_opus_header_is_id_header (buf)) {
266     GST_ERROR_OBJECT (dec, "Header is not an Opus ID header");
267     return GST_FLOW_ERROR;
268   }
269
270   gst_buffer_map (buf, &map, GST_MAP_READ);
271   data = map.data;
272
273   if (!(dec->n_channels == 0 || dec->n_channels == data[9])) {
274     gst_buffer_unmap (buf, &map);
275     GST_ERROR_OBJECT (dec, "Opus ID header has invalid channels");
276     return GST_FLOW_ERROR;
277   }
278
279   dec->n_channels = data[9];
280   dec->pre_skip = GST_READ_UINT16_LE (data + 10);
281   dec->r128_gain = GST_READ_UINT16_LE (data + 16);
282   dec->r128_gain_volume = gst_opus_dec_get_r128_volume (dec->r128_gain);
283   GST_INFO_OBJECT (dec,
284       "Found pre-skip of %u samples, R128 gain %d (volume %f)",
285       dec->pre_skip, dec->r128_gain, dec->r128_gain_volume);
286
287   dec->channel_mapping_family = data[18];
288   if (dec->channel_mapping_family == 0) {
289     /* implicit mapping */
290     GST_INFO_OBJECT (dec, "Channel mapping family 0, implicit mapping");
291     dec->n_streams = dec->n_stereo_streams = 1;
292     dec->channel_mapping[0] = 0;
293     dec->channel_mapping[1] = 1;
294   } else {
295     dec->n_streams = data[19];
296     dec->n_stereo_streams = data[20];
297     memcpy (dec->channel_mapping, data + 21, dec->n_channels);
298
299     if (dec->channel_mapping_family == 1) {
300       GST_INFO_OBJECT (dec, "Channel mapping family 1, Vorbis mapping");
301       switch (dec->n_channels) {
302         case 1:
303         case 2:
304           /* nothing */
305           break;
306         case 3:
307         case 4:
308         case 5:
309         case 6:
310         case 7:
311         case 8:
312           posn = gst_opus_channel_positions[dec->n_channels - 1];
313           break;
314         default:{
315           gint i;
316
317           GST_ELEMENT_WARNING (GST_ELEMENT (dec), STREAM, DECODE,
318               (NULL), ("Using NONE channel layout for more than 8 channels"));
319
320           for (i = 0; i < dec->n_channels; i++)
321             pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
322
323           posn = pos;
324         }
325       }
326     } else {
327       GST_INFO_OBJECT (dec, "Channel mapping family %d",
328           dec->channel_mapping_family);
329     }
330   }
331
332   gst_opus_dec_negotiate (dec, posn);
333
334   gst_buffer_unmap (buf, &map);
335
336   return GST_FLOW_OK;
337 }
338
339
340 static GstFlowReturn
341 gst_opus_dec_parse_comments (GstOpusDec * dec, GstBuffer * buf)
342 {
343   return GST_FLOW_OK;
344 }
345
346 static GstFlowReturn
347 opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buffer)
348 {
349   GstFlowReturn res = GST_FLOW_OK;
350   gsize size;
351   guint8 *data;
352   GstBuffer *outbuf;
353   gint16 *out_data;
354   int n, err;
355   int samples;
356   unsigned int packet_size;
357   GstBuffer *buf;
358   GstMapInfo map, omap;
359
360   if (dec->state == NULL) {
361     /* If we did not get any headers, default to 2 channels */
362     if (dec->n_channels == 0) {
363       GST_INFO_OBJECT (dec, "No header, assuming single stream");
364       dec->n_channels = 2;
365       dec->sample_rate = 48000;
366       /* default stereo mapping */
367       dec->channel_mapping_family = 0;
368       dec->channel_mapping[0] = 0;
369       dec->channel_mapping[1] = 1;
370       dec->n_streams = 1;
371       dec->n_stereo_streams = 1;
372
373       gst_opus_dec_negotiate (dec, NULL);
374     }
375
376     GST_DEBUG_OBJECT (dec, "Creating decoder with %d channels, %d Hz",
377         dec->n_channels, dec->sample_rate);
378 #ifndef GST_DISABLE_GST_DEBUG
379     gst_opus_common_log_channel_mapping_table (GST_ELEMENT (dec), opusdec_debug,
380         "Mapping table", dec->n_channels, dec->channel_mapping);
381 #endif
382
383     GST_DEBUG_OBJECT (dec, "%d streams, %d stereo", dec->n_streams,
384         dec->n_stereo_streams);
385     dec->state =
386         opus_multistream_decoder_create (dec->sample_rate, dec->n_channels,
387         dec->n_streams, dec->n_stereo_streams, dec->channel_mapping, &err);
388     if (!dec->state || err != OPUS_OK)
389       goto creation_failed;
390   }
391
392   if (buffer) {
393     GST_DEBUG_OBJECT (dec, "Received buffer of size %" G_GSIZE_FORMAT,
394         gst_buffer_get_size (buffer));
395   } else {
396     GST_DEBUG_OBJECT (dec, "Received missing buffer");
397   }
398
399   /* if using in-band FEC, we introdude one extra frame's delay as we need
400      to potentially wait for next buffer to decode a missing buffer */
401   if (dec->use_inband_fec && !dec->primed) {
402     GST_DEBUG_OBJECT (dec, "First buffer received in FEC mode, early out");
403     gst_buffer_replace (&dec->last_buffer, buffer);
404     dec->primed = TRUE;
405     goto done;
406   }
407
408   /* That's the buffer we'll be sending to the opus decoder. */
409   buf = (dec->use_inband_fec
410       && gst_buffer_get_size (dec->last_buffer) >
411       0) ? dec->last_buffer : buffer;
412
413   if (buf && gst_buffer_get_size (buf) > 0) {
414     gst_buffer_map (buf, &map, GST_MAP_READ);
415     data = map.data;
416     size = map.size;
417     GST_DEBUG_OBJECT (dec, "Using buffer of size %" G_GSIZE_FORMAT, size);
418   } else {
419     /* concealment data, pass NULL as the bits parameters */
420     GST_DEBUG_OBJECT (dec, "Using NULL buffer");
421     data = NULL;
422     size = 0;
423   }
424
425   /* use maximum size (120 ms) as the number of returned samples is
426      not constant over the stream. */
427   samples = 120 * dec->sample_rate / 1000;
428   packet_size = samples * dec->n_channels * 2;
429
430   outbuf = gst_buffer_new_and_alloc (packet_size);
431   if (!outbuf) {
432     goto buffer_failed;
433   }
434
435   gst_buffer_map (outbuf, &omap, GST_MAP_WRITE);
436   out_data = (gint16 *) omap.data;
437
438   if (dec->use_inband_fec) {
439     if (dec->last_buffer) {
440       /* normal delayed decode */
441       GST_LOG_OBJECT (dec, "FEC enabled, decoding last delayed buffer");
442       n = opus_multistream_decode (dec->state, data, size, out_data, samples,
443           0);
444     } else {
445       /* FEC reconstruction decode */
446       GST_LOG_OBJECT (dec, "FEC enabled, reconstructing last buffer");
447       n = opus_multistream_decode (dec->state, data, size, out_data, samples,
448           1);
449     }
450   } else {
451     /* normal decode */
452     GST_LOG_OBJECT (dec, "FEC disabled, decoding buffer");
453     n = opus_multistream_decode (dec->state, data, size, out_data, samples, 0);
454   }
455   gst_buffer_unmap (outbuf, &omap);
456   if (data != NULL)
457     gst_buffer_unmap (buf, &map);
458
459   if (n < 0) {
460     GST_ELEMENT_ERROR (dec, STREAM, DECODE, ("Decoding error: %d", n), (NULL));
461     gst_buffer_unref (outbuf);
462     return GST_FLOW_ERROR;
463   }
464   GST_DEBUG_OBJECT (dec, "decoded %d samples", n);
465   gst_buffer_set_size (outbuf, n * 2 * dec->n_channels);
466
467   /* Skip any samples that need skipping */
468   if (dec->pre_skip > 0) {
469     guint scaled_pre_skip = dec->pre_skip * dec->sample_rate / 48000;
470     guint skip = scaled_pre_skip > n ? n : scaled_pre_skip;
471     guint scaled_skip = skip * 48000 / dec->sample_rate;
472
473     gst_buffer_resize (outbuf, skip * 2 * dec->n_channels, -1);
474     dec->pre_skip -= scaled_skip;
475     GST_INFO_OBJECT (dec,
476         "Skipping %u samples (%u at 48000 Hz, %u left to skip)", skip,
477         scaled_skip, dec->pre_skip);
478   }
479
480   if (gst_buffer_get_size (outbuf) == 0) {
481     gst_buffer_unref (outbuf);
482     outbuf = NULL;
483   } else if (dec->opus_pos[0] != GST_AUDIO_CHANNEL_POSITION_INVALID) {
484     gst_audio_buffer_reorder_channels (outbuf, GST_AUDIO_FORMAT_S16,
485         dec->n_channels, dec->opus_pos, dec->info.position);
486   }
487
488   /* Apply gain */
489   /* Would be better off leaving this to a volume element, as this is
490      a naive conversion that does too many int/float conversions.
491      However, we don't have control over the pipeline...
492      So make it optional if the user program wants to use a volume,
493      but do it by default so the correct volume goes out by default */
494   if (dec->apply_gain && outbuf && dec->r128_gain) {
495     gsize rsize;
496     unsigned int i, nsamples;
497     double volume = dec->r128_gain_volume;
498     gint16 *samples;
499
500     gst_buffer_map (outbuf, &omap, GST_MAP_READWRITE);
501     samples = (gint16 *) omap.data;
502     rsize = omap.size;
503     GST_DEBUG_OBJECT (dec, "Applying gain: volume %f", volume);
504     nsamples = rsize / 2;
505     for (i = 0; i < nsamples; ++i) {
506       int sample = (int) (samples[i] * volume + 0.5);
507       samples[i] = sample < -32768 ? -32768 : sample > 32767 ? 32767 : sample;
508     }
509     gst_buffer_unmap (outbuf, &omap);
510   }
511
512   if (dec->use_inband_fec) {
513     gst_buffer_replace (&dec->last_buffer, buffer);
514   }
515
516   res = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), outbuf, 1);
517
518   if (res != GST_FLOW_OK)
519     GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (res));
520
521 done:
522   return res;
523
524 creation_failed:
525   GST_ERROR_OBJECT (dec, "Failed to create Opus decoder: %d", err);
526   return GST_FLOW_ERROR;
527
528 buffer_failed:
529   GST_ERROR_OBJECT (dec, "Failed to create %u byte buffer", packet_size);
530   return GST_FLOW_ERROR;
531 }
532
533 static gboolean
534 gst_opus_dec_set_format (GstAudioDecoder * bdec, GstCaps * caps)
535 {
536   GstOpusDec *dec = GST_OPUS_DEC (bdec);
537   gboolean ret = TRUE;
538   GstStructure *s;
539   const GValue *streamheader;
540
541   GST_DEBUG_OBJECT (dec, "set_format: %" GST_PTR_FORMAT, caps);
542
543   s = gst_caps_get_structure (caps, 0);
544   if ((streamheader = gst_structure_get_value (s, "streamheader")) &&
545       G_VALUE_HOLDS (streamheader, GST_TYPE_ARRAY) &&
546       gst_value_array_get_size (streamheader) >= 2) {
547     const GValue *header, *vorbiscomment;
548     GstBuffer *buf;
549     GstFlowReturn res = GST_FLOW_OK;
550
551     header = gst_value_array_get_value (streamheader, 0);
552     if (header && G_VALUE_HOLDS (header, GST_TYPE_BUFFER)) {
553       buf = gst_value_get_buffer (header);
554       res = gst_opus_dec_parse_header (dec, buf);
555       if (res != GST_FLOW_OK)
556         goto done;
557       gst_buffer_replace (&dec->streamheader, buf);
558     }
559
560     vorbiscomment = gst_value_array_get_value (streamheader, 1);
561     if (vorbiscomment && G_VALUE_HOLDS (vorbiscomment, GST_TYPE_BUFFER)) {
562       buf = gst_value_get_buffer (vorbiscomment);
563       res = gst_opus_dec_parse_comments (dec, buf);
564       if (res != GST_FLOW_OK)
565         goto done;
566       gst_buffer_replace (&dec->vorbiscomment, buf);
567     }
568   }
569
570 done:
571   return ret;
572 }
573
574 static gboolean
575 memcmp_buffers (GstBuffer * buf1, GstBuffer * buf2)
576 {
577   gsize size1, size2;
578   gboolean res;
579   GstMapInfo map;
580
581   size1 = gst_buffer_get_size (buf1);
582   size2 = gst_buffer_get_size (buf2);
583
584   if (size1 != size2)
585     return FALSE;
586
587   gst_buffer_map (buf1, &map, GST_MAP_READ);
588   res = gst_buffer_memcmp (buf2, 0, map.data, map.size) == 0;
589   gst_buffer_unmap (buf1, &map);
590
591   return res;
592 }
593
594 static GstFlowReturn
595 gst_opus_dec_handle_frame (GstAudioDecoder * adec, GstBuffer * buf)
596 {
597   GstFlowReturn res;
598   GstOpusDec *dec;
599
600   /* no fancy draining */
601   if (G_UNLIKELY (!buf))
602     return GST_FLOW_OK;
603
604   dec = GST_OPUS_DEC (adec);
605   GST_LOG_OBJECT (dec,
606       "Got buffer ts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
607       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
608       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
609
610   /* If we have the streamheader and vorbiscomment from the caps already
611    * ignore them here */
612   if (dec->streamheader && dec->vorbiscomment) {
613     if (memcmp_buffers (dec->streamheader, buf)) {
614       GST_DEBUG_OBJECT (dec, "found streamheader");
615       gst_audio_decoder_finish_frame (adec, NULL, 1);
616       res = GST_FLOW_OK;
617     } else if (memcmp_buffers (dec->vorbiscomment, buf)) {
618       GST_DEBUG_OBJECT (dec, "found vorbiscomments");
619       gst_audio_decoder_finish_frame (adec, NULL, 1);
620       res = GST_FLOW_OK;
621     } else {
622       res = opus_dec_chain_parse_data (dec, buf);
623     }
624   } else {
625     /* Otherwise fall back to packet counting and assume that the
626      * first two packets might be the headers, checking magic. */
627     switch (dec->packetno) {
628       case 0:
629         if (gst_opus_header_is_header (buf, "OpusHead", 8)) {
630           GST_DEBUG_OBJECT (dec, "found streamheader");
631           res = gst_opus_dec_parse_header (dec, buf);
632           gst_audio_decoder_finish_frame (adec, NULL, 1);
633         } else {
634           res = opus_dec_chain_parse_data (dec, buf);
635         }
636         break;
637       case 1:
638         if (gst_opus_header_is_header (buf, "OpusTags", 8)) {
639           GST_DEBUG_OBJECT (dec, "counted vorbiscomments");
640           res = gst_opus_dec_parse_comments (dec, buf);
641           gst_audio_decoder_finish_frame (adec, NULL, 1);
642         } else {
643           res = opus_dec_chain_parse_data (dec, buf);
644         }
645         break;
646       default:
647       {
648         res = opus_dec_chain_parse_data (dec, buf);
649         break;
650       }
651     }
652   }
653
654   dec->packetno++;
655
656   return res;
657 }
658
659 static void
660 gst_opus_dec_get_property (GObject * object, guint prop_id, GValue * value,
661     GParamSpec * pspec)
662 {
663   GstOpusDec *dec = GST_OPUS_DEC (object);
664
665   switch (prop_id) {
666     case PROP_USE_INBAND_FEC:
667       g_value_set_boolean (value, dec->use_inband_fec);
668       break;
669     case PROP_APPLY_GAIN:
670       g_value_set_boolean (value, dec->apply_gain);
671       break;
672     default:
673       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
674       break;
675   }
676 }
677
678 static void
679 gst_opus_dec_set_property (GObject * object, guint prop_id,
680     const GValue * value, GParamSpec * pspec)
681 {
682   GstOpusDec *dec = GST_OPUS_DEC (object);
683
684   switch (prop_id) {
685     case PROP_USE_INBAND_FEC:
686       dec->use_inband_fec = g_value_get_boolean (value);
687       break;
688     case PROP_APPLY_GAIN:
689       dec->apply_gain = g_value_get_boolean (value);
690       break;
691     default:
692       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
693       break;
694   }
695 }