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/wav64.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/wav64.c')
-rw-r--r-- | apps/codecs/wav64.c | 113 |
1 files changed, 48 insertions, 65 deletions
diff --git a/apps/codecs/wav64.c b/apps/codecs/wav64.c index 9dbdab8368..c763e6f7f0 100644 --- a/apps/codecs/wav64.c +++ b/apps/codecs/wav64.c | |||
@@ -159,9 +159,19 @@ static uint8_t *read_buffer(size_t *realsize) | |||
159 | } | 159 | } |
160 | 160 | ||
161 | /* this is the codec entry point */ | 161 | /* this is the codec entry point */ |
162 | enum codec_status codec_main(void) | 162 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
163 | { | ||
164 | if (reason == CODEC_LOAD) { | ||
165 | /* Generic codec initialisation */ | ||
166 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
167 | } | ||
168 | |||
169 | return CODEC_OK; | ||
170 | } | ||
171 | |||
172 | /* this is called for each file to process */ | ||
173 | enum codec_status codec_run(void) | ||
163 | { | 174 | { |
164 | int status; | ||
165 | uint32_t decodedsamples; | 175 | uint32_t decodedsamples; |
166 | size_t n; | 176 | size_t n; |
167 | int bufcount; | 177 | int bufcount; |
@@ -171,39 +181,29 @@ enum codec_status codec_main(void) | |||
171 | off_t firstblockposn; /* position of the first block in file */ | 181 | off_t firstblockposn; /* position of the first block in file */ |
172 | const struct pcm_codec *codec; | 182 | const struct pcm_codec *codec; |
173 | uint64_t size; | 183 | uint64_t size; |
174 | 184 | intptr_t param; | |
175 | /* Generic codec initialisation */ | ||
176 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
177 | |||
178 | next_track: | ||
179 | status = CODEC_OK; | ||
180 | 185 | ||
181 | if (codec_init()) { | 186 | if (codec_init()) { |
182 | DEBUGF("codec_init() error\n"); | 187 | DEBUGF("codec_init() error\n"); |
183 | status = CODEC_ERROR; | 188 | return CODEC_ERROR; |
184 | goto exit; | ||
185 | } | 189 | } |
186 | 190 | ||
187 | if (codec_wait_taginfo() != 0) | ||
188 | goto done; | ||
189 | |||
190 | codec_set_replaygain(ci->id3); | 191 | codec_set_replaygain(ci->id3); |
191 | 192 | ||
192 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ | 193 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ |
193 | bytesdone = ci->id3->offset; | 194 | bytesdone = ci->id3->offset; |
194 | 195 | ||
195 | /* get RIFF chunk header */ | 196 | /* get RIFF chunk header */ |
197 | ci->seek_buffer(0); | ||
196 | buf = ci->request_buffer(&n, 40); | 198 | buf = ci->request_buffer(&n, 40); |
197 | if (n < 40) { | 199 | if (n < 40) { |
198 | DEBUGF("request_buffer error\n"); | 200 | DEBUGF("request_buffer error\n"); |
199 | status = CODEC_ERROR; | 201 | return CODEC_ERROR; |
200 | goto done; | ||
201 | } | 202 | } |
202 | if ((memcmp(buf , WAVE64_GUID_RIFF, 16) != 0) || | 203 | if ((memcmp(buf , WAVE64_GUID_RIFF, 16) != 0) || |
203 | (memcmp(buf+24, WAVE64_GUID_WAVE, 16) != 0)) | 204 | (memcmp(buf+24, WAVE64_GUID_WAVE, 16) != 0)) |
204 | { | 205 | { |
205 | status = CODEC_ERROR; | 206 | return CODEC_ERROR; |
206 | goto done; | ||
207 | } | 207 | } |
208 | 208 | ||
209 | /* advance to first WAVE chunk */ | 209 | /* advance to first WAVE chunk */ |
@@ -224,8 +224,7 @@ next_track: | |||
224 | if (n < 8) { | 224 | if (n < 8) { |
225 | DEBUGF("data chunk request_buffer error\n"); | 225 | DEBUGF("data chunk request_buffer error\n"); |
226 | /* no more chunks, 'data' chunk must not have been found */ | 226 | /* no more chunks, 'data' chunk must not have been found */ |
227 | status = CODEC_ERROR; | 227 | return CODEC_ERROR; |
228 | goto done; | ||
229 | } | 228 | } |
230 | 229 | ||
231 | /* chunkSize */ | 230 | /* chunkSize */ |
@@ -233,8 +232,7 @@ next_track: | |||
233 | if (memcmp(buf, WAVE64_GUID_FMT, 16) == 0) { | 232 | if (memcmp(buf, WAVE64_GUID_FMT, 16) == 0) { |
234 | if (size < 16) { | 233 | if (size < 16) { |
235 | DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%d < 16\n", (int)size); | 234 | DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%d < 16\n", (int)size); |
236 | status = CODEC_ERROR; | 235 | return CODEC_ERROR; |
237 | goto done; | ||
238 | } | 236 | } |
239 | /* wFormatTag */ | 237 | /* wFormatTag */ |
240 | format.formattag=buf[24]|(buf[25]<<8); | 238 | format.formattag=buf[24]|(buf[25]<<8); |
@@ -263,8 +261,7 @@ next_track: | |||
263 | if (format.size < 22) { | 261 | if (format.size < 22) { |
264 | DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " | 262 | DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " |
265 | "missing extension\n"); | 263 | "missing extension\n"); |
266 | status = CODEC_ERROR; | 264 | return CODEC_ERROR; |
267 | goto done; | ||
268 | } | 265 | } |
269 | /* wValidBitsPerSample */ | 266 | /* wValidBitsPerSample */ |
270 | format.bitspersample = buf[42]|(buf[43]<<8); | 267 | format.bitspersample = buf[42]|(buf[43]<<8); |
@@ -279,10 +276,7 @@ next_track: | |||
279 | if (format.formattag == WAVE_FORMAT_ADPCM) | 276 | if (format.formattag == WAVE_FORMAT_ADPCM) |
280 | { | 277 | { |
281 | if (!set_msadpcm_coeffs(buf)) | 278 | if (!set_msadpcm_coeffs(buf)) |
282 | { | 279 | return CODEC_ERROR; |
283 | status = CODEC_ERROR; | ||
284 | goto done; | ||
285 | } | ||
286 | } | 280 | } |
287 | 281 | ||
288 | /* get codec */ | 282 | /* get codec */ |
@@ -291,8 +285,7 @@ next_track: | |||
291 | { | 285 | { |
292 | DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", | 286 | DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", |
293 | (unsigned int) format.formattag); | 287 | (unsigned int) format.formattag); |
294 | status = CODEC_ERROR; | 288 | return CODEC_ERROR; |
295 | goto done; | ||
296 | } | 289 | } |
297 | 290 | ||
298 | /* riff 8bit linear pcm is unsigned */ | 291 | /* riff 8bit linear pcm is unsigned */ |
@@ -301,10 +294,7 @@ next_track: | |||
301 | 294 | ||
302 | /* check format, and calculate chunk size */ | 295 | /* check format, and calculate chunk size */ |
303 | if (!codec->set_format(&format)) | 296 | if (!codec->set_format(&format)) |
304 | { | 297 | return CODEC_ERROR; |
305 | status = CODEC_ERROR; | ||
306 | goto done; | ||
307 | } | ||
308 | } else if (memcmp(buf, WAVE64_GUID_DATA, 16) == 0) { | 298 | } else if (memcmp(buf, WAVE64_GUID_DATA, 16) == 0) { |
309 | format.numbytes = size; | 299 | format.numbytes = size; |
310 | /* advance to start of data */ | 300 | /* advance to start of data */ |
@@ -330,31 +320,26 @@ next_track: | |||
330 | if (!codec) | 320 | if (!codec) |
331 | { | 321 | { |
332 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); | 322 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); |
333 | status = CODEC_ERROR; | 323 | return CODEC_ERROR; |
334 | goto done; | ||
335 | } | 324 | } |
336 | 325 | ||
337 | /* common format check */ | 326 | /* common format check */ |
338 | if (format.channels == 0) { | 327 | if (format.channels == 0) { |
339 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); | 328 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); |
340 | status = CODEC_ERROR; | 329 | return CODEC_ERROR; |
341 | goto done; | ||
342 | } | 330 | } |
343 | if (format.samplesperblock == 0) { | 331 | if (format.samplesperblock == 0) { |
344 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); | 332 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); |
345 | status = CODEC_ERROR; | 333 | return CODEC_ERROR; |
346 | goto done; | ||
347 | } | 334 | } |
348 | if (format.blockalign == 0) | 335 | if (format.blockalign == 0) |
349 | { | 336 | { |
350 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); | 337 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); |
351 | status = CODEC_ERROR; | 338 | return CODEC_ERROR; |
352 | goto done; | ||
353 | } | 339 | } |
354 | if (format.numbytes == 0) { | 340 | if (format.numbytes == 0) { |
355 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); | 341 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); |
356 | status = CODEC_ERROR; | 342 | return CODEC_ERROR; |
357 | goto done; | ||
358 | } | 343 | } |
359 | 344 | ||
360 | /* check chunksize */ | 345 | /* check chunksize */ |
@@ -364,8 +349,7 @@ next_track: | |||
364 | if (format.chunksize == 0) | 349 | if (format.chunksize == 0) |
365 | { | 350 | { |
366 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); | 351 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); |
367 | status = CODEC_ERROR; | 352 | return CODEC_ERROR; |
368 | goto done; | ||
369 | } | 353 | } |
370 | 354 | ||
371 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 355 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
@@ -375,8 +359,7 @@ next_track: | |||
375 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | 359 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); |
376 | } else { | 360 | } else { |
377 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); | 361 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); |
378 | status = CODEC_ERROR; | 362 | return CODEC_ERROR; |
379 | goto done; | ||
380 | } | 363 | } |
381 | 364 | ||
382 | /* make sure we're at the correct offset */ | 365 | /* make sure we're at the correct offset */ |
@@ -385,14 +368,14 @@ next_track: | |||
385 | struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, | 368 | struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, |
386 | PCM_SEEK_POS, &read_buffer); | 369 | PCM_SEEK_POS, &read_buffer); |
387 | 370 | ||
388 | if (newpos->pos > format.numbytes) | 371 | if (newpos->pos > format.numbytes) { |
389 | goto done; | 372 | return CODEC_OK; |
373 | } | ||
390 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 374 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
391 | { | 375 | { |
392 | bytesdone = newpos->pos; | 376 | bytesdone = newpos->pos; |
393 | decodedsamples = newpos->samples; | 377 | decodedsamples = newpos->samples; |
394 | } | 378 | } |
395 | ci->seek_complete(); | ||
396 | } else { | 379 | } else { |
397 | /* already where we need to be */ | 380 | /* already where we need to be */ |
398 | bytesdone = 0; | 381 | bytesdone = 0; |
@@ -402,22 +385,29 @@ next_track: | |||
402 | endofstream = 0; | 385 | endofstream = 0; |
403 | 386 | ||
404 | while (!endofstream) { | 387 | while (!endofstream) { |
405 | ci->yield(); | 388 | enum codec_command_action action = ci->get_command(¶m); |
406 | if (ci->stop_codec || ci->new_track) { | 389 | |
390 | if (action == CODEC_ACTION_HALT) | ||
407 | break; | 391 | break; |
408 | } | ||
409 | 392 | ||
410 | if (ci->seek_time) { | 393 | if (action == CODEC_ACTION_SEEK_TIME) { |
411 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, | 394 | struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, |
412 | &read_buffer); | 395 | &read_buffer); |
413 | 396 | ||
414 | if (newpos->pos > format.numbytes) | 397 | if (newpos->pos > format.numbytes) |
398 | { | ||
399 | ci->set_elapsed(ci->id3->length); | ||
400 | ci->seek_complete(); | ||
415 | break; | 401 | break; |
402 | } | ||
403 | |||
416 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 404 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
417 | { | 405 | { |
418 | bytesdone = newpos->pos; | 406 | bytesdone = newpos->pos; |
419 | decodedsamples = newpos->samples; | 407 | decodedsamples = newpos->samples; |
420 | } | 408 | } |
409 | |||
410 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | ||
421 | ci->seek_complete(); | 411 | ci->seek_complete(); |
422 | } | 412 | } |
423 | 413 | ||
@@ -429,11 +419,10 @@ next_track: | |||
429 | endofstream = 1; | 419 | endofstream = 1; |
430 | } | 420 | } |
431 | 421 | ||
432 | status = codec->decode(wavbuf, n, samples, &bufcount); | 422 | if (codec->decode(wavbuf, n, samples, &bufcount) == CODEC_ERROR) |
433 | if (status == CODEC_ERROR) | ||
434 | { | 423 | { |
435 | DEBUGF("codec error\n"); | 424 | DEBUGF("codec error\n"); |
436 | goto done; | 425 | return CODEC_ERROR; |
437 | } | 426 | } |
438 | 427 | ||
439 | ci->pcmbuf_insert(samples, NULL, bufcount); | 428 | ci->pcmbuf_insert(samples, NULL, bufcount); |
@@ -445,12 +434,6 @@ next_track: | |||
445 | endofstream = 1; | 434 | endofstream = 1; |
446 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | 435 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); |
447 | } | 436 | } |
448 | status = CODEC_OK; | ||
449 | |||
450 | done: | ||
451 | if (ci->request_next_track()) | ||
452 | goto next_track; | ||
453 | 437 | ||
454 | exit: | 438 | return CODEC_OK; |
455 | return status; | ||
456 | } | 439 | } |