Use fast mode with patch track and patch record if possible.

Use fast mode with patch track/patch record if fast mixer/fast capture
is enabled. With the fast track and fast mixer/fast capture, we can get
a better performance on latency.

Bug: 111800664
Test: make phone call on marlin/walleye with enabling legacy usb hal
Change-Id: I0edd5978049e7c55da217a7a19e45fcbe5c3ac62
gugelfrei
jiabin 6 years ago
parent 88585f96fe
commit 01c8f5681c

@ -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>
@ -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);
@ -176,6 +191,7 @@ void FastCapture::onWork()
mTotalNativeFramesRead += framesRead;
dumpState->mFramesRead = mTotalNativeFramesRead;
mReadBufferState = framesRead;
patchBuffer.frameCount = framesRead;
} else {
dumpState->mReadErrors++;
mReadBufferState = 0;
@ -193,11 +209,18 @@ void FastCapture::onWork()
}
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) {
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.
int32_t rear = cblk->u.mStreaming.mRear;
android_atomic_release_store(framesWritten + rear, &cblk->u.mStreaming.mRear);
cblk->mServer += framesWritten;

@ -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>
@ -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:

@ -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();
@ -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,
@ -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(

@ -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);

@ -1527,6 +1527,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…
Cancel
Save