[xiph-commits] r7421 - in icecast/trunk/ices0: . doc src

brendan at motherfish-iii.xiph.org brendan
Thu Aug 5 19:04:11 PDT 2004


Author: brendan
Date: Thu Aug  5 19:04:11 2004
New Revision: 7421

Added:
icecast/trunk/ices0/src/in_mp4.c
icecast/trunk/ices0/src/in_mp4.h
Modified:
icecast/trunk/ices0/NEWS
icecast/trunk/ices0/README
icecast/trunk/ices0/TODO
icecast/trunk/ices0/configure.ac
icecast/trunk/ices0/doc/ices.1.in
icecast/trunk/ices0/src/Makefile.am
icecast/trunk/ices0/src/icestypes.h
icecast/trunk/ices0/src/stream.c
Log:
MP4 (AAC) transcoding support. Doesn't read metadata. Only reads stereo files.
Can't read from pipes.


Modified: icecast/trunk/ices0/NEWS
===================================================================
--- icecast/trunk/ices0/NEWS	2004-07-30 17:33:50 UTC (rev 7420)
+++ icecast/trunk/ices0/NEWS	2004-07-30 18:59:21 UTC (rev 7421)
@@ -1,3 +1,4 @@
+	* MP4 audio support added via libfaad.
* Crossfader added.
* Tested with LAME 3.96.1
0.3     2003-07-13

Modified: icecast/trunk/ices0/README
===================================================================
--- icecast/trunk/ices0/README	2004-07-30 17:33:50 UTC (rev 7420)
+++ icecast/trunk/ices0/README	2004-07-30 18:59:21 UTC (rev 7421)
@@ -9,6 +9,8 @@
2. Signal Handling
3. Playlist Handling
4. Reencoding
+	 5. Vorbis and MP4 transcoding
+	 6. Crossfading
D. Configuring
1. Command line options
2. Configuration file (ices.conf)
@@ -92,6 +94,13 @@
init, shutdown, get_next, and get_current_lineno. I suggest
you take a look in the distributed module files and just
expand on that.
+	 5. Vorbis and MP4 transcoding
+            If compiled with the appropriate libraries, ices can transcode
+            Ogg Vorbis and MP4 (AAC) audio files to MP3 on the fly. Keep your
+	    sources in whatever format you like best.
+	 6. Crossfading
+	    If compiled with reencoding support, ices can also crossfade
+            between tracks, giving you that pro radio station sound.
D. Configuring
ices can do everything shout could do, and more. It can be
configured through hard coded defaults, a configfile, and command
@@ -103,6 +112,7 @@
Options:
o -B (Background (daemon mode))
o -b <stream bitrate>
+               o -C <crossfade seconds>
o -c <configfile>
o -D <base directory>
o -d <stream description>
@@ -129,37 +139,38 @@
<?xml version="1.0"?>
<ices:Configuration xmlns:ices="http://www.icecast.org/
projects/ices">
-                        <ices:Playlist>
-                                <ices:File>apan.txt</ices:File>
-                                <ices:Randomize>1</ices:Randomize>
-                                <ices:Type>builtin</ices:Type>
-                                <ices:Module>ices</ices:Module>
-                        </ices:Playlist>
-                        <ices:Server>
-                                <ices:Hostname>localhost</ices:Hostname>
-                                <ices:Port>8000</ices:Port>
-                                <ices:Password>letmein</ices:Password>
-                                <ices:Protocol>xaudiocast</ices:Protocol>
-                        </ices:Server>
-                        <ices:Execution>
-                                <ices:Background>0</ices:Background>
-                                <ices:Verbose>1</ices:Verbose>
-                                <ices:BaseDirectory>/tmp</ices:BaseDirectory>
-                                <ices:Reencode>0</ices:Reencode>
-                                <ices:Samplerate>-1</ices:Samplerate>
-                                <ices:Channels>-1</ices:Channels>
-                        </ices:Execution>
-                        <ices:Stream>
-                                <ices:Name>Cool ices default name from XML</ice
+                        <Playlist>
+                                <File>apan.txt</File>
+                                <Randomize>1</Randomize>
+                                <Type>builtin</Type>
+                                <Module>ices</Module>
+				<Crossfade>0</Crossfade>
+                        </Playlist>
+                        <Server>
+                                <Hostname>localhost</Hostname>
+                                <Port>8000</Port>
+                                <Password>letmein</Password>
+                                <Protocol>http</Protocol>
+                        </Server>
+                        <Execution>
+                                <Background>0</Background>
+                                <Verbose>1</Verbose>
+                                <BaseDirectory>/tmp</BaseDirectory>
+                                <Reencode>0</Reencode>
+                                <Samplerate>-1</Samplerate>
+                                <Channels>-1</Channels>
+                        </Execution>
+                        <Stream>
+                                <Name>Cool ices default name from XML</ice
s:Name>
-                                <ices:Genre>Cool ices genre from XML</ices:Genr
+                                <Genre>Cool ices genre from XML</Genr
e>
-                                <ices:Description>Cool ices description from XM
-L</ices:Description>
-                                <ices:URL>Cool ices URL from XML</ices:URL>
-                                <ices:Bitrate>128</ices:Bitrate>
-                                <ices:Public>1</ices:Public>
-                        </ices:Stream>
+                                <Description>Cool ices description from XM
+L</Description>
+                                <URL>Cool ices URL from XML</URL>
+                                <Bitrate>128</Bitrate>
+                                <Public>1</Public>
+                        </Stream>
</ices:Configuration>
3. Configurations options
This describes all the different options in ices.
@@ -300,6 +311,11 @@
ices.pm, although do NOT specify the file extension for
the module. Use 'whatever' instead of 'whatever.pm' or
'whatever.py'
+	       o Playlist Crossfade
+                 Command line option: -C <crossfade secs>
+                 Config file tag: Playlist/Crossfade
+                 If this is greater than zero, and you have reencoding support,
+                 ices will crossfade the specified number of seconds between tracks.
E. Licensing
ices is licensed under the Gnu General Public License, and for
more info about that I suggest you read the file named COPYING.
@@ -308,4 +324,4 @@
nice streaming mp3 client, go to developer.icecast.org.
_______

-          This document is written by Alexander Haväng [eel at icecast.org].
+    This document was originally written by Alexander Haväng [eel at icecast.org].

Modified: icecast/trunk/ices0/TODO
===================================================================
--- icecast/trunk/ices0/TODO	2004-07-30 17:33:50 UTC (rev 7420)
+++ icecast/trunk/ices0/TODO	2004-07-30 18:59:21 UTC (rev 7421)
@@ -1,4 +1,5 @@
+* MP4: metadata, piped input, mono
* Improved error handling
* Make the scripting engines, and vorbis and MP3 reencoding, run-time linkable

-$Id: TODO,v 1.5 2003/03/19 18:58:24 brendan Exp $
+$Id$


Property changes on: icecast/trunk/ices0/TODO
___________________________________________________________________
Name: svn:keywords
+ Id

Modified: icecast/trunk/ices0/configure.ac
===================================================================
--- icecast/trunk/ices0/configure.ac	2004-07-30 17:33:50 UTC (rev 7420)
+++ icecast/trunk/ices0/configure.ac	2004-07-30 18:59:21 UTC (rev 7421)
@@ -251,7 +251,7 @@
fi

AC_ARG_WITH(vorbis,
-  [[  --with-vorbis[=DIR]     support for vorbis using libvorbisfile [in DIR]]])
+  [[  --with-vorbis[=DIR]     support for vorbis transcoding using libvorbisfile [in DIR]]])

if test "$have_LAME" != "yes"
then
@@ -296,6 +296,52 @@
fi
fi

+AC_ARG_WITH(faad,
+  [[  --with-faad[=DIR]     support for MP4 (AAC) transcoding using libfaad [in DIR]]])
+
+if test "$have_LAME" != "yes"
+then
+  if test -n "$with_faad" -a "$with_faad" != "no"
+  then
+    AC_MSG_ERROR([MP4 transcoding cannot be enabled without LAME])
+  elif test "$with_faad" != "no"
+  then
+    AC_MSG_RESULT([MP4 transcoding is disabled because LAME is not enabled])
+    with_faad="no"
+  fi
+fi
+
+have_faad="no"
+if test "$with_faad" != "no"
+then
+  if test -n "$with_faad" -a "$with_faad" != "yes"
+  then
+    CPPFLAGS="$CPPFLAGS -I$with_faad/include"
+    LDFLAGS="$LDFLAGS -L$with_faad/lib"
+  fi
+
+  AC_CHECK_HEADER(faad.h, have_faad="maybe")
+  if test "$have_faad" != "no"
+  then
+    AC_CHECK_LIB(mp4v2, MP4Read, [
+      LIBS="$LIBS -lmp4v2 -lfaad"
+      AC_DEFINE(HAVE_LIBFAAD, 1, [Define if you have libfaad])
+      ICES_OBJECTS="$ICES_OBJECTS in_mp4.o"
+      have_faad="yes"
+    ],[have_faad="no"])
+  fi
+fi
+
+if test "$with_faad" != "no" -a "$have_faad" != "yes"
+then
+  if test -n "$with_faad"
+  then
+    AC_MSG_ERROR([Could not find libfaad])
+  else
+    AC_MSG_RESULT([Could not find libfaad, MP4 transcoding disabled])
+  fi
+fi
+
dnl -- and finish up --

LIBS="$LIBS $LIBM $LIBDL"
@@ -312,3 +358,4 @@
AC_MSG_RESULT([  Perl    : $have_perl])
AC_MSG_RESULT([  LAME    : $have_LAME])
AC_MSG_RESULT([  Vorbis  : $have_vorbis])
+AC_MSG_RESULT([  MP4     : $have_faad])

Modified: icecast/trunk/ices0/doc/ices.1.in
===================================================================
--- icecast/trunk/ices0/doc/ices.1.in	2004-07-30 17:33:50 UTC (rev 7420)
+++ icecast/trunk/ices0/doc/ices.1.in	2004-07-30 18:59:21 UTC (rev 7421)
@@ -68,7 +68,8 @@
On-the-fly reencoding of your source audio to a different bitrate,
number of channels and/or sample rate. ices can also decode Ogg Vorbis
files and reencode them on the fly as MP3, for the benefit of older
-listening software.
+listening software. This just in: it can transcode MP4 (AAC) files now
+too.
.IP \(bu
Crossfading between tracks. This is a new feature, and requires
reencoding support.

Modified: icecast/trunk/ices0/src/Makefile.am
===================================================================
--- icecast/trunk/ices0/src/Makefile.am	2004-07-30 17:33:50 UTC (rev 7420)
+++ icecast/trunk/ices0/src/Makefile.am	2004-07-30 18:59:21 UTC (rev 7421)
@@ -5,13 +5,13 @@
bin_PROGRAMS = ices

noinst_HEADERS = icestypes.h definitions.h setup.h log.h stream.h util.h \
-	cue.h metadata.h in_vorbis.h mp3.h id3.h signals.h reencode.h \
+	cue.h metadata.h in_vorbis.h mp3.h in_mp4.h id3.h signals.h reencode.h \
ices_config.h

ices_SOURCES = ices.c log.c setup.c stream.c util.c mp3.c cue.c metadata.c \
id3.c signals.c crossfade.c

-EXTRA_ices_SOURCES = ices_config.c reencode.c in_vorbis.c
+EXTRA_ices_SOURCES = ices_config.c reencode.c in_vorbis.c in_mp4.c

ices_LDADD = $(ICES_OBJECTS) playlist/libplaylist.a
ices_DEPENDENCIES = $(ices_LDADD)

Modified: icecast/trunk/ices0/src/icestypes.h
===================================================================
--- icecast/trunk/ices0/src/icestypes.h	2004-07-30 17:33:50 UTC (rev 7420)
+++ icecast/trunk/ices0/src/icestypes.h	2004-07-30 18:59:21 UTC (rev 7421)
@@ -78,7 +78,8 @@
/* -- input stream types -- */
typedef enum {
ICES_INPUT_VORBIS,
-  ICES_INPUT_MP3
+  ICES_INPUT_MP3,
+  ICES_INPUT_MP4
} input_type_t;

typedef struct _input_stream_t {

Added: icecast/trunk/ices0/src/in_mp4.c
===================================================================
--- icecast/trunk/ices0/src/in_mp4.c	2004-07-30 17:33:50 UTC (rev 7420)
+++ icecast/trunk/ices0/src/in_mp4.c	2004-07-30 18:59:21 UTC (rev 7421)
@@ -0,0 +1,198 @@
+/* in_mp4.c
+ * Plugin to read MP4 files as PCM
+ *
+ * Copyright (c) 2004 Brendan Cully <brendan at xiph.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.
+ *
+ * $Id$
+ */
+
+#include "config.h"
+#include "in_mp4.h"
+#include "metadata.h"
+
+#include <string.h>
+
+/* fink error? */
+#define HAVE_IN_PORT_T 1
+#define HAVE_SOCKLEN_T 1
+#include <mp4.h>
+#include <faad.h>
+
+#define SAMPLESIZE 2
+#ifdef WORDS_BIGENDIAN
+# define ICES_OV_BE 1
+#else
+# define ICES_OV_BE 0
+#endif
+
+/* -- data structures -- */
+typedef struct {
+  MP4FileHandle mp4file;
+  MP4TrackId track;
+  faacDecHandle decoder;
+  MP4SampleId cur_sample;
+} mp4_in_t;
+
+/* -- static prototypes -- */
+static int ices_mp4_readpcm (input_stream_t* self, size_t len,
+				int16_t* left, int16_t* right);
+static int ices_mp4_close (input_stream_t* self);
+
+/* try to open an MP4 file for decoding. Returns:
+ *   0: success
+ *   1: not an MP4 file
+ *  -1: error opening
+ */
+int
+ices_mp4_open (input_stream_t* self, char* buf, size_t len)
+{
+  mp4_in_t* mp4_data;
+  MP4FileHandle mp4file;
+  MP4TrackId track;
+  faacDecHandle decoder;
+  unsigned int tracks;
+  unsigned int i;
+  unsigned char *escfg;
+  unsigned int escfglen;
+  unsigned long samplerate;
+  unsigned char channels;
+
+  /* At the moment we can only open seekable streams */
+  if (! self->filesize)
+    return 1;
+
+  if ((mp4file = MP4Read(self->path, 0)) == MP4_INVALID_FILE_HANDLE)
+    return 1;
+
+  /* find audio stream */
+  track = MP4_INVALID_TRACK_ID;
+  tracks = MP4GetNumberOfTracks(mp4file, MP4_AUDIO_TRACK_TYPE, 0);
+  for (i = 0; i < tracks; i++) {
+    if ((track = MP4FindTrackId(mp4file, i, MP4_AUDIO_TRACK_TYPE, 0)) != MP4_INVALID_TRACK_ID)
+      break;
+  }
+  if (track == MP4_INVALID_TRACK_ID) {
+    ices_log_error("ices_mp4_open: No audio track found");
+    goto errMP4;
+  }
+
+  MP4GetTrackESConfiguration(mp4file, track, &escfg, &escfglen);
+  if (!escfg) {
+    ices_log_error("ices_mp4_open: No audio format information found");
+    goto errMP4;
+  }
+
+  if (!(decoder = faacDecOpen())) {
+    ices_log_error("ices_mp4_open: Could not get a FAAD handle");
+    goto errMP4;
+  }
+
+  if (faacDecInit2(decoder, escfg, escfglen, &samplerate, &channels) < 0) {
+    ices_log_error("ices_mp4_open: Could not initialise FAAD");
+    free(escfg);
+    goto errFAAC;
+  }
+  free(escfg);
+
+  ices_log_debug("Found MP4 audio at track %u, sample rate %u, %u channels", track, samplerate, channels);
+
+  if (channels != 2) {
+    ices_log_error("ices_mp4_open: Bad number of channels");
+    goto errFAAC;
+  }
+
+  if (!(mp4_data = (mp4_in_t*)malloc (sizeof (mp4_in_t)))) {
+    ices_log_error ("Malloc failed in ices_mp4_open");
+    goto errFAAC;
+  }
+
+  close(self->fd);
+
+  self->samplerate = samplerate;
+  self->channels = channels;
+
+  mp4_data->mp4file = mp4file;
+  mp4_data->track = track;
+  mp4_data->decoder = decoder;
+  mp4_data->cur_sample = 1;
+
+  self->type = ICES_INPUT_MP4;
+  self->data = mp4_data;
+
+  self->read = NULL;
+  self->readpcm = ices_mp4_readpcm;
+  self->close = ices_mp4_close;
+
+  return 0;
+
+errFAAC:
+  faacDecClose(decoder);
+errMP4:
+  MP4Close(mp4file);
+
+  return -1;
+}
+
+static int
+ices_mp4_readpcm (input_stream_t* self, size_t olen, int16_t* left,
+		     int16_t* right)
+{
+  mp4_in_t* mp4_data = (mp4_in_t*)self->data;
+  unsigned char* buf;
+  unsigned int blen;
+  faacDecFrameInfo fi;
+  void* decbuf;
+  int i;
+
+  fi.samples = 0;
+  while (fi.samples == 0) {
+    buf = NULL;
+    if (!MP4ReadSample(mp4_data->mp4file, mp4_data->track, mp4_data->cur_sample++,
+		       &buf, &blen, NULL, NULL, NULL, NULL) || !blen)
+    {
+      ices_log_error("Error reading MP4");
+      return 0;
+    }
+
+    decbuf = faacDecDecode(mp4_data->decoder, &fi, buf, blen);
+    free (buf);
+    if (fi.error) {
+      ices_log_error("Error decoding MP4: %s", faacDecGetErrorMessage(fi.error));
+      return 0;
+    }
+
+  }
+  i = 0;
+  while (i < fi.samples * 2) {
+    *left++ = ((int16_t*)decbuf)[i++];
+    *right++ = ((int16_t*)decbuf)[i++];
+  }
+
+  return fi.samples / 2;
+}
+
+static int
+ices_mp4_close (input_stream_t* self)
+{
+  mp4_in_t* mp4_data = (mp4_in_t*) self->data;
+
+  faacDecClose(mp4_data->decoder);
+  MP4Close(mp4_data->mp4file);
+  free (mp4_data);
+
+  return 0;
+}


Property changes on: icecast/trunk/ices0/src/in_mp4.c
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native

Added: icecast/trunk/ices0/src/in_mp4.h
===================================================================
--- icecast/trunk/ices0/src/in_mp4.h	2004-07-30 17:33:50 UTC (rev 7420)
+++ icecast/trunk/ices0/src/in_mp4.h	2004-07-30 18:59:21 UTC (rev 7421)
@@ -0,0 +1,30 @@
+/* in_mp4.h
+ * ices input plugin to read MP4 files as PCM
+ *
+ * Copyright (c) 2004 Brendan Cully <brendan at xiph.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.
+ *
+ * $Id$
+ */
+
+#ifndef IN_MP4_H
+#define IN_MP4_H
+
+#include "definitions.h"
+
+int ices_mp4_open (input_stream_t* self, char* buf, size_t len);
+
+#endif


Property changes on: icecast/trunk/ices0/src/in_mp4.h
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native

Modified: icecast/trunk/ices0/src/stream.c
===================================================================
--- icecast/trunk/ices0/src/stream.c	2004-07-30 17:33:50 UTC (rev 7420)
+++ icecast/trunk/ices0/src/stream.c	2004-07-30 18:59:21 UTC (rev 7421)
@@ -352,6 +352,15 @@
return -1;
}

+  #ifdef HAVE_LIBFAAD
+  if (!(rc = ices_mp4_open (source, buf, len)))
+    return 0;
+  if (rc < 0) {
+    close(fd);
+    return -1;
+  }
+  #endif
+
if (!(rc = ices_mp3_open (source, buf, len)))
return 0;
if (rc < 0) {



More information about the commits mailing list