summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorGlenn Kasten <gkasten@google.com>2012-06-01 11:04:43 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-06-01 11:04:43 -0700
commit0c22272f1c97fd4b7e106030a1fd5e6b50680b61 (patch)
tree0b27f53c60c0e20d3e06d0fa7eb1f8e04ff6697f /services
parentdadc0ddbfe309086801b479ddc91c55eeb2a9cbb (diff)
parent820ba70df8ba595ae9055dfd34fdbfa32f70f14d (diff)
downloadframeworks_av-0c22272f1c97fd4b7e106030a1fd5e6b50680b61.zip
frameworks_av-0c22272f1c97fd4b7e106030a1fd5e6b50680b61.tar.gz
frameworks_av-0c22272f1c97fd4b7e106030a1fd5e6b50680b61.tar.bz2
Merge "Pipe throttle based on requested frame count" into jb-dev
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.