diff options
author | Max Kellermann <max@duempel.org> | 2008-08-26 08:27:11 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2008-08-26 08:27:11 +0200 |
commit | e99333167e152dcdd3b40ae812f920eb5023543a (patch) | |
tree | 3e9358e115aebac8e3bf601a62455a5c99e4f196 /src/inputPlugins/aac_plugin.c | |
parent | 5300f79ca98c55b367a612c93f0d7b2eef72ad23 (diff) | |
download | mpd-e99333167e152dcdd3b40ae812f920eb5023543a.tar.gz mpd-e99333167e152dcdd3b40ae812f920eb5023543a.tar.xz mpd-e99333167e152dcdd3b40ae812f920eb5023543a.zip |
aac: support decoding AAC streams
Copy some code from aac_decode() to aac_stream_decode() and apply
necessary changes to allow streaming audio data. Both functions might
be merged later.
Diffstat (limited to 'src/inputPlugins/aac_plugin.c')
-rw-r--r-- | src/inputPlugins/aac_plugin.c | 139 |
1 files changed, 137 insertions, 2 deletions
diff --git a/src/inputPlugins/aac_plugin.c b/src/inputPlugins/aac_plugin.c index a01d4ccbf..c168e9bef 100644 --- a/src/inputPlugins/aac_plugin.c +++ b/src/inputPlugins/aac_plugin.c @@ -300,6 +300,141 @@ static int getAacTotalTime(char *file) return file_time; } +static int aac_stream_decode(struct decoder * mpd_decoder, + InputStream *inStream) +{ + float file_time; + float totalTime = 0; + faacDecHandle decoder; + faacDecFrameInfo frameInfo; + faacDecConfigurationPtr config; + long bread; + AudioFormat audio_format; + uint32_t sampleRate; + unsigned char channels; + unsigned int sampleCount; + char *sampleBuffer; + size_t sampleBufferLen; + mpd_uint16 bitRate = 0; + AacBuffer b; + int initialized = 0; + + initAacBuffer(inStream, &b); + + decoder = faacDecOpen(); + + config = faacDecGetCurrentConfiguration(decoder); + config->outputFormat = FAAD_FMT_16BIT; +#ifdef HAVE_FAACDECCONFIGURATION_DOWNMATRIX + config->downMatrix = 1; +#endif +#ifdef HAVE_FAACDECCONFIGURATION_DONTUPSAMPLEIMPLICITSBR + config->dontUpSampleImplicitSBR = 0; +#endif + faacDecSetConfiguration(decoder, config); + + while (b.bytesIntoBuffer < FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS && + !b.atEof && + decoder_get_command(mpd_decoder) == DECODE_COMMAND_NONE) { + fillAacBuffer(&b); + adts_find_frame(&b); + fillAacBuffer(&b); + my_usleep(10000); + } + +#ifdef HAVE_FAAD_BUFLEN_FUNCS + bread = faacDecInit(decoder, b.buffer, b.bytesIntoBuffer, + &sampleRate, &channels); +#else + bread = faacDecInit(decoder, b.buffer, &sampleRate, &channels); +#endif + if (bread < 0) { + ERROR("Error not a AAC stream.\n"); + faacDecClose(decoder); + if (b.buffer) + free(b.buffer); + return -1; + } + + audio_format.bits = 16; + + file_time = 0.0; + + advanceAacBuffer(&b, bread); + + while (1) { + fillAacBuffer(&b); + adts_find_frame(&b); + fillAacBuffer(&b); + + if (b.bytesIntoBuffer == 0) + break; + +#ifdef HAVE_FAAD_BUFLEN_FUNCS + sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer, + b.bytesIntoBuffer); +#else + sampleBuffer = faacDecDecode(decoder, &frameInfo, b.buffer); +#endif + + if (frameInfo.error > 0) { + ERROR("error decoding AAC stream\n"); + ERROR("faad2 error: %s\n", + faacDecGetErrorMessage(frameInfo.error)); + break; + } +#ifdef HAVE_FAACDECFRAMEINFO_SAMPLERATE + sampleRate = frameInfo.samplerate; +#endif + + if (!initialized) { + audio_format.channels = frameInfo.channels; + audio_format.sampleRate = sampleRate; + decoder_initialized(mpd_decoder, &audio_format, totalTime); + initialized = 1; + } + + advanceAacBuffer(&b, frameInfo.bytesconsumed); + + sampleCount = (unsigned long)(frameInfo.samples); + + if (sampleCount > 0) { + bitRate = frameInfo.bytesconsumed * 8.0 * + frameInfo.channels * sampleRate / + frameInfo.samples / 1000 + 0.5; + file_time += + (float)(frameInfo.samples) / frameInfo.channels / + sampleRate; + } + + sampleBufferLen = sampleCount * 2; + + decoder_data(mpd_decoder, NULL, 0, sampleBuffer, + sampleBufferLen, file_time, + bitRate, NULL); + if (decoder_get_command(mpd_decoder) == DECODE_COMMAND_SEEK) { + decoder_seek_error(mpd_decoder); + } else if (decoder_get_command(mpd_decoder) == DECODE_COMMAND_STOP) + break; + } + + decoder_flush(mpd_decoder); + + faacDecClose(decoder); + if (b.buffer) + free(b.buffer); + + if (!initialized) + return -1; + + if (decoder_get_command(mpd_decoder) == DECODE_COMMAND_SEEK) { + decoder_seek_error(mpd_decoder); + } + + return 0; +} + + static int aac_decode(struct decoder * mpd_decoder, char *path) { float file_time; @@ -461,10 +596,10 @@ struct decoder_plugin aacPlugin = { NULL, NULL, NULL, - NULL, + aac_stream_decode, aac_decode, aacTagDup, - INPUT_PLUGIN_STREAM_FILE, + INPUT_PLUGIN_STREAM_FILE | INPUT_PLUGIN_STREAM_URL, aac_suffixes, aac_mimeTypes }; |