Merge "audioflinger: Add support for RecordTrack with no conversion"
diff --git a/media/libmedia/TypeConverter.cpp b/media/libmedia/TypeConverter.cpp
index a3db754..514c795 100644
--- a/media/libmedia/TypeConverter.cpp
+++ b/media/libmedia/TypeConverter.cpp
@@ -132,6 +132,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_MMAP_NOIRQ),
MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_VOIP_TX),
MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_HW_AV_SYNC),
+ MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_DIRECT),
TERMINATOR
};
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 13477f3..53a4ce9 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2335,6 +2335,9 @@
return 0;
}
+ // Some flags are specific to framework and must not leak to the HAL.
+ flags = static_cast<audio_input_flags_t>(flags & ~AUDIO_INPUT_FRAMEWORK_FLAGS);
+
// Audio Policy can request a specific handle for hardware hotword.
// The goal here is not to re-open an already opened input.
// It is to use a pre-assigned I/O handle.
diff --git a/services/audioflinger/MmapTracks.h b/services/audioflinger/MmapTracks.h
index 241af09..968d5aa 100644
--- a/services/audioflinger/MmapTracks.h
+++ b/services/audioflinger/MmapTracks.h
@@ -40,6 +40,7 @@
audio_session_t triggerSession);
virtual void stop();
virtual bool isFastTrack() const { return false; }
+ bool isDirect() const override { return true; }
void appendDumpHeader(String8& result);
void appendDump(String8& result, bool active);
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index c2927ba..42a5a90 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -423,6 +423,14 @@
uint32_t sampleRate = mPlayback.thread()->sampleRate();
audio_format_t format = mPlayback.thread()->format();
+ audio_format_t inputFormat = mRecord.thread()->format();
+ if (!audio_is_linear_pcm(inputFormat)) {
+ // The playbackThread format will say PCM for IEC61937 packetized stream.
+ // Use recordThread format.
+ format = inputFormat;
+ }
+ audio_input_flags_t inputFlags = mAudioPatch.sources[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ?
+ mAudioPatch.sources[0].flags.input : AUDIO_INPUT_FLAG_NONE;
sp<RecordThread::PatchRecord> tempRecordTrack = new (std::nothrow) RecordThread::PatchRecord(
mRecord.thread().get(),
sampleRate,
@@ -431,12 +439,15 @@
frameCount,
NULL,
(size_t)0 /* bufferSize */,
- AUDIO_INPUT_FLAG_NONE);
+ inputFlags);
status = mRecord.checkTrack(tempRecordTrack.get());
if (status != NO_ERROR) {
return status;
}
+ audio_output_flags_t outputFlags = mAudioPatch.sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ?
+ mAudioPatch.sinks[0].flags.output : AUDIO_OUTPUT_FLAG_NONE;
+
// 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(
@@ -448,7 +459,7 @@
frameCount,
tempRecordTrack->buffer(),
tempRecordTrack->bufferSize(),
- AUDIO_OUTPUT_FLAG_NONE);
+ outputFlags);
status = mPlayback.checkTrack(tempPatchTrack.get());
if (status != NO_ERROR) {
return status;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index a93899b..4d5f6b0 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -71,7 +71,8 @@
}
bool isOffloaded() const
{ return (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0; }
- bool isDirect() const { return (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0; }
+ bool isDirect() const override
+ { return (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0; }
bool isOffloadedOrDirect() const { return (mFlags
& (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD
| AUDIO_OUTPUT_FLAG_DIRECT)) != 0; }
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 43b6391..b0c9fda 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -63,6 +63,8 @@
const ExtendedTimestamp ×tamp);
virtual bool isFastTrack() const { return (mFlags & AUDIO_INPUT_FLAG_FAST) != 0; }
+ bool isDirect() const override
+ { return (mFlags & AUDIO_INPUT_FLAG_DIRECT) != 0; }
void setSilenced(bool silenced) { if (!isPatchTrack()) mSilenced = silenced; }
bool isSilenced() const { return mSilenced; }
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 2fe6378..c673a6f 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6815,9 +6815,33 @@
framesOut = min(framesOut,
destinationFramesPossible(
framesIn, mSampleRate, activeTrack->mSampleRate));
- // process frames from the RecordThread buffer provider to the RecordTrack buffer
- framesOut = activeTrack->mRecordBufferConverter->convert(
- activeTrack->mSink.raw, activeTrack->mResamplerBufferProvider, framesOut);
+
+ if (activeTrack->isDirect()) {
+ // No RecordBufferConverter used for compressed formats. Pass
+ // straight from RecordThread buffer to RecordTrack buffer.
+ AudioBufferProvider::Buffer buffer;
+ buffer.frameCount = framesOut;
+ status_t status = activeTrack->mResamplerBufferProvider->getNextBuffer(&buffer);
+ if (status == OK && buffer.frameCount != 0) {
+ ALOGV_IF(buffer.frameCount != framesOut,
+ "%s() read less than expected (%zu vs %zu)",
+ __func__, buffer.frameCount, framesOut);
+ framesOut = buffer.frameCount;
+ memcpy(activeTrack->mSink.raw, buffer.raw, buffer.frameCount);
+ activeTrack->mResamplerBufferProvider->releaseBuffer(&buffer);
+ } else {
+ framesOut = 0;
+ ALOGE("%s() cannot fill request, status: %d, frameCount: %zu",
+ __func__, status, buffer.frameCount);
+ }
+ } else {
+ // process frames from the RecordThread buffer provider to the RecordTrack
+ // buffer
+ framesOut = activeTrack->mRecordBufferConverter->convert(
+ activeTrack->mSink.raw,
+ activeTrack->mResamplerBufferProvider,
+ framesOut);
+ }
if (framesOut > 0 && (overrun == OVERRUN_UNKNOWN)) {
overrun = OVERRUN_FALSE;
@@ -7189,8 +7213,10 @@
// see previously buffered data before it called start(), but with greater risk of overrun.
recordTrack->mResamplerBufferProvider->reset();
- // clear any converter state as new data will be discontinuous
- recordTrack->mRecordBufferConverter->reset();
+ if (!recordTrack->isDirect()) {
+ // clear any converter state as new data will be discontinuous
+ recordTrack->mRecordBufferConverter->reset();
+ }
recordTrack->mState = TrackBase::STARTING_2;
// signal thread to start
mWaitWorkCV.broadcast();
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index dafba1e..95da9d7 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -91,6 +91,7 @@
void* buffer() const { return mBuffer; }
size_t bufferSize() const { return mBufferSize; }
virtual bool isFastTrack() const = 0;
+ virtual bool isDirect() const = 0;
bool isOutputTrack() const { return (mType == TYPE_OUTPUT); }
bool isPatchTrack() const { return (mType == TYPE_PATCH); }
bool isExternalTrack() const { return !isOutputTrack() && !isPatchTrack(); }
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index f6c33e2..22e610e 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1694,18 +1694,20 @@
return;
}
- mRecordBufferConverter = new RecordBufferConverter(
- thread->mChannelMask, thread->mFormat, thread->mSampleRate,
- channelMask, format, sampleRate);
- // Check if the RecordBufferConverter construction was successful.
- // If not, don't continue with construction.
- //
- // NOTE: It would be extremely rare that the record track cannot be created
- // for the current device, but a pending or future device change would make
- // the record track configuration valid.
- if (mRecordBufferConverter->initCheck() != NO_ERROR) {
- ALOGE("RecordTrack unable to create record buffer converter");
- return;
+ if (!isDirect()) {
+ mRecordBufferConverter = new RecordBufferConverter(
+ thread->mChannelMask, thread->mFormat, thread->mSampleRate,
+ channelMask, format, sampleRate);
+ // Check if the RecordBufferConverter construction was successful.
+ // If not, don't continue with construction.
+ //
+ // NOTE: It would be extremely rare that the record track cannot be created
+ // for the current device, but a pending or future device change would make
+ // the record track configuration valid.
+ if (mRecordBufferConverter->initCheck() != NO_ERROR) {
+ ALOGE("RecordTrack unable to create record buffer converter");
+ return;
+ }
}
mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,