diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-10-16 01:25:17 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-10-16 01:25:17 +0000 |
commit | a9b2fb5ee3114fe835f6515b6aeae7454f66d821 (patch) | |
tree | fc4e96d0c1f215565918406c8827b16b806c1345 /apps/playback.c | |
parent | a3fbbc9fa7e12fd3fce122bbd235dc362050e024 (diff) | |
download | rockbox-a9b2fb5ee3114fe835f6515b6aeae7454f66d821.tar.gz rockbox-a9b2fb5ee3114fe835f6515b6aeae7454f66d821.zip |
Finally full multicore support for PortalPlayer 502x targets with an eye towards the possibility of other types. All SVN targets the low-lag code to speed up blocking operations. Most files are modified here simple due to a name change to actually support a real event object and a param change to create_thread. Add some use of new features but just sit on things for a bit and leave full integration for later. Work will continue on to address size on sensitive targets and simplify things if possible. Any PP target having problems with SWP can easily be changed to sw corelocks with one #define change in config.h though only PP5020 has shown an issue and seems to work without any difficulties.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15134 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/playback.c')
-rw-r--r-- | apps/playback.c | 92 |
1 files changed, 53 insertions, 39 deletions
diff --git a/apps/playback.c b/apps/playback.c index b80c68384f..0fd1c21daf 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -290,8 +290,8 @@ static void set_current_codec(int codec_idx); | |||
290 | static void set_filebuf_watermark(int seconds); | 290 | static void set_filebuf_watermark(int seconds); |
291 | 291 | ||
292 | /* Audio thread */ | 292 | /* Audio thread */ |
293 | static struct event_queue audio_queue; | 293 | static struct event_queue audio_queue NOCACHEBSS_ATTR; |
294 | static struct queue_sender_list audio_queue_sender_list; | 294 | static struct queue_sender_list audio_queue_sender_list NOCACHEBSS_ATTR; |
295 | static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; | 295 | static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; |
296 | static const char audio_thread_name[] = "audio"; | 296 | static const char audio_thread_name[] = "audio"; |
297 | 297 | ||
@@ -340,9 +340,10 @@ static unsigned char *dram_buf = NULL; | |||
340 | automatically swaps in the other and the swap when unlocking should not | 340 | automatically swaps in the other and the swap when unlocking should not |
341 | happen if the parity is even. | 341 | happen if the parity is even. |
342 | */ | 342 | */ |
343 | static bool swap_codec_parity = false; /* true=odd, false=even */ | 343 | static bool swap_codec_parity NOCACHEBSS_ATTR = false; /* true=odd, false=even */ |
344 | /* Mutex to control which codec (normal/voice) is running */ | 344 | /* Locking to control which codec (normal/voice) is running */ |
345 | static struct mutex mutex_codecthread NOCACHEBSS_ATTR; | 345 | static struct semaphore sem_codecthread NOCACHEBSS_ATTR; |
346 | static struct event event_codecthread NOCACHEBSS_ATTR; | ||
346 | 347 | ||
347 | /* Voice state */ | 348 | /* Voice state */ |
348 | static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */ | 349 | static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */ |
@@ -424,8 +425,7 @@ static void wait_for_voice_swap_in(void) | |||
424 | if (NULL == iram_buf) | 425 | if (NULL == iram_buf) |
425 | return; | 426 | return; |
426 | 427 | ||
427 | while (current_codec != CODEC_IDX_VOICE) | 428 | event_wait(&event_codecthread, STATE_NONSIGNALED); |
428 | yield(); | ||
429 | #endif /* PLAYBACK_VOICE */ | 429 | #endif /* PLAYBACK_VOICE */ |
430 | } | 430 | } |
431 | 431 | ||
@@ -924,21 +924,21 @@ static void swap_codec(void) | |||
924 | } | 924 | } |
925 | 925 | ||
926 | /* Release my semaphore */ | 926 | /* Release my semaphore */ |
927 | mutex_unlock(&mutex_codecthread); | 927 | semaphore_release(&sem_codecthread); |
928 | logf("unlocked: %d", my_codec); | 928 | logf("unlocked: %d", my_codec); |
929 | 929 | ||
930 | /* Loop until the other codec has locked and run */ | 930 | /* Wait for other codec */ |
931 | do { | 931 | event_wait(&event_codecthread, |
932 | /* Release my semaphore and force a task switch. */ | 932 | (my_codec == CODEC_IDX_AUDIO) ? STATE_NONSIGNALED : STATE_SIGNALED); |
933 | yield(); | ||
934 | } while (my_codec == current_codec); | ||
935 | 933 | ||
936 | /* Wait for other codec to unlock */ | 934 | /* Wait for other codec to unlock */ |
937 | mutex_lock(&mutex_codecthread); | 935 | logf("waiting for lock: %d", my_codec); |
936 | semaphore_wait(&sem_codecthread); | ||
938 | 937 | ||
939 | /* Take control */ | 938 | /* Take control */ |
940 | logf("waiting for lock: %d", my_codec); | ||
941 | set_current_codec(my_codec); | 939 | set_current_codec(my_codec); |
940 | event_set_state(&event_codecthread, | ||
941 | (my_codec == CODEC_IDX_AUDIO) ? STATE_SIGNALED : STATE_NONSIGNALED); | ||
942 | 942 | ||
943 | /* Reload our IRAM and DRAM */ | 943 | /* Reload our IRAM and DRAM */ |
944 | memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE); | 944 | memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE); |
@@ -1161,7 +1161,7 @@ static bool voice_on_voice_stop(bool aborting, size_t *realsize) | |||
1161 | 1161 | ||
1162 | static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize) | 1162 | static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize) |
1163 | { | 1163 | { |
1164 | struct event ev; | 1164 | struct queue_event ev; |
1165 | 1165 | ||
1166 | if (ci_voice.new_track) | 1166 | if (ci_voice.new_track) |
1167 | { | 1167 | { |
@@ -1332,7 +1332,8 @@ static void voice_thread(void) | |||
1332 | { | 1332 | { |
1333 | logf("Loading voice codec"); | 1333 | logf("Loading voice codec"); |
1334 | voice_codec_loaded = true; | 1334 | voice_codec_loaded = true; |
1335 | mutex_lock(&mutex_codecthread); | 1335 | semaphore_wait(&sem_codecthread); |
1336 | event_set_state(&event_codecthread, false); | ||
1336 | set_current_codec(CODEC_IDX_VOICE); | 1337 | set_current_codec(CODEC_IDX_VOICE); |
1337 | dsp_configure(DSP_RESET, 0); | 1338 | dsp_configure(DSP_RESET, 0); |
1338 | voice_remaining = 0; | 1339 | voice_remaining = 0; |
@@ -1344,9 +1345,8 @@ static void voice_thread(void) | |||
1344 | 1345 | ||
1345 | logf("Voice codec finished"); | 1346 | logf("Voice codec finished"); |
1346 | voice_codec_loaded = false; | 1347 | voice_codec_loaded = false; |
1347 | mutex_unlock(&mutex_codecthread); | ||
1348 | voice_thread_p = NULL; | 1348 | voice_thread_p = NULL; |
1349 | remove_thread(NULL); | 1349 | semaphore_release(&sem_codecthread); |
1350 | } /* voice_thread */ | 1350 | } /* voice_thread */ |
1351 | 1351 | ||
1352 | #endif /* PLAYBACK_VOICE */ | 1352 | #endif /* PLAYBACK_VOICE */ |
@@ -1968,7 +1968,7 @@ static bool codec_request_next_track_callback(void) | |||
1968 | 1968 | ||
1969 | static void codec_thread(void) | 1969 | static void codec_thread(void) |
1970 | { | 1970 | { |
1971 | struct event ev; | 1971 | struct queue_event ev; |
1972 | int status; | 1972 | int status; |
1973 | size_t wrap; | 1973 | size_t wrap; |
1974 | 1974 | ||
@@ -1988,13 +1988,14 @@ static void codec_thread(void) | |||
1988 | LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); | 1988 | LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); |
1989 | queue_post(&voice_queue, Q_AUDIO_PLAY, 0); | 1989 | queue_post(&voice_queue, Q_AUDIO_PLAY, 0); |
1990 | } | 1990 | } |
1991 | mutex_lock(&mutex_codecthread); | 1991 | semaphore_wait(&sem_codecthread); |
1992 | event_set_state(&event_codecthread, true); | ||
1992 | #endif | 1993 | #endif |
1993 | set_current_codec(CODEC_IDX_AUDIO); | 1994 | set_current_codec(CODEC_IDX_AUDIO); |
1994 | ci.stop_codec = false; | 1995 | ci.stop_codec = false; |
1995 | status = codec_load_file((const char *)ev.data, &ci); | 1996 | status = codec_load_file((const char *)ev.data, &ci); |
1996 | #ifdef PLAYBACK_VOICE | 1997 | #ifdef PLAYBACK_VOICE |
1997 | mutex_unlock(&mutex_codecthread); | 1998 | semaphore_release(&sem_codecthread); |
1998 | #endif | 1999 | #endif |
1999 | break; | 2000 | break; |
2000 | 2001 | ||
@@ -2019,7 +2020,8 @@ static void codec_thread(void) | |||
2019 | LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); | 2020 | LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); |
2020 | queue_post(&voice_queue, Q_AUDIO_PLAY, 0); | 2021 | queue_post(&voice_queue, Q_AUDIO_PLAY, 0); |
2021 | } | 2022 | } |
2022 | mutex_lock(&mutex_codecthread); | 2023 | semaphore_wait(&sem_codecthread); |
2024 | event_set_state(&event_codecthread, true); | ||
2023 | #endif | 2025 | #endif |
2024 | set_current_codec(CODEC_IDX_AUDIO); | 2026 | set_current_codec(CODEC_IDX_AUDIO); |
2025 | ci.stop_codec = false; | 2027 | ci.stop_codec = false; |
@@ -2027,7 +2029,7 @@ static void codec_thread(void) | |||
2027 | status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize, | 2029 | status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize, |
2028 | &filebuf[0], wrap, &ci); | 2030 | &filebuf[0], wrap, &ci); |
2029 | #ifdef PLAYBACK_VOICE | 2031 | #ifdef PLAYBACK_VOICE |
2030 | mutex_unlock(&mutex_codecthread); | 2032 | semaphore_release(&sem_codecthread); |
2031 | #endif | 2033 | #endif |
2032 | break; | 2034 | break; |
2033 | 2035 | ||
@@ -2041,14 +2043,15 @@ static void codec_thread(void) | |||
2041 | LOGFQUEUE("codec > voice Q_ENCODER_RECORD"); | 2043 | LOGFQUEUE("codec > voice Q_ENCODER_RECORD"); |
2042 | queue_post(&voice_queue, Q_ENCODER_RECORD, 0); | 2044 | queue_post(&voice_queue, Q_ENCODER_RECORD, 0); |
2043 | } | 2045 | } |
2044 | mutex_lock(&mutex_codecthread); | 2046 | semaphore_wait(&sem_codecthread); |
2047 | event_set_state(&event_codecthread, true); | ||
2045 | #endif | 2048 | #endif |
2046 | logf("loading encoder"); | 2049 | logf("loading encoder"); |
2047 | set_current_codec(CODEC_IDX_AUDIO); | 2050 | set_current_codec(CODEC_IDX_AUDIO); |
2048 | ci.stop_encoder = false; | 2051 | ci.stop_encoder = false; |
2049 | status = codec_load_file((const char *)ev.data, &ci); | 2052 | status = codec_load_file((const char *)ev.data, &ci); |
2050 | #ifdef PLAYBACK_VOICE | 2053 | #ifdef PLAYBACK_VOICE |
2051 | mutex_unlock(&mutex_codecthread); | 2054 | semaphore_release(&sem_codecthread); |
2052 | #endif | 2055 | #endif |
2053 | logf("encoder stopped"); | 2056 | logf("encoder stopped"); |
2054 | break; | 2057 | break; |
@@ -3594,13 +3597,13 @@ static bool ata_fillbuffer_callback(void) | |||
3594 | 3597 | ||
3595 | static void audio_thread(void) | 3598 | static void audio_thread(void) |
3596 | { | 3599 | { |
3597 | struct event ev; | 3600 | struct queue_event ev; |
3598 | 3601 | ||
3599 | pcm_postinit(); | 3602 | pcm_postinit(); |
3600 | 3603 | ||
3601 | #ifdef PLAYBACK_VOICE | 3604 | #ifdef PLAYBACK_VOICE |
3602 | /* Unlock mutex that init stage locks before creating this thread */ | 3605 | /* Unlock semaphore that init stage locks before creating this thread */ |
3603 | mutex_unlock(&mutex_codecthread); | 3606 | semaphore_release(&sem_codecthread); |
3604 | 3607 | ||
3605 | /* Buffers must be set up by now - should panic - really */ | 3608 | /* Buffers must be set up by now - should panic - really */ |
3606 | if (buffer_state != BUFFER_STATE_INITIALIZED) | 3609 | if (buffer_state != BUFFER_STATE_INITIALIZED) |
@@ -3764,7 +3767,9 @@ void audio_init(void) | |||
3764 | #ifdef PLAYBACK_VOICE | 3767 | #ifdef PLAYBACK_VOICE |
3765 | static bool voicetagtrue = true; | 3768 | static bool voicetagtrue = true; |
3766 | static struct mp3entry id3_voice; | 3769 | static struct mp3entry id3_voice; |
3770 | struct thread_entry *voice_thread_p = NULL; | ||
3767 | #endif | 3771 | #endif |
3772 | struct thread_entry *audio_thread_p; | ||
3768 | 3773 | ||
3769 | /* Can never do this twice */ | 3774 | /* Can never do this twice */ |
3770 | if (audio_is_initialized) | 3775 | if (audio_is_initialized) |
@@ -3779,11 +3784,11 @@ void audio_init(void) | |||
3779 | to send messages. Thread creation will be delayed however so nothing | 3784 | to send messages. Thread creation will be delayed however so nothing |
3780 | starts running until ready if something yields such as talk_init. */ | 3785 | starts running until ready if something yields such as talk_init. */ |
3781 | #ifdef PLAYBACK_VOICE | 3786 | #ifdef PLAYBACK_VOICE |
3782 | mutex_init(&mutex_codecthread); | ||
3783 | /* Take ownership of lock to prevent playback of anything before audio | 3787 | /* Take ownership of lock to prevent playback of anything before audio |
3784 | hardware is initialized - audio thread unlocks it after final init | 3788 | hardware is initialized - audio thread unlocks it after final init |
3785 | stage */ | 3789 | stage */ |
3786 | mutex_lock(&mutex_codecthread); | 3790 | semaphore_init(&sem_codecthread, 1, 0); |
3791 | event_init(&event_codecthread, EVENT_MANUAL | STATE_SIGNALED); | ||
3787 | #endif | 3792 | #endif |
3788 | queue_init(&audio_queue, true); | 3793 | queue_init(&audio_queue, true); |
3789 | queue_enable_queue_send(&audio_queue, &audio_queue_sender_list); | 3794 | queue_enable_queue_send(&audio_queue, &audio_queue_sender_list); |
@@ -3842,16 +3847,16 @@ void audio_init(void) | |||
3842 | talk first */ | 3847 | talk first */ |
3843 | talk_init(); | 3848 | talk_init(); |
3844 | 3849 | ||
3845 | /* Create the threads late now that we shouldn't be yielding again before | ||
3846 | returning */ | ||
3847 | codec_thread_p = create_thread( | 3850 | codec_thread_p = create_thread( |
3848 | codec_thread, codec_stack, sizeof(codec_stack), | 3851 | codec_thread, codec_stack, sizeof(codec_stack), |
3852 | CREATE_THREAD_FROZEN, | ||
3849 | codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK) | 3853 | codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK) |
3850 | IF_COP(, CPU, true)); | 3854 | IF_COP(, CPU)); |
3851 | 3855 | ||
3852 | create_thread(audio_thread, audio_stack, sizeof(audio_stack), | 3856 | audio_thread_p = create_thread(audio_thread, audio_stack, |
3857 | sizeof(audio_stack), CREATE_THREAD_FROZEN, | ||
3853 | audio_thread_name IF_PRIO(, PRIORITY_BUFFERING) | 3858 | audio_thread_name IF_PRIO(, PRIORITY_BUFFERING) |
3854 | IF_COP(, CPU, false)); | 3859 | IF_COP(, CPU)); |
3855 | 3860 | ||
3856 | #ifdef PLAYBACK_VOICE | 3861 | #ifdef PLAYBACK_VOICE |
3857 | /* TODO: Change this around when various speech codecs can be used */ | 3862 | /* TODO: Change this around when various speech codecs can be used */ |
@@ -3859,9 +3864,10 @@ void audio_init(void) | |||
3859 | { | 3864 | { |
3860 | logf("Starting voice codec"); | 3865 | logf("Starting voice codec"); |
3861 | queue_init(&voice_queue, true); | 3866 | queue_init(&voice_queue, true); |
3862 | create_thread(voice_thread, voice_stack, | 3867 | voice_thread_p = create_thread(voice_thread, voice_stack, |
3863 | sizeof(voice_stack), voice_thread_name | 3868 | sizeof(voice_stack), CREATE_THREAD_FROZEN, |
3864 | IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU, false)); | 3869 | voice_thread_name |
3870 | IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU)); | ||
3865 | } | 3871 | } |
3866 | #endif | 3872 | #endif |
3867 | 3873 | ||
@@ -3881,5 +3887,13 @@ void audio_init(void) | |||
3881 | #ifndef HAVE_FLASH_STORAGE | 3887 | #ifndef HAVE_FLASH_STORAGE |
3882 | audio_set_buffer_margin(global_settings.buffer_margin); | 3888 | audio_set_buffer_margin(global_settings.buffer_margin); |
3883 | #endif | 3889 | #endif |
3890 | |||
3891 | /* it's safe to let the threads run now */ | ||
3892 | thread_thaw(codec_thread_p); | ||
3893 | #ifdef PLAYBACK_VOICE | ||
3894 | if (voice_thread_p) | ||
3895 | thread_thaw(voice_thread_p); | ||
3896 | #endif | ||
3897 | thread_thaw(audio_thread_p); | ||
3884 | } /* audio_init */ | 3898 | } /* audio_init */ |
3885 | 3899 | ||