summaryrefslogtreecommitdiff
path: root/apps/codecs/mpa.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/mpa.c')
-rw-r--r--apps/codecs/mpa.c142
1 files changed, 137 insertions, 5 deletions
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c
index 7ac96fb8b2..c916aefcaa 100644
--- a/apps/codecs/mpa.c
+++ b/apps/codecs/mpa.c
@@ -25,13 +25,34 @@
25 25
26CODEC_HEADER 26CODEC_HEADER
27 27
28#if (CONFIG_CPU == PP5024 || CONFIG_CPU == PP5022 || CONFIG_CPU == PP5020 \
29 || CONFIG_CPU == PP5002) && !defined(MPEGPLAYER)
30#define MPA_SYNTH_ON_COP
31#endif
32
28struct mad_stream stream IBSS_ATTR; 33struct mad_stream stream IBSS_ATTR;
29struct mad_frame frame IBSS_ATTR; 34struct mad_frame frame IBSS_ATTR;
30struct mad_synth synth IBSS_ATTR; 35struct mad_synth synth IBSS_ATTR;
31 36
37#ifdef MPA_SYNTH_ON_COP
38volatile short synth_running IBSS_ATTR; /*synthesis is running*/
39volatile short die IBSS_ATTR; /*thread should die*/
40
41#if (CONFIG_CPU == PP5024) || (CONFIG_CPU == PP5022)
42mad_fixed_t sbsample_prev[2][36][32] IBSS_ATTR;
43#else
44mad_fixed_t sbsample_prev[2][36][32] SHAREDBSS_ATTR;
45#endif
46
47struct semaphore synth_done_sem IBSS_ATTR;
48struct semaphore synth_pending_sem IBSS_ATTR;
49#endif
50
32#define INPUT_CHUNK_SIZE 8192 51#define INPUT_CHUNK_SIZE 8192
33 52
34mad_fixed_t mad_frame_overlap[2][32][18] IBSS_ATTR; 53mad_fixed_t mad_frame_overlap[2][32][18] IBSS_ATTR;
54mad_fixed_t sbsample[2][36][32] IBSS_ATTR;
55
35unsigned char mad_main_data[MAD_BUFFER_MDLEN] IBSS_ATTR; 56unsigned char mad_main_data[MAD_BUFFER_MDLEN] IBSS_ATTR;
36/* TODO: what latency does layer 1 have? */ 57/* TODO: what latency does layer 1 have? */
37int mpeg_latency[3] = { 0, 481, 529 }; 58int mpeg_latency[3] = { 0, 481, 529 };
@@ -43,6 +64,14 @@ void init_mad(void)
43 ci->memset(&frame, 0, sizeof(struct mad_frame)); 64 ci->memset(&frame, 0, sizeof(struct mad_frame));
44 ci->memset(&synth, 0, sizeof(struct mad_synth)); 65 ci->memset(&synth, 0, sizeof(struct mad_synth));
45 66
67#ifdef MPA_SYNTH_ON_COP
68 frame.sbsample_prev = &sbsample_prev;
69#else
70 frame.sbsample_prev = &sbsample;
71#endif
72
73 frame.sbsample=&sbsample;
74
46 mad_stream_init(&stream); 75 mad_stream_init(&stream);
47 mad_frame_init(&frame); 76 mad_frame_init(&frame);
48 mad_synth_init(&synth); 77 mad_synth_init(&synth);
@@ -51,6 +80,8 @@ void init_mad(void)
51 ci->memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap)); 80 ci->memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap));
52 frame.overlap = &mad_frame_overlap; 81 frame.overlap = &mad_frame_overlap;
53 stream.main_data = &mad_main_data; 82 stream.main_data = &mad_main_data;
83
84
54} 85}
55 86
56int get_file_pos(int newtime) 87int get_file_pos(int newtime)
@@ -159,6 +190,90 @@ static void set_elapsed(struct mp3entry* id3)
159 } 190 }
160} 191}
161 192
193#ifdef MPA_SYNTH_ON_COP
194
195/*
196 * Run the synthesis filter on the COProcessor
197 */
198
199static int mad_synth_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)/2] IBSS_ATTR;
200
201static const unsigned char * const mad_synth_thread_name = "mp3dec";
202static struct thread_entry *mad_synth_thread_p;
203
204
205static void mad_synth_thread(void){
206
207 while(1){
208 ci->semaphore_wait(&synth_pending_sem);
209
210 if(die){
211 die=0;
212 invalidate_icache();
213 return ;
214 }
215 synth_running = 1;
216 mad_synth_frame(&synth, &frame);
217 synth_running = 0;
218 ci->semaphore_release(&synth_done_sem);
219 }
220}
221
222
223static int mad_synth_thread_wait_pcm(void){
224 ci->semaphore_wait(&synth_done_sem);
225 return 0;
226}
227
228static void mad_synth_thread_ready(void){
229 mad_fixed_t (*temp)[2][36][32];
230 while(1){
231 /*check if synth is currently running before changing its inputs! */
232 if(!synth_running){
233 /*circular buffer that holds 2 frames' samples*/
234 temp=frame.sbsample;
235 frame.sbsample = frame.sbsample_prev;
236 frame.sbsample_prev=temp;
237
238 ci->semaphore_release(&synth_pending_sem);
239 return ;
240 }
241 ci->yield(); /*synth thread currently running, wait for it*/
242 }
243}
244
245static int mad_synth_thread_create(void){
246 synth_running=0;
247 die=0;
248
249 ci->semaphore_init(&synth_done_sem, 1, 0);
250 ci->semaphore_init(&synth_pending_sem, 1, 0);
251
252 mad_synth_thread_p = ci->create_thread(mad_synth_thread,
253 mad_synth_thread_stack,
254 sizeof(mad_synth_thread_stack), 0,
255 mad_synth_thread_name
256 IF_PRIO(, PRIORITY_PLAYBACK), COP);
257
258 if (mad_synth_thread_p == NULL)
259 return false;
260
261 return true;
262
263}
264#else
265static void mad_synth_thread_ready(void){
266 mad_synth_frame(&synth, &frame);
267}
268static int mad_synth_thread_create(void){
269 return 0;
270}
271static int mad_synth_thread_wait_pcm(void){
272 return 0;
273}
274
275#endif
276
162/* this is the codec entry point */ 277/* this is the codec entry point */
163enum codec_status codec_main(void) 278enum codec_status codec_main(void)
164{ 279{
@@ -180,8 +295,12 @@ enum codec_status codec_main(void)
180 /* Create a decoder instance */ 295 /* Create a decoder instance */
181 296
182 ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS); 297 ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS);
183 298
184next_track: 299next_track:
300
301 /*does nothing on 1 processor systems*/
302 mad_synth_thread_create();
303
185 status = CODEC_OK; 304 status = CODEC_OK;
186 305
187 /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */ 306 /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */
@@ -300,6 +419,9 @@ next_track:
300 data (not the one just decoded above). When we exit the decoding 419 data (not the one just decoded above). When we exit the decoding
301 loop we will need to process the final frame that was decoded. */ 420 loop we will need to process the final frame that was decoded. */
302 if (framelength > 0) { 421 if (framelength > 0) {
422
423 mad_synth_thread_wait_pcm();
424
303 /* In case of a mono file, the second array will be ignored. */ 425 /* In case of a mono file, the second array will be ignored. */
304 ci->pcmbuf_insert(&synth.pcm.samples[0][samples_to_skip], 426 ci->pcmbuf_insert(&synth.pcm.samples[0][samples_to_skip],
305 &synth.pcm.samples[1][samples_to_skip], 427 &synth.pcm.samples[1][samples_to_skip],
@@ -308,8 +430,9 @@ next_track:
308 /* Only skip samples for the first frame added. */ 430 /* Only skip samples for the first frame added. */
309 samples_to_skip = 0; 431 samples_to_skip = 0;
310 } 432 }
311 433
312 mad_synth_frame(&synth, &frame); 434 mad_synth_thread_ready();
435 //mad_synth_frame(&synth, &frame);
313 436
314 /* Check if sample rate and stereo settings changed in this frame. */ 437 /* Check if sample rate and stereo settings changed in this frame. */
315 if (frame.header.samplerate != current_frequency) { 438 if (frame.header.samplerate != current_frequency) {
@@ -345,11 +468,20 @@ next_track:
345 468
346 /* Finish the remaining decoded frame. 469 /* Finish the remaining decoded frame.
347 Cut the required samples from the end. */ 470 Cut the required samples from the end. */
348 if (framelength > stop_skip) 471 if (framelength > stop_skip){
472 mad_synth_thread_wait_pcm();
349 ci->pcmbuf_insert(synth.pcm.samples[0], synth.pcm.samples[1], 473 ci->pcmbuf_insert(synth.pcm.samples[0], synth.pcm.samples[1],
350 framelength - stop_skip); 474 framelength - stop_skip);
351 475}
476#ifdef MPA_SYNTH_ON_COP
477 /*mop up COP thread*/
478 die=1;
479 ci->semaphore_release(&synth_pending_sem);
480 ci->thread_wait(mad_synth_thread_p);
481 invalidate_icache();
352 stream.error = 0; 482 stream.error = 0;
483#endif
484
353 485
354 if (ci->request_next_track()) 486 if (ci->request_next_track())
355 goto next_track; 487 goto next_track;