MonoPipe.cpp revision 28ed2f93324988767b5658eba7c1fa781a275183
1010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten/* 2010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Copyright (C) 2012 The Android Open Source Project 3010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * 4010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * you may not use this file except in compliance with the License. 6010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * You may obtain a copy of the License at 7010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * 8010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * 10010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Unless required by applicable law or agreed to in writing, software 11010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * See the License for the specific language governing permissions and 14010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * limitations under the License. 15010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten */ 16010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 17010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#define LOG_TAG "MonoPipe" 18010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten//#define LOG_NDEBUG 0 19010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 20010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <cutils/atomic.h> 21010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <cutils/compiler.h> 22010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <utils/Log.h> 2328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten#include <utils/Trace.h> 24010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include "MonoPipe.h" 25010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include "roundup.h" 26010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 27010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastennamespace android { 28010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 29820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn KastenMonoPipe::MonoPipe(size_t reqFrames, NBAIO_Format format, bool writeCanBlock) : 30010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten NBAIO_Sink(format), 31820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten mReqFrames(reqFrames), 32820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten mMaxFrames(roundup(reqFrames)), 33010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mBuffer(malloc(mMaxFrames * Format_frameSize(format))), 34010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mFront(0), 35010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mRear(0), 3628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mWriteTsValid(false), 3728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // mWriteTs 3828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mSetpoint((reqFrames * 11) / 16), 39010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mWriteCanBlock(writeCanBlock) 40010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 41010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 42010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 43010662326b9c43c703725f933e95e0897f8a6bddGlenn KastenMonoPipe::~MonoPipe() 44010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 45010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten free(mBuffer); 46010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 47010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 48010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastenssize_t MonoPipe::availableToWrite() const 49010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 50010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY(!mNegotiated)) { 51010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return NEGOTIATE; 52010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 53820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten // uses mMaxFrames not mReqFrames, so allows "over-filling" the pipe beyond requested limit 54010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ssize_t ret = mMaxFrames - (mRear - android_atomic_acquire_load(&mFront)); 55010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT((0 <= ret) && (ret <= mMaxFrames)); 56010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return ret; 57010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 58010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 59010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastenssize_t MonoPipe::write(const void *buffer, size_t count) 60010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 61010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY(!mNegotiated)) { 62010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return NEGOTIATE; 63010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 64010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t totalFramesWritten = 0; 656d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten while (count > 0) { 66820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten // can't return a negative value, as we already checked for !mNegotiated 676d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten size_t avail = availableToWrite(); 686d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten size_t written = avail; 69010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_LIKELY(written > count)) { 70010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten written = count; 71010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 72010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t rear = mRear & (mMaxFrames - 1); 73010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t part1 = mMaxFrames - rear; 74010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (part1 > written) { 75010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten part1 = written; 76010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 77010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_LIKELY(part1 > 0)) { 78010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten memcpy((char *) mBuffer + (rear << mBitShift), buffer, part1 << mBitShift); 79010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY(rear + part1 == mMaxFrames)) { 80010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t part2 = written - part1; 81010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_LIKELY(part2 > 0)) { 82010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten memcpy(mBuffer, (char *) buffer + (part1 << mBitShift), part2 << mBitShift); 83010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 84010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 85010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten android_atomic_release_store(written + mRear, &mRear); 86010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten totalFramesWritten += written; 87010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 886d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten if (!mWriteCanBlock) { 89010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten break; 90010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 916d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten count -= written; 92010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten buffer = (char *) buffer + (written << mBitShift); 936d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten // Simulate blocking I/O by sleeping at different rates, depending on a throttle. 9428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // The throttle tries to keep the mean pipe depth near the setpoint, with a slight jitter. 95820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten uint32_t ns; 966d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten if (written > 0) { 97820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten size_t filled = (mMaxFrames - avail) + written; 98820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten // FIXME cache these values to avoid re-computation 9928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (filled <= mSetpoint / 2) { 100820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten // pipe is (nearly) empty, fill quickly 1016d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten ns = written * ( 500000000 / Format_sampleRate(mFormat)); 10228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else if (filled <= (mSetpoint * 3) / 4) { 10328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is below setpoint, fill at slightly faster rate 1046d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten ns = written * ( 750000000 / Format_sampleRate(mFormat)); 10528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else if (filled <= (mSetpoint * 5) / 4) { 10628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is at setpoint, fill at nominal rate 1076d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten ns = written * (1000000000 / Format_sampleRate(mFormat)); 10828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else if (filled <= (mSetpoint * 3) / 2) { 10928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is above setpoint, fill at slightly slower rate 11028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = written * (1150000000 / Format_sampleRate(mFormat)); 11128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else if (filled <= (mSetpoint * 7) / 4) { 11228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is overflowing, fill slowly 11328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = written * (1350000000 / Format_sampleRate(mFormat)); 114820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten } else { 11528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is severely overflowing 11628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = written * (1750000000 / Format_sampleRate(mFormat)); 1176d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten } 1186d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten } else { 11928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = count * (1350000000 / Format_sampleRate(mFormat)); 1206d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten } 1216d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten if (ns > 999999999) { 1226d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten ns = 999999999; 1236d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten } 12428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten struct timespec nowTs; 12528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten bool nowTsValid = !clock_gettime(CLOCK_MONOTONIC, &nowTs); 12628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // deduct the elapsed time since previous write() completed 12728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (nowTsValid && mWriteTsValid) { 12828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten time_t sec = nowTs.tv_sec - mWriteTs.tv_sec; 12928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten long nsec = nowTs.tv_nsec - mWriteTs.tv_nsec; 13028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (nsec < 0) { 13128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten --sec; 13228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten nsec += 1000000000; 13328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 13428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (sec == 0) { 13528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if ((long) ns > nsec) { 13628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns -= nsec; 13728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else { 13828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = 0; 13928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 14028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 14128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 14228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (ns > 0) { 14328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten const struct timespec req = {0, ns}; 14428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten nanosleep(&req, NULL); 14528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 14628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // record the time that this write() completed 14728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (nowTsValid) { 14828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mWriteTs = nowTs; 14928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if ((mWriteTs.tv_nsec += ns) >= 1000000000) { 15028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mWriteTs.tv_nsec -= 1000000000; 15128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ++mWriteTs.tv_sec; 15228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 15328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 15428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mWriteTsValid = nowTsValid; 155010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 156010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mFramesWritten += totalFramesWritten; 157010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return totalFramesWritten; 158010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 159010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 16028ed2f93324988767b5658eba7c1fa781a275183Glenn Kastenvoid MonoPipe::setAvgFrames(size_t setpoint) 16128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten{ 16228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mSetpoint = setpoint; 16328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten} 16428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten 165010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} // namespace android 166