size_t Format_frameSize(NBAIO_Format format) { #ifdef MTK_HD_AUDIO_ARCHITECTURE return Format_channelCount(format) * sizeof(short) * Format_wordCount(format); #else return Format_channelCount(format) * sizeof(short); #endif }
size_t Format_frameBitShift(NBAIO_Format format) { #ifdef MTK_HD_AUDIO_ARCHITECTURE return Format_channelCount(format) + Format_wordCount(format) - 1; #else // sizeof(short) == 2, so frame size == 1 << channels return Format_channelCount(format); #endif }
void FastCapture::onWork() { const FastCaptureState * const current = (const FastCaptureState *) mCurrent; FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) mDumpState; const FastCaptureState::Command command = mCommand; const size_t frameCount = current->mFrameCount; if ((command & FastCaptureState::READ) /*&& isWarm*/) { ALOG_ASSERT(mInputSource != NULL); ALOG_ASSERT(mReadBuffer != NULL); dumpState->mReadSequence++; ATRACE_BEGIN("read"); ssize_t framesRead = mInputSource->read(mReadBuffer, frameCount, AudioBufferProvider::kInvalidPTS); ATRACE_END(); dumpState->mReadSequence++; if (framesRead >= 0) { LOG_ALWAYS_FATAL_IF((size_t) framesRead > frameCount); mTotalNativeFramesRead += framesRead; dumpState->mFramesRead = mTotalNativeFramesRead; mReadBufferState = framesRead; } else { dumpState->mReadErrors++; mReadBufferState = 0; } // FIXME rename to attemptedIO mAttemptedWrite = true; } if (command & FastCaptureState::WRITE) { ALOG_ASSERT(mPipeSink != NULL); ALOG_ASSERT(mReadBuffer != NULL); if (mReadBufferState < 0) { unsigned channelCount = Format_channelCount(mFormat); memset(mReadBuffer, 0, frameCount * Format_frameSize(mFormat)); mReadBufferState = frameCount; } if (mReadBufferState > 0) { ssize_t framesWritten = mPipeSink->write(mReadBuffer, mReadBufferState); // FIXME This supports at most one fast capture client. // To handle multiple clients this could be converted to an array, // or with a lot more work the control block could be shared by all clients. audio_track_cblk_t* cblk = current->mCblk; if (cblk != NULL && framesWritten > 0) { int32_t rear = cblk->u.mStreaming.mRear; android_atomic_release_store(framesWritten + rear, &cblk->u.mStreaming.mRear); cblk->mServer += framesWritten; int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); if (!(old & CBLK_FUTEX_WAKE)) { // client is never in server process, so don't use FUTEX_WAKE_PRIVATE (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, 1); } } } } }
size_t Format_frameBitShift(NBAIO_Format format) { // sizeof(short) == 2, so frame size == 1 << channels return Format_channelCount(format); }
size_t Format_frameSize(NBAIO_Format format) { return Format_channelCount(format) * sizeof(short); }
void FastCapture::onStateChange() { const FastCaptureState * const current = (const FastCaptureState *) mCurrent; const FastCaptureState * const previous = (const FastCaptureState *) mPrevious; FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) mDumpState; const size_t frameCount = current->mFrameCount; bool eitherChanged = false; // check for change in input HAL configuration NBAIO_Format previousFormat = mFormat; if (current->mInputSourceGen != mInputSourceGen) { mInputSource = current->mInputSource; mInputSourceGen = current->mInputSourceGen; if (mInputSource == NULL) { mFormat = Format_Invalid; mSampleRate = 0; } else { mFormat = mInputSource->format(); mSampleRate = Format_sampleRate(mFormat); unsigned channelCount = Format_channelCount(mFormat); ALOG_ASSERT(channelCount >= 1 && channelCount <= FCC_8); } dumpState->mSampleRate = mSampleRate; eitherChanged = true; } // check for change in pipe if (current->mPipeSinkGen != mPipeSinkGen) { mPipeSink = current->mPipeSink; mPipeSinkGen = current->mPipeSinkGen; eitherChanged = true; } // input source and pipe sink must be compatible if (eitherChanged && mInputSource != NULL && mPipeSink != NULL) { ALOG_ASSERT(Format_isEqual(mFormat, mPipeSink->format())); } if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) { // FIXME to avoid priority inversion, don't free here free(mReadBuffer); mReadBuffer = NULL; if (frameCount > 0 && mSampleRate > 0) { // FIXME new may block for unbounded time at internal mutex of the heap // implementation; it would be better to have normal capture thread allocate for // us to avoid blocking here and to prevent possible priority inversion size_t bufferSize = frameCount * Format_frameSize(mFormat); (void)posix_memalign(&mReadBuffer, 32, bufferSize); memset(mReadBuffer, 0, bufferSize); // if posix_memalign fails, will segv here. mPeriodNs = (frameCount * 1000000000LL) / mSampleRate; // 1.00 mUnderrunNs = (frameCount * 1750000000LL) / mSampleRate; // 1.75 mOverrunNs = (frameCount * 500000000LL) / mSampleRate; // 0.50 mForceNs = (frameCount * 950000000LL) / mSampleRate; // 0.95 mWarmupNsMin = (frameCount * 750000000LL) / mSampleRate; // 0.75 mWarmupNsMax = (frameCount * 1250000000LL) / mSampleRate; // 1.25 } else { mPeriodNs = 0; mUnderrunNs = 0; mOverrunNs = 0; mForceNs = 0; mWarmupNsMin = 0; mWarmupNsMax = LONG_MAX; } mReadBufferState = -1; dumpState->mFrameCount = frameCount; } }