Merge pull request #1774 from nextcloud/feature/1773/update-webrtc-library

Android update WebRTC library
This commit is contained in:
Tim Krueger 2022-02-23 13:20:09 +01:00 committed by GitHub
commit 89f64b392a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 196 additions and 196 deletions

View File

@ -4,9 +4,11 @@
* @author Mario Danic
* @author Andy Scherzinger
* @author Marcel Hibbe
* @author Tim Krüger
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
* Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -34,6 +36,20 @@ configurations {
ktlint
}
def urlFile = { url, fileName ->
File file = new File("$buildDir/download/${fileName}")
file.parentFile.mkdirs()
if (!file.exists()) {
new URL(url).withInputStream { downloadStream ->
file.withOutputStream { fileOut ->
fileOut << downloadStream
}
}
}
files(file.absolutePath)
}
android {
compileSdkVersion 30
buildToolsVersion '30.0.3'
@ -134,6 +150,7 @@ android {
}
check.dependsOn 'spotbugsGplayDebugReport', 'lint', 'ktlint', 'detekt'
lint.dependsOn 'preBuild'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
@ -240,7 +257,8 @@ dependencies {
kapt "com.jakewharton:butterknife-compiler:${butterknifeVersion}"
implementation 'eu.davidea:flexible-adapter:5.1.0'
implementation 'eu.davidea:flexible-adapter-ui:1.0.0'
implementation 'org.webrtc:google-webrtc:1.0.32006'
implementation urlFile('https://github.com/nextcloud-releases/talk-clients-webrtc/releases/download/96.4664.0-RC1/libwebrtc-96.4664.0.aar',
'libwebrtc-96.4664.0.aar')
implementation 'com.yarolegovich:lovely-dialog:1.1.1'
implementation 'com.yarolegovich:mp:1.1.6'
implementation 'me.zhanghai.android.effortlesspermissions:library:1.1.0'

View File

@ -93,7 +93,7 @@ import com.nextcloud.talk.utils.power.PowerManagerUtils;
import com.nextcloud.talk.utils.preferences.AppPreferences;
import com.nextcloud.talk.utils.singletons.ApplicationWideCurrentRoomHolder;
import com.nextcloud.talk.webrtc.MagicAudioManager;
import com.nextcloud.talk.webrtc.MagicPeerConnectionWrapper;
import com.nextcloud.talk.webrtc.PeerConnectionWrapper;
import com.nextcloud.talk.webrtc.MagicWebRTCUtils;
import com.nextcloud.talk.webrtc.MagicWebSocketInstance;
import com.nextcloud.talk.webrtc.WebSocketConnectionHelper;
@ -213,9 +213,9 @@ public class CallActivity extends CallBaseActivity {
private UserEntity conversationUser;
private String conversationName;
private String callSession;
private MediaStream localMediaStream;
private MediaStream localStream;
private String credentials;
private List<MagicPeerConnectionWrapper> magicPeerConnectionWrapperList = new ArrayList<>();
private List<PeerConnectionWrapper> peerConnectionWrapperList = new ArrayList<>();
private Map<String, Participant> participantMap = new HashMap<>();
private boolean videoOn = false;
@ -408,7 +408,7 @@ public class CallActivity extends CallBaseActivity {
audioConstraints = new MediaConstraints();
videoConstraints = new MediaConstraints();
localMediaStream = peerConnectionFactory.createLocalMediaStream("NCMS");
localStream = peerConnectionFactory.createLocalMediaStream("NCMS");
// Create and audio manager that will take care of audio routing,
// audio modes, audio device enumeration etc.
@ -781,7 +781,7 @@ public class CallActivity extends CallBaseActivity {
videoCapturer.initialize(surfaceTextureHelper, getApplicationContext(), videoSource.getCapturerObserver());
}
localVideoTrack = peerConnectionFactory.createVideoTrack("NCv0", videoSource);
localMediaStream.addTrack(localVideoTrack);
localStream.addTrack(localVideoTrack);
localVideoTrack.setEnabled(false);
localVideoTrack.addSink(binding.selfVideoRenderer);
}
@ -791,7 +791,7 @@ public class CallActivity extends CallBaseActivity {
audioSource = peerConnectionFactory.createAudioSource(audioConstraints);
localAudioTrack = peerConnectionFactory.createAudioTrack("NCa0", audioSource);
localAudioTrack.setEnabled(false);
localMediaStream.addTrack(localAudioTrack);
localStream.addTrack(localAudioTrack);
}
private VideoCapturer createCameraCapturer(CameraEnumerator enumerator) {
@ -963,8 +963,8 @@ public class CallActivity extends CallBaseActivity {
}
}
if (localMediaStream != null && localMediaStream.videoTracks.size() > 0) {
localMediaStream.videoTracks.get(0).setEnabled(enable);
if (localStream != null && localStream.videoTracks.size() > 0) {
localStream.videoTracks.get(0).setEnabled(enable);
}
if (enable) {
binding.selfVideoRenderer.setVisibility(View.VISIBLE);
@ -980,20 +980,20 @@ public class CallActivity extends CallBaseActivity {
binding.microphoneButton.setAlpha(0.7f);
}
if (localMediaStream != null && localMediaStream.audioTracks.size() > 0) {
localMediaStream.audioTracks.get(0).setEnabled(enable);
if (localStream != null && localStream.audioTracks.size() > 0) {
localStream.audioTracks.get(0).setEnabled(enable);
}
}
if (isConnectionEstablished() && magicPeerConnectionWrapperList != null) {
if (isConnectionEstablished() && peerConnectionWrapperList != null) {
if (!hasMCU) {
for (MagicPeerConnectionWrapper magicPeerConnectionWrapper : magicPeerConnectionWrapperList) {
magicPeerConnectionWrapper.sendChannelData(new DataChannelMessage(message));
for (PeerConnectionWrapper peerConnectionWrapper : peerConnectionWrapperList) {
peerConnectionWrapper.sendChannelData(new DataChannelMessage(message));
}
} else {
for (MagicPeerConnectionWrapper magicPeerConnectionWrapper : magicPeerConnectionWrapperList) {
if (magicPeerConnectionWrapper.getSessionId().equals(webSocketClient.getSessionId())) {
magicPeerConnectionWrapper.sendChannelData(new DataChannelMessage(message));
for (PeerConnectionWrapper peerConnectionWrapper : peerConnectionWrapperList) {
if (peerConnectionWrapper.getSessionId().equals(webSocketClient.getSessionId())) {
peerConnectionWrapper.sendChannelData(new DataChannelMessage(message));
break;
}
}
@ -1517,7 +1517,7 @@ public class CallActivity extends CallBaseActivity {
private void processMessage(NCSignalingMessage ncSignalingMessage) {
if (ncSignalingMessage.getRoomType().equals("video") || ncSignalingMessage.getRoomType().equals("screen")) {
MagicPeerConnectionWrapper magicPeerConnectionWrapper =
PeerConnectionWrapper peerConnectionWrapper =
getPeerConnectionWrapperForSessionIdAndType(ncSignalingMessage.getFrom(),
ncSignalingMessage.getRoomType(), false);
@ -1535,7 +1535,7 @@ public class CallActivity extends CallBaseActivity {
break;
case "offer":
case "answer":
magicPeerConnectionWrapper.setNick(ncSignalingMessage.getPayload().getNick());
peerConnectionWrapper.setNick(ncSignalingMessage.getPayload().getNick());
SessionDescription sessionDescriptionWithPreferredCodec;
String sessionDescriptionStringWithPreferredCodec = MagicWebRTCUtils.preferCodec
@ -1546,8 +1546,8 @@ public class CallActivity extends CallBaseActivity {
SessionDescription.Type.fromCanonicalForm(type),
sessionDescriptionStringWithPreferredCodec);
if (magicPeerConnectionWrapper.getPeerConnection() != null) {
magicPeerConnectionWrapper.getPeerConnection().setRemoteDescription(magicPeerConnectionWrapper
if (peerConnectionWrapper.getPeerConnection() != null) {
peerConnectionWrapper.getPeerConnection().setRemoteDescription(peerConnectionWrapper
.getMagicSdpObserver(), sessionDescriptionWithPreferredCodec);
}
break;
@ -1555,10 +1555,10 @@ public class CallActivity extends CallBaseActivity {
NCIceCandidate ncIceCandidate = ncSignalingMessage.getPayload().getIceCandidate();
IceCandidate iceCandidate = new IceCandidate(ncIceCandidate.getSdpMid(),
ncIceCandidate.getSdpMLineIndex(), ncIceCandidate.getCandidate());
magicPeerConnectionWrapper.addCandidate(iceCandidate);
peerConnectionWrapper.addCandidate(iceCandidate);
break;
case "endOfCandidates":
magicPeerConnectionWrapper.drainIceCandidates();
peerConnectionWrapper.drainIceCandidates();
break;
default:
break;
@ -1608,7 +1608,7 @@ public class CallActivity extends CallBaseActivity {
peerConnectionFactory = null;
}
localMediaStream = null;
localAudioTrack = null;
localVideoTrack = null;
@ -1618,8 +1618,16 @@ public class CallActivity extends CallBaseActivity {
}
}
for (int i = 0; i < magicPeerConnectionWrapperList.size(); i++) {
endPeerConnection(magicPeerConnectionWrapperList.get(i).getSessionId(), false);
for (int i = 0; i < peerConnectionWrapperList.size(); i++) {
endPeerConnection(peerConnectionWrapperList.get(i).getSessionId(), false);
}
if(localStream != null) {
localStream.dispose();
localStream = null;
Log.d(TAG, "Disposed localStream");
} else {
Log.d(TAG, "localStream is null");
}
hangupNetworkCalls(shutDownView);
@ -1703,9 +1711,9 @@ public class CallActivity extends CallBaseActivity {
}
}
for (MagicPeerConnectionWrapper magicPeerConnectionWrapper : magicPeerConnectionWrapperList) {
if (!magicPeerConnectionWrapper.isMCUPublisher()) {
oldSessions.add(magicPeerConnectionWrapper.getSessionId());
for (PeerConnectionWrapper peerConnectionWrapper : peerConnectionWrapperList) {
if (!peerConnectionWrapper.isMCUPublisher()) {
oldSessions.add(peerConnectionWrapper.getSessionId());
}
}
@ -1775,86 +1783,86 @@ public class CallActivity extends CallBaseActivity {
});
}
private void deleteMagicPeerConnection(MagicPeerConnectionWrapper magicPeerConnectionWrapper) {
magicPeerConnectionWrapper.removePeerConnection();
magicPeerConnectionWrapperList.remove(magicPeerConnectionWrapper);
private void deletePeerConnection(PeerConnectionWrapper peerConnectionWrapper) {
peerConnectionWrapper.removePeerConnection();
peerConnectionWrapperList.remove(peerConnectionWrapper);
}
private MagicPeerConnectionWrapper getPeerConnectionWrapperForSessionId(String sessionId, String type) {
for (int i = 0; i < magicPeerConnectionWrapperList.size(); i++) {
if (magicPeerConnectionWrapperList.get(i).getSessionId().equals(sessionId) && magicPeerConnectionWrapperList.get(i).getVideoStreamType().equals(type)) {
return magicPeerConnectionWrapperList.get(i);
private PeerConnectionWrapper getPeerConnectionWrapperForSessionId(String sessionId, String type) {
for (int i = 0; i < peerConnectionWrapperList.size(); i++) {
if (peerConnectionWrapperList.get(i).getSessionId().equals(sessionId) && peerConnectionWrapperList.get(i).getVideoStreamType().equals(type)) {
return peerConnectionWrapperList.get(i);
}
}
return null;
}
private MagicPeerConnectionWrapper getPeerConnectionWrapperForSessionIdAndType(String sessionId, String type, boolean publisher) {
MagicPeerConnectionWrapper magicPeerConnectionWrapper;
if ((magicPeerConnectionWrapper = getPeerConnectionWrapperForSessionId(sessionId, type)) != null) {
return magicPeerConnectionWrapper;
private PeerConnectionWrapper getPeerConnectionWrapperForSessionIdAndType(String sessionId, String type, boolean publisher) {
PeerConnectionWrapper peerConnectionWrapper;
if ((peerConnectionWrapper = getPeerConnectionWrapperForSessionId(sessionId, type)) != null) {
return peerConnectionWrapper;
} else {
if (hasMCU && publisher) {
magicPeerConnectionWrapper = new MagicPeerConnectionWrapper(peerConnectionFactory,
iceServers,
sdpConstraintsForMCU,
sessionId,
callSession,
localMediaStream,
true,
true,
type);
peerConnectionWrapper = new PeerConnectionWrapper(peerConnectionFactory,
iceServers,
sdpConstraintsForMCU,
sessionId,
callSession,
localStream,
true,
true,
type);
} else if (hasMCU) {
magicPeerConnectionWrapper = new MagicPeerConnectionWrapper(peerConnectionFactory,
iceServers,
sdpConstraints,
sessionId,
callSession,
null,
false,
true,
type);
peerConnectionWrapper = new PeerConnectionWrapper(peerConnectionFactory,
iceServers,
sdpConstraints,
sessionId,
callSession,
null,
false,
true,
type);
} else {
if (!"screen".equals(type)) {
magicPeerConnectionWrapper = new MagicPeerConnectionWrapper(peerConnectionFactory,
iceServers,
sdpConstraints,
sessionId,
callSession,
localMediaStream,
false,
false,
type);
peerConnectionWrapper = new PeerConnectionWrapper(peerConnectionFactory,
iceServers,
sdpConstraints,
sessionId,
callSession,
localStream,
false,
false,
type);
} else {
magicPeerConnectionWrapper = new MagicPeerConnectionWrapper(peerConnectionFactory,
iceServers,
sdpConstraints,
sessionId,
callSession,
null,
false,
false,
type);
peerConnectionWrapper = new PeerConnectionWrapper(peerConnectionFactory,
iceServers,
sdpConstraints,
sessionId,
callSession,
null,
false,
false,
type);
}
}
magicPeerConnectionWrapperList.add(magicPeerConnectionWrapper);
peerConnectionWrapperList.add(peerConnectionWrapper);
if (publisher) {
startSendingNick();
}
return magicPeerConnectionWrapper;
return peerConnectionWrapper;
}
}
private List<MagicPeerConnectionWrapper> getPeerConnectionWrapperListForSessionId(String sessionId) {
List<MagicPeerConnectionWrapper> internalList = new ArrayList<>();
for (MagicPeerConnectionWrapper magicPeerConnectionWrapper : magicPeerConnectionWrapperList) {
if (magicPeerConnectionWrapper.getSessionId().equals(sessionId)) {
internalList.add(magicPeerConnectionWrapper);
private List<PeerConnectionWrapper> getPeerConnectionWrapperListForSessionId(String sessionId) {
List<PeerConnectionWrapper> internalList = new ArrayList<>();
for (PeerConnectionWrapper peerConnectionWrapper : peerConnectionWrapperList) {
if (peerConnectionWrapper.getSessionId().equals(sessionId)) {
internalList.add(peerConnectionWrapper);
}
}
@ -1862,15 +1870,15 @@ public class CallActivity extends CallBaseActivity {
}
private void endPeerConnection(String sessionId, boolean justScreen) {
List<MagicPeerConnectionWrapper> magicPeerConnectionWrappers;
MagicPeerConnectionWrapper magicPeerConnectionWrapper;
if (!(magicPeerConnectionWrappers = getPeerConnectionWrapperListForSessionId(sessionId)).isEmpty()) {
for (int i = 0; i < magicPeerConnectionWrappers.size(); i++) {
magicPeerConnectionWrapper = magicPeerConnectionWrappers.get(i);
if (magicPeerConnectionWrapper.getSessionId().equals(sessionId)) {
if (magicPeerConnectionWrapper.getVideoStreamType().equals("screen") || !justScreen) {
List<PeerConnectionWrapper> peerConnectionWrappers;
PeerConnectionWrapper peerConnectionWrapper;
if (!(peerConnectionWrappers = getPeerConnectionWrapperListForSessionId(sessionId)).isEmpty()) {
for (int i = 0; i < peerConnectionWrappers.size(); i++) {
peerConnectionWrapper = peerConnectionWrappers.get(i);
if (peerConnectionWrapper.getSessionId().equals(sessionId)) {
if (peerConnectionWrapper.getVideoStreamType().equals("screen") || !justScreen) {
runOnUiThread(() -> removeMediaStream(sessionId));
deleteMagicPeerConnection(magicPeerConnectionWrapper);
deletePeerConnection(peerConnectionWrapper);
}
}
}
@ -1982,10 +1990,10 @@ public class CallActivity extends CallBaseActivity {
nickChangedPayload.put("userid", conversationUser.getUserId());
nickChangedPayload.put("name", conversationUser.getDisplayName());
dataChannelMessage.setPayload(nickChangedPayload);
final MagicPeerConnectionWrapper magicPeerConnectionWrapper;
for (int i = 0; i < magicPeerConnectionWrapperList.size(); i++) {
if (magicPeerConnectionWrapperList.get(i).isMCUPublisher()) {
magicPeerConnectionWrapper = magicPeerConnectionWrapperList.get(i);
final PeerConnectionWrapper peerConnectionWrapper;
for (int i = 0; i < peerConnectionWrapperList.size(); i++) {
if (peerConnectionWrapperList.get(i).isMCUPublisher()) {
peerConnectionWrapper = peerConnectionWrapperList.get(i);
Observable
.interval(1, TimeUnit.SECONDS)
.repeatUntil(() -> (!isConnectionEstablished() || isDestroyed()))
@ -1998,7 +2006,7 @@ public class CallActivity extends CallBaseActivity {
@Override
public void onNext(@io.reactivex.annotations.NonNull Long aLong) {
magicPeerConnectionWrapper.sendNickChannelData(dataChannelMessage);
peerConnectionWrapper.sendNickChannelData(dataChannelMessage);
}
@Override

View File

@ -2,6 +2,8 @@
* Nextcloud Talk application
*
* @author Mario Danic
* @author Tim Krüger
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
*
* This program is free software: you can redistribute it and/or modify
@ -37,6 +39,7 @@ import com.nextcloud.talk.models.json.signaling.DataChannelMessageNick;
import com.nextcloud.talk.models.json.signaling.NCIceCandidate;
import org.greenrobot.eventbus.EventBus;
import org.webrtc.AudioTrack;
import org.webrtc.DataChannel;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
@ -46,81 +49,87 @@ import org.webrtc.PeerConnectionFactory;
import org.webrtc.RtpReceiver;
import org.webrtc.SdpObserver;
import org.webrtc.SessionDescription;
import org.webrtc.VideoTrack;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import javax.inject.Inject;
import androidx.annotation.Nullable;
import autodagger.AutoInjector;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
@AutoInjector(NextcloudTalkApplication.class)
public class MagicPeerConnectionWrapper {
private static final String TAG = "MagicPeerConWrapper";
public class PeerConnectionWrapper {
private static final String TAG = PeerConnectionWrapper.class.getCanonicalName();
private List<IceCandidate> iceCandidates = new ArrayList<>();
private PeerConnection peerConnection;
private String sessionId;
private String nick;
private MediaConstraints sdpConstraints;
private DataChannel magicDataChannel;
private MagicSdpObserver magicSdpObserver;
private MediaStream remoteMediaStream;
private final MediaConstraints mediaConstraints;
private DataChannel dataChannel;
private final MagicSdpObserver magicSdpObserver;
private MediaStream remoteStream;
private boolean remoteVideoOn;
private boolean remoteAudioOn;
private final boolean hasInitiated;
private boolean hasInitiated;
private MediaStream localMediaStream;
private boolean isMCUPublisher;
private boolean hasMCU;
private String videoStreamType;
private int connectionAttempts = 0;
private PeerConnection.IceConnectionState peerIceConnectionState;
private final MediaStream localStream;
private final boolean isMCUPublisher;
private final String videoStreamType;
@Inject
Context context;
public MagicPeerConnectionWrapper(PeerConnectionFactory peerConnectionFactory,
List<PeerConnection.IceServer> iceServerList,
MediaConstraints sdpConstraints,
String sessionId, String localSession, @Nullable MediaStream mediaStream,
boolean isMCUPublisher, boolean hasMCU, String videoStreamType) {
public PeerConnectionWrapper(PeerConnectionFactory peerConnectionFactory,
List<PeerConnection.IceServer> iceServerList,
MediaConstraints mediaConstraints,
String sessionId, String localSession, @Nullable MediaStream localStream,
boolean isMCUPublisher, boolean hasMCU, String videoStreamType) {
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
Objects.requireNonNull(NextcloudTalkApplication.Companion.getSharedApplication()).getComponentApplication().inject(this);
this.localMediaStream = mediaStream;
this.localStream = localStream;
this.videoStreamType = videoStreamType;
this.hasMCU = hasMCU;
this.sessionId = sessionId;
this.sdpConstraints = sdpConstraints;
this.mediaConstraints = mediaConstraints;
magicSdpObserver = new MagicSdpObserver();
hasInitiated = sessionId.compareTo(localSession) < 0;
this.isMCUPublisher = isMCUPublisher;
peerConnection = peerConnectionFactory.createPeerConnection(iceServerList, sdpConstraints,
new MagicPeerConnectionObserver());
PeerConnection.RTCConfiguration configuration = new PeerConnection.RTCConfiguration(iceServerList);
configuration.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
peerConnection = peerConnectionFactory.createPeerConnection(configuration, new MagicPeerConnectionObserver());
if (peerConnection != null) {
if (localMediaStream != null) {
peerConnection.addStream(localMediaStream);
if (this.localStream != null) {
List<String> localStreamIds = Collections.singletonList(this.localStream.getId());
for(AudioTrack track : this.localStream.audioTracks) {
peerConnection.addTrack(track, localStreamIds);
}
for(VideoTrack track : this.localStream.videoTracks) {
peerConnection.addTrack(track, localStreamIds);
}
}
if (hasMCU || hasInitiated) {
DataChannel.Init init = new DataChannel.Init();
init.negotiated = false;
magicDataChannel = peerConnection.createDataChannel("status", init);
magicDataChannel.registerObserver(new MagicDataChannelObserver());
dataChannel = peerConnection.createDataChannel("status", init);
dataChannel.registerObserver(new MagicDataChannelObserver());
if (isMCUPublisher) {
peerConnection.createOffer(magicSdpObserver, sdpConstraints);
peerConnection.createOffer(magicSdpObserver, mediaConstraints);
} else if (hasMCU && this.videoStreamType.equals("video")) {
// If the connection type is "screen" the client sharing the screen will send an
// offer; offers should be requested only for videos.
@ -128,7 +137,7 @@ public class MagicPeerConnectionWrapper {
hashMap.put("sessionId", sessionId);
EventBus.getDefault().post(new WebSocketCommunicationEvent("peerReadyForRequestingOffer", hashMap));
} else if (!hasMCU && hasInitiated) {
peerConnection.createOffer(magicSdpObserver, sdpConstraints);
peerConnection.createOffer(magicSdpObserver, mediaConstraints);
}
}
}
@ -139,18 +148,20 @@ public class MagicPeerConnectionWrapper {
}
public void removePeerConnection() {
if (magicDataChannel != null) {
magicDataChannel.dispose();
magicDataChannel = null;
if (dataChannel != null) {
dataChannel.dispose();
dataChannel = null;
Log.d(TAG, "Disposed DataChannel");
} else {
Log.d(TAG, "DataChannel is null.");
}
if (peerConnection != null) {
if (localMediaStream != null) {
peerConnection.removeStream(localMediaStream);
}
peerConnection.close();
peerConnection = null;
Log.d(TAG, "Disposed PeerConnection");
} else {
Log.d(TAG, "PeerConnection is null.");
}
}
@ -179,10 +190,10 @@ public class MagicPeerConnectionWrapper {
public void sendNickChannelData(DataChannelMessageNick dataChannelMessage) {
ByteBuffer buffer;
if (magicDataChannel != null) {
if (dataChannel != null) {
try {
buffer = ByteBuffer.wrap(LoganSquare.serialize(dataChannelMessage).getBytes());
magicDataChannel.send(new DataChannel.Buffer(buffer, false));
dataChannel.send(new DataChannel.Buffer(buffer, false));
} catch (IOException e) {
Log.d(TAG, "Failed to send channel data, attempting regular " + dataChannelMessage);
}
@ -191,10 +202,10 @@ public class MagicPeerConnectionWrapper {
public void sendChannelData(DataChannelMessage dataChannelMessage) {
ByteBuffer buffer;
if (magicDataChannel != null) {
if (dataChannel != null) {
try {
buffer = ByteBuffer.wrap(LoganSquare.serialize(dataChannelMessage).getBytes());
magicDataChannel.send(new DataChannel.Buffer(buffer, false));
dataChannel.send(new DataChannel.Buffer(buffer, false));
} catch (IOException e) {
Log.d(TAG, "Failed to send channel data, attempting regular " + dataChannelMessage);
}
@ -217,7 +228,7 @@ public class MagicPeerConnectionWrapper {
if (!TextUtils.isEmpty(nick)) {
return nick;
} else {
return NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_nick_guest);
return Objects.requireNonNull(NextcloudTalkApplication.Companion.getSharedApplication()).getString(R.string.nc_nick_guest);
}
}
@ -226,14 +237,14 @@ public class MagicPeerConnectionWrapper {
}
private void sendInitialMediaStatus() {
if (localMediaStream != null) {
if (localMediaStream.videoTracks.size() == 1 && localMediaStream.videoTracks.get(0).enabled()) {
if (localStream != null) {
if (localStream.videoTracks.size() == 1 && localStream.videoTracks.get(0).enabled()) {
sendChannelData(new DataChannelMessage("videoOn"));
} else {
sendChannelData(new DataChannelMessage("videoOff"));
}
if (localMediaStream.audioTracks.size() == 1 && localMediaStream.audioTracks.get(0).enabled()) {
if (localStream.audioTracks.size() == 1 && localStream.audioTracks.get(0).enabled()) {
sendChannelData(new DataChannelMessage("audioOn"));
} else {
sendChannelData(new DataChannelMessage("audioOff"));
@ -254,8 +265,8 @@ public class MagicPeerConnectionWrapper {
@Override
public void onStateChange() {
if (magicDataChannel != null && magicDataChannel.state().equals(DataChannel.State.OPEN) &&
magicDataChannel.label().equals("status")) {
if (dataChannel != null && dataChannel.state().equals(DataChannel.State.OPEN) &&
dataChannel.label().equals("status")) {
sendInitialMediaStatus();
}
}
@ -292,23 +303,18 @@ public class MagicPeerConnectionWrapper {
.NICK_CHANGE, sessionId, payloadHashMap.get("name"), null, videoStreamType));
}
}
} else if ("audioOn".equals(dataChannelMessage.getType())) {
remoteAudioOn = true;
EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
.AUDIO_CHANGE, sessionId, null, remoteAudioOn, videoStreamType));
.AUDIO_CHANGE, sessionId, null, TRUE, videoStreamType));
} else if ("audioOff".equals(dataChannelMessage.getType())) {
remoteAudioOn = false;
EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
.AUDIO_CHANGE, sessionId, null, remoteAudioOn, videoStreamType));
.AUDIO_CHANGE, sessionId, null, FALSE, videoStreamType));
} else if ("videoOn".equals(dataChannelMessage.getType())) {
remoteVideoOn = true;
EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
.VIDEO_CHANGE, sessionId, null, remoteVideoOn, videoStreamType));
.VIDEO_CHANGE, sessionId, null, TRUE, videoStreamType));
} else if ("videoOff".equals(dataChannelMessage.getType())) {
remoteVideoOn = false;
EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
.VIDEO_CHANGE, sessionId, null, remoteVideoOn, videoStreamType));
.VIDEO_CHANGE, sessionId, null, FALSE, videoStreamType));
}
} catch (IOException e) {
Log.d(TAG, "Failed to parse data channel message");
@ -316,26 +322,6 @@ public class MagicPeerConnectionWrapper {
}
}
private void restartIce() {
if (connectionAttempts <= 5) {
if (!hasMCU || isMCUPublisher) {
MediaConstraints.KeyValuePair iceRestartConstraint =
new MediaConstraints.KeyValuePair("IceRestart", "true");
if (sdpConstraints.mandatory.contains(iceRestartConstraint)) {
sdpConstraints.mandatory.add(iceRestartConstraint);
}
peerConnection.createOffer(magicSdpObserver, sdpConstraints);
} else {
// we have an MCU and this is not the publisher
// Do something if we have an MCU
}
connectionAttempts++;
}
}
private class MagicPeerConnectionObserver implements PeerConnection.Observer {
@Override
@ -344,16 +330,12 @@ public class MagicPeerConnectionWrapper {
@Override
public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
peerIceConnectionState = iceConnectionState;
Log.d("iceConnectionChangeTo: ", iceConnectionState.name() + " over " + peerConnection.hashCode() + " " + sessionId);
if (iceConnectionState.equals(PeerConnection.IceConnectionState.CONNECTED)) {
connectionAttempts = 0;
/*EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
.PEER_CONNECTED, sessionId, null, null));*/
if (!isMCUPublisher) {
EventBus.getDefault().post(new MediaStreamEvent(remoteMediaStream, sessionId, videoStreamType));
EventBus.getDefault().post(new MediaStreamEvent(remoteStream, sessionId, videoStreamType));
}
if (hasInitiated) {
@ -363,11 +345,7 @@ public class MagicPeerConnectionWrapper {
} else if (iceConnectionState.equals(PeerConnection.IceConnectionState.CLOSED)) {
EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
.PEER_CLOSED, sessionId, null, null, videoStreamType));
connectionAttempts = 0;
} else if (iceConnectionState.equals(PeerConnection.IceConnectionState.FAILED)) {
/*if (MerlinTheWizard.isConnectedToInternet() && connectionAttempts < 5) {
restartIce();
}*/
if (isMCUPublisher) {
EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType.PUBLISHER_FAILED, sessionId, null, null, null));
}
@ -401,7 +379,7 @@ public class MagicPeerConnectionWrapper {
@Override
public void onAddStream(MediaStream mediaStream) {
remoteMediaStream = mediaStream;
remoteStream = mediaStream;
}
@Override
@ -414,8 +392,8 @@ public class MagicPeerConnectionWrapper {
@Override
public void onDataChannel(DataChannel dataChannel) {
if (dataChannel.label().equals("status") || dataChannel.label().equals("JanusDataChannel")) {
magicDataChannel = dataChannel;
magicDataChannel.registerObserver(new MagicDataChannelObserver());
PeerConnectionWrapper.this.dataChannel = dataChannel;
PeerConnectionWrapper.this.dataChannel.registerObserver(new MagicDataChannelObserver());
}
}
@ -466,7 +444,7 @@ public class MagicPeerConnectionWrapper {
public void onSetSuccess() {
if (peerConnection != null) {
if (peerConnection.getLocalDescription() == null) {
peerConnection.createAnswer(magicSdpObserver, sdpConstraints);
peerConnection.createAnswer(magicSdpObserver, mediaConstraints);
}
if (peerConnection.getRemoteDescription() != null) {
@ -475,8 +453,4 @@ public class MagicPeerConnectionWrapper {
}
}
}
public PeerConnection.IceConnectionState getPeerIceConnectionState() {
return peerIceConnectionState;
}
}

View File

@ -56,12 +56,12 @@ end
# run Lint
puts "running Lint..."
system './gradlew --console=plain clean lintGplayDebug'
system './gradlew --console=plain lintGplayDebug'
# confirm that Lint ran w/out error
result = $?.to_i
if result != 0
puts "FAIL: failed to run ./gradlew --console=plain clean lintGplayDebug"
puts "FAIL: failed to run ./gradlew --console=plain lintGplayDebug"
exit 1
end