summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuenter Bartsch <guenter@users.sourceforge.net>2003-05-25 13:39:13 +0000
committerGuenter Bartsch <guenter@users.sourceforge.net>2003-05-25 13:39:13 +0000
commit91662bdf80f304b6f8e987a19899738af106172a (patch)
treeafec233636ba723bc6465909bb16e280fde4e027
parentd69fd28af6d47dfe7d0a557aad09d8abd2a0fae3 (diff)
downloadxine-lib-91662bdf80f304b6f8e987a19899738af106172a.tar.gz
xine-lib-91662bdf80f304b6f8e987a19899738af106172a.tar.bz2
speex support contributed by Conrad Parker <conrad@metadecks.org>
CVS patchset: 4926 CVS date: 2003/05/25 13:39:13
-rw-r--r--AUTHORS3
-rw-r--r--ChangeLog3
-rw-r--r--configure.ac17
-rw-r--r--m4/Makefile.am1
-rw-r--r--m4/speex.m490
-rw-r--r--src/Makefile.am1
-rw-r--r--src/demuxers/Makefile.am2
-rw-r--r--src/demuxers/demux_ogg.c74
-rw-r--r--src/libspeex/Makefile.am34
-rw-r--r--src/libspeex/xine_decoder.c462
-rw-r--r--src/xine-engine/buffer.h3
-rw-r--r--src/xine-engine/buffer_types.c9
12 files changed, 687 insertions, 12 deletions
diff --git a/AUTHORS b/AUTHORS
index 5fe02aaec..62c81e325 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -383,4 +383,7 @@ Tim Champagne <tchamp@aurasoft.com>
Matthew Grooms
msvc win32 port
+Conrad Parker <conrad@metadecks.org>
+ 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)
@@ -626,6 +626,17 @@ AM_PATH_OGG(
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 ---------------------------------------------
AM_PATH_LIBFLAC([],
@@ -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 <jack@icecast.org> 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <speex.h>
+
+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 <stdio.h>
+#include <speex/codec.h>
+], [ 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 <ogg/ogg.h>
#include <vorbis/codec.h>
+#ifdef HAVE_SPEEX
+#include <speex.h>
+#include <speex_header.h>
+#include <speex_stereo.h>
+#include <speex_callbacks.h>
+#endif
+
#ifdef HAVE_THEORA
#include <theora/theora.h>
#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 <stdlib.h>
+#include <string.h>
+
+#include "xine_internal.h"
+#include "audio_out.h"
+#include "buffer.h"
+
+#include <ogg/ogg.h>
+#include <speex.h>
+#include <speex_header.h>
+#include <speex_callbacks.h>
+#include <speex_stereo.h>
+
+#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" }
};