Support Compressed Capture in AudioRecord
Bug: 206156079
Test: atest AudioRecordTest
Change-Id: Ie16107b79c6b16c261501c68050109249eda3961
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index ebd488a..edcb86a 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -69,8 +69,9 @@
// We double the size of input buffer for ping pong use of record buffer.
// Assumes audio_is_linear_pcm(format)
- if ((*frameCount = (size * 2) / (audio_channel_count_from_in_mask(channelMask) *
- audio_bytes_per_sample(format))) == 0) {
+ const auto sampleSize = audio_channel_count_from_in_mask(channelMask) *
+ audio_bytes_per_sample(format);
+ if (sampleSize == 0 || ((*frameCount = (size * 2) / sampleSize) == 0)) {
ALOGE("%s(): Unsupported configuration: sampleRate %u, format %#x, channelMask %#x",
__func__, sampleRate, format, channelMask);
return BAD_VALUE;
@@ -357,6 +358,12 @@
if (format == AUDIO_FORMAT_DEFAULT) {
format = AUDIO_FORMAT_PCM_16_BIT;
}
+ if (!audio_is_linear_pcm(format)) {
+ // Compressed capture requires direct
+ flags = (audio_input_flags_t) (flags | AUDIO_INPUT_FLAG_DIRECT);
+ ALOGI("%s(): Format %#x is not linear pcm. Setting DIRECT, using flags %#x", __func__,
+ format, flags);
+ }
mFormat = format;
mChannelMask = channelMask;
mSessionId = sessionId;
@@ -396,9 +403,8 @@
goto error;
}
- // AudioFlinger capture only supports linear PCM
- if (!audio_is_valid_format(mFormat) || !audio_is_linear_pcm(mFormat)) {
- errorMessage = StringPrintf("%s: Format %#x is not linear pcm", __func__, mFormat);
+ if (!audio_is_valid_format(mFormat)) {
+ errorMessage = StringPrintf("%s: Format %#x is not valid", __func__, mFormat);
status = BAD_VALUE;
goto error;
}
@@ -718,6 +724,11 @@
if (status == OK) {
timestamp->mPosition[ExtendedTimestamp::LOCATION_CLIENT] = mFramesRead;
timestamp->mTimeNs[ExtendedTimestamp::LOCATION_CLIENT] = 0;
+ if (!audio_is_linear_pcm(mFormat)) {
+ // Don't do retrograde corrections or server offset if track is
+ // compressed
+ return OK;
+ }
// server side frame offset in case AudioRecord has been restored.
for (int i = ExtendedTimestamp::LOCATION_SERVER;
i < ExtendedTimestamp::LOCATION_MAX; ++i) {
@@ -1184,7 +1195,13 @@
if (status == DEAD_OBJECT) {
// re-create track, unless someone else has already done so
if (newSequence == oldSequence) {
- status = restoreRecord_l("obtainBuffer");
+ if (!audio_is_linear_pcm(mFormat)) {
+ // If compressed capture, don't attempt to restore the track.
+ // Return a DEAD_OBJECT error and let the caller recreate.
+ tryCounter = 0;
+ } else {
+ status = restoreRecord_l("obtainBuffer");
+ }
if (status != NO_ERROR) {
buffer.mFrameCount = 0;
buffer.mRaw = NULL;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 61537a8..982893d 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1864,6 +1864,8 @@
bool isTimestampCorrectionEnabled() const override {
// checks popcount for exactly one device.
+ // Is currently disabled. Before enabling,
+ // verify compressed record timestamps.
return audio_is_input_device(mTimestampCorrectedDevice)
&& inDeviceType() == mTimestampCorrectedDevice;
}
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 233865f..279ff3d 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -2635,6 +2635,8 @@
// ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
mKernelFrameTime.store(ft);
if (!audio_is_linear_pcm(mFormat)) {
+ // Stream is direct, return provided timestamp with no conversion
+ mServerProxy->setTimestamp(timestamp);
return;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index fc6e05e..4b91d87 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2387,7 +2387,7 @@
break; // success
} else if (profileFlags & AUDIO_INPUT_FLAG_RAW) {
profileFlags = (audio_input_flags_t) (profileFlags & ~AUDIO_INPUT_FLAG_RAW); // retry
- } else if (profileFlags != AUDIO_INPUT_FLAG_NONE) {
+ } else if (profileFlags != AUDIO_INPUT_FLAG_NONE && audio_is_linear_pcm(config->format)) {
profileFlags = AUDIO_INPUT_FLAG_NONE; // retry
} else { // fail
ALOGW("%s could not find profile for device %s, sampling rate %u, format %#x, "