MonoPipe.cpp revision 2dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0
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 202c3b2da3049627264b7c6b449a1622f002210f03John Grossman#include <common_time/cc_helper.h> 21010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <cutils/atomic.h> 22010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <cutils/compiler.h> 232c3b2da3049627264b7c6b449a1622f002210f03John Grossman#include <utils/LinearTransform.h> 24010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <utils/Log.h> 2528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten#include <utils/Trace.h> 262dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <media/AudioBufferProvider.h> 272dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <media/nbaio/MonoPipe.h> 282dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <media/nbaio/roundup.h> 29010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 302c3b2da3049627264b7c6b449a1622f002210f03John Grossman 31010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastennamespace android { 32010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 33820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn KastenMonoPipe::MonoPipe(size_t reqFrames, NBAIO_Format format, bool writeCanBlock) : 34010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten NBAIO_Sink(format), 352c3b2da3049627264b7c6b449a1622f002210f03John Grossman mUpdateSeq(0), 36820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten mReqFrames(reqFrames), 37820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten mMaxFrames(roundup(reqFrames)), 38010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mBuffer(malloc(mMaxFrames * Format_frameSize(format))), 39010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mFront(0), 40010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mRear(0), 4128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mWriteTsValid(false), 4228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // mWriteTs 4328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mSetpoint((reqFrames * 11) / 16), 44010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mWriteCanBlock(writeCanBlock) 45010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 462c3b2da3049627264b7c6b449a1622f002210f03John Grossman CCHelper tmpHelper; 472c3b2da3049627264b7c6b449a1622f002210f03John Grossman status_t res; 482c3b2da3049627264b7c6b449a1622f002210f03John Grossman uint64_t N, D; 492c3b2da3049627264b7c6b449a1622f002210f03John Grossman 502c3b2da3049627264b7c6b449a1622f002210f03John Grossman mNextRdPTS = AudioBufferProvider::kInvalidPTS; 512c3b2da3049627264b7c6b449a1622f002210f03John Grossman 522c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_zero = 0; 532c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.b_zero = 0; 542c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_to_b_numer = 0; 552c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_to_b_denom = 0; 562c3b2da3049627264b7c6b449a1622f002210f03John Grossman 572c3b2da3049627264b7c6b449a1622f002210f03John Grossman D = Format_sampleRate(format); 582c3b2da3049627264b7c6b449a1622f002210f03John Grossman if (OK != (res = tmpHelper.getLocalFreq(&N))) { 592c3b2da3049627264b7c6b449a1622f002210f03John Grossman ALOGE("Failed to fetch local time frequency when constructing a" 602c3b2da3049627264b7c6b449a1622f002210f03John Grossman " MonoPipe (res = %d). getNextWriteTimestamp calls will be" 612c3b2da3049627264b7c6b449a1622f002210f03John Grossman " non-functional", res); 622c3b2da3049627264b7c6b449a1622f002210f03John Grossman return; 632c3b2da3049627264b7c6b449a1622f002210f03John Grossman } 642c3b2da3049627264b7c6b449a1622f002210f03John Grossman 652c3b2da3049627264b7c6b449a1622f002210f03John Grossman LinearTransform::reduce(&N, &D); 662c3b2da3049627264b7c6b449a1622f002210f03John Grossman static const uint64_t kSignedHiBitsMask = ~(0x7FFFFFFFull); 672c3b2da3049627264b7c6b449a1622f002210f03John Grossman static const uint64_t kUnsignedHiBitsMask = ~(0xFFFFFFFFull); 682c3b2da3049627264b7c6b449a1622f002210f03John Grossman if ((N & kSignedHiBitsMask) || (D & kUnsignedHiBitsMask)) { 692c3b2da3049627264b7c6b449a1622f002210f03John Grossman ALOGE("Cannot reduce sample rate to local clock frequency ratio to fit" 702c3b2da3049627264b7c6b449a1622f002210f03John Grossman " in a 32/32 bit rational. (max reduction is 0x%016llx/0x%016llx" 712c3b2da3049627264b7c6b449a1622f002210f03John Grossman "). getNextWriteTimestamp calls will be non-functional", N, D); 722c3b2da3049627264b7c6b449a1622f002210f03John Grossman return; 732c3b2da3049627264b7c6b449a1622f002210f03John Grossman } 742c3b2da3049627264b7c6b449a1622f002210f03John Grossman 752c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_to_b_numer = static_cast<int32_t>(N); 762c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_to_b_denom = static_cast<uint32_t>(D); 77010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 78010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 79010662326b9c43c703725f933e95e0897f8a6bddGlenn KastenMonoPipe::~MonoPipe() 80010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 81010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten free(mBuffer); 82010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 83010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 84010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastenssize_t MonoPipe::availableToWrite() const 85010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 86010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY(!mNegotiated)) { 87010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return NEGOTIATE; 88010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 89820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten // uses mMaxFrames not mReqFrames, so allows "over-filling" the pipe beyond requested limit 90010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ssize_t ret = mMaxFrames - (mRear - android_atomic_acquire_load(&mFront)); 91010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT((0 <= ret) && (ret <= mMaxFrames)); 92010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return ret; 93010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 94010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 95010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastenssize_t MonoPipe::write(const void *buffer, size_t count) 96010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 97010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY(!mNegotiated)) { 98010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return NEGOTIATE; 99010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 100010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t totalFramesWritten = 0; 1016d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten while (count > 0) { 102820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten // can't return a negative value, as we already checked for !mNegotiated 1036d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten size_t avail = availableToWrite(); 1046d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten size_t written = avail; 105010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_LIKELY(written > count)) { 106010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten written = count; 107010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 108010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t rear = mRear & (mMaxFrames - 1); 109010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t part1 = mMaxFrames - rear; 110010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (part1 > written) { 111010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten part1 = written; 112010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 113010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_LIKELY(part1 > 0)) { 114010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten memcpy((char *) mBuffer + (rear << mBitShift), buffer, part1 << mBitShift); 115010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY(rear + part1 == mMaxFrames)) { 116010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t part2 = written - part1; 117010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_LIKELY(part2 > 0)) { 118010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten memcpy(mBuffer, (char *) buffer + (part1 << mBitShift), part2 << mBitShift); 119010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 120010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 121010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten android_atomic_release_store(written + mRear, &mRear); 122010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten totalFramesWritten += written; 123010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 1246d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten if (!mWriteCanBlock) { 125010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten break; 126010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 1276d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten count -= written; 128010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten buffer = (char *) buffer + (written << mBitShift); 1296d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten // Simulate blocking I/O by sleeping at different rates, depending on a throttle. 13028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // The throttle tries to keep the mean pipe depth near the setpoint, with a slight jitter. 131820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten uint32_t ns; 1326d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten if (written > 0) { 133820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten size_t filled = (mMaxFrames - avail) + written; 134820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten // FIXME cache these values to avoid re-computation 13528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (filled <= mSetpoint / 2) { 136820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten // pipe is (nearly) empty, fill quickly 1376d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten ns = written * ( 500000000 / Format_sampleRate(mFormat)); 13828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else if (filled <= (mSetpoint * 3) / 4) { 13928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is below setpoint, fill at slightly faster rate 1406d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten ns = written * ( 750000000 / Format_sampleRate(mFormat)); 14128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else if (filled <= (mSetpoint * 5) / 4) { 14228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is at setpoint, fill at nominal rate 1436d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten ns = written * (1000000000 / Format_sampleRate(mFormat)); 14428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else if (filled <= (mSetpoint * 3) / 2) { 14528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is above setpoint, fill at slightly slower rate 14628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = written * (1150000000 / Format_sampleRate(mFormat)); 14728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else if (filled <= (mSetpoint * 7) / 4) { 14828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is overflowing, fill slowly 14928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = written * (1350000000 / Format_sampleRate(mFormat)); 150820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten } else { 15128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is severely overflowing 15228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = written * (1750000000 / Format_sampleRate(mFormat)); 1536d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten } 1546d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten } else { 15528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = count * (1350000000 / Format_sampleRate(mFormat)); 1566d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten } 1576d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten if (ns > 999999999) { 1586d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten ns = 999999999; 1596d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten } 16028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten struct timespec nowTs; 16128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten bool nowTsValid = !clock_gettime(CLOCK_MONOTONIC, &nowTs); 16228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // deduct the elapsed time since previous write() completed 16328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (nowTsValid && mWriteTsValid) { 16428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten time_t sec = nowTs.tv_sec - mWriteTs.tv_sec; 16528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten long nsec = nowTs.tv_nsec - mWriteTs.tv_nsec; 16628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (nsec < 0) { 16728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten --sec; 16828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten nsec += 1000000000; 16928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 17028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (sec == 0) { 17128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if ((long) ns > nsec) { 17228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns -= nsec; 17328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else { 17428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = 0; 17528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 17628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 17728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 17828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (ns > 0) { 17928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten const struct timespec req = {0, ns}; 18028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten nanosleep(&req, NULL); 18128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 18228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // record the time that this write() completed 18328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (nowTsValid) { 18428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mWriteTs = nowTs; 18528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if ((mWriteTs.tv_nsec += ns) >= 1000000000) { 18628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mWriteTs.tv_nsec -= 1000000000; 18728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ++mWriteTs.tv_sec; 18828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 18928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 19028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mWriteTsValid = nowTsValid; 191010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 192010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mFramesWritten += totalFramesWritten; 193010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return totalFramesWritten; 194010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 195010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 19628ed2f93324988767b5658eba7c1fa781a275183Glenn Kastenvoid MonoPipe::setAvgFrames(size_t setpoint) 19728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten{ 19828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mSetpoint = setpoint; 19928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten} 20028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten 2012c3b2da3049627264b7c6b449a1622f002210f03John Grossmanstatus_t MonoPipe::getNextWriteTimestamp(int64_t *timestamp) 2022c3b2da3049627264b7c6b449a1622f002210f03John Grossman{ 2032c3b2da3049627264b7c6b449a1622f002210f03John Grossman int32_t front; 2042c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2052c3b2da3049627264b7c6b449a1622f002210f03John Grossman ALOG_ASSERT(NULL != timestamp); 2062c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2072c3b2da3049627264b7c6b449a1622f002210f03John Grossman if (0 == mSamplesToLocalTime.a_to_b_denom) 2082c3b2da3049627264b7c6b449a1622f002210f03John Grossman return UNKNOWN_ERROR; 2092c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2102c3b2da3049627264b7c6b449a1622f002210f03John Grossman observeFrontAndNRPTS(&front, timestamp); 2112c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2122c3b2da3049627264b7c6b449a1622f002210f03John Grossman if (AudioBufferProvider::kInvalidPTS != *timestamp) { 2132c3b2da3049627264b7c6b449a1622f002210f03John Grossman // If we have a valid read-pointer and next read timestamp pair, then 2142c3b2da3049627264b7c6b449a1622f002210f03John Grossman // use the current value of the write pointer to figure out how many 2152c3b2da3049627264b7c6b449a1622f002210f03John Grossman // frames are in the buffer, and offset the timestamp by that amt. Then 2162c3b2da3049627264b7c6b449a1622f002210f03John Grossman // next time we write to the MonoPipe, the data will hit the speakers at 2172c3b2da3049627264b7c6b449a1622f002210f03John Grossman // the next read timestamp plus the current amount of data in the 2182c3b2da3049627264b7c6b449a1622f002210f03John Grossman // MonoPipe. 2192c3b2da3049627264b7c6b449a1622f002210f03John Grossman size_t pendingFrames = (mRear - front) & (mMaxFrames - 1); 2202c3b2da3049627264b7c6b449a1622f002210f03John Grossman *timestamp = offsetTimestampByAudioFrames(*timestamp, pendingFrames); 2212c3b2da3049627264b7c6b449a1622f002210f03John Grossman } 2222c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2232c3b2da3049627264b7c6b449a1622f002210f03John Grossman return OK; 2242c3b2da3049627264b7c6b449a1622f002210f03John Grossman} 2252c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2262c3b2da3049627264b7c6b449a1622f002210f03John Grossmanvoid MonoPipe::updateFrontAndNRPTS(int32_t newFront, int64_t newNextRdPTS) 2272c3b2da3049627264b7c6b449a1622f002210f03John Grossman{ 2282c3b2da3049627264b7c6b449a1622f002210f03John Grossman // Set the MSB of the update sequence number to indicate that there is a 2292c3b2da3049627264b7c6b449a1622f002210f03John Grossman // multi-variable update in progress. Use an atomic store with an "acquire" 2302c3b2da3049627264b7c6b449a1622f002210f03John Grossman // barrier to make sure that the next operations cannot be re-ordered and 2312c3b2da3049627264b7c6b449a1622f002210f03John Grossman // take place before the change to mUpdateSeq is commited.. 2322c3b2da3049627264b7c6b449a1622f002210f03John Grossman int32_t tmp = mUpdateSeq | 0x80000000; 2332c3b2da3049627264b7c6b449a1622f002210f03John Grossman android_atomic_acquire_store(tmp, &mUpdateSeq); 2342c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2352c3b2da3049627264b7c6b449a1622f002210f03John Grossman // Update mFront and mNextRdPTS 2362c3b2da3049627264b7c6b449a1622f002210f03John Grossman mFront = newFront; 2372c3b2da3049627264b7c6b449a1622f002210f03John Grossman mNextRdPTS = newNextRdPTS; 2382c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2392c3b2da3049627264b7c6b449a1622f002210f03John Grossman // We are finished with the update. Compute the next sequnce number (which 2402c3b2da3049627264b7c6b449a1622f002210f03John Grossman // should be the old sequence number, plus one, and with the MSB cleared) 2412c3b2da3049627264b7c6b449a1622f002210f03John Grossman // and then store it in mUpdateSeq using an atomic store with a "release" 2422c3b2da3049627264b7c6b449a1622f002210f03John Grossman // barrier so our update operations cannot be re-ordered past the update of 2432c3b2da3049627264b7c6b449a1622f002210f03John Grossman // the sequence number. 2442c3b2da3049627264b7c6b449a1622f002210f03John Grossman tmp = (tmp + 1) & 0x7FFFFFFF; 2452c3b2da3049627264b7c6b449a1622f002210f03John Grossman android_atomic_release_store(tmp, &mUpdateSeq); 2462c3b2da3049627264b7c6b449a1622f002210f03John Grossman} 2472c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2482c3b2da3049627264b7c6b449a1622f002210f03John Grossmanvoid MonoPipe::observeFrontAndNRPTS(int32_t *outFront, int64_t *outNextRdPTS) 2492c3b2da3049627264b7c6b449a1622f002210f03John Grossman{ 2502c3b2da3049627264b7c6b449a1622f002210f03John Grossman // Perform an atomic observation of mFront and mNextRdPTS. Basically, 2512c3b2da3049627264b7c6b449a1622f002210f03John Grossman // atomically observe the sequence number, then observer the variables, then 2522c3b2da3049627264b7c6b449a1622f002210f03John Grossman // atomically observe the sequence number again. If the two observations of 2532c3b2da3049627264b7c6b449a1622f002210f03John Grossman // the sequence number match, and the update-in-progress bit was not set, 2542c3b2da3049627264b7c6b449a1622f002210f03John Grossman // then we know we have a successful atomic observation. Otherwise, we loop 2552c3b2da3049627264b7c6b449a1622f002210f03John Grossman // around and try again. 2562c3b2da3049627264b7c6b449a1622f002210f03John Grossman // 2572c3b2da3049627264b7c6b449a1622f002210f03John Grossman // Note, it is very important that the observer be a lower priority thread 2582c3b2da3049627264b7c6b449a1622f002210f03John Grossman // than the updater. If the updater is lower than the observer, or they are 2592c3b2da3049627264b7c6b449a1622f002210f03John Grossman // the same priority and running with SCHED_FIFO (implying that quantum 2602c3b2da3049627264b7c6b449a1622f002210f03John Grossman // based premption is disabled) then we run the risk of deadlock. 2612c3b2da3049627264b7c6b449a1622f002210f03John Grossman int32_t seqOne, seqTwo; 2622c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2632c3b2da3049627264b7c6b449a1622f002210f03John Grossman do { 2642c3b2da3049627264b7c6b449a1622f002210f03John Grossman seqOne = android_atomic_acquire_load(&mUpdateSeq); 2652c3b2da3049627264b7c6b449a1622f002210f03John Grossman *outFront = mFront; 2662c3b2da3049627264b7c6b449a1622f002210f03John Grossman *outNextRdPTS = mNextRdPTS; 2672c3b2da3049627264b7c6b449a1622f002210f03John Grossman seqTwo = android_atomic_release_load(&mUpdateSeq); 2682c3b2da3049627264b7c6b449a1622f002210f03John Grossman } while ((seqOne != seqTwo) || (seqOne & 0x80000000)); 2692c3b2da3049627264b7c6b449a1622f002210f03John Grossman} 2702c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2712c3b2da3049627264b7c6b449a1622f002210f03John Grossmanint64_t MonoPipe::offsetTimestampByAudioFrames(int64_t ts, size_t audFrames) 2722c3b2da3049627264b7c6b449a1622f002210f03John Grossman{ 2732c3b2da3049627264b7c6b449a1622f002210f03John Grossman if (0 == mSamplesToLocalTime.a_to_b_denom) 2742c3b2da3049627264b7c6b449a1622f002210f03John Grossman return AudioBufferProvider::kInvalidPTS; 2752c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2762c3b2da3049627264b7c6b449a1622f002210f03John Grossman if (ts == AudioBufferProvider::kInvalidPTS) 2772c3b2da3049627264b7c6b449a1622f002210f03John Grossman return AudioBufferProvider::kInvalidPTS; 2782c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2792c3b2da3049627264b7c6b449a1622f002210f03John Grossman int64_t frame_lt_duration; 2802c3b2da3049627264b7c6b449a1622f002210f03John Grossman if (!mSamplesToLocalTime.doForwardTransform(audFrames, 2812c3b2da3049627264b7c6b449a1622f002210f03John Grossman &frame_lt_duration)) { 2822c3b2da3049627264b7c6b449a1622f002210f03John Grossman // This should never fail, but if there is a bug which is causing it 2832c3b2da3049627264b7c6b449a1622f002210f03John Grossman // to fail, this message would probably end up flooding the logs 2842c3b2da3049627264b7c6b449a1622f002210f03John Grossman // because the conversion would probably fail forever. Log the 2852c3b2da3049627264b7c6b449a1622f002210f03John Grossman // error, but then zero out the ratio in the linear transform so 2862c3b2da3049627264b7c6b449a1622f002210f03John Grossman // that we don't try to do any conversions from now on. This 2872c3b2da3049627264b7c6b449a1622f002210f03John Grossman // MonoPipe's getNextWriteTimestamp is now broken for good. 2882c3b2da3049627264b7c6b449a1622f002210f03John Grossman ALOGE("Overflow when attempting to convert %d audio frames to" 2892c3b2da3049627264b7c6b449a1622f002210f03John Grossman " duration in local time. getNextWriteTimestamp will fail from" 2902c3b2da3049627264b7c6b449a1622f002210f03John Grossman " now on.", audFrames); 2912c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_to_b_numer = 0; 2922c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_to_b_denom = 0; 2932c3b2da3049627264b7c6b449a1622f002210f03John Grossman return AudioBufferProvider::kInvalidPTS; 2942c3b2da3049627264b7c6b449a1622f002210f03John Grossman } 2952c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2962c3b2da3049627264b7c6b449a1622f002210f03John Grossman return ts + frame_lt_duration; 2972c3b2da3049627264b7c6b449a1622f002210f03John Grossman} 2982c3b2da3049627264b7c6b449a1622f002210f03John Grossman 299010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} // namespace android 300