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 170f6a0435713c435e1aaeacbfd9ce7abb6a5b19a9Mark Salyzyn#include <inttypes.h> 180f6a0435713c435e1aaeacbfd9ce7abb6a5b19a9Mark Salyzyn 19010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#define LOG_TAG "MonoPipe" 20010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten//#define LOG_NDEBUG 0 21010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 222c3b2da3049627264b7c6b449a1622f002210f03John Grossman#include <common_time/cc_helper.h> 23010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <cutils/atomic.h> 24010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <cutils/compiler.h> 252c3b2da3049627264b7c6b449a1622f002210f03John Grossman#include <utils/LinearTransform.h> 26010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <utils/Log.h> 2728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten#include <utils/Trace.h> 282dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <media/AudioBufferProvider.h> 292dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <media/nbaio/MonoPipe.h> 302dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <media/nbaio/roundup.h> 31010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 322c3b2da3049627264b7c6b449a1622f002210f03John Grossman 33010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastennamespace android { 34010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 353f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kastenstatic uint64_t cacheN; // output of CCHelper::getLocalFreq() 363f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kastenstatic bool cacheValid; // whether cacheN is valid 373f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kastenstatic pthread_once_t cacheOnceControl = PTHREAD_ONCE_INIT; 383f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten 393f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kastenstatic void cacheOnceInit() 403f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten{ 413f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten CCHelper tmpHelper; 423f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten status_t res; 433f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten if (OK != (res = tmpHelper.getLocalFreq(&cacheN))) { 443f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten ALOGE("Failed to fetch local time frequency when constructing a" 453f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten " MonoPipe (res = %d). getNextWriteTimestamp calls will be" 463f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten " non-functional", res); 473f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten return; 483f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten } 493f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten cacheValid = true; 503f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten} 513f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten 5272e54af9fcdc4754914fe2bf8de699523538b315Glenn KastenMonoPipe::MonoPipe(size_t reqFrames, const NBAIO_Format& format, bool writeCanBlock) : 53010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten NBAIO_Sink(format), 542c3b2da3049627264b7c6b449a1622f002210f03John Grossman mUpdateSeq(0), 55820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten mReqFrames(reqFrames), 56820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten mMaxFrames(roundup(reqFrames)), 57010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mBuffer(malloc(mMaxFrames * Format_frameSize(format))), 58010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mFront(0), 59010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mRear(0), 6028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mWriteTsValid(false), 6128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // mWriteTs 6228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mSetpoint((reqFrames * 11) / 16), 63003d9f71937070791418bf7efc1f7fe1e4c6b821Glenn Kasten mWriteCanBlock(writeCanBlock), 64a07a1c2c91dc7ee6ded319262499f20cd01edcf7Glenn Kasten mIsShutdown(false), 65a07a1c2c91dc7ee6ded319262499f20cd01edcf7Glenn Kasten // mTimestampShared 66a07a1c2c91dc7ee6ded319262499f20cd01edcf7Glenn Kasten mTimestampMutator(&mTimestampShared), 67a07a1c2c91dc7ee6ded319262499f20cd01edcf7Glenn Kasten mTimestampObserver(&mTimestampShared) 68010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 692c3b2da3049627264b7c6b449a1622f002210f03John Grossman uint64_t N, D; 702c3b2da3049627264b7c6b449a1622f002210f03John Grossman 712c3b2da3049627264b7c6b449a1622f002210f03John Grossman mNextRdPTS = AudioBufferProvider::kInvalidPTS; 722c3b2da3049627264b7c6b449a1622f002210f03John Grossman 732c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_zero = 0; 742c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.b_zero = 0; 752c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_to_b_numer = 0; 762c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_to_b_denom = 0; 772c3b2da3049627264b7c6b449a1622f002210f03John Grossman 782c3b2da3049627264b7c6b449a1622f002210f03John Grossman D = Format_sampleRate(format); 793f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten 803f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten (void) pthread_once(&cacheOnceControl, cacheOnceInit); 813f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten if (!cacheValid) { 823f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten // log has already been done 832c3b2da3049627264b7c6b449a1622f002210f03John Grossman return; 842c3b2da3049627264b7c6b449a1622f002210f03John Grossman } 853f35eb55f0e2bc5a4dda7f58ed52654403a87efaGlenn Kasten N = cacheN; 862c3b2da3049627264b7c6b449a1622f002210f03John Grossman 872c3b2da3049627264b7c6b449a1622f002210f03John Grossman LinearTransform::reduce(&N, &D); 882c3b2da3049627264b7c6b449a1622f002210f03John Grossman static const uint64_t kSignedHiBitsMask = ~(0x7FFFFFFFull); 892c3b2da3049627264b7c6b449a1622f002210f03John Grossman static const uint64_t kUnsignedHiBitsMask = ~(0xFFFFFFFFull); 902c3b2da3049627264b7c6b449a1622f002210f03John Grossman if ((N & kSignedHiBitsMask) || (D & kUnsignedHiBitsMask)) { 912c3b2da3049627264b7c6b449a1622f002210f03John Grossman ALOGE("Cannot reduce sample rate to local clock frequency ratio to fit" 920f6a0435713c435e1aaeacbfd9ce7abb6a5b19a9Mark Salyzyn " in a 32/32 bit rational. (max reduction is 0x%016" PRIx64 "/0x%016" PRIx64 932c3b2da3049627264b7c6b449a1622f002210f03John Grossman "). getNextWriteTimestamp calls will be non-functional", N, D); 942c3b2da3049627264b7c6b449a1622f002210f03John Grossman return; 952c3b2da3049627264b7c6b449a1622f002210f03John Grossman } 962c3b2da3049627264b7c6b449a1622f002210f03John Grossman 972c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_to_b_numer = static_cast<int32_t>(N); 982c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_to_b_denom = static_cast<uint32_t>(D); 99010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 100010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 101010662326b9c43c703725f933e95e0897f8a6bddGlenn KastenMonoPipe::~MonoPipe() 102010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 103010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten free(mBuffer); 104010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 105010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 106010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastenssize_t MonoPipe::availableToWrite() const 107010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 108010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY(!mNegotiated)) { 109010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return NEGOTIATE; 110010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 111820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten // uses mMaxFrames not mReqFrames, so allows "over-filling" the pipe beyond requested limit 112010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ssize_t ret = mMaxFrames - (mRear - android_atomic_acquire_load(&mFront)); 113010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT((0 <= ret) && (ret <= mMaxFrames)); 114010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return ret; 115010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 116010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 117010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastenssize_t MonoPipe::write(const void *buffer, size_t count) 118010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 119010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY(!mNegotiated)) { 120010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return NEGOTIATE; 121010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 122010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t totalFramesWritten = 0; 1236d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten while (count > 0) { 124820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten // can't return a negative value, as we already checked for !mNegotiated 1256d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten size_t avail = availableToWrite(); 1266d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten size_t written = avail; 127010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_LIKELY(written > count)) { 128010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten written = count; 129010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 130010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t rear = mRear & (mMaxFrames - 1); 131010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t part1 = mMaxFrames - rear; 132010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (part1 > written) { 133010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten part1 = written; 134010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 135010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_LIKELY(part1 > 0)) { 1364d693d6b8cc1283f92f5301daf19a07abc772a2bGlenn Kasten memcpy((char *) mBuffer + (rear * mFrameSize), buffer, part1 * mFrameSize); 137010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY(rear + part1 == mMaxFrames)) { 138010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t part2 = written - part1; 139010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_LIKELY(part2 > 0)) { 1404d693d6b8cc1283f92f5301daf19a07abc772a2bGlenn Kasten memcpy(mBuffer, (char *) buffer + (part1 * mFrameSize), part2 * mFrameSize); 141010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 142010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 143010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten android_atomic_release_store(written + mRear, &mRear); 144010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten totalFramesWritten += written; 145010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 146003d9f71937070791418bf7efc1f7fe1e4c6b821Glenn Kasten if (!mWriteCanBlock || mIsShutdown) { 147010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten break; 148010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 1496d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten count -= written; 1504d693d6b8cc1283f92f5301daf19a07abc772a2bGlenn Kasten buffer = (char *) buffer + (written * mFrameSize); 1516d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten // Simulate blocking I/O by sleeping at different rates, depending on a throttle. 15228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // The throttle tries to keep the mean pipe depth near the setpoint, with a slight jitter. 153820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten uint32_t ns; 1546d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten if (written > 0) { 155820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten size_t filled = (mMaxFrames - avail) + written; 156820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten // FIXME cache these values to avoid re-computation 15728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (filled <= mSetpoint / 2) { 158820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten // pipe is (nearly) empty, fill quickly 1596d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten ns = written * ( 500000000 / Format_sampleRate(mFormat)); 16028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else if (filled <= (mSetpoint * 3) / 4) { 16128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is below setpoint, fill at slightly faster rate 1626d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten ns = written * ( 750000000 / Format_sampleRate(mFormat)); 16328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else if (filled <= (mSetpoint * 5) / 4) { 16428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is at setpoint, fill at nominal rate 1656d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten ns = written * (1000000000 / Format_sampleRate(mFormat)); 16628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else if (filled <= (mSetpoint * 3) / 2) { 16728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is above setpoint, fill at slightly slower rate 16828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = written * (1150000000 / Format_sampleRate(mFormat)); 16928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else if (filled <= (mSetpoint * 7) / 4) { 17028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is overflowing, fill slowly 17128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = written * (1350000000 / Format_sampleRate(mFormat)); 172820ba70df8ba595ae9055dfd34fdbfa32f70f14dGlenn Kasten } else { 17328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // pipe is severely overflowing 17428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = written * (1750000000 / Format_sampleRate(mFormat)); 1756d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten } 1766d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten } else { 17728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = count * (1350000000 / Format_sampleRate(mFormat)); 1786d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten } 1796d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten if (ns > 999999999) { 1806d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten ns = 999999999; 1816d8aabe8a3be1ac0789d00b82c3ca8b81381f5abGlenn Kasten } 18228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten struct timespec nowTs; 18328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten bool nowTsValid = !clock_gettime(CLOCK_MONOTONIC, &nowTs); 18428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // deduct the elapsed time since previous write() completed 18528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (nowTsValid && mWriteTsValid) { 18628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten time_t sec = nowTs.tv_sec - mWriteTs.tv_sec; 18728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten long nsec = nowTs.tv_nsec - mWriteTs.tv_nsec; 18880b3273cea8660fe8a5868d024d2788a1e083ffcGlenn Kasten ALOGE_IF(sec < 0 || (sec == 0 && nsec < 0), 18980b3273cea8660fe8a5868d024d2788a1e083ffcGlenn Kasten "clock_gettime(CLOCK_MONOTONIC) failed: was %ld.%09ld but now %ld.%09ld", 19080b3273cea8660fe8a5868d024d2788a1e083ffcGlenn Kasten mWriteTs.tv_sec, mWriteTs.tv_nsec, nowTs.tv_sec, nowTs.tv_nsec); 19128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (nsec < 0) { 19228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten --sec; 19328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten nsec += 1000000000; 19428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 19528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (sec == 0) { 19628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if ((long) ns > nsec) { 19728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns -= nsec; 19828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } else { 19928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ns = 0; 20028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 20128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 20228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 20328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (ns > 0) { 2043b546caeb0a576c4d7d7f1e8d2fdfed2bb8bdeedsynergydev const struct timespec req = {0, static_cast<long>(ns)}; 20528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten nanosleep(&req, NULL); 20628ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 20728ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten // record the time that this write() completed 20828ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if (nowTsValid) { 20928ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mWriteTs = nowTs; 21028ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten if ((mWriteTs.tv_nsec += ns) >= 1000000000) { 21128ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mWriteTs.tv_nsec -= 1000000000; 21228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten ++mWriteTs.tv_sec; 21328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 21428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten } 21528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mWriteTsValid = nowTsValid; 216010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 217010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mFramesWritten += totalFramesWritten; 218010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return totalFramesWritten; 219010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 220010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 22128ed2f93324988767b5658eba7c1fa781a275183Glenn Kastenvoid MonoPipe::setAvgFrames(size_t setpoint) 22228ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten{ 22328ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten mSetpoint = setpoint; 22428ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten} 22528ed2f93324988767b5658eba7c1fa781a275183Glenn Kasten 2262c3b2da3049627264b7c6b449a1622f002210f03John Grossmanstatus_t MonoPipe::getNextWriteTimestamp(int64_t *timestamp) 2272c3b2da3049627264b7c6b449a1622f002210f03John Grossman{ 2282c3b2da3049627264b7c6b449a1622f002210f03John Grossman int32_t front; 2292c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2302c3b2da3049627264b7c6b449a1622f002210f03John Grossman ALOG_ASSERT(NULL != timestamp); 2312c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2322c3b2da3049627264b7c6b449a1622f002210f03John Grossman if (0 == mSamplesToLocalTime.a_to_b_denom) 2332c3b2da3049627264b7c6b449a1622f002210f03John Grossman return UNKNOWN_ERROR; 2342c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2352c3b2da3049627264b7c6b449a1622f002210f03John Grossman observeFrontAndNRPTS(&front, timestamp); 2362c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2372c3b2da3049627264b7c6b449a1622f002210f03John Grossman if (AudioBufferProvider::kInvalidPTS != *timestamp) { 2382c3b2da3049627264b7c6b449a1622f002210f03John Grossman // If we have a valid read-pointer and next read timestamp pair, then 2392c3b2da3049627264b7c6b449a1622f002210f03John Grossman // use the current value of the write pointer to figure out how many 2402c3b2da3049627264b7c6b449a1622f002210f03John Grossman // frames are in the buffer, and offset the timestamp by that amt. Then 2412c3b2da3049627264b7c6b449a1622f002210f03John Grossman // next time we write to the MonoPipe, the data will hit the speakers at 2422c3b2da3049627264b7c6b449a1622f002210f03John Grossman // the next read timestamp plus the current amount of data in the 2432c3b2da3049627264b7c6b449a1622f002210f03John Grossman // MonoPipe. 2442c3b2da3049627264b7c6b449a1622f002210f03John Grossman size_t pendingFrames = (mRear - front) & (mMaxFrames - 1); 2452c3b2da3049627264b7c6b449a1622f002210f03John Grossman *timestamp = offsetTimestampByAudioFrames(*timestamp, pendingFrames); 2462c3b2da3049627264b7c6b449a1622f002210f03John Grossman } 2472c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2482c3b2da3049627264b7c6b449a1622f002210f03John Grossman return OK; 2492c3b2da3049627264b7c6b449a1622f002210f03John Grossman} 2502c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2512c3b2da3049627264b7c6b449a1622f002210f03John Grossmanvoid MonoPipe::updateFrontAndNRPTS(int32_t newFront, int64_t newNextRdPTS) 2522c3b2da3049627264b7c6b449a1622f002210f03John Grossman{ 2532c3b2da3049627264b7c6b449a1622f002210f03John Grossman // Set the MSB of the update sequence number to indicate that there is a 2542c3b2da3049627264b7c6b449a1622f002210f03John Grossman // multi-variable update in progress. Use an atomic store with an "acquire" 2552c3b2da3049627264b7c6b449a1622f002210f03John Grossman // barrier to make sure that the next operations cannot be re-ordered and 2562c3b2da3049627264b7c6b449a1622f002210f03John Grossman // take place before the change to mUpdateSeq is commited.. 2572c3b2da3049627264b7c6b449a1622f002210f03John Grossman int32_t tmp = mUpdateSeq | 0x80000000; 2582c3b2da3049627264b7c6b449a1622f002210f03John Grossman android_atomic_acquire_store(tmp, &mUpdateSeq); 2592c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2602c3b2da3049627264b7c6b449a1622f002210f03John Grossman // Update mFront and mNextRdPTS 2612c3b2da3049627264b7c6b449a1622f002210f03John Grossman mFront = newFront; 2622c3b2da3049627264b7c6b449a1622f002210f03John Grossman mNextRdPTS = newNextRdPTS; 2632c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2642c3b2da3049627264b7c6b449a1622f002210f03John Grossman // We are finished with the update. Compute the next sequnce number (which 2652c3b2da3049627264b7c6b449a1622f002210f03John Grossman // should be the old sequence number, plus one, and with the MSB cleared) 2662c3b2da3049627264b7c6b449a1622f002210f03John Grossman // and then store it in mUpdateSeq using an atomic store with a "release" 2672c3b2da3049627264b7c6b449a1622f002210f03John Grossman // barrier so our update operations cannot be re-ordered past the update of 2682c3b2da3049627264b7c6b449a1622f002210f03John Grossman // the sequence number. 2692c3b2da3049627264b7c6b449a1622f002210f03John Grossman tmp = (tmp + 1) & 0x7FFFFFFF; 2702c3b2da3049627264b7c6b449a1622f002210f03John Grossman android_atomic_release_store(tmp, &mUpdateSeq); 2712c3b2da3049627264b7c6b449a1622f002210f03John Grossman} 2722c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2732c3b2da3049627264b7c6b449a1622f002210f03John Grossmanvoid MonoPipe::observeFrontAndNRPTS(int32_t *outFront, int64_t *outNextRdPTS) 2742c3b2da3049627264b7c6b449a1622f002210f03John Grossman{ 2752c3b2da3049627264b7c6b449a1622f002210f03John Grossman // Perform an atomic observation of mFront and mNextRdPTS. Basically, 2762c3b2da3049627264b7c6b449a1622f002210f03John Grossman // atomically observe the sequence number, then observer the variables, then 2772c3b2da3049627264b7c6b449a1622f002210f03John Grossman // atomically observe the sequence number again. If the two observations of 2782c3b2da3049627264b7c6b449a1622f002210f03John Grossman // the sequence number match, and the update-in-progress bit was not set, 2792c3b2da3049627264b7c6b449a1622f002210f03John Grossman // then we know we have a successful atomic observation. Otherwise, we loop 2802c3b2da3049627264b7c6b449a1622f002210f03John Grossman // around and try again. 2812c3b2da3049627264b7c6b449a1622f002210f03John Grossman // 2822c3b2da3049627264b7c6b449a1622f002210f03John Grossman // Note, it is very important that the observer be a lower priority thread 2832c3b2da3049627264b7c6b449a1622f002210f03John Grossman // than the updater. If the updater is lower than the observer, or they are 2842c3b2da3049627264b7c6b449a1622f002210f03John Grossman // the same priority and running with SCHED_FIFO (implying that quantum 2852c3b2da3049627264b7c6b449a1622f002210f03John Grossman // based premption is disabled) then we run the risk of deadlock. 2862c3b2da3049627264b7c6b449a1622f002210f03John Grossman int32_t seqOne, seqTwo; 2872c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2882c3b2da3049627264b7c6b449a1622f002210f03John Grossman do { 2892c3b2da3049627264b7c6b449a1622f002210f03John Grossman seqOne = android_atomic_acquire_load(&mUpdateSeq); 2902c3b2da3049627264b7c6b449a1622f002210f03John Grossman *outFront = mFront; 2912c3b2da3049627264b7c6b449a1622f002210f03John Grossman *outNextRdPTS = mNextRdPTS; 2922c3b2da3049627264b7c6b449a1622f002210f03John Grossman seqTwo = android_atomic_release_load(&mUpdateSeq); 2932c3b2da3049627264b7c6b449a1622f002210f03John Grossman } while ((seqOne != seqTwo) || (seqOne & 0x80000000)); 2942c3b2da3049627264b7c6b449a1622f002210f03John Grossman} 2952c3b2da3049627264b7c6b449a1622f002210f03John Grossman 2962c3b2da3049627264b7c6b449a1622f002210f03John Grossmanint64_t MonoPipe::offsetTimestampByAudioFrames(int64_t ts, size_t audFrames) 2972c3b2da3049627264b7c6b449a1622f002210f03John Grossman{ 2982c3b2da3049627264b7c6b449a1622f002210f03John Grossman if (0 == mSamplesToLocalTime.a_to_b_denom) 2992c3b2da3049627264b7c6b449a1622f002210f03John Grossman return AudioBufferProvider::kInvalidPTS; 3002c3b2da3049627264b7c6b449a1622f002210f03John Grossman 3012c3b2da3049627264b7c6b449a1622f002210f03John Grossman if (ts == AudioBufferProvider::kInvalidPTS) 3022c3b2da3049627264b7c6b449a1622f002210f03John Grossman return AudioBufferProvider::kInvalidPTS; 3032c3b2da3049627264b7c6b449a1622f002210f03John Grossman 3042c3b2da3049627264b7c6b449a1622f002210f03John Grossman int64_t frame_lt_duration; 3052c3b2da3049627264b7c6b449a1622f002210f03John Grossman if (!mSamplesToLocalTime.doForwardTransform(audFrames, 3062c3b2da3049627264b7c6b449a1622f002210f03John Grossman &frame_lt_duration)) { 3072c3b2da3049627264b7c6b449a1622f002210f03John Grossman // This should never fail, but if there is a bug which is causing it 3082c3b2da3049627264b7c6b449a1622f002210f03John Grossman // to fail, this message would probably end up flooding the logs 3092c3b2da3049627264b7c6b449a1622f002210f03John Grossman // because the conversion would probably fail forever. Log the 3102c3b2da3049627264b7c6b449a1622f002210f03John Grossman // error, but then zero out the ratio in the linear transform so 3112c3b2da3049627264b7c6b449a1622f002210f03John Grossman // that we don't try to do any conversions from now on. This 3122c3b2da3049627264b7c6b449a1622f002210f03John Grossman // MonoPipe's getNextWriteTimestamp is now broken for good. 3130f6a0435713c435e1aaeacbfd9ce7abb6a5b19a9Mark Salyzyn ALOGE("Overflow when attempting to convert %zu audio frames to" 3142c3b2da3049627264b7c6b449a1622f002210f03John Grossman " duration in local time. getNextWriteTimestamp will fail from" 3152c3b2da3049627264b7c6b449a1622f002210f03John Grossman " now on.", audFrames); 3162c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_to_b_numer = 0; 3172c3b2da3049627264b7c6b449a1622f002210f03John Grossman mSamplesToLocalTime.a_to_b_denom = 0; 3182c3b2da3049627264b7c6b449a1622f002210f03John Grossman return AudioBufferProvider::kInvalidPTS; 3192c3b2da3049627264b7c6b449a1622f002210f03John Grossman } 3202c3b2da3049627264b7c6b449a1622f002210f03John Grossman 3212c3b2da3049627264b7c6b449a1622f002210f03John Grossman return ts + frame_lt_duration; 3222c3b2da3049627264b7c6b449a1622f002210f03John Grossman} 3232c3b2da3049627264b7c6b449a1622f002210f03John Grossman 324003d9f71937070791418bf7efc1f7fe1e4c6b821Glenn Kastenvoid MonoPipe::shutdown(bool newState) 325003d9f71937070791418bf7efc1f7fe1e4c6b821Glenn Kasten{ 326003d9f71937070791418bf7efc1f7fe1e4c6b821Glenn Kasten mIsShutdown = newState; 327003d9f71937070791418bf7efc1f7fe1e4c6b821Glenn Kasten} 328003d9f71937070791418bf7efc1f7fe1e4c6b821Glenn Kasten 329003d9f71937070791418bf7efc1f7fe1e4c6b821Glenn Kastenbool MonoPipe::isShutdown() 330003d9f71937070791418bf7efc1f7fe1e4c6b821Glenn Kasten{ 331003d9f71937070791418bf7efc1f7fe1e4c6b821Glenn Kasten return mIsShutdown; 332003d9f71937070791418bf7efc1f7fe1e4c6b821Glenn Kasten} 333003d9f71937070791418bf7efc1f7fe1e4c6b821Glenn Kasten 334767094dd98b01baf21de2ad09c27b3c98776cf73Glenn Kastenstatus_t MonoPipe::getTimestamp(AudioTimestamp& timestamp) 335767094dd98b01baf21de2ad09c27b3c98776cf73Glenn Kasten{ 3364d0815d694e5a2edb3ce48427de50f55d0f84c0bGlenn Kasten if (mTimestampObserver.poll(timestamp)) { 3374d0815d694e5a2edb3ce48427de50f55d0f84c0bGlenn Kasten return OK; 3384d0815d694e5a2edb3ce48427de50f55d0f84c0bGlenn Kasten } 339767094dd98b01baf21de2ad09c27b3c98776cf73Glenn Kasten return INVALID_OPERATION; 340767094dd98b01baf21de2ad09c27b3c98776cf73Glenn Kasten} 341767094dd98b01baf21de2ad09c27b3c98776cf73Glenn Kasten 342010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} // namespace android 343