diff options
author | Glenn Kasten <gkasten@google.com> | 2012-06-01 11:04:43 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-06-01 11:04:43 -0700 |
commit | 0c22272f1c97fd4b7e106030a1fd5e6b50680b61 (patch) | |
tree | 0b27f53c60c0e20d3e06d0fa7eb1f8e04ff6697f | |
parent | dadc0ddbfe309086801b479ddc91c55eeb2a9cbb (diff) | |
parent | 820ba70df8ba595ae9055dfd34fdbfa32f70f14d (diff) | |
download | frameworks_av-0c22272f1c97fd4b7e106030a1fd5e6b50680b61.zip frameworks_av-0c22272f1c97fd4b7e106030a1fd5e6b50680b61.tar.gz frameworks_av-0c22272f1c97fd4b7e106030a1fd5e6b50680b61.tar.bz2 |
Merge "Pipe throttle based on requested frame count" into jb-dev
-rw-r--r-- | services/audioflinger/MonoPipe.cpp | 58 | ||||
-rw-r--r-- | services/audioflinger/MonoPipe.h | 7 |
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. |