From 584acf39528aa7faac911cee528b6f09d9d2855c Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Fri, 25 Nov 2005 18:15:51 +0000 Subject: ext/wavpack/: put back wavpack - still needs porting Original commit message from CVS: * ext/wavpack/gstwavpackcommon.h: * ext/wavpack/gstwavpackdec.c: (gst_wavpack_dec_link), (gst_wavpack_dec_wvclink), (gst_wavpack_dec_get_type), (gst_wavpack_dec_base_init), (gst_wavpack_dec_dispose), (gst_wavpack_dec_class_init), (gst_wavpack_dec_src_query), (gst_wavpack_dec_init), (gst_wavpack_dec_setup_context), (gst_wavpack_dec_format_samples), (gst_wavpack_dec_loop), (gst_wavpack_dec_plugin_init): * ext/wavpack/gstwavpackdec.h: * ext/wavpack/gstwavpackparse.c: (gst_wavpack_parse_get_type), (gst_wavpack_parse_base_init), (gst_wavpack_parse_dispose), (gst_wavpack_parse_class_init), (gst_wavpack_parse_src_query), (gst_wavpack_parse_src_event), (find_header), (find_sample), (gst_wavpack_parse_seek), (gst_wavpack_parse_init), (gst_wavpack_parse_handle_event), (gst_wavpack_parse_loop), (gst_wavpack_parse_change_state), (gst_wavpack_parse_plugin_init): * ext/wavpack/gstwavpackparse.h: put back wavpack - still needs porting --- ext/wavpack/gstwavpackdec.c | 406 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 ext/wavpack/gstwavpackdec.c (limited to 'ext/wavpack/gstwavpackdec.c') diff --git a/ext/wavpack/gstwavpackdec.c b/ext/wavpack/gstwavpackdec.c new file mode 100644 index 00000000..d9fa074c --- /dev/null +++ b/ext/wavpack/gstwavpackdec.c @@ -0,0 +1,406 @@ +/* GStreamer Wavpack plugin + * (c) 2005 Arwed v. Merkatz + * + * gstwavpackdec.c: raw Wavpack bitstream decoder + * + * 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. + */ + +#include + +#include +#include + +#include +#include "gstwavpackdec.h" +#include "gstwavpackcommon.h" + +/* Filter signals and args */ +enum +{ + LAST_SIGNAL +}; + +enum +{ + ARG_0 +}; + +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-wavpack, " + "width = (int) { 8, 16, 24, 32 }, " + "channels = (int) { 1, 2 }, " + "rate = (int) [ 8000, 96000 ], " "framed = (boolean) true") + ); + +static GstStaticPadTemplate wvc_sink_factory = +GST_STATIC_PAD_TEMPLATE ("wvcsink", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS ("audio/x-wavpack-correction, " "framed = (boolean) true") + ); + +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-int, " + "width = (int) { 8, 16, 24 }, " + "depth = (int) { 8, 16, 24 }, " + "channels = (int) { 1, 2 }, " + "rate = (int) [ 8000, 96000 ], " + "endianness = (int) LITTLE_ENDIAN, " + "signed = (boolean) true;" + "audio/x-raw-float, " + "width = (int) 32, " + "channels = (int) { 1, 2 }, " + "rate = (int) [ 8000, 96000 ], " + "endianness = (int) LITTLE_ENDIAN, " "buffer-frames = (int) 0") + ); + +static void gst_wavpack_dec_class_init (GstWavpackDecClass * klass); +static void gst_wavpack_dec_base_init (GstWavpackDecClass * klass); +static void gst_wavpack_dec_init (GstWavpackDec * wavpackdec); + +static void gst_wavpack_dec_loop (GstElement * element); + +static GstElementClass *parent = NULL; + +static GstPadLinkReturn +gst_wavpack_dec_link (GstPad * pad, const GstCaps * caps) +{ + GstWavpackDec *wavpackdec = GST_WAVPACK_DEC (gst_pad_get_parent (pad)); + GstStructure *structure = gst_caps_get_structure (caps, 0); + GstCaps *srccaps; + gint bits; + + if (!gst_caps_is_fixed (caps)) + return GST_PAD_LINK_DELAYED; + + gst_structure_get_int (structure, "rate", + (gint32 *) & wavpackdec->samplerate); + gst_structure_get_int (structure, "channels", + (gint *) & wavpackdec->channels); + gst_structure_get_int (structure, "width", &bits); + wavpackdec->width = bits; + + if (bits != 32) { + srccaps = gst_caps_new_simple ("audio/x-raw-int", + "rate", G_TYPE_INT, wavpackdec->samplerate, + "channels", G_TYPE_INT, wavpackdec->channels, + "depth", G_TYPE_INT, bits, + "width", G_TYPE_INT, bits, + "endianness", G_TYPE_INT, LITTLE_ENDIAN, + "signed", G_TYPE_BOOLEAN, TRUE, NULL); + } else { + srccaps = gst_caps_new_simple ("audio/x-raw-float", + "rate", G_TYPE_INT, wavpackdec->samplerate, + "channels", G_TYPE_INT, wavpackdec->channels, + "width", G_TYPE_INT, 32, + "endianness", G_TYPE_INT, LITTLE_ENDIAN, + "buffer-frames", G_TYPE_INT, 0, NULL); + } + + gst_pad_set_explicit_caps (wavpackdec->srcpad, srccaps); + + // blocks are usually 0.5 seconds long, assume that's always the case for now + wavpackdec->decodebuf = + (int32_t *) g_malloc ((wavpackdec->samplerate / 2) * + wavpackdec->channels * sizeof (int32_t)); + return GST_PAD_LINK_OK; +} + +static GstPadLinkReturn +gst_wavpack_dec_wvclink (GstPad * pad, const GstCaps * caps) +{ + if (!gst_caps_is_fixed (caps)) + return GST_PAD_LINK_DELAYED; + + return GST_PAD_LINK_OK; +} + +GType +gst_wavpack_dec_get_type (void) +{ + static GType plugin_type = 0; + + if (!plugin_type) { + static const GTypeInfo plugin_info = { + sizeof (GstWavpackDecClass), + (GBaseInitFunc) gst_wavpack_dec_base_init, + NULL, + (GClassInitFunc) gst_wavpack_dec_class_init, + NULL, + NULL, + sizeof (GstWavpackDec), + 0, + (GInstanceInitFunc) gst_wavpack_dec_init, + }; + plugin_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstWavpackDec", &plugin_info, 0); + } + return plugin_type; +} + +static void +gst_wavpack_dec_base_init (GstWavpackDecClass * klass) +{ + static GstElementDetails plugin_details = { + "WAVPACK decoder", + "Codec/Decoder/Audio", + "Decode Wavpack audio data", + "Arwed v. Merkatz " + }; + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&wvc_sink_factory)); + gst_element_class_set_details (element_class, &plugin_details); +} + +static void +gst_wavpack_dec_dispose (GObject * object) +{ + GstWavpackDec *wavpackdec = GST_WAVPACK_DEC (object); + + g_free (wavpackdec->decodebuf); + + G_OBJECT_CLASS (parent)->dispose (object); +} + +static void +gst_wavpack_dec_class_init (GstWavpackDecClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->dispose = gst_wavpack_dec_dispose; +} + +static gboolean +gst_wavpack_dec_src_query (GstPad * pad, GstQueryType type, + GstFormat * format, gint64 * value) +{ + return gst_pad_query_default (pad, type, format, value); +} + +static void +gst_wavpack_dec_init (GstWavpackDec * wavpackdec) +{ + GstElementClass *klass = GST_ELEMENT_GET_CLASS (wavpackdec); + + wavpackdec->sinkpad = + gst_pad_new_from_template (gst_element_class_get_pad_template (klass, + "sink"), "sink"); + gst_pad_set_link_function (wavpackdec->sinkpad, gst_wavpack_dec_link); + + wavpackdec->wvcsinkpad = + gst_pad_new_from_template (gst_element_class_get_pad_template (klass, + "wvcsink"), "wvcsink"); + gst_pad_set_link_function (wavpackdec->wvcsinkpad, gst_wavpack_dec_wvclink); + + wavpackdec->srcpad = + gst_pad_new_from_template (gst_element_class_get_pad_template (klass, + "src"), "src"); + gst_pad_use_explicit_caps (wavpackdec->srcpad); + + gst_pad_set_query_function (wavpackdec->srcpad, gst_wavpack_dec_src_query); + + gst_element_add_pad (GST_ELEMENT (wavpackdec), wavpackdec->sinkpad); + gst_element_add_pad (GST_ELEMENT (wavpackdec), wavpackdec->srcpad); + gst_element_add_pad (GST_ELEMENT (wavpackdec), wavpackdec->wvcsinkpad); + gst_element_set_loop_function (GST_ELEMENT (wavpackdec), + gst_wavpack_dec_loop); + + wavpackdec->decodebuf = NULL; + wavpackdec->stream = (WavpackStream *) g_malloc0 (sizeof (WavpackStream)); + wavpackdec->context = (WavpackContext *) g_malloc0 (sizeof (WavpackContext)); +} + +static void +gst_wavpack_dec_setup_context (GstWavpackDec * wavpackdec, guchar * data, + guchar * cdata) +{ + WavpackContext *context = wavpackdec->context; + WavpackStream *stream = wavpackdec->stream; + + memset (context, 0, sizeof (context)); + + context->open_flags = 0; + context->current_stream = 0; + context->num_streams = 1; + + memset (stream, 0, sizeof (stream)); + context->streams[0] = stream; + + gst_wavpack_read_header (&stream->wphdr, data); + stream->blockbuff = data; + + if (cdata) { + context->wvc_flag = TRUE; + gst_wavpack_read_header (&stream->wphdr, cdata); + stream->block2buff = cdata; + } else { + context->wvc_flag = FALSE; + } + + unpack_init (context); +} + +static GstBuffer * +gst_wavpack_dec_format_samples (GstWavpackDec * wavpackdec, int32_t * samples, + guint num_samples) +{ + GstBuffer *buf; + gint i; + guint8 *dst; + int32_t temp; + + buf = + gst_buffer_new_and_alloc (num_samples * wavpackdec->width / 8 * + wavpackdec->channels); + dst = (guint8 *) GST_BUFFER_DATA (buf); + + switch (wavpackdec->width) { + case 8: + for (i = 0; i < num_samples * wavpackdec->channels; ++i) + *dst++ = *samples++ + 128; + break; + case 16: + for (i = 0; i < num_samples * wavpackdec->channels; ++i) { + *dst++ = (guint8) (temp = *samples++); + *dst++ = (guint8) (temp >> 8); + } + break; + case 24: + for (i = 0; i < num_samples * wavpackdec->channels; ++i) { + *dst++ = (guint8) (temp = *samples++); + *dst++ = (guint8) (temp >> 8); + *dst++ = (guint8) (temp >> 16); + } + break; + case 32: + for (i = 0; i < num_samples * wavpackdec->channels; ++i) { + *dst++ = (guint8) (temp = *samples++); + *dst++ = (guint8) (temp >> 8); + *dst++ = (guint8) (temp >> 16); + *dst++ = (guint8) (temp >> 24); + } + break; + default: + break; + } + + return buf; +} + + +static void +gst_wavpack_dec_loop (GstElement * element) +{ + GstWavpackDec *wavpackdec = GST_WAVPACK_DEC (element); + GstData *data, *cdata = NULL; + GstBuffer *buf, *outbuf, *cbuf = NULL; + + gboolean got_event = FALSE; + + if (!gst_pad_is_linked (wavpackdec->sinkpad)) { + return; + } + + /* + if (!gst_pad_is_linked (wavpackdec->wvcsinkpad)) { + return; + } + */ + + data = gst_pad_pull (wavpackdec->sinkpad); + + if (GST_IS_EVENT (data)) { + GstEvent *event = GST_EVENT (data); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + gst_event_unref (event); + gst_pad_push (wavpackdec->srcpad, + GST_DATA (gst_event_new (GST_EVENT_EOS))); + gst_element_set_eos (element); + break; + default: + gst_pad_event_default (wavpackdec->srcpad, event); + break; + } + got_event = TRUE; + } + + if (gst_pad_is_linked (wavpackdec->wvcsinkpad)) { + cdata = gst_pad_pull (wavpackdec->wvcsinkpad); + if (GST_IS_EVENT (cdata)) { + GstEvent *event = GST_EVENT (cdata); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + gst_event_unref (event); + gst_pad_push (wavpackdec->srcpad, + GST_DATA (gst_event_new (GST_EVENT_EOS))); + gst_element_set_eos (element); + break; + default: + gst_pad_event_default (wavpackdec->srcpad, event); + break; + } + got_event = TRUE; + } else { + cbuf = GST_BUFFER (cdata); + } + } + + if (got_event) + return; + + buf = GST_BUFFER (data); + + gst_wavpack_dec_setup_context (wavpackdec, GST_BUFFER_DATA (buf), + cbuf ? GST_BUFFER_DATA (cbuf) : NULL); + unpack_samples (wavpackdec->context, wavpackdec->decodebuf, + wavpackdec->context->streams[0]->wphdr.block_samples); + outbuf = + gst_wavpack_dec_format_samples (wavpackdec, wavpackdec->decodebuf, + wavpackdec->context->streams[0]->wphdr.block_samples); + + GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf); + GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf); + gst_buffer_unref (buf); + + gst_pad_push (wavpackdec->srcpad, GST_DATA (outbuf)); +} + +gboolean +gst_wavpack_dec_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "wavpackdec", + GST_RANK_PRIMARY, GST_TYPE_WAVPACK_DEC); +} -- cgit v1.2.1