Add an optional override for AudioRecord device

This is important when we have multiple named devices connected over
USB (eg. "Webcam", "Microphone", "Headset") and there is some way to
choose a specific input device to route from.

Bug: b/154440591
Change-Id: I8dc1801a5e4db7f7bb439e855d43897c1f7d8bc4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/173748
Commit-Queue: Robin Lee <rgl@google.com>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31130}
This commit is contained in:
Robin Lee
2020-04-24 16:23:28 +02:00
committed by Commit Bot
parent c8660b1650
commit 1b8ef63876
2 changed files with 38 additions and 1 deletions

View File

@ -10,8 +10,11 @@
package org.webrtc.audio;
import android.media.AudioManager;
import android.content.Context;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.os.Build;
import android.support.annotation.RequiresApi;
import org.webrtc.JniCommon;
import org.webrtc.Logging;
@ -369,6 +372,18 @@ public class JavaAudioDeviceModule implements AudioDeviceModule {
audioInput.setMicrophoneMute(mute);
}
/**
* Start to prefer a specific {@link AudioDeviceInfo} device for recording. Typically this should
* only be used if a client gives an explicit option for choosing a physical device to record
* from. Otherwise the best-matching device for other parameters will be used. Calling after
* recording is started may cause a temporary interruption if the audio routing changes.
*/
@RequiresApi(Build.VERSION_CODES.M)
public void setPreferredInputDevice(AudioDeviceInfo preferredInputDevice) {
Logging.d(TAG, "setPreferredInputDevice: " + preferredInputDevice);
audioInput.setPreferredDevice(preferredInputDevice);
}
private static native long nativeCreateAudioDeviceModule(Context context,
AudioManager audioManager, WebRtcAudioRecord audioInput, WebRtcAudioTrack audioOutput,
int inputSampleRate, int outputSampleRate, boolean useStereoInput, boolean useStereoOutput);

View File

@ -21,6 +21,7 @@ import android.media.MediaRecorder.AudioSource;
import android.os.Build;
import android.os.Process;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import java.lang.System;
import java.nio.ByteBuffer;
import java.util.Arrays;
@ -87,6 +88,7 @@ class WebRtcAudioRecord {
private @Nullable AudioRecord audioRecord;
private @Nullable AudioRecordThread audioThread;
private @Nullable AudioDeviceInfo preferredDevice;
private @Nullable ScheduledExecutorService executor;
private @Nullable ScheduledFuture<String> future;
@ -296,6 +298,9 @@ class WebRtcAudioRecord {
// Throws IllegalArgumentException.
audioRecord = createAudioRecordOnMOrHigher(
audioSource, sampleRate, channelConfig, audioFormat, bufferSizeInBytes);
if (preferredDevice != null) {
setPreferredDevice(preferredDevice);
}
} else {
// Use the old AudioRecord constructor for API levels below 23.
// Throws UnsupportedOperationException.
@ -329,6 +334,23 @@ class WebRtcAudioRecord {
return framesPerBuffer;
}
/**
* Prefer a specific {@link AudioDeviceInfo} device for recording. Calling after recording starts
* is valid but may cause a temporary interruption if the audio routing changes.
*/
@RequiresApi(Build.VERSION_CODES.M)
@TargetApi(Build.VERSION_CODES.M)
void setPreferredDevice(@Nullable AudioDeviceInfo preferredDevice) {
Logging.d(
TAG, "setPreferredDevice " + (preferredDevice != null ? preferredDevice.getId() : null));
this.preferredDevice = preferredDevice;
if (audioRecord != null) {
if (!audioRecord.setPreferredDevice(preferredDevice)) {
Logging.e(TAG, "setPreferredDevice failed");
}
}
}
@CalledByNative
private boolean startRecording() {
Logging.d(TAG, "startRecording");