Loading services/audioflinger/FastCapture.cpp +28 −5 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #define ATRACE_TAG ATRACE_TAG_AUDIO #include "Configuration.h" #include <audio_utils/format.h> #include <linux/futex.h> #include <sys/syscall.h> #include <media/AudioBufferProvider.h> Loading Loading @@ -161,7 +162,21 @@ 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; size_t frameCount = current->mFrameCount; AudioBufferProvider* fastPatchRecordBufferProvider = current->mFastPatchRecordBufferProvider; AudioBufferProvider::Buffer patchBuffer; if (fastPatchRecordBufferProvider != 0) { patchBuffer.frameCount = ~0; status_t status = fastPatchRecordBufferProvider->getNextBuffer(&patchBuffer); if (status != NO_ERROR) { frameCount = 0; } else if (patchBuffer.frameCount < frameCount) { // TODO: Make sure that it doesn't cause any issues if we just get a small available // buffer from the buffer provider. frameCount = patchBuffer.frameCount; } } if ((command & FastCaptureState::READ) /*&& isWarm*/) { ALOG_ASSERT(mInputSource != NULL); Loading @@ -176,6 +191,7 @@ void FastCapture::onWork() mTotalNativeFramesRead += framesRead; dumpState->mFramesRead = mTotalNativeFramesRead; mReadBufferState = framesRead; patchBuffer.frameCount = framesRead; } else { dumpState->mReadErrors++; mReadBufferState = 0; Loading @@ -193,11 +209,18 @@ void FastCapture::onWork() } if (mReadBufferState > 0) { ssize_t framesWritten = mPipeSink->write(mReadBuffer, mReadBufferState); audio_track_cblk_t* cblk = current->mCblk; if (fastPatchRecordBufferProvider != 0) { // This indicates the fast track is a patch record, update the cblk by // calling releaseBuffer(). memcpy_by_audio_format(patchBuffer.raw, current->mFastPatchRecordFormat, mReadBuffer, mFormat.mFormat, framesWritten * mFormat.mChannelCount); patchBuffer.frameCount = framesWritten; fastPatchRecordBufferProvider->releaseBuffer(&patchBuffer); } else if (cblk != NULL && framesWritten > 0) { // 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; Loading services/audioflinger/FastCaptureState.h +5 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #define ANDROID_AUDIO_FAST_CAPTURE_STATE_H #include <media/nbaio/NBAIO.h> #include <media/AudioBufferProvider.h> #include "FastThreadState.h" #include <private/media/AudioTrackShared.h> Loading @@ -37,6 +38,10 @@ struct FastCaptureState : FastThreadState { size_t mFrameCount; // number of frames per fast capture buffer audio_track_cblk_t* mCblk; // control block for the single fast client, or NULL audio_format_t mFastPatchRecordFormat = AUDIO_FORMAT_INVALID; AudioBufferProvider* mFastPatchRecordBufferProvider = nullptr; // a reference to a patch // record in fast mode // Extends FastThreadState::Command static const Command // The following commands also process configuration changes, and can be "or"ed: Loading services/audioflinger/PatchPanel.cpp +21 −5 Original line number Diff line number Diff line Loading @@ -431,14 +431,14 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) // use a pseudo LCM between input and output framecount size_t playbackFrameCount = mPlayback.thread()->frameCount(); int playbackShift = __builtin_ctz(playbackFrameCount); size_t recordFramecount = mRecord.thread()->frameCount(); int shift = __builtin_ctz(recordFramecount); size_t recordFrameCount = mRecord.thread()->frameCount(); int shift = __builtin_ctz(recordFrameCount); if (playbackShift < shift) { shift = playbackShift; } size_t frameCount = (playbackFrameCount * recordFramecount) >> shift; ALOGV("%s() playframeCount %zu recordFramecount %zu frameCount %zu", __func__, playbackFrameCount, recordFramecount, frameCount); size_t frameCount = (playbackFrameCount * recordFrameCount) >> shift; ALOGV("%s() playframeCount %zu recordFrameCount %zu frameCount %zu", __func__, playbackFrameCount, recordFrameCount, frameCount); // create a special record track to capture from record thread uint32_t channelCount = mPlayback.thread()->channelCount(); Loading @@ -455,6 +455,17 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) } audio_input_flags_t inputFlags = mAudioPatch.sources[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ? mAudioPatch.sources[0].flags.input : AUDIO_INPUT_FLAG_NONE; if (sampleRate == mRecord.thread()->sampleRate() && inChannelMask == mRecord.thread()->channelMask() && mRecord.thread()->fastTrackAvailable() && mRecord.thread()->hasFastCapture()) { // Create a fast track if the record thread has fast capture to get better performance. // Only enable fast mode when there is no resample needed. inputFlags = (audio_input_flags_t) (inputFlags | AUDIO_INPUT_FLAG_FAST); } else { // Fast mode is not available in this case. inputFlags = (audio_input_flags_t) (inputFlags & ~AUDIO_INPUT_FLAG_FAST); } sp<RecordThread::PatchRecord> tempRecordTrack = new (std::nothrow) RecordThread::PatchRecord( mRecord.thread().get(), sampleRate, Loading @@ -476,6 +487,11 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) // "reuse one existing output mix" case streamType = mAudioPatch.sources[1].ext.mix.usecase.stream; } if (mPlayback.thread()->hasFastMixer()) { // Create a fast track if the playback thread has fast mixer to get better performance. outputFlags = (audio_output_flags_t) (outputFlags | AUDIO_OUTPUT_FLAG_FAST); } // create a special playback track to render to playback thread. // this track is given the same buffer as the PatchRecord buffer sp<PlaybackThread::PatchTrack> tempPatchTrack = new (std::nothrow) PlaybackThread::PatchTrack( Loading services/audioflinger/Threads.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -6700,6 +6700,14 @@ reacquire_wakelock: } didModify = true; } AudioBufferProvider* abp = (fastTrack != 0 && fastTrack->isPatchTrack()) ? reinterpret_cast<AudioBufferProvider*>(fastTrack.get()) : nullptr; if (state->mFastPatchRecordBufferProvider != abp) { state->mFastPatchRecordBufferProvider = abp; state->mFastPatchRecordFormat = fastTrack == 0 ? AUDIO_FORMAT_INVALID : fastTrack->format(); didModify = true; } sq->end(didModify); if (didModify) { sq->push(block); Loading services/audioflinger/Threads.h +2 −0 Original line number Diff line number Diff line Loading @@ -1530,6 +1530,8 @@ public: void updateMetadata_l() override; bool fastTrackAvailable() const { return mFastTrackAvail; } private: // Enter standby if not already in standby, and set mStandby flag void standbyIfNotAlreadyInStandby(); Loading Loading
services/audioflinger/FastCapture.cpp +28 −5 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #define ATRACE_TAG ATRACE_TAG_AUDIO #include "Configuration.h" #include <audio_utils/format.h> #include <linux/futex.h> #include <sys/syscall.h> #include <media/AudioBufferProvider.h> Loading Loading @@ -161,7 +162,21 @@ 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; size_t frameCount = current->mFrameCount; AudioBufferProvider* fastPatchRecordBufferProvider = current->mFastPatchRecordBufferProvider; AudioBufferProvider::Buffer patchBuffer; if (fastPatchRecordBufferProvider != 0) { patchBuffer.frameCount = ~0; status_t status = fastPatchRecordBufferProvider->getNextBuffer(&patchBuffer); if (status != NO_ERROR) { frameCount = 0; } else if (patchBuffer.frameCount < frameCount) { // TODO: Make sure that it doesn't cause any issues if we just get a small available // buffer from the buffer provider. frameCount = patchBuffer.frameCount; } } if ((command & FastCaptureState::READ) /*&& isWarm*/) { ALOG_ASSERT(mInputSource != NULL); Loading @@ -176,6 +191,7 @@ void FastCapture::onWork() mTotalNativeFramesRead += framesRead; dumpState->mFramesRead = mTotalNativeFramesRead; mReadBufferState = framesRead; patchBuffer.frameCount = framesRead; } else { dumpState->mReadErrors++; mReadBufferState = 0; Loading @@ -193,11 +209,18 @@ void FastCapture::onWork() } if (mReadBufferState > 0) { ssize_t framesWritten = mPipeSink->write(mReadBuffer, mReadBufferState); audio_track_cblk_t* cblk = current->mCblk; if (fastPatchRecordBufferProvider != 0) { // This indicates the fast track is a patch record, update the cblk by // calling releaseBuffer(). memcpy_by_audio_format(patchBuffer.raw, current->mFastPatchRecordFormat, mReadBuffer, mFormat.mFormat, framesWritten * mFormat.mChannelCount); patchBuffer.frameCount = framesWritten; fastPatchRecordBufferProvider->releaseBuffer(&patchBuffer); } else if (cblk != NULL && framesWritten > 0) { // 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; Loading
services/audioflinger/FastCaptureState.h +5 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #define ANDROID_AUDIO_FAST_CAPTURE_STATE_H #include <media/nbaio/NBAIO.h> #include <media/AudioBufferProvider.h> #include "FastThreadState.h" #include <private/media/AudioTrackShared.h> Loading @@ -37,6 +38,10 @@ struct FastCaptureState : FastThreadState { size_t mFrameCount; // number of frames per fast capture buffer audio_track_cblk_t* mCblk; // control block for the single fast client, or NULL audio_format_t mFastPatchRecordFormat = AUDIO_FORMAT_INVALID; AudioBufferProvider* mFastPatchRecordBufferProvider = nullptr; // a reference to a patch // record in fast mode // Extends FastThreadState::Command static const Command // The following commands also process configuration changes, and can be "or"ed: Loading
services/audioflinger/PatchPanel.cpp +21 −5 Original line number Diff line number Diff line Loading @@ -431,14 +431,14 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) // use a pseudo LCM between input and output framecount size_t playbackFrameCount = mPlayback.thread()->frameCount(); int playbackShift = __builtin_ctz(playbackFrameCount); size_t recordFramecount = mRecord.thread()->frameCount(); int shift = __builtin_ctz(recordFramecount); size_t recordFrameCount = mRecord.thread()->frameCount(); int shift = __builtin_ctz(recordFrameCount); if (playbackShift < shift) { shift = playbackShift; } size_t frameCount = (playbackFrameCount * recordFramecount) >> shift; ALOGV("%s() playframeCount %zu recordFramecount %zu frameCount %zu", __func__, playbackFrameCount, recordFramecount, frameCount); size_t frameCount = (playbackFrameCount * recordFrameCount) >> shift; ALOGV("%s() playframeCount %zu recordFrameCount %zu frameCount %zu", __func__, playbackFrameCount, recordFrameCount, frameCount); // create a special record track to capture from record thread uint32_t channelCount = mPlayback.thread()->channelCount(); Loading @@ -455,6 +455,17 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) } audio_input_flags_t inputFlags = mAudioPatch.sources[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ? mAudioPatch.sources[0].flags.input : AUDIO_INPUT_FLAG_NONE; if (sampleRate == mRecord.thread()->sampleRate() && inChannelMask == mRecord.thread()->channelMask() && mRecord.thread()->fastTrackAvailable() && mRecord.thread()->hasFastCapture()) { // Create a fast track if the record thread has fast capture to get better performance. // Only enable fast mode when there is no resample needed. inputFlags = (audio_input_flags_t) (inputFlags | AUDIO_INPUT_FLAG_FAST); } else { // Fast mode is not available in this case. inputFlags = (audio_input_flags_t) (inputFlags & ~AUDIO_INPUT_FLAG_FAST); } sp<RecordThread::PatchRecord> tempRecordTrack = new (std::nothrow) RecordThread::PatchRecord( mRecord.thread().get(), sampleRate, Loading @@ -476,6 +487,11 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) // "reuse one existing output mix" case streamType = mAudioPatch.sources[1].ext.mix.usecase.stream; } if (mPlayback.thread()->hasFastMixer()) { // Create a fast track if the playback thread has fast mixer to get better performance. outputFlags = (audio_output_flags_t) (outputFlags | AUDIO_OUTPUT_FLAG_FAST); } // create a special playback track to render to playback thread. // this track is given the same buffer as the PatchRecord buffer sp<PlaybackThread::PatchTrack> tempPatchTrack = new (std::nothrow) PlaybackThread::PatchTrack( Loading
services/audioflinger/Threads.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -6700,6 +6700,14 @@ reacquire_wakelock: } didModify = true; } AudioBufferProvider* abp = (fastTrack != 0 && fastTrack->isPatchTrack()) ? reinterpret_cast<AudioBufferProvider*>(fastTrack.get()) : nullptr; if (state->mFastPatchRecordBufferProvider != abp) { state->mFastPatchRecordBufferProvider = abp; state->mFastPatchRecordFormat = fastTrack == 0 ? AUDIO_FORMAT_INVALID : fastTrack->format(); didModify = true; } sq->end(didModify); if (didModify) { sq->push(block); Loading
services/audioflinger/Threads.h +2 −0 Original line number Diff line number Diff line Loading @@ -1530,6 +1530,8 @@ public: void updateMetadata_l() override; bool fastTrackAvailable() const { return mFastTrackAvail; } private: // Enter standby if not already in standby, and set mStandby flag void standbyIfNotAlreadyInStandby(); Loading