1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <inttypes.h> 18 19#define LOG_TAG "MonoPipe" 20//#define LOG_NDEBUG 0 21 22#include <cutils/atomic.h> 23#include <cutils/compiler.h> 24#include <utils/Log.h> 25#include <utils/Trace.h> 26#include <media/AudioBufferProvider.h> 27#include <media/nbaio/MonoPipe.h> 28#include <audio_utils/roundup.h> 29 30 31namespace android { 32 33MonoPipe::MonoPipe(size_t reqFrames, const NBAIO_Format& format, bool writeCanBlock) : 34 NBAIO_Sink(format), 35 mReqFrames(reqFrames), 36 mMaxFrames(roundup(reqFrames)), 37 mBuffer(malloc(mMaxFrames * Format_frameSize(format))), 38 mFront(0), 39 mRear(0), 40 mWriteTsValid(false), 41 // mWriteTs 42 mSetpoint((reqFrames * 11) / 16), 43 mWriteCanBlock(writeCanBlock), 44 mIsShutdown(false), 45 // mTimestampShared 46 mTimestampMutator(&mTimestampShared), 47 mTimestampObserver(&mTimestampShared) 48{ 49} 50 51MonoPipe::~MonoPipe() 52{ 53 free(mBuffer); 54} 55 56ssize_t MonoPipe::availableToWrite() const 57{ 58 if (CC_UNLIKELY(!mNegotiated)) { 59 return NEGOTIATE; 60 } 61 // uses mMaxFrames not mReqFrames, so allows "over-filling" the pipe beyond requested limit 62 ssize_t ret = mMaxFrames - (mRear - android_atomic_acquire_load(&mFront)); 63 ALOG_ASSERT((0 <= ret) && (ret <= mMaxFrames)); 64 return ret; 65} 66 67ssize_t MonoPipe::write(const void *buffer, size_t count) 68{ 69 if (CC_UNLIKELY(!mNegotiated)) { 70 return NEGOTIATE; 71 } 72 size_t totalFramesWritten = 0; 73 while (count > 0) { 74 // can't return a negative value, as we already checked for !mNegotiated 75 size_t avail = availableToWrite(); 76 size_t written = avail; 77 if (CC_LIKELY(written > count)) { 78 written = count; 79 } 80 size_t rear = mRear & (mMaxFrames - 1); 81 size_t part1 = mMaxFrames - rear; 82 if (part1 > written) { 83 part1 = written; 84 } 85 if (CC_LIKELY(part1 > 0)) { 86 memcpy((char *) mBuffer + (rear * mFrameSize), buffer, part1 * mFrameSize); 87 if (CC_UNLIKELY(rear + part1 == mMaxFrames)) { 88 size_t part2 = written - part1; 89 if (CC_LIKELY(part2 > 0)) { 90 memcpy(mBuffer, (char *) buffer + (part1 * mFrameSize), part2 * mFrameSize); 91 } 92 } 93 android_atomic_release_store(written + mRear, &mRear); 94 totalFramesWritten += written; 95 } 96 if (!mWriteCanBlock || mIsShutdown) { 97 break; 98 } 99 count -= written; 100 buffer = (char *) buffer + (written * mFrameSize); 101 // Simulate blocking I/O by sleeping at different rates, depending on a throttle. 102 // The throttle tries to keep the mean pipe depth near the setpoint, with a slight jitter. 103 uint32_t ns; 104 if (written > 0) { 105 size_t filled = (mMaxFrames - avail) + written; 106 // FIXME cache these values to avoid re-computation 107 if (filled <= mSetpoint / 2) { 108 // pipe is (nearly) empty, fill quickly 109 ns = written * ( 500000000 / Format_sampleRate(mFormat)); 110 } else if (filled <= (mSetpoint * 3) / 4) { 111 // pipe is below setpoint, fill at slightly faster rate 112 ns = written * ( 750000000 / Format_sampleRate(mFormat)); 113 } else if (filled <= (mSetpoint * 5) / 4) { 114 // pipe is at setpoint, fill at nominal rate 115 ns = written * (1000000000 / Format_sampleRate(mFormat)); 116 } else if (filled <= (mSetpoint * 3) / 2) { 117 // pipe is above setpoint, fill at slightly slower rate 118 ns = written * (1150000000 / Format_sampleRate(mFormat)); 119 } else if (filled <= (mSetpoint * 7) / 4) { 120 // pipe is overflowing, fill slowly 121 ns = written * (1350000000 / Format_sampleRate(mFormat)); 122 } else { 123 // pipe is severely overflowing 124 ns = written * (1750000000 / Format_sampleRate(mFormat)); 125 } 126 } else { 127 ns = count * (1350000000 / Format_sampleRate(mFormat)); 128 } 129 if (ns > 999999999) { 130 ns = 999999999; 131 } 132 struct timespec nowTs; 133 bool nowTsValid = !clock_gettime(CLOCK_MONOTONIC, &nowTs); 134 // deduct the elapsed time since previous write() completed 135 if (nowTsValid && mWriteTsValid) { 136 time_t sec = nowTs.tv_sec - mWriteTs.tv_sec; 137 long nsec = nowTs.tv_nsec - mWriteTs.tv_nsec; 138 ALOGE_IF(sec < 0 || (sec == 0 && nsec < 0), 139 "clock_gettime(CLOCK_MONOTONIC) failed: was %ld.%09ld but now %ld.%09ld", 140 mWriteTs.tv_sec, mWriteTs.tv_nsec, nowTs.tv_sec, nowTs.tv_nsec); 141 if (nsec < 0) { 142 --sec; 143 nsec += 1000000000; 144 } 145 if (sec == 0) { 146 if ((long) ns > nsec) { 147 ns -= nsec; 148 } else { 149 ns = 0; 150 } 151 } 152 } 153 if (ns > 0) { 154 const struct timespec req = {0, static_cast<long>(ns)}; 155 nanosleep(&req, NULL); 156 } 157 // record the time that this write() completed 158 if (nowTsValid) { 159 mWriteTs = nowTs; 160 if ((mWriteTs.tv_nsec += ns) >= 1000000000) { 161 mWriteTs.tv_nsec -= 1000000000; 162 ++mWriteTs.tv_sec; 163 } 164 } 165 mWriteTsValid = nowTsValid; 166 } 167 mFramesWritten += totalFramesWritten; 168 return totalFramesWritten; 169} 170 171void MonoPipe::setAvgFrames(size_t setpoint) 172{ 173 mSetpoint = setpoint; 174} 175 176void MonoPipe::shutdown(bool newState) 177{ 178 mIsShutdown = newState; 179} 180 181bool MonoPipe::isShutdown() 182{ 183 return mIsShutdown; 184} 185 186status_t MonoPipe::getTimestamp(ExtendedTimestamp ×tamp) 187{ 188 ExtendedTimestamp ets; 189 if (mTimestampObserver.poll(ets)) { 190 timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = 191 ets.mPosition[ExtendedTimestamp::LOCATION_KERNEL]; 192 timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = 193 ets.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]; 194 return OK; 195 } 196 return INVALID_OPERATION; 197} 198 199} // namespace android 200