summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorGlenn Kasten <gkasten@google.com>2012-05-30 16:34:17 -0700
committerGlenn Kasten <gkasten@google.com>2012-05-30 17:39:45 -0700
commit820ba70df8ba595ae9055dfd34fdbfa32f70f14d (patch)
treee97d469bcac8dc241ed7f6690db31035a6f1493b /services
parent4364d2d1fd712faed7e839b58fedba3f48f626d0 (diff)
downloadframeworks_av-820ba70df8ba595ae9055dfd34fdbfa32f70f14d.zip
frameworks_av-820ba70df8ba595ae9055dfd34fdbfa32f70f14d.tar.gz
frameworks_av-820ba70df8ba595ae9055dfd34fdbfa32f70f14d.tar.bz2
Pipe throttle based on requested frame count
Now does throttling based on the requested frame count, but still permits overfilling pipe up to the rounded-up frame count. Also still uses the larger frame count for non-blocking arithmetic. Bug: 6585323 Change-Id: Ic2420a071419905524a14c22ebe1ce0e32d70a9d
Diffstat (limited to 'services')
-rw-r--r--services/audioflinger/MonoPipe.cpp58
-rw-r--r--services/audioflinger/MonoPipe.h7
2 files changed, 24 insertions, 41 deletions
diff --git a/services/audioflinger/MonoPipe.cpp b/services/audioflinger/MonoPipe.cpp
index fd16e92..6efb8b1 100644
--- a/services/audioflinger/MonoPipe.cpp
+++ b/services/audioflinger/MonoPipe.cpp
@@ -25,9 +25,10 @@
namespace android {
-MonoPipe::MonoPipe(size_t maxFrames, NBAIO_Format format, bool writeCanBlock) :
+MonoPipe::MonoPipe(size_t reqFrames, NBAIO_Format format, bool writeCanBlock) :
NBAIO_Sink(format),
- mMaxFrames(roundup(maxFrames)),
+ mReqFrames(reqFrames),
+ mMaxFrames(roundup(reqFrames)),
mBuffer(malloc(mMaxFrames * Format_frameSize(format))),
mFront(0),
mRear(0),
@@ -45,6 +46,7 @@ ssize_t MonoPipe::availableToWrite() const
if (CC_UNLIKELY(!mNegotiated)) {
return NEGOTIATE;
}
+ // uses mMaxFrames not mReqFrames, so allows "over-filling" the pipe beyond requested limit
ssize_t ret = mMaxFrames - (mRear - android_atomic_acquire_load(&mFront));
ALOG_ASSERT((0 <= ret) && (ret <= mMaxFrames));
return ret;
@@ -57,6 +59,7 @@ ssize_t MonoPipe::write(const void *buffer, size_t count)
}
size_t totalFramesWritten = 0;
while (count > 0) {
+ // can't return a negative value, as we already checked for !mNegotiated
size_t avail = availableToWrite();
size_t written = avail;
if (CC_LIKELY(written > count)) {
@@ -84,50 +87,29 @@ ssize_t MonoPipe::write(const void *buffer, size_t count)
count -= written;
buffer = (char *) buffer + (written << mBitShift);
// 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;
- }
+ // The throttle tries to keep the pipe about 11/16 full on average, with a slight jitter.
+ uint32_t ns;
if (written > 0) {
- // FIXME cache these values also
- switch (throttle) {
- case THROTTLE_VERY_FAST:
- default:
+ size_t filled = (mMaxFrames - avail) + written;
+ // FIXME cache these values to avoid re-computation
+ if (filled <= mReqFrames / 4) {
+ // pipe is (nearly) empty, fill quickly
ns = written * ( 500000000 / Format_sampleRate(mFormat));
- break;
- case THROTTLE_FAST:
+ } else if (filled <= mReqFrames / 2) {
+ // pipe is normal, fill at slightly faster rate
ns = written * ( 750000000 / Format_sampleRate(mFormat));
- break;
- case THROTTLE_NOMINAL:
+ } else if (filled <= (mReqFrames * 5) / 8) {
+ // pipe is normal, fill at nominal rate
ns = written * (1000000000 / Format_sampleRate(mFormat));
- break;
- case THROTTLE_SLOW:
+ } else if (filled <= (mReqFrames * 3) / 4) {
+ // pipe is normal, fill at slightly slower rate
ns = written * (1100000000 / Format_sampleRate(mFormat));
- break;
- case THROTTLE_VERY_SLOW:
+ } else {
+ // pipe is (nearly) full, fill slowly
ns = written * (1250000000 / Format_sampleRate(mFormat));
- break;
}
} else {
- ns = mMaxFrames * (250000000 / Format_sampleRate(mFormat));
+ ns = mReqFrames * (250000000 / Format_sampleRate(mFormat));
}
if (ns > 999999999) {
ns = 999999999;
diff --git a/services/audioflinger/MonoPipe.h b/services/audioflinger/MonoPipe.h
index 545d6ac..aaaa51f 100644
--- a/services/audioflinger/MonoPipe.h
+++ b/services/audioflinger/MonoPipe.h
@@ -33,11 +33,11 @@ class MonoPipe : public NBAIO_Sink {
friend class MonoPipeReader;
public:
- // maxFrames will be rounded up to a power of 2, and all slots are available. Must be >= 2.
+ // reqFrames will be rounded up to a power of 2, and all slots are available. Must be >= 2.
// Note: whatever shares this object with another thread needs to do so in an SMP-safe way (like
// creating it the object before creating the other thread, or storing the object with a
// release_store). Otherwise the other thread could see a partially-constructed object.
- MonoPipe(size_t maxFrames, NBAIO_Format format, bool writeCanBlock = false);
+ MonoPipe(size_t reqFrames, NBAIO_Format format, bool writeCanBlock = false);
virtual ~MonoPipe();
// NBAIO_Port interface
@@ -58,9 +58,10 @@ public:
// average number of frames present in the pipe under normal conditions.
// See throttling mechanism in MonoPipe::write()
- size_t getAvgFrames() const { return (mMaxFrames * 11) / 16; }
+ size_t getAvgFrames() const { return (mReqFrames * 11) / 16; }
private:
+ const size_t mReqFrames; // as requested in constructor, unrounded
const size_t mMaxFrames; // always a power of 2
void * const mBuffer;
// mFront and mRear will never be separated by more than mMaxFrames.