[xiph-commits] r7428 - in icecast/trunk/ices0: . src
brendan at motherfish-iii.xiph.org
brendan
Thu Aug 5 19:04:50 PDT 2004
Author: brendan
Date: Thu Aug 5 19:04:50 2004
New Revision: 7428
Added:
icecast/trunk/ices0/src/in_flac.c
icecast/trunk/ices0/src/in_flac.h
Modified:
icecast/trunk/ices0/configure.ac
icecast/trunk/ices0/src/Makefile.am
icecast/trunk/ices0/src/icestypes.h
icecast/trunk/ices0/src/setup.c
icecast/trunk/ices0/src/stream.c
Log:
Couldn't sleep, so I wrote a FLAC plugin.
Modified: icecast/trunk/ices0/configure.ac
===================================================================
--- icecast/trunk/ices0/configure.ac 2004-07-31 08:11:05 UTC (rev 7427)
+++ icecast/trunk/ices0/configure.ac 2004-07-31 09:11:47 UTC (rev 7428)
@@ -342,6 +342,52 @@
fi
fi
+AC_ARG_WITH(flac,
+ [[ --with-flac[=DIR] support for FLAC transcoding using libFLAC [in DIR]]])
+
+if test "$have_LAME" != "yes"
+then
+ if test -n "$with_flac" -a "$with_flac" != "no"
+ then
+ AC_MSG_ERROR([FLAC transcoding cannot be enabled without LAME])
+ elif test "$with_flac" != "no"
+ then
+ AC_MSG_RESULT([FLAC transcoding is disabled because LAME is not enabled])
+ with_flac="no"
+ fi
+fi
+
+have_flac="no"
+if test "$with_flac" != "no"
+then
+ if test -n "$with_flac" -a "$with_flac" != "yes"
+ then
+ CPPFLAGS="$CPPFLAGS -I$with_flac/include"
+ LDFLAGS="$LDFLAGS -L$with_flac/lib"
+ fi
+
+ AC_CHECK_HEADER(faad.h, have_flac="maybe")
+ if test "$have_flac" != "no"
+ then
+ AC_CHECK_LIB(FLAC, FLAC__stream_decoder_new, [
+ LIBS="$LIBS -lFLAC"
+ AC_DEFINE(HAVE_LIBFLAC, 1, [Define if you have libFLAC])
+ ICES_OBJECTS="$ICES_OBJECTS in_flac.o"
+ have_flac="yes"
+ ],[have_flac="no"])
+ fi
+fi
+
+if test "$with_flac" != "no" -a "$have_flac" != "yes"
+then
+ if test -n "$with_flac"
+ then
+ AC_MSG_ERROR([Could not find libFLAC])
+ else
+ AC_MSG_RESULT([Could not find libFLAC, FLAC transcoding disabled])
+ fi
+fi
+
dnl -- and finish up --
LIBS="$LIBS $LIBM $LIBDL"
@@ -359,3 +405,4 @@
AC_MSG_RESULT([ LAME : $have_LAME])
AC_MSG_RESULT([ Vorbis : $have_vorbis])
AC_MSG_RESULT([ MP4 : $have_faad])
+AC_MSG_RESULT([ FLAC : $have_flac])
Modified: icecast/trunk/ices0/src/Makefile.am
===================================================================
--- icecast/trunk/ices0/src/Makefile.am 2004-07-31 08:11:05 UTC (rev 7427)
+++ icecast/trunk/ices0/src/Makefile.am 2004-07-31 09:11:47 UTC (rev 7428)
@@ -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 in_mp4.h id3.h signals.h reencode.h \
- ices_config.h
+ cue.h metadata.h in_vorbis.h mp3.h in_mp4.h in_flac.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 in_mp4.c
+EXTRA_ices_SOURCES = ices_config.c reencode.c in_vorbis.c in_mp4.c in_flac.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-31 08:11:05 UTC (rev 7427)
+++ icecast/trunk/ices0/src/icestypes.h 2004-07-31 09:11:47 UTC (rev 7428)
@@ -79,7 +79,8 @@
typedef enum {
ICES_INPUT_VORBIS,
ICES_INPUT_MP3,
- ICES_INPUT_MP4
+ ICES_INPUT_MP4,
+ ICES_INPUT_FLAC
} input_type_t;
typedef struct _input_stream_t {
Added: icecast/trunk/ices0/src/in_flac.c
===================================================================
--- icecast/trunk/ices0/src/in_flac.c 2004-07-31 08:11:05 UTC (rev 7427)
+++ icecast/trunk/ices0/src/in_flac.c 2004-07-31 09:11:47 UTC (rev 7428)
@@ -0,0 +1,279 @@
+/* in_flac.c
+ * Plugin to read FLAC 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_flac.h"
+#include "metadata.h"
+
+#include <FLAC/stream_decoder.h>
+
+/* -- data structures -- */
+typedef struct {
+ FLAC__StreamDecoder* decoder;
+ unsigned char parsed;
+ /* read buffer */
+ char *buf;
+ size_t len;
+ /* write buffer */
+ int16_t *left;
+ int16_t *right;
+ size_t olen;
+} flac_in_t;
+
+/* -- static prototypes -- */
+static int ices_flac_readpcm (input_stream_t* self, size_t len,
+ int16_t* left, int16_t* right);
+static int ices_flac_close (input_stream_t* self);
+
+/* -- FLAC callbacks -- */
+static FLAC__StreamDecoderReadStatus
+flac_read_cb(const FLAC__StreamDecoder* decoder, FLAC__byte buffer[],
+ unsigned* bytes, void* client_data);
+static FLAC__StreamDecoderWriteStatus
+flac_write_cb(const FLAC__StreamDecoder* decoder, const FLAC__Frame* frame,
+ const FLAC__int32* const buffer[], void* client_data);
+static void
+flac_metadata_cb(const FLAC__StreamDecoder* decoder,
+ const FLAC__StreamMetadata* metadata, void* client_data);
+static void
+flac_error_cb(const FLAC__StreamDecoder* decoder,
+ FLAC__StreamDecoderErrorStatus status, void* client_data);
+
+/* try to open a FLAC file for decoding. Returns:
+ * 0: success
+ * 1: not a FLAC file
+ * -1: error opening
+ */
+int
+ices_flac_open (input_stream_t* self, char* buf, size_t len)
+{
+ flac_in_t* flac_data;
+ FLAC__StreamDecoder* decoder;
+
+ if (!(decoder = FLAC__stream_decoder_new())) {
+ ices_log_error("ices_flac_open: Error allocating FLAC decoder");
+ return -1;
+ }
+
+ FLAC__stream_decoder_set_read_callback(decoder, flac_read_cb);
+ FLAC__stream_decoder_set_write_callback(decoder, flac_write_cb);
+ FLAC__stream_decoder_set_metadata_callback(decoder, flac_metadata_cb);
+ FLAC__stream_decoder_set_error_callback(decoder, flac_error_cb);
+
+ FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
+
+ if (!(flac_data = (flac_in_t*)malloc (sizeof (flac_in_t)))) {
+ ices_log_error ("Malloc failed in ices_flac_open");
+ goto errDecoder;
+ }
+ FLAC__stream_decoder_set_client_data(decoder, self);
+
+ flac_data->decoder = decoder;
+ flac_data->parsed = 0;
+ flac_data->buf = buf;
+ flac_data->len = len;
+
+ self->data = flac_data;
+
+ switch (FLAC__stream_decoder_init(decoder)) {
+ case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
+ break;
+ case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
+ ices_log_error("Could not allocate memory during FLAC decoder init");
+ goto errData;
+ default:
+ ices_log_error("Unexpected error during FLAC decoder init");
+ goto errData;
+ }
+
+ if (!FLAC__stream_decoder_process_single(decoder)) {
+ ices_log_error("Could not find FLAC metadata header");
+ free(flac_data);
+ FLAC__stream_decoder_delete(decoder);
+ return 1;;
+ }
+ if (!flac_data->parsed) {
+ ices_log_error("Could not find FLAC metadata header in prebuffer");
+ goto errData;
+ }
+
+ self->type = ICES_INPUT_FLAC;
+
+ self->read = NULL;
+ self->readpcm = ices_flac_readpcm;
+ self->close = ices_flac_close;
+
+ if (!FLAC__stream_decoder_process_until_end_of_metadata(decoder)) {
+ ices_log_error("Error seeking past FLAC metadata");
+ goto errData;
+ }
+
+ return 0;
+
+errData:
+ free(flac_data);
+errDecoder:
+ FLAC__stream_decoder_delete(decoder);
+
+ return -1;
+}
+
+static int
+ices_flac_readpcm (input_stream_t* self, size_t olen, int16_t* left,
+ int16_t* right)
+{
+ flac_in_t* flac_data = (flac_in_t*)self->data;
+
+ flac_data->left = left;
+ flac_data->right = right;
+ flac_data->olen = olen;
+ if (!FLAC__stream_decoder_process_single(flac_data->decoder)) {
+ switch (FLAC__stream_decoder_get_state(flac_data->decoder)) {
+ case FLAC__STREAM_DECODER_END_OF_STREAM:
+ return 0;
+ default:
+ ices_log_error("Error reading FLAC stream");
+ }
+ }
+ if (FLAC__stream_decoder_get_state(flac_data->decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
+ return 0;
+
+ return flac_data->olen;
+}
+
+static int
+ices_flac_close (input_stream_t* self)
+{
+ flac_in_t* flac_data = (flac_in_t*) self->data;
+
+ FLAC__stream_decoder_finish(flac_data->decoder);
+ FLAC__stream_decoder_delete(flac_data->decoder);
+ free (flac_data);
+
+ return 0;
+}
+
+/* -- callbacks -- */
+static FLAC__StreamDecoderReadStatus
+flac_read_cb(const FLAC__StreamDecoder* decoder, FLAC__byte buffer[],
+ unsigned* bytes, void* client_data)
+{
+ input_stream_t* self = (input_stream_t*)client_data;
+ flac_in_t* flac_data = (flac_in_t*)self->data;
+ ssize_t len;
+ char errbuf[128];
+
+ if (!flac_data->len) {
+ if (!flac_data->parsed) {
+ *bytes = 0;
+ return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+ }
+ if ((len = read(self->fd, buffer, *bytes)) > 0)
+ return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+ if (!len)
+ return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+ ices_log_error("Error reading FLAC stream: %s", ices_util_strerror(errno, errbuf, sizeof(errbuf)));
+ return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+ }
+
+ if (flac_data->len < *bytes)
+ *bytes = flac_data->len;
+ memcpy(buffer, flac_data->buf, *bytes);
+ flac_data->len -= *bytes;
+
+ return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+}
+
+static FLAC__StreamDecoderWriteStatus
+flac_write_cb(const FLAC__StreamDecoder* decoder, const FLAC__Frame* frame,
+ const FLAC__int32* const buffer[], void* client_data)
+{
+ input_stream_t* self = (input_stream_t*)client_data;
+ flac_in_t* flac_data = (flac_in_t*)self->data;
+ int i;
+
+ for (i = 0; i < frame->header.blocksize; i++) {
+ flac_data->left[i] = buffer[0][i];
+ if (self->channels > 1)
+ flac_data->right[i] = buffer[1][i];
+ }
+ if (self->channels == 1)
+ memcpy(flac_data->right, flac_data->left, frame->header.blocksize << 1);
+
+ flac_data->olen = frame->header.blocksize;
+
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+static void
+flac_metadata_cb(const FLAC__StreamDecoder* decoder,
+ const FLAC__StreamMetadata* metadata, void* client_data)
+{
+ input_stream_t* self = (input_stream_t*)client_data;
+ flac_in_t* flac_data = (flac_in_t*)self->data;
+ FLAC__StreamMetadata_VorbisComment_Entry* comment;
+ char* artist = NULL;
+ char* title = NULL;
+ int i;
+
+ switch(metadata->type) {
+ case FLAC__METADATA_TYPE_STREAMINFO:
+ self->samplerate = metadata->data.stream_info.sample_rate;
+ self->channels = metadata->data.stream_info.channels;
+ flac_data->parsed = 1;
+ ices_log_debug("Found FLAC file, %d Hz, %d channels, %d bits", self->samplerate, self->channels, metadata->data.stream_info.bits_per_sample);
+ break;
+ case FLAC__METADATA_TYPE_VORBIS_COMMENT:
+ for (i = 0; i < metadata->data.vorbis_comment.num_comments; i++) {
+ comment = metadata->data.vorbis_comment.comments + i;
+
+ if (!strncasecmp("artist", comment->entry, 6))
+ artist = comment->entry + 7;
+ else if (!strncasecmp("title", comment->entry, 5))
+ title = comment->entry + 6;
+
+ ices_metadata_set(artist, title);
+ }
+ break;
+ default:
+ ices_log_debug("Ignoring unknown FLAC metadata type");
+ }
+}
+
+static void
+flac_error_cb(const FLAC__StreamDecoder* decoder,
+ FLAC__StreamDecoderErrorStatus status, void* client_data)
+{
+ switch (status) {
+ case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
+ ices_log_error("FLAC lost sync");
+ break;
+ case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
+ ices_log_error("Bad header in FLAC stream");
+ break;
+ case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
+ ices_log_error("Bad CRC for FLAC frame");
+ break;
+ default:
+ ices_log_error("Unspecified error decoding FLAC stream");
+ }
+}
Property changes on: icecast/trunk/ices0/src/in_flac.c
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: icecast/trunk/ices0/src/in_flac.h
===================================================================
--- icecast/trunk/ices0/src/in_flac.h 2004-07-31 08:11:05 UTC (rev 7427)
+++ icecast/trunk/ices0/src/in_flac.h 2004-07-31 09:11:47 UTC (rev 7428)
@@ -0,0 +1,30 @@
+/* in_flac.h
+ * ices input plugin to read FLAC 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_FLAC_H
+#define IN_FLAC_H
+
+#include "definitions.h"
+
+int ices_flac_open (input_stream_t* self, char* buf, size_t len);
+
+#endif
Property changes on: icecast/trunk/ices0/src/in_flac.h
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: icecast/trunk/ices0/src/setup.c
===================================================================
--- icecast/trunk/ices0/src/setup.c 2004-07-31 08:11:05 UTC (rev 7427)
+++ icecast/trunk/ices0/src/setup.c 2004-07-31 09:11:47 UTC (rev 7428)
@@ -592,6 +592,9 @@
#ifdef HAVE_LIBVORBISFILE
"Vorbis "
#endif
+#ifdef HAVE_LIBFLAC
+ "FLAC "
+#endif
#ifdef HAVE_LIBFAAD
"MP4"
#endif
Modified: icecast/trunk/ices0/src/stream.c
===================================================================
--- icecast/trunk/ices0/src/stream.c 2004-07-31 08:11:05 UTC (rev 7427)
+++ icecast/trunk/ices0/src/stream.c 2004-07-31 09:11:47 UTC (rev 7428)
@@ -29,6 +29,9 @@
#ifdef HAVE_LIBFAAD
#include "in_mp4.h"
#endif
+#ifdef HAVE_LIBFLAC
+#include "in_flac.h"
+#endif
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
@@ -356,14 +359,23 @@
return -1;
}
- #ifdef HAVE_LIBFAAD
+#ifdef HAVE_LIBFLAC
+ if (!(rc = ices_flac_open (source, buf, len)))
+ return 0;
+ if (rc < 0) {
+ close(fd);
+ return -1;
+ }
+#endif
+
+#ifdef HAVE_LIBFAAD
if (!(rc = ices_mp4_open (source, buf, len)))
return 0;
if (rc < 0) {
close(fd);
return -1;
}
- #endif
+#endif
if (!(rc = ices_mp3_open (source, buf, len)))
return 0;
More information about the commits
mailing list