diff options
Diffstat (limited to 'apps/codecs/aac.c')
-rw-r--r-- | apps/codecs/aac.c | 129 |
1 files changed, 75 insertions, 54 deletions
diff --git a/apps/codecs/aac.c b/apps/codecs/aac.c index 6c86f38372..0c48422a53 100644 --- a/apps/codecs/aac.c +++ b/apps/codecs/aac.c | |||
@@ -29,6 +29,8 @@ CODEC_HEADER | |||
29 | extern char iramcopy[]; | 29 | extern char iramcopy[]; |
30 | extern char iramstart[]; | 30 | extern char iramstart[]; |
31 | extern char iramend[]; | 31 | extern char iramend[]; |
32 | extern char iedata[]; | ||
33 | extern char iend[]; | ||
32 | #endif | 34 | #endif |
33 | 35 | ||
34 | struct codec_api* rb; | 36 | struct codec_api* rb; |
@@ -37,27 +39,35 @@ struct codec_api* ci; | |||
37 | /* this is the codec entry point */ | 39 | /* this is the codec entry point */ |
38 | enum codec_status codec_start(struct codec_api* api) | 40 | enum codec_status codec_start(struct codec_api* api) |
39 | { | 41 | { |
42 | /* Note that when dealing with QuickTime/MPEG4 files, terminology is | ||
43 | * a bit confusing. Files with sound are split up in chunks, where | ||
44 | * each chunk contains one or more samples. Each sample in turn | ||
45 | * contains a number of "sound samples" (the kind you refer to with | ||
46 | * the sampling frequency). | ||
47 | */ | ||
40 | size_t n; | 48 | size_t n; |
41 | static demux_res_t demux_res; | 49 | static demux_res_t demux_res; |
42 | stream_t input_stream; | 50 | stream_t input_stream; |
43 | uint32_t samplesdone; | 51 | uint32_t sound_samples_done; |
44 | uint32_t elapsedtime; | 52 | uint32_t elapsed_time; |
45 | uint32_t sample_duration; | 53 | uint32_t sample_duration; |
46 | uint32_t sample_byte_size; | 54 | uint32_t sample_byte_size; |
47 | int samplesdecoded; | 55 | int file_offset; |
48 | unsigned int i; | 56 | unsigned int i; |
49 | unsigned char* buffer; | 57 | unsigned char* buffer; |
50 | static NeAACDecFrameInfo frameInfo; | 58 | static NeAACDecFrameInfo frame_info; |
51 | NeAACDecHandle hDecoder; | 59 | NeAACDecHandle decoder; |
52 | int err; | 60 | int err; |
53 | int16_t* decodedbuffer; | 61 | uint32_t s = 0; |
62 | unsigned char c = 0; | ||
54 | 63 | ||
55 | /* Generic codec initialisation */ | 64 | /* Generic codec initialisation */ |
56 | rb = api; | 65 | rb = api; |
57 | ci = api; | 66 | ci = api; |
58 | 67 | ||
59 | #ifndef SIMULATOR | 68 | #ifndef SIMULATOR |
60 | rb->memcpy(iramstart, iramcopy, iramend-iramstart); | 69 | ci->memcpy(iramstart, iramcopy, iramend-iramstart); |
70 | ci->memset(iedata, 0, iend - iedata); | ||
61 | #endif | 71 | #endif |
62 | 72 | ||
63 | ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16)); | 73 | ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16)); |
@@ -68,9 +78,10 @@ enum codec_status codec_start(struct codec_api* api) | |||
68 | ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(29)); | 78 | ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(29)); |
69 | 79 | ||
70 | next_track: | 80 | next_track: |
81 | err = CODEC_OK; | ||
71 | 82 | ||
72 | if (codec_init(api)) { | 83 | if (codec_init(api)) { |
73 | LOGF("FAAD: Error initialising codec\n"); | 84 | LOGF("FAAD: Codec init error\n"); |
74 | err = CODEC_ERROR; | 85 | err = CODEC_ERROR; |
75 | goto exit; | 86 | goto exit; |
76 | } | 87 | } |
@@ -78,7 +89,7 @@ next_track: | |||
78 | while (!*ci->taginfo_ready && !ci->stop_codec) | 89 | while (!*ci->taginfo_ready && !ci->stop_codec) |
79 | ci->sleep(1); | 90 | ci->sleep(1); |
80 | 91 | ||
81 | samplesdone = ci->id3->offset; | 92 | sound_samples_done = ci->id3->offset; |
82 | 93 | ||
83 | ci->configure(DSP_SET_FREQUENCY, (long *)(rb->id3->frequency)); | 94 | ci->configure(DSP_SET_FREQUENCY, (long *)(rb->id3->frequency)); |
84 | 95 | ||
@@ -87,52 +98,49 @@ next_track: | |||
87 | /* if qtmovie_read returns successfully, the stream is up to | 98 | /* if qtmovie_read returns successfully, the stream is up to |
88 | * the movie data, which can be used directly by the decoder */ | 99 | * the movie data, which can be used directly by the decoder */ |
89 | if (!qtmovie_read(&input_stream, &demux_res)) { | 100 | if (!qtmovie_read(&input_stream, &demux_res)) { |
90 | LOGF("FAAD: Error initialising file\n"); | 101 | LOGF("FAAD: File init error\n"); |
91 | err = CODEC_ERROR; | 102 | err = CODEC_ERROR; |
92 | goto done; | 103 | goto done; |
93 | } | 104 | } |
94 | 105 | ||
95 | /* initialise the sound converter */ | 106 | /* initialise the sound converter */ |
96 | hDecoder = NULL; | 107 | decoder = NeAACDecOpen(); |
97 | hDecoder = NeAACDecOpen(); | ||
98 | 108 | ||
99 | if (!hDecoder) { | 109 | if (!decoder) { |
100 | LOGF("FAAD: Error opening decoder\n"); | 110 | LOGF("FAAD: Decode open error\n"); |
101 | err = CODEC_ERROR; | 111 | err = CODEC_ERROR; |
102 | goto done; | 112 | goto done; |
103 | } | 113 | } |
104 | 114 | ||
105 | NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(hDecoder); | 115 | NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder); |
106 | conf->outputFormat = FAAD_FMT_24BIT; /* irrelevant, we don't convert */ | 116 | conf->outputFormat = FAAD_FMT_24BIT; /* irrelevant, we don't convert */ |
107 | NeAACDecSetConfiguration(hDecoder, conf); | 117 | NeAACDecSetConfiguration(decoder, conf); |
108 | |||
109 | uint32_t s=0; | ||
110 | unsigned char c=0; | ||
111 | 118 | ||
112 | err = NeAACDecInit2(hDecoder, demux_res.codecdata,demux_res.codecdata_len, &s, &c); | 119 | err = NeAACDecInit2(decoder, demux_res.codecdata, demux_res.codecdata_len, &s, &c); |
113 | if (err) { | 120 | if (err) { |
114 | LOGF("FAAD: Error initialising decoder: %d, type=%d\n", err,hDecoder->object_type); | 121 | LOGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type); |
115 | err = CODEC_ERROR; | 122 | err = CODEC_ERROR; |
116 | goto done; | 123 | goto done; |
117 | } | 124 | } |
118 | 125 | ||
119 | ci->id3->frequency=s; | 126 | ci->id3->frequency = s; |
120 | 127 | ||
121 | i=0; | 128 | i = 0; |
122 | 129 | ||
123 | if (samplesdone > 0) { | 130 | if (sound_samples_done > 0) { |
124 | if (alac_seek_raw(&demux_res, &input_stream, samplesdone, | 131 | if (alac_seek_raw(&demux_res, &input_stream, sound_samples_done, |
125 | &samplesdone, (int *)&i)) { | 132 | &sound_samples_done, (int*) &i)) { |
126 | elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); | 133 | elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100); |
127 | ci->set_elapsed(elapsedtime); | 134 | ci->set_elapsed(elapsed_time); |
128 | } else { | 135 | } else { |
129 | samplesdone=0; | 136 | sound_samples_done = 0; |
130 | } | 137 | } |
131 | } | 138 | } |
132 | 139 | ||
133 | /* The main decoding loop */ | 140 | /* The main decoding loop */ |
134 | while (i < demux_res.num_sample_byte_sizes) { | 141 | while (i < demux_res.num_sample_byte_sizes) { |
135 | rb->yield(); | 142 | rb->yield(); |
143 | |||
136 | if (ci->stop_codec || ci->new_track) { | 144 | if (ci->stop_codec || ci->new_track) { |
137 | break; | 145 | break; |
138 | } | 146 | } |
@@ -140,10 +148,10 @@ next_track: | |||
140 | /* Deal with any pending seek requests */ | 148 | /* Deal with any pending seek requests */ |
141 | if (ci->seek_time) { | 149 | if (ci->seek_time) { |
142 | if (alac_seek(&demux_res, &input_stream, | 150 | if (alac_seek(&demux_res, &input_stream, |
143 | ((ci->seek_time-1)/10) * (ci->id3->frequency/100), | 151 | ((ci->seek_time-1)/10)*(ci->id3->frequency/100), |
144 | &samplesdone, (int *)&i)) { | 152 | &sound_samples_done, (int*) &i)) { |
145 | elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); | 153 | elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100); |
146 | ci->set_elapsed(elapsedtime); | 154 | ci->set_elapsed(elapsed_time); |
147 | } | 155 | } |
148 | ci->seek_complete(); | 156 | ci->seek_complete(); |
149 | } | 157 | } |
@@ -151,52 +159,65 @@ next_track: | |||
151 | /* Lookup the length (in samples and bytes) of block i */ | 159 | /* Lookup the length (in samples and bytes) of block i */ |
152 | if (!get_sample_info(&demux_res, i, &sample_duration, | 160 | if (!get_sample_info(&demux_res, i, &sample_duration, |
153 | &sample_byte_size)) { | 161 | &sample_byte_size)) { |
154 | LOGF("AAC: Error in get_sample_info\n"); | 162 | LOGF("AAC: get_sample_info error\n"); |
155 | err = CODEC_ERROR; | 163 | err = CODEC_ERROR; |
156 | goto done; | 164 | goto done; |
157 | } | 165 | } |
158 | 166 | ||
167 | /* There can be gaps between chunks, so skip ahead if needed. It | ||
168 | * doesn't seem to happen much, but it probably means that a | ||
169 | * "proper" file can have chunks out of order. Why one would want | ||
170 | * that an good question (but files with gaps do exist, so who | ||
171 | * knows?), so we don't support that - for now, at least. | ||
172 | */ | ||
173 | file_offset = get_sample_offset(&demux_res, i); | ||
174 | |||
175 | if (file_offset > ci->curpos) | ||
176 | { | ||
177 | ci->advance_buffer(file_offset - ci->curpos); | ||
178 | } | ||
179 | |||
159 | /* Request the required number of bytes from the input buffer */ | 180 | /* Request the required number of bytes from the input buffer */ |
160 | buffer=ci->request_buffer(&n,sample_byte_size); | 181 | buffer=ci->request_buffer(&n,sample_byte_size); |
161 | 182 | ||
162 | /* Decode one block - returned samples will be host-endian */ | 183 | /* Decode one block - returned samples will be host-endian */ |
163 | rb->yield(); | 184 | NeAACDecDecode(decoder, &frame_info, buffer, n); |
164 | decodedbuffer = NeAACDecDecode(hDecoder, &frameInfo, buffer, n); | 185 | /* Ignore return value, we access samples in the decoder struct |
165 | /* ignore decodedbuffer return value, we access samples in the | 186 | * directly. |
166 | decoder struct directly */ | 187 | */ |
167 | if (frameInfo.error > 0) { | 188 | if (frame_info.error > 0) { |
168 | LOGF("FAAD: decoding error \"%s\"\n", NeAACDecGetErrorMessage(frameInfo.error)); | 189 | LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error)); |
169 | err = CODEC_ERROR; | 190 | err = CODEC_ERROR; |
170 | goto done; | 191 | goto done; |
171 | } | 192 | } |
172 | 193 | ||
173 | /* Get the number of decoded samples */ | ||
174 | samplesdecoded=frameInfo.samples; | ||
175 | |||
176 | /* Advance codec buffer */ | 194 | /* Advance codec buffer */ |
177 | ci->advance_buffer(n); | 195 | ci->advance_buffer(n); |
178 | 196 | ||
179 | /* Output the audio */ | 197 | /* Output the audio */ |
180 | rb->yield(); | 198 | rb->yield(); |
181 | while (!rb->pcmbuf_insert_split(hDecoder->time_out[0], | 199 | while (!rb->pcmbuf_insert_split(decoder->time_out[0], |
182 | hDecoder->time_out[1], | 200 | decoder->time_out[1], |
183 | frameInfo.samples*2)) | 201 | frame_info.samples * 2)) |
184 | rb->yield(); | 202 | { |
203 | rb->sleep(1); | ||
204 | } | ||
185 | 205 | ||
186 | /* Update the elapsed-time indicator */ | 206 | /* Update the elapsed-time indicator */ |
187 | samplesdone+=sample_duration; | 207 | sound_samples_done += sample_duration; |
188 | elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); | 208 | elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100); |
189 | ci->set_elapsed(elapsedtime); | 209 | ci->set_elapsed(elapsed_time); |
190 | 210 | ||
191 | /* Keep track of current position - for resuming */ | 211 | /* Keep track of current position - for resuming */ |
192 | ci->set_offset(elapsedtime); | 212 | ci->set_offset(elapsed_time); |
193 | 213 | ||
194 | i++; | 214 | i++; |
195 | } | 215 | } |
216 | |||
196 | err = CODEC_OK; | 217 | err = CODEC_OK; |
197 | 218 | ||
198 | done: | 219 | done: |
199 | LOGF("AAC: Decoded %d samples\n",samplesdone); | 220 | LOGF("AAC: Decoded %d samples, %d frames\n", sound_samples_done); |
200 | 221 | ||
201 | if (ci->request_next_track()) | 222 | if (ci->request_next_track()) |
202 | goto next_track; | 223 | goto next_track; |