From: Andre Date: Fri, 12 May 2006 18:38:45 +0000 (+0200) Subject: First draft of the aac audio format handler X-Git-Tag: v0.2.14~138 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=55f0f9461990455656bef7a36b0f963e3d676653 First draft of the aac audio format handler Not working yet. aacdec still works. --- diff --git a/Makefile.in b/Makefile.in index ee0cca6e..e2214945 100644 --- a/Makefile.in +++ b/Makefile.in @@ -142,6 +142,12 @@ grab_client.cmdline.h grab_client.cmdline.c: grab_client.ggo 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@ diff --git a/aac.h b/aac.h new file mode 100644 index 00000000..8ae7502e --- /dev/null +++ b/aac.h @@ -0,0 +1,5 @@ +#include + +/* exported symbols from aac_common.c */ +NeAACDecHandle aac_open(void); +int aac_find_esds(unsigned char *buf, unsigned buflen, int *skip); diff --git a/aac_afh.c b/aac_afh.c new file mode 100644 index 00000000..436005e0 --- /dev/null +++ b/aac_afh.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2006 Andre Noll + * + * 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); +} diff --git a/aac_common.c b/aac_common.c new file mode 100644 index 00000000..16109b95 --- /dev/null +++ b/aac_common.c @@ -0,0 +1,95 @@ +#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; +} + diff --git a/aacdec.c b/aacdec.c index 0eab773a..7ea7856f 100644 --- a/aacdec.c +++ b/aacdec.c @@ -28,10 +28,8 @@ #include "list.h" #include "filter.h" #include "error.h" -#include #include "string.h" - -#include +#include "aac.h" /** the output buffer size */ #define MAX_CHANNELS 6 @@ -44,9 +42,7 @@ */ struct private_mp4dec_data { NeAACDecHandle decoder; - NeAACDecConfigurationPtr config; NeAACDecFrameInfo frame_info; - mp4AudioSpecificConfig mp4ASC; int initialized; int decoder_length; @@ -57,61 +53,10 @@ struct private_mp4dec_data { 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); @@ -173,7 +118,9 @@ static ssize_t mp4dec(char *inbuffer, size_t len, struct filter_node *fn) 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); @@ -183,6 +130,7 @@ static ssize_t mp4dec(char *inbuffer, size_t len, struct filter_node *fn) } padd->consumed = ret; } else { + padd->consumed += skip; p = padd->inbuf + padd->consumed; ret = E_AACDEC_INIT; if (NeAACDecInit2(padd->decoder, p, @@ -260,13 +208,7 @@ static void mp4dec_open(struct filter_node *fn) 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) diff --git a/afs.c b/afs.c index 6cc58bb4..29bae161 100644 --- a/afs.c +++ b/afs.c @@ -22,10 +22,10 @@ * the current audio format, audio file selector and of the activated senders. */ +#include "server.h" #include /* gettimeofday */ #include "server.cmdline.h" #include "db.h" -#include "server.h" #include "afs.h" #include "send.h" #include "error.h" @@ -51,6 +51,9 @@ static FILE *audio_file = NULL; #ifdef HAVE_OGGVORBIS void ogg_init(void *); #endif +#ifdef HAVE_FAAD + void aac_afh_init(void *); +#endif /** * the list of supported audio formats @@ -67,6 +70,12 @@ struct audio_format afl[] = { .name = "ogg", .init = ogg_init, }, +#endif +#ifdef HAVE_FAAD + { + .name = "aac", + .init = aac_afh_init, + }, #endif { .name = NULL, diff --git a/afs.h b/afs.h index f1dc9b94..cc96dbbb 100644 --- a/afs.h +++ b/afs.h @@ -27,9 +27,17 @@ #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 diff --git a/configure.ac b/configure.ac index 91cd2842..89720902 100644 --- a/configure.ac +++ b/configure.ac @@ -233,8 +233,10 @@ AC_CHECK_HEADER(neaacdec.h, [], have_faad=no) 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) diff --git a/error.h b/error.h index 614390f2..eda69627 100644 --- a/error.h +++ b/error.h @@ -48,8 +48,10 @@ enum para_subsystem { SS_DB, SS_OGG, SS_MP3, + SS_AAC_AFH, SS_MP3DEC, SS_AACDEC, + SS_AAC_COMMON, SS_SERVER, SS_AFS, SS_MYSQL_SELECTOR, @@ -188,6 +190,15 @@ extern const char **para_errlist[]; 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?)"), \ @@ -448,6 +459,8 @@ SS_ENUM(AACDEC); 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);