summaryrefslogtreecommitdiff
path: root/apps/codecs/flac.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/flac.c')
-rw-r--r--apps/codecs/flac.c405
1 files changed, 124 insertions, 281 deletions
diff --git a/apps/codecs/flac.c b/apps/codecs/flac.c
index 45fc21466c..b9a3a8a249 100644
--- a/apps/codecs/flac.c
+++ b/apps/codecs/flac.c
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2002 Björn Stenberg 10 * Copyright (C) 2005 Dave Chapman
11 * 11 *
12 * All files in this archive are subject to the GNU General Public License. 12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement. 13 * See the file COPYING in the source tree root for full license agreement.
@@ -18,156 +18,7 @@
18 ****************************************************************************/ 18 ****************************************************************************/
19 19
20#include "codeclib.h" 20#include "codeclib.h"
21#include <codecs/libFLAC/include/FLAC/seekable_stream_decoder.h> 21#include <codecs/libffmpegFLAC/decoder.h>
22#include <codecs/libFLAC/include/FLAC/format.h>
23#include <codecs/libFLAC/include/FLAC/metadata.h>
24
25#define FLAC_MAX_SUPPORTED_BLOCKSIZE 4608
26#define FLAC_MAX_SUPPORTED_CHANNELS 2
27
28static uint32_t samplesdone;
29
30static FLAC__StreamMetadata *stream_info;
31static FLAC__StreamMetadata *seek_table;
32unsigned int metadata_length;
33
34/* Called when the FLAC decoder needs some FLAC data to decode */
35FLAC__SeekableStreamDecoderReadStatus flac_read_handler(const FLAC__SeekableStreamDecoder *dec,
36 FLAC__byte buffer[], unsigned *bytes, void *data)
37{
38 struct codec_api* ci = (struct codec_api*)data;
39 (void)dec;
40
41 *bytes=(unsigned)(ci->read_filebuf(buffer,*bytes));
42
43 if (*bytes==0) {
44 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
45 } else {
46 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
47 }
48}
49
50static unsigned char pcmbuf[FLAC_MAX_SUPPORTED_BLOCKSIZE*FLAC_MAX_SUPPORTED_CHANNELS*2] IDATA_ATTR;
51
52/* Called when the FLAC decoder has some decoded PCM data to write */
53FLAC__StreamDecoderWriteStatus flac_write_handler(const FLAC__SeekableStreamDecoder *dec,
54 const FLAC__Frame *frame,
55 const FLAC__int32 * const buf[],
56 void *data)
57{
58 struct codec_api* ci = (struct codec_api*)data;
59 (void)dec;
60 unsigned int c_samp, c_chan, d_samp;
61 uint32_t data_size = frame->header.blocksize * frame->header.channels * 2; /* Assume 16-bit words */
62 uint32_t samples = frame->header.blocksize;
63 int yieldcounter = 0;
64
65
66 if (samples*frame->header.channels > (FLAC_MAX_SUPPORTED_BLOCKSIZE*FLAC_MAX_SUPPORTED_CHANNELS)) {
67 // ERROR!!!
68 // DEBUGF("ERROR: samples*frame->header.channels=%d\n",samples*frame->header.channels);
69 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
70 }
71
72 (void)dec;
73 for (c_samp = d_samp = 0; c_samp < samples; c_samp++) {
74 for(c_chan = 0; c_chan < frame->header.channels; c_chan++, d_samp++) {
75 pcmbuf[d_samp*2] = (buf[c_chan][c_samp]&0xff00)>>8;
76 pcmbuf[(d_samp*2)+1] = buf[c_chan][c_samp]&0xff;
77 if (yieldcounter++ == 100) {
78 ci->yield();
79 yieldcounter = 0;
80 }
81 }
82 }
83
84 samplesdone+=samples;
85 ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
86
87 ci->yield();
88 while (!ci->pcmbuf_insert(pcmbuf, data_size))
89 ci->yield();
90
91 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
92}
93
94void flac_metadata_handler(const FLAC__SeekableStreamDecoder *dec,
95 const FLAC__StreamMetadata *meta, void *data)
96{
97 /* Ignore metadata for now... */
98 (void)dec;
99 (void)data;
100
101 metadata_length += meta->length;
102
103 if ( meta->type == FLAC__METADATA_TYPE_STREAMINFO ) {
104 stream_info = FLAC__metadata_object_clone( meta );
105 if ( stream_info == NULL ) {
106 //return CODEC_ERROR;
107 }
108 } else if ( meta->type == FLAC__METADATA_TYPE_SEEKTABLE ) {
109 seek_table = FLAC__metadata_object_clone( meta );
110 if ( seek_table == NULL ) {
111 //return CODEC_ERROR;
112 }
113 }
114}
115
116
117void flac_error_handler(const FLAC__SeekableStreamDecoder *dec,
118 FLAC__StreamDecoderErrorStatus status, void *data)
119{
120 (void)dec;
121 (void)status;
122 (void)data;
123}
124
125FLAC__SeekableStreamDecoderSeekStatus flac_seek_handler(const FLAC__SeekableStreamDecoder *decoder,
126 FLAC__uint64 absolute_byte_offset,
127 void *client_data)
128{
129 (void)decoder;
130 struct codec_api* ci = (struct codec_api*)client_data;
131
132 if (ci->seek_buffer(absolute_byte_offset)) {
133 return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
134 } else {
135 return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
136 }
137}
138
139FLAC__SeekableStreamDecoderTellStatus flac_tell_handler(const FLAC__SeekableStreamDecoder *decoder,
140 FLAC__uint64 *absolute_byte_offset, void *client_data)
141{
142 struct codec_api* ci = (struct codec_api*)client_data;
143
144 (void)decoder;
145 *absolute_byte_offset = ci->curpos;
146 return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
147}
148
149FLAC__SeekableStreamDecoderLengthStatus flac_length_handler(const FLAC__SeekableStreamDecoder *decoder,
150 FLAC__uint64 *stream_length, void *client_data)
151{
152 struct codec_api* ci = (struct codec_api*)client_data;
153
154 (void)decoder;
155 *stream_length = ci->filesize;
156 return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
157}
158
159FLAC__bool flac_eof_handler(const FLAC__SeekableStreamDecoder *decoder,
160 void *client_data)
161{
162 struct codec_api* ci = (struct codec_api*)client_data;
163
164 (void)decoder;
165 if (ci->curpos >= ci->filesize) {
166 return true;
167 } else {
168 return false;
169 }
170}
171 22
172#ifndef SIMULATOR 23#ifndef SIMULATOR
173extern char iramcopy[]; 24extern char iramcopy[];
@@ -175,78 +26,101 @@ extern char iramstart[];
175extern char iramend[]; 26extern char iramend[];
176#endif 27#endif
177 28
178FLAC__uint64 find_sample_number(struct codec_api *ci, size_t offset) 29struct codec_api* rb;
30struct codec_api* ci;
31
32/* The output buffers containing the decoded samples (channels 0 and 1) */
33int32_t decoded0[MAX_BLOCKSIZE] IBSS_ATTR;
34int32_t decoded1[MAX_BLOCKSIZE] IBSS_ATTR;
35
36static bool flac_init(FLACContext* fc)
179{ 37{
180 FLAC__StreamMetadata_SeekPoint *points; 38 unsigned char buf[255];
181 FLAC__uint64 prev_sample, next_sample; 39 bool found_streaminfo=false;
182 size_t prev_offset, next_offset; 40 int endofmetadata=0;
183 int percent; 41 int blocklength;
184 42
185 if (offset >= (ci->id3->filesize - metadata_length)) { 43 if (ci->read_filebuf(buf, 4) < 4)
186 return stream_info->data.stream_info.total_samples; 44 {
45 return false;
187 } 46 }
188 47
189 prev_offset = 0; 48 if (ci->memcmp(buf,"fLaC",4) != 0)
190 prev_sample = 0; 49 {
191 next_offset = ci->id3->filesize - metadata_length; 50 return false;
192 next_sample = stream_info->data.stream_info.total_samples; 51 }
193 52 fc->metadatalength = 4;
194 if (seek_table) {
195 int left, right, middle;
196 53
197 middle = 0; /* Silence compiler warnings */ 54 while (!endofmetadata) {
198 points = seek_table->data.seek_table.points; 55 if (ci->read_filebuf(buf, 4) < 4)
199 left = 0; 56 {
200 right = seek_table->data.seek_table.num_points - 1; 57 return false;
58 }
201 59
202 /* Do a binary search to find the matching seek point */ 60 endofmetadata=(buf[0]&0x80);
203 while (left <= right) { 61 blocklength = (buf[1] << 16) | (buf[2] << 8) | buf[3];
204 middle = (left + right) / 2; 62 fc->metadatalength+=blocklength+4;
205 63
206 if ((FLAC__uint64)offset < points[middle].stream_offset) { 64 if ((buf[0] & 0x7f) == 0) /* 0 is the STREAMINFO block */
207 right = middle - 1; 65 {
208 } else if ((FLAC__uint64)offset > points[middle].stream_offset) { 66 /* FIXME: Don't trust the value of blocklength */
209 left = middle + 1; 67 if (ci->read_filebuf(buf, blocklength) < 0)
210 } else { 68 {
211 return points[middle].sample_number; 69 return false;
212 } 70 }
213 } 71
214 72 fc->filesize = ci->filesize;
215 /* Didn't find a matching seek point, so get the sample numbers of the 73 fc->min_blocksize = (buf[0] << 8) | buf[1];
216 * seek points to the left and right of offset to make our guess more 74 fc->max_blocksize = (buf[2] << 8) | buf[3];
217 * accurate. Accuracy depends on how close these sample numbers are to 75 fc->min_framesize = (buf[4] << 16) | (buf[5] << 8) | buf[6];
218 * each other. 76 fc->max_framesize = (buf[7] << 16) | (buf[8] << 8) | buf[9];
219 */ 77 fc->samplerate = (buf[10] << 12) | (buf[11] << 4)
220 if ((unsigned)left >= seek_table->data.seek_table.num_points) { 78 | ((buf[12] & 0xf0) >> 4);
221 prev_offset = points[middle].stream_offset; 79 fc->channels = ((buf[12]&0x0e)>>1) + 1;
222 prev_sample = points[middle].sample_number; 80 fc->bps = (((buf[12]&0x01) << 4) | ((buf[13]&0xf0)>>4) ) + 1;
223 } else if (right < 0) { 81
224 next_offset = points[middle].stream_offset; 82 /* totalsamples is a 36-bit field, but we assume <= 32 bits are
225 next_sample = points[middle].sample_number; 83 used */
84 fc->totalsamples = (buf[14] << 24) | (buf[15] << 16)
85 | (buf[16] << 8) | buf[17];
86
87 /* Calculate track length (in ms) and estimate the bitrate
88 (in kbit/s) */
89 fc->length = (fc->totalsamples / fc->samplerate) * 1000;
90
91 found_streaminfo=true;
92 } else if ((buf[0] & 0x7f) == 3) { /* 3 is the SEEKTABLE block */
93 ci->advance_buffer(blocklength);
226 } else { 94 } else {
227 middle--; 95 /* Skip to next metadata block */
228 prev_offset = points[middle].stream_offset; 96 ci->advance_buffer(blocklength);
229 prev_sample = points[middle].sample_number;
230 next_offset = points[middle+1].stream_offset;
231 next_sample = points[middle+1].sample_number;
232 } 97 }
233 } 98 }
234 99
235 /* Either there's no seek table or we didn't find our seek point, so now we 100 if (found_streaminfo) {
236 * have to guess. 101 fc->bitrate = ((fc->filesize-fc->metadatalength) * 8) / fc->length;
237 */ 102 return true;
238 percent = ((offset - prev_offset) * 100) / (next_offset - prev_offset); 103 } else {
239 return (FLAC__uint64)(percent * (next_sample - prev_sample) / 100 + prev_sample); 104 return false;
105 }
240} 106}
241 107
242/* this is the codec entry point */ 108/* this is the codec entry point */
243enum codec_status codec_start(struct codec_api* api) 109enum codec_status codec_start(struct codec_api* api)
244{ 110{
245 struct codec_api* ci = api; 111 size_t n;
246 FLAC__SeekableStreamDecoder* flacDecoder; 112 static int8_t buf[MAX_FRAMESIZE];
247 FLAC__uint64 offset; 113 FLACContext fc;
114 uint32_t samplesdone;
115 uint32_t elapsedtime;
116 int bytesleft;
117 int consumed;
248 118
249 TEST_CODEC_API(ci); 119 /* Generic codec initialisation */
120 TEST_CODEC_API(api);
121
122 rb = api;
123 ci = (struct codec_api*)api;
250 124
251#ifndef SIMULATOR 125#ifndef SIMULATOR
252 ci->memcpy(iramstart, iramcopy, iramend-iramstart); 126 ci->memcpy(iramstart, iramcopy, iramend-iramstart);
@@ -254,19 +128,17 @@ enum codec_status codec_start(struct codec_api* api)
254 128
255 ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*10)); 129 ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*10));
256 ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512)); 130 ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
257 ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*1024)); 131 ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*128));
258 132
259 ci->configure(CODEC_DSP_ENABLE, (bool *)true); 133 ci->configure(CODEC_DSP_ENABLE, (bool *)true);
260 ci->configure(DSP_DITHER, (bool *)false); 134 ci->configure(DSP_DITHER, (bool *)false);
261 ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED); 135 ci->configure(DSP_SET_STEREO_MODE, (long *)STEREO_NONINTERLEAVED);
262 ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16)); 136 ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(28));
263 137
264next_track: 138 next_track:
265 metadata_length = 0;
266 seek_table = NULL;
267 stream_info = NULL;
268 139
269 if (codec_init(api)) { 140 if (!flac_init(&fc)) {
141 LOGF("FLAC: Error initialising codec\n");
270 return CODEC_ERROR; 142 return CODEC_ERROR;
271 } 143 }
272 144
@@ -274,87 +146,58 @@ next_track:
274 ci->yield(); 146 ci->yield();
275 147
276 ci->configure(DSP_SET_FREQUENCY, (long *)(ci->id3->frequency)); 148 ci->configure(DSP_SET_FREQUENCY, (long *)(ci->id3->frequency));
277 codec_set_replaygain(ci->id3);
278
279 /* Create a decoder instance */
280 flacDecoder = FLAC__seekable_stream_decoder_new();
281 149
282 /* Set up the decoder and the callback functions - this must be done before init */ 150 /* The main decoding loop */
283 151 bytesleft=ci->read_filebuf(buf,sizeof(buf));
284 /* The following are required for stream_decoder and higher */ 152 while (bytesleft) {
285 FLAC__seekable_stream_decoder_set_client_data(flacDecoder,ci);
286 FLAC__seekable_stream_decoder_set_write_callback(flacDecoder, flac_write_handler);
287 FLAC__seekable_stream_decoder_set_read_callback(flacDecoder, flac_read_handler);
288 FLAC__seekable_stream_decoder_set_metadata_callback(flacDecoder, flac_metadata_handler);
289 FLAC__seekable_stream_decoder_set_error_callback(flacDecoder, flac_error_handler);
290 FLAC__seekable_stream_decoder_set_metadata_respond_all(flacDecoder);
291
292 /* The following are only for the seekable_stream_decoder */
293 FLAC__seekable_stream_decoder_set_seek_callback(flacDecoder, flac_seek_handler);
294 FLAC__seekable_stream_decoder_set_tell_callback(flacDecoder, flac_tell_handler);
295 FLAC__seekable_stream_decoder_set_length_callback(flacDecoder, flac_length_handler);
296 FLAC__seekable_stream_decoder_set_eof_callback(flacDecoder, flac_eof_handler);
297
298
299 /* QUESTION: What do we do when the init fails? */
300 if (FLAC__seekable_stream_decoder_init(flacDecoder)) {
301 return CODEC_ERROR;
302 }
303
304 /* The first thing to do is to parse the metadata */
305 FLAC__seekable_stream_decoder_process_until_end_of_metadata(flacDecoder);
306
307 if (ci->id3->offset && stream_info) {
308 FLAC__uint64 sample;
309
310 sample = find_sample_number(ci, ci->id3->offset - metadata_length);
311 ci->advance_buffer(ci->id3->offset);
312 FLAC__seekable_stream_decoder_seek_absolute(flacDecoder, sample);
313 FLAC__seekable_stream_decoder_get_decode_position(flacDecoder, &offset);
314 ci->set_offset(offset);
315 samplesdone = (uint32_t)sample;
316 ci->set_elapsed(sample/(ci->id3->frequency/1000));
317 } else {
318 samplesdone = 0;
319 ci->set_elapsed(0);
320 }
321
322 /* The main decoder loop */
323 while (FLAC__seekable_stream_decoder_get_state(flacDecoder) != FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) {
324 ci->yield(); 153 ci->yield();
325 if (ci->stop_codec || ci->reload_codec) { 154 if (ci->stop_codec || ci->reload_codec) {
326 break; 155 break;
327 } 156 }
328 157
158 /* Deal with any pending seek requests */
329 if (ci->seek_time) { 159 if (ci->seek_time) {
330 int sample_loc; 160 /* We only support seeking to start of track at the moment */
161 if (ci->seek_time==1) {
162 if (ci->seek_buffer(fc.metadatalength)) {
163 /* Refill the input buffer */
164 bytesleft=ci->read_filebuf(buf,sizeof(buf));
165 ci->set_elapsed(0);
166 }
167 }
168 ci->seek_time = 0;
169 }
331 170
332 sample_loc = ci->seek_time/1000 * ci->id3->frequency; 171 if(flac_decode_frame(&fc,decoded0,decoded1,buf,
333 if (FLAC__seekable_stream_decoder_seek_absolute(flacDecoder, sample_loc)) { 172 bytesleft,ci->yield) < 0) {
334 samplesdone = sample_loc; 173 LOGF("FLAC: Decode error, aborting\n");
335 ci->set_elapsed(samplesdone/(ci->id3->frequency/1000)); 174 return CODEC_ERROR;
336 }
337 ci->seek_time = 0;
338 } 175 }
176 consumed=fc.gb.index/8;
339 177
340 FLAC__seekable_stream_decoder_process_single(flacDecoder); 178 ci->yield();
341 FLAC__seekable_stream_decoder_get_decode_position(flacDecoder, &offset); 179 while(!ci->pcmbuf_insert_split((char*)decoded0,(char*)decoded1,
342 ci->set_offset(offset); 180 fc.blocksize*4)) {
343 } 181 ci->yield();
182 }
344 183
345 /* Flush the libFLAC buffers */ 184 /* Update the elapsed-time indicator */
346 FLAC__seekable_stream_decoder_finish(flacDecoder); 185 samplesdone=fc.samplenumber+fc.blocksize;
186 elapsedtime=(samplesdone*10)/(ci->id3->frequency/100);
187 ci->set_elapsed(elapsedtime);
347 188
348 if (ci->request_next_track()) { 189 memmove(buf,&buf[consumed],bytesleft-consumed);
349 if (stream_info) { 190 bytesleft-=consumed;
350 FLAC__metadata_object_delete(stream_info); 191
351 } 192 n=ci->read_filebuf(&buf[bytesleft],sizeof(buf)-bytesleft);
352 if (seek_table) { 193 if (n > 0) {
353 FLAC__metadata_object_delete(seek_table); 194 bytesleft+=n;
354 } 195 }
355 metadata_length = 0;
356 goto next_track;
357 } 196 }
197 LOGF("FLAC: Decoded %d samples\n",samplesdone);
198
199 if (ci->request_next_track())
200 goto next_track;
358 201
359 return CODEC_OK; 202 return CODEC_OK;
360} 203}