summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/FastMixer.cpp
diff options
context:
space:
mode:
authorGlenn Kasten <gkasten@google.com>2012-06-13 17:14:03 -0700
committerGlenn Kasten <gkasten@google.com>2012-06-15 10:21:47 -0700
commit972af221ae7253e406e0e1ea853e56a3010ed6b1 (patch)
tree77175ced586c67275d09b73524b935b15eab3090 /services/audioflinger/FastMixer.cpp
parentfc42e16d96b7e1b18b573f40df1319c56f8ab933 (diff)
downloadframeworks_av-972af221ae7253e406e0e1ea853e56a3010ed6b1.zip
frameworks_av-972af221ae7253e406e0e1ea853e56a3010ed6b1.tar.gz
frameworks_av-972af221ae7253e406e0e1ea853e56a3010ed6b1.tar.bz2
FastMixer compensates for SRC jitter in audio HAL
Force a sleep if audio HAL write() returns too quickly. Bug: 6661275 Change-Id: Ie810f5a087b89fb24dab229a0e500af1dee53571
Diffstat (limited to 'services/audioflinger/FastMixer.cpp')
-rw-r--r--services/audioflinger/FastMixer.cpp20
1 files changed, 14 insertions, 6 deletions
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 19ee9b3..2c5d751 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -65,6 +65,7 @@ bool FastMixer::threadLoop()
long periodNs = 0; // expected period; the time required to render one mix buffer
long underrunNs = 0; // underrun likely when write cycle is greater than this value
long overrunNs = 0; // overrun likely when write cycle is less than this value
+ long forceNs = 0; // if overrun detected, force the write cycle to take this much time
long warmupNs = 0; // warmup complete when write cycle is greater than to this value
FastMixerDumpState dummyDumpState, *dumpState = &dummyDumpState;
bool ignoreNextOverrun = true; // used to ignore initial overrun and first after an underrun
@@ -221,11 +222,14 @@ bool FastMixer::threadLoop()
periodNs = (frameCount * 1000000000LL) / sampleRate; // 1.00
underrunNs = (frameCount * 1750000000LL) / sampleRate; // 1.75
overrunNs = (frameCount * 250000000LL) / sampleRate; // 0.25
+ forceNs = (frameCount * 750000000LL) / sampleRate; // 0.75
warmupNs = (frameCount * 500000000LL) / sampleRate; // 0.50
} else {
periodNs = 0;
underrunNs = 0;
overrunNs = 0;
+ forceNs = 0;
+ warmupNs = 0;
}
mixBufferState = UNDEFINED;
#if !LOG_NDEBUG
@@ -468,6 +472,8 @@ bool FastMixer::threadLoop()
dumpState->mWarmupCycles = warmupCycles;
}
}
+ sleepNs = -1;
+ if (isWarm) {
if (sec > 0 || nsec > underrunNs) {
#if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER)
ScopedTrace st(ATRACE_TAG, "underrun");
@@ -476,7 +482,6 @@ bool FastMixer::threadLoop()
ALOGV("underrun: time since last cycle %d.%03ld sec",
(int) sec, nsec / 1000000L);
dumpState->mUnderruns++;
- sleepNs = -1;
ignoreNextOverrun = true;
} else if (nsec < overrunNs) {
if (ignoreNextOverrun) {
@@ -487,14 +492,17 @@ bool FastMixer::threadLoop()
(int) sec, nsec / 1000000L);
dumpState->mOverruns++;
}
- // Code for non blocking audio HAL. Sleep time must be tuned to allow
- // catching up after an underrun
- // sleepNs = periodNs - overrunNs;
- sleepNs = -1;
+ // This forces a minimum cycle time. It:
+ // - compensates for an audio HAL with jitter due to sample rate conversion
+ // - works with a variable buffer depth audio HAL that never pulls at a rate
+ // < than overrunNs per buffer.
+ // - recovers from overrun immediately after underrun
+ // It doesn't work with a non-blocking audio HAL.
+ sleepNs = forceNs - nsec;
} else {
- sleepNs = -1;
ignoreNextOverrun = false;
}
+ }
#ifdef FAST_MIXER_STATISTICS
// advance the FIFO queue bounds
size_t i = bounds & (FastMixerDumpState::kSamplingN - 1);