From b87beb11fd9a5b253f301069348198950e529038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Wed, 4 Apr 2007 22:40:45 +0200 Subject: Rename xine_decoder.c to xine_musepack_decoder.c. Use xineplug_LTLIBRARIES. --HG-- rename : src/libmusepack/xine_decoder.c => src/libmusepack/xine_musepack_decoder.c --- src/libmusepack/Makefile.am | 9 +- src/libmusepack/xine_decoder.c | 471 -------------------------------- src/libmusepack/xine_musepack_decoder.c | 471 ++++++++++++++++++++++++++++++++ 3 files changed, 474 insertions(+), 477 deletions(-) delete mode 100644 src/libmusepack/xine_decoder.c create mode 100644 src/libmusepack/xine_musepack_decoder.c (limited to 'src') diff --git a/src/libmusepack/Makefile.am b/src/libmusepack/Makefile.am index 021ec0985..d39426597 100644 --- a/src/libmusepack/Makefile.am +++ b/src/libmusepack/Makefile.am @@ -4,10 +4,8 @@ SUBDIRS = musepack EXTRA_DIST = diff_against_svn.patch -libdir = $(XINE_PLUGINDIR) - if MUSEPACK -lib_LTLIBRARIES = xineplug_decode_mpc.la +xineplug_LTLIBRARIES = xineplug_decode_mpc.la endif if EXTERNAL_MPCDEC @@ -23,7 +21,6 @@ else xineplug_decode_mpc_la_LIBADD = $(XINE_LIB) endif -xineplug_decode_mpc_la_SOURCES = $(internal_sources) xine_decoder.c +xineplug_decode_mpc_la_SOURCES = $(internal_sources) xine_musepack_decoder.c xineplug_decode_mpc_la_CFLAGS = $(VISIBILITY_FLAG) -xineplug_decode_mpc_la_LDFLAGS = -avoid-version -module - +xineplug_decode_mpc_la_LDFLAGS = $(xineplug_ldflags) diff --git a/src/libmusepack/xine_decoder.c b/src/libmusepack/xine_decoder.c deleted file mode 100644 index 26c2eddf5..000000000 --- a/src/libmusepack/xine_decoder.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright (C) 2005 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * xine interface to libmusepack by James Stembridge - * - * TODO: - * 32bit float output - * Seeking?? - * - * $Id: xine_decoder.c,v 1.10 2007/01/19 02:35:36 dgp85 Exp $ - */ - -#include -#include -#include -#include -#include - -#define LOG_MODULE "mpc_decoder" -#define LOG_VERBOSE -/* -#define LOG -*/ - -#include "xine_internal.h" -#include "audio_out.h" -#include "buffer.h" -#include "xineutils.h" - -#ifdef HAVE_MPCDEC_MPCDEC_H -# include -#else -# include "musepack/musepack.h" -#endif - -#define MPC_DECODER_MEMSIZE 65536 -#define MPC_DECODER_MEMSIZE2 (MPC_DECODER_MEMSIZE/2) - -#define INIT_BUFSIZE (MPC_DECODER_MEMSIZE*2) - -typedef struct { - audio_decoder_class_t decoder_class; -} mpc_class_t; - -typedef struct mpc_decoder_s { - audio_decoder_t audio_decoder; - - xine_stream_t *stream; - - int sample_rate; /* audio sample rate */ - int bits_per_sample; /* bits/sample, usually 8 or 16 */ - int channels; /* 1 or 2, usually */ - - int output_open; /* flag to indicate audio is ready */ - - unsigned char *buf; /* data accumulation buffer */ - unsigned int buf_max; /* maximum size of buf */ - unsigned int read; /* size of accum. data already read */ - unsigned int size; /* size of accumulated data in buf */ - - mpc_reader reader; - mpc_streaminfo streaminfo; - mpc_decoder decoder; - - int decoder_ok; - unsigned int current_frame; - - int32_t file_size; - -} mpc_decoder_t; - - -/************************************************************************** - * musepack specific functions - *************************************************************************/ - -/* Reads size bytes of data into buffer at ptr. */ -static int32_t mpc_reader_read(void *data, void *ptr, int size) { - mpc_decoder_t *this = (mpc_decoder_t *) data; - - lprintf("mpc_reader_read: size=%d\n", size); - - /* Don't try to read more data than we have */ - if (size > (this->size - this->read)) - size = this->size - this->read; - - /* Copy the data */ - xine_fast_memcpy(ptr, &this->buf[this->read], size); - - /* Update our position in the data buffer */ - this->read += size; - - return size; -} - -/* Seeks to byte position offset. */ -static mpc_bool_t mpc_reader_seek(void *data, int32_t offset) { - mpc_decoder_t *this = (mpc_decoder_t *) data; - - lprintf("mpc_reader_seek: offset=%d\n", offset); - - /* seek is only called when reading the header so we can assume - * that the buffer starts at the start of the file */ - this->read = offset; - - return TRUE; -} - -/* Returns the current byte offset in the stream. */ -static int32_t mpc_reader_tell(void *data) { - lprintf("mpc_reader_tell\n"); - - /* Tell isn't used so just return 0 */ - return 0; -} - -/* Returns the total length of the source stream, in bytes. */ -static int32_t mpc_reader_get_size(void *data) { - mpc_decoder_t *this = (mpc_decoder_t *) data; - - lprintf("mpc_reader_get_size\n"); - - return this->file_size; -} - -/* True if the stream is a seekable stream. */ -static mpc_bool_t mpc_reader_canseek(void *data) { - lprintf("mpc_reader_canseek\n"); - - return TRUE; -} - -/* Convert 32bit float samples into 16bit int samples */ -static inline void float_to_int(float *_f, int16_t *s16, int samples) { - int i; - float f; - for (i = 0; i < samples; i++) { - f = _f[i] * 32767; - if (f > INT16_MAX) f = INT16_MAX; - if (f < INT16_MIN) f = INT16_MIN; - s16[i] = f; - /* printf("samples[%d] = %f, %d\n", i, _f[i], s16[num_channels*i]); */ - } -} - -/* Decode a musepack frame */ -static int mpc_decode_frame (mpc_decoder_t *this) { - float buffer[MPC_DECODER_BUFFER_LENGTH]; - uint32_t frames; - - lprintf("mpd_decode_frame\n"); - - frames = mpc_decoder_decode(&this->decoder, buffer, 0, 0); - - if (frames > 0) { - audio_buffer_t *audio_buffer; - int16_t *int_samples; - - lprintf("got %d samples\n", frames); - - /* Get audio buffer */ - audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); - audio_buffer->vpts = 0; - audio_buffer->num_frames = frames; - - /* Convert samples */ - int_samples = (int16_t *) audio_buffer->mem; - float_to_int(buffer, int_samples, frames*this->channels); - - /* Output converted samples */ - this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); - } - - return frames; -} - -/************************************************************************** - * xine audio plugin functions - *************************************************************************/ - -static void mpc_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { - mpc_decoder_t *this = (mpc_decoder_t *) this_gen; - int err; - - lprintf("mpc_decode_data\n"); - - if (!_x_stream_info_get(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED)) - return; - - /* We don't handle special buffers */ - if (buf->decoder_flags & BUF_FLAG_SPECIAL) - return; - - /* Read header */ - if (buf->decoder_flags & BUF_FLAG_HEADER) { - - lprintf("header\n"); - - /* File size is in decoder_info[0] */ - this->file_size = buf->decoder_info[0]; - - /* Initialise the data accumulation buffer */ - this->buf = xine_xmalloc(INIT_BUFSIZE); - this->buf_max = INIT_BUFSIZE; - this->read = 0; - this->size = 0; - - /* Initialise the reader */ - this->reader.read = mpc_reader_read; - this->reader.seek = mpc_reader_seek; - this->reader.tell = mpc_reader_tell; - this->reader.get_size = mpc_reader_get_size; - this->reader.canseek = mpc_reader_canseek; - this->reader.data = this; - - /* Copy header to buffer */ - xine_fast_memcpy(this->buf, buf->content, buf->size); - this->size = buf->size; - - /* Initialise and read stream info */ - mpc_streaminfo_init(&this->streaminfo); - - if ((err = mpc_streaminfo_read(&this->streaminfo, &this->reader))) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - _("libmusepack: mpc_streaminfo_read failed: %d\n"), err); - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); - return; - } - - this->sample_rate = this->streaminfo.sample_freq; - this->channels = this->streaminfo.channels; - this->bits_per_sample = 16; - - /* After the header the demuxer starts sending data from an offset - * of 28 bytes */ - this->size = 28; - - /* We need to keep track of the current frame so we now when we've - * reached the end of the stream */ - this->current_frame = 0; - - /* Setup the decoder */ - mpc_decoder_setup(&this->decoder, &this->reader); - this->decoder_ok = 0; - - /* Take this opportunity to initialize stream/meta information */ - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, - "Musepack (libmusepack)"); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, - (int) this->streaminfo.average_bitrate); - - return; - } - - lprintf("data: %u size=%u read=%u\n", buf->size, this->size, this->read); - - /* if the audio output is not open yet, open the audio output */ - if (!this->output_open) { - this->output_open = this->stream->audio_out->open( - this->stream->audio_out, - this->stream, - this->bits_per_sample, - this->sample_rate, - _x_ao_channels2mode(this->channels)); - } - - /* if the audio still isn't open, do not go any further with the decode */ - if (!this->output_open) - return; - - /* If we run out of space in our internal buffer we discard what's - * already been read */ - if (((this->size + buf->size) > this->buf_max) && this->read) { - lprintf("discarding read data\n"); - this->size -= this->read; - memmove(this->buf, &this->buf[this->read], this->size); - this->read = 0; - } - - /* If there still isn't space we have to increase the size of the - * internal buffer */ - if ((this->size + buf->size) > this->buf_max) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "libmusepack: increasing internal buffer size\n"); - this->buf_max += 2*buf->size; - this->buf = realloc(this->buf, this->buf_max); - } - - /* Copy data */ - xine_fast_memcpy(&this->buf[this->size], buf->content, buf->size); - this->size += buf->size; - - /* Time to decode */ - if (buf->decoder_flags & BUF_FLAG_FRAME_END) { - /* Increment frame count */ - if (this->current_frame++ == this->streaminfo.frames) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - _("libmusepack: data after last frame ignored\n")); - return; - } - - if (!this->decoder_ok) { - /* We require MPC_DECODER_MEMSIZE bytes to initialise the decoder */ - if ((this->size - this->read) >= MPC_DECODER_MEMSIZE) { - lprintf("initialise"); - - if (!mpc_decoder_initialize(&this->decoder, &this->streaminfo)) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - _("libmusepack: mpc_decoder_initialise failed\n")); - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); - return; - } - - this->decoder_ok = 1; - } else { - /* Not enough data yet */ - return; - } - } - - /* mpc_decoder_decode may cause a read of MPC_DECODER_MEMSIZE/2 bytes so - * make sure we have enough data available */ - if ((this->size - this->read) >= MPC_DECODER_MEMSIZE2) { - lprintf("decoding\n"); - - if ((err = mpc_decode_frame(this)) < 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - _("libmusepack: mpc_decoder_decode failed: %d\n"), err); - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); - return; - } - } - - /* If we are at the end of the stream we decode the remaining frames as we - * know we'll have enough data */ - if (this->current_frame == this->streaminfo.frames) { - lprintf("flushing buffers\n"); - - do { - if ((err = mpc_decode_frame(this)) < 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - _("libmusepack: mpc_decoder_decode failed: %d\n"), err); - } - } while (err > 0); - - lprintf("buffers flushed\n"); - } - } -} - -static void mpc_reset (audio_decoder_t *this_gen) { - mpc_decoder_t *this = (mpc_decoder_t *) this_gen; - - this->size = 0; - this->read = 0; -} - -static void mpc_discontinuity (audio_decoder_t *this_gen) { - /* mpc_decoder_t *this = (mpc_decoder_t *) this_gen; */ -} - -static void mpc_dispose (audio_decoder_t *this_gen) { - - mpc_decoder_t *this = (mpc_decoder_t *) this_gen; - - /* close the audio output */ - if (this->output_open) - this->stream->audio_out->close (this->stream->audio_out, this->stream); - this->output_open = 0; - - /* free anything that was allocated during operation */ - if (this->buf) - free(this->buf); - - free(this); -} - -static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) { - - mpc_decoder_t *this ; - - this = (mpc_decoder_t *) xine_xmalloc (sizeof (mpc_decoder_t)); - - /* connect the member functions */ - this->audio_decoder.decode_data = mpc_decode_data; - this->audio_decoder.reset = mpc_reset; - this->audio_decoder.discontinuity = mpc_discontinuity; - this->audio_decoder.dispose = mpc_dispose; - - /* connect the stream */ - this->stream = stream; - - /* audio output is not open at the start */ - this->output_open = 0; - - /* no buffer yet */ - this->buf = NULL; - - /* initialize the basic audio parameters */ - this->channels = 0; - this->sample_rate = 0; - this->bits_per_sample = 0; - - /* return the newly-initialized audio decoder */ - return &this->audio_decoder; -} - -static char *get_identifier (audio_decoder_class_t *this) { - return "mpc"; -} - -static char *get_description (audio_decoder_class_t *this) { - return "mpc: musepack audio decoder plugin"; -} - -static void dispose_class (audio_decoder_class_t *this_gen) { - - mpc_class_t *this = (mpc_class_t *)this_gen; - - free (this); -} - -static void *init_plugin (xine_t *xine, void *data) { - - mpc_class_t *this ; - - this = (mpc_class_t *) xine_xmalloc (sizeof (mpc_class_t)); - - this->decoder_class.open_plugin = open_plugin; - this->decoder_class.get_identifier = get_identifier; - this->decoder_class.get_description = get_description; - this->decoder_class.dispose = dispose_class; - - return this; -} - -static uint32_t audio_types[] = { - BUF_AUDIO_MPC, - 0 -}; - -static const decoder_info_t dec_info_audio = { - audio_types, /* supported types */ - 5 /* priority */ -}; - -const plugin_info_t xine_plugin_info[] EXPORTED = { - /* { type, API version, "name", version, special_info, init_function }, */ - { PLUGIN_AUDIO_DECODER, 15, "mpc", XINE_VERSION_CODE, &dec_info_audio, &init_plugin }, - { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; - diff --git a/src/libmusepack/xine_musepack_decoder.c b/src/libmusepack/xine_musepack_decoder.c new file mode 100644 index 000000000..26c2eddf5 --- /dev/null +++ b/src/libmusepack/xine_musepack_decoder.c @@ -0,0 +1,471 @@ +/* + * Copyright (C) 2005 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * xine interface to libmusepack by James Stembridge + * + * TODO: + * 32bit float output + * Seeking?? + * + * $Id: xine_decoder.c,v 1.10 2007/01/19 02:35:36 dgp85 Exp $ + */ + +#include +#include +#include +#include +#include + +#define LOG_MODULE "mpc_decoder" +#define LOG_VERBOSE +/* +#define LOG +*/ + +#include "xine_internal.h" +#include "audio_out.h" +#include "buffer.h" +#include "xineutils.h" + +#ifdef HAVE_MPCDEC_MPCDEC_H +# include +#else +# include "musepack/musepack.h" +#endif + +#define MPC_DECODER_MEMSIZE 65536 +#define MPC_DECODER_MEMSIZE2 (MPC_DECODER_MEMSIZE/2) + +#define INIT_BUFSIZE (MPC_DECODER_MEMSIZE*2) + +typedef struct { + audio_decoder_class_t decoder_class; +} mpc_class_t; + +typedef struct mpc_decoder_s { + audio_decoder_t audio_decoder; + + xine_stream_t *stream; + + int sample_rate; /* audio sample rate */ + int bits_per_sample; /* bits/sample, usually 8 or 16 */ + int channels; /* 1 or 2, usually */ + + int output_open; /* flag to indicate audio is ready */ + + unsigned char *buf; /* data accumulation buffer */ + unsigned int buf_max; /* maximum size of buf */ + unsigned int read; /* size of accum. data already read */ + unsigned int size; /* size of accumulated data in buf */ + + mpc_reader reader; + mpc_streaminfo streaminfo; + mpc_decoder decoder; + + int decoder_ok; + unsigned int current_frame; + + int32_t file_size; + +} mpc_decoder_t; + + +/************************************************************************** + * musepack specific functions + *************************************************************************/ + +/* Reads size bytes of data into buffer at ptr. */ +static int32_t mpc_reader_read(void *data, void *ptr, int size) { + mpc_decoder_t *this = (mpc_decoder_t *) data; + + lprintf("mpc_reader_read: size=%d\n", size); + + /* Don't try to read more data than we have */ + if (size > (this->size - this->read)) + size = this->size - this->read; + + /* Copy the data */ + xine_fast_memcpy(ptr, &this->buf[this->read], size); + + /* Update our position in the data buffer */ + this->read += size; + + return size; +} + +/* Seeks to byte position offset. */ +static mpc_bool_t mpc_reader_seek(void *data, int32_t offset) { + mpc_decoder_t *this = (mpc_decoder_t *) data; + + lprintf("mpc_reader_seek: offset=%d\n", offset); + + /* seek is only called when reading the header so we can assume + * that the buffer starts at the start of the file */ + this->read = offset; + + return TRUE; +} + +/* Returns the current byte offset in the stream. */ +static int32_t mpc_reader_tell(void *data) { + lprintf("mpc_reader_tell\n"); + + /* Tell isn't used so just return 0 */ + return 0; +} + +/* Returns the total length of the source stream, in bytes. */ +static int32_t mpc_reader_get_size(void *data) { + mpc_decoder_t *this = (mpc_decoder_t *) data; + + lprintf("mpc_reader_get_size\n"); + + return this->file_size; +} + +/* True if the stream is a seekable stream. */ +static mpc_bool_t mpc_reader_canseek(void *data) { + lprintf("mpc_reader_canseek\n"); + + return TRUE; +} + +/* Convert 32bit float samples into 16bit int samples */ +static inline void float_to_int(float *_f, int16_t *s16, int samples) { + int i; + float f; + for (i = 0; i < samples; i++) { + f = _f[i] * 32767; + if (f > INT16_MAX) f = INT16_MAX; + if (f < INT16_MIN) f = INT16_MIN; + s16[i] = f; + /* printf("samples[%d] = %f, %d\n", i, _f[i], s16[num_channels*i]); */ + } +} + +/* Decode a musepack frame */ +static int mpc_decode_frame (mpc_decoder_t *this) { + float buffer[MPC_DECODER_BUFFER_LENGTH]; + uint32_t frames; + + lprintf("mpd_decode_frame\n"); + + frames = mpc_decoder_decode(&this->decoder, buffer, 0, 0); + + if (frames > 0) { + audio_buffer_t *audio_buffer; + int16_t *int_samples; + + lprintf("got %d samples\n", frames); + + /* Get audio buffer */ + audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); + audio_buffer->vpts = 0; + audio_buffer->num_frames = frames; + + /* Convert samples */ + int_samples = (int16_t *) audio_buffer->mem; + float_to_int(buffer, int_samples, frames*this->channels); + + /* Output converted samples */ + this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); + } + + return frames; +} + +/************************************************************************** + * xine audio plugin functions + *************************************************************************/ + +static void mpc_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { + mpc_decoder_t *this = (mpc_decoder_t *) this_gen; + int err; + + lprintf("mpc_decode_data\n"); + + if (!_x_stream_info_get(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED)) + return; + + /* We don't handle special buffers */ + if (buf->decoder_flags & BUF_FLAG_SPECIAL) + return; + + /* Read header */ + if (buf->decoder_flags & BUF_FLAG_HEADER) { + + lprintf("header\n"); + + /* File size is in decoder_info[0] */ + this->file_size = buf->decoder_info[0]; + + /* Initialise the data accumulation buffer */ + this->buf = xine_xmalloc(INIT_BUFSIZE); + this->buf_max = INIT_BUFSIZE; + this->read = 0; + this->size = 0; + + /* Initialise the reader */ + this->reader.read = mpc_reader_read; + this->reader.seek = mpc_reader_seek; + this->reader.tell = mpc_reader_tell; + this->reader.get_size = mpc_reader_get_size; + this->reader.canseek = mpc_reader_canseek; + this->reader.data = this; + + /* Copy header to buffer */ + xine_fast_memcpy(this->buf, buf->content, buf->size); + this->size = buf->size; + + /* Initialise and read stream info */ + mpc_streaminfo_init(&this->streaminfo); + + if ((err = mpc_streaminfo_read(&this->streaminfo, &this->reader))) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + _("libmusepack: mpc_streaminfo_read failed: %d\n"), err); + + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); + return; + } + + this->sample_rate = this->streaminfo.sample_freq; + this->channels = this->streaminfo.channels; + this->bits_per_sample = 16; + + /* After the header the demuxer starts sending data from an offset + * of 28 bytes */ + this->size = 28; + + /* We need to keep track of the current frame so we now when we've + * reached the end of the stream */ + this->current_frame = 0; + + /* Setup the decoder */ + mpc_decoder_setup(&this->decoder, &this->reader); + this->decoder_ok = 0; + + /* Take this opportunity to initialize stream/meta information */ + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + "Musepack (libmusepack)"); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, + (int) this->streaminfo.average_bitrate); + + return; + } + + lprintf("data: %u size=%u read=%u\n", buf->size, this->size, this->read); + + /* if the audio output is not open yet, open the audio output */ + if (!this->output_open) { + this->output_open = this->stream->audio_out->open( + this->stream->audio_out, + this->stream, + this->bits_per_sample, + this->sample_rate, + _x_ao_channels2mode(this->channels)); + } + + /* if the audio still isn't open, do not go any further with the decode */ + if (!this->output_open) + return; + + /* If we run out of space in our internal buffer we discard what's + * already been read */ + if (((this->size + buf->size) > this->buf_max) && this->read) { + lprintf("discarding read data\n"); + this->size -= this->read; + memmove(this->buf, &this->buf[this->read], this->size); + this->read = 0; + } + + /* If there still isn't space we have to increase the size of the + * internal buffer */ + if ((this->size + buf->size) > this->buf_max) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "libmusepack: increasing internal buffer size\n"); + this->buf_max += 2*buf->size; + this->buf = realloc(this->buf, this->buf_max); + } + + /* Copy data */ + xine_fast_memcpy(&this->buf[this->size], buf->content, buf->size); + this->size += buf->size; + + /* Time to decode */ + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { + /* Increment frame count */ + if (this->current_frame++ == this->streaminfo.frames) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + _("libmusepack: data after last frame ignored\n")); + return; + } + + if (!this->decoder_ok) { + /* We require MPC_DECODER_MEMSIZE bytes to initialise the decoder */ + if ((this->size - this->read) >= MPC_DECODER_MEMSIZE) { + lprintf("initialise"); + + if (!mpc_decoder_initialize(&this->decoder, &this->streaminfo)) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + _("libmusepack: mpc_decoder_initialise failed\n")); + + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); + return; + } + + this->decoder_ok = 1; + } else { + /* Not enough data yet */ + return; + } + } + + /* mpc_decoder_decode may cause a read of MPC_DECODER_MEMSIZE/2 bytes so + * make sure we have enough data available */ + if ((this->size - this->read) >= MPC_DECODER_MEMSIZE2) { + lprintf("decoding\n"); + + if ((err = mpc_decode_frame(this)) < 0) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + _("libmusepack: mpc_decoder_decode failed: %d\n"), err); + + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); + return; + } + } + + /* If we are at the end of the stream we decode the remaining frames as we + * know we'll have enough data */ + if (this->current_frame == this->streaminfo.frames) { + lprintf("flushing buffers\n"); + + do { + if ((err = mpc_decode_frame(this)) < 0) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + _("libmusepack: mpc_decoder_decode failed: %d\n"), err); + } + } while (err > 0); + + lprintf("buffers flushed\n"); + } + } +} + +static void mpc_reset (audio_decoder_t *this_gen) { + mpc_decoder_t *this = (mpc_decoder_t *) this_gen; + + this->size = 0; + this->read = 0; +} + +static void mpc_discontinuity (audio_decoder_t *this_gen) { + /* mpc_decoder_t *this = (mpc_decoder_t *) this_gen; */ +} + +static void mpc_dispose (audio_decoder_t *this_gen) { + + mpc_decoder_t *this = (mpc_decoder_t *) this_gen; + + /* close the audio output */ + if (this->output_open) + this->stream->audio_out->close (this->stream->audio_out, this->stream); + this->output_open = 0; + + /* free anything that was allocated during operation */ + if (this->buf) + free(this->buf); + + free(this); +} + +static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) { + + mpc_decoder_t *this ; + + this = (mpc_decoder_t *) xine_xmalloc (sizeof (mpc_decoder_t)); + + /* connect the member functions */ + this->audio_decoder.decode_data = mpc_decode_data; + this->audio_decoder.reset = mpc_reset; + this->audio_decoder.discontinuity = mpc_discontinuity; + this->audio_decoder.dispose = mpc_dispose; + + /* connect the stream */ + this->stream = stream; + + /* audio output is not open at the start */ + this->output_open = 0; + + /* no buffer yet */ + this->buf = NULL; + + /* initialize the basic audio parameters */ + this->channels = 0; + this->sample_rate = 0; + this->bits_per_sample = 0; + + /* return the newly-initialized audio decoder */ + return &this->audio_decoder; +} + +static char *get_identifier (audio_decoder_class_t *this) { + return "mpc"; +} + +static char *get_description (audio_decoder_class_t *this) { + return "mpc: musepack audio decoder plugin"; +} + +static void dispose_class (audio_decoder_class_t *this_gen) { + + mpc_class_t *this = (mpc_class_t *)this_gen; + + free (this); +} + +static void *init_plugin (xine_t *xine, void *data) { + + mpc_class_t *this ; + + this = (mpc_class_t *) xine_xmalloc (sizeof (mpc_class_t)); + + this->decoder_class.open_plugin = open_plugin; + this->decoder_class.get_identifier = get_identifier; + this->decoder_class.get_description = get_description; + this->decoder_class.dispose = dispose_class; + + return this; +} + +static uint32_t audio_types[] = { + BUF_AUDIO_MPC, + 0 +}; + +static const decoder_info_t dec_info_audio = { + audio_types, /* supported types */ + 5 /* priority */ +}; + +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* { type, API version, "name", version, special_info, init_function }, */ + { PLUGIN_AUDIO_DECODER, 15, "mpc", XINE_VERSION_CODE, &dec_info_audio, &init_plugin }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; + -- cgit v1.2.3