if (framesAvailable != NULL) { *framesAvailable = framesIn; } if (hasOverrun != NULL) { *hasOverrun = overrun; } } // AudioBufferProvider interface status_t ResamplerBufferProvider::getNextBuffer( AudioBufferProvider::Buffer* buffer) { const auto threadBase = mRecordTrack->thread().promote(); if (threadBase == 0) { buffer->frameCount = 0; buffer->raw = NULL; return NOT_ENOUGH_DATA; } auto* const recordThread = static_cast(threadBase->asIAfRecordThread().get()); int32_t rear = recordThread->mRsmpInRear; int32_t front = mRsmpInFront; ssize_t filled = audio_utils::safe_sub_overflow(rear, front); // FIXME should not be P2 (don't want to increase latency) // FIXME if client not keeping up, discard LOG_ALWAYS_FATAL_IF(!(0 <= filled && (size_t) filled <= recordThread->mRsmpInFrames)); // 'filled' may be non-contiguous, so return only the first contiguous chunk front &= recordThread->mRsmpInFramesP2 - 1; size_t part1 = recordThread->mRsmpInFramesP2 - front; if (part1 > (size_t) filled) { part1 = filled; } size_t ask = buffer->frameCount; ALOG_ASSERT(ask > 0); if (part1 > ask) { part1 = ask; } if (part1 == 0) { // out of data is fine since the resampler will return a short-count. buffer->raw = NULL; buffer->frameCount = 0; mRsmpInUnrel = 0; return NOT_ENOUGH_DATA; } buffer->raw = (uint8_t*)recordThread->mRsmpInBuffer + front * recordThread->mFrameSize; buffer->frameCount = part1; mRsmpInUnrel = part1; return NO_ERROR; } // AudioBufferProvider interface void ResamplerBufferProvider::releaseBuffer( AudioBufferProvider::Buffer* buffer) { int32_t stepCount = static_cast(buffer->frameCount); if (stepCount == 0) { return; } ALOG_ASSERT(stepCount <= (int32_t)mRsmpInUnrel); mRsmpInUnrel -= stepCount; mRsmpInFront = audio_utils::safe_add_overflow(mRsmpInFront, stepCount); buffer->raw = NULL; buffer->frameCount = 0; } void RecordThread::checkBtNrec() { audio_utils::lock_guard _l(mutex()); checkBtNrec_l(); } void RecordThread::checkBtNrec_l() { // disable AEC and NS if the device is a BT SCO headset supporting those // pre processings bool suspend = audio_is_bluetooth_sco_device(inDeviceType_l()) && mAfThreadCallback->btNrecIsOff(); if (mBtNrecSuspended.exchange(suspend) != suspend) { for (size_t i = 0; i < mEffectChains.size(); i++) { setEffectSuspended_l(FX_IID_AEC, suspend, mEffectChains[i]->sessionId()); setEffectSuspended_l(FX_IID_NS, suspend, mEffectChains[i]->sessionId()); } } } bool RecordThread::checkForNewParameter_l(const String8& keyValuePair, status_t& status) { bool reconfig = false; status = NO_ERROR; audio_format_t reqFormat = mFormat; uint32_t samplingRate = mSampleRate; // TODO this may change if we want to support capture from HDMI PCM multi channel (e.g on TVs). [[maybe_unused]] audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(mChannelCount); AudioParameter param = AudioParameter(keyValuePair); int value; // scope for AutoPark extends to end of method AutoPark park(mFastCapture); // TODO Investigate when this code runs. Check with audio policy when a sample rate and // channel count change can be requested. Do we mandate the first client defines the // HAL sampling rate and channel count or do we allow changes on the fly? if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) { samplingRate = value;