Sfoglia il codice sorgente

Some work

Signed-off-by: Mario Danic <mario@lovelyhq.com>
Mario Danic 7 anni fa
parent
commit
f26c38444b

+ 250 - 22
app/src/main/java/com/nextcloud/talk/activities/CallActivity.java

@@ -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();
+            }
+
+            @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();
 
-            router.setRoot(RouterTransaction.with(new CallController(bundleBuilder.build()))
-            .popChangeHandler(new SimpleSwapChangeHandler())
-            .pushChangeHandler((new SimpleSwapChangeHandler())));
+        // 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;
     }
 
-    @Override
-    public void onBackPressed() {
-        if (!router.handleBack()) {
-            super.onBackPressed();
+    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 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;