More work on swcodec. No significant pcmbuf functions are called from the audio thread now. Do not be surprised if seek or skip behavior gets weird after this, but it Works for Me (TM), and is a significant step in the right direction.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9510 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Brandon Low 2006-04-05 04:27:16 +00:00
parent 4ff8744e55
commit 33a62e8a8e
5 changed files with 29 additions and 45 deletions

View file

@ -111,13 +111,13 @@ reasonable amount of time for the typical user to react */
void ab_jump_to_A_marker(void) void ab_jump_to_A_marker(void)
{ {
#if (CONFIG_CODEC == SWCODEC) #if (CONFIG_CODEC != SWCODEC)
audio_seamless_seek(ab_A_marker);
#else
bool paused = (audio_status() & AUDIO_STATUS_PAUSE) != 0; bool paused = (audio_status() & AUDIO_STATUS_PAUSE) != 0;
if ( ! paused ) if ( ! paused )
audio_pause(); audio_pause();
#endif
audio_ff_rewind(ab_A_marker); audio_ff_rewind(ab_A_marker);
#if (CONFIG_CODEC != SWCODEC)
if ( ! paused ) if ( ! paused )
audio_resume(); audio_resume();
#endif #endif

View file

@ -61,8 +61,6 @@ static bool crossfade_init IDATA_ATTR;
static size_t crossfade_pos IDATA_ATTR; static size_t crossfade_pos IDATA_ATTR;
static size_t crossfade_rem IDATA_ATTR; static size_t crossfade_rem IDATA_ATTR;
static struct mutex pcmbuf_mutex IDATA_ATTR;
/* Crossfade modes. If CFM_CROSSFADE is selected, normal /* Crossfade modes. If CFM_CROSSFADE is selected, normal
* crossfader will activate. Selecting CFM_FLUSH is a special * crossfader will activate. Selecting CFM_FLUSH is a special
* operation that only overwrites the pcm buffer without crossfading. * operation that only overwrites the pcm buffer without crossfading.
@ -297,7 +295,6 @@ bool pcmbuf_crossfade_init(bool manual_skip)
void pcmbuf_play_stop(void) void pcmbuf_play_stop(void)
{ {
mutex_lock(&pcmbuf_mutex);
/** Prevent a very tiny pop from happening by muting audio /** Prevent a very tiny pop from happening by muting audio
* until dma has been initialized. */ * until dma has been initialized. */
pcm_mute(true); pcm_mute(true);
@ -320,7 +317,6 @@ void pcmbuf_play_stop(void)
pcmbuf_set_boost_mode(false); pcmbuf_set_boost_mode(false);
pcmbuf_boost(false); pcmbuf_boost(false);
mutex_unlock(&pcmbuf_mutex);
} }
int pcmbuf_used_descs(void) { int pcmbuf_used_descs(void) {
@ -356,7 +352,6 @@ static void pcmbuf_init_pcmbuffers(void) {
* ...CODECBUFFER|---------PCMBUF---------|GUARDBUF|DESCS| */ * ...CODECBUFFER|---------PCMBUF---------|GUARDBUF|DESCS| */
void pcmbuf_init(size_t bufsize) void pcmbuf_init(size_t bufsize)
{ {
mutex_init(&pcmbuf_mutex);
pcmbuf_size = bufsize; pcmbuf_size = bufsize;
pcmbuf_descsize = pcmbuf_descs()*sizeof(struct pcmbufdesc); pcmbuf_descsize = pcmbuf_descs()*sizeof(struct pcmbufdesc);
audiobuffer = (char *)&audiobuf[(audiobufend - audiobuf) - audiobuffer = (char *)&audiobuf[(audiobufend - audiobuf) -
@ -401,8 +396,6 @@ void pcmbuf_pause(bool pause) {
/* Force playback. */ /* Force playback. */
void pcmbuf_play_start(void) void pcmbuf_play_start(void)
{ {
mutex_lock(&pcmbuf_mutex);
if (!pcm_is_playing() && pcmbuf_unplayed_bytes) if (!pcm_is_playing() && pcmbuf_unplayed_bytes)
{ {
/** Prevent a very tiny pop from happening by muting audio /** Prevent a very tiny pop from happening by muting audio
@ -417,8 +410,6 @@ void pcmbuf_play_start(void)
/* Now unmute the audio. */ /* Now unmute the audio. */
pcm_mute(false); pcm_mute(false);
} }
mutex_unlock(&pcmbuf_mutex);
} }
/** /**
@ -426,8 +417,6 @@ void pcmbuf_play_start(void)
*/ */
static void pcmbuf_flush_fillpos(void) static void pcmbuf_flush_fillpos(void)
{ {
mutex_lock(&pcmbuf_mutex);
if (audiobuffer_fillpos) { if (audiobuffer_fillpos) {
/* Never use the last buffer descriptor */ /* Never use the last buffer descriptor */
while (pcmbuf_write == pcmbuf_write_end) { while (pcmbuf_write == pcmbuf_write_end) {
@ -444,8 +433,6 @@ static void pcmbuf_flush_fillpos(void)
} }
pcmbuf_add_chunk(); pcmbuf_add_chunk();
} }
mutex_unlock(&pcmbuf_mutex);
} }
/** /**

View file

@ -70,6 +70,7 @@
static volatile bool audio_codec_loaded; static volatile bool audio_codec_loaded;
static volatile bool voice_codec_loaded; static volatile bool voice_codec_loaded;
static volatile bool playing; static volatile bool playing;
static volatile bool seeking;
#define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec" #define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec"
#define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec" #define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec"
@ -102,7 +103,6 @@ enum {
Q_AUDIO_TRACK_CHANGED, Q_AUDIO_TRACK_CHANGED,
Q_AUDIO_DIR_NEXT, Q_AUDIO_DIR_NEXT,
Q_AUDIO_DIR_PREV, Q_AUDIO_DIR_PREV,
Q_AUDIO_SEAMLESS_SEEK,
Q_AUDIO_POSTINIT, Q_AUDIO_POSTINIT,
Q_CODEC_LOAD, Q_CODEC_LOAD,
@ -679,7 +679,12 @@ off_t codec_mp3_get_filepos_callback(int newtime)
void codec_seek_complete_callback(void) void codec_seek_complete_callback(void)
{ {
/* assume we're called from non-voice codec, as they shouldn't seek */ /* assume we're called from non-voice codec, as they shouldn't seek */
if (pcm_is_paused()) {
/* If this is not a seamless seek, clear the buffer */
pcmbuf_play_stop();
}
ci.seek_time = 0; ci.seek_time = 0;
seeking = false;
} }
bool codec_seek_buffer_callback(size_t newpos) bool codec_seek_buffer_callback(size_t newpos)
@ -1329,10 +1334,10 @@ static void audio_clear_track_entries(bool buffered_only)
static void stop_codec_flush(void) static void stop_codec_flush(void)
{ {
ci.stop_codec = true; ci.stop_codec = true;
pcmbuf_play_stop(); pcmbuf_pause(true);
while (audio_codec_loaded) while (audio_codec_loaded)
yield(); yield();
pcmbuf_play_stop(); pcmbuf_pause(false);
} }
static void audio_stop_playback(bool resume) static void audio_stop_playback(bool resume)
@ -1343,7 +1348,6 @@ static void audio_stop_playback(bool resume)
playing = false; playing = false;
filling = false; filling = false;
stop_codec_flush(); stop_codec_flush();
pcmbuf_pause(false);
if (current_fd >= 0) { if (current_fd >= 0) {
close(current_fd); close(current_fd);
current_fd = -1; current_fd = -1;
@ -1768,11 +1772,11 @@ static void initiate_track_change(int peek_index)
{ {
/* Detect if disk is spinning or already loading. */ /* Detect if disk is spinning or already loading. */
if (filling || ci.reload_codec || !audio_codec_loaded) { if (filling || ci.reload_codec || !audio_codec_loaded) {
if (pcmbuf_is_crossfade_enabled()) if (pcmbuf_is_crossfade_enabled()) {
pcmbuf_crossfade_init(true); pcmbuf_crossfade_init(true);
else ci.stop_codec = true;
pcmbuf_play_stop(); } else
ci.stop_codec = true; stop_codec_flush();
queue_post(&audio_queue, Q_AUDIO_PLAY, 0); queue_post(&audio_queue, Q_AUDIO_PLAY, 0);
} else { } else {
new_track = peek_index; new_track = peek_index;
@ -1836,10 +1840,6 @@ void audio_thread(void)
play_pending = false; play_pending = false;
last_tick = current_tick; last_tick = current_tick;
/* Do not start crossfading if audio is paused. */
if (pcm_is_paused())
pcmbuf_play_stop();
#ifdef CONFIG_TUNER #ifdef CONFIG_TUNER
/* check if radio is playing */ /* check if radio is playing */
if (get_radio_status() != FMRADIO_OFF) { if (get_radio_status() != FMRADIO_OFF) {
@ -1848,6 +1848,7 @@ void audio_thread(void)
#endif #endif
logf("starting..."); logf("starting...");
playing = true; playing = true;
ci.stop_codec = true; ci.stop_codec = true;
ci.reload_codec = false; ci.reload_codec = false;
@ -1896,13 +1897,6 @@ void audio_thread(void)
break; break;
case Q_AUDIO_FF_REWIND: case Q_AUDIO_FF_REWIND:
if (!playing)
break ;
pcmbuf_play_stop();
ci.seek_time = (long)ev.data+1;
break ;
case Q_AUDIO_SEAMLESS_SEEK:
if (!playing) if (!playing)
break ; break ;
ci.seek_time = (long)ev.data+1; ci.seek_time = (long)ev.data+1;
@ -1911,6 +1905,7 @@ void audio_thread(void)
case Q_AUDIO_DIR_NEXT: case Q_AUDIO_DIR_NEXT:
logf("audio_dir_next"); logf("audio_dir_next");
playlist_end = false; playlist_end = false;
/* pcmbuf_beep may or may not be safe on audio thread */
if (global_settings.beep) if (global_settings.beep)
pcmbuf_beep(5000, 100, 2500*global_settings.beep); pcmbuf_beep(5000, 100, 2500*global_settings.beep);
initiate_dir_change(1); initiate_dir_change(1);
@ -1919,6 +1914,7 @@ void audio_thread(void)
case Q_AUDIO_DIR_PREV: case Q_AUDIO_DIR_PREV:
logf("audio_dir_prev"); logf("audio_dir_prev");
playlist_end = false; playlist_end = false;
/* pcmbuf_beep may or may not be safe on audio thread */
if (global_settings.beep) if (global_settings.beep)
pcmbuf_beep(5000, 100, 2500*global_settings.beep); pcmbuf_beep(5000, 100, 2500*global_settings.beep);
initiate_dir_change(-1); initiate_dir_change(-1);
@ -2010,6 +2006,9 @@ void codec_thread(void)
#endif #endif
} }
if (ci.stop_codec && pcm_is_paused())
pcmbuf_play_stop();
audio_codec_loaded = false; audio_codec_loaded = false;
switch (ev.id) { switch (ev.id) {
@ -2191,7 +2190,6 @@ void audio_play(long offset)
else else
{ {
stop_codec_flush(); stop_codec_flush();
pcmbuf_play_stop();
} }
queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset); queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset);
@ -2268,14 +2266,14 @@ void audio_prev_dir(void)
void audio_ff_rewind(long newpos) void audio_ff_rewind(long newpos)
{ {
logf("rewind: %d", newpos); logf("ff/rewind: %d", newpos);
seeking = true;
queue_post(&audio_queue, Q_AUDIO_FF_REWIND, (int *)newpos); queue_post(&audio_queue, Q_AUDIO_FF_REWIND, (int *)newpos);
} /* This is a hack, the correct solution is to report back to
* the caller when the seek is complete. */
void audio_seamless_seek(long newpos) while (seeking) {
{ yield();
logf("seamless_seek: %d", newpos); }
queue_post(&audio_queue, Q_AUDIO_SEAMLESS_SEEK, (int *)newpos);
} }
void audio_flush_and_reload_tracks(void) void audio_flush_and_reload_tracks(void)

View file

@ -71,7 +71,6 @@ void audio_next(void);
void audio_prev(void); void audio_prev(void);
int audio_status(void); int audio_status(void);
void audio_ff_rewind(long newtime); void audio_ff_rewind(long newtime);
void audio_seamless_seek(long newtime);
void audio_flush_and_reload_tracks(void); void audio_flush_and_reload_tracks(void);
struct mp3entry* audio_current_track(void); struct mp3entry* audio_current_track(void);
struct mp3entry* audio_next_track(void); struct mp3entry* audio_next_track(void);

View file

@ -638,7 +638,7 @@ void pcm_play_pause(bool play)
/* nothing yet */ /* nothing yet */
#endif #endif
} }
} } /* pcm_playing && needs_change */
} }
bool pcm_is_playing(void) { bool pcm_is_playing(void) {