diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/demuxers/Makefile.am | 3 | ||||
-rw-r--r-- | src/demuxers/demux_tta.c | 321 | ||||
-rw-r--r-- | src/demuxers/group_audio.c | 7 | ||||
-rw-r--r-- | src/demuxers/group_audio.h | 3 |
4 files changed, 331 insertions, 3 deletions
diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index 0c008946e..07996b2c7 100644 --- a/src/demuxers/Makefile.am +++ b/src/demuxers/Makefile.am @@ -130,7 +130,8 @@ xineplug_dmx_audio_la_SOURCES = group_audio.c demux_aud.c demux_aiff.c \ demux_realaudio.c demux_snd.c demux_voc.c \ demux_vox.c demux_wav.c demux_ac3.c id3.c \ demux_aac.c demux_mod.c demux_flac.c \ - demux_mpc.c demux_dts.c demux_shn.c + demux_mpc.c demux_dts.c demux_shn.c \ + demux_tta.c xineplug_dmx_audio_la_LIBADD = $(XINE_LIB) $(LIBMODPLUG_LIBS) xineplug_dmx_audio_la_LDFLAGS = -avoid-version -module diff --git a/src/demuxers/demux_tta.c b/src/demuxers/demux_tta.c new file mode 100644 index 000000000..111c38071 --- /dev/null +++ b/src/demuxers/demux_tta.c @@ -0,0 +1,321 @@ +/* + * Copyright (C) 2006 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 + * + * True Audio demuxer by Diego Pettenò <flameeyes@gentoo.org> + * Inspired by tta libavformat demuxer by Alex Beregszaszi + * + * $Id: demux_tta.c,v 1.1 2006/12/26 16:59:55 dgp85 Exp $ + */ + +#define LOG_MODULE "demux_tta" +#define LOG_VERBOSE + +#include "xine_internal.h" +#include "xineutils.h" +#include "demux.h" +#include "buffer.h" +#include "bswap.h" +#include "group_audio.h" + +typedef struct { + demux_plugin_t demux_plugin; + + xine_stream_t *stream; + fifo_buffer_t *video_fifo; + fifo_buffer_t *audio_fifo; + input_plugin_t *input; + int status; + + union { + struct tta_header { + uint32_t signature; /* TTA1 */ + uint16_t flags; /* Skipped */ + uint16_t channels; + uint16_t bits_per_sample; + uint32_t samplerate; + uint32_t data_length; + uint32_t crc32; + } __attribute__((__packed__)) tta; + uint8_t buffer[22]; /* This is the size of the header */ + } header; + + uint32_t totalframes; + uint32_t currentframe; + uint32_t *seektable; +} demux_tta_t; + +typedef struct { + demux_class_t demux_class; +} demux_tta_class_t; + +#define FOURCC_32(a, b, c, d) (d + (c<<8) + (b<<16) + (a<<24)) + +static int open_tta_file(demux_tta_t *this) { + uint8_t peek[4]; + uint32_t framelen; int i; + + if (_x_demux_read_header(this->input, peek, 4) != 4) + return 0; + + if ( BE_32(peek) != FOURCC_32('T', 'T', 'A', '1') ) + return 0; + + if ( this->input->read(this->input, this->header.buffer, sizeof(this->header)) != sizeof(this->header) ) + return 0; + + framelen = 1.04489795918367346939 * le2me_32(this->header.tta.samplerate); + this->totalframes = le2me_32(this->header.tta.data_length) / framelen + ((le2me_32(this->header.tta.data_length) % framelen) ? 1 : 0); + this->currentframe = 0; + + if(this->totalframes >= UINT_MAX/sizeof(uint32_t)) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, _("demux_tta: total frames count too high\n")); + return 0; + } + + this->seektable = xine_xmalloc(sizeof(uint32_t)*this->totalframes); + this->input->read(this->input, this->seektable, sizeof(uint32_t)*this->totalframes); + + /* Skip the CRC32 */ + this->input->seek(this->input, 4, SEEK_CUR); + + return 1; +} + +static int demux_tta_send_chunk(demux_plugin_t *this_gen) { + demux_tta_t *this = (demux_tta_t *) this_gen; + uint32_t bytes_to_read; + + if ( this->currentframe > this->totalframes ) { + this->status = DEMUX_FINISHED; + return this->status; + } + + bytes_to_read = le2me_32(this->seektable[this->currentframe]); + + while(bytes_to_read) { + off_t bytes_read = 0; + buf_element_t *buf = NULL; + + /* Get a buffer */ + buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo); + buf->type = BUF_AUDIO_TTA; + buf->pts = 0; + buf->extra_info->total_time = this->totalframes; + buf->decoder_flags = 0; + + /* Set normalised position */ + buf->extra_info->input_normpos = + (int) ((double) this->currentframe * 65535 / this->totalframes); + + /* Set time */ + /* buf->extra_info->input_time = this->current_sample / this->samplerate; */ + + bytes_read = this->input->read(this->input, buf->content, ( bytes_to_read > buf->max_size ) ? buf->max_size : bytes_to_read); + + buf->size = bytes_read; + + bytes_to_read -= bytes_read; + + if ( bytes_to_read <= 0 ) + buf->decoder_flags |= BUF_FLAG_FRAME_END; + + this->audio_fifo->put(this->audio_fifo, buf); + } + + this->currentframe++; + + return this->status; +} + +static void demux_tta_send_headers(demux_plugin_t *this_gen) { + demux_tta_t *this = (demux_tta_t *) this_gen; + buf_element_t *buf; + + this->audio_fifo = this->stream->audio_fifo; + + this->status = DEMUX_OK; + + _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 0); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_CHANNELS, + le2me_16(this->header.tta.channels)); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, + le2me_32(this->header.tta.samplerate)); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITS, + le2me_16(this->header.tta.bits_per_sample)); + + /* send start buffers */ + _x_demux_control_start(this->stream); + + /* send init info to decoders */ + if (this->audio_fifo) { + xine_waveformatex wave; + + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_AUDIO_TTA; + buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; + buf->decoder_info[0] = 0; + buf->decoder_info[1] = le2me_32(this->header.tta.samplerate); + buf->decoder_info[2] = le2me_16(this->header.tta.bits_per_sample); + buf->decoder_info[3] = le2me_16(this->header.tta.channels); + + buf->size = sizeof(xine_waveformatex) + sizeof(this->header) + sizeof(uint32_t)*this->totalframes; + memcpy(buf->content+sizeof(xine_waveformatex), this->header.buffer, sizeof(this->header)); + memcpy(buf->content+sizeof(xine_waveformatex)+sizeof(this->header), this->seektable, sizeof(uint32_t)*this->totalframes); + + wave.cbSize = buf->size - sizeof(xine_waveformatex); + memcpy(buf->content, &wave, sizeof(wave)); + + this->audio_fifo->put (this->audio_fifo, buf); + } +} + +static int demux_tta_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time, int playing) { + demux_tta_t *this = (demux_tta_t *) this_gen; + + /* if thread is not running, initialize demuxer */ + if( !playing ) { + + /* send new pts */ + _x_demux_control_newpts(this->stream, 0, 0); + + this->status = DEMUX_OK; + } + + return this->status; +} + +static void demux_tta_dispose (demux_plugin_t *this_gen) { + demux_tta_t *this = (demux_tta_t *) this_gen; + + free(this); +} + +static int demux_tta_get_status (demux_plugin_t *this_gen) { + demux_tta_t *this = (demux_tta_t *) this_gen; + + return this->status; +} + +static int demux_tta_get_stream_length (demux_plugin_t *this_gen) { +// demux_tta_t *this = (demux_tta_t *) this_gen; + + return 0; +} + +static uint32_t demux_tta_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_tta_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + +static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, + input_plugin_t *input) { + + demux_tta_t *this; + + this = xine_xmalloc (sizeof (demux_tta_t)); + this->stream = stream; + this->input = input; + + this->demux_plugin.send_headers = demux_tta_send_headers; + this->demux_plugin.send_chunk = demux_tta_send_chunk; + this->demux_plugin.seek = demux_tta_seek; + this->demux_plugin.dispose = demux_tta_dispose; + this->demux_plugin.get_status = demux_tta_get_status; + this->demux_plugin.get_stream_length = demux_tta_get_stream_length; + this->demux_plugin.get_capabilities = demux_tta_get_capabilities; + this->demux_plugin.get_optional_data = demux_tta_get_optional_data; + this->demux_plugin.demux_class = class_gen; + + this->status = DEMUX_FINISHED; + + this->seektable = NULL; + + switch (stream->content_detection_method) { + + case METHOD_BY_EXTENSION: { + char *extensions, *mrl; + + mrl = input->get_mrl (input); + extensions = class_gen->get_extensions (class_gen); + + if (!_x_demux_check_extension (mrl, extensions)) { + free (this); + return NULL; + } + } + /* Falling through is intended */ + + case METHOD_BY_CONTENT: + case METHOD_EXPLICIT: + if (!open_tta_file(this)) { + free (this); + return NULL; + } + break; + + default: + free (this); + return NULL; + } + + return &this->demux_plugin; +} + +static char *get_description (demux_class_t *this_gen) { + return "True Audio demux plugin"; +} + +static char *get_identifier (demux_class_t *this_gen) { + return "True Audio"; +} + +static char *get_extensions (demux_class_t *this_gen) { + return "tta"; +} + +static char *get_mimetypes (demux_class_t *this_gen) { + return NULL; +} + +static void class_dispose (demux_class_t *this_gen) { + demux_tta_class_t *this = (demux_tta_class_t *) this_gen; + + free (this); +} + +void *demux_tta_init_plugin (xine_t *xine, void *data) { + demux_tta_class_t *this; + + this = xine_xmalloc (sizeof (demux_tta_class_t)); + + this->demux_class.open_plugin = open_plugin; + this->demux_class.get_description = get_description; + this->demux_class.get_identifier = get_identifier; + this->demux_class.get_mimetypes = get_mimetypes; + this->demux_class.get_extensions = get_extensions; + this->demux_class.dispose = class_dispose; + + return this; +} diff --git a/src/demuxers/group_audio.c b/src/demuxers/group_audio.c index 7139ee5b9..bd8a291bb 100644 --- a/src/demuxers/group_audio.c +++ b/src/demuxers/group_audio.c @@ -19,7 +19,7 @@ * * This file contains plugin entries for several demuxers used in games * - * $Id: group_audio.c,v 1.24 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: group_audio.c,v 1.25 2006/12/26 16:59:55 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -87,6 +87,10 @@ static const demuxer_info_t demux_info_snd = { 10 /* priority */ }; +static const demuxer_info_t demux_info_tta = { + 10 /* priority */ +}; + static const demuxer_info_t demux_info_voc = { 10 /* priority */ }; @@ -120,6 +124,7 @@ const plugin_info_t xine_plugin_info[] EXPORTED = { { PLUGIN_DEMUX, 26, "realaudio", XINE_VERSION_CODE, &demux_info_realaudio, demux_realaudio_init_plugin }, { PLUGIN_DEMUX, 26, "shn", XINE_VERSION_CODE, &demux_info_shn, demux_shn_init_plugin }, { PLUGIN_DEMUX, 26, "snd", XINE_VERSION_CODE, &demux_info_snd, demux_snd_init_plugin }, + { PLUGIN_DEMUX, 26, "tta", XINE_VERSION_CODE, &demux_info_tta, demux_tta_init_plugin }, { PLUGIN_DEMUX, 26, "voc", XINE_VERSION_CODE, &demux_info_voc, demux_voc_init_plugin }, { PLUGIN_DEMUX, 26, "vox", XINE_VERSION_CODE, &demux_info_vox, demux_vox_init_plugin }, { PLUGIN_DEMUX, 26, "wav", XINE_VERSION_CODE, &demux_info_wav, demux_wav_init_plugin }, diff --git a/src/demuxers/group_audio.h b/src/demuxers/group_audio.h index fba22cffa..7f1fccc5e 100644 --- a/src/demuxers/group_audio.h +++ b/src/demuxers/group_audio.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: group_audio.h,v 1.8 2005/05/29 19:20:48 jstembridge Exp $ + * $Id: group_audio.h,v 1.9 2006/12/26 16:59:55 dgp85 Exp $ */ #ifndef HAVE_GROUP_AUDIO_H @@ -38,6 +38,7 @@ void *demux_nsf_init_plugin (xine_t *xine, void *data); void *demux_realaudio_init_plugin (xine_t *xine, void *data); void *demux_shn_init_plugin (xine_t *xine, void *data); void *demux_snd_init_plugin (xine_t *xine, void *data); +void *demux_tta_init_plugin (xine_t *xine, void *data); void *demux_voc_init_plugin (xine_t *xine, void *data); void *demux_vox_init_plugin (xine_t *xine, void *data); void *demux_wav_init_plugin (xine_t *xine, void *data); |