Not working yet. aacdec still works.
aacdec.o: aacdec.c
$(CC) -c $(CPPFLAGS) $(DEBUG_CPPFLAGS) @faad_cppflags@ $<
+aac_common.o: aac_common.c
+ $(CC) -c $(CPPFLAGS) $(DEBUG_CPPFLAGS) @faad_cppflags@ $<
+
+aac_afh.o: aac_afh.c
+ $(CC) -c $(CPPFLAGS) $(DEBUG_CPPFLAGS) @faad_cppflags@ $<
+
para_recv: @recv_objs@
$(CC) @recv_objs@ -o $@ @recv_ldflags@
--- /dev/null
+#include <neaacdec.h>
+
+/* exported symbols from aac_common.c */
+NeAACDecHandle aac_open(void);
+int aac_find_esds(unsigned char *buf, unsigned buflen, int *skip);
--- /dev/null
+/*
+ * Copyright (C) 2006 Andre Noll <maan@systemlinux.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, USA.
+ */
+/** \file aac_afh.c para_server's aac audio format handler */
+
+
+#include "server.cmdline.h"
+#include "server.h"
+#include "afs.h"
+#include "error.h"
+#include "string.h"
+#include "aac.h"
+
+/* must be big enough to hold header */
+#define DEFAULT_INBUF_SIZE 65536
+
+static FILE *infile;
+static int inbuf_size;
+static unsigned char *inbuf;
+static ssize_t *chunk_table;
+struct audio_format *af;
+
+unsigned num_chunks, chunk_num;
+
+NeAACDecHandle handle;
+static void aac_close_audio_file(void)
+{
+}
+
+/*
+ * Init m4a file and write some tech data to given pointers.
+ */
+static int aac_get_file_info(FILE *file, char *info_str, long unsigned *frames,
+ int *seconds)
+{
+ int ret, skip, decoder_len;
+ unsigned inbuf_len;
+ unsigned long rate = 0;
+ unsigned char channels = 0;
+
+ free(inbuf);
+ inbuf_size = DEFAULT_INBUF_SIZE;
+ inbuf = para_malloc(inbuf_size);
+ infile = file;
+
+ PARA_INFO_LOG("file: %p\n", file);
+ ret = read(fileno(infile), inbuf, inbuf_size);
+ PARA_INFO_LOG("read %d bytes\n", ret);
+ if (ret <= 0)
+ return -E_AAC_READ;
+ PARA_INFO_LOG("checking aac %d bytes\n", ret);
+ inbuf_len = ret;
+ ret = aac_find_esds(inbuf, inbuf_len, &skip);
+ if (ret < 0)
+ return ret;
+ decoder_len = ret;
+ handle = aac_open();
+ ret = NeAACDecInit(handle, inbuf + skip,
+ inbuf_len - skip, &rate, &channels);
+ PARA_INFO_LOG("rate: %lu, channels: %d\n", rate, channels);
+
+ return 1;
+}
+
+/*
+ * Simple stream reposition routine
+ */
+static int aac_reposition_stream(long unsigned request)
+{
+ return -E_AAC_REPOS;
+}
+
+static int get_chunk_size(long unsigned chunk_num)
+{
+ int ret;
+ if (chunk_num >= num_chunks)
+ return -1;
+ ret = chunk_table[chunk_num + 1] - chunk_table[chunk_num];
+ if (!ret)
+ return ret;
+#if 0
+ PARA_DEBUG_LOG("chunk %d: %lli-%lli (%lli bytes)\n",
+ chunk_num,
+ chunk_table[chunk_num],
+ chunk_table[chunk_num + 1] - 1,
+ ret);
+#endif
+ return ret;
+}
+
+char *aac_read_chunk(long unsigned current_chunk, ssize_t *len)
+{
+ return (char *)inbuf;
+}
+
+void aac_afh_init(void *p)
+{
+ af = p;
+ af->reposition_stream = aac_reposition_stream;
+ af->get_file_info = aac_get_file_info,
+ af->read_chunk = aac_read_chunk;
+ af->close_audio_file = aac_close_audio_file;
+ af->get_header_info = NULL;
+ af->chunk_tv.tv_sec = 0;
+ af->chunk_tv.tv_usec = 250 * 1000;
+ tv_scale(3, &af->chunk_tv, &af->eof_tv);
+}
--- /dev/null
+#include "para.h"
+#include "aac.h"
+#include "error.h"
+
+NeAACDecHandle aac_open(void)
+{
+ NeAACDecHandle h = NeAACDecOpen();
+ NeAACDecConfigurationPtr c = NeAACDecGetCurrentConfiguration(h);
+
+ c->defObjectType = LC;
+ c->outputFormat = FAAD_FMT_16BIT;
+ c->downMatrix = 0;
+ NeAACDecSetConfiguration(h, c);
+ return h;
+};
+
+static int aac_read_decoder_length(unsigned char *buf, int *description_len)
+{
+ uint8_t b;
+ uint8_t numBytes = 0;
+ uint32_t length = 0;
+
+ do {
+ b = buf[numBytes];
+ numBytes++;
+ length = (length << 7) | (b & 0x7F);
+ } while
+ ((b & 0x80) && numBytes < 4);
+ *description_len = numBytes;
+ return length;
+}
+
+int aac_find_esds(unsigned char *buf, unsigned buflen, int *skip)
+{
+ int i;
+
+ for (i = 0; i + 4 < buflen; i++) {
+ unsigned char *p = buf + i;
+ int decoder_length, description_len;
+
+ if (p[0] != 'e' || p[1] != 's' || p[2] != 'd' || p[3] != 's')
+ continue;
+ i += 8;
+ p = buf + i;
+ PARA_INFO_LOG("found esds@%d, next: %x\n", i, *p);
+ if (*p == 3)
+ i += 8;
+ else
+ i += 6;
+ p = buf + i;
+ PARA_INFO_LOG("next: %x\n", *p);
+ if (*p != 4)
+ continue;
+ i += 18;
+ p = buf + i;
+ PARA_INFO_LOG("next: %x\n", *p);
+ if (*p != 5)
+ continue;
+ i++;
+ decoder_length = aac_read_decoder_length(p, &description_len);
+ PARA_INFO_LOG("decoder length: %d\n", decoder_length);
+ i += description_len;
+ *skip = i;
+ return decoder_length;
+ }
+ return -E_ESDS;
+}
+
+unsigned aac_read_int32(unsigned char *buf)
+{
+ uint8_t *d = (uint8_t*)buf;
+ return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
+}
+
+
+int find_stco(unsigned char *buf, unsigned buflen, int *skip)
+{
+ int i, ret;
+
+ for (i = 0; i + 16 < buflen; i++) {
+ unsigned char *p = buf + i;
+
+ if (p[0] != 's' || p[1] != 't' || p[2] != 'c' || p[3] != 'o')
+ continue;
+ PARA_INFO_LOG("found stco@%d\n", i);
+ i += 8;
+ ret = aac_read_int32(buf + i);
+ i += 4;
+ PARA_INFO_LOG("num entries: %d\n", ret);
+ *skip = i;
+ return ret;
+ }
+ return -E_STCO;
+}
+
#include "list.h"
#include "filter.h"
#include "error.h"
-#include <mad.h>
#include "string.h"
-
-#include <neaacdec.h>
+#include "aac.h"
/** the output buffer size */
#define MAX_CHANNELS 6
*/
struct private_mp4dec_data {
NeAACDecHandle decoder;
- NeAACDecConfigurationPtr config;
NeAACDecFrameInfo frame_info;
- mp4AudioSpecificConfig mp4ASC;
int initialized;
int decoder_length;
unsigned noffsets;
unsigned *offset;
+ unsigned offset0;
int offset_pos;
};
-static int read_mp4_descr_length(struct private_mp4dec_data *padd)
-{
- uint8_t b;
- uint8_t numBytes = 0;
- uint32_t length = 0;
-
- do {
- b = padd->inbuf[padd->consumed + numBytes];
- numBytes++;
- length = (length << 7) | (b & 0x7F);
- } while
- ((b & 0x80) && numBytes < 4);
- padd->consumed += numBytes;
- return length;
-}
-
-static int find_esds(struct private_mp4dec_data *padd)
-{
- for (; padd->consumed < padd->inbuf_len; padd->consumed++) {
- unsigned char *p = padd->inbuf + padd->consumed;
- int decoder_length;
-
- if (p[0] != 'e' || p[1] != 's' || p[2] != 'd' || p[3] != 's')
- continue;
- padd->consumed += 8;
- p = padd->inbuf + padd->consumed;
- PARA_INFO_LOG("found esds: %d, next: %x\n", padd->consumed, *p);
- if (*p == 3)
- padd->consumed += 8;
- else
- padd->consumed += 6;
- p = padd->inbuf + padd->consumed;
- PARA_INFO_LOG("next: %x\n", *p);
- if (*p != 4)
- continue;
- padd->consumed += 18;
- p = padd->inbuf + padd->consumed;
- PARA_INFO_LOG("next: %x\n", *p);
- if (*p != 5)
- continue;
- padd->consumed++;
- decoder_length = read_mp4_descr_length(padd);
- PARA_INFO_LOG("decoder length: %d\n", decoder_length);
- p = padd->inbuf + padd->consumed;
- PARA_INFO_LOG("decoder data0: %x\n", *p & 0xff);
- p++;
- PARA_INFO_LOG("decoder data1: %x\n", *p & 0xff);
- return decoder_length;
- }
- return -E_ESDS;
-}
-
static int read_int32(struct private_mp4dec_data *padd, unsigned *result)
{
uint8_t *d = (uint8_t*)(padd->inbuf + padd->consumed);
padd->inbuf_len = len;
if (!padd->initialized) {
- padd->decoder_length = find_esds(padd);
+ int skip;
+ padd->decoder_length = aac_find_esds(padd->inbuf, padd->inbuf_len,
+ &skip);
if (padd->decoder_length < 0) {
ret = NeAACDecInit(padd->decoder, padd->inbuf,
padd->inbuf_len, &rate, &channels);
}
padd->consumed = ret;
} else {
+ padd->consumed += skip;
p = padd->inbuf + padd->consumed;
ret = E_AACDEC_INIT;
if (NeAACDecInit2(padd->decoder, p,
fn->bufsize = AAC_OUTBUF_SIZE;
fn->buf = para_calloc(fn->bufsize);
-
- padd->decoder = NeAACDecOpen();
- padd->config = NeAACDecGetCurrentConfiguration(padd->decoder);
- padd->config->defObjectType = LC;
- padd->config->outputFormat = FAAD_FMT_16BIT;
- padd->config->downMatrix = 0;
- NeAACDecSetConfiguration(padd->decoder, padd->config);
+ padd->decoder = aac_open();
}
static void mp4dec_close(struct filter_node *fn)
* the current audio format, audio file selector and of the activated senders.
*/
+#include "server.h"
#include <sys/time.h> /* gettimeofday */
#include "server.cmdline.h"
#include "db.h"
-#include "server.h"
#include "afs.h"
#include "send.h"
#include "error.h"
#ifdef HAVE_OGGVORBIS
void ogg_init(void *);
#endif
+#ifdef HAVE_FAAD
+ void aac_afh_init(void *);
+#endif
/**
* the list of supported audio formats
.name = "ogg",
.init = ogg_init,
},
+#endif
+#ifdef HAVE_FAAD
+ {
+ .name = "aac",
+ .init = aac_afh_init,
+ },
#endif
{
.name = NULL,
#define OV_AUDIO_FORMAT_ARRAY
#endif
-#define SUPPORTED_AUDIO_FORMATS "mp3" OV_AUDIO_FORMAT
-#define SUPPORTED_AUDIO_FORMATS_ARRAY "mp3" OV_AUDIO_FORMAT_ARRAY, NULL
+#ifdef HAVE_FAAD
+#define AAC_AUDIO_FORMAT " aac"
+#define AAC_AUDIO_FORMAT_ARRAY , "aac"
+#else
+#define AAC_AUDIO_FORMAT ""
+#define AAC_AUDIO_FORMAT_ARRAY
+#endif
+#define SUPPORTED_AUDIO_FORMATS "mp3" OV_AUDIO_FORMAT AAC_AUDIO_FORMAT
+#define SUPPORTED_AUDIO_FORMATS_ARRAY "mp3" OV_AUDIO_FORMAT_ARRAY \
+ AAC_AUDIO_FORMAT_ARRAY, NULL
/* status flags */
#define AFS_NOMORE 1
AC_CHECK_LIB([faad], [NeAACDecOpen], [], have_faad=no)
if test "$have_faad" = "yes"; then
AC_DEFINE(HAVE_FAAD, 1, define to 1 if you want to build the aacdec filter)
- filter_errlist_objs="$filter_errlist_objs aacdec"
- audiod_errlist_objs="$audiod_errlist_objs aacdec"
+ filter_errlist_objs="$filter_errlist_objs aacdec aac_common"
+ audiod_errlist_objs="$audiod_errlist_objs aacdec aac_common"
+ server_errlist_objs="$server_errlist_objs aac_afh aac_common"
+ server_ldflags="$server_ldflags $faad_libs -lfaad"
filter_ldflags="$filter_ldflags $faad_libs -lfaad"
audiod_ldflags="$audiod_ldflags $faad_libs -lfaad"
AC_SUBST(faad_cppflags)
SS_DB,
SS_OGG,
SS_MP3,
+ SS_AAC_AFH,
SS_MP3DEC,
SS_AACDEC,
+ SS_AAC_COMMON,
SS_SERVER,
SS_AFS,
SS_MYSQL_SELECTOR,
PARA_ERROR(HEADER_BITRATE, "invalid header bitrate"), \
+#define AAC_AFH_ERRORS \
+ PARA_ERROR(AAC_REPOS, "aac repositioning error"), \
+ PARA_ERROR(AAC_READ, "aac read error"), \
+
+
+#define AAC_COMMON_ERRORS \
+ PARA_ERROR(AAC_OPEN, "NeAACDecOpen() failed"), \
+ PARA_ERROR(AAC_BUF, "invalid buffer"), \
+
#define OGG_ERRORS \
PARA_ERROR(OGG_READ, "ogg read error"), \
PARA_ERROR(SYNC_PAGEOUT, "ogg sync page-out error (no ogg file?)"), \
SS_ENUM(FILTER);
SS_ENUM(MP3);
SS_ENUM(OGG);
+SS_ENUM(AAC_AFH);
+SS_ENUM(AAC_COMMON);
SS_ENUM(SERVER);
SS_ENUM(AFS);
SS_ENUM(COMMAND);