diff options
Diffstat (limited to 'src/libmusepack/xine_musepack_decoder.c')
-rw-r--r-- | src/libmusepack/xine_musepack_decoder.c | 547 |
1 files changed, 0 insertions, 547 deletions
diff --git a/src/libmusepack/xine_musepack_decoder.c b/src/libmusepack/xine_musepack_decoder.c deleted file mode 100644 index 52973c751..000000000 --- a/src/libmusepack/xine_musepack_decoder.c +++ /dev/null @@ -1,547 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * xine interface to libmusepack by James Stembridge <jstembridge@gmail.com> - * - * TODO: - * 32bit float output - * Seeking?? - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <unistd.h> - -#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 <mpcdec/mpcdec.h> -#elif defined(HAVE_MPC_MPCDEC_H) -# include <mpc/mpcdec.h> -#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; -#ifndef HAVE_MPC_MPCDEC_H - mpc_decoder decoder; -#else - mpc_demux *decoder; -#endif - - 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. */ -#ifndef HAVE_MPC_MPCDEC_H -static int32_t mpc_reader_read(void *data, void *ptr, int size) { - mpc_decoder_t *this = (mpc_decoder_t *) data; -#else -static int32_t mpc_reader_read(mpc_reader *data, void *ptr, int size) { - mpc_decoder_t *this = (mpc_decoder_t *) data->data; -#endif - - 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. */ -#ifndef HAVE_MPC_MPCDEC_H -static mpc_bool_t mpc_reader_seek(void *data, int32_t offset) { - mpc_decoder_t *this = (mpc_decoder_t *) data; -#else -static mpc_bool_t mpc_reader_seek(mpc_reader *data, int32_t offset) { - mpc_decoder_t *this = (mpc_decoder_t *) data->data; -#endif - - 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; - -#ifndef HAVE_MPC_MPCDEC_H - return TRUE; -#else - return MPC_TRUE; -#endif -} - -/* Returns the current byte offset in the stream. */ -#ifndef HAVE_MPC_MPCDEC_H -static int32_t mpc_reader_tell(void *data) { -#else -static int32_t mpc_reader_tell(mpc_reader *data) { -#endif - 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. */ -#ifndef HAVE_MPC_MPCDEC_H -static int32_t mpc_reader_get_size(void *data) { - mpc_decoder_t *this = (mpc_decoder_t *) data; -#else -static int32_t mpc_reader_get_size(mpc_reader *data) { - mpc_decoder_t *this = (mpc_decoder_t *) data->data; -#endif - - lprintf("mpc_reader_get_size\n"); - - return this->file_size; -} - -/* True if the stream is a seekable stream. */ -#ifndef HAVE_MPC_MPCDEC_H -static mpc_bool_t mpc_reader_canseek(void *data) { - lprintf("mpc_reader_canseek\n"); - - return TRUE; -#else -static mpc_bool_t mpc_reader_canseek(mpc_reader *data) { - - lprintf("mpc_reader_canseek\n"); - return MPC_TRUE; -#endif -} - -/* 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; -#ifdef HAVE_MPC_MPCDEC_H - mpc_frame_info frame; -#endif - - lprintf("mpd_decode_frame\n"); - -#ifndef HAVE_MPC_MPCDEC_H - frames = mpc_decoder_decode(&this->decoder, buffer, 0, 0); -#else - frame.buffer = buffer; - mpc_demux_decode(this->decoder, &frame); - frames = frame.samples; -#endif - - 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 = calloc(1, 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; - -#ifdef HAVE_MPC_MPCDEC_H - this->decoder = mpc_demux_init(&this->reader); - if (!this->decoder) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - _("libmusepack: mpc_demux_init failed.\n")); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); - return; - } - mpc_demux_get_info(this->decoder, &this->streaminfo); -#else - /* 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; - } -#endif - - 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 */ -#ifndef HAVE_MPC_MPCDEC_H - mpc_decoder_setup(&this->decoder, &this->reader); -#endif - 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 */ -#ifndef HAVE_MPC_MPCDEC_H - if (this->current_frame++ == this->streaminfo.frames) { -#else - if (this->current_frame++ == this->streaminfo.samples) { -#endif - 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"); - -#ifndef HAVE_MPC_MPCDEC_H - if (!mpc_decoder_initialize(&this->decoder, &this->streaminfo)) { -#else - if (!this->decoder) { -#endif - 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 */ -#ifndef HAVE_MPC_MPCDEC_H - if (this->current_frame == this->streaminfo.frames) { -#else - if (this->current_frame == this->streaminfo.samples) { -#endif - 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); -#ifdef HAVE_MPC_MPCDEC_H - if (this->decoder) - mpc_demux_exit(this->decoder); -#endif - - 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 *) calloc(1, 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 *) calloc(1, 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 } -}; - |