Fix RuntimeException during call initialization.

fork-5.53.8
Alex Hart 2021-08-10 17:08:55 -03:00 zatwierdzone przez GitHub
rodzic 3baf10f0e9
commit 824a8ac5f2
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
14 zmienionych plików z 121 dodań i 55 usunięć

Wyświetl plik

@ -22,7 +22,7 @@ public class BroadcastVideoSink implements VideoSink {
public static final int DEVICE_ROTATION_IGNORE = -1; public static final int DEVICE_ROTATION_IGNORE = -1;
private final EglBase eglBase; private final EglBaseWrapper eglBase;
private final WeakHashMap<VideoSink, Boolean> sinks; private final WeakHashMap<VideoSink, Boolean> sinks;
private final WeakHashMap<Object, Point> requestingSizes; private final WeakHashMap<Object, Point> requestingSizes;
private boolean dirtySizes; private boolean dirtySizes;
@ -32,7 +32,7 @@ public class BroadcastVideoSink implements VideoSink {
private boolean rotateWithDevice; private boolean rotateWithDevice;
public BroadcastVideoSink() { public BroadcastVideoSink() {
this(null, false, true, 0); this(new EglBaseWrapper(null), false, true, 0);
} }
/** /**
@ -41,7 +41,7 @@ public class BroadcastVideoSink implements VideoSink {
* @param rotateWithDevice Rotate video frame to match device orientation * @param rotateWithDevice Rotate video frame to match device orientation
* @param deviceOrientationDegrees Device orientation in degrees * @param deviceOrientationDegrees Device orientation in degrees
*/ */
public BroadcastVideoSink(@Nullable EglBase eglBase, boolean forceRotate, boolean rotateWithDevice, int deviceOrientationDegrees) { public BroadcastVideoSink(@NonNull EglBaseWrapper eglBase, boolean forceRotate, boolean rotateWithDevice, int deviceOrientationDegrees) {
this.eglBase = eglBase; this.eglBase = eglBase;
this.sinks = new WeakHashMap<>(); this.sinks = new WeakHashMap<>();
this.requestingSizes = new WeakHashMap<>(); this.requestingSizes = new WeakHashMap<>();
@ -52,7 +52,7 @@ public class BroadcastVideoSink implements VideoSink {
this.rotateWithDevice = rotateWithDevice; this.rotateWithDevice = rotateWithDevice;
} }
public @Nullable EglBase getEglBase() { public @NonNull EglBaseWrapper getLockableEglBase() {
return eglBase; return eglBase;
} }

Wyświetl plik

@ -144,9 +144,9 @@ public class CallParticipantView extends ConstraintLayout {
renderer.setVisibility(hasContentToRender ? View.VISIBLE : View.GONE); renderer.setVisibility(hasContentToRender ? View.VISIBLE : View.GONE);
if (participant.isVideoEnabled()) { if (participant.isVideoEnabled()) {
if (participant.getVideoSink().getEglBase() != null) { participant.getVideoSink().getLockableEglBase().performWithValidEglBase(eglBase -> {
renderer.init(participant.getVideoSink().getEglBase()); renderer.init(eglBase);
} });
renderer.attachBroadcastVideoSink(participant.getVideoSink()); renderer.attachBroadcastVideoSink(participant.getVideoSink());
} else { } else {
renderer.attachBroadcastVideoSink(null); renderer.attachBroadcastVideoSink(null);

Wyświetl plik

@ -0,0 +1,70 @@
package org.thoughtcrime.securesms.components.webrtc
import android.opengl.EGL14
import org.signal.core.util.logging.Log
import org.webrtc.EglBase
import org.webrtc.EglBase10
import org.webrtc.EglBase14
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
import java.util.function.Consumer
import javax.microedition.khronos.egl.EGL10
import kotlin.concurrent.withLock
private val TAG = Log.tag(EglBaseWrapper::class.java)
/**
* Wrapper which allows caller to perform synchronized actions on an EglBase object.
*/
class EglBaseWrapper(val eglBase: EglBase?) {
private val lock: Lock = ReentrantLock()
fun require(): EglBase = requireNotNull(eglBase)
@Volatile
private var isReleased: Boolean = false
fun performWithValidEglBase(consumer: Consumer<EglBase>) {
if (isReleased) {
Log.d(TAG, "Tried to use a released EglBase", Exception())
return
}
if (eglBase == null) {
return
}
lock.withLock {
if (isReleased) {
Log.d(TAG, "Tried to use a released EglBase", Exception())
return
}
val hasSharedContext = when (val context: EglBase.Context = eglBase.eglBaseContext) {
is EglBase14.Context -> context.rawContext != EGL14.EGL_NO_CONTEXT
is EglBase10.Context -> context.rawContext != EGL10.EGL_NO_CONTEXT
else -> throw IllegalStateException("Unknown context")
}
if (hasSharedContext) {
consumer.accept(eglBase)
}
}
}
fun releaseEglBase() {
if (isReleased || eglBase == null) {
return
}
lock.withLock {
if (isReleased) {
return
}
isReleased = true
eglBase.release()
}
}
}

Wyświetl plik

@ -47,7 +47,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.ringrtc.CameraState; import org.thoughtcrime.securesms.ringrtc.CameraState;
import org.thoughtcrime.securesms.util.BlurTransformation; import org.thoughtcrime.securesms.util.BlurTransformation;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.SetUtil; import org.thoughtcrime.securesms.util.SetUtil;
import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.views.Stub; import org.thoughtcrime.securesms.util.views.Stub;
@ -377,9 +376,10 @@ public class WebRtcCallView extends ConstraintLayout {
smallLocalRender.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL); smallLocalRender.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL);
largeLocalRender.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL); largeLocalRender.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL);
if (localCallParticipant.getVideoSink().getEglBase() != null) { localCallParticipant.getVideoSink().getLockableEglBase().performWithValidEglBase(eglBase -> {
largeLocalRender.init(localCallParticipant.getVideoSink().getEglBase()); largeLocalRender.init(eglBase);
} });
videoToggle.setChecked(localCallParticipant.isVideoEnabled(), false); videoToggle.setChecked(localCallParticipant.isVideoEnabled(), false);
smallLocalRender.setRenderInPip(true); smallLocalRender.setRenderInPip(true);

Wyświetl plik

@ -14,13 +14,13 @@ import com.annimon.stream.Stream;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.signal.ringrtc.CameraControl; import org.signal.ringrtc.CameraControl;
import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper;
import org.webrtc.Camera1Enumerator; import org.webrtc.Camera1Enumerator;
import org.webrtc.Camera2Capturer; import org.webrtc.Camera2Capturer;
import org.webrtc.Camera2Enumerator; import org.webrtc.Camera2Enumerator;
import org.webrtc.CameraEnumerator; import org.webrtc.CameraEnumerator;
import org.webrtc.CameraVideoCapturer; import org.webrtc.CameraVideoCapturer;
import org.webrtc.CapturerObserver; import org.webrtc.CapturerObserver;
import org.webrtc.EglBase;
import org.webrtc.SurfaceTextureHelper; import org.webrtc.SurfaceTextureHelper;
import org.webrtc.VideoFrame; import org.webrtc.VideoFrame;
@ -39,19 +39,19 @@ public class Camera implements CameraControl, CameraVideoCapturer.CameraSwitchHa
private static final String TAG = Log.tag(Camera.class); private static final String TAG = Log.tag(Camera.class);
@NonNull private final Context context; @NonNull private final Context context;
@Nullable private final CameraVideoCapturer capturer; @Nullable private final CameraVideoCapturer capturer;
@NonNull private final CameraEventListener cameraEventListener; @NonNull private final CameraEventListener cameraEventListener;
@NonNull private final EglBase eglBase; @NonNull private final EglBaseWrapper eglBase;
private final int cameraCount; private final int cameraCount;
@NonNull private CameraState.Direction activeDirection; @NonNull private CameraState.Direction activeDirection;
private boolean enabled; private boolean enabled;
private boolean isInitialized; private boolean isInitialized;
private int orientation; private int orientation;
public Camera(@NonNull Context context, public Camera(@NonNull Context context,
@NonNull CameraEventListener cameraEventListener, @NonNull CameraEventListener cameraEventListener,
@NonNull EglBase eglBase, @NonNull EglBaseWrapper eglBase,
@NonNull CameraState.Direction desiredCameraDirection) @NonNull CameraState.Direction desiredCameraDirection)
{ {
this.context = context; this.context = context;
@ -80,11 +80,13 @@ public class Camera implements CameraControl, CameraVideoCapturer.CameraSwitchHa
@Override @Override
public void initCapturer(@NonNull CapturerObserver observer) { public void initCapturer(@NonNull CapturerObserver observer) {
if (capturer != null) { if (capturer != null) {
capturer.initialize(SurfaceTextureHelper.create("WebRTC-SurfaceTextureHelper", eglBase.getEglBaseContext()), eglBase.performWithValidEglBase(base -> {
context, capturer.initialize(SurfaceTextureHelper.create("WebRTC-SurfaceTextureHelper", base.getEglBaseContext()),
new CameraCapturerWrapper(observer)); context,
capturer.setOrientation(orientation); new CameraCapturerWrapper(observer));
isInitialized = true; capturer.setOrientation(orientation);
isInitialized = true;
});
} }
} }

Wyświetl plik

@ -45,7 +45,7 @@ public class BeginCallActionProcessorDelegate extends WebRtcActionProcessor {
CallParticipant.createRemote(new CallParticipantId(remotePeer.getRecipient()), CallParticipant.createRemote(new CallParticipantId(remotePeer.getRecipient()),
remotePeer.getRecipient(), remotePeer.getRecipient(),
null, null,
new BroadcastVideoSink(currentState.getVideoState().getEglBase(), new BroadcastVideoSink(currentState.getVideoState().getLockableEglBase(),
false, false,
true, true,
currentState.getLocalDeviceState().getOrientation().getDegrees()), currentState.getLocalDeviceState().getOrientation().getDegrees()),
@ -92,7 +92,7 @@ public class BeginCallActionProcessorDelegate extends WebRtcActionProcessor {
CallParticipant.createRemote(new CallParticipantId(remotePeer.getRecipient()), CallParticipant.createRemote(new CallParticipantId(remotePeer.getRecipient()),
remotePeer.getRecipient(), remotePeer.getRecipient(),
null, null,
new BroadcastVideoSink(currentState.getVideoState().getEglBase(), new BroadcastVideoSink(currentState.getVideoState().getLockableEglBase(),
false, false,
true, true,
currentState.getLocalDeviceState().getOrientation().getDegrees()), currentState.getLocalDeviceState().getOrientation().getDegrees()),

Wyświetl plik

@ -92,11 +92,11 @@ public class GroupActionProcessor extends DeviceAwareActionProcessor {
BroadcastVideoSink videoSink; BroadcastVideoSink videoSink;
VideoTrack videoTrack = device.getVideoTrack(); VideoTrack videoTrack = device.getVideoTrack();
if (videoTrack != null) { if (videoTrack != null) {
videoSink = (callParticipant != null && callParticipant.getVideoSink().getEglBase() != null) ? callParticipant.getVideoSink() videoSink = (callParticipant != null && callParticipant.getVideoSink().getLockableEglBase().getEglBase() != null) ? callParticipant.getVideoSink()
: new BroadcastVideoSink(currentState.getVideoState().requireEglBase(), : new BroadcastVideoSink(currentState.getVideoState().getLockableEglBase(),
true, true,
true, true,
currentState.getLocalDeviceState().getOrientation().getDegrees()); currentState.getLocalDeviceState().getOrientation().getDegrees());
videoTrack.addSink(videoSink); videoTrack.addSink(videoSink);
} else { } else {
videoSink = new BroadcastVideoSink(); videoSink = new BroadcastVideoSink();
@ -267,7 +267,7 @@ public class GroupActionProcessor extends DeviceAwareActionProcessor {
currentState = terminateGroupCall(currentState, false).builder() currentState = terminateGroupCall(currentState, false).builder()
.actionProcessor(new GroupNetworkUnavailableActionProcessor(webRtcInteractor)) .actionProcessor(new GroupNetworkUnavailableActionProcessor(webRtcInteractor))
.changeVideoState() .changeVideoState()
.eglBase(videoState.getEglBase()) .eglBase(videoState.getLockableEglBase())
.camera(videoState.getCamera()) .camera(videoState.getCamera())
.localSink(videoState.getLocalSink()) .localSink(videoState.getLocalSink())
.commit() .commit()

Wyświetl plik

@ -44,7 +44,7 @@ class GroupNetworkUnavailableActionProcessor extends WebRtcActionProcessor {
byte[] groupId = currentState.getCallInfoState().getCallRecipient().requireGroupId().getDecodedId(); byte[] groupId = currentState.getCallInfoState().getCallRecipient().requireGroupId().getDecodedId();
GroupCall groupCall = webRtcInteractor.getCallManager().createGroupCall(groupId, GroupCall groupCall = webRtcInteractor.getCallManager().createGroupCall(groupId,
SignalStore.internalValues().groupCallingServer(), SignalStore.internalValues().groupCallingServer(),
currentState.getVideoState().requireEglBase(), currentState.getVideoState().getLockableEglBase().require(),
webRtcInteractor.getGroupCallObserver()); webRtcInteractor.getGroupCallObserver());
return currentState.builder() return currentState.builder()

Wyświetl plik

@ -45,7 +45,7 @@ public class GroupPreJoinActionProcessor extends GroupActionProcessor {
byte[] groupId = currentState.getCallInfoState().getCallRecipient().requireGroupId().getDecodedId(); byte[] groupId = currentState.getCallInfoState().getCallRecipient().requireGroupId().getDecodedId();
GroupCall groupCall = webRtcInteractor.getCallManager().createGroupCall(groupId, GroupCall groupCall = webRtcInteractor.getCallManager().createGroupCall(groupId,
SignalStore.internalValues().groupCallingServer(), SignalStore.internalValues().groupCallingServer(),
currentState.getVideoState().requireEglBase(), currentState.getVideoState().getLockableEglBase().require(),
webRtcInteractor.getGroupCallObserver()); webRtcInteractor.getGroupCallObserver());
try { try {

Wyświetl plik

@ -86,7 +86,7 @@ public class IncomingCallActionProcessor extends DeviceAwareActionProcessor {
try { try {
webRtcInteractor.getCallManager().proceed(activePeer.getCallId(), webRtcInteractor.getCallManager().proceed(activePeer.getCallId(),
context, context,
videoState.requireEglBase(), videoState.getLockableEglBase().require(),
videoState.requireLocalSink(), videoState.requireLocalSink(),
callParticipant.getVideoSink(), callParticipant.getVideoSink(),
videoState.requireCamera(), videoState.requireCamera(),

Wyświetl plik

@ -118,7 +118,7 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor {
webRtcInteractor.getCallManager().proceed(activePeer.getCallId(), webRtcInteractor.getCallManager().proceed(activePeer.getCallId(),
context, context,
videoState.requireEglBase(), videoState.getLockableEglBase().require(),
videoState.requireLocalSink(), videoState.requireLocalSink(),
callParticipant.getVideoSink(), callParticipant.getVideoSink(),
videoState.requireCamera(), videoState.requireCamera(),

Wyświetl plik

@ -6,6 +6,7 @@ import androidx.annotation.NonNull;
import org.signal.core.util.ThreadUtil; import org.signal.core.util.ThreadUtil;
import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink; import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink;
import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper;
import org.thoughtcrime.securesms.ringrtc.Camera; import org.thoughtcrime.securesms.ringrtc.Camera;
import org.thoughtcrime.securesms.ringrtc.CameraEventListener; import org.thoughtcrime.securesms.ringrtc.CameraEventListener;
import org.thoughtcrime.securesms.ringrtc.CameraState; import org.thoughtcrime.securesms.ringrtc.CameraState;
@ -31,7 +32,7 @@ public final class WebRtcVideoUtil {
final WebRtcServiceStateBuilder builder = currentState.builder(); final WebRtcServiceStateBuilder builder = currentState.builder();
ThreadUtil.runOnMainSync(() -> { ThreadUtil.runOnMainSync(() -> {
EglBase eglBase = EglBase.create(); EglBaseWrapper eglBase = new EglBaseWrapper(EglBase.create());
BroadcastVideoSink localSink = new BroadcastVideoSink(eglBase, BroadcastVideoSink localSink = new BroadcastVideoSink(eglBase,
true, true,
false, false,
@ -66,7 +67,7 @@ public final class WebRtcVideoUtil {
camera = new Camera(context, camera = new Camera(context,
cameraEventListener, cameraEventListener,
currentState.getVideoState().requireEglBase(), currentState.getVideoState().getLockableEglBase(),
currentState.getLocalDeviceState().getCameraState().getActiveDirection()); currentState.getLocalDeviceState().getCameraState().getActiveDirection());
camera.setOrientation(currentState.getLocalDeviceState().getOrientation().getDegrees()); camera.setOrientation(currentState.getLocalDeviceState().getOrientation().getDegrees());
@ -88,10 +89,7 @@ public final class WebRtcVideoUtil {
camera.dispose(); camera.dispose();
} }
EglBase eglBase = currentState.getVideoState().getEglBase(); currentState.getVideoState().getLockableEglBase().releaseEglBase();
if (eglBase != null) {
eglBase.release();
}
return currentState.builder() return currentState.builder()
.changeVideoState() .changeVideoState()

Wyświetl plik

@ -4,8 +4,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink; import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink;
import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper;
import org.thoughtcrime.securesms.ringrtc.Camera; import org.thoughtcrime.securesms.ringrtc.Camera;
import org.webrtc.EglBase;
import java.util.Objects; import java.util.Objects;
@ -13,7 +13,7 @@ import java.util.Objects;
* Local device video state and infrastructure. * Local device video state and infrastructure.
*/ */
public final class VideoState { public final class VideoState {
EglBase eglBase; EglBaseWrapper eglBase;
BroadcastVideoSink localSink; BroadcastVideoSink localSink;
Camera camera; Camera camera;
@ -25,20 +25,16 @@ public final class VideoState {
this(toCopy.eglBase, toCopy.localSink, toCopy.camera); this(toCopy.eglBase, toCopy.localSink, toCopy.camera);
} }
VideoState(@Nullable EglBase eglBase, @Nullable BroadcastVideoSink localSink, @Nullable Camera camera) { VideoState(@NonNull EglBaseWrapper eglBase, @Nullable BroadcastVideoSink localSink, @Nullable Camera camera) {
this.eglBase = eglBase; this.eglBase = eglBase;
this.localSink = localSink; this.localSink = localSink;
this.camera = camera; this.camera = camera;
} }
public @Nullable EglBase getEglBase() { public @NonNull EglBaseWrapper getLockableEglBase() {
return eglBase; return eglBase;
} }
public @NonNull EglBase requireEglBase() {
return Objects.requireNonNull(eglBase);
}
public @Nullable BroadcastVideoSink getLocalSink() { public @Nullable BroadcastVideoSink getLocalSink() {
return localSink; return localSink;
} }

Wyświetl plik

@ -8,6 +8,7 @@ import com.annimon.stream.OptionalLong;
import org.signal.ringrtc.GroupCall; import org.signal.ringrtc.GroupCall;
import org.thoughtcrime.securesms.components.sensors.Orientation; import org.thoughtcrime.securesms.components.sensors.Orientation;
import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink; import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink;
import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper;
import org.thoughtcrime.securesms.events.CallParticipant; import org.thoughtcrime.securesms.events.CallParticipant;
import org.thoughtcrime.securesms.events.CallParticipantId; import org.thoughtcrime.securesms.events.CallParticipantId;
import org.thoughtcrime.securesms.events.WebRtcViewModel; import org.thoughtcrime.securesms.events.WebRtcViewModel;
@ -17,7 +18,6 @@ import org.thoughtcrime.securesms.ringrtc.Camera;
import org.thoughtcrime.securesms.ringrtc.CameraState; import org.thoughtcrime.securesms.ringrtc.CameraState;
import org.thoughtcrime.securesms.ringrtc.RemotePeer; import org.thoughtcrime.securesms.ringrtc.RemotePeer;
import org.thoughtcrime.securesms.service.webrtc.WebRtcActionProcessor; import org.thoughtcrime.securesms.service.webrtc.WebRtcActionProcessor;
import org.webrtc.EglBase;
import java.util.Collection; import java.util.Collection;
@ -177,7 +177,7 @@ public class WebRtcServiceStateBuilder {
return WebRtcServiceStateBuilder.this.build(); return WebRtcServiceStateBuilder.this.build();
} }
public @NonNull VideoStateBuilder eglBase(@Nullable EglBase eglBase) { public @NonNull VideoStateBuilder eglBase(@Nullable EglBaseWrapper eglBase) {
toBuild.eglBase = eglBase; toBuild.eglBase = eglBase;
return this; return this;
} }