[MPlayer-dev-eng] [RFC] Speex support
Reimar Döffinger
Reimar.Doeffinger at stud.uni-karlsruhe.de
Tue Nov 1 18:00:16 CET 2005
Hi,
the attached patch adds support for speex decoding. Please test, esp.
the configure part.
Known bugs:
1) the ogg demuxer does not create valid timestamps. I do not intend to
that (flac in ogg has the same problem).
2) speex files with more than one frame per ogg packet will not work
(I do not yet know what is needed to fix that).
Greetings,
Reimar Döffinger
-------------- next part --------------
Index: Makefile
===================================================================
RCS file: /cvsroot/mplayer/main/Makefile,v
retrieving revision 1.330
diff -u -r1.330 Makefile
--- Makefile 19 Aug 2005 19:24:30 -0000 1.330
+++ Makefile 1 Nov 2005 16:26:40 -0000
@@ -104,6 +104,7 @@
$(XMMS_LIB) \
$(X264_LIB) \
$(MUSEPACK_LIB) \
+ $(SPEEX_LIB) \
COMMON_LIBS = libmpcodecs/libmpcodecs.a \
$(W32_LIB) \
Index: configure
===================================================================
RCS file: /cvsroot/mplayer/main/configure,v
retrieving revision 1.1096
diff -u -r1.1096 configure
--- configure 26 Oct 2005 20:40:19 -0000 1.1096
+++ configure 1 Nov 2005 16:27:06 -0000
@@ -243,6 +243,7 @@
--enable-tremor-low build with lower accuracy internal tremor [disabled]
--enable-external-tremor build with external tremor [disabled]
--disable-vorbis disable OggVorbis support entirely [autodetect]
+ --disable-speex disable Speex support entirely [autodetect]
--enable-theora build with OggTheora support [autodetect]
--disable-internal-matroska disable internal Matroska support [enabled]
--enable-external-faad build with external FAAD2 (AAC) support [autodetect]
@@ -1486,6 +1487,7 @@
_tremor_internal=yes
_tremor_low=no
_vorbis=auto
+_speex=auto
_theora=auto
_mp3lib=yes
_liba52=yes
@@ -1679,6 +1681,8 @@
--disable-liblzo) _liblzo=no ;;
--enable-vorbis) _vorbis=yes ;;
--disable-vorbis) _vorbis=no ;;
+ --enable-speex) _speex=yes ;;
+ --disable-speex) _speex=no ;;
--enable-internal-tremor) _tremor_internal=yes ;;
--disable-internal-tremor) _tremor_internal=no ;;
--enable-tremor-low) _tremor_low=yes ;;
@@ -5389,6 +5393,29 @@
fi
echores "$_vorbis"
+echocheck "libspeex (version >= 1.1 required)"
+if test "$_speex" = auto ; then
+ _speex=no
+ cat > $TMPC << EOF
+#include <speex/speex.h>
+int main(void) {
+ SpeexBits bits;
+ void *dec;
+ speex_decode_int(dec, &bits, dec);
+}
+EOF
+ cc_check -lspeex $_ld_lm && _speex=yes
+fi
+if test "$_speex" = yes ; then
+ _def_speex='#define HAVE_SPEEX 1'
+ _ld_speex='-lspeex'
+ _codecmodules="speex $_codecmodules"
+else
+ _def_speex='#undef HAVE_SPEEX'
+ _nocodecmodules="speex $_nocodecmodules"
+fi
+echores "$_speex"
+
echocheck "OggTheora support"
if test "$_theora" = auto ; then
_theora=no
@@ -6977,6 +7005,7 @@
TREMOR = $_tremor_internal
TREMOR_FLAGS = $_tremor_flags
+SPEEX = $_speex
MUSEPACK = $_musepack
UNRARLIB = $_unrarlib
@@ -7086,6 +7115,7 @@
LIBLZO_LIB= $_ld_liblzo
MAD_LIB = $_ld_mad
VORBIS_LIB = $_ld_vorbis $_ld_libdv
+SPEEX_LIB = $_ld_speex
THEORA_LIB = $_ld_theora
FAAD_LIB = $_ld_faad
INTERNAL_FAAD = $_faad_internal
@@ -7664,6 +7694,9 @@
/* enable Tremor as vorbis decoder */
$_def_tremor
+/* enable Speex support */
+$_def_speex
+
/* enable musepack support */
$_def_musepack
Index: libmpcodecs/Makefile
===================================================================
RCS file: /cvsroot/mplayer/main/libmpcodecs/Makefile,v
retrieving revision 1.151
diff -u -r1.151 Makefile
--- libmpcodecs/Makefile 19 Sep 2005 15:23:15 -0000 1.151
+++ libmpcodecs/Makefile 1 Nov 2005 16:28:31 -0000
@@ -209,6 +210,10 @@
AUDIO_SRCS += ad_mpc.c
endif
+ifeq ($(SPEEX),yes)
+AUDIO_SRCS += ad_speex.c
+endif
+
ifeq ($(FAAC),yes)
ENCODER_SRCS += ae_faac.c
endif
Index: libmpcodecs/ad.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpcodecs/ad.c,v
retrieving revision 1.21
diff -u -r1.21 ad.c
--- libmpcodecs/ad.c 10 Jul 2005 17:14:11 -0000 1.21
+++ libmpcodecs/ad.c 1 Nov 2005 16:28:31 -0000
@@ -33,6 +33,7 @@
extern ad_functions_t mpcodecs_ad_msgsm;
extern ad_functions_t mpcodecs_ad_faad;
extern ad_functions_t mpcodecs_ad_libvorbis;
+extern ad_functions_t mpcodecs_ad_libspeex;
extern ad_functions_t mpcodecs_ad_libmad;
extern ad_functions_t mpcodecs_ad_realaud;
extern ad_functions_t mpcodecs_ad_libdv;
@@ -78,6 +79,7 @@
#ifdef HAVE_OGGVORBIS
&mpcodecs_ad_libvorbis,
#endif
+#ifdef HAVE_SPEEX
+ &mpcodecs_ad_libspeex,
+#endif
#ifdef USE_LIBMAD
&mpcodecs_ad_libmad,
#endif
Index: libmpcodecs/ad_speex.c
===================================================================
RCS file: libmpcodecs/ad_speex.c
diff -N libmpcodecs/ad_speex.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libmpcodecs/ad_speex.c 1 Nov 2005 16:28:32 -0000
@@ -0,0 +1,82 @@
+/**
+ * Speex decoder by Reimar Döffinger <Reimar.Doeffinger at stud.uni-karlsruhe.de>
+ * License: GPL
+ * This code may be be relicensed under the terms of the GNU LGPL when it
+ * becomes part of the FFmpeg project (ffmpeg.org)
+ */
+#include "config.h"
+#include <speex/speex.h>
+#include "ad_internal.h"
+
+static ad_info_t info = {
+ "Speex audio decoder",
+ "speex",
+ "Reimar Döffinger",
+ "",
+ ""
+};
+
+LIBAD_EXTERN(libspeex)
+
+typedef struct {
+ SpeexBits bits;
+ void *dec_context;
+} context_t;
+
+static int preinit(sh_audio_t *sh) {
+ return 1;
+}
+
+static int init(sh_audio_t *sh) {
+ unsigned char *hdr = (unsigned char *)&sh->wf[1];
+ context_t *ctx = (context_t *)calloc(1, sizeof(context_t));
+ int mode;
+ if (!sh->wf || sh->wf->cbSize < 80) {
+ mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "Missing extradata!\n");
+ return 0;
+ }
+ mode = hdr[40] | hdr[41] << 8 | hdr[42] << 16 | hdr[43] << 24;
+ ctx->dec_context = speex_decoder_init(mode ? &speex_wb_mode : &speex_nb_mode);
+ speex_bits_init(&ctx->bits);
+ sh->context = ctx;
+ sh->channels = hdr[48] | hdr[49] << 8 | hdr[50] << 16 | hdr[51] << 24;
+ sh->samplerate = hdr[36] | hdr[37] << 8 | hdr[38] << 16 | hdr[39] << 24;
+ sh->samplesize = 2;
+ sh->sample_format = AF_FORMAT_S16_NE;
+ return 1;
+}
+
+static void uninit(sh_audio_t *sh) {
+ context_t *ctx = sh->context;
+ if (ctx) {
+ speex_bits_destroy(&ctx->bits);
+ speex_decoder_destroy(ctx->dec_context);
+ free(ctx);
+ }
+ ctx = NULL;
+}
+
+static int decode_audio(sh_audio_t *sh, unsigned char *buf,
+ int minlen, int maxlen) {
+ context_t *ctx = sh->context;
+ int len, framelen;
+ char *packet;
+ int err;
+ speex_decoder_ctl(ctx->dec_context, SPEEX_GET_FRAME_SIZE, &framelen);
+ if (maxlen < framelen * sizeof(short)) {
+ mp_msg(MSGT_DECAUDIO, MSGL_V, "maxlen too small in decode_audio\n");
+ return -1;
+ }
+ len = ds_get_packet(sh->ds, (unsigned char **)&packet);
+ if (len <= 0) return -1;
+ speex_bits_read_from(&ctx->bits, packet, len);
+ err = speex_decode_int(ctx->dec_context, &ctx->bits, (short *)buf);
+ if (err == -2)
+ mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Error decoding file.\n");
+ return framelen * sizeof(short);
+}
+
+static int control(sh_audio_t *sh, int cmd, void *arg, ...) {
+ return CONTROL_UNKNOWN;
+}
+
Index: libmpdemux/demux_ogg.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/demux_ogg.c,v
retrieving revision 1.82
diff -u -r1.82 demux_ogg.c
--- libmpdemux/demux_ogg.c 1 Nov 2005 16:12:53 -0000 1.82
+++ libmpdemux/demux_ogg.c 1 Nov 2005 16:29:03 -0000
@@ -16,6 +16,7 @@
#include "stheader.h"
#define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's')
+#define FOURCC_SPEEX mmioFOURCC('s', 'p', 'x', ' ')
#define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o')
#ifdef TREMOR
@@ -116,6 +117,7 @@
ogg_stream_state stream;
int hdr_packets;
int vorbis;
+ int speex;
int theora;
int flac;
int text;
@@ -352,6 +354,8 @@
os->lastsize = blocksize;
os->lastpos = pack->granulepos;
}
+ } else if (os->speex) {
+ data = pack->packet;
# ifdef HAVE_OGGTHEORA
} else if (os->theora) {
/* we pass complete packets to theora, mustn't strip the header! */
@@ -540,8 +544,8 @@
// (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
// We jump nothing for FLAC. Ain't this great? Packet contents have to be
// handled differently for each and every stream type. The joy! The joy!
- if(!os->flac && ((*pack->packet & PACKET_TYPE_HEADER) &&
- (ds != d->audio || ( ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) ) &&
+ if(!os->flac && !os->speex && ((*pack->packet & PACKET_TYPE_HEADER) &&
+ (ds != d->audio || ( (((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS) || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) ) &&
(ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA))))
return 0;
@@ -916,6 +920,27 @@
ogg_d->subs[ogg_d->num_sub].id = n_audio;
n_audio++;
mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Vorbis), -aid %d\n",ogg_d->num_sub,n_audio-1);
+ } else if (pack.bytes >= 80 && !strncmp(pack.packet,"Speex", 5)) {
+ sh_a = new_sh_audio(demuxer, ogg_d->num_sub);
+ sh_a->wf = (WAVEFORMATEX*)calloc(1, sizeof(WAVEFORMATEX) + pack.bytes);
+ sh_a->format = FOURCC_SPEEX;
+ sh_a->samplerate = sh_a->wf->nSamplesPerSec = get_uint32(&pack.packet[36]);
+ sh_a->channels = sh_a->wf->nChannels = get_uint32(&pack.packet[48]);
+ sh_a->wf->wFormatTag = sh_a->format;
+ sh_a->wf->nAvgBytesPerSec = get_uint32(&pack.packet[52]);
+ sh_a->wf->nBlockAlign = 0;
+ sh_a->wf->wBitsPerSample = 16;
+ sh_a->samplesize = 2;
+ sh_a->wf->cbSize = pack.bytes;
+ memcpy(&sh_a->wf[1], pack.packet, pack.bytes);
+
+ ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate;
+ ogg_d->subs[ogg_d->num_sub].speex = 1;
+ if (identify)
+ mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_AUDIO_ID=%d\n", n_audio);
+ ogg_d->subs[ogg_d->num_sub].id = n_audio;
+ n_audio++;
+ mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Speex), -aid %d\n",ogg_d->num_sub,n_audio-1);
// check for Theora
# ifdef HAVE_OGGTHEORA
@@ -1549,7 +1574,7 @@
break;
}
}
- if(!precision && (is_keyframe || os->vorbis) ) {
+ if(!precision && (is_keyframe || os->vorbis || os->speex) ) {
ogg_sub.lines = 0;
vo_sub = &ogg_sub;
vo_osd_changed(OSDTYPE_SUBTITLE);
More information about the MPlayer-dev-eng
mailing list