1 /* GStreamer Wavpack plugin
2 * (c) 2005 Arwed v. Merkatz <v.merkatz@gmx.net>
4 * gstwavpackdec.c: raw Wavpack bitstream decoder
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
27 #include <wavpack/wavpack.h>
28 #include "gstwavpackdec.h"
29 #include "gstwavpackcommon.h"
31 GST_DEBUG_CATEGORY_STATIC (gst_wavpack_dec_debug);
32 #define GST_CAT_DEFAULT gst_wavpack_dec_debug
34 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
37 GST_STATIC_CAPS ("audio/x-wavpack, "
38 "width = (int) { 8, 16, 24, 32 }, "
39 "channels = (int) { 1, 2 }, "
40 "rate = (int) [ 6000, 192000 ], " "framed = (boolean) true")
43 static GstStaticPadTemplate wvc_sink_factory =
44 GST_STATIC_PAD_TEMPLATE ("wvcsink",
47 GST_STATIC_CAPS ("audio/x-wavpack-correction, " "framed = (boolean) true")
50 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
53 GST_STATIC_CAPS ("audio/x-raw-int, "
54 "width = (int) { 8, 16, 24, 32 }, "
55 "depth = (int) { 8, 16, 24, 32 }, "
56 "channels = (int) { 1, 2 }, "
57 "rate = (int) [ 6000, 192000 ], "
58 "endianness = (int) LITTLE_ENDIAN, " "signed = (boolean) true")
62 "channels = (int) { 1, 2 }, "
63 "rate = (int) [ 6000, 192000 ], " "endianness = (int) LITTLE_ENDIAN"
67 static GstFlowReturn gst_wavpack_dec_chain (GstPad * pad, GstBuffer * buffer);
68 static gboolean gst_wavpack_dec_sink_event (GstPad * pad, GstEvent * event);
70 GST_BOILERPLATE (GstWavpackDec, gst_wavpack_dec, GstElement, GST_TYPE_ELEMENT)
72 static gboolean gst_wavpack_dec_setcaps (GstPad * pad, GstCaps * caps)
74 GstWavpackDec *wavpackdec = GST_WAVPACK_DEC (gst_pad_get_parent (pad));
75 GstStructure *structure;
77 gint bits, rate, channels;
79 structure = gst_caps_get_structure (caps, 0);
80 if (!gst_structure_get_int (structure, "rate", &rate) ||
81 !gst_structure_get_int (structure, "channels", &channels) ||
82 !gst_structure_get_int (structure, "width", &bits)) {
86 wavpackdec->samplerate = rate;
87 wavpackdec->channels = channels;
88 wavpackdec->width = bits;
90 /* 32-bit output seems to be in fact 32 bit int (e.g. Prod_Girls.wv) */
91 /* if (bits != 32) { */
92 srccaps = gst_caps_new_simple ("audio/x-raw-int",
93 "rate", G_TYPE_INT, wavpackdec->samplerate,
94 "channels", G_TYPE_INT, wavpackdec->channels,
95 "depth", G_TYPE_INT, bits,
96 "width", G_TYPE_INT, bits,
97 "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
98 "signed", G_TYPE_BOOLEAN, TRUE, NULL);
101 srccaps = gst_caps_new_simple ("audio/x-raw-float",
102 "rate", G_TYPE_INT, wavpackdec->samplerate,
103 "channels", G_TYPE_INT, wavpackdec->channels,
104 "width", G_TYPE_INT, 32,
105 "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, NULL);
108 /* gst_pad_set_caps (wavpackdec->sinkpad, caps); */
110 gst_pad_set_caps (wavpackdec->srcpad, srccaps);
111 gst_pad_use_fixed_caps (wavpackdec->srcpad);
117 static GstPadLinkReturn
118 gst_wavpack_dec_wvclink (GstPad * pad, GstPad * peer)
120 if (!gst_caps_is_fixed (GST_PAD_CAPS (peer)))
121 return GST_PAD_LINK_REFUSED;
123 return GST_PAD_LINK_OK;
128 gst_wavpack_dec_base_init (gpointer klass)
130 static GstElementDetails plugin_details = {
132 "Codec/Decoder/Audio",
133 "Decode Wavpack audio data",
134 "Arwed v. Merkatz <v.merkatz@gmx.net>"
136 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
138 gst_element_class_add_pad_template (element_class,
139 gst_static_pad_template_get (&src_factory));
140 gst_element_class_add_pad_template (element_class,
141 gst_static_pad_template_get (&sink_factory));
142 gst_element_class_add_pad_template (element_class,
143 gst_static_pad_template_get (&wvc_sink_factory));
144 gst_element_class_set_details (element_class, &plugin_details);
148 gst_wavpack_dec_dispose (GObject * object)
150 GstWavpackDec *wavpackdec = GST_WAVPACK_DEC (object);
152 g_free (wavpackdec->decodebuf);
153 wavpackdec->decodebuf = NULL;
155 /* FIXME: what about wavpackdec->stream and wavpackdec->context? (tpm) */
157 G_OBJECT_CLASS (parent_class)->dispose (object);
161 gst_wavpack_dec_class_init (GstWavpackDecClass * klass)
163 GObjectClass *gobject_class;
164 GstElementClass *gstelement_class;
166 gobject_class = (GObjectClass *) klass;
167 gstelement_class = (GstElementClass *) klass;
169 gobject_class->dispose = gst_wavpack_dec_dispose;
173 gst_wavpack_dec_src_query (GstPad * pad, GstQuery * query)
175 return gst_pad_query_default (pad, query);
179 gst_wavpack_dec_sink_event (GstPad * pad, GstEvent * event)
183 dec = GST_WAVPACK_DEC (gst_pad_get_parent (pad));
185 GST_LOG_OBJECT (dec, "Received %s event", GST_EVENT_TYPE_NAME (event));
186 switch (GST_EVENT_TYPE (event)) {
187 case GST_EVENT_NEWSEGMENT:{
188 /* TODO: save current segment so we can do clipping, for now
189 * we'll just leave the clipping to the audio sink */
196 gst_object_unref (dec);
198 return gst_pad_event_default (pad, event);
202 gst_wavpack_dec_init (GstWavpackDec * wavpackdec, GstWavpackDecClass * gklass)
204 GstElementClass *klass = GST_ELEMENT_GET_CLASS (wavpackdec);
206 wavpackdec->sinkpad =
207 gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
209 gst_element_add_pad (GST_ELEMENT (wavpackdec), wavpackdec->sinkpad);
211 gst_pad_set_chain_function (wavpackdec->sinkpad,
212 GST_DEBUG_FUNCPTR (gst_wavpack_dec_chain));
213 gst_pad_set_setcaps_function (wavpackdec->sinkpad,
214 GST_DEBUG_FUNCPTR (gst_wavpack_dec_setcaps));
215 gst_pad_set_event_function (wavpackdec->sinkpad,
216 GST_DEBUG_FUNCPTR (gst_wavpack_dec_sink_event));
219 wavpackdec->wvcsinkpad =
220 gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
221 "wvcsink"), "wvcsink");
222 gst_pad_set_link_function (wavpackdec->wvcsinkpad, gst_wavpack_dec_wvclink);
223 gst_element_add_pad (GST_ELEMENT (wavpackdec), wavpackdec->wvcsinkpad);
228 gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
230 gst_pad_use_fixed_caps (wavpackdec->srcpad);
232 gst_pad_set_query_function (wavpackdec->srcpad,
233 GST_DEBUG_FUNCPTR (gst_wavpack_dec_src_query));
235 gst_element_add_pad (GST_ELEMENT (wavpackdec), wavpackdec->srcpad);
237 wavpackdec->decodebuf = NULL;
238 wavpackdec->decodebuf_size = 0;
239 wavpackdec->stream = (WavpackStream *) g_malloc0 (sizeof (WavpackStream));
240 wavpackdec->context = (WavpackContext *) g_malloc0 (sizeof (WavpackContext));
244 gst_wavpack_dec_setup_context (GstWavpackDec * wavpackdec, guchar * data,
247 WavpackContext *context = wavpackdec->context;
248 WavpackStream *stream = wavpackdec->stream;
251 memset (context, 0, sizeof (context));
253 context->open_flags = 0;
254 context->current_stream = 0;
255 context->num_streams = 1;
257 memset (stream, 0, sizeof (stream));
258 context->streams[0] = stream;
260 gst_wavpack_read_header (&stream->wphdr, data);
261 stream->blockbuff = data;
264 context->wvc_flag = TRUE;
265 gst_wavpack_read_header (&stream->wphdr, cdata);
266 stream->block2buff = cdata;
268 context->wvc_flag = FALSE;
272 stream->wphdr.block_samples * wavpackdec->channels * sizeof (int32_t);
273 if (wavpackdec->decodebuf_size < buffer_size) {
274 wavpackdec->decodebuf =
275 (int32_t *) g_realloc (wavpackdec->decodebuf, buffer_size);
276 wavpackdec->decodebuf_size = buffer_size;
279 unpack_init (context);
283 gst_wavpack_dec_format_samples (GstWavpackDec * wavpackdec, int32_t * samples,
292 gst_buffer_new_and_alloc (num_samples * wavpackdec->width / 8 *
293 wavpackdec->channels);
295 dst = (guint8 *) GST_BUFFER_DATA (buf);
297 switch (wavpackdec->width) {
299 for (i = 0; i < num_samples * wavpackdec->channels; ++i)
300 *dst++ = *samples++ + 128;
303 for (i = 0; i < num_samples * wavpackdec->channels; ++i) {
304 *dst++ = (guint8) (temp = *samples++);
305 *dst++ = (guint8) (temp >> 8);
309 for (i = 0; i < num_samples * wavpackdec->channels; ++i) {
310 *dst++ = (guint8) (temp = *samples++);
311 *dst++ = (guint8) (temp >> 8);
312 *dst++ = (guint8) (temp >> 16);
316 for (i = 0; i < num_samples * wavpackdec->channels; ++i) {
317 *dst++ = (guint8) (temp = *samples++);
318 *dst++ = (guint8) (temp >> 8);
319 *dst++ = (guint8) (temp >> 16);
320 *dst++ = (guint8) (temp >> 24);
331 gst_wavpack_dec_chain (GstPad * pad, GstBuffer * buf)
334 GstWavpackDec *wavpackdec = GST_WAVPACK_DEC (gst_pad_get_parent (pad));
335 GstBuffer *outbuf, *cbuf = NULL;
336 GstFlowReturn ret = GST_FLOW_OK;
339 if (gst_pad_is_linked (wavpackdec->wvcsinkpad)) {
340 if (GST_FLOW_OK != gst_pad_pull_range (wavpackdec->wvcsinkpad,
341 wavpackdec->wvcflushed_bytes, -1, &cbuf)) {
344 wavpackdec->wvcflushed_bytes += GST_BUFFER_SIZE (cbuf);
350 gst_wavpack_dec_setup_context (wavpackdec, GST_BUFFER_DATA (buf),
351 cbuf ? GST_BUFFER_DATA (cbuf) : NULL);
352 unpack_samples (wavpackdec->context, wavpackdec->decodebuf,
353 wavpackdec->context->streams[0]->wphdr.block_samples);
355 gst_wavpack_dec_format_samples (wavpackdec, wavpackdec->decodebuf,
356 wavpackdec->context->streams[0]->wphdr.block_samples);
358 gst_buffer_stamp (outbuf, buf);
360 gst_buffer_unref (buf);
362 gst_buffer_unref (cbuf);
365 gst_buffer_set_caps (outbuf, GST_PAD_CAPS (wavpackdec->srcpad));
367 GST_LOG_OBJECT (wavpackdec, "pushing buffer with time %" GST_TIME_FORMAT,
368 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
370 ret = gst_pad_push (wavpackdec->srcpad, outbuf);
371 if (ret != GST_FLOW_OK) {
372 GST_DEBUG_OBJECT (wavpackdec, "pad_push: %s", gst_flow_get_name (ret));
379 gst_wavpack_dec_plugin_init (GstPlugin * plugin)
381 if (!gst_element_register (plugin, "wavpackdec",
382 GST_RANK_PRIMARY, GST_TYPE_WAVPACK_DEC))
385 GST_DEBUG_CATEGORY_INIT (gst_wavpack_dec_debug, "wavpackdec", 0,