Android: Add AudioDeviceModule interface and clean up implementation code
This CL introduces sdk/android/api/org/webrtc/audio/AudioDeviceModule.java, which is the new interface for audio device modules on Android. This CL also refactors the main AudioDeviceModule implementation, which is sdk/android/api/org/webrtc/audio/JavaAudioDeviceModule.java and makes it conform to the new interface. The old code used global static methods to configure the audio device code. This CL gets rid of all that and uses a builder pattern in JavaAudioDeviceModule instead. The only two dynamic methods left in the interface are setSpeakerMute() and setMicrophoneMute(). Removing the global static methods allowed a significant cleanup, and e.g. the file sdk/android/src/jni/audio_device/audio_manager.cc has been completely removed. The PeerConnectionFactory interface is also updated to allow passing in an external AudioDeviceModule. The current built-in ADM is encapsulated under LegacyAudioDeviceModule.java, which is the default for now to ensure backwards compatibility. Bug: webrtc:7452 Change-Id: I64d5f4dba9a004da001f1acb2bd0c1b1f2b64f21 Reviewed-on: https://webrtc-review.googlesource.com/65360 Commit-Queue: Magnus Jedvert <magjed@webrtc.org> Reviewed-by: Magnus Jedvert <magjed@webrtc.org> Reviewed-by: Paulina Hensman <phensman@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22765}
This commit is contained in:
committed by
Commit Bot
parent
3ab5c40f72
commit
66f1e9eb34
@ -71,6 +71,10 @@ import org.webrtc.VideoSink;
|
||||
import org.webrtc.VideoSource;
|
||||
import org.webrtc.VideoTrack;
|
||||
import org.webrtc.audio.JavaAudioDeviceModule;
|
||||
import org.webrtc.audio.JavaAudioDeviceModule.AudioRecordErrorCallback;
|
||||
import org.webrtc.audio.JavaAudioDeviceModule.AudioTrackErrorCallback;
|
||||
import org.webrtc.audio.LegacyAudioDeviceModule;
|
||||
import org.webrtc.audio.AudioDeviceModule;
|
||||
import org.webrtc.voiceengine.WebRtcAudioManager;
|
||||
import org.webrtc.voiceengine.WebRtcAudioRecord;
|
||||
import org.webrtc.voiceengine.WebRtcAudioRecord.AudioRecordStartErrorCode;
|
||||
@ -106,8 +110,6 @@ public class PeerConnectionClient {
|
||||
"WebRTC-H264HighProfile/Enabled/";
|
||||
private static final String DISABLE_WEBRTC_AGC_FIELDTRIAL =
|
||||
"WebRTC-Audio-MinimizeResamplingOnMobile/Enabled/";
|
||||
private static final String EXTERNAL_ANDROID_AUDIO_DEVICE_FIELDTRIAL =
|
||||
"WebRTC-ExternalAndroidAudioDevice/Enabled/";
|
||||
private static final String AUDIO_CODEC_PARAM_BITRATE = "maxaveragebitrate";
|
||||
private static final String AUDIO_ECHO_CANCELLATION_CONSTRAINT = "googEchoCancellation";
|
||||
private static final String AUDIO_AUTO_GAIN_CONTROL_CONSTRAINT = "googAutoGainControl";
|
||||
@ -428,7 +430,6 @@ public class PeerConnectionClient {
|
||||
Log.d(TAG, "Disable WebRTC AGC field trial.");
|
||||
}
|
||||
if (!peerConnectionParameters.useLegacyAudioDevice) {
|
||||
fieldTrials += EXTERNAL_ANDROID_AUDIO_DEVICE_FIELDTRIAL;
|
||||
Log.d(TAG, "Enable WebRTC external Android audio device field trial.");
|
||||
}
|
||||
|
||||
@ -492,11 +493,10 @@ public class PeerConnectionClient {
|
||||
}
|
||||
}
|
||||
|
||||
if (peerConnectionParameters.useLegacyAudioDevice) {
|
||||
setupAudioDeviceLegacy();
|
||||
} else {
|
||||
setupAudioDevice();
|
||||
}
|
||||
final AudioDeviceModule adm = peerConnectionParameters.useLegacyAudioDevice
|
||||
? createLegacyAudioDevice()
|
||||
: createJavaAudioDevice();
|
||||
|
||||
// Create peer connection factory.
|
||||
if (options != null) {
|
||||
Log.d(TAG, "Factory networkIgnoreMask option: " + options.networkIgnoreMask);
|
||||
@ -515,11 +515,16 @@ public class PeerConnectionClient {
|
||||
decoderFactory = new SoftwareVideoDecoderFactory();
|
||||
}
|
||||
|
||||
factory = new PeerConnectionFactory(options, encoderFactory, decoderFactory);
|
||||
factory = PeerConnectionFactory.builder()
|
||||
.setOptions(options)
|
||||
.setAudioDeviceModule(adm)
|
||||
.setVideoEncoderFactory(encoderFactory)
|
||||
.setVideoDecoderFactory(decoderFactory)
|
||||
.createPeerConnectionFactory();
|
||||
Log.d(TAG, "Peer connection factory created.");
|
||||
}
|
||||
|
||||
void setupAudioDeviceLegacy() {
|
||||
AudioDeviceModule createLegacyAudioDevice() {
|
||||
// Enable/disable OpenSL ES playback.
|
||||
if (!peerConnectionParameters.useOpenSLES) {
|
||||
Log.d(TAG, "Disable OpenSL ES audio even if device supports it");
|
||||
@ -589,37 +594,19 @@ public class PeerConnectionClient {
|
||||
reportError(errorMessage);
|
||||
}
|
||||
});
|
||||
|
||||
return new LegacyAudioDeviceModule();
|
||||
}
|
||||
|
||||
void setupAudioDevice() {
|
||||
AudioDeviceModule createJavaAudioDevice() {
|
||||
// Enable/disable OpenSL ES playback.
|
||||
if (!peerConnectionParameters.useOpenSLES) {
|
||||
Log.d(TAG, "Disable OpenSL ES audio even if device supports it");
|
||||
} else {
|
||||
Log.d(TAG, "Allow OpenSL ES audio if device supports it");
|
||||
Log.w(TAG, "External OpenSLES ADM not implemented yet.");
|
||||
// TODO(magjed): Add support for external OpenSLES ADM.
|
||||
}
|
||||
|
||||
if (peerConnectionParameters.disableBuiltInAEC) {
|
||||
Log.d(TAG, "Disable built-in AEC even if device supports it");
|
||||
JavaAudioDeviceModule.setWebRtcBasedAcousticEchoCanceler(true);
|
||||
} else {
|
||||
Log.d(TAG, "Enable built-in AEC if device supports it");
|
||||
JavaAudioDeviceModule.setWebRtcBasedAcousticEchoCanceler(false);
|
||||
}
|
||||
|
||||
if (peerConnectionParameters.disableBuiltInNS) {
|
||||
Log.d(TAG, "Disable built-in NS even if device supports it");
|
||||
JavaAudioDeviceModule.setWebRtcBasedNoiseSuppressor(true);
|
||||
} else {
|
||||
Log.d(TAG, "Enable built-in NS if device supports it");
|
||||
JavaAudioDeviceModule.setWebRtcBasedNoiseSuppressor(false);
|
||||
}
|
||||
|
||||
JavaAudioDeviceModule.setOnAudioSamplesReady(saveRecordedAudioToFile);
|
||||
|
||||
// Set audio record error callbacks.
|
||||
JavaAudioDeviceModule.setErrorCallback(new JavaAudioDeviceModule.AudioRecordErrorCallback() {
|
||||
AudioRecordErrorCallback audioRecordErrorCallback = new AudioRecordErrorCallback() {
|
||||
@Override
|
||||
public void onWebRtcAudioRecordInitError(String errorMessage) {
|
||||
Log.e(TAG, "onWebRtcAudioRecordInitError: " + errorMessage);
|
||||
@ -638,9 +625,9 @@ public class PeerConnectionClient {
|
||||
Log.e(TAG, "onWebRtcAudioRecordError: " + errorMessage);
|
||||
reportError(errorMessage);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
JavaAudioDeviceModule.setErrorCallback(new JavaAudioDeviceModule.AudioTrackErrorCallback() {
|
||||
AudioTrackErrorCallback audioTrackErrorCallback = new AudioTrackErrorCallback() {
|
||||
@Override
|
||||
public void onWebRtcAudioTrackInitError(String errorMessage) {
|
||||
Log.e(TAG, "onWebRtcAudioTrackInitError: " + errorMessage);
|
||||
@ -659,7 +646,16 @@ public class PeerConnectionClient {
|
||||
Log.e(TAG, "onWebRtcAudioTrackError: " + errorMessage);
|
||||
reportError(errorMessage);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return JavaAudioDeviceModule.builder(appContext)
|
||||
.setSamplesReadyCallback(saveRecordedAudioToFile)
|
||||
.setUseHardwareAcousticEchoCanceler(peerConnectionParameters.disableBuiltInAEC)
|
||||
.setUseHardwareNoiseSuppressor(peerConnectionParameters.disableBuiltInNS)
|
||||
.setAudioRecordErrorCallback(audioRecordErrorCallback)
|
||||
.setAudioTrackErrorCallback(audioTrackErrorCallback)
|
||||
.setSamplesReadyCallback(saveRecordedAudioToFile)
|
||||
.createAudioDeviceModule();
|
||||
}
|
||||
|
||||
private void createMediaConstraintsInternal() {
|
||||
|
||||
@ -18,7 +18,6 @@ import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import org.webrtc.Camera2Enumerator;
|
||||
import org.webrtc.audio.JavaAudioDeviceModule;
|
||||
import org.webrtc.voiceengine.WebRtcAudioUtils;
|
||||
|
||||
/**
|
||||
* Settings activity for AppRTC.
|
||||
@ -174,56 +173,26 @@ public class SettingsActivity extends Activity implements OnSharedPreferenceChan
|
||||
camera2Preference.setEnabled(false);
|
||||
}
|
||||
|
||||
// Disable forcing WebRTC based AEC so it won't affect our value.
|
||||
// Otherwise, if it was enabled, isAcousticEchoCancelerSupported would always return false.
|
||||
if (sharedPreferences.getBoolean(keyprefUseLegacyAudioDevice, false)) {
|
||||
WebRtcAudioUtils.setWebRtcBasedAcousticEchoCanceler(false);
|
||||
if (!WebRtcAudioUtils.isAcousticEchoCancelerSupported()) {
|
||||
Preference disableBuiltInAECPreference =
|
||||
settingsFragment.findPreference(keyprefDisableBuiltInAEC);
|
||||
if (!JavaAudioDeviceModule.isBuiltInAcousticEchoCancelerSupported()) {
|
||||
Preference disableBuiltInAECPreference =
|
||||
settingsFragment.findPreference(keyprefDisableBuiltInAEC);
|
||||
|
||||
disableBuiltInAECPreference.setSummary(getString(R.string.pref_built_in_aec_not_available));
|
||||
disableBuiltInAECPreference.setEnabled(false);
|
||||
}
|
||||
disableBuiltInAECPreference.setSummary(getString(R.string.pref_built_in_aec_not_available));
|
||||
disableBuiltInAECPreference.setEnabled(false);
|
||||
}
|
||||
|
||||
Preference disableBuiltInAGCPreference =
|
||||
settingsFragment.findPreference(keyprefDisableBuiltInAGC);
|
||||
Preference disableBuiltInAGCPreference =
|
||||
settingsFragment.findPreference(keyprefDisableBuiltInAGC);
|
||||
|
||||
disableBuiltInAGCPreference.setSummary(getString(R.string.pref_built_in_agc_not_available));
|
||||
disableBuiltInAGCPreference.setEnabled(false);
|
||||
disableBuiltInAGCPreference.setSummary(getString(R.string.pref_built_in_agc_not_available));
|
||||
disableBuiltInAGCPreference.setEnabled(false);
|
||||
|
||||
WebRtcAudioUtils.setWebRtcBasedNoiseSuppressor(false);
|
||||
if (!WebRtcAudioUtils.isNoiseSuppressorSupported()) {
|
||||
Preference disableBuiltInNSPreference =
|
||||
settingsFragment.findPreference(keyprefDisableBuiltInNS);
|
||||
if (!JavaAudioDeviceModule.isBuiltInNoiseSuppressorSupported()) {
|
||||
Preference disableBuiltInNSPreference =
|
||||
settingsFragment.findPreference(keyprefDisableBuiltInNS);
|
||||
|
||||
disableBuiltInNSPreference.setSummary(getString(R.string.pref_built_in_ns_not_available));
|
||||
disableBuiltInNSPreference.setEnabled(false);
|
||||
}
|
||||
} else {
|
||||
JavaAudioDeviceModule.setWebRtcBasedAcousticEchoCanceler(false);
|
||||
if (!JavaAudioDeviceModule.isAcousticEchoCancelerSupported()) {
|
||||
Preference disableBuiltInAECPreference =
|
||||
settingsFragment.findPreference(keyprefDisableBuiltInAEC);
|
||||
|
||||
disableBuiltInAECPreference.setSummary(getString(R.string.pref_built_in_aec_not_available));
|
||||
disableBuiltInAECPreference.setEnabled(false);
|
||||
}
|
||||
|
||||
Preference disableBuiltInAGCPreference =
|
||||
settingsFragment.findPreference(keyprefDisableBuiltInAGC);
|
||||
|
||||
disableBuiltInAGCPreference.setSummary(getString(R.string.pref_built_in_agc_not_available));
|
||||
disableBuiltInAGCPreference.setEnabled(false);
|
||||
|
||||
JavaAudioDeviceModule.setWebRtcBasedNoiseSuppressor(false);
|
||||
if (!JavaAudioDeviceModule.isNoiseSuppressorSupported()) {
|
||||
Preference disableBuiltInNSPreference =
|
||||
settingsFragment.findPreference(keyprefDisableBuiltInNS);
|
||||
|
||||
disableBuiltInNSPreference.setSummary(getString(R.string.pref_built_in_ns_not_available));
|
||||
disableBuiltInNSPreference.setEnabled(false);
|
||||
}
|
||||
disableBuiltInNSPreference.setSummary(getString(R.string.pref_built_in_ns_not_available));
|
||||
disableBuiltInNSPreference.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user