forked from len0rd/rockbox
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
This commit is contained in:
parent
b95dbd21cf
commit
5c903724fb
1 changed files with 72 additions and 72 deletions
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
CODEC_HEADER
|
CODEC_HEADER
|
||||||
|
|
||||||
#if defined(CPU_PP) && !defined(MPEGPLAYER)
|
#if NUM_CORES > 1 && !defined(MPEGPLAYER)
|
||||||
#define MPA_SYNTH_ON_COP
|
#define MPA_SYNTH_ON_COP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -34,8 +34,7 @@ struct mad_frame frame IBSS_ATTR;
|
||||||
struct mad_synth synth IBSS_ATTR;
|
struct mad_synth synth IBSS_ATTR;
|
||||||
|
|
||||||
#ifdef MPA_SYNTH_ON_COP
|
#ifdef MPA_SYNTH_ON_COP
|
||||||
volatile short synth_running IBSS_ATTR; /*synthesis is running*/
|
volatile short die IBSS_ATTR = 0; /*thread should die*/
|
||||||
volatile short die IBSS_ATTR; /*thread should die*/
|
|
||||||
|
|
||||||
#if (CONFIG_CPU == PP5024) || (CONFIG_CPU == PP5022)
|
#if (CONFIG_CPU == PP5024) || (CONFIG_CPU == PP5022)
|
||||||
mad_fixed_t sbsample_prev[2][36][32] IBSS_ATTR;
|
mad_fixed_t sbsample_prev[2][36][32] IBSS_ATTR;
|
||||||
|
|
@ -68,7 +67,6 @@ void init_mad(void)
|
||||||
#ifdef MPA_SYNTH_ON_COP
|
#ifdef MPA_SYNTH_ON_COP
|
||||||
frame.sbsample_prev = &sbsample_prev;
|
frame.sbsample_prev = &sbsample_prev;
|
||||||
ci->memset(&sbsample_prev, 0, sizeof(sbsample_prev));
|
ci->memset(&sbsample_prev, 0, sizeof(sbsample_prev));
|
||||||
synth_running=0;
|
|
||||||
#else
|
#else
|
||||||
frame.sbsample_prev = &sbsample;
|
frame.sbsample_prev = &sbsample;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -208,47 +206,42 @@ static struct thread_entry *mad_synth_thread_p;
|
||||||
static void mad_synth_thread(void){
|
static void mad_synth_thread(void){
|
||||||
|
|
||||||
while(1){
|
while(1){
|
||||||
|
ci->semaphore_release(&synth_done_sem);
|
||||||
ci->semaphore_wait(&synth_pending_sem);
|
ci->semaphore_wait(&synth_pending_sem);
|
||||||
|
|
||||||
if(die){
|
if(die)
|
||||||
die=0;
|
break;
|
||||||
invalidate_icache();
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
synth_running = 1;
|
|
||||||
mad_synth_frame(&synth, &frame);
|
mad_synth_frame(&synth, &frame);
|
||||||
synth_running = 0;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait for the synth thread to go idle which indicates a PCM frame has been
|
||||||
|
* synthesized */
|
||||||
|
static inline void mad_synth_thread_wait_pcm(void){
|
||||||
|
ci->semaphore_wait(&synth_done_sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* increment the done semaphore - used after a wait for idle to preserve the
|
||||||
|
* semaphore count */
|
||||||
|
static inline void mad_synth_thread_unwait_pcm(void){
|
||||||
ci->semaphore_release(&synth_done_sem);
|
ci->semaphore_release(&synth_done_sem);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int mad_synth_thread_wait_pcm(void){
|
|
||||||
ci->semaphore_wait(&synth_done_sem);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* after synth thread has gone idle - switch decoded frames and commence
|
||||||
|
* synthesis on it */
|
||||||
static void mad_synth_thread_ready(void){
|
static void mad_synth_thread_ready(void){
|
||||||
mad_fixed_t (*temp)[2][36][32];
|
mad_fixed_t (*temp)[2][36][32];
|
||||||
while(1){
|
|
||||||
/*check if synth is currently running before changing its inputs! */
|
|
||||||
if(!synth_running){
|
|
||||||
/*circular buffer that holds 2 frames' samples*/
|
/*circular buffer that holds 2 frames' samples*/
|
||||||
temp=frame.sbsample;
|
temp=frame.sbsample;
|
||||||
frame.sbsample = frame.sbsample_prev;
|
frame.sbsample = frame.sbsample_prev;
|
||||||
frame.sbsample_prev=temp;
|
frame.sbsample_prev=temp;
|
||||||
|
|
||||||
ci->semaphore_release(&synth_pending_sem);
|
ci->semaphore_release(&synth_pending_sem);
|
||||||
return ;
|
|
||||||
}
|
|
||||||
ci->yield(); /*synth thread currently running, wait for it*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mad_synth_thread_create(void){
|
static bool mad_synth_thread_create(void){
|
||||||
synth_running=0;
|
|
||||||
die=0;
|
|
||||||
|
|
||||||
ci->semaphore_init(&synth_done_sem, 1, 0);
|
ci->semaphore_init(&synth_done_sem, 1, 0);
|
||||||
ci->semaphore_init(&synth_pending_sem, 1, 0);
|
ci->semaphore_init(&synth_pending_sem, 1, 0);
|
||||||
|
|
||||||
|
|
@ -256,25 +249,35 @@ static int mad_synth_thread_create(void){
|
||||||
mad_synth_thread_stack,
|
mad_synth_thread_stack,
|
||||||
sizeof(mad_synth_thread_stack), 0,
|
sizeof(mad_synth_thread_stack), 0,
|
||||||
mad_synth_thread_name
|
mad_synth_thread_name
|
||||||
IF_PRIO(, PRIORITY_PLAYBACK), COP);
|
IF_PRIO(, PRIORITY_PLAYBACK)
|
||||||
|
IF_COP(, COP));
|
||||||
|
|
||||||
if (mad_synth_thread_p == NULL)
|
if (mad_synth_thread_p == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mad_synth_thread_quit(void){
|
||||||
|
/*mop up COP thread*/
|
||||||
|
die=1;
|
||||||
|
ci->semaphore_release(&synth_pending_sem);
|
||||||
|
ci->thread_wait(mad_synth_thread_p);
|
||||||
|
invalidate_icache();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void mad_synth_thread_ready(void){
|
static inline void mad_synth_thread_ready(void){
|
||||||
mad_synth_frame(&synth, &frame);
|
mad_synth_frame(&synth, &frame);
|
||||||
}
|
}
|
||||||
static int mad_synth_thread_create(void){
|
static inline bool mad_synth_thread_create(void){
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
static int mad_synth_thread_wait_pcm(void){
|
static inline void mad_synth_thread_quit(void){
|
||||||
return 0;
|
}
|
||||||
|
static inline void mad_synth_thread_wait_pcm(void){
|
||||||
|
}
|
||||||
|
static inline void mad_synth_thread_unwait_pcm(void){
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* this is the codec entry point */
|
/* this is the codec entry point */
|
||||||
|
|
@ -299,10 +302,11 @@ enum codec_status codec_main(void)
|
||||||
|
|
||||||
ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS);
|
ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS);
|
||||||
|
|
||||||
next_track:
|
/*does nothing on 1 processor systems except return true*/
|
||||||
|
if(!mad_synth_thread_create())
|
||||||
|
return CODEC_ERROR;
|
||||||
|
|
||||||
/*does nothing on 1 processor systems*/
|
next_track:
|
||||||
mad_synth_thread_create();
|
|
||||||
|
|
||||||
status = CODEC_OK;
|
status = CODEC_OK;
|
||||||
|
|
||||||
|
|
@ -365,11 +369,10 @@ next_track:
|
||||||
if (ci->seek_time) {
|
if (ci->seek_time) {
|
||||||
int newpos;
|
int newpos;
|
||||||
|
|
||||||
#ifdef MPA_SYNTH_ON_COP
|
/*make sure the synth thread is idle before seeking - MT only*/
|
||||||
/*make sure the synth thread is idle before seeking*/
|
|
||||||
if(synth_running)
|
|
||||||
mad_synth_thread_wait_pcm();
|
mad_synth_thread_wait_pcm();
|
||||||
#endif
|
mad_synth_thread_unwait_pcm();
|
||||||
|
|
||||||
samplesdone = ((int64_t)(ci->seek_time-1))*current_frequency/1000;
|
samplesdone = ((int64_t)(ci->seek_time-1))*current_frequency/1000;
|
||||||
|
|
||||||
if (ci->seek_time-1 == 0) {
|
if (ci->seek_time-1 == 0) {
|
||||||
|
|
@ -426,10 +429,10 @@ next_track:
|
||||||
/* Do the pcmbuf insert here. Note, this is the PREVIOUS frame's pcm
|
/* Do the pcmbuf insert here. Note, this is the PREVIOUS frame's pcm
|
||||||
data (not the one just decoded above). When we exit the decoding
|
data (not the one just decoded above). When we exit the decoding
|
||||||
loop we will need to process the final frame that was decoded. */
|
loop we will need to process the final frame that was decoded. */
|
||||||
if (framelength > 0) {
|
|
||||||
|
|
||||||
mad_synth_thread_wait_pcm();
|
mad_synth_thread_wait_pcm();
|
||||||
|
|
||||||
|
if (framelength > 0) {
|
||||||
|
|
||||||
/* In case of a mono file, the second array will be ignored. */
|
/* In case of a mono file, the second array will be ignored. */
|
||||||
ci->pcmbuf_insert(&synth.pcm.samples[0][samples_to_skip],
|
ci->pcmbuf_insert(&synth.pcm.samples[0][samples_to_skip],
|
||||||
&synth.pcm.samples[1][samples_to_skip],
|
&synth.pcm.samples[1][samples_to_skip],
|
||||||
|
|
@ -439,8 +442,8 @@ next_track:
|
||||||
samples_to_skip = 0;
|
samples_to_skip = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initiate PCM synthesis on the COP (MT) or perform it here (ST) */
|
||||||
mad_synth_thread_ready();
|
mad_synth_thread_ready();
|
||||||
//mad_synth_frame(&synth, &frame);
|
|
||||||
|
|
||||||
/* Check if sample rate and stereo settings changed in this frame. */
|
/* Check if sample rate and stereo settings changed in this frame. */
|
||||||
if (frame.header.samplerate != current_frequency) {
|
if (frame.header.samplerate != current_frequency) {
|
||||||
|
|
@ -474,25 +477,22 @@ next_track:
|
||||||
ci->set_elapsed(samplesdone / (current_frequency / 1000));
|
ci->set_elapsed(samplesdone / (current_frequency / 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* wait for synth idle - MT only*/
|
||||||
|
mad_synth_thread_wait_pcm();
|
||||||
|
mad_synth_thread_unwait_pcm();
|
||||||
|
|
||||||
/* Finish the remaining decoded frame.
|
/* Finish the remaining decoded frame.
|
||||||
Cut the required samples from the end. */
|
Cut the required samples from the end. */
|
||||||
if (framelength > stop_skip){
|
if (framelength > stop_skip){
|
||||||
mad_synth_thread_wait_pcm();
|
|
||||||
ci->pcmbuf_insert(synth.pcm.samples[0], synth.pcm.samples[1],
|
ci->pcmbuf_insert(synth.pcm.samples[0], synth.pcm.samples[1],
|
||||||
framelength - stop_skip);
|
framelength - stop_skip);
|
||||||
}
|
}
|
||||||
#ifdef MPA_SYNTH_ON_COP
|
|
||||||
/*mop up COP thread*/
|
|
||||||
die=1;
|
|
||||||
ci->semaphore_release(&synth_pending_sem);
|
|
||||||
ci->thread_wait(mad_synth_thread_p);
|
|
||||||
invalidate_icache();
|
|
||||||
stream.error = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
if (ci->request_next_track())
|
if (ci->request_next_track())
|
||||||
goto next_track;
|
goto next_track;
|
||||||
|
|
||||||
|
/*mop up COP thread - MT only*/
|
||||||
|
mad_synth_thread_quit();
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue