diff options
author | Glenn Kasten <gkasten@google.com> | 2012-05-18 10:47:28 -0700 |
---|---|---|
committer | Glenn Kasten <gkasten@google.com> | 2012-05-18 11:44:27 -0700 |
commit | 6d8aabe8a3be1ac0789d00b82c3ca8b81381f5ab (patch) | |
tree | 1f621b7f3f61ede29474f1d2c3802ecffa1df4c7 | |
parent | 874a897f09dc7b06679bb273506d7e0fa0152220 (diff) | |
download | frameworks_av-6d8aabe8a3be1ac0789d00b82c3ca8b81381f5ab.zip frameworks_av-6d8aabe8a3be1ac0789d00b82c3ca8b81381f5ab.tar.gz frameworks_av-6d8aabe8a3be1ac0789d00b82c3ca8b81381f5ab.tar.bz2 |
Add throttle to have pipe fill at more stable rate
Change-Id: Ibff9ab62764e2acd04518a4a00e25f19e28aff4a
-rw-r--r-- | services/audioflinger/MonoPipe.cpp | 74 | ||||
-rw-r--r-- | services/audioflinger/MonoPipe.h | 1 |
2 files changed, 58 insertions, 17 deletions
diff --git a/services/audioflinger/MonoPipe.cpp b/services/audioflinger/MonoPipe.cpp index b0ddf83..fd16e92 100644 --- a/services/audioflinger/MonoPipe.cpp +++ b/services/audioflinger/MonoPipe.cpp @@ -33,16 +33,6 @@ MonoPipe::MonoPipe(size_t maxFrames, NBAIO_Format format, bool writeCanBlock) : mRear(0), mWriteCanBlock(writeCanBlock) { - if (writeCanBlock) { - // compute sleep time to be about 2/3 of a full pipe; - // this gives a balance between risk of underrun vs. too-frequent wakeups - mSleep.tv_sec = 0; - uint64_t ns = mMaxFrames * (666666667 / Format_sampleRate(format)); - if (ns > 999999999) { - ns = 999999999; - } - mSleep.tv_nsec = ns; - } } MonoPipe::~MonoPipe() @@ -62,13 +52,13 @@ ssize_t MonoPipe::availableToWrite() const ssize_t MonoPipe::write(const void *buffer, size_t count) { - // count == 0 is unlikely and not worth checking for explicitly; will be handled automatically if (CC_UNLIKELY(!mNegotiated)) { return NEGOTIATE; } size_t totalFramesWritten = 0; - for (;;) { - size_t written = availableToWrite(); + while (count > 0) { + size_t avail = availableToWrite(); + size_t written = avail; if (CC_LIKELY(written > count)) { written = count; } @@ -88,12 +78,64 @@ ssize_t MonoPipe::write(const void *buffer, size_t count) android_atomic_release_store(written + mRear, &mRear); totalFramesWritten += written; } - if ((count -= written) == 0 || !mWriteCanBlock) { + if (!mWriteCanBlock) { break; } + count -= written; buffer = (char *) buffer + (written << mBitShift); - // simulate blocking I/O by sleeping - nanosleep(&mSleep, NULL); + // Simulate blocking I/O by sleeping at different rates, depending on a throttle. + // The throttle tries to keep the pipe about 5/8 full on average, with a slight jitter. + uint64_t ns; + enum { + THROTTLE_VERY_FAST, // pipe is (nearly) empty, fill quickly + THROTTLE_FAST, // pipe is normal, fill at slightly faster rate + THROTTLE_NOMINAL, // pipe is normal, fill at nominal rate + THROTTLE_SLOW, // pipe is normal, fill at slightly slower rate + THROTTLE_VERY_SLOW, // pipe is (nearly) full, fill slowly + } throttle; + avail -= written; + // FIXME cache these values to avoid re-computation + if (avail >= (mMaxFrames * 3) / 4) { + throttle = THROTTLE_VERY_FAST; + } else if (avail >= mMaxFrames / 2) { + throttle = THROTTLE_FAST; + } else if (avail >= (mMaxFrames * 3) / 8) { + throttle = THROTTLE_NOMINAL; + } else if (avail >= mMaxFrames / 4) { + throttle = THROTTLE_SLOW; + } else { + throttle = THROTTLE_VERY_SLOW; + } + if (written > 0) { + // FIXME cache these values also + switch (throttle) { + case THROTTLE_VERY_FAST: + default: + ns = written * ( 500000000 / Format_sampleRate(mFormat)); + break; + case THROTTLE_FAST: + ns = written * ( 750000000 / Format_sampleRate(mFormat)); + break; + case THROTTLE_NOMINAL: + ns = written * (1000000000 / Format_sampleRate(mFormat)); + break; + case THROTTLE_SLOW: + ns = written * (1100000000 / Format_sampleRate(mFormat)); + break; + case THROTTLE_VERY_SLOW: + ns = written * (1250000000 / Format_sampleRate(mFormat)); + break; + } + } else { + ns = mMaxFrames * (250000000 / Format_sampleRate(mFormat)); + } + if (ns > 999999999) { + ns = 999999999; + } + struct timespec sleep; + sleep.tv_sec = 0; + sleep.tv_nsec = ns; + nanosleep(&sleep, NULL); } mFramesWritten += totalFramesWritten; return totalFramesWritten; diff --git a/services/audioflinger/MonoPipe.h b/services/audioflinger/MonoPipe.h index 45e6bb4..1f56e54 100644 --- a/services/audioflinger/MonoPipe.h +++ b/services/audioflinger/MonoPipe.h @@ -67,7 +67,6 @@ private: volatile int32_t mRear; // written by writer with android_atomic_release_store, // read by reader with android_atomic_acquire_load const bool mWriteCanBlock; // whether write() should block if the pipe is full - struct timespec mSleep; // time to sleep if blocking is enabled and the pipe is full }; } // namespace android |