Loading services/audioflinger/MonoPipe.cpp +20 −38 Original line number Diff line number Diff line Loading @@ -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), Loading @@ -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; Loading @@ -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)) { Loading Loading @@ -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; Loading services/audioflinger/MonoPipe.h +4 −3 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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. Loading Loading
services/audioflinger/MonoPipe.cpp +20 −38 Original line number Diff line number Diff line Loading @@ -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), Loading @@ -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; Loading @@ -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)) { Loading Loading @@ -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; Loading
services/audioflinger/MonoPipe.h +4 −3 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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. Loading