diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-04-27 03:08:23 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-04-27 03:08:23 +0000 |
commit | c537d5958e8b421ac4f9bef6c8b9e7425a6cf167 (patch) | |
tree | 7ed36518fb6524da7bbd913ba7619b85b5d15d23 /apps/codecs/aiff.c | |
parent | dcf0f8de4a37ff1d2ea510aef75fa67977a8bdcc (diff) | |
download | rockbox-c537d5958e8b421ac4f9bef6c8b9e7425a6cf167.tar.gz rockbox-c537d5958e8b421ac4f9bef6c8b9e7425a6cf167.zip |
Commit FS#12069 - Playback rework - first stages. Gives as thorough as possible a treatment of codec management, track change and metadata logic as possible while maintaining fairly narrow focus and not rewriting everything all at once. Please see the rockbox-dev mail archive on 2011-04-25 (Playback engine rework) for a more thorough manifest of what was addressed. Plugins and codecs become incompatible.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29785 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/aiff.c')
-rw-r--r-- | apps/codecs/aiff.c | 108 |
1 files changed, 48 insertions, 60 deletions
diff --git a/apps/codecs/aiff.c b/apps/codecs/aiff.c index d4cf8660dd..3fc137eaeb 100644 --- a/apps/codecs/aiff.c +++ b/apps/codecs/aiff.c | |||
@@ -61,9 +61,20 @@ static const struct pcm_codec *get_codec(uint32_t formattag) | |||
61 | return NULL; | 61 | return NULL; |
62 | } | 62 | } |
63 | 63 | ||
64 | enum codec_status codec_main(void) | 64 | /* this is the codec entry point */ |
65 | enum codec_status codec_main(enum codec_entry_call_reason reason) | ||
66 | { | ||
67 | if (reason == CODEC_LOAD) { | ||
68 | /* Generic codec initialisation */ | ||
69 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
70 | } | ||
71 | |||
72 | return CODEC_OK; | ||
73 | } | ||
74 | |||
75 | /* this is called for each file to process */ | ||
76 | enum codec_status codec_run(void) | ||
65 | { | 77 | { |
66 | int status; | ||
67 | struct pcm_format format; | 78 | struct pcm_format format; |
68 | uint32_t bytesdone, decodedsamples; | 79 | uint32_t bytesdone, decodedsamples; |
69 | uint32_t num_sample_frames = 0; | 80 | uint32_t num_sample_frames = 0; |
@@ -77,38 +88,28 @@ enum codec_status codec_main(void) | |||
77 | bool is_aifc = false; | 88 | bool is_aifc = false; |
78 | const struct pcm_codec *codec; | 89 | const struct pcm_codec *codec; |
79 | uint32_t size; | 90 | uint32_t size; |
80 | 91 | intptr_t param; | |
81 | /* Generic codec initialisation */ | ||
82 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
83 | |||
84 | next_track: | ||
85 | status = CODEC_OK; | ||
86 | 92 | ||
87 | if (codec_init()) { | 93 | if (codec_init()) { |
88 | status = CODEC_ERROR; | 94 | return CODEC_ERROR; |
89 | goto exit; | ||
90 | } | 95 | } |
91 | 96 | ||
92 | if (codec_wait_taginfo() != 0) | ||
93 | goto done; | ||
94 | |||
95 | codec_set_replaygain(ci->id3); | 97 | codec_set_replaygain(ci->id3); |
96 | 98 | ||
97 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ | 99 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ |
98 | bytesdone = ci->id3->offset; | 100 | bytesdone = ci->id3->offset; |
99 | 101 | ||
100 | /* assume the AIFF header is less than 1024 bytes */ | 102 | /* assume the AIFF header is less than 1024 bytes */ |
103 | ci->seek_buffer(0); | ||
101 | buf = ci->request_buffer(&n, 1024); | 104 | buf = ci->request_buffer(&n, 1024); |
102 | if (n < 54) { | 105 | if (n < 54) { |
103 | status = CODEC_ERROR; | 106 | return CODEC_ERROR; |
104 | goto done; | ||
105 | } | 107 | } |
106 | 108 | ||
107 | if (memcmp(buf, "FORM", 4) != 0) | 109 | if (memcmp(buf, "FORM", 4) != 0) |
108 | { | 110 | { |
109 | DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[0]); | 111 | DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[0]); |
110 | status = CODEC_ERROR; | 112 | return CODEC_ERROR; |
111 | goto done; | ||
112 | } | 113 | } |
113 | if (memcmp(&buf[8], "AIFF", 4) == 0) | 114 | if (memcmp(&buf[8], "AIFF", 4) == 0) |
114 | is_aifc = false; | 115 | is_aifc = false; |
@@ -117,8 +118,7 @@ next_track: | |||
117 | else | 118 | else |
118 | { | 119 | { |
119 | DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[8]); | 120 | DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[8]); |
120 | status = CODEC_ERROR; | 121 | return CODEC_ERROR; |
121 | goto done; | ||
122 | } | 122 | } |
123 | 123 | ||
124 | buf += 12; | 124 | buf += 12; |
@@ -141,8 +141,7 @@ next_track: | |||
141 | { | 141 | { |
142 | DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < %d\n", | 142 | DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < %d\n", |
143 | (unsigned long)size, (is_aifc)?22:18); | 143 | (unsigned long)size, (is_aifc)?22:18); |
144 | status = CODEC_ERROR; | 144 | return CODEC_ERROR; |
145 | goto done; | ||
146 | } | 145 | } |
147 | /* num_channels */ | 146 | /* num_channels */ |
148 | format.channels = ((buf[8]<<8)|buf[9]); | 147 | format.channels = ((buf[8]<<8)|buf[9]); |
@@ -154,8 +153,7 @@ next_track: | |||
154 | /* sample_rate (don't use last 4 bytes, only integer fs) */ | 153 | /* sample_rate (don't use last 4 bytes, only integer fs) */ |
155 | if (buf[16] != 0x40) { | 154 | if (buf[16] != 0x40) { |
156 | DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n"); | 155 | DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n"); |
157 | status = CODEC_ERROR; | 156 | return CODEC_ERROR; |
158 | goto done; | ||
159 | } | 157 | } |
160 | format.samplespersec = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1; | 158 | format.samplespersec = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1; |
161 | format.samplespersec >>= (16 + 14 - buf[17]); | 159 | format.samplespersec >>= (16 + 14 - buf[17]); |
@@ -181,8 +179,7 @@ next_track: | |||
181 | } else if (memcmp(buf, "SSND", 4)==0) { | 179 | } else if (memcmp(buf, "SSND", 4)==0) { |
182 | if (format.bitspersample == 0) { | 180 | if (format.bitspersample == 0) { |
183 | DEBUGF("CODEC_ERROR: unsupported chunk order\n"); | 181 | DEBUGF("CODEC_ERROR: unsupported chunk order\n"); |
184 | status = CODEC_ERROR; | 182 | return CODEC_ERROR; |
185 | goto done; | ||
186 | } | 183 | } |
187 | /* offset2snd */ | 184 | /* offset2snd */ |
188 | offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; | 185 | offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; |
@@ -205,21 +202,18 @@ next_track: | |||
205 | buf += size; | 202 | buf += size; |
206 | if (n < size) { | 203 | if (n < size) { |
207 | DEBUGF("CODEC_ERROR: AIFF header size > 1024\n"); | 204 | DEBUGF("CODEC_ERROR: AIFF header size > 1024\n"); |
208 | status = CODEC_ERROR; | 205 | return CODEC_ERROR; |
209 | goto done; | ||
210 | } | 206 | } |
211 | n -= size; | 207 | n -= size; |
212 | } /* while 'SSND' */ | 208 | } /* while 'SSND' */ |
213 | 209 | ||
214 | if (format.channels == 0) { | 210 | if (format.channels == 0) { |
215 | DEBUGF("CODEC_ERROR: 'COMM' chunk not found or 0-channels file\n"); | 211 | DEBUGF("CODEC_ERROR: 'COMM' chunk not found or 0-channels file\n"); |
216 | status = CODEC_ERROR; | 212 | return CODEC_ERROR; |
217 | goto done; | ||
218 | } | 213 | } |
219 | if (format.numbytes == 0) { | 214 | if (format.numbytes == 0) { |
220 | DEBUGF("CODEC_ERROR: 'SSND' chunk not found or has zero length\n"); | 215 | DEBUGF("CODEC_ERROR: 'SSND' chunk not found or has zero length\n"); |
221 | status = CODEC_ERROR; | 216 | return CODEC_ERROR; |
222 | goto done; | ||
223 | } | 217 | } |
224 | 218 | ||
225 | codec = get_codec(format.formattag); | 219 | codec = get_codec(format.formattag); |
@@ -227,14 +221,12 @@ next_track: | |||
227 | { | 221 | { |
228 | DEBUGF("CODEC_ERROR: AIFC does not support compressionType: 0x%x\n", | 222 | DEBUGF("CODEC_ERROR: AIFC does not support compressionType: 0x%x\n", |
229 | (unsigned int)format.formattag); | 223 | (unsigned int)format.formattag); |
230 | status = CODEC_ERROR; | 224 | return CODEC_ERROR; |
231 | goto done; | ||
232 | } | 225 | } |
233 | 226 | ||
234 | if (!codec->set_format(&format)) | 227 | if (!codec->set_format(&format)) |
235 | { | 228 | { |
236 | status = CODEC_ERROR; | 229 | return CODEC_ERROR; |
237 | goto done; | ||
238 | } | 230 | } |
239 | 231 | ||
240 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 232 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
@@ -245,21 +237,18 @@ next_track: | |||
245 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | 237 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); |
246 | } else { | 238 | } else { |
247 | DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n"); | 239 | DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n"); |
248 | status = CODEC_ERROR; | 240 | return CODEC_ERROR; |
249 | goto done; | ||
250 | } | 241 | } |
251 | 242 | ||
252 | if (format.samplesperblock == 0) | 243 | if (format.samplesperblock == 0) |
253 | { | 244 | { |
254 | DEBUGF("CODEC_ERROR: samplesperblock is 0\n"); | 245 | DEBUGF("CODEC_ERROR: samplesperblock is 0\n"); |
255 | status = CODEC_ERROR; | 246 | return CODEC_ERROR; |
256 | goto done; | ||
257 | } | 247 | } |
258 | if (format.blockalign == 0) | 248 | if (format.blockalign == 0) |
259 | { | 249 | { |
260 | DEBUGF("CODEC_ERROR: blockalign is 0\n"); | 250 | DEBUGF("CODEC_ERROR: blockalign is 0\n"); |
261 | status = CODEC_ERROR; | 251 | return CODEC_ERROR; |
262 | goto done; | ||
263 | } | 252 | } |
264 | 253 | ||
265 | /* check chunksize */ | 254 | /* check chunksize */ |
@@ -269,8 +258,7 @@ next_track: | |||
269 | if (format.chunksize == 0) | 258 | if (format.chunksize == 0) |
270 | { | 259 | { |
271 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); | 260 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); |
272 | status = CODEC_ERROR; | 261 | return CODEC_ERROR; |
273 | goto done; | ||
274 | } | 262 | } |
275 | 263 | ||
276 | firstblockposn = 1024 - n; | 264 | firstblockposn = 1024 - n; |
@@ -283,13 +271,13 @@ next_track: | |||
283 | PCM_SEEK_POS, NULL); | 271 | PCM_SEEK_POS, NULL); |
284 | 272 | ||
285 | if (newpos->pos > format.numbytes) | 273 | if (newpos->pos > format.numbytes) |
286 | goto done; | 274 | return CODEC_OK; |
275 | |||
287 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 276 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
288 | { | 277 | { |
289 | bytesdone = newpos->pos; | 278 | bytesdone = newpos->pos; |
290 | decodedsamples = newpos->samples; | 279 | decodedsamples = newpos->samples; |
291 | } | 280 | } |
292 | ci->seek_complete(); | ||
293 | } else { | 281 | } else { |
294 | /* already where we need to be */ | 282 | /* already where we need to be */ |
295 | bytesdone = 0; | 283 | bytesdone = 0; |
@@ -299,21 +287,29 @@ next_track: | |||
299 | endofstream = 0; | 287 | endofstream = 0; |
300 | 288 | ||
301 | while (!endofstream) { | 289 | while (!endofstream) { |
302 | ci->yield(); | 290 | enum codec_command_action action = ci->get_command(¶m); |
303 | if (ci->stop_codec || ci->new_track) | 291 | |
292 | if (action == CODEC_ACTION_HALT) | ||
304 | break; | 293 | break; |
305 | 294 | ||
306 | if (ci->seek_time) { | 295 | if (action == CODEC_ACTION_SEEK_TIME) { |
307 | /* 3rd args(read_buffer) is unnecessary in the format which AIFF supports. */ | 296 | /* 3rd args(read_buffer) is unnecessary in the format which AIFF supports. */ |
308 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, NULL); | 297 | struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, NULL); |
309 | 298 | ||
310 | if (newpos->pos > format.numbytes) | 299 | if (newpos->pos > format.numbytes) |
300 | { | ||
301 | ci->set_elapsed(ci->id3->length); | ||
302 | ci->seek_complete(); | ||
311 | break; | 303 | break; |
304 | } | ||
305 | |||
312 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 306 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
313 | { | 307 | { |
314 | bytesdone = newpos->pos; | 308 | bytesdone = newpos->pos; |
315 | decodedsamples = newpos->samples; | 309 | decodedsamples = newpos->samples; |
316 | } | 310 | } |
311 | |||
312 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | ||
317 | ci->seek_complete(); | 313 | ci->seek_complete(); |
318 | } | 314 | } |
319 | aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); | 315 | aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); |
@@ -326,11 +322,10 @@ next_track: | |||
326 | endofstream = 1; | 322 | endofstream = 1; |
327 | } | 323 | } |
328 | 324 | ||
329 | status = codec->decode(aifbuf, n, samples, &bufcount); | 325 | if (codec->decode(aifbuf, n, samples, &bufcount) == CODEC_ERROR) |
330 | if (status == CODEC_ERROR) | ||
331 | { | 326 | { |
332 | DEBUGF("codec error\n"); | 327 | DEBUGF("codec error\n"); |
333 | goto done; | 328 | return CODEC_ERROR; |
334 | } | 329 | } |
335 | 330 | ||
336 | ci->pcmbuf_insert(samples, NULL, bufcount); | 331 | ci->pcmbuf_insert(samples, NULL, bufcount); |
@@ -343,13 +338,6 @@ next_track: | |||
343 | 338 | ||
344 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | 339 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); |
345 | } | 340 | } |
346 | status = CODEC_OK; | ||
347 | |||
348 | done: | ||
349 | if (ci->request_next_track()) | ||
350 | goto next_track; | ||
351 | 341 | ||
352 | exit: | 342 | return CODEC_OK; |
353 | return status; | ||
354 | } | 343 | } |
355 | |||