summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2012-05-13 03:25:55 -0400
committerMichael Sevakis <jethead71@rockbox.org>2012-05-13 03:25:55 -0400
commit80d5267a9b5e98a904e479ea6fa89868ffbe1c1e (patch)
tree7b6f35d5cdead2afbecae6fb95229667caca0c8e /apps
parent1d21e54fc4f586bbdfb765c90c9a64c060eeecc4 (diff)
downloadrockbox-80d5267a9b5e98a904e479ea6fa89868ffbe1c1e.tar.gz
rockbox-80d5267a9b5e98a904e479ea6fa89868ffbe1c1e.zip
More strictly enforce "no PCM insert" rules for codecs.
Takes care of when codecs try to sneak-in another PCM buffer insert at the wrong time. Codecs are wiley and just can't always be trusted to cooperate. Change-Id: Idc2f51238a5fd69a9d9c0741fbc29addc6615bdf
Diffstat (limited to 'apps')
-rw-r--r--apps/codec_thread.c47
1 files changed, 27 insertions, 20 deletions
diff --git a/apps/codec_thread.c b/apps/codec_thread.c
index 523f0b8e35..308b2ff982 100644
--- a/apps/codec_thread.c
+++ b/apps/codec_thread.c
@@ -214,40 +214,41 @@ static void codec_pcmbuf_insert_callback(
const void *ch1, const void *ch2, int count)
{
struct dsp_buffer src;
-
src.remcount = count;
src.pin[0] = ch1;
src.pin[1] = ch2;
src.proc_mask = 0;
- while (1)
+ while (LIKELY(queue_empty(&codec_queue)) ||
+ codec_check_queue__have_msg() >= 0)
{
struct dsp_buffer dst;
dst.remcount = 0;
dst.bufcount = MAX(src.remcount, 1024); /* Arbitrary min request */
- while ((dst.p16out = pcmbuf_request_buffer(&dst.bufcount)) == NULL)
+ if ((dst.p16out = pcmbuf_request_buffer(&dst.bufcount)) == NULL)
{
cancel_cpu_boost();
/* It may be awhile before space is available but we want
"instant" response to any message */
queue_wait_w_tmo(&codec_queue, NULL, HZ/20);
+ }
+ else
+ {
+ dsp_process(ci.dsp, &src, &dst);
- if (!queue_empty(&codec_queue) &&
- codec_check_queue__have_msg() < 0)
+ if (dst.remcount > 0)
{
- return;
+ pcmbuf_write_complete(dst.remcount, ci.id3->elapsed,
+ ci.id3->offset);
+ }
+ else if (src.remcount <= 0)
+ {
+ return; /* No input remains and DSP purged */
}
}
-
- dsp_process(ci.dsp, &src, &dst);
-
- if (dst.remcount > 0)
- pcmbuf_write_complete(dst.remcount, ci.id3->elapsed, ci.id3->offset);
- else if (src.remcount <= 0)
- break; /* No input remains and DSP purged */
- }
+ }
}
/* helper function, not a callback */
@@ -360,9 +361,12 @@ static enum codec_command_action
{
enum codec_command_action action = CODEC_ACTION_NULL;
struct queue_event ev;
- queue_wait(&codec_queue, &ev);
- switch (ev.id)
+ queue_peek(&codec_queue, &ev); /* Find out what it is */
+
+ long id = ev.id;
+
+ switch (id)
{
case Q_CODEC_RUN: /* Already running */
LOGFQUEUE("codec < Q_CODEC_RUN");
@@ -370,27 +374,30 @@ static enum codec_command_action
case Q_CODEC_PAUSE: /* Stay here and wait */
LOGFQUEUE("codec < Q_CODEC_PAUSE");
+ queue_wait(&codec_queue, &ev); /* Remove message */
codec_queue_ack(Q_CODEC_PAUSE);
+ queue_wait(&codec_queue, NULL); /* Wait for next (no remove) */
continue;
case Q_CODEC_SEEK: /* Audio wants codec to seek */
LOGFQUEUE("codec < Q_CODEC_SEEK %ld", ev.data);
*param = ev.data;
action = CODEC_ACTION_SEEK_TIME;
+ trigger_cpu_boost();
break;
case Q_CODEC_STOP: /* Must only return 0 in main loop */
LOGFQUEUE("codec < Q_CODEC_STOP");
- action = CODEC_ACTION_HALT;
dsp_configure(ci.dsp, DSP_FLUSH, 0); /* Discontinuity */
- break;
+ return CODEC_ACTION_HALT; /* Leave in queue */
default: /* This is in error in this context. */
- ev.id = Q_NULL;
logf("codec bad req %ld (%s)", ev.id, __func__);
+ id = Q_NULL;
}
- codec_queue_ack(ev.id);
+ queue_wait(&codec_queue, &ev); /* Actually remove it */
+ codec_queue_ack(id);
return action;
}
}