Reland "Add an optional override for AudioRecord device"

This is a reland of 1b8ef63876ebfa55a51c8ca9b1d8206bf8233e01. It was
previously reverted (https://webrtc-review.googlesource.com/c/src/+/175008)
but the revert was found to be unnecessary.

Original change's description:
> 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}

TBR=henrika@webrtc.org,sakal@webrtc.org,rgl@google.com

Bug: b/154440591, b/155256727
Change-Id: Ic9bf8305c85552a0dc0d2cde6190988423e7fc70
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/175084
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Commit-Queue: Henrik Lundin <henrik.lundin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31255}
This commit is contained in:
Robin Lee
2020-04-24 16:23:28 +02:00
committed by Commit Bot
parent 46b3bc6c24
commit 97755813dd
2 changed files with 38 additions and 1 deletions

View File

@ -10,8 +10,11 @@
package org.webrtc.audio; package org.webrtc.audio;
import android.media.AudioManager;
import android.content.Context; 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.JniCommon;
import org.webrtc.Logging; import org.webrtc.Logging;
@ -369,6 +372,18 @@ public class JavaAudioDeviceModule implements AudioDeviceModule {
audioInput.setMicrophoneMute(mute); 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, private static native long nativeCreateAudioDeviceModule(Context context,
AudioManager audioManager, WebRtcAudioRecord audioInput, WebRtcAudioTrack audioOutput, AudioManager audioManager, WebRtcAudioRecord audioInput, WebRtcAudioTrack audioOutput,
int inputSampleRate, int outputSampleRate, boolean useStereoInput, boolean useStereoOutput); 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.Build;
import android.os.Process; import android.os.Process;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import java.lang.System; import java.lang.System;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Arrays; import java.util.Arrays;
@ -87,6 +88,7 @@ class WebRtcAudioRecord {
private @Nullable AudioRecord audioRecord; private @Nullable AudioRecord audioRecord;
private @Nullable AudioRecordThread audioThread; private @Nullable AudioRecordThread audioThread;
private @Nullable AudioDeviceInfo preferredDevice;
private @Nullable ScheduledExecutorService executor; private @Nullable ScheduledExecutorService executor;
private @Nullable ScheduledFuture<String> future; private @Nullable ScheduledFuture<String> future;
@ -296,6 +298,9 @@ class WebRtcAudioRecord {
// Throws IllegalArgumentException. // Throws IllegalArgumentException.
audioRecord = createAudioRecordOnMOrHigher( audioRecord = createAudioRecordOnMOrHigher(
audioSource, sampleRate, channelConfig, audioFormat, bufferSizeInBytes); audioSource, sampleRate, channelConfig, audioFormat, bufferSizeInBytes);
if (preferredDevice != null) {
setPreferredDevice(preferredDevice);
}
} else { } else {
// Use the old AudioRecord constructor for API levels below 23. // Use the old AudioRecord constructor for API levels below 23.
// Throws UnsupportedOperationException. // Throws UnsupportedOperationException.
@ -329,6 +334,23 @@ class WebRtcAudioRecord {
return framesPerBuffer; 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 @CalledByNative
private boolean startRecording() { private boolean startRecording() {
Logging.d(TAG, "startRecording"); Logging.d(TAG, "startRecording");