From 91662bdf80f304b6f8e987a19899738af106172a Mon Sep 17 00:00:00 2001 From: Guenter Bartsch Date: Sun, 25 May 2003 13:39:13 +0000 Subject: speex support contributed by Conrad Parker CVS patchset: 4926 CVS date: 2003/05/25 13:39:13 --- AUTHORS | 3 + ChangeLog | 3 +- configure.ac | 17 +- m4/Makefile.am | 1 + m4/speex.m4 | 90 ++++++++ src/Makefile.am | 1 + src/demuxers/Makefile.am | 2 +- src/demuxers/demux_ogg.c | 74 ++++++- src/libspeex/Makefile.am | 34 +++ src/libspeex/xine_decoder.c | 462 +++++++++++++++++++++++++++++++++++++++++ src/xine-engine/buffer.h | 3 +- src/xine-engine/buffer_types.c | 9 +- 12 files changed, 687 insertions(+), 12 deletions(-) create mode 100644 m4/speex.m4 create mode 100644 src/libspeex/Makefile.am create mode 100644 src/libspeex/xine_decoder.c diff --git a/AUTHORS b/AUTHORS index 5fe02aaec..62c81e325 100644 --- a/AUTHORS +++ b/AUTHORS @@ -383,4 +383,7 @@ Tim Champagne Matthew Grooms msvc win32 port +Conrad Parker + speex support + (let us know if we've forgotten anyone) diff --git a/ChangeLog b/ChangeLog index 47d248437..ec369476b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,7 +14,8 @@ xine-lib (1-beta13) (23.976, 59.94 and 60 fps) * move http proxy configuration to xine itself * add expand post video filter for displaying subtitles in borders - + * speex (http://www.speex.org) audio decoder support + xine-lib (1-beta12) * enabled SVQ3 video decoding via ffmpeg * playback of theorastreams added diff --git a/configure.ac b/configure.ac index a4e199a28..46d146135 100644 --- a/configure.ac +++ b/configure.ac @@ -41,7 +41,7 @@ dnl for a release tarball do "rm .cvsversion" before "make dist" if test -f .cvsversion; then XINE_PRE="cvs" else - XINE_PRE="beta12" + XINE_PRE="beta13" fi AC_SUBST(XINE_MAJOR) @@ -625,6 +625,17 @@ AM_PATH_OGG( AC_MSG_RESULT([*** All of OGG/Theora dependent parts will be disabled ***])) AM_CONDITIONAL(HAVE_THEORA, [test x"$no_ogg" != "xyes" -a x"$no_theora" != "xyes"]) +dnl --------------------------------------------- +dnl Ogg/Speex libs. +dnl --------------------------------------------- + +AM_PATH_OGG( + [ AM_PATH_SPEEX(AC_DEFINE(HAVE_SPEEX,1,[Define this if you have speex]), + AC_MSG_RESULT([*** All OGG/SPEEX dependent parts will be disabled ***])) + ], + AC_MSG_RESULT([*** All of OGG/Speex dependent parts will be disabled ***])) +AM_CONDITIONAL(HAVE_SPEEX, [test x"$no_ogg" != "xyes" -a x"$no_speex" != "xyes"]) + dnl --------------------------------------------- dnl check for libFLAC dnl --------------------------------------------- @@ -1364,6 +1375,7 @@ src/libspucc/Makefile src/libsputext/Makefile src/libvorbis/Makefile src/libtheora/Makefile +src/libspeex/Makefile src/libw32dll/Makefile src/libw32dll/wine/Makefile src/libw32dll/DirectShow/Makefile @@ -1511,6 +1523,9 @@ echo " - nosefart" if test x"$no_vorbis" != "xyes"; then echo " - vorbis" fi +if test x"$no_speex" != "xyes"; then + echo " - speex" +fi if test x"$enable_w32dll" = "xyes"; then echo " - w32dll" fi diff --git a/m4/Makefile.am b/m4/Makefile.am index 128058997..f01b7e597 100644 --- a/m4/Makefile.am +++ b/m4/Makefile.am @@ -29,6 +29,7 @@ EXTRA_DIST = \ progtest.m4 \ sdl.m4 \ vorbis.m4 \ + speex.m4 \ theora.m4 \ xine.m4 \ _xine.m4 \ diff --git a/m4/speex.m4 b/m4/speex.m4 new file mode 100644 index 000000000..e3f1b9556 --- /dev/null +++ b/m4/speex.m4 @@ -0,0 +1,90 @@ +# Configure paths for libspeex +# Jack Moffitt 10-21-2000 +# Shamelessly stolen from Owen Taylor and Manish Singh + +dnl AM_PATH_SPEEX([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Test for libspeex, and define SPEEX_CFLAGS and SPEEX_LIBS +dnl +AC_DEFUN([AM_PATH_SPEEX], +[dnl +dnl Get the cflags and libraries +dnl +AC_ARG_WITH(speex-prefix,[ --with-speex-prefix=PFX Prefix where libspeex is installed (optional)], speex_prefix="$withval", speex_prefix="") +AC_ARG_ENABLE(speextest, [ --disable-speextest Do not try to compile and run a test Speex program],, enable_speextest=yes) + + if test x$speex_prefix != x ; then + speex_args="$speex_args --prefix=$speex_prefix" + SPEEX_CFLAGS="-I$speex_prefix/include" + SPEEX_LIBDIR="-L$speex_prefix/lib" + fi + + SPEEX_LIBS="$SPEEX_LIBDIR -lspeex -lm" + + AC_MSG_CHECKING(for Speex) + no_speex="" + + + if test "x$enable_speextest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $SPEEX_CFLAGS" + LIBS="$LIBS $SPEEX_LIBS $OGG_LIBS" +dnl +dnl Now check if the installed Speex is sufficiently new. +dnl + rm -f conf.speextest + AC_TRY_RUN([ +#include +#include +#include +#include + +int main () +{ + system("touch conf.speextest"); + return 0; +} + +],, no_speex=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + + if test "x$no_speex" = x ; then + AC_MSG_RESULT(yes) + ifelse([$1], , :, [$1]) + else + AC_MSG_RESULT(no) + if test -f conf.speextest ; then + : + else + echo "*** Could not run Speex test program, checking why..." + CFLAGS="$CFLAGS $SPEEX_CFLAGS" + LIBS="$LIBS $SPEEX_LIBS $OGG_LIBS" + AC_TRY_LINK([ +#include +#include +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding Speex or finding the wrong" + echo "*** version of Speex. If it is not finding Speex, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means Speex was incorrectly installed" + echo "*** or that you have moved Speex since it was installed." ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + SPEEX_CFLAGS="" + SPEEX_LIBS="" + ifelse([$2], , :, [$2]) + fi + AC_SUBST(SPEEX_CFLAGS) + AC_SUBST(SPEEX_LIBS) + rm -f conf.speextest +]) diff --git a/src/Makefile.am b/src/Makefile.am index 6ee20c116..8a88ad77b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -27,6 +27,7 @@ SUBDIRS = \ libxineadec \ libvorbis \ libtheora \ + libspeex \ libreal \ libfaad \ libflac \ diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index b6bdde3ee..d5c4404bd 100644 --- a/src/demuxers/Makefile.am +++ b/src/demuxers/Makefile.am @@ -46,7 +46,7 @@ lib_LTLIBRARIES = $(ogg_module) $(asf_module) $(mng_module) $(image_module) \ xineplug_dmx_nsv.la xineplug_dmx_ogg_la_SOURCES = demux_ogg.c -xineplug_dmx_ogg_la_LIBADD = $(OGG_LIBS) $(VORBIS_LIBS) $(THEORA_LIBS) $(XINE_LIB) +xineplug_dmx_ogg_la_LIBADD = $(OGG_LIBS) $(VORBIS_LIBS) $(SPEEX_LIBS) $(THEORA_LIBS) $(XINE_LIB) xineplug_dmx_ogg_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ xineplug_dmx_avi_la_SOURCES = demux_avi.c diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c index a3cb38060..78c5fa532 100644 --- a/src/demuxers/demux_ogg.c +++ b/src/demuxers/demux_ogg.c @@ -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: demux_ogg.c,v 1.100 2003/05/12 19:44:35 heinchen Exp $ + * $Id: demux_ogg.c,v 1.101 2003/05/25 13:39:14 guenter Exp $ * * demultiplexer for ogg streams * @@ -38,6 +38,13 @@ #include #include +#ifdef HAVE_SPEEX +#include +#include +#include +#include +#endif + #ifdef HAVE_THEORA #include #endif @@ -181,7 +188,7 @@ static int read_ogg_packet (demux_ogg_t *this) { buffer = ogg_sync_buffer(&this->oy, CHUNKSIZE); bytes = this->input->read(this->input, buffer, CHUNKSIZE); ogg_sync_wrote(&this->oy, bytes); - if (bytes < CHUNKSIZE) { + if (bytes < CHUNKSIZE/2) { return 0; } } @@ -369,6 +376,9 @@ static void send_ogg_buf (demux_ogg_t *this, og_ghost->packet = buf->content + op_size; buf->size = op->bytes; + } else if ((this->buf_types[stream_num] & 0xFFFF0000) == BUF_AUDIO_SPEEX) { + memcpy (buf->content, op->packet, op->bytes); + buf->size = op->bytes; } else { memcpy (buf->content, op->packet+1+hdrlen, op->bytes-1-hdrlen); buf->size = op->bytes-1-hdrlen; @@ -386,7 +396,7 @@ static void send_ogg_buf (demux_ogg_t *this, buf->pts = 0; #ifdef LOG - printf ("demuxogg: audiostream %d op-gpos %lld hdr-gpos %lld pts %lld \n" + printf ("demux_ogg: audiostream %d op-gpos %lld hdr-gpos %lld pts %lld \n" ,stream_num ,op->granulepos ,this->header_granulepos[stream_num] @@ -648,6 +658,54 @@ static void demux_ogg_send_header (demux_ogg_t *this) { } vorbis_comment_clear(&vc); vorbis_info_clear(&vi); + } else if (!strncmp (&op.packet[0], "Speex", 5)) { + +#ifdef HAVE_SPEEX + void * st; + SpeexMode * mode; + SpeexHeader * header; + + this->buf_types[stream_num] = BUF_AUDIO_SPEEX + +this->num_audio_streams++; + + this->preview_buffers[stream_num] = 1; + + header = speex_packet_to_header (op.packet, op.bytes); + + if (header) { + int bitrate; + mode = speex_mode_list[header->mode]; + + st = speex_decoder_init (mode); + + speex_decoder_ctl (st, SPEEX_GET_BITRATE, &bitrate); + + if (bitrate <= 1) + bitrate = 16000; /* assume 16 kbit */ + + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE] + = bitrate; + + this->factor[stream_num] = 90000; + this->quotient[stream_num] = header->rate; + + this->avg_bitrate += bitrate; + +#ifdef LOG + printf ("demux_ogg: detected Speex stream,\trate %d\tbitrate %d\n", + header->rate, bitrate); +#endif + + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] + = header->rate; + + this->preview_buffers[stream_num] += header->extra_headers; + } +#else + printf ("demux_ogg: Speex stream detected, unable to play\n"); + + this->buf_types[stream_num] = BUF_CONTROL_NOP; +#endif } else if (!strncmp (&op.packet[1], "video", 5)) { buf_element_t *buf; @@ -1135,7 +1193,7 @@ static void demux_ogg_send_content (demux_ogg_t *this) { /* printf("demux_ogg: packet: %.8s\n", op.packet); */ /* printf("demux_ogg: got a packet\n"); */ - if ((*op.packet & PACKET_TYPE_HEADER) && (this->buf_types[stream_num]!=BUF_VIDEO_THEORA)) { + if ((*op.packet & PACKET_TYPE_HEADER) && (this->buf_types[stream_num]!=BUF_VIDEO_THEORA) && (this->buf_types[stream_num]!=BUF_AUDIO_SPEEX)) { if (op.granulepos!=-1) { this->header_granulepos[stream_num]=op.granulepos; #ifdef LOG @@ -1487,7 +1545,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, return NULL; if (strncasecmp(ending, ".ogg", 4) && - strncasecmp(ending, ".ogm", 4)) { + strncasecmp(ending, ".ogm", 4) && + strncasecmp(ending, ".spx", 4)) { return NULL; } @@ -1542,12 +1601,13 @@ static char *get_identifier (demux_class_t *this_gen) { } static char *get_extensions (demux_class_t *this_gen) { - return "ogg ogm"; + return "ogg ogm spx"; } static char *get_mimetypes (demux_class_t *this_gen) { return "audio/x-ogg: ogg: OggVorbis Audio;" - "application/x-ogg: ogg: OggVorbis Audio;"; + "audio/x-speex: ogg: Speex Audio;" + "application/x-ogg: ogg: OggVorbis Audio;"; } static void class_dispose (demux_class_t *this_gen) { diff --git a/src/libspeex/Makefile.am b/src/libspeex/Makefile.am new file mode 100644 index 000000000..627f14f65 --- /dev/null +++ b/src/libspeex/Makefile.am @@ -0,0 +1,34 @@ +## +## Process this file with automake to produce Makefile.in +## + +AM_CFLAGS = $(SPEEX_CFLAGS) + +LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic + +libdir = $(XINE_PLUGINDIR) + +if HAVE_SPEEX +speex_module = xineplug_decode_speex.la +endif + +lib_LTLIBRARIES = $(speex_module) + +xineplug_decode_speex_la_SOURCES = xine_decoder.c +xineplug_decode_speex_la_LIBADD = $(SPEEX_LIBS) +xineplug_decode_speex_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ + +debug: +# @$(MAKE) CFLAGS="$(DEBUG_CFLAGS) $(OGG_CFLAGS) $(SPEEX_CFLAGS)" + @$(MAKE) CFLAGS="$(DEBUG_CFLAGS)" + +install-debug: debug + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +mostlyclean-generic: + -rm -f *~ \#* .*~ .\#* + +maintainer-clean-generic: + -@echo "This command is intended for maintainers to use;" + -@echo "it deletes files that may require special tools to rebuild." + -rm -f Makefile.in diff --git a/src/libspeex/xine_decoder.c b/src/libspeex/xine_decoder.c new file mode 100644 index 000000000..5f3584d22 --- /dev/null +++ b/src/libspeex/xine_decoder.c @@ -0,0 +1,462 @@ +/* + * Copyright (C) 2000-2002 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 + * + * $Id: xine_decoder.c,v 1.1 2003/05/25 13:39:14 guenter Exp $ + * + * (ogg/)speex audio decoder plugin (libspeex wrapper) for xine + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "xine_internal.h" +#include "audio_out.h" +#include "buffer.h" + +#include +#include +#include +#include +#include + +#define MAX_FRAME_SIZE 2000 + +/* +#define LOG +*/ + +typedef struct { + audio_decoder_class_t decoder_class; +} speex_class_t; + +typedef struct speex_decoder_s { + audio_decoder_t audio_decoder; + + int64_t pts; + + int output_sampling_rate; + int output_open; + int output_mode; + + /* speex stuff */ + void *st; + int frame_size; + int rate; + int nframes; + int channels; + SpeexBits bits; + SpeexStereoState stereo; + int expect_metadata; + + float output[MAX_FRAME_SIZE]; + + int header_count; + + xine_stream_t *stream; + +} speex_decoder_t; + + +static void speex_reset (audio_decoder_t *this_gen) { + + speex_decoder_t *this = (speex_decoder_t *) this_gen; + + speex_bits_init (&this->bits); +} + +static void speex_discontinuity (audio_decoder_t *this_gen) { + + speex_decoder_t *this = (speex_decoder_t *) this_gen; + + this->pts=0; +} + +/* Known speex comment keys from ogg123 sources*/ +static struct { + char *key; /* includes the '=' for programming convenience */ + int xine_metainfo_index; +} speex_comment_keys[] = { + {"ARTIST=", XINE_META_INFO_ARTIST}, + {"ALBUM=", XINE_META_INFO_ALBUM}, + {"TITLE=", XINE_META_INFO_TITLE}, + {"GENRE=", XINE_META_INFO_GENRE}, + {"DESCRIPTION=", XINE_META_INFO_COMMENT}, + {"DATE=", XINE_META_INFO_YEAR}, + {NULL, 0} +}; + +#define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \ + ((buf[base+2]<<16)&0xff0000)| \ + ((buf[base+1]<<8)&0xff00)| \ + (buf[base]&0xff)) + +static +void read_metadata (speex_decoder_t *this, char * comments, int length) +{ + char * c = comments; + int len, i, nb_fields; + char * end; + + this->stream->meta_info[XINE_META_INFO_AUDIOCODEC] = strdup ("speex"); + + if (length < 8) { + printf ("libspeex: invalid/corrupted comments\n"); + return; + } + + end = c+length; + len = readint (c, 0); + c += 4; + + if (c+len > end) { + printf ("libspeex: invalid/corrupted comments\n"); + return; + } + +#ifdef LOG + /* Encoder */ + printf ("libspeex: "); + fwrite (c, 1, len, stdout); + printf ("\n"); +#endif + + c += len; + + if (c+4 > end) { + printf ("libspeex: invalid/corrupted comments\n"); + return; + } + + nb_fields = readint (c, 0); + c += 4; + + for (i = 0; i < nb_fields; i++) { + if (c+4 > end) { + printf ("libspeex: invalid/corrupted comments\n"); + return; + } + + len = readint (c, 0); + c += 4; + if (c+len > end) { + printf ("libspeex: invalid/corrupted comments\n"); + return; + } + +#ifdef LOG + printf ("libspeex: "); + fwrite (c, 1, len, stdout); + printf ("\n"); +#endif + + for (i = 0; speex_comment_keys[i].key != NULL; i++) { + + if ( !strncasecmp (speex_comment_keys[i].key, c, + strlen(speex_comment_keys[i].key)) ) { + int keylen = strlen(speex_comment_keys[i].key); + char * meta_info; + +#ifdef LOG + printf ("libspeex: known metadata %d %d\n", + i, speex_comment_keys[i].xine_metainfo_index); +#endif + + meta_info = xine_xmalloc (len - keylen); + memcpy (meta_info, c + keylen, len - keylen); + + this->stream->meta_info[speex_comment_keys[i].xine_metainfo_index] = + meta_info; + } + } + + c += len; + } +} + +static void speex_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { + + speex_decoder_t *this = (speex_decoder_t *) this_gen; + +#ifdef LOG + printf ("libspeex: decode buf=%8p content=%8p flags=%08x\n", + buf, buf->content, buf->decoder_flags); +#endif + + if (buf->decoder_flags & BUF_FLAG_PREVIEW) { +#ifdef LOG + printf ("libspeex: preview buffer, %d headers to go\n", this->header_count); +#endif + + if (this->header_count) { + + if (!this->st) { + SpeexMode * spx_mode; + SpeexHeader * spx_header; + int modeID; + int bitrate; + + speex_bits_init (&this->bits); + + spx_header = speex_packet_to_header (buf->content, buf->size); + + if (!spx_header) { + printf ("libspeex: could not read Speex header\n"); + return; + } + + modeID = spx_header->mode; + spx_mode = speex_mode_list[modeID]; + + if (spx_mode->bitstream_version != spx_header->mode_bitstream_version) { + printf ("libspeex: incompatible Speex mode bitstream version\n"); + return; + } + + this->st = speex_decoder_init (spx_mode); + if (!this->st) { + printf ("libspeex: decoder initialization failed\n"); + return; + } + + this->rate = spx_header->rate; + speex_decoder_ctl (this->st, SPEEX_SET_SAMPLING_RATE, &this->rate); + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] + = this->rate; + + this->channels = spx_header->nb_channels; + if (this->channels == 2) { + SpeexCallback callback; + + callback.callback_id = SPEEX_INBAND_STEREO; + callback.func = speex_std_stereo_request_handler; + callback.data = &this->stereo; + speex_decoder_ctl (this->st, SPEEX_SET_HANDLER, &callback); + } + + this->nframes = spx_header->frames_per_packet; + if (!this->nframes) this->nframes = 1; + + speex_decoder_ctl (this->st, SPEEX_GET_FRAME_SIZE, &this->frame_size); + + speex_decoder_ctl (this->st, SPEEX_GET_BITRATE, &bitrate); + if (bitrate <= 1) bitrate = 16000; /* assume 16 kbit */ + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE] = bitrate; + + this->header_count += spx_header->extra_headers; + this->expect_metadata = 1; + + free (spx_header); + } else if (this->expect_metadata) { + read_metadata (this, buf->content, buf->size); + } + + this->header_count--; + + if (!this->header_count) { + int mode = AO_CAP_MODE_MONO; + + switch (this->channels) { + case 1: + mode = AO_CAP_MODE_MONO; + break; + case 2: + mode = AO_CAP_MODE_STEREO; + break; + case 4: + mode = AO_CAP_MODE_4CHANNEL; + break; + case 5: + mode = AO_CAP_MODE_5CHANNEL; + break; + case 6: + mode = AO_CAP_MODE_5_1CHANNEL; + break; + default: + printf ("libspeex: help, %d channels ?!\n", + this->channels); + /* FIXME: handle error */ + } + + if (!this->output_open) { + this->output_open = + this->stream->audio_out->open(this->stream->audio_out, + this->stream, + 16, + this->rate, + mode); + } + } + } + + } else if (this->output_open) { + int i, j; + + audio_buffer_t *audio_buffer; + + audio_buffer = + this->stream->audio_out->get_buffer (this->stream->audio_out); + + speex_bits_read_from (&this->bits, buf->content, buf->size); + + for (j = 0; j < this->nframes; j++) { + int ret; + int bitrate; + ogg_int16_t * ptr = audio_buffer->mem; + + ret = speex_decode (this->st, &this->bits, this->output); + + if (ret==-1) + break; + if (ret==-2) { + printf ("libspeex: Decoding error, corrupted stream?\n"); + break; + } + if (speex_bits_remaining(&this->bits)<0) { + printf ("libspeex: Decoding overflow, corrupted stream?\n"); + break; + } + + if (this->channels == 2) { + speex_decode_stereo (this->output, this->frame_size, &this->stereo); + } + + speex_decoder_ctl (this->st, SPEEX_GET_BITRATE, &bitrate); + if (bitrate <= 1) bitrate = 16000; /* assume 16 kbit */ + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE] = bitrate; + + /*PCM saturation (just in case)*/ + for (i=0; i < this->frame_size * this->channels; i++) + { + if (this->output[i]>32000.0) + this->output[i]=32000.0; + else if (this->output[i]<-32000.0) + this->output[i]=-32000.0; + } + + /*Convert to short and play */ + for (i=0; i< this->frame_size * this->channels; i++) { + *ptr++ = (ogg_int16_t)this->output[i]; + } + + audio_buffer->vpts = this->pts; + this->pts=0; + audio_buffer->num_frames = this->frame_size; + + this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); + + buf->pts=0; + + } + } +#ifdef LOG + else + printf ("libspeex: output not open\n"); +#endif +} + +static void speex_dispose (audio_decoder_t *this_gen) { + + speex_decoder_t *this = (speex_decoder_t *) this_gen; + + if (this->st) { + speex_decoder_destroy (this->st); + } + speex_bits_destroy (&this->bits); + + if (this->output_open) + this->stream->audio_out->close (this->stream->audio_out, this->stream); + + free (this_gen); +} + +static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, + xine_stream_t *stream) { + + speex_decoder_t *this ; + static SpeexStereoState init_stereo = SPEEX_STEREO_STATE_INIT; + + this = (speex_decoder_t *) malloc (sizeof (speex_decoder_t)); + + this->audio_decoder.decode_data = speex_decode_data; + this->audio_decoder.reset = speex_reset; + this->audio_decoder.discontinuity = speex_discontinuity; + this->audio_decoder.dispose = speex_dispose; + this->stream = stream; + + this->output_open = 0; + this->header_count = 2; + this->expect_metadata = 0; + + this->st = NULL; + + this->channels = 1; + + memcpy (&this->stereo, &init_stereo, sizeof (SpeexStereoState)); + + return (audio_decoder_t *) this; +} + +/* + * speex plugin class + */ + +static char *get_identifier (audio_decoder_class_t *this) { + return "speex"; +} + +static char *get_description (audio_decoder_class_t *this) { + return "Speex audio decoder plugin"; +} + +static void dispose_class (audio_decoder_class_t *this) { + free (this); +} + +static void *init_plugin (xine_t *xine, void *data) { + + speex_class_t *this; + + this = (speex_class_t *) malloc (sizeof (speex_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_SPEEX, 0 + }; + +static decoder_info_t dec_info_audio = { + audio_types, /* supported types */ + 5 /* priority */ +}; + +plugin_info_t xine_plugin_info[] = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_AUDIO_DECODER, 13, "speex", XINE_VERSION_CODE, &dec_info_audio, init_plugin }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h index 8299cad9d..fca482503 100644 --- a/src/xine-engine/buffer.h +++ b/src/xine-engine/buffer.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: buffer.h,v 1.114 2003/05/20 13:50:57 mroi Exp $ + * $Id: buffer.h,v 1.115 2003/05/25 13:39:14 guenter Exp $ * * * contents: @@ -204,6 +204,7 @@ extern "C" { #define BUF_AUDIO_FLAC 0x032C0000 #define BUF_AUDIO_DV 0x032D0000 #define BUF_AUDIO_WMAV 0x032E0000 +#define BUF_AUDIO_SPEEX 0x032F0000 /* spu buffer types: */ diff --git a/src/xine-engine/buffer_types.c b/src/xine-engine/buffer_types.c index cb438b70d..d10746691 100644 --- a/src/xine-engine/buffer_types.c +++ b/src/xine-engine/buffer_types.c @@ -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: buffer_types.c,v 1.63 2003/05/19 21:49:57 tmmm Exp $ + * $Id: buffer_types.c,v 1.64 2003/05/25 13:39:14 guenter Exp $ * * * contents: @@ -863,6 +863,13 @@ static audio_db_t audio_db[] = { BUF_AUDIO_28_8, "Real 28.8" }, +{ + { + 0 + }, + BUF_AUDIO_SPEEX, + "Speex" +}, { { 0 }, 0, "last entry" } }; -- cgit v1.2.3