X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=aacdec_filter.c;h=a2459d82b31991a8e9ac578e0559a398c83f4e10;hp=59c49893f59acc58a6df8c5d8b7386b8008c3dca;hb=HEAD;hpb=395aeb9da9c9cc2febe91b5a906c72e59e217594 diff --git a/aacdec_filter.c b/aacdec_filter.c index 59c49893..87a7900a 100644 --- a/aacdec_filter.c +++ b/aacdec_filter.c @@ -1,8 +1,4 @@ -/* - * Copyright (C) 2006-2009 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ +/* Copyright (C) 2006 Andre Noll , see file COPYING. */ /* * based in parts on libfaad, Copyright (C) 2003-2005 M. Bakker, * Ahead Software AG @@ -11,186 +7,158 @@ /** \file aacdec_filter.c paraslash's aac (m4a) decoder. */ #include +#include #include "para.h" +#include "portable_io.h" #include "list.h" #include "sched.h" -#include "ggo.h" +#include "buffer_tree.h" #include "filter.h" #include "error.h" #include "string.h" -#include "aac.h" - -/** the output buffer size */ -#define AAC_OUTBUF_SIZE (32 * 1024) -/** give up decoding after that many errors */ +/** Give up decoding after that many errors. */ #define MAX_ERRORS 20 /** * data specific to the aacdec filter * - * \sa filter, filter_node + * \sa \ref filter, \ref filter_node. */ struct private_aacdec_data { /** the return value of aac_open */ NeAACDecHandle handle; - /** info about the currently decoded frame */ - NeAACDecFrameInfo frame_info; /** whether this instance of the aac decoder is already initialized */ - int initialized; - /** - * return value of aac_find_esds(). Used to call the right aacdec - * init function - */ - unsigned long decoder_length; + bool initialized; /** number of times the decoder returned an error */ unsigned error_count; /** number of bytes already consumed from the imput stream */ size_t consumed_total; - /** return value of aac_find_entry_point */ - size_t entry; + /** The number of channels of the current stream. */ + unsigned int channels; + /** Current sample rate in Hz. */ + unsigned int sample_rate; }; -static ssize_t aacdec(char *input_buffer, size_t len, struct filter_node *fn) +static int aacdec_execute(struct btr_node *btrn, const char *cmd, char **result) { + struct filter_node *fn = btr_context(btrn); + struct private_aacdec_data *padd = fn->private_data; + + return decoder_execute(cmd, padd->sample_rate, padd->channels, result); +} + +static void aacdec_open(struct filter_node *fn) +{ + NeAACDecConfigurationPtr c; + struct private_aacdec_data *padd = zalloc(sizeof(*padd)); + + padd->handle = NeAACDecOpen(); + c = NeAACDecGetCurrentConfiguration(padd->handle); + c->defObjectType = LC; + c->outputFormat = FAAD_FMT_16BIT; + c->downMatrix = 0; + NeAACDecSetConfiguration(padd->handle, c); + + fn->private_data = padd; + fn->min_iqs = 2048; +} + +static void aacdec_close(struct filter_node *fn) +{ + struct private_aacdec_data *padd = fn->private_data; + + NeAACDecClose(padd->handle); + free(padd); + fn->private_data = NULL; +} + +static int aacdec_post_monitor(__a_unused struct sched *s, void *context) +{ + struct filter_node *fn = context; + struct btr_node *btrn = fn->btrn; struct private_aacdec_data *padd = fn->private_data; - struct filter_chain *fc = fn->fc; int i, ret; - unsigned char *p, *outbuffer; - unsigned char *inbuf = (unsigned char*)input_buffer; - size_t skip, consumed = 0; + char *inbuf, *outbuf, *btrbuf; + size_t len, consumed, loaded = 0; + NeAACDecFrameInfo frame_info; - if (fn->loaded > fn->bufsize * 3 / 5) - return 0; - ret = *fc->input_error; +next_buffer: + ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL); if (ret < 0) - return ret; - if (len < 2048) + goto err; + if (ret == 0) return 0; - + btr_merge(btrn, fn->min_iqs); + len = btr_next_buffer(btrn, &inbuf); + len = PARA_MIN(len, (size_t)8192); + consumed = 0; if (!padd->initialized) { unsigned long rate = 0; unsigned char channels = 0; - ret = aac_find_esds(inbuf, len, &skip, &padd->decoder_length); + ret = NeAACDecInit(padd->handle, (unsigned char *)inbuf, + len, &rate, &channels); + PARA_INFO_LOG("decoder init: %d\n", ret); if (ret < 0) { - PARA_INFO_LOG("%s\n", para_strerror(-ret)); - ret = NeAACDecInit(padd->handle, inbuf, - len, &rate, &channels); - PARA_INFO_LOG("decoder init: %d\n", ret); - if (ret < 0) { - ret = -E_AACDEC_INIT; - goto out; - } - consumed = ret; - } else { - PARA_INFO_LOG("decoder len: %lu\n", - padd->decoder_length); - consumed += skip; - p = inbuf + consumed; ret = -E_AACDEC_INIT; - if (NeAACDecInit2(padd->handle, p, - padd->decoder_length, &rate, - &channels) < 0) - goto out; - } - fc->samplerate = rate; - fc->channels = channels; - PARA_INFO_LOG("rate: %u, channels: %d\n", - fc->samplerate, fc->channels); - padd->initialized = 1; - } - if (padd->decoder_length > 0) { - consumed = 0; - if (!padd->entry) { - ret = aac_find_entry_point(inbuf + consumed, - len - consumed, &skip); - if (ret < 0) { - ret = len; - goto out; - } - consumed += skip; - padd->entry = ret; - PARA_INFO_LOG("entry: %zu\n", padd->entry); + goto err; } - ret = len; - if (padd->consumed_total + len < padd->entry) - goto out; - if (padd->consumed_total < padd->entry) - consumed = padd->entry - padd->consumed_total; + consumed = ret; + padd->sample_rate = rate; + padd->channels = channels; + PARA_INFO_LOG("rate: %u, channels: %u\n", + padd->sample_rate, padd->channels); + padd->initialized = true; } - for (; consumed < len; consumed++) - if ((inbuf[consumed] & 0xfe) == 0x20) - break; if (consumed >= len) goto success; - p = inbuf + consumed; - outbuffer = NeAACDecDecode(padd->handle, &padd->frame_info, p, - len - consumed); - if (padd->frame_info.error) { + //PARA_CRIT_LOG("consumed: %zu (%zu + %zu), have: %zu\n", padd->consumed_total + consumed, + // padd->consumed_total, consumed, len - consumed); + outbuf = NeAACDecDecode(padd->handle, &frame_info, + (unsigned char *)inbuf + consumed, len - consumed); + if (frame_info.error) { + int err = frame_info.error; ret = -E_AAC_DECODE; if (padd->error_count++ > MAX_ERRORS) - goto out; - PARA_ERROR_LOG("frame_error: %d, consumed: %zu + %zd + %lu\n", - padd->frame_info.error, padd->consumed_total, - consumed, padd->frame_info.bytesconsumed); - PARA_ERROR_LOG("%s\n", NeAACDecGetErrorMessage( - padd->frame_info.error)); - consumed++; /* catch 21 */ + goto err; + PARA_NOTICE_LOG("error #%u: (%s)\n", padd->error_count, + NeAACDecGetErrorMessage(err)); + PARA_NOTICE_LOG("consumed (total, buffer, frame): " + "%zu, %zu, %lu\n", + padd->consumed_total, consumed, + frame_info.bytesconsumed); + consumed++; /* just eat one byte and hope for the best */ goto success; } padd->error_count = 0; - consumed += padd->frame_info.bytesconsumed; - ret = consumed; - if (!padd->frame_info.samples) - goto out; - ret = -E_AAC_OVERRUN; - if (padd->frame_info.samples * 2 + fn->loaded > fn->bufsize) - goto out; - for (i = 0; i < padd->frame_info.samples; i++) { - short *s = (short *)outbuffer; - write_int16_host_endian(fn->buf + fn->loaded, s[i]); - fn->loaded += 2; + //PARA_CRIT_LOG("decoder ate %lu\n", frame_info.bytesconsumed); + consumed += frame_info.bytesconsumed; + if (!frame_info.samples) + goto success; + btrbuf = arr_alloc(2, frame_info.samples); + for (i = 0; i < frame_info.samples; i++) { + short sh = ((short *)outbuf)[i]; + write_int16_host_endian(btrbuf + loaded, sh); + loaded += 2; } + btr_add_output(btrbuf, loaded, btrn); success: - ret = consumed; -out: - if (ret > 0) - padd->consumed_total += ret; + btr_consume(btrn, consumed); + padd->consumed_total += consumed; + if (loaded == 0) + goto next_buffer; + return 1; +err: + assert(ret < 0); + btr_remove_node(&fn->btrn); return ret; } -static void aacdec_open(struct filter_node *fn) -{ - struct private_aacdec_data *padd = para_calloc(sizeof(*padd)); - - fn->private_data = padd; - fn->bufsize = AAC_OUTBUF_SIZE; - fn->buf = para_calloc(fn->bufsize); - padd->handle = aac_open(); -} - -static void aacdec_close(struct filter_node *fn) -{ - struct private_aacdec_data *padd = fn->private_data; - - NeAACDecClose(padd->handle); - free(fn->buf); - fn->buf = NULL; - free(padd); - fn->private_data = NULL; -} - -/** - * the init function of the aacdec filter - * - * \param f pointer to the filter struct to initialize - * - * \sa filter::init - */ -void aacdec_filter_init(struct filter *f) -{ - f->open = aacdec_open; - f->convert = aacdec; - f->close = aacdec_close; -} +const struct filter lsg_filter_cmd_com_aacdec_user_data = { + .open = aacdec_open, + .close = aacdec_close, + .pre_monitor = generic_filter_pre_monitor, + .post_monitor = aacdec_post_monitor, + .execute = aacdec_execute +};