Add screen share receive support and improve video calling rotation.

This commit is contained in:
Cody Henthorne
2021-05-25 12:15:07 -04:00
committed by Greyson Parrelli
parent 513e5b45c5
commit b9b2924939
41 changed files with 665 additions and 397 deletions

View File

@@ -95,6 +95,21 @@ public class ActiveCallActionProcessorDelegate extends WebRtcActionProcessor {
.build();
}
@Override
protected @NonNull WebRtcServiceState handleScreenSharingEnable(@NonNull WebRtcServiceState currentState, boolean enable) {
RemotePeer activePeer = currentState.getCallInfoState().requireActivePeer();
Log.i(tag, "handleScreenSharingEnable(): call_id: " + activePeer.getCallId() + " enable: " + enable);
CallParticipant oldParticipant = Objects.requireNonNull(currentState.getCallInfoState().getRemoteCallParticipant(activePeer.getRecipient()));
CallParticipant newParticipant = oldParticipant.withScreenSharingEnabled(enable);
return currentState.builder()
.changeCallInfoState()
.putParticipant(activePeer.getRecipient(), newParticipant)
.build();
}
@Override
protected @NonNull WebRtcServiceState handleLocalHangup(@NonNull WebRtcServiceState currentState) {
RemotePeer remotePeer = currentState.getCallInfoState().getActivePeer();

View File

@@ -34,6 +34,7 @@ public class BeginCallActionProcessorDelegate extends WebRtcActionProcessor {
@NonNull OfferMessage.Type offerType)
{
remotePeer.setCallStartTimestamp(System.currentTimeMillis());
currentState = currentState.builder()
.actionProcessor(new OutgoingCallActionProcessor(webRtcInteractor))
.changeCallInfoState()
@@ -41,17 +42,20 @@ public class BeginCallActionProcessorDelegate extends WebRtcActionProcessor {
.callState(WebRtcViewModel.State.CALL_OUTGOING)
.putRemotePeer(remotePeer)
.putParticipant(remotePeer.getRecipient(),
CallParticipant.createRemote(
new CallParticipantId(remotePeer.getRecipient()),
remotePeer.getRecipient(),
null,
new BroadcastVideoSink(currentState.getVideoState().getEglBase()),
true,
false,
0,
true,
0,
CallParticipant.DeviceOrdinal.PRIMARY
CallParticipant.createRemote(new CallParticipantId(remotePeer.getRecipient()),
remotePeer.getRecipient(),
null,
new BroadcastVideoSink(currentState.getVideoState().getEglBase(),
false,
true,
currentState.getLocalDeviceState().getOrientation().getDegrees()),
true,
false,
0,
true,
0,
false,
CallParticipant.DeviceOrdinal.PRIMARY
))
.build();
@@ -85,17 +89,20 @@ public class BeginCallActionProcessorDelegate extends WebRtcActionProcessor {
.activePeer(remotePeer)
.callState(WebRtcViewModel.State.CALL_INCOMING)
.putParticipant(remotePeer.getRecipient(),
CallParticipant.createRemote(
new CallParticipantId(remotePeer.getRecipient()),
remotePeer.getRecipient(),
null,
new BroadcastVideoSink(currentState.getVideoState().getEglBase()),
true,
false,
0,
true,
0,
CallParticipant.DeviceOrdinal.PRIMARY
CallParticipant.createRemote(new CallParticipantId(remotePeer.getRecipient()),
remotePeer.getRecipient(),
null,
new BroadcastVideoSink(currentState.getVideoState().getEglBase(),
false,
true,
currentState.getLocalDeviceState().getOrientation().getDegrees()),
true,
false,
0,
true,
0,
false,
CallParticipant.DeviceOrdinal.PRIMARY
))
.build();
}

View File

@@ -40,7 +40,7 @@ public class ConnectedCallActionProcessor extends DeviceAwareActionProcessor {
try {
webRtcInteractor.getCallManager().setVideoEnable(enable);
} catch (CallException e) {
} catch (CallException e) {
return callFailure(currentState, "setVideoEnable() failed: ", e);
}
@@ -77,10 +77,15 @@ public class ConnectedCallActionProcessor extends DeviceAwareActionProcessor {
}
@Override
protected @NonNull WebRtcServiceState handleRemoteVideoEnable(@NonNull WebRtcServiceState currentState, boolean enable) {
protected @NonNull WebRtcServiceState handleRemoteVideoEnable(@NonNull WebRtcServiceState currentState, boolean enable) {
return activeCallDelegate.handleRemoteVideoEnable(currentState, enable);
}
@Override
protected @NonNull WebRtcServiceState handleScreenSharingEnable(@NonNull WebRtcServiceState currentState, boolean enable) {
return activeCallDelegate.handleScreenSharingEnable(currentState, enable);
}
@Override
protected @NonNull WebRtcServiceState handleSendIceCandidates(@NonNull WebRtcServiceState currentState,
@NonNull WebRtcData.CallMetadata callMetadata,

View File

@@ -5,6 +5,8 @@ import android.media.AudioManager;
import androidx.annotation.NonNull;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink;
import org.thoughtcrime.securesms.ringrtc.Camera;
import org.thoughtcrime.securesms.ringrtc.CameraState;
import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState;
import org.thoughtcrime.securesms.util.ServiceUtil;
@@ -109,6 +111,11 @@ public abstract class DeviceAwareActionProcessor extends WebRtcActionProcessor {
public @NonNull WebRtcServiceState handleCameraSwitchCompleted(@NonNull WebRtcServiceState currentState, @NonNull CameraState newCameraState) {
Log.i(tag, "handleCameraSwitchCompleted():");
BroadcastVideoSink localSink = currentState.getVideoState().getLocalSink();
if (localSink != null) {
localSink.setRotateToRightSide(newCameraState.getActiveDirection() == CameraState.Direction.BACK);
}
return currentState.builder()
.changeLocalDeviceState()
.cameraState(newCameraState)

View File

@@ -93,10 +93,13 @@ public class GroupActionProcessor extends DeviceAwareActionProcessor {
VideoTrack videoTrack = device.getVideoTrack();
if (videoTrack != null) {
videoSink = (callParticipant != null && callParticipant.getVideoSink().getEglBase() != null) ? callParticipant.getVideoSink()
: new BroadcastVideoSink(currentState.getVideoState().requireEglBase());
: new BroadcastVideoSink(currentState.getVideoState().requireEglBase(),
true,
true,
currentState.getLocalDeviceState().getOrientation().getDegrees());
videoTrack.addSink(videoSink);
} else {
videoSink = new BroadcastVideoSink(null);
videoSink = new BroadcastVideoSink();
}
builder.putParticipant(callParticipantId,
@@ -109,6 +112,7 @@ public class GroupActionProcessor extends DeviceAwareActionProcessor {
device.getSpeakerTime(),
device.getMediaKeysReceived(),
device.getAddedTime(),
Boolean.TRUE.equals(device.getPresenting()),
seen.contains(recipient) ? CallParticipant.DeviceOrdinal.SECONDARY
: CallParticipant.DeviceOrdinal.PRIMARY));
@@ -318,11 +322,6 @@ public class GroupActionProcessor extends DeviceAwareActionProcessor {
return terminateGroupCall(currentState);
}
@Override
protected @NonNull WebRtcServiceState handleOrientationChanged(@NonNull WebRtcServiceState currentState, int orientationDegrees) {
return currentState;
}
public synchronized @NonNull WebRtcServiceState terminateGroupCall(@NonNull WebRtcServiceState currentState) {
return terminateGroupCall(currentState, true);
}

View File

@@ -8,7 +8,6 @@ import com.annimon.stream.Stream;
import org.signal.core.util.logging.Log;
import org.signal.ringrtc.CallException;
import org.signal.ringrtc.CallManager;
import org.signal.ringrtc.GroupCall;
import org.signal.ringrtc.PeekInfo;
import org.thoughtcrime.securesms.BuildConfig;
@@ -123,7 +122,17 @@ public class GroupPreJoinActionProcessor extends GroupActionProcessor {
.clearParticipantMap();
for (Recipient recipient : callParticipants) {
builder.putParticipant(recipient, CallParticipant.createRemote(new CallParticipantId(recipient), recipient, null, new BroadcastVideoSink(null), true, true, 0, false, 0, CallParticipant.DeviceOrdinal.PRIMARY));
builder.putParticipant(recipient, CallParticipant.createRemote(new CallParticipantId(recipient),
recipient,
null,
new BroadcastVideoSink(),
true,
true,
0,
false,
0,
false,
CallParticipant.DeviceOrdinal.PRIMARY));
}
return builder.build();

View File

@@ -10,7 +10,6 @@ import org.signal.core.util.logging.Log;
import org.signal.ringrtc.CallException;
import org.signal.ringrtc.CallId;
import org.signal.ringrtc.CallManager;
import org.thoughtcrime.securesms.components.webrtc.OrientationAwareVideoSink;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
@@ -24,7 +23,6 @@ import org.thoughtcrime.securesms.ringrtc.RemotePeer;
import org.thoughtcrime.securesms.service.webrtc.state.VideoState;
import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState;
import org.thoughtcrime.securesms.util.NetworkUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.webrtc.locks.LockManager;
import org.webrtc.PeerConnection;
import org.whispersystems.signalservice.api.messages.calls.AnswerMessage;
@@ -89,8 +87,8 @@ public class IncomingCallActionProcessor extends DeviceAwareActionProcessor {
webRtcInteractor.getCallManager().proceed(activePeer.getCallId(),
context,
videoState.requireEglBase(),
new OrientationAwareVideoSink(videoState.requireLocalSink()),
new OrientationAwareVideoSink(callParticipant.getVideoSink()),
videoState.requireLocalSink(),
callParticipant.getVideoSink(),
videoState.requireCamera(),
iceServers,
hideIp,
@@ -198,6 +196,11 @@ public class IncomingCallActionProcessor extends DeviceAwareActionProcessor {
return activeCallDelegate.handleRemoteVideoEnable(currentState, enable);
}
@Override
protected @NonNull WebRtcServiceState handleScreenSharingEnable(@NonNull WebRtcServiceState currentState, boolean enable) {
return activeCallDelegate.handleScreenSharingEnable(currentState, enable);
}
@Override
protected @NonNull WebRtcServiceState handleReceivedOfferWhileActive(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) {
return activeCallDelegate.handleReceivedOfferWhileActive(currentState, remotePeer);

View File

@@ -10,7 +10,6 @@ import org.signal.core.util.logging.Log;
import org.signal.ringrtc.CallException;
import org.signal.ringrtc.CallId;
import org.signal.ringrtc.CallManager;
import org.thoughtcrime.securesms.components.webrtc.OrientationAwareVideoSink;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.events.CallParticipant;
@@ -120,8 +119,8 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor {
webRtcInteractor.getCallManager().proceed(activePeer.getCallId(),
context,
videoState.requireEglBase(),
new OrientationAwareVideoSink(videoState.requireLocalSink()),
new OrientationAwareVideoSink(callParticipant.getVideoSink()),
videoState.requireLocalSink(),
callParticipant.getVideoSink(),
videoState.requireCamera(),
iceServers,
isAlwaysTurn,
@@ -198,6 +197,11 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor {
return activeCallDelegate.handleRemoteVideoEnable(currentState, enable);
}
@Override
protected @NonNull WebRtcServiceState handleScreenSharingEnable(@NonNull WebRtcServiceState currentState, boolean enable) {
return activeCallDelegate.handleScreenSharingEnable(currentState, enable);
}
@Override
protected @NonNull WebRtcServiceState handleLocalHangup(@NonNull WebRtcServiceState currentState) {
return activeCallDelegate.handleLocalHangup(currentState);

View File

@@ -394,6 +394,10 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
return p.handleRemoteVideoEnable(s, true);
case REMOTE_VIDEO_DISABLE:
return p.handleRemoteVideoEnable(s, false);
case REMOTE_SHARING_SCREEN_ENABLE:
return p.handleScreenSharingEnable(s, true);
case REMOTE_SHARING_SCREEN_DISABLE:
return p.handleScreenSharingEnable(s, false);
case ENDED_REMOTE_HANGUP:
case ENDED_REMOTE_HANGUP_NEED_PERMISSION:
case ENDED_REMOTE_HANGUP_ACCEPTED:
@@ -641,6 +645,11 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
process((s, p) -> p.handleGroupCallEnded(s, groupCall.hashCode(), groupCallEndReason));
}
@Override
public void onFullyInitialized() {
process((s, p) -> p.handleOrientationChanged(s, s.getLocalDeviceState().getOrientation().getDegrees()));
}
@Override
public void onCameraSwitchCompleted(@NonNull final CameraState newCameraState) {
process((s, p) -> p.handleCameraSwitchCompleted(s, newCameraState));

View File

@@ -12,6 +12,7 @@ import org.signal.ringrtc.CallId;
import org.signal.ringrtc.CallManager;
import org.signal.ringrtc.GroupCall;
import org.thoughtcrime.securesms.components.sensors.Orientation;
import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.events.CallParticipant;
@@ -276,6 +277,11 @@ public abstract class WebRtcActionProcessor {
return currentState;
}
protected @NonNull WebRtcServiceState handleScreenSharingEnable(@NonNull WebRtcServiceState currentState, boolean enable) {
Log.i(tag, "handleScreenSharingEnable not processed");
return currentState;
}
protected @NonNull WebRtcServiceState handleReceivedHangup(@NonNull WebRtcServiceState currentState,
@NonNull CallMetadata callMetadata,
@NonNull HangupMetadata hangupMetadata)
@@ -454,6 +460,15 @@ public abstract class WebRtcActionProcessor {
camera.setOrientation(orientationDegrees);
}
BroadcastVideoSink sink = currentState.getVideoState().getLocalSink();
if (sink != null) {
sink.setDeviceOrientationDegrees(orientationDegrees);
}
for (CallParticipant callParticipant : currentState.getCallInfoState().getRemoteCallParticipants()) {
callParticipant.getVideoSink().setDeviceOrientationDegrees(orientationDegrees);
}
return currentState.builder()
.changeLocalDeviceState()
.setOrientation(Orientation.fromDegrees(orientationDegrees))

View File

@@ -6,7 +6,6 @@ import androidx.annotation.NonNull;
import org.signal.core.util.ThreadUtil;
import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink;
import org.thoughtcrime.securesms.components.webrtc.OrientationAwareVideoSink;
import org.thoughtcrime.securesms.ringrtc.Camera;
import org.thoughtcrime.securesms.ringrtc.CameraEventListener;
import org.thoughtcrime.securesms.ringrtc.CameraState;
@@ -33,7 +32,10 @@ public final class WebRtcVideoUtil {
ThreadUtil.runOnMainSync(() -> {
EglBase eglBase = EglBase.create();
BroadcastVideoSink localSink = new BroadcastVideoSink(eglBase);
BroadcastVideoSink localSink = new BroadcastVideoSink(eglBase,
true,
false,
currentState.getLocalDeviceState().getOrientation().getDegrees());
Camera camera = new Camera(context, cameraEventListener, eglBase, CameraState.Direction.FRONT);
camera.setOrientation(currentState.getLocalDeviceState().getOrientation().getDegrees());
@@ -104,7 +106,7 @@ public final class WebRtcVideoUtil {
public static @NonNull WebRtcServiceState initializeVanityCamera(@NonNull WebRtcServiceState currentState) {
Camera camera = currentState.getVideoState().requireCamera();
VideoSink sink = new OrientationAwareVideoSink(currentState.getVideoState().requireLocalSink());
VideoSink sink = currentState.getVideoState().requireLocalSink();
if (camera.hasCapturer()) {
camera.initCapturer(new CapturerObserver() {