disable hardware AEC on some devices. fixes #3734
This commit is contained in:
parent
de941f6036
commit
a2a7256682
|
@ -8,7 +8,6 @@ import android.util.Log;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.base.Throwables;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
@ -41,6 +40,8 @@ import org.webrtc.SessionDescription;
|
||||||
import org.webrtc.SurfaceTextureHelper;
|
import org.webrtc.SurfaceTextureHelper;
|
||||||
import org.webrtc.VideoSource;
|
import org.webrtc.VideoSource;
|
||||||
import org.webrtc.VideoTrack;
|
import org.webrtc.VideoTrack;
|
||||||
|
import org.webrtc.audio.JavaAudioDeviceModule;
|
||||||
|
import org.webrtc.voiceengine.WebRtcAudioEffects;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -57,6 +58,22 @@ public class WebRTCWrapper {
|
||||||
|
|
||||||
private static final String EXTENDED_LOGGING_TAG = WebRTCWrapper.class.getSimpleName();
|
private static final String EXTENDED_LOGGING_TAG = WebRTCWrapper.class.getSimpleName();
|
||||||
|
|
||||||
|
//we should probably keep this in sync with: https://github.com/signalapp/Signal-Android/blob/master/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java#L296
|
||||||
|
private static final Set<String> HARDWARE_AEC_BLACKLIST = new ImmutableSet.Builder<String>()
|
||||||
|
.add("Pixel")
|
||||||
|
.add("Pixel XL")
|
||||||
|
.add("Moto G5")
|
||||||
|
.add("Moto G (5S) Plus")
|
||||||
|
.add("Moto G4")
|
||||||
|
.add("TA-1053")
|
||||||
|
.add("Mi A1")
|
||||||
|
.add("Mi A2")
|
||||||
|
.add("E5823") // Sony z5 compact
|
||||||
|
.add("Redmi Note 5")
|
||||||
|
.add("FP2") // Fairphone FP2
|
||||||
|
.add("MI 5")
|
||||||
|
.build();
|
||||||
|
|
||||||
private static final int CAPTURING_RESOLUTION = 1920;
|
private static final int CAPTURING_RESOLUTION = 1920;
|
||||||
private static final int CAPTURING_MAX_FRAME_RATE = 30;
|
private static final int CAPTURING_MAX_FRAME_RATE = 30;
|
||||||
|
|
||||||
|
@ -165,6 +182,30 @@ public class WebRTCWrapper {
|
||||||
this.eventCallback = eventCallback;
|
this.eventCallback = eventCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void dispose(final PeerConnection peerConnection) {
|
||||||
|
try {
|
||||||
|
peerConnection.dispose();
|
||||||
|
} catch (final IllegalStateException e) {
|
||||||
|
Log.e(Config.LOGTAG, "unable to dispose of peer connection", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static CapturerChoice of(CameraEnumerator enumerator, final String deviceName, Set<String> availableCameras) {
|
||||||
|
final CameraVideoCapturer capturer = enumerator.createCapturer(deviceName, null);
|
||||||
|
if (capturer == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final ArrayList<CameraEnumerationAndroid.CaptureFormat> choices = new ArrayList<>(enumerator.getSupportedFormats(deviceName));
|
||||||
|
Collections.sort(choices, (a, b) -> b.width - a.width);
|
||||||
|
for (final CameraEnumerationAndroid.CaptureFormat captureFormat : choices) {
|
||||||
|
if (captureFormat.width <= CAPTURING_RESOLUTION) {
|
||||||
|
return new CapturerChoice(capturer, captureFormat, availableCameras);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void setup(final Context context, final AppRTCAudioManager.SpeakerPhonePreference speakerPhonePreference) throws InitializationException {
|
public void setup(final Context context, final AppRTCAudioManager.SpeakerPhonePreference speakerPhonePreference) throws InitializationException {
|
||||||
try {
|
try {
|
||||||
PeerConnectionFactory.initialize(
|
PeerConnectionFactory.initialize(
|
||||||
|
@ -186,9 +227,15 @@ public class WebRTCWrapper {
|
||||||
Preconditions.checkState(this.eglBase != null);
|
Preconditions.checkState(this.eglBase != null);
|
||||||
Preconditions.checkNotNull(media);
|
Preconditions.checkNotNull(media);
|
||||||
Preconditions.checkArgument(media.size() > 0, "media can not be empty when initializing peer connection");
|
Preconditions.checkArgument(media.size() > 0, "media can not be empty when initializing peer connection");
|
||||||
|
final boolean setUseHardwareAcousticEchoCanceler = WebRtcAudioEffects.canUseAcousticEchoCanceler() && !HARDWARE_AEC_BLACKLIST.contains(Build.MODEL);
|
||||||
|
Log.d(Config.LOGTAG, String.format("setUseHardwareAcousticEchoCanceler(%s) model=%s", setUseHardwareAcousticEchoCanceler, Build.MODEL));
|
||||||
PeerConnectionFactory peerConnectionFactory = PeerConnectionFactory.builder()
|
PeerConnectionFactory peerConnectionFactory = PeerConnectionFactory.builder()
|
||||||
.setVideoDecoderFactory(new DefaultVideoDecoderFactory(eglBase.getEglBaseContext()))
|
.setVideoDecoderFactory(new DefaultVideoDecoderFactory(eglBase.getEglBaseContext()))
|
||||||
.setVideoEncoderFactory(new DefaultVideoEncoderFactory(eglBase.getEglBaseContext(), true, true))
|
.setVideoEncoderFactory(new DefaultVideoEncoderFactory(eglBase.getEglBaseContext(), true, true))
|
||||||
|
.setAudioDeviceModule(JavaAudioDeviceModule.builder(context)
|
||||||
|
.setUseHardwareAcousticEchoCanceler(setUseHardwareAcousticEchoCanceler)
|
||||||
|
.createAudioDeviceModule()
|
||||||
|
)
|
||||||
.createPeerConnectionFactory();
|
.createPeerConnectionFactory();
|
||||||
|
|
||||||
|
|
||||||
|
@ -258,14 +305,6 @@ public class WebRTCWrapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void dispose(final PeerConnection peerConnection) {
|
|
||||||
try {
|
|
||||||
peerConnection.dispose();
|
|
||||||
} catch (final IllegalStateException e) {
|
|
||||||
Log.e(Config.LOGTAG, "unable to dispose of peer connection", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized void verifyClosed() {
|
synchronized void verifyClosed() {
|
||||||
if (this.peerConnection != null
|
if (this.peerConnection != null
|
||||||
|| this.eglBase != null
|
|| this.eglBase != null
|
||||||
|
@ -469,22 +508,6 @@ public class WebRTCWrapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static CapturerChoice of(CameraEnumerator enumerator, final String deviceName, Set<String> availableCameras) {
|
|
||||||
final CameraVideoCapturer capturer = enumerator.createCapturer(deviceName, null);
|
|
||||||
if (capturer == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final ArrayList<CameraEnumerationAndroid.CaptureFormat> choices = new ArrayList<>(enumerator.getSupportedFormats(deviceName));
|
|
||||||
Collections.sort(choices, (a, b) -> b.width - a.width);
|
|
||||||
for (final CameraEnumerationAndroid.CaptureFormat captureFormat : choices) {
|
|
||||||
if (captureFormat.width <= CAPTURING_RESOLUTION) {
|
|
||||||
return new CapturerChoice(capturer, captureFormat, availableCameras);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PeerConnection.PeerConnectionState getState() {
|
public PeerConnection.PeerConnectionState getState() {
|
||||||
return requirePeerConnection().connectionState();
|
return requirePeerConnection().connectionState();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue