Some work

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2017-11-08 20:06:33 +01:00
parent 526e4d1f9e
commit f26c38444b

View File

@ -20,21 +20,39 @@
package com.nextcloud.talk.activities;
import android.Manifest;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import com.bluelinelabs.conductor.Conductor;
import com.bluelinelabs.conductor.Router;
import com.bluelinelabs.conductor.RouterTransaction;
import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler;
import com.gun0912.tedpermission.PermissionListener;
import com.gun0912.tedpermission.TedPermission;
import com.nextcloud.talk.R;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.CallController;
import com.nextcloud.talk.utils.bundle.BundleBuilder;
import com.nextcloud.talk.webrtc.MagicPeerConnectionObserver;
import com.nextcloud.talk.webrtc.MagicSdpObserver;
import org.webrtc.AudioSource;
import org.webrtc.AudioTrack;
import org.webrtc.Camera1Enumerator;
import org.webrtc.CameraEnumerator;
import org.webrtc.IceCandidate;
import org.webrtc.Logging;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.SessionDescription;
import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoRenderer;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;
import java.util.ArrayList;
import java.util.List;
import autodagger.AutoInjector;
import butterknife.BindView;
@ -44,14 +62,29 @@ import butterknife.ButterKnife;
public class CallActivity extends AppCompatActivity {
private static final String TAG = "CallActivity";
@BindView(R.id.controller_container)
ViewGroup container;
@BindView(R.id.pip_video_view)
SurfaceViewRenderer pipVideoView;
private Router router;
@BindView(R.id.fullscreen_video_view)
SurfaceViewRenderer fullScreenVideoView;
private String roomToken;
private String userDisplayName;
PeerConnectionFactory peerConnectionFactory;
MediaConstraints audioConstraints;
MediaConstraints videoConstraints;
MediaConstraints sdpConstraints;
VideoSource videoSource;
VideoTrack localVideoTrack;
AudioSource audioSource;
AudioTrack localAudioTrack;
VideoRenderer localRenderer;
VideoRenderer remoteRenderer;
PeerConnection localPeer, remotePeer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -70,26 +103,221 @@ public class CallActivity extends AppCompatActivity {
roomToken = getIntent().getExtras().getString("roomToken", "");
userDisplayName = getIntent().getExtras().getString("userDisplayName", "");
router = Conductor.attachRouter(this, container, savedInstanceState);
if (!router.hasRootController()) {
BundleBuilder bundleBuilder = new BundleBuilder(new Bundle());
bundleBuilder.putString("roomToken", roomToken);
bundleBuilder.putString("userDisplayName", userDisplayName);
PermissionListener permissionlistener = new PermissionListener() {
@Override
public void onPermissionGranted() {
start();
call();
}
router.setRoot(RouterTransaction.with(new CallController(bundleBuilder.build()))
.popChangeHandler(new SimpleSwapChangeHandler())
.pushChangeHandler((new SimpleSwapChangeHandler())));
@Override
public void onPermissionDenied(ArrayList<String> deniedPermissions) {
}
};
TedPermission.with(this)
.setPermissionListener(permissionlistener)
.setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]")
.setPermissions(android.Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO,
Manifest.permission.MODIFY_AUDIO_SETTINGS, Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.ACCESS_WIFI_STATE, Manifest.permission.INTERNET)
.check();
}
private VideoCapturer createVideoCapturer() {
VideoCapturer videoCapturer;
videoCapturer = createCameraCapturer(new Camera1Enumerator(false));
return videoCapturer;
}
private VideoCapturer createCameraCapturer(CameraEnumerator enumerator) {
final String[] deviceNames = enumerator.getDeviceNames();
// First, try to find front facing camera
Logging.d(TAG, "Looking for front facing cameras.");
for (String deviceName : deviceNames) {
if (enumerator.isFrontFacing(deviceName)) {
Logging.d(TAG, "Creating front facing camera capturer.");
VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
if (videoCapturer != null) {
return videoCapturer;
}
}
}
// Front facing camera not found, try something else
Logging.d(TAG, "Looking for other cameras.");
for (String deviceName : deviceNames) {
if (!enumerator.isFrontFacing(deviceName)) {
Logging.d(TAG, "Creating other camera capturer.");
VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
if (videoCapturer != null) {
return videoCapturer;
}
}
}
return null;
}
public void start() {
//Initialize PeerConnectionFactory globals.
//Params are context, initAudio,initVideo and videoCodecHwAcceleration
PeerConnectionFactory.initializeAndroidGlobals(this, true, true,
false);
//Create a new PeerConnectionFactory instance.
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
peerConnectionFactory = new PeerConnectionFactory(options);
//Now create a VideoCapturer instance. Callback methods are there if you want to do something! Duh!
VideoCapturer videoCapturerAndroid = createVideoCapturer();
//Create MediaConstraints - Will be useful for specifying video and audio constraints.
audioConstraints = new MediaConstraints();
videoConstraints = new MediaConstraints();
//Create a VideoSource instance
videoSource = peerConnectionFactory.createVideoSource(videoCapturerAndroid);
localVideoTrack = peerConnectionFactory.createVideoTrack("100", videoSource);
//create an AudioSource instance
audioSource = peerConnectionFactory.createAudioSource(audioConstraints);
localAudioTrack = peerConnectionFactory.createAudioTrack("101", audioSource);
//create a videoRenderer based on SurfaceViewRenderer instance
localRenderer = new VideoRenderer(pipVideoView);
// And finally, with our VideoRenderer ready, we
// can add our renderer to the VideoTrack.
localVideoTrack.addRenderer(localRenderer);
}
private void call() {
//we already have video and audio tracks. Now create peerconnections
List<PeerConnection.IceServer> iceServers = new ArrayList<>();
iceServers.add(new PeerConnection.IceServer("stun:stun.nextcloud.com:443"));
//create sdpConstraints
sdpConstraints = new MediaConstraints();
sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveAudio", "true"));
sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveVideo", "true"));
sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("internalSctpDataChannels", "true"));
sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
//creating localPeer
localPeer = peerConnectionFactory.createPeerConnection(iceServers, sdpConstraints,
new MagicPeerConnectionObserver() {
@Override
public void onIceCandidate(IceCandidate iceCandidate) {
super.onIceCandidate(iceCandidate);
onIceCandidateReceived(localPeer, iceCandidate);
}
});
//creating remotePeer
remotePeer = peerConnectionFactory.createPeerConnection(iceServers, sdpConstraints,
new MagicPeerConnectionObserver() {
@Override
public void onIceCandidate(IceCandidate iceCandidate) {
super.onIceCandidate(iceCandidate);
onIceCandidateReceived(remotePeer, iceCandidate);
}
public void onAddStream(MediaStream mediaStream) {
super.onAddStream(mediaStream);
gotRemoteStream(mediaStream);
}
@Override
public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
super.onIceGatheringChange(iceGatheringState);
}
});
//creating local mediastream
MediaStream stream = peerConnectionFactory.createLocalMediaStream("102");
stream.addTrack(localAudioTrack);
stream.addTrack(localVideoTrack);
localPeer.addStream(stream);
//creating Offer
localPeer.createOffer(new MagicSdpObserver(){
@Override
public void onCreateSuccess(SessionDescription sessionDescription) {
//we have localOffer. Set it as local desc for localpeer and remote desc for remote peer.
//try to create answer from the remote peer.
super.onCreateSuccess(sessionDescription);
localPeer.setLocalDescription(new MagicSdpObserver(), sessionDescription);
remotePeer.setRemoteDescription(new MagicSdpObserver(), sessionDescription);
remotePeer.createAnswer(new MagicSdpObserver() {
@Override
public void onCreateSuccess(SessionDescription sessionDescription) {
//remote answer generated. Now set it as local desc for remote peer and remote desc for local peer.
super.onCreateSuccess(sessionDescription);
remotePeer.setLocalDescription(new MagicSdpObserver(), sessionDescription);
localPeer.setRemoteDescription(new MagicSdpObserver(), sessionDescription);
}
},new MediaConstraints());
}
},sdpConstraints);
}
private void hangup() {
if (localPeer != null) {
localPeer.close();
localPeer = null;
}
if (remotePeer != null) {
remotePeer.close();
remotePeer = null;
}
}
private void gotRemoteStream(MediaStream stream) {
//we have remote video stream. add to the renderer.
final VideoTrack videoTrack = stream.videoTracks.getFirst();
AudioTrack audioTrack = stream.audioTracks.getFirst();
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
remoteRenderer = new VideoRenderer(fullScreenVideoView);
videoTrack.addRenderer(remoteRenderer);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public void onIceCandidateReceived(PeerConnection peer, IceCandidate iceCandidate) {
//we have received ice candidate. We can set it to the other peer.
if (peer == localPeer) {
remotePeer.addIceCandidate(iceCandidate);
} else {
localPeer.addIceCandidate(iceCandidate);
}
}
@Override
public void onBackPressed() {
if (!router.handleBack()) {
super.onBackPressed();
}
public void onDestroy() {
super.onDestroy();
hangup();
}
private static int getSystemUiVisibility() {
int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;