speex support contributed by Conrad Parker <conrad@metadecks.org>
authorGuenter Bartsch <guenter@users.sourceforge.net>
Sun May 25 13:39:13 2003 +0000 (2003-05-25)
changeset 4836d08ce5755b77
parent 4835 ba6a4e89d4a7
child 4837 0b9b9253cd52
speex support contributed by Conrad Parker <conrad@metadecks.org>

CVS patchset: 4926
CVS date: 2003/05/25 13:39:13
AUTHORS
ChangeLog
configure.ac
m4/Makefile.am
m4/speex.m4
src/Makefile.am
src/demuxers/Makefile.am
src/demuxers/demux_ogg.c
src/libspeex/Makefile.am
src/libspeex/xine_decoder.c
src/xine-engine/buffer.h
src/xine-engine/buffer_types.c
     1.1 --- a/AUTHORS	Sun May 25 12:00:22 2003 +0000
     1.2 +++ b/AUTHORS	Sun May 25 13:39:13 2003 +0000
     1.3 @@ -383,4 +383,7 @@
     1.4  Matthew Grooms
     1.5    msvc win32 port
     1.6  
     1.7 +Conrad Parker <conrad@metadecks.org>
     1.8 +  speex support
     1.9 +
    1.10  (let us know if we've forgotten anyone)
     2.1 --- a/ChangeLog	Sun May 25 12:00:22 2003 +0000
     2.2 +++ b/ChangeLog	Sun May 25 13:39:13 2003 +0000
     2.3 @@ -14,7 +14,8 @@
     2.4      (23.976, 59.94 and 60 fps)
     2.5    * move http proxy configuration to xine itself
     2.6    * add expand post video filter for displaying subtitles in borders
     2.7 -  
     2.8 +  * speex (http://www.speex.org) audio decoder support
     2.9 +	
    2.10  xine-lib (1-beta12)
    2.11    * enabled SVQ3 video decoding via ffmpeg
    2.12    * playback of theorastreams added
     3.1 --- a/configure.ac	Sun May 25 12:00:22 2003 +0000
     3.2 +++ b/configure.ac	Sun May 25 13:39:13 2003 +0000
     3.3 @@ -41,7 +41,7 @@
     3.4  if test -f .cvsversion; then
     3.5    XINE_PRE="cvs"
     3.6  else
     3.7 -  XINE_PRE="beta12"
     3.8 +  XINE_PRE="beta13"
     3.9  fi
    3.10  
    3.11  AC_SUBST(XINE_MAJOR)
    3.12 @@ -626,6 +626,17 @@
    3.13  AM_CONDITIONAL(HAVE_THEORA, [test x"$no_ogg" != "xyes" -a x"$no_theora" != "xyes"])
    3.14  
    3.15  dnl ---------------------------------------------
    3.16 +dnl Ogg/Speex libs.
    3.17 +dnl ---------------------------------------------
    3.18 +
    3.19 +AM_PATH_OGG(
    3.20 +           [ AM_PATH_SPEEX(AC_DEFINE(HAVE_SPEEX,1,[Define this if you have speex]),
    3.21 +                           AC_MSG_RESULT([*** All OGG/SPEEX dependent parts will be disabled ***]))
    3.22 +          ],
    3.23 +           AC_MSG_RESULT([*** All of OGG/Speex dependent parts will be disabled ***]))
    3.24 +AM_CONDITIONAL(HAVE_SPEEX, [test x"$no_ogg" != "xyes" -a x"$no_speex" != "xyes"])
    3.25 +
    3.26 +dnl ---------------------------------------------
    3.27  dnl check for libFLAC
    3.28  dnl ---------------------------------------------
    3.29  AM_PATH_LIBFLAC([],
    3.30 @@ -1364,6 +1375,7 @@
    3.31  src/libsputext/Makefile
    3.32  src/libvorbis/Makefile
    3.33  src/libtheora/Makefile
    3.34 +src/libspeex/Makefile
    3.35  src/libw32dll/Makefile
    3.36  src/libw32dll/wine/Makefile
    3.37  src/libw32dll/DirectShow/Makefile
    3.38 @@ -1511,6 +1523,9 @@
    3.39  if test x"$no_vorbis" != "xyes"; then
    3.40    echo "   - vorbis"
    3.41  fi
    3.42 +if test x"$no_speex" != "xyes"; then
    3.43 +  echo "   - speex"
    3.44 +fi
    3.45  if test x"$enable_w32dll" = "xyes"; then
    3.46    echo "   - w32dll"
    3.47  fi
     4.1 --- a/m4/Makefile.am	Sun May 25 12:00:22 2003 +0000
     4.2 +++ b/m4/Makefile.am	Sun May 25 13:39:13 2003 +0000
     4.3 @@ -29,6 +29,7 @@
     4.4  	progtest.m4 \
     4.5  	sdl.m4 \
     4.6  	vorbis.m4 \
     4.7 +	speex.m4 \
     4.8  	theora.m4 \
     4.9  	xine.m4 \
    4.10  	_xine.m4 \
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/m4/speex.m4	Sun May 25 13:39:13 2003 +0000
     5.3 @@ -0,0 +1,90 @@
     5.4 +# Configure paths for libspeex
     5.5 +# Jack Moffitt <jack@icecast.org> 10-21-2000
     5.6 +# Shamelessly stolen from Owen Taylor and Manish Singh
     5.7 +
     5.8 +dnl AM_PATH_SPEEX([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
     5.9 +dnl Test for libspeex, and define SPEEX_CFLAGS and SPEEX_LIBS
    5.10 +dnl
    5.11 +AC_DEFUN([AM_PATH_SPEEX],
    5.12 +[dnl 
    5.13 +dnl Get the cflags and libraries
    5.14 +dnl
    5.15 +AC_ARG_WITH(speex-prefix,[  --with-speex-prefix=PFX   Prefix where libspeex is installed (optional)], speex_prefix="$withval", speex_prefix="")
    5.16 +AC_ARG_ENABLE(speextest, [  --disable-speextest       Do not try to compile and run a test Speex program],, enable_speextest=yes)
    5.17 +
    5.18 +  if test x$speex_prefix != x ; then
    5.19 +    speex_args="$speex_args --prefix=$speex_prefix"
    5.20 +    SPEEX_CFLAGS="-I$speex_prefix/include"
    5.21 +    SPEEX_LIBDIR="-L$speex_prefix/lib"
    5.22 +  fi
    5.23 +
    5.24 +  SPEEX_LIBS="$SPEEX_LIBDIR -lspeex -lm"
    5.25 +
    5.26 +  AC_MSG_CHECKING(for Speex)
    5.27 +  no_speex=""
    5.28 +
    5.29 +
    5.30 +  if test "x$enable_speextest" = "xyes" ; then
    5.31 +    ac_save_CFLAGS="$CFLAGS"
    5.32 +    ac_save_LIBS="$LIBS"
    5.33 +    CFLAGS="$CFLAGS $SPEEX_CFLAGS"
    5.34 +    LIBS="$LIBS $SPEEX_LIBS $OGG_LIBS"
    5.35 +dnl
    5.36 +dnl Now check if the installed Speex is sufficiently new.
    5.37 +dnl
    5.38 +      rm -f conf.speextest
    5.39 +      AC_TRY_RUN([
    5.40 +#include <stdio.h>
    5.41 +#include <stdlib.h>
    5.42 +#include <string.h>
    5.43 +#include <speex.h>
    5.44 +
    5.45 +int main ()
    5.46 +{
    5.47 +  system("touch conf.speextest");
    5.48 +  return 0;
    5.49 +}
    5.50 +
    5.51 +],, no_speex=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
    5.52 +       CFLAGS="$ac_save_CFLAGS"
    5.53 +       LIBS="$ac_save_LIBS"
    5.54 +  fi
    5.55 +
    5.56 +  if test "x$no_speex" = x ; then
    5.57 +     AC_MSG_RESULT(yes)
    5.58 +     ifelse([$1], , :, [$1])     
    5.59 +  else
    5.60 +     AC_MSG_RESULT(no)
    5.61 +     if test -f conf.speextest ; then
    5.62 +       :
    5.63 +     else
    5.64 +       echo "*** Could not run Speex test program, checking why..."
    5.65 +       CFLAGS="$CFLAGS $SPEEX_CFLAGS"
    5.66 +       LIBS="$LIBS $SPEEX_LIBS $OGG_LIBS"
    5.67 +       AC_TRY_LINK([
    5.68 +#include <stdio.h>
    5.69 +#include <speex/codec.h>
    5.70 +],     [ return 0; ],
    5.71 +       [ echo "*** The test program compiled, but did not run. This usually means"
    5.72 +       echo "*** that the run-time linker is not finding Speex or finding the wrong"
    5.73 +       echo "*** version of Speex. If it is not finding Speex, you'll need to set your"
    5.74 +       echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
    5.75 +       echo "*** to the installed location  Also, make sure you have run ldconfig if that"
    5.76 +       echo "*** is required on your system"
    5.77 +       echo "***"
    5.78 +       echo "*** If you have an old version installed, it is best to remove it, although"
    5.79 +       echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
    5.80 +       [ echo "*** The test program failed to compile or link. See the file config.log for the"
    5.81 +       echo "*** exact error that occured. This usually means Speex was incorrectly installed"
    5.82 +       echo "*** or that you have moved Speex since it was installed." ])
    5.83 +       CFLAGS="$ac_save_CFLAGS"
    5.84 +       LIBS="$ac_save_LIBS"
    5.85 +     fi
    5.86 +     SPEEX_CFLAGS=""
    5.87 +     SPEEX_LIBS=""
    5.88 +     ifelse([$2], , :, [$2])
    5.89 +  fi
    5.90 +  AC_SUBST(SPEEX_CFLAGS)
    5.91 +  AC_SUBST(SPEEX_LIBS)
    5.92 +  rm -f conf.speextest
    5.93 +])
     6.1 --- a/src/Makefile.am	Sun May 25 12:00:22 2003 +0000
     6.2 +++ b/src/Makefile.am	Sun May 25 13:39:13 2003 +0000
     6.3 @@ -27,6 +27,7 @@
     6.4  	libxineadec \
     6.5  	libvorbis \
     6.6  	libtheora \
     6.7 +	libspeex \
     6.8  	libreal \
     6.9  	libfaad \
    6.10  	libflac \
     7.1 --- a/src/demuxers/Makefile.am	Sun May 25 12:00:22 2003 +0000
     7.2 +++ b/src/demuxers/Makefile.am	Sun May 25 13:39:13 2003 +0000
     7.3 @@ -46,7 +46,7 @@
     7.4  	xineplug_dmx_nsv.la 
     7.5  
     7.6  xineplug_dmx_ogg_la_SOURCES = demux_ogg.c
     7.7 -xineplug_dmx_ogg_la_LIBADD = $(OGG_LIBS) $(VORBIS_LIBS) $(THEORA_LIBS) $(XINE_LIB)
     7.8 +xineplug_dmx_ogg_la_LIBADD = $(OGG_LIBS) $(VORBIS_LIBS) $(SPEEX_LIBS) $(THEORA_LIBS) $(XINE_LIB)
     7.9  xineplug_dmx_ogg_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
    7.10  
    7.11  xineplug_dmx_avi_la_SOURCES = demux_avi.c
     8.1 --- a/src/demuxers/demux_ogg.c	Sun May 25 12:00:22 2003 +0000
     8.2 +++ b/src/demuxers/demux_ogg.c	Sun May 25 13:39:13 2003 +0000
     8.3 @@ -17,7 +17,7 @@
     8.4   * along with this program; if not, write to the Free Software
     8.5   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
     8.6   *
     8.7 - * $Id: demux_ogg.c,v 1.100 2003/05/12 19:44:35 heinchen Exp $
     8.8 + * $Id: demux_ogg.c,v 1.101 2003/05/25 13:39:14 guenter Exp $
     8.9   *
    8.10   * demultiplexer for ogg streams
    8.11   *
    8.12 @@ -38,6 +38,13 @@
    8.13  #include <ogg/ogg.h>
    8.14  #include <vorbis/codec.h>
    8.15  
    8.16 +#ifdef HAVE_SPEEX
    8.17 +#include <speex.h>
    8.18 +#include <speex_header.h>
    8.19 +#include <speex_stereo.h>
    8.20 +#include <speex_callbacks.h>
    8.21 +#endif
    8.22 +
    8.23  #ifdef HAVE_THEORA
    8.24  #include <theora/theora.h>
    8.25  #endif
    8.26 @@ -181,7 +188,7 @@
    8.27      buffer = ogg_sync_buffer(&this->oy, CHUNKSIZE);
    8.28      bytes  = this->input->read(this->input, buffer, CHUNKSIZE);
    8.29      ogg_sync_wrote(&this->oy, bytes);
    8.30 -    if (bytes < CHUNKSIZE) {
    8.31 +    if (bytes < CHUNKSIZE/2) {
    8.32        return 0;
    8.33      }
    8.34    }
    8.35 @@ -369,6 +376,9 @@
    8.36        og_ghost->packet = buf->content + op_size;
    8.37        
    8.38        buf->size   = op->bytes;
    8.39 +    } else if ((this->buf_types[stream_num] & 0xFFFF0000) == BUF_AUDIO_SPEEX) {
    8.40 +      memcpy (buf->content, op->packet, op->bytes);
    8.41 +      buf->size   = op->bytes;      
    8.42      } else {
    8.43        memcpy (buf->content, op->packet+1+hdrlen, op->bytes-1-hdrlen);
    8.44        buf->size   = op->bytes-1-hdrlen;
    8.45 @@ -386,7 +396,7 @@
    8.46        buf->pts = 0; 
    8.47  
    8.48  #ifdef LOG
    8.49 -    printf ("demuxogg: audiostream %d op-gpos %lld hdr-gpos %lld pts %lld \n"
    8.50 +    printf ("demux_ogg: audiostream %d op-gpos %lld hdr-gpos %lld pts %lld \n"
    8.51  	    ,stream_num
    8.52  	    ,op->granulepos
    8.53  	    ,this->header_granulepos[stream_num]
    8.54 @@ -648,6 +658,54 @@
    8.55  	  }
    8.56  	  vorbis_comment_clear(&vc);
    8.57  	  vorbis_info_clear(&vi);
    8.58 +	} else if (!strncmp (&op.packet[0], "Speex", 5)) {
    8.59 +
    8.60 +#ifdef HAVE_SPEEX
    8.61 +	  void * st;
    8.62 +	  SpeexMode * mode;
    8.63 +	  SpeexHeader * header;
    8.64 +
    8.65 +	  this->buf_types[stream_num] = BUF_AUDIO_SPEEX
    8.66 +	    +this->num_audio_streams++;
    8.67 +
    8.68 +	  this->preview_buffers[stream_num] = 1;
    8.69 +
    8.70 +	  header = speex_packet_to_header (op.packet, op.bytes);
    8.71 +
    8.72 +	  if (header) {
    8.73 +	    int bitrate;
    8.74 +	    mode = speex_mode_list[header->mode];
    8.75 +
    8.76 +	    st = speex_decoder_init (mode);
    8.77 +
    8.78 +	    speex_decoder_ctl (st, SPEEX_GET_BITRATE, &bitrate);
    8.79 +
    8.80 +	    if (bitrate <= 1)
    8.81 +	      bitrate = 16000; /* assume 16 kbit */
    8.82 +
    8.83 +	    this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE]
    8.84 +	      = bitrate;
    8.85 +
    8.86 +	    this->factor[stream_num] = 90000;
    8.87 +	    this->quotient[stream_num] = header->rate;
    8.88 +
    8.89 +	    this->avg_bitrate += bitrate;
    8.90 +
    8.91 +#ifdef LOG
    8.92 +	    printf ("demux_ogg: detected Speex stream,\trate %d\tbitrate %d\n",
    8.93 +		     header->rate, bitrate);
    8.94 +#endif
    8.95 +
    8.96 +	    this->stream->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE]
    8.97 +	      = header->rate;
    8.98 +
    8.99 +	    this->preview_buffers[stream_num] += header->extra_headers;
   8.100 +	  }
   8.101 +#else
   8.102 +	  printf ("demux_ogg: Speex stream detected, unable to play\n");
   8.103 +
   8.104 +	  this->buf_types[stream_num] = BUF_CONTROL_NOP;
   8.105 +#endif
   8.106  	} else if (!strncmp (&op.packet[1], "video", 5)) {
   8.107  	  
   8.108  	  buf_element_t    *buf;
   8.109 @@ -1135,7 +1193,7 @@
   8.110      /* printf("demux_ogg: packet: %.8s\n", op.packet); */
   8.111      /* printf("demux_ogg:   got a packet\n"); */
   8.112  
   8.113 -    if ((*op.packet & PACKET_TYPE_HEADER) && (this->buf_types[stream_num]!=BUF_VIDEO_THEORA)) {
   8.114 +    if ((*op.packet & PACKET_TYPE_HEADER) && (this->buf_types[stream_num]!=BUF_VIDEO_THEORA) && (this->buf_types[stream_num]!=BUF_AUDIO_SPEEX)) {
   8.115        if (op.granulepos!=-1) {
   8.116  	this->header_granulepos[stream_num]=op.granulepos;
   8.117  #ifdef LOG
   8.118 @@ -1487,7 +1545,8 @@
   8.119        return NULL;
   8.120        
   8.121      if (strncasecmp(ending, ".ogg", 4) &&
   8.122 -        strncasecmp(ending, ".ogm", 4)) {
   8.123 +        strncasecmp(ending, ".ogm", 4) &&
   8.124 +	strncasecmp(ending, ".spx", 4)) {
   8.125        return NULL;
   8.126      } 
   8.127  
   8.128 @@ -1542,12 +1601,13 @@
   8.129  }
   8.130  
   8.131  static char *get_extensions (demux_class_t *this_gen) {
   8.132 -  return "ogg ogm";
   8.133 +  return "ogg ogm spx";
   8.134  }
   8.135  
   8.136  static char *get_mimetypes (demux_class_t *this_gen) {
   8.137    return "audio/x-ogg: ogg: OggVorbis Audio;"
   8.138 -         "application/x-ogg: ogg: OggVorbis Audio;"; 
   8.139 +         "audio/x-speex: ogg: Speex Audio;"
   8.140 +         "application/x-ogg: ogg: OggVorbis Audio;";
   8.141  }
   8.142  
   8.143  static void class_dispose (demux_class_t *this_gen) {
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/libspeex/Makefile.am	Sun May 25 13:39:13 2003 +0000
     9.3 @@ -0,0 +1,34 @@
     9.4 +##
     9.5 +## Process this file with automake to produce Makefile.in
     9.6 +##
     9.7 +
     9.8 +AM_CFLAGS = $(SPEEX_CFLAGS)
     9.9 +
    9.10 +LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic
    9.11 +
    9.12 +libdir = $(XINE_PLUGINDIR)
    9.13 +
    9.14 +if HAVE_SPEEX
    9.15 +speex_module = xineplug_decode_speex.la
    9.16 +endif
    9.17 +
    9.18 +lib_LTLIBRARIES = $(speex_module)
    9.19 +
    9.20 +xineplug_decode_speex_la_SOURCES = xine_decoder.c
    9.21 +xineplug_decode_speex_la_LIBADD = $(SPEEX_LIBS)
    9.22 +xineplug_decode_speex_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@
    9.23 +
    9.24 +debug:
    9.25 +#	@$(MAKE) CFLAGS="$(DEBUG_CFLAGS) $(OGG_CFLAGS) $(SPEEX_CFLAGS)"
    9.26 +	@$(MAKE) CFLAGS="$(DEBUG_CFLAGS)"
    9.27 +
    9.28 +install-debug: debug
    9.29 +	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
    9.30 +
    9.31 +mostlyclean-generic:
    9.32 +	-rm -f *~ \#* .*~ .\#*
    9.33 +
    9.34 +maintainer-clean-generic:
    9.35 +	-@echo "This command is intended for maintainers to use;"
    9.36 +	-@echo "it deletes files that may require special tools to rebuild."
    9.37 +	-rm -f Makefile.in
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/libspeex/xine_decoder.c	Sun May 25 13:39:13 2003 +0000
    10.3 @@ -0,0 +1,462 @@
    10.4 +/* 
    10.5 + * Copyright (C) 2000-2002 the xine project
    10.6 + * 
    10.7 + * This file is part of xine, a free video player.
    10.8 + * 
    10.9 + * xine is free software; you can redistribute it and/or modify
   10.10 + * it under the terms of the GNU General Public License as published by
   10.11 + * the Free Software Foundation; either version 2 of the License, or
   10.12 + * (at your option) any later version.
   10.13 + * 
   10.14 + * xine is distributed in the hope that it will be useful,
   10.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.17 + * GNU General Public License for more details.
   10.18 + * 
   10.19 + * You should have received a copy of the GNU General Public License
   10.20 + * along with this program; if not, write to the Free Software
   10.21 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
   10.22 + *
   10.23 + * $Id: xine_decoder.c,v 1.1 2003/05/25 13:39:14 guenter Exp $
   10.24 + *
   10.25 + * (ogg/)speex audio decoder plugin (libspeex wrapper) for xine
   10.26 + */
   10.27 +
   10.28 +#ifdef HAVE_CONFIG_H
   10.29 +#include "config.h"
   10.30 +#endif
   10.31 +
   10.32 +#include <stdlib.h>
   10.33 +#include <string.h>
   10.34 +
   10.35 +#include "xine_internal.h"
   10.36 +#include "audio_out.h"
   10.37 +#include "buffer.h"
   10.38 +
   10.39 +#include <ogg/ogg.h>
   10.40 +#include <speex.h>
   10.41 +#include <speex_header.h>
   10.42 +#include <speex_callbacks.h>
   10.43 +#include <speex_stereo.h>
   10.44 +
   10.45 +#define MAX_FRAME_SIZE 2000
   10.46 +
   10.47 +/*
   10.48 +#define LOG
   10.49 +*/
   10.50 +
   10.51 +typedef struct {
   10.52 +  audio_decoder_class_t   decoder_class;
   10.53 +} speex_class_t;
   10.54 +
   10.55 +typedef struct speex_decoder_s {
   10.56 +  audio_decoder_t   audio_decoder;
   10.57 +
   10.58 +  int64_t           pts;
   10.59 +
   10.60 +  int               output_sampling_rate;
   10.61 +  int               output_open;
   10.62 +  int               output_mode;
   10.63 +
   10.64 +  /* speex stuff */
   10.65 +  void             *st;
   10.66 +  int               frame_size;
   10.67 +  int               rate;
   10.68 +  int               nframes;
   10.69 +  int               channels;
   10.70 +  SpeexBits         bits;
   10.71 +  SpeexStereoState  stereo;
   10.72 +  int               expect_metadata;
   10.73 +
   10.74 +  float             output[MAX_FRAME_SIZE];
   10.75 +
   10.76 +  int               header_count;
   10.77 +
   10.78 +  xine_stream_t    *stream;
   10.79 +
   10.80 +} speex_decoder_t;
   10.81 +
   10.82 +
   10.83 +static void speex_reset (audio_decoder_t *this_gen) {
   10.84 +
   10.85 +  speex_decoder_t *this = (speex_decoder_t *) this_gen;
   10.86 +
   10.87 +  speex_bits_init (&this->bits);
   10.88 +}
   10.89 +
   10.90 +static void speex_discontinuity (audio_decoder_t *this_gen) {
   10.91 +
   10.92 +  speex_decoder_t *this = (speex_decoder_t *) this_gen;
   10.93 +
   10.94 +  this->pts=0;
   10.95 +}
   10.96 +
   10.97 +/* Known speex comment keys from ogg123 sources*/
   10.98 +static struct {
   10.99 +  char *key;         /* includes the '=' for programming convenience */
  10.100 +  int   xine_metainfo_index;
  10.101 +} speex_comment_keys[] = {
  10.102 +  {"ARTIST=", XINE_META_INFO_ARTIST},
  10.103 +  {"ALBUM=", XINE_META_INFO_ALBUM},
  10.104 +  {"TITLE=", XINE_META_INFO_TITLE},
  10.105 +  {"GENRE=", XINE_META_INFO_GENRE},
  10.106 +  {"DESCRIPTION=", XINE_META_INFO_COMMENT},
  10.107 +  {"DATE=", XINE_META_INFO_YEAR},
  10.108 +  {NULL, 0}
  10.109 +};
  10.110 +
  10.111 +#define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \
  10.112 +                           ((buf[base+2]<<16)&0xff0000)| \
  10.113 +                           ((buf[base+1]<<8)&0xff00)| \
  10.114 +                            (buf[base]&0xff))
  10.115 +
  10.116 +static
  10.117 +void read_metadata (speex_decoder_t *this, char * comments, int length)
  10.118 +{
  10.119 +  char * c = comments;
  10.120 +  int len, i, nb_fields;
  10.121 +  char * end;
  10.122 +
  10.123 +  this->stream->meta_info[XINE_META_INFO_AUDIOCODEC] = strdup ("speex");
  10.124 +
  10.125 +  if (length < 8) {
  10.126 +    printf ("libspeex: invalid/corrupted comments\n");
  10.127 +    return;
  10.128 +  }
  10.129 +
  10.130 +  end = c+length;
  10.131 +  len = readint (c, 0);
  10.132 +  c += 4;
  10.133 +
  10.134 +  if (c+len > end) {
  10.135 +    printf ("libspeex: invalid/corrupted comments\n");
  10.136 +    return;
  10.137 +  }
  10.138 +
  10.139 +#ifdef LOG
  10.140 +  /* Encoder */
  10.141 +  printf ("libspeex: ");
  10.142 +  fwrite (c, 1, len, stdout);
  10.143 +  printf ("\n");
  10.144 +#endif
  10.145 +
  10.146 +  c += len;
  10.147 +
  10.148 +  if (c+4 > end) {
  10.149 +    printf ("libspeex: invalid/corrupted comments\n");
  10.150 +    return;
  10.151 +  }
  10.152 +
  10.153 +  nb_fields = readint (c, 0);
  10.154 +  c += 4;
  10.155 +
  10.156 +  for (i = 0; i < nb_fields; i++) {
  10.157 +    if (c+4 > end) {
  10.158 +      printf ("libspeex: invalid/corrupted comments\n");
  10.159 +      return;
  10.160 +    }
  10.161 +
  10.162 +    len = readint (c, 0);
  10.163 +    c += 4;
  10.164 +    if (c+len > end) {
  10.165 +      printf ("libspeex: invalid/corrupted comments\n");
  10.166 +      return;
  10.167 +    }
  10.168 +
  10.169 +#ifdef LOG
  10.170 +    printf ("libspeex: ");
  10.171 +    fwrite (c, 1, len, stdout);
  10.172 +    printf ("\n");
  10.173 +#endif
  10.174 +
  10.175 +    for (i = 0; speex_comment_keys[i].key != NULL; i++) {
  10.176 +
  10.177 +      if ( !strncasecmp (speex_comment_keys[i].key, c,
  10.178 +			 strlen(speex_comment_keys[i].key)) ) {
  10.179 +	int keylen = strlen(speex_comment_keys[i].key);
  10.180 +	char * meta_info;
  10.181 +	
  10.182 +#ifdef LOG
  10.183 +	printf ("libspeex: known metadata %d %d\n",
  10.184 +		i, speex_comment_keys[i].xine_metainfo_index);
  10.185 +#endif
  10.186 +	
  10.187 +	meta_info = xine_xmalloc (len - keylen);
  10.188 +	memcpy (meta_info, c + keylen, len - keylen);
  10.189 +	
  10.190 +	this->stream->meta_info[speex_comment_keys[i].xine_metainfo_index] =
  10.191 +	  meta_info;
  10.192 +      }
  10.193 +    }
  10.194 +
  10.195 +    c += len;
  10.196 +  }
  10.197 +}
  10.198 +
  10.199 +static void speex_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
  10.200 +
  10.201 +  speex_decoder_t *this = (speex_decoder_t *) this_gen;
  10.202 +
  10.203 +#ifdef LOG
  10.204 +  printf ("libspeex: decode buf=%8p content=%8p flags=%08x\n",
  10.205 +	  buf, buf->content, buf->decoder_flags);
  10.206 +#endif
  10.207 +
  10.208 +  if (buf->decoder_flags & BUF_FLAG_PREVIEW) {
  10.209 +#ifdef LOG
  10.210 +    printf ("libspeex: preview buffer, %d headers to go\n", this->header_count);
  10.211 +#endif
  10.212 +
  10.213 +    if (this->header_count) {
  10.214 +
  10.215 +      if (!this->st) {
  10.216 +	SpeexMode * spx_mode;
  10.217 +	SpeexHeader * spx_header;
  10.218 +	int modeID;
  10.219 +	int bitrate;
  10.220 +
  10.221 +	speex_bits_init (&this->bits);
  10.222 +
  10.223 +	spx_header = speex_packet_to_header (buf->content, buf->size);
  10.224 +
  10.225 +	if (!spx_header) {
  10.226 +	  printf ("libspeex: could not read Speex header\n");
  10.227 +	  return;
  10.228 +	}
  10.229 +
  10.230 +	modeID = spx_header->mode;
  10.231 +	spx_mode = speex_mode_list[modeID];
  10.232 +
  10.233 +	if (spx_mode->bitstream_version != spx_header->mode_bitstream_version) {
  10.234 +	  printf ("libspeex: incompatible Speex mode bitstream version\n");
  10.235 +	  return;
  10.236 +	}
  10.237 +
  10.238 +	this->st = speex_decoder_init (spx_mode);
  10.239 +	if (!this->st) {
  10.240 +	  printf ("libspeex: decoder initialization failed\n");
  10.241 +	  return;
  10.242 +	}
  10.243 +
  10.244 +	this->rate = spx_header->rate;
  10.245 +	speex_decoder_ctl (this->st, SPEEX_SET_SAMPLING_RATE, &this->rate);
  10.246 +	this->stream->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE]
  10.247 +	  = this->rate;
  10.248 +
  10.249 +	this->channels = spx_header->nb_channels;
  10.250 +	if (this->channels == 2) {
  10.251 +	  SpeexCallback callback;
  10.252 +	
  10.253 +	  callback.callback_id = SPEEX_INBAND_STEREO;
  10.254 +	  callback.func = speex_std_stereo_request_handler;
  10.255 +	  callback.data = &this->stereo;
  10.256 +	  speex_decoder_ctl (this->st, SPEEX_SET_HANDLER, &callback);
  10.257 +	}
  10.258 +
  10.259 +	this->nframes = spx_header->frames_per_packet;
  10.260 +	if (!this->nframes) this->nframes = 1;
  10.261 +      
  10.262 +	speex_decoder_ctl (this->st, SPEEX_GET_FRAME_SIZE, &this->frame_size);
  10.263 +
  10.264 +	speex_decoder_ctl (this->st, SPEEX_GET_BITRATE, &bitrate);
  10.265 +	if (bitrate <= 1) bitrate = 16000; /* assume 16 kbit */
  10.266 +	this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE] = bitrate;
  10.267 +
  10.268 +	this->header_count += spx_header->extra_headers;
  10.269 +	this->expect_metadata = 1;
  10.270 +
  10.271 +	free (spx_header);
  10.272 +      } else if (this->expect_metadata) {
  10.273 +	read_metadata (this, buf->content, buf->size);
  10.274 +      }
  10.275 +
  10.276 +      this->header_count--;
  10.277 +
  10.278 +      if (!this->header_count) {
  10.279 +	int mode = AO_CAP_MODE_MONO;
  10.280 +
  10.281 +	switch (this->channels) {
  10.282 +	case 1: 
  10.283 +	  mode = AO_CAP_MODE_MONO;
  10.284 +	  break;
  10.285 +	case 2: 
  10.286 +	  mode = AO_CAP_MODE_STEREO;
  10.287 +	  break;
  10.288 +	case 4: 
  10.289 +	  mode = AO_CAP_MODE_4CHANNEL;
  10.290 +	  break;
  10.291 +	case 5: 
  10.292 +	  mode = AO_CAP_MODE_5CHANNEL;
  10.293 +	  break;
  10.294 +	case 6: 
  10.295 +	  mode = AO_CAP_MODE_5_1CHANNEL;
  10.296 +	  break;
  10.297 +	default:
  10.298 +	  printf ("libspeex: help, %d channels ?!\n",
  10.299 +		  this->channels);
  10.300 +	  /* FIXME: handle error */
  10.301 +	}
  10.302 +	
  10.303 +	if (!this->output_open) {
  10.304 +	  this->output_open =
  10.305 +	    this->stream->audio_out->open(this->stream->audio_out, 
  10.306 +					  this->stream,
  10.307 +					  16,
  10.308 +					  this->rate,
  10.309 +					  mode);
  10.310 +	}
  10.311 +      }
  10.312 +    }
  10.313 +    
  10.314 +  } else if (this->output_open) {
  10.315 +    int i, j;
  10.316 +
  10.317 +    audio_buffer_t *audio_buffer;
  10.318 +
  10.319 +    audio_buffer =
  10.320 +      this->stream->audio_out->get_buffer (this->stream->audio_out);
  10.321 +
  10.322 +    speex_bits_read_from (&this->bits, buf->content, buf->size);
  10.323 +
  10.324 +    for (j = 0; j < this->nframes; j++) {
  10.325 +      int ret;
  10.326 +      int bitrate;
  10.327 +      ogg_int16_t * ptr = audio_buffer->mem;
  10.328 +
  10.329 +      ret = speex_decode (this->st, &this->bits, this->output);
  10.330 +
  10.331 +      if (ret==-1)
  10.332 +	break;
  10.333 +      if (ret==-2) {
  10.334 +	printf ("libspeex: Decoding error, corrupted stream?\n");
  10.335 +	break;
  10.336 +      }
  10.337 +      if (speex_bits_remaining(&this->bits)<0) {
  10.338 +	printf ("libspeex: Decoding overflow, corrupted stream?\n");
  10.339 +	break;
  10.340 +      }
  10.341 +
  10.342 +      if (this->channels == 2) {
  10.343 +	speex_decode_stereo (this->output, this->frame_size, &this->stereo);
  10.344 +      }
  10.345 +
  10.346 +      speex_decoder_ctl (this->st, SPEEX_GET_BITRATE, &bitrate);
  10.347 +      if (bitrate <= 1) bitrate = 16000; /* assume 16 kbit */
  10.348 +      this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE] = bitrate;
  10.349 +
  10.350 +      /*PCM saturation (just in case)*/
  10.351 +      for (i=0; i < this->frame_size * this->channels; i++)
  10.352 +	{
  10.353 +	  if (this->output[i]>32000.0)
  10.354 +	    this->output[i]=32000.0;
  10.355 +	  else if (this->output[i]<-32000.0)
  10.356 +	    this->output[i]=-32000.0;
  10.357 +	}
  10.358 +
  10.359 +      /*Convert to short and play */	
  10.360 +      for (i=0; i< this->frame_size * this->channels; i++) {
  10.361 +	*ptr++ = (ogg_int16_t)this->output[i];
  10.362 +      }
  10.363 +
  10.364 +      audio_buffer->vpts       = this->pts;
  10.365 +      this->pts=0;
  10.366 +      audio_buffer->num_frames = this->frame_size;
  10.367 +	
  10.368 +      this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream);
  10.369 +	
  10.370 +      buf->pts=0;
  10.371 +
  10.372 +    }
  10.373 +  }
  10.374 +#ifdef LOG
  10.375 +  else
  10.376 +    printf ("libspeex: output not open\n");
  10.377 +#endif
  10.378 +}
  10.379 +
  10.380 +static void speex_dispose (audio_decoder_t *this_gen) {
  10.381 +
  10.382 +  speex_decoder_t *this = (speex_decoder_t *) this_gen; 
  10.383 +  
  10.384 +  if (this->st) {
  10.385 +    speex_decoder_destroy (this->st);
  10.386 +  }
  10.387 +  speex_bits_destroy (&this->bits);
  10.388 +
  10.389 +  if (this->output_open) 
  10.390 +    this->stream->audio_out->close (this->stream->audio_out, this->stream);
  10.391 +
  10.392 +  free (this_gen);
  10.393 +}
  10.394 +
  10.395 +static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, 
  10.396 +				     xine_stream_t *stream) {
  10.397 +
  10.398 +  speex_decoder_t *this ;
  10.399 +  static SpeexStereoState init_stereo = SPEEX_STEREO_STATE_INIT;
  10.400 +
  10.401 +  this = (speex_decoder_t *) malloc (sizeof (speex_decoder_t));
  10.402 +
  10.403 +  this->audio_decoder.decode_data         = speex_decode_data;
  10.404 +  this->audio_decoder.reset               = speex_reset;
  10.405 +  this->audio_decoder.discontinuity       = speex_discontinuity;
  10.406 +  this->audio_decoder.dispose             = speex_dispose;
  10.407 +  this->stream                            = stream;
  10.408 +
  10.409 +  this->output_open     = 0;
  10.410 +  this->header_count    = 2;
  10.411 +  this->expect_metadata = 0;
  10.412 +
  10.413 +  this->st = NULL;
  10.414 +
  10.415 +  this->channels = 1;
  10.416 +
  10.417 +  memcpy (&this->stereo, &init_stereo, sizeof (SpeexStereoState));
  10.418 +
  10.419 +  return (audio_decoder_t *) this;
  10.420 +}
  10.421 +
  10.422 +/*
  10.423 + * speex plugin class
  10.424 + */
  10.425 +
  10.426 +static char *get_identifier (audio_decoder_class_t *this) {
  10.427 +  return "speex";
  10.428 +}
  10.429 +
  10.430 +static char *get_description (audio_decoder_class_t *this) {
  10.431 +  return "Speex audio decoder plugin";
  10.432 +}
  10.433 +
  10.434 +static void dispose_class (audio_decoder_class_t *this) {
  10.435 +  free (this);
  10.436 +}
  10.437 +
  10.438 +static void *init_plugin (xine_t *xine, void *data) {
  10.439 +
  10.440 +  speex_class_t *this;
  10.441 +  
  10.442 +  this = (speex_class_t *) malloc (sizeof (speex_class_t));
  10.443 +
  10.444 +  this->decoder_class.open_plugin     = open_plugin;
  10.445 +  this->decoder_class.get_identifier  = get_identifier;
  10.446 +  this->decoder_class.get_description = get_description;
  10.447 +  this->decoder_class.dispose         = dispose_class;
  10.448 +
  10.449 +  return this;
  10.450 +}
  10.451 +
  10.452 +static uint32_t audio_types[] = { 
  10.453 +  BUF_AUDIO_SPEEX, 0
  10.454 + };
  10.455 +
  10.456 +static decoder_info_t dec_info_audio = {
  10.457 +  audio_types,         /* supported types */
  10.458 +  5                    /* priority        */
  10.459 +};
  10.460 +
  10.461 +plugin_info_t xine_plugin_info[] = {
  10.462 +  /* type, API, "name", version, special_info, init_function */  
  10.463 +  { PLUGIN_AUDIO_DECODER, 13, "speex", XINE_VERSION_CODE, &dec_info_audio, init_plugin },
  10.464 +  { PLUGIN_NONE, 0, "", 0, NULL, NULL }
  10.465 +};
    11.1 --- a/src/xine-engine/buffer.h	Sun May 25 12:00:22 2003 +0000
    11.2 +++ b/src/xine-engine/buffer.h	Sun May 25 13:39:13 2003 +0000
    11.3 @@ -17,7 +17,7 @@
    11.4   * along with this program; if not, write to the Free Software
    11.5   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
    11.6   *
    11.7 - * $Id: buffer.h,v 1.114 2003/05/20 13:50:57 mroi Exp $
    11.8 + * $Id: buffer.h,v 1.115 2003/05/25 13:39:14 guenter Exp $
    11.9   *
   11.10   *
   11.11   * contents:
   11.12 @@ -204,6 +204,7 @@
   11.13  #define BUF_AUDIO_FLAC		0x032C0000
   11.14  #define BUF_AUDIO_DV		0x032D0000
   11.15  #define BUF_AUDIO_WMAV		0x032E0000
   11.16 +#define BUF_AUDIO_SPEEX		0x032F0000
   11.17  
   11.18  /* spu buffer types:    */
   11.19  
    12.1 --- a/src/xine-engine/buffer_types.c	Sun May 25 12:00:22 2003 +0000
    12.2 +++ b/src/xine-engine/buffer_types.c	Sun May 25 13:39:13 2003 +0000
    12.3 @@ -17,7 +17,7 @@
    12.4   * along with this program; if not, write to the Free Software
    12.5   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
    12.6   *
    12.7 - * $Id: buffer_types.c,v 1.63 2003/05/19 21:49:57 tmmm Exp $
    12.8 + * $Id: buffer_types.c,v 1.64 2003/05/25 13:39:14 guenter Exp $
    12.9   *
   12.10   *
   12.11   * contents:
   12.12 @@ -863,6 +863,13 @@
   12.13    BUF_AUDIO_28_8,
   12.14    "Real 28.8"
   12.15  },
   12.16 +{
   12.17 +  {
   12.18 +    0
   12.19 +  },
   12.20 +  BUF_AUDIO_SPEEX,
   12.21 +  "Speex"
   12.22 +},
   12.23  { { 0 }, 0, "last entry" }
   12.24  };
   12.25