summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/aac_bsf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/aac_bsf.c')
-rw-r--r--lib/rbcodec/codecs/aac_bsf.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/aac_bsf.c b/lib/rbcodec/codecs/aac_bsf.c
new file mode 100644
index 0000000000..3bce283958
--- /dev/null
+++ b/lib/rbcodec/codecs/aac_bsf.c
@@ -0,0 +1,157 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Codec for aac files without container
11 *
12 * Written by Igor B. Poretsky
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23
24#include "codeclib.h"
25#include "libfaad/common.h"
26#include "libfaad/structs.h"
27#include "libfaad/decoder.h"
28
29CODEC_HEADER
30
31/* The maximum buffer size handled by faad. 12 bytes are required by libfaad
32 * as headroom (see libfaad/bits.c). FAAD_BYTE_BUFFER_SIZE bytes are buffered
33 * for each frame. */
34#define FAAD_BYTE_BUFFER_SIZE (2048-12)
35
36static void update_playing_time(void)
37{
38 ci->set_elapsed((unsigned long)((ci->id3->offset - ci->id3->first_frame_offset) * 8LL / ci->id3->bitrate));
39}
40
41/* this is the codec entry point */
42enum codec_status codec_main(enum codec_entry_call_reason reason)
43{
44 if (reason == CODEC_LOAD) {
45 /* Generic codec initialisation */
46 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
47 ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
48 }
49
50 return CODEC_OK;
51}
52
53/* this is called for each file to process */
54enum codec_status codec_run(void)
55{
56 size_t n;
57 int32_t bread;
58 unsigned int frame_samples;
59 uint32_t s = 0;
60 unsigned char c = 0;
61 long action = CODEC_ACTION_NULL;
62 intptr_t param;
63 unsigned char* buffer;
64 NeAACDecFrameInfo frame_info;
65 NeAACDecHandle decoder;
66 NeAACDecConfigurationPtr conf;
67
68 /* Clean and initialize decoder structures */
69 if (codec_init()) {
70 LOGF("FAAD: Codec init error\n");
71 return CODEC_ERROR;
72 }
73
74 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
75 codec_set_replaygain(ci->id3);
76
77 ci->seek_buffer(ci->id3->first_frame_offset);
78
79 /* initialise the sound converter */
80 decoder = NeAACDecOpen();
81
82 if (!decoder) {
83 LOGF("FAAD: Decode open error\n");
84 return CODEC_ERROR;
85 }
86
87 conf = NeAACDecGetCurrentConfiguration(decoder);
88 conf->outputFormat = FAAD_FMT_24BIT; /* irrelevant, we don't convert */
89 NeAACDecSetConfiguration(decoder, conf);
90
91 buffer=ci->request_buffer(&n, FAAD_BYTE_BUFFER_SIZE);
92 bread = NeAACDecInit(decoder, buffer, n, &s, &c);
93 if (bread < 0) {
94 LOGF("FAAD: DecInit: %ld, %d\n", bread, decoder->object_type);
95 return CODEC_ERROR;
96 }
97 ci->advance_buffer(bread);
98
99 if (ci->id3->offset > ci->id3->first_frame_offset) {
100 /* Resume the desired (byte) position. */
101 ci->seek_buffer(ci->id3->offset);
102 NeAACDecPostSeekReset(decoder, 0);
103 update_playing_time();
104 } else if (ci->id3->elapsed) {
105 action = CODEC_ACTION_SEEK_TIME;
106 param = ci->id3->elapsed;
107 } else {
108 ci->set_elapsed(0);
109 ci->set_offset(ci->id3->first_frame_offset);
110 }
111
112 /* The main decoding loop */
113 while (1) {
114 if (action == CODEC_ACTION_NULL)
115 action = ci->get_command(&param);
116
117 if (action == CODEC_ACTION_HALT)
118 break;
119
120 /* Deal with any pending seek requests */
121 if (action == CODEC_ACTION_SEEK_TIME) {
122 /* Seek to the desired time position. */
123 ci->seek_buffer(ci->id3->first_frame_offset + (uint32_t)((uint64_t)param * ci->id3->bitrate / 8));
124 ci->set_elapsed((unsigned long)param);
125 NeAACDecPostSeekReset(decoder, 0);
126 ci->seek_complete();
127 }
128
129 action = CODEC_ACTION_NULL;
130
131 /* Request the required number of bytes from the input buffer */
132 buffer=ci->request_buffer(&n, FAAD_BYTE_BUFFER_SIZE);
133
134 if (n == 0) /* End of Stream */
135 break;
136
137 /* Decode one block - returned samples will be host-endian */
138 if (NeAACDecDecode(decoder, &frame_info, buffer, n) == NULL || frame_info.error > 0) {
139 LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error));
140 return CODEC_ERROR;
141 }
142
143 /* Advance codec buffer (no need to call set_offset because of this) */
144 ci->advance_buffer(frame_info.bytesconsumed);
145
146 /* Output the audio */
147 ci->yield();
148 frame_samples = frame_info.samples >> 1;
149 ci->pcmbuf_insert(&decoder->time_out[0][0], &decoder->time_out[1][0], frame_samples);
150
151 /* Update the elapsed-time indicator */
152 update_playing_time();
153 }
154
155 LOGF("AAC: Decoding complete\n");
156 return CODEC_OK;
157}