shout: added mp3 encoder
[mk: moved this patch after "Refactor and cleanup of shout Ogg and MP3 audio outputs". The original commit message follows, although it is outdated:] Creation of shout_mp3 audio output plugin. Basically I just copied the existing shout plugin and replaced ogg with lame. Uses lame for mp3 encoding. Next step is to pull common functionality out of each shout plugin and share it between them. Configuration options for "shout_mp3" are the same as for "shout".
This commit is contained in:
parent
4970c42c86
commit
5f8eebd122
35
configure.ac
35
configure.ac
@ -74,6 +74,7 @@ fi
|
||||
|
||||
AC_ARG_ENABLE(ao,[ --enable-ao enable support for libao (default: disable)],[enable_ao=$enableval],[enable_ao=no])
|
||||
AC_ARG_ENABLE(shout_ogg,[ --disable-shout_ogg disable support for ogg streaming through shout (default: enable)],[enable_shout_ogg=$enableval],[enable_shout_ogg=yes])
|
||||
AC_ARG_ENABLE(shout_mp3,[ --disable-shout_mp3 disable support for mp3 streaming through shout (default: enable)],[enable_shout_mp3=$enableval],[enable_shout_mp3=yes])
|
||||
AC_ARG_ENABLE(iconv,[ --disable-iconv disable iconv support (default: enable)],[enable_iconv=$enableval],[enable_iconv=yes])
|
||||
AC_ARG_ENABLE(ipv6,[ --disable-ipv6 disable IPv6 support (default: enable)],[enable_ipv6=$enableval],[enable_ipv6=yes])
|
||||
AC_ARG_ENABLE(tcp,[ --disable-tcp disable support for clients connecting via TCP (default: enable)],[enable_tcp=$enableval],[enable_tcp=yes])
|
||||
@ -88,6 +89,7 @@ AC_ARG_ENABLE(oggvorbis,[ --disable-oggvorbis disable Ogg Vorbis support (d
|
||||
AC_ARG_ENABLE(oggflac,[ --disable-oggflac disable OggFLAC support (default: enable)],[enable_oggflac=$enableval],enable_oggflac=yes)
|
||||
AC_ARG_ENABLE(flac,[ --disable-flac disable flac support (default: enable)],[enable_flac=$enableval],[enable_flac=yes])
|
||||
AC_ARG_ENABLE(mp3,[ --disable-mp3 disable mp3 support (default: enable)],[enable_mp3=$enableval],[enable_mp3=yes])
|
||||
AC_ARG_ENABLE(lame,[ --disable-lame disable lame support (default: enable)],[enable_lame=$enableval],[enable_lame=yes])
|
||||
AC_ARG_ENABLE(aac,[ --disable-aac disable AAC support (default: enable)],[enable_aac=$enableval],[enable_aac=yes])
|
||||
AC_ARG_ENABLE(audiofile,[ --disable-audiofile disable audiofile support, disables wave support (default: enable)],[enable_audiofile=$enableval],[enable_audiofile=yes])
|
||||
AC_ARG_ENABLE(mod,[ --enable-mod enable MOD support (default: disable)],[enable_mod=$enableval],[enable_mod=yes])
|
||||
@ -207,6 +209,20 @@ if test x$enable_shout_ogg = xyes; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x$enable_shout_mp3 = xyes; then
|
||||
if test x$enable_lame = xno; then
|
||||
AC_MSG_WARN([disabling mp3 shout streaming support because lame is not enabled])
|
||||
enable_shout_mp3=no
|
||||
fi
|
||||
if test x$enable_shout = xno; then
|
||||
AC_MSG_WARN([disabling mp3 shout streaming support because libshout is not found])
|
||||
enable_shout_mp3=no
|
||||
fi
|
||||
if test x$enable_shout_mp3 = xyes; then
|
||||
AC_DEFINE(HAVE_SHOUT_MP3, 1, [Define to enable mp3 streaming support])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x$enable_ao = xyes; then
|
||||
XIPH_PATH_AO([AC_DEFINE(HAVE_AO, 1, [Define to play with ao]) MPD_LIBS="$MPD_LIBS $AO_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AO_CFLAGS"], enable_ao=no)
|
||||
fi
|
||||
@ -364,6 +380,12 @@ if test x$enable_mp3 = xyes; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x$enable_lame = xyes; then
|
||||
AM_PATH_LAME([MPD_LIBS="$MPD_LIBS $LAME_LIBS" MPD_CFLAGS="$MPD_CFLAGS $LAME_CFLAGS"],
|
||||
[enable_lame=no;AC_MSG_WARN(You need lame -- disabling lame support)])
|
||||
fi
|
||||
|
||||
|
||||
if test x$enable_mpc = xyes; then
|
||||
if test "x$mpcdec_libraries" != "x" ; then
|
||||
MPCDEC_LIBS="-L$mpcdec_libraries"
|
||||
@ -753,11 +775,18 @@ else
|
||||
echo " Shout ogg streaming support ...disabled"
|
||||
fi
|
||||
|
||||
if test x$enable_shout_mp3 = xyes; then
|
||||
echo " Shout mp3 streaming support ...enabled"
|
||||
else
|
||||
echo " Shout mp3 streaming support ...disabled"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
if test x$enable_ao = xno &&
|
||||
test x$enable_oss = xno &&
|
||||
test x$enable_shout_ogg = xno &&
|
||||
test x$enable_shout_mp3 = xno &&
|
||||
test x$enable_alsa = xno &&
|
||||
test x$enable_osx = xno &&
|
||||
test x$enable_pulse = xno &&
|
||||
@ -781,6 +810,12 @@ else
|
||||
echo " mp3 support ...................disabled"
|
||||
fi
|
||||
|
||||
if test x$enable_lame = xyes; then
|
||||
echo " lame support ..................enabled"
|
||||
else
|
||||
echo " lame support ..................disabled"
|
||||
fi
|
||||
|
||||
if test x$enable_oggvorbis = xyes; then
|
||||
echo " Ogg Vorbis support ............enabled"
|
||||
if test x$use_tremor = xyes; then
|
||||
|
108
m4/lame.m4
Normal file
108
m4/lame.m4
Normal file
@ -0,0 +1,108 @@
|
||||
dnl borrowed from oddsock.org
|
||||
dnl AM_PATH_LAME([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
|
||||
dnl Test for liblame, and define LAME_CFLAGS and LAME_LIBS
|
||||
dnl
|
||||
AC_DEFUN([AM_PATH_LAME],
|
||||
[dnl
|
||||
dnl Get the cflags and libraries
|
||||
dnl
|
||||
AC_ARG_WITH(lame,[ --with-lame=PFX Prefix where liblame is installed (optional)], lame_prefix="$withval", lame_prefix="")
|
||||
AC_ARG_WITH(lame-libraries,[ --with-lame-libraries=DIR Directory where liblame library is installed (optional)], lame_libraries="$withval", lame_libraries="")
|
||||
AC_ARG_WITH(lame-includes,[ --with-lame-includes=DIR Directory where liblame header files are installed (optional)], lame_includes="$withval", lame_includes="")
|
||||
AC_ARG_ENABLE(lametest, [ --disable-lametest Do not try to compile and run a test liblame program],, enable_lametest=yes)
|
||||
|
||||
if test "x$lame_prefix" != "xno" ; then
|
||||
|
||||
if test "x$lame_libraries" != "x" ; then
|
||||
LAME_LIBS="-L$lame_libraries"
|
||||
elif test "x$lame_prefix" != "x" ; then
|
||||
LAME_LIBS="-L$lame_prefix/lib"
|
||||
elif test "x$prefix" != "xNONE" ; then
|
||||
LAME_LIBS="-L$prefix/lib"
|
||||
fi
|
||||
|
||||
LAME_LIBS="$LAME_LIBS -lmp3lame -lm"
|
||||
|
||||
if test "x$lame_includes" != "x" ; then
|
||||
LAME_CFLAGS="-I$lame_includes"
|
||||
elif test "x$lame_prefix" != "x" ; then
|
||||
LAME_CFLAGS="-I$lame_prefix/include"
|
||||
elif test "x$prefix" != "xNONE"; then
|
||||
LAME_CFLAGS="-I$prefix/include"
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(for liblame)
|
||||
no_lame=""
|
||||
|
||||
|
||||
if test "x$enable_lametest" = "xyes" ; then
|
||||
ac_save_CFLAGS="$CFLAGS"
|
||||
ac_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $LAME_CFLAGS"
|
||||
LIBS="$LIBS $LAME_LIBS"
|
||||
dnl
|
||||
dnl Now check if the installed liblame is sufficiently new.
|
||||
dnl
|
||||
rm -f conf.lametest
|
||||
AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <lame/lame.h>
|
||||
|
||||
int main ()
|
||||
{
|
||||
system("touch conf.lametest");
|
||||
return 0;
|
||||
}
|
||||
|
||||
],, no_lame=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
|
||||
if test "x$no_lame" = "x" ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$1], , :, [$1])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test -f conf.lametest ; then
|
||||
:
|
||||
else
|
||||
echo "*** Could not run liblame test program, checking why..."
|
||||
CFLAGS="$CFLAGS $LAME_CFLAGS"
|
||||
LIBS="$LIBS $LAME_LIBS"
|
||||
AC_TRY_LINK([
|
||||
#include <stdio.h>
|
||||
#include <lame/lame.h>
|
||||
], [ return 0; ],
|
||||
[ echo "*** The test program compiled, but did not run. This usually means"
|
||||
echo "*** that the run-time linker is not finding liblame or finding the wrong"
|
||||
echo "*** version of liblame. If it is not finding liblame, 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 liblame was incorrectly installed"
|
||||
echo "*** or that you have moved liblame since it was installed." ])
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
LAME_CFLAGS=""
|
||||
LAME_LIBS=""
|
||||
ifelse([$2], , :, [$2])
|
||||
fi
|
||||
AC_DEFINE(HAVE_LAME, 1, [Define if you have liblame.])
|
||||
use_lame="1"
|
||||
else
|
||||
LAME_CFLAGS=""
|
||||
LAME_LIBS=""
|
||||
fi
|
||||
AC_SUBST(LAME_CFLAGS)
|
||||
AC_SUBST(LAME_LIBS)
|
||||
rm -f conf.lametest
|
||||
])
|
||||
|
@ -4,6 +4,7 @@ SUBDIRS = $(MP4FF_SUBDIR)
|
||||
mpd_audioOutputs = \
|
||||
audioOutputs/audioOutput_shout.c \
|
||||
audioOutputs/audioOutput_shout_ogg.c \
|
||||
audioOutputs/audioOutput_shout_mp3.c \
|
||||
audioOutputs/audioOutput_null.c \
|
||||
audioOutputs/audioOutput_fifo.c \
|
||||
audioOutputs/audioOutput_alsa.c \
|
||||
|
@ -113,6 +113,7 @@ static void free_shout_data(struct shout_data *sd)
|
||||
static void load_shout_plugins(void)
|
||||
{
|
||||
init_shout_encoder_plugins();
|
||||
load_shout_encoder_plugin(&shout_mp3_encoder);
|
||||
load_shout_encoder_plugin(&shout_ogg_encoder);
|
||||
}
|
||||
|
||||
|
@ -94,6 +94,7 @@ struct shout_data {
|
||||
shout_buffer buf;
|
||||
};
|
||||
|
||||
extern shout_encoder_plugin shout_mp3_encoder;
|
||||
extern shout_encoder_plugin shout_ogg_encoder;
|
||||
|
||||
#endif
|
||||
|
194
src/audioOutputs/audioOutput_shout_mp3.c
Normal file
194
src/audioOutputs/audioOutput_shout_mp3.c
Normal file
@ -0,0 +1,194 @@
|
||||
/* the Music Player Daemon (MPD)
|
||||
* Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
|
||||
* This project's homepage is: http://www.musicpd.org
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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
|
||||
*/
|
||||
|
||||
#include "../output_api.h"
|
||||
|
||||
#ifdef HAVE_SHOUT_MP3
|
||||
|
||||
#include "../utils.h"
|
||||
#include "audioOutput_shout.h"
|
||||
#include <lame/lame.h>
|
||||
|
||||
typedef struct _lame_data {
|
||||
lame_global_flags *gfp;
|
||||
} lame_data;
|
||||
|
||||
|
||||
static int shout_mp3_encoder_init(shout_data * sd)
|
||||
{
|
||||
lame_data *ld;
|
||||
|
||||
if (NULL == (ld = xmalloc(sizeof(lame_data))))
|
||||
FATAL("error initializing lame encoder data\n");
|
||||
sd->encoder_data = ld;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shout_mp3_encoder_clear_encoder(shout_data * sd)
|
||||
{
|
||||
lame_data *ld = (lame_data *)sd->encoder_data;
|
||||
shout_buffer *buf = &sd->buf;
|
||||
int ret;
|
||||
|
||||
if ((ret = lame_encode_flush(ld->gfp, buf->data + buf->len,
|
||||
buf->len)) < 0)
|
||||
ERROR("error flushing lame buffers\n");
|
||||
|
||||
return (ret > 0);
|
||||
}
|
||||
|
||||
static void shout_mp3_encoder_finish(shout_data * sd)
|
||||
{
|
||||
lame_data *ld = (lame_data *)sd->encoder_data;
|
||||
|
||||
lame_close(ld->gfp);
|
||||
ld->gfp = NULL;
|
||||
}
|
||||
|
||||
static int shout_mp3_encoder_init_encoder(shout_data * sd)
|
||||
{
|
||||
lame_data *ld = (lame_data *)sd->encoder_data;
|
||||
|
||||
if (NULL == (ld->gfp = lame_init())) {
|
||||
ERROR("error initializing lame encoder for shout\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sd->quality >= -1.0) {
|
||||
if (0 != lame_set_VBR(ld->gfp, vbr_rh)) {
|
||||
ERROR("error setting lame VBR mode\n");
|
||||
return -1;
|
||||
}
|
||||
if (0 != lame_set_VBR_q(ld->gfp, sd->quality)) {
|
||||
ERROR("error setting lame VBR quality\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (0 != lame_set_brate(ld->gfp, sd->bitrate)) {
|
||||
ERROR("error setting lame bitrate\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != lame_set_num_channels(ld->gfp,
|
||||
sd->audio_format.channels)) {
|
||||
ERROR("error setting lame num channels\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != lame_set_in_samplerate(ld->gfp,
|
||||
sd->audio_format.sampleRate)) {
|
||||
ERROR("error setting lame sample rate\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 > lame_init_params(ld->gfp))
|
||||
FATAL("error initializing lame params\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shout_mp3_encoder_send_metadata(shout_data * sd,
|
||||
char * song, size_t size)
|
||||
{
|
||||
char artist[size];
|
||||
char title[size];
|
||||
int i;
|
||||
struct tag *tag = sd->tag;
|
||||
|
||||
strncpy(artist, "", size);
|
||||
strncpy(title, "", size);
|
||||
|
||||
for (i = 0; i < tag->numOfItems; i++) {
|
||||
switch (tag->items[i]->type) {
|
||||
case TAG_ITEM_ARTIST:
|
||||
strncpy(artist, tag->items[i]->value, size);
|
||||
break;
|
||||
case TAG_ITEM_TITLE:
|
||||
strncpy(title, tag->items[i]->value, size);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
snprintf(song, size, "%s - %s", title, artist);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int shout_mp3_encoder_encode(shout_data * sd,
|
||||
const char * chunk, size_t len)
|
||||
{
|
||||
unsigned int i;
|
||||
int j;
|
||||
float (*lamebuf)[2];
|
||||
shout_buffer *buf = &(sd->buf);
|
||||
unsigned int samples;
|
||||
int bytes = sd->audio_format.bits / 8;
|
||||
lame_data *ld = (lame_data *)sd->encoder_data;
|
||||
int bytes_out;
|
||||
|
||||
samples = len / (bytes * sd->audio_format.channels);
|
||||
/* rough estimate, from lame.h */
|
||||
lamebuf = xmalloc(sizeof(float) * (1.25 * samples + 7200));
|
||||
|
||||
/* this is for only 16-bit audio */
|
||||
|
||||
for (i = 0; i < samples; i++) {
|
||||
for (j = 0; j < sd->audio_format.channels; j++) {
|
||||
lamebuf[j][i] = *((const mpd_sint16 *) chunk);
|
||||
chunk += bytes;
|
||||
}
|
||||
}
|
||||
|
||||
bytes_out = lame_encode_buffer_float(ld->gfp, lamebuf[0], lamebuf[1],
|
||||
samples, buf->data,
|
||||
buf->max_len - buf->len);
|
||||
free(lamebuf);
|
||||
|
||||
if (0 > bytes_out) {
|
||||
ERROR("error encoding lame buffer for shout\n");
|
||||
lame_close(ld->gfp);
|
||||
ld->gfp = NULL;
|
||||
return -1;
|
||||
} else
|
||||
buf->len = bytes_out; /* signed to unsigned conversion */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
shout_encoder_plugin shout_mp3_encoder = {
|
||||
"mp3",
|
||||
SHOUT_FORMAT_MP3,
|
||||
|
||||
shout_mp3_encoder_clear_encoder,
|
||||
shout_mp3_encoder_encode,
|
||||
shout_mp3_encoder_finish,
|
||||
shout_mp3_encoder_init,
|
||||
shout_mp3_encoder_init_encoder,
|
||||
shout_mp3_encoder_send_metadata,
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
DISABLED_SHOUT_ENCODER_PLUGIN(shout_mp3_encoder);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user