Tizen 2.0 Release
[framework/multimedia/gst-plugins-good0.10.git] / ext / wavpack / gstwavpackdec.c
1 /* GStreamer Wavpack plugin
2  * Copyright (c) 2005 Arwed v. Merkatz <v.merkatz@gmx.net>
3  * Copyright (c) 2006 Edward Hervey <bilboed@gmail.com>
4  * Copyright (c) 2006 Sebastian Dröge <slomo@circular-chaos.org>
5  *
6  * gstwavpackdec.c: raw Wavpack bitstream decoder
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /**
25  * SECTION:element-wavpackdec
26  *
27  * WavpackDec decodes framed (for example by the WavpackParse element)
28  * Wavpack streams and decodes them to raw audio.
29  * <ulink url="http://www.wavpack.com/">Wavpack</ulink> is an open-source
30  * audio codec that features both lossless and lossy encoding.
31  *
32  * <refsect2>
33  * <title>Example launch line</title>
34  * |[
35  * gst-launch filesrc location=test.wv ! wavpackparse ! wavpackdec ! audioconvert ! audioresample ! autoaudiosink
36  * ]| This pipeline decodes the Wavpack file test.wv into raw audio buffers and
37  * tries to play it back using an automatically found audio sink.
38  * </refsect2>
39  */
40
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44
45 #include <gst/gst.h>
46 #include <gst/audio/audio.h>
47 #include <gst/audio/multichannel.h>
48
49 #include <math.h>
50 #include <string.h>
51
52 #include <wavpack/wavpack.h>
53 #include "gstwavpackdec.h"
54 #include "gstwavpackcommon.h"
55 #include "gstwavpackstreamreader.h"
56
57
58 #define WAVPACK_DEC_MAX_ERRORS 16
59
60 GST_DEBUG_CATEGORY_STATIC (gst_wavpack_dec_debug);
61 #define GST_CAT_DEFAULT gst_wavpack_dec_debug
62
63 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
64     GST_PAD_SINK,
65     GST_PAD_ALWAYS,
66     GST_STATIC_CAPS ("audio/x-wavpack, "
67         "width = (int) [ 1, 32 ], "
68         "channels = (int) [ 1, 8 ], "
69         "rate = (int) [ 6000, 192000 ], " "framed = (boolean) true")
70     );
71
72 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
73     GST_PAD_SRC,
74     GST_PAD_ALWAYS,
75     GST_STATIC_CAPS ("audio/x-raw-int, "
76         "width = (int) 32, "
77         "depth = (int) [ 1, 32 ], "
78         "channels = (int) [ 1, 8 ], "
79         "rate = (int) [ 6000, 192000 ], "
80         "endianness = (int) BYTE_ORDER, " "signed = (boolean) true")
81     );
82
83 static GstFlowReturn gst_wavpack_dec_chain (GstPad * pad, GstBuffer * buffer);
84 static gboolean gst_wavpack_dec_sink_set_caps (GstPad * pad, GstCaps * caps);
85 static gboolean gst_wavpack_dec_sink_event (GstPad * pad, GstEvent * event);
86 static void gst_wavpack_dec_finalize (GObject * object);
87 static GstStateChangeReturn gst_wavpack_dec_change_state (GstElement * element,
88     GstStateChange transition);
89 static void gst_wavpack_dec_post_tags (GstWavpackDec * dec);
90
91 GST_BOILERPLATE (GstWavpackDec, gst_wavpack_dec, GstElement, GST_TYPE_ELEMENT);
92
93 static void
94 gst_wavpack_dec_base_init (gpointer klass)
95 {
96   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
97
98   gst_element_class_add_static_pad_template (element_class, &src_factory);
99   gst_element_class_add_static_pad_template (element_class, &sink_factory);
100   gst_element_class_set_details_simple (element_class, "Wavpack audio decoder",
101       "Codec/Decoder/Audio",
102       "Decodes Wavpack audio data",
103       "Arwed v. Merkatz <v.merkatz@gmx.net>, "
104       "Sebastian Dröge <slomo@circular-chaos.org>");
105 }
106
107 static void
108 gst_wavpack_dec_class_init (GstWavpackDecClass * klass)
109 {
110   GObjectClass *gobject_class = (GObjectClass *) klass;
111   GstElementClass *gstelement_class = (GstElementClass *) klass;
112
113   gstelement_class->change_state =
114       GST_DEBUG_FUNCPTR (gst_wavpack_dec_change_state);
115   gobject_class->finalize = gst_wavpack_dec_finalize;
116 }
117
118 static void
119 gst_wavpack_dec_reset (GstWavpackDec * dec)
120 {
121   dec->wv_id.buffer = NULL;
122   dec->wv_id.position = dec->wv_id.length = 0;
123
124   dec->error_count = 0;
125
126   dec->channels = 0;
127   dec->channel_mask = 0;
128   dec->sample_rate = 0;
129   dec->depth = 0;
130
131   gst_segment_init (&dec->segment, GST_FORMAT_TIME);
132   dec->next_block_index = 0;
133 }
134
135 static void
136 gst_wavpack_dec_init (GstWavpackDec * dec, GstWavpackDecClass * gklass)
137 {
138   dec->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
139   gst_pad_set_chain_function (dec->sinkpad,
140       GST_DEBUG_FUNCPTR (gst_wavpack_dec_chain));
141   gst_pad_set_setcaps_function (dec->sinkpad,
142       GST_DEBUG_FUNCPTR (gst_wavpack_dec_sink_set_caps));
143   gst_pad_set_event_function (dec->sinkpad,
144       GST_DEBUG_FUNCPTR (gst_wavpack_dec_sink_event));
145   gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
146
147   dec->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
148   gst_pad_use_fixed_caps (dec->srcpad);
149   gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
150
151   dec->context = NULL;
152   dec->stream_reader = gst_wavpack_stream_reader_new ();
153
154   gst_wavpack_dec_reset (dec);
155 }
156
157 static void
158 gst_wavpack_dec_finalize (GObject * object)
159 {
160   GstWavpackDec *dec = GST_WAVPACK_DEC (object);
161
162   g_free (dec->stream_reader);
163   dec->stream_reader = NULL;
164
165   G_OBJECT_CLASS (parent_class)->finalize (object);
166 }
167
168 static gboolean
169 gst_wavpack_dec_sink_set_caps (GstPad * pad, GstCaps * caps)
170 {
171   GstWavpackDec *dec = GST_WAVPACK_DEC (gst_pad_get_parent (pad));
172   GstStructure *structure = gst_caps_get_structure (caps, 0);
173
174   /* Check if we can set the caps here already */
175   if (gst_structure_get_int (structure, "channels", &dec->channels) &&
176       gst_structure_get_int (structure, "rate", &dec->sample_rate) &&
177       gst_structure_get_int (structure, "width", &dec->depth)) {
178     GstCaps *caps;
179     GstAudioChannelPosition *pos;
180
181     caps = gst_caps_new_simple ("audio/x-raw-int",
182         "rate", G_TYPE_INT, dec->sample_rate,
183         "channels", G_TYPE_INT, dec->channels,
184         "depth", G_TYPE_INT, dec->depth,
185         "width", G_TYPE_INT, 32,
186         "endianness", G_TYPE_INT, G_BYTE_ORDER,
187         "signed", G_TYPE_BOOLEAN, TRUE, NULL);
188
189     /* If we already have the channel layout set from upstream
190      * take this */
191     if (gst_structure_has_field (structure, "channel-positions")) {
192       pos = gst_audio_get_channel_positions (structure);
193       if (pos != NULL && dec->channels > 2) {
194         GstStructure *new_str = gst_caps_get_structure (caps, 0);
195
196         gst_audio_set_channel_positions (new_str, pos);
197         dec->channel_mask =
198             gst_wavpack_get_channel_mask_from_positions (pos, dec->channels);
199       }
200
201       if (pos != NULL)
202         g_free (pos);
203     }
204
205     GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
206
207     /* should always succeed */
208     gst_pad_set_caps (dec->srcpad, caps);
209     gst_caps_unref (caps);
210
211     /* send GST_TAG_AUDIO_CODEC and GST_TAG_BITRATE tags before something
212      * is decoded or after the format has changed */
213     gst_wavpack_dec_post_tags (dec);
214   }
215
216   gst_object_unref (dec);
217
218   return TRUE;
219 }
220
221 static void
222 gst_wavpack_dec_post_tags (GstWavpackDec * dec)
223 {
224   GstTagList *list;
225   GstFormat format_time = GST_FORMAT_TIME, format_bytes = GST_FORMAT_BYTES;
226   gint64 duration, size;
227
228   list = gst_tag_list_new ();
229
230   gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
231       GST_TAG_AUDIO_CODEC, "Wavpack", NULL);
232
233   /* try to estimate the average bitrate */
234   if (gst_pad_query_peer_duration (dec->sinkpad, &format_bytes, &size) &&
235       gst_pad_query_peer_duration (dec->sinkpad, &format_time, &duration) &&
236       size > 0 && duration > 0) {
237     guint64 bitrate;
238
239     bitrate = gst_util_uint64_scale (size, 8 * GST_SECOND, duration);
240     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
241         (guint) bitrate, NULL);
242   }
243
244   gst_element_post_message (GST_ELEMENT (dec),
245       gst_message_new_tag (GST_OBJECT (dec), list));
246 }
247
248 static GstFlowReturn
249 gst_wavpack_dec_chain (GstPad * pad, GstBuffer * buf)
250 {
251   GstWavpackDec *dec;
252   GstBuffer *outbuf = NULL;
253   GstFlowReturn ret = GST_FLOW_OK;
254   WavpackHeader wph;
255   int32_t decoded, unpacked_size;
256   gboolean format_changed;
257
258   dec = GST_WAVPACK_DEC (GST_PAD_PARENT (pad));
259
260   /* check input, we only accept framed input with complete chunks */
261   if (GST_BUFFER_SIZE (buf) < sizeof (WavpackHeader))
262     goto input_not_framed;
263
264   if (!gst_wavpack_read_header (&wph, GST_BUFFER_DATA (buf)))
265     goto invalid_header;
266
267   if (GST_BUFFER_SIZE (buf) < wph.ckSize + 4 * 1 + 4)
268     goto input_not_framed;
269
270   if (!(wph.flags & INITIAL_BLOCK))
271     goto input_not_framed;
272
273   dec->wv_id.buffer = GST_BUFFER_DATA (buf);
274   dec->wv_id.length = GST_BUFFER_SIZE (buf);
275   dec->wv_id.position = 0;
276
277   /* create a new wavpack context if there is none yet but if there
278    * was already one (i.e. caps were set on the srcpad) check whether
279    * the new one has the same caps */
280   if (!dec->context) {
281     gchar error_msg[80];
282
283     dec->context = WavpackOpenFileInputEx (dec->stream_reader,
284         &dec->wv_id, NULL, error_msg, OPEN_STREAMING, 0);
285
286     if (!dec->context) {
287       GST_WARNING ("Couldn't decode buffer: %s", error_msg);
288       dec->error_count++;
289       if (dec->error_count <= WAVPACK_DEC_MAX_ERRORS) {
290         goto out;               /* just return OK for now */
291       } else {
292         goto decode_error;
293       }
294     }
295   }
296
297   g_assert (dec->context != NULL);
298
299   dec->error_count = 0;
300
301   format_changed =
302       (dec->sample_rate != WavpackGetSampleRate (dec->context)) ||
303       (dec->channels != WavpackGetNumChannels (dec->context)) ||
304       (dec->depth != WavpackGetBitsPerSample (dec->context)) ||
305 #ifdef WAVPACK_OLD_API
306       (dec->channel_mask != dec->context->config.channel_mask);
307 #else
308       (dec->channel_mask != WavpackGetChannelMask (dec->context));
309 #endif
310
311   if (!GST_PAD_CAPS (dec->srcpad) || format_changed) {
312     GstCaps *caps;
313     gint channel_mask;
314
315     dec->sample_rate = WavpackGetSampleRate (dec->context);
316     dec->channels = WavpackGetNumChannels (dec->context);
317     dec->depth = WavpackGetBitsPerSample (dec->context);
318
319     caps = gst_caps_new_simple ("audio/x-raw-int",
320         "rate", G_TYPE_INT, dec->sample_rate,
321         "channels", G_TYPE_INT, dec->channels,
322         "depth", G_TYPE_INT, dec->depth,
323         "width", G_TYPE_INT, 32,
324         "endianness", G_TYPE_INT, G_BYTE_ORDER,
325         "signed", G_TYPE_BOOLEAN, TRUE, NULL);
326
327 #ifdef WAVPACK_OLD_API
328     channel_mask = dec->context->config.channel_mask;
329 #else
330     channel_mask = WavpackGetChannelMask (dec->context);
331 #endif
332     if (channel_mask == 0)
333       channel_mask = gst_wavpack_get_default_channel_mask (dec->channels);
334
335     dec->channel_mask = channel_mask;
336
337     /* Only set the channel layout for more than two channels
338      * otherwise things break unfortunately */
339     if (channel_mask != 0 && dec->channels > 2)
340       if (!gst_wavpack_set_channel_layout (caps, channel_mask))
341         GST_WARNING_OBJECT (dec, "Failed to set channel layout");
342
343     GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
344
345     /* should always succeed */
346     gst_pad_set_caps (dec->srcpad, caps);
347     gst_caps_unref (caps);
348
349     /* send GST_TAG_AUDIO_CODEC and GST_TAG_BITRATE tags before something
350      * is decoded or after the format has changed */
351     gst_wavpack_dec_post_tags (dec);
352   }
353
354   /* alloc output buffer */
355   unpacked_size = 4 * wph.block_samples * dec->channels;
356   ret = gst_pad_alloc_buffer (dec->srcpad, GST_BUFFER_OFFSET (buf),
357       unpacked_size, GST_PAD_CAPS (dec->srcpad), &outbuf);
358
359   if (ret != GST_FLOW_OK)
360     goto out;
361
362   gst_buffer_copy_metadata (outbuf, buf, GST_BUFFER_COPY_TIMESTAMPS);
363
364   /* If we got a DISCONT buffer forward the flag. Nothing else
365    * has to be done as libwavpack doesn't store state between
366    * Wavpack blocks */
367   if (GST_BUFFER_IS_DISCONT (buf) || dec->next_block_index != wph.block_index)
368     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
369
370   dec->next_block_index = wph.block_index + wph.block_samples;
371
372   /* decode */
373   decoded = WavpackUnpackSamples (dec->context,
374       (int32_t *) GST_BUFFER_DATA (outbuf), wph.block_samples);
375   if (decoded != wph.block_samples)
376     goto decode_error;
377
378   if ((outbuf = gst_audio_buffer_clip (outbuf, &dec->segment,
379               dec->sample_rate, 4 * dec->channels))) {
380     GST_LOG_OBJECT (dec, "pushing buffer with time %" GST_TIME_FORMAT,
381         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
382     ret = gst_pad_push (dec->srcpad, outbuf);
383   }
384
385 out:
386
387   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
388     GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (ret));
389   }
390
391   gst_buffer_unref (buf);
392
393   return ret;
394
395 /* ERRORS */
396 input_not_framed:
397   {
398     GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Expected framed input"));
399     gst_buffer_unref (buf);
400     return GST_FLOW_ERROR;
401   }
402 invalid_header:
403   {
404     GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Invalid wavpack header"));
405     gst_buffer_unref (buf);
406     return GST_FLOW_ERROR;
407   }
408 decode_error:
409   {
410     const gchar *reason = "unknown";
411
412     if (dec->context) {
413 #ifdef WAVPACK_OLD_API
414       reason = dec->context->error_message;
415 #else
416       reason = WavpackGetErrorMessage (dec->context);
417 #endif
418     } else {
419       reason = "couldn't create decoder context";
420     }
421     GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
422         ("Failed to decode wavpack stream: %s", reason));
423     if (outbuf)
424       gst_buffer_unref (outbuf);
425     gst_buffer_unref (buf);
426     return GST_FLOW_ERROR;
427   }
428 }
429
430 static gboolean
431 gst_wavpack_dec_sink_event (GstPad * pad, GstEvent * event)
432 {
433   GstWavpackDec *dec = GST_WAVPACK_DEC (gst_pad_get_parent (pad));
434
435   GST_LOG_OBJECT (dec, "Received %s event", GST_EVENT_TYPE_NAME (event));
436   switch (GST_EVENT_TYPE (event)) {
437     case GST_EVENT_NEWSEGMENT:{
438       GstFormat fmt;
439       gboolean is_update;
440       gint64 start, end, base;
441       gdouble rate;
442
443       gst_event_parse_new_segment (event, &is_update, &rate, &fmt, &start,
444           &end, &base);
445       if (fmt == GST_FORMAT_TIME) {
446         GST_DEBUG ("Got NEWSEGMENT event in GST_FORMAT_TIME, passing on (%"
447             GST_TIME_FORMAT " - %" GST_TIME_FORMAT ")", GST_TIME_ARGS (start),
448             GST_TIME_ARGS (end));
449         gst_segment_set_newsegment (&dec->segment, is_update, rate, fmt,
450             start, end, base);
451       } else {
452         gst_segment_init (&dec->segment, GST_FORMAT_TIME);
453       }
454       break;
455     }
456     default:
457       break;
458   }
459
460   gst_object_unref (dec);
461   return gst_pad_event_default (pad, event);
462 }
463
464 static GstStateChangeReturn
465 gst_wavpack_dec_change_state (GstElement * element, GstStateChange transition)
466 {
467   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
468   GstWavpackDec *dec = GST_WAVPACK_DEC (element);
469
470   switch (transition) {
471     case GST_STATE_CHANGE_NULL_TO_READY:
472       break;
473     case GST_STATE_CHANGE_READY_TO_PAUSED:
474       break;
475     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
476       break;
477     default:
478       break;
479   }
480
481   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
482
483   switch (transition) {
484     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
485       break;
486     case GST_STATE_CHANGE_PAUSED_TO_READY:
487       if (dec->context) {
488         WavpackCloseFile (dec->context);
489         dec->context = NULL;
490       }
491
492       gst_wavpack_dec_reset (dec);
493       break;
494     case GST_STATE_CHANGE_READY_TO_NULL:
495       break;
496     default:
497       break;
498   }
499
500   return ret;
501 }
502
503 gboolean
504 gst_wavpack_dec_plugin_init (GstPlugin * plugin)
505 {
506   if (!gst_element_register (plugin, "wavpackdec",
507           GST_RANK_PRIMARY, GST_TYPE_WAVPACK_DEC))
508     return FALSE;
509   GST_DEBUG_CATEGORY_INIT (gst_wavpack_dec_debug, "wavpack_dec", 0,
510       "Wavpack decoder");
511   return TRUE;
512 }