summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-09-23 08:09:04 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-09-23 08:09:04 +0000
commit5c903724fbc930d57d4e07a719d4abfd65dec593 (patch)
treec3f4e1a81e2035aaa57bfdbac7c7a1efe35b1041
parentb95dbd21cf79940a02ef9f95d8914b7f439f2891 (diff)
downloadrockbox-5c903724fbc930d57d4e07a719d4abfd65dec593.tar.gz
rockbox-5c903724fbc930d57d4e07a719d4abfd65dec593.zip
Simplify synchronizaton for MPA codec and make it fully atomic, let synth thread exist for life of codec, do a bit of cleanup and use number of cores do determine if it is compiled as multithread instead of CPU type.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18573 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs/mpa.c144
1 files changed, 72 insertions, 72 deletions
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c
index e81d8d96c0..f998412de1 100644
--- a/apps/codecs/mpa.c
+++ b/apps/codecs/mpa.c
@@ -25,7 +25,7 @@
25 25
26CODEC_HEADER 26CODEC_HEADER
27 27
28#if defined(CPU_PP) && !defined(MPEGPLAYER) 28#if NUM_CORES > 1 && !defined(MPEGPLAYER)
29#define MPA_SYNTH_ON_COP 29#define MPA_SYNTH_ON_COP
30#endif 30#endif
31 31
@@ -34,8 +34,7 @@ struct mad_frame frame IBSS_ATTR;
34struct mad_synth synth IBSS_ATTR; 34struct mad_synth synth IBSS_ATTR;
35 35
36#ifdef MPA_SYNTH_ON_COP 36#ifdef MPA_SYNTH_ON_COP
37volatile short synth_running IBSS_ATTR; /*synthesis is running*/ 37volatile short die IBSS_ATTR = 0; /*thread should die*/
38volatile short die IBSS_ATTR; /*thread should die*/
39 38
40#if (CONFIG_CPU == PP5024) || (CONFIG_CPU == PP5022) 39#if (CONFIG_CPU == PP5024) || (CONFIG_CPU == PP5022)
41mad_fixed_t sbsample_prev[2][36][32] IBSS_ATTR; 40mad_fixed_t sbsample_prev[2][36][32] IBSS_ATTR;
@@ -68,7 +67,6 @@ void init_mad(void)
68#ifdef MPA_SYNTH_ON_COP 67#ifdef MPA_SYNTH_ON_COP
69 frame.sbsample_prev = &sbsample_prev; 68 frame.sbsample_prev = &sbsample_prev;
70 ci->memset(&sbsample_prev, 0, sizeof(sbsample_prev)); 69 ci->memset(&sbsample_prev, 0, sizeof(sbsample_prev));
71 synth_running=0;
72#else 70#else
73 frame.sbsample_prev = &sbsample; 71 frame.sbsample_prev = &sbsample;
74#endif 72#endif
@@ -208,73 +206,78 @@ static struct thread_entry *mad_synth_thread_p;
208static void mad_synth_thread(void){ 206static void mad_synth_thread(void){
209 207
210 while(1){ 208 while(1){
209 ci->semaphore_release(&synth_done_sem);
211 ci->semaphore_wait(&synth_pending_sem); 210 ci->semaphore_wait(&synth_pending_sem);
212 211
213 if(die){ 212 if(die)
214 die=0; 213 break;
215 invalidate_icache(); 214
216 return ;
217 }
218 synth_running = 1;
219 mad_synth_frame(&synth, &frame); 215 mad_synth_frame(&synth, &frame);
220 synth_running = 0;
221 ci->semaphore_release(&synth_done_sem);
222 } 216 }
223} 217}
224 218
225 219/* wait for the synth thread to go idle which indicates a PCM frame has been
226static int mad_synth_thread_wait_pcm(void){ 220 * synthesized */
221static inline void mad_synth_thread_wait_pcm(void){
227 ci->semaphore_wait(&synth_done_sem); 222 ci->semaphore_wait(&synth_done_sem);
228 return 0;
229} 223}
230 224
225/* increment the done semaphore - used after a wait for idle to preserve the
226 * semaphore count */
227static inline void mad_synth_thread_unwait_pcm(void){
228 ci->semaphore_release(&synth_done_sem);
229}
230
231/* after synth thread has gone idle - switch decoded frames and commence
232 * synthesis on it */
231static void mad_synth_thread_ready(void){ 233static void mad_synth_thread_ready(void){
232 mad_fixed_t (*temp)[2][36][32]; 234 mad_fixed_t (*temp)[2][36][32];
233 while(1){ 235
234 /*check if synth is currently running before changing its inputs! */ 236 /*circular buffer that holds 2 frames' samples*/
235 if(!synth_running){ 237 temp=frame.sbsample;
236 /*circular buffer that holds 2 frames' samples*/ 238 frame.sbsample = frame.sbsample_prev;
237 temp=frame.sbsample; 239 frame.sbsample_prev=temp;
238 frame.sbsample = frame.sbsample_prev; 240
239 frame.sbsample_prev=temp; 241 ci->semaphore_release(&synth_pending_sem);
240
241 ci->semaphore_release(&synth_pending_sem);
242 return ;
243 }
244 ci->yield(); /*synth thread currently running, wait for it*/
245 }
246} 242}
247 243
248static int mad_synth_thread_create(void){ 244static bool mad_synth_thread_create(void){
249 synth_running=0; 245 ci->semaphore_init(&synth_done_sem, 1, 0);
250 die=0; 246 ci->semaphore_init(&synth_pending_sem, 1, 0);
251
252 ci->semaphore_init(&synth_done_sem, 1, 0);
253 ci->semaphore_init(&synth_pending_sem, 1, 0);
254 247
255 mad_synth_thread_p = ci->create_thread(mad_synth_thread, 248 mad_synth_thread_p = ci->create_thread(mad_synth_thread,
256 mad_synth_thread_stack, 249 mad_synth_thread_stack,
257 sizeof(mad_synth_thread_stack), 0, 250 sizeof(mad_synth_thread_stack), 0,
258 mad_synth_thread_name 251 mad_synth_thread_name
259 IF_PRIO(, PRIORITY_PLAYBACK), COP); 252 IF_PRIO(, PRIORITY_PLAYBACK)
260 253 IF_COP(, COP));
261 if (mad_synth_thread_p == NULL)
262 return false;
263
264 return true;
265 254
255 if (mad_synth_thread_p == NULL)
256 return false;
257
258 return true;
259}
260
261static void mad_synth_thread_quit(void){
262 /*mop up COP thread*/
263 die=1;
264 ci->semaphore_release(&synth_pending_sem);
265 ci->thread_wait(mad_synth_thread_p);
266 invalidate_icache();
266} 267}
267#else 268#else
268static void mad_synth_thread_ready(void){ 269static inline void mad_synth_thread_ready(void){
269 mad_synth_frame(&synth, &frame); 270 mad_synth_frame(&synth, &frame);
270} 271}
271static int mad_synth_thread_create(void){ 272static inline bool mad_synth_thread_create(void){
272 return 0; 273 return true;
273} 274}
274static int mad_synth_thread_wait_pcm(void){ 275static inline void mad_synth_thread_quit(void){
275 return 0; 276}
277static inline void mad_synth_thread_wait_pcm(void){
278}
279static inline void mad_synth_thread_unwait_pcm(void){
276} 280}
277
278#endif 281#endif
279 282
280/* this is the codec entry point */ 283/* this is the codec entry point */
@@ -298,12 +301,13 @@ enum codec_status codec_main(void)
298 /* Create a decoder instance */ 301 /* Create a decoder instance */
299 302
300 ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS); 303 ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS);
304
305 /*does nothing on 1 processor systems except return true*/
306 if(!mad_synth_thread_create())
307 return CODEC_ERROR;
301 308
302next_track: 309next_track:
303 310
304 /*does nothing on 1 processor systems*/
305 mad_synth_thread_create();
306
307 status = CODEC_OK; 311 status = CODEC_OK;
308 312
309 /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */ 313 /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */
@@ -365,11 +369,10 @@ next_track:
365 if (ci->seek_time) { 369 if (ci->seek_time) {
366 int newpos; 370 int newpos;
367 371
368#ifdef MPA_SYNTH_ON_COP 372 /*make sure the synth thread is idle before seeking - MT only*/
369 /*make sure the synth thread is idle before seeking*/ 373 mad_synth_thread_wait_pcm();
370 if(synth_running) 374 mad_synth_thread_unwait_pcm();
371 mad_synth_thread_wait_pcm(); 375
372#endif
373 samplesdone = ((int64_t)(ci->seek_time-1))*current_frequency/1000; 376 samplesdone = ((int64_t)(ci->seek_time-1))*current_frequency/1000;
374 377
375 if (ci->seek_time-1 == 0) { 378 if (ci->seek_time-1 == 0) {
@@ -426,10 +429,10 @@ next_track:
426 /* Do the pcmbuf insert here. Note, this is the PREVIOUS frame's pcm 429 /* Do the pcmbuf insert here. Note, this is the PREVIOUS frame's pcm
427 data (not the one just decoded above). When we exit the decoding 430 data (not the one just decoded above). When we exit the decoding
428 loop we will need to process the final frame that was decoded. */ 431 loop we will need to process the final frame that was decoded. */
432 mad_synth_thread_wait_pcm();
433
429 if (framelength > 0) { 434 if (framelength > 0) {
430 435
431 mad_synth_thread_wait_pcm();
432
433 /* In case of a mono file, the second array will be ignored. */ 436 /* In case of a mono file, the second array will be ignored. */
434 ci->pcmbuf_insert(&synth.pcm.samples[0][samples_to_skip], 437 ci->pcmbuf_insert(&synth.pcm.samples[0][samples_to_skip],
435 &synth.pcm.samples[1][samples_to_skip], 438 &synth.pcm.samples[1][samples_to_skip],
@@ -438,9 +441,9 @@ next_track:
438 /* Only skip samples for the first frame added. */ 441 /* Only skip samples for the first frame added. */
439 samples_to_skip = 0; 442 samples_to_skip = 0;
440 } 443 }
441 444
445 /* Initiate PCM synthesis on the COP (MT) or perform it here (ST) */
442 mad_synth_thread_ready(); 446 mad_synth_thread_ready();
443 //mad_synth_frame(&synth, &frame);
444 447
445 /* Check if sample rate and stereo settings changed in this frame. */ 448 /* Check if sample rate and stereo settings changed in this frame. */
446 if (frame.header.samplerate != current_frequency) { 449 if (frame.header.samplerate != current_frequency) {
@@ -474,25 +477,22 @@ next_track:
474 ci->set_elapsed(samplesdone / (current_frequency / 1000)); 477 ci->set_elapsed(samplesdone / (current_frequency / 1000));
475 } 478 }
476 479
480 /* wait for synth idle - MT only*/
481 mad_synth_thread_wait_pcm();
482 mad_synth_thread_unwait_pcm();
483
477 /* Finish the remaining decoded frame. 484 /* Finish the remaining decoded frame.
478 Cut the required samples from the end. */ 485 Cut the required samples from the end. */
479 if (framelength > stop_skip){ 486 if (framelength > stop_skip){
480 mad_synth_thread_wait_pcm();
481 ci->pcmbuf_insert(synth.pcm.samples[0], synth.pcm.samples[1], 487 ci->pcmbuf_insert(synth.pcm.samples[0], synth.pcm.samples[1],
482 framelength - stop_skip); 488 framelength - stop_skip);
483} 489 }
484#ifdef MPA_SYNTH_ON_COP
485 /*mop up COP thread*/
486 die=1;
487 ci->semaphore_release(&synth_pending_sem);
488 ci->thread_wait(mad_synth_thread_p);
489 invalidate_icache();
490 stream.error = 0;
491#endif
492
493 490
494 if (ci->request_next_track()) 491 if (ci->request_next_track())
495 goto next_track; 492 goto next_track;
496 493
494 /*mop up COP thread - MT only*/
495 mad_synth_thread_quit();
496
497 return status; 497 return status;
498} 498}