FastCapture.cpp revision f91df1b368a140abd37c80b204bd48d78778cc43
124035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian/* 224035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian * Copyright (C) 2014 The Android Open Source Project 324035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian * 424035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian * Licensed under the Apache License, Version 2.0 (the "License"); 524035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian * you may not use this file except in compliance with the License. 624035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian * You may obtain a copy of the License at 724035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian * 824035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian * http://www.apache.org/licenses/LICENSE-2.0 924035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian * 1024035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian * Unless required by applicable law or agreed to in writing, software 1124035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian * distributed under the License is distributed on an "AS IS" BASIS, 1224035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1324035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian * See the License for the specific language governing permissions and 1424035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian * limitations under the License. 1524035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian */ 1624035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian 1724035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian#define LOG_TAG "FastCapture" 1824035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian//#define LOG_NDEBUG 0 1924035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian 2024035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian#define ATRACE_TAG ATRACE_TAG_AUDIO 2124035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian 2224035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian#include "Configuration.h" 231cadb25da1ed875bdd078270e642966724a0c39aMathias Agopian#include <linux/futex.h> 2424035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian#include <sys/syscall.h> 2524035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian#include <media/AudioBufferProvider.h> 2624035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian#include <utils/Log.h> 2724035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian#include <utils/Trace.h> 2824035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian#include "FastCapture.h" 2924035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian 3024035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopiannamespace android { 317f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian 3224035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian/*static*/ const FastCaptureState FastCapture::initial; 3324035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian 347f781d155221c4067c93f85b4153c204423f49f2Mathias AgopianFastCapture::FastCapture() : FastThread(), 357f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian inputSource(NULL), inputSourceGen(0), pipeSink(NULL), pipeSinkGen(0), 367f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian readBuffer(NULL), readBufferState(-1), format(Format_Invalid), sampleRate(0), 3724035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian // dummyDumpState 381cadb25da1ed875bdd078270e642966724a0c39aMathias Agopian totalNativeFramesRead(0) 3924035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian{ 40288870ebc3da8121b7a237a53280bd8b931b7a2fElliott Hughes previous = &initial; 4124035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian current = &initial; 4224035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian 4324035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian mDummyDumpState = &dummyDumpState; 4424035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian} 4524035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian 4624035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias AgopianFastCapture::~FastCapture() 4724035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian{ 4824035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian} 4924035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian 5024035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias AgopianFastCaptureStateQueue* FastCapture::sq() 5124035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian{ 5224035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian return &mSQ; 5324035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian} 5424035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian 5524035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopianconst FastThreadState *FastCapture::poll() 5624035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian{ 5724035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian return mSQ.poll(); 5824035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian} 5924035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian 607f781d155221c4067c93f85b4153c204423f49f2Mathias Agopianvoid FastCapture::setLog(NBLog::Writer *logWriter __unused) 6124035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian{ 6224035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian} 6324035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian 6424035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopianvoid FastCapture::onIdle() 6524035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian{ 6624035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian preIdle = *(const FastCaptureState *)current; 6724035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian current = &preIdle; 6824035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian} 6924035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian 7024035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopianvoid FastCapture::onExit() 7124035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian{ 7224035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian delete[] readBuffer; 7324035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian} 741cadb25da1ed875bdd078270e642966724a0c39aMathias Agopian 7524035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopianbool FastCapture::isSubClassCommand(FastThreadState::Command command) 7624035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian{ 7724035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian switch ((FastCaptureState::Command) command) { 78a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian case FastCaptureState::READ: 797f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian case FastCaptureState::WRITE: 80a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian case FastCaptureState::READ_WRITE: 81a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian return true; 82a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian default: 83a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian return false; 84a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian } 85a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian} 86a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian 87a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopianvoid FastCapture::onStateChange() 88a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian{ 89a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian const FastCaptureState * const current = (const FastCaptureState *) this->current; 90a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian const FastCaptureState * const previous = (const FastCaptureState *) this->previous; 91a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) this->dumpState; 92a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian const size_t frameCount = current->mFrameCount; 93a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian 94a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian bool eitherChanged = false; 95a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian 96a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian // check for change in input HAL configuration 97a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian NBAIO_Format previousFormat = format; 98a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian if (current->mInputSourceGen != inputSourceGen) { 99a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian inputSource = current->mInputSource; 100a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian inputSourceGen = current->mInputSourceGen; 101a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian if (inputSource == NULL) { 102a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian format = Format_Invalid; 103a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian sampleRate = 0; 104a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian } else { 105a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian format = inputSource->format(); 106a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian sampleRate = Format_sampleRate(format); 107a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian unsigned channelCount = Format_channelCount(format); 108a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian ALOG_ASSERT(channelCount == 1 || channelCount == 2); 109a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian } 110a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian dumpState->mSampleRate = sampleRate; 111a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian eitherChanged = true; 112a6d86e5ea748a7bcde4ff30b0b1f882dca36a8f3Mathias Agopian } 1137f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian 1147f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian // check for change in pipe 1157f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian if (current->mPipeSinkGen != pipeSinkGen) { 1167f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian pipeSink = current->mPipeSink; 1177f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian pipeSinkGen = current->mPipeSinkGen; 11824035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian eitherChanged = true; 11924035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian } 1207f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian 12124035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian // input source and pipe sink must be compatible 12224035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian if (eitherChanged && inputSource != NULL && pipeSink != NULL) { 1237f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian ALOG_ASSERT(Format_isEqual(format, pipeSink->format())); 1247f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian } 1257f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian 12624035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian if ((!Format_isEqual(format, previousFormat)) || (frameCount != previous->mFrameCount)) { 12724035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian // FIXME to avoid priority inversion, don't delete here 12824035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian delete[] readBuffer; 1297f781d155221c4067c93f85b4153c204423f49f2Mathias Agopian readBuffer = NULL; 13024035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian if (frameCount > 0 && sampleRate > 0) { 13124035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian // FIXME new may block for unbounded time at internal mutex of the heap 13224035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian // implementation; it would be better to have normal capture thread allocate for 13324035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian // us to avoid blocking here and to prevent possible priority inversion 13424035338ed6329e4d85fb00cf99a91e2cdd55ba5Mathias Agopian unsigned channelCount = Format_channelCount(format); 135 // FIXME frameSize 136 readBuffer = new short[frameCount * channelCount]; 137 periodNs = (frameCount * 1000000000LL) / sampleRate; // 1.00 138 underrunNs = (frameCount * 1750000000LL) / sampleRate; // 1.75 139 overrunNs = (frameCount * 500000000LL) / sampleRate; // 0.50 140 forceNs = (frameCount * 950000000LL) / sampleRate; // 0.95 141 warmupNs = (frameCount * 500000000LL) / sampleRate; // 0.50 142 } else { 143 periodNs = 0; 144 underrunNs = 0; 145 overrunNs = 0; 146 forceNs = 0; 147 warmupNs = 0; 148 } 149 readBufferState = -1; 150 dumpState->mFrameCount = frameCount; 151 } 152 153} 154 155void FastCapture::onWork() 156{ 157 const FastCaptureState * const current = (const FastCaptureState *) this->current; 158 FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) this->dumpState; 159 const FastCaptureState::Command command = this->command; 160 const size_t frameCount = current->mFrameCount; 161 162 if ((command & FastCaptureState::READ) /*&& isWarm*/) { 163 ALOG_ASSERT(inputSource != NULL); 164 ALOG_ASSERT(readBuffer != NULL); 165 dumpState->mReadSequence++; 166 ATRACE_BEGIN("read"); 167 ssize_t framesRead = inputSource->read(readBuffer, frameCount, 168 AudioBufferProvider::kInvalidPTS); 169 ATRACE_END(); 170 dumpState->mReadSequence++; 171 if (framesRead >= 0) { 172 LOG_ALWAYS_FATAL_IF((size_t) framesRead > frameCount); 173 totalNativeFramesRead += framesRead; 174 dumpState->mFramesRead = totalNativeFramesRead; 175 readBufferState = framesRead; 176 } else { 177 dumpState->mReadErrors++; 178 readBufferState = 0; 179 } 180 // FIXME rename to attemptedIO 181 attemptedWrite = true; 182 } 183 184 if (command & FastCaptureState::WRITE) { 185 ALOG_ASSERT(pipeSink != NULL); 186 ALOG_ASSERT(readBuffer != NULL); 187 if (readBufferState < 0) { 188 unsigned channelCount = Format_channelCount(format); 189 // FIXME frameSize 190 memset(readBuffer, 0, frameCount * channelCount * sizeof(short)); 191 readBufferState = frameCount; 192 } 193 if (readBufferState > 0) { 194 ssize_t framesWritten = pipeSink->write(readBuffer, readBufferState); 195 // FIXME This supports at most one fast capture client. 196 // To handle multiple clients this could be converted to an array, 197 // or with a lot more work the control block could be shared by all clients. 198 audio_track_cblk_t* cblk = current->mCblk; 199 if (cblk != NULL && framesWritten > 0) { 200 int32_t rear = cblk->u.mStreaming.mRear; 201 android_atomic_release_store(framesWritten + rear, &cblk->u.mStreaming.mRear); 202 cblk->mServer += framesWritten; 203 int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); 204 if (!(old & CBLK_FUTEX_WAKE)) { 205 // client is never in server process, so don't use FUTEX_WAKE_PRIVATE 206 (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, 1); 207 } 208 } 209 } 210 } 211} 212 213FastCaptureDumpState::FastCaptureDumpState() : FastThreadDumpState(), 214 mReadSequence(0), mFramesRead(0), mReadErrors(0), mSampleRate(0), mFrameCount(0) 215{ 216} 217 218FastCaptureDumpState::~FastCaptureDumpState() 219{ 220} 221 222} // namespace android 223