Search in sources :

Example 26 with SessionDescription

use of org.webrtc.SessionDescription in project matrix-android-sdk by matrix-org.

the class MXWebRtcCall method answer.

// user actions
/**
 * The call is accepted.
 */
@Override
public void answer() {
    super.answer();
    Log.d(LOG_TAG, "answer " + getCallState());
    if (!CALL_STATE_CREATED.equals(getCallState()) && (null != mPeerConnection)) {
        mUIThreadHandler.post(() -> {
            if (null == mPeerConnection) {
                Log.d(LOG_TAG, "answer the connection has been closed");
                return;
            }
            dispatchOnStateDidChange(CALL_STATE_CREATE_ANSWER);
            MediaConstraints constraints = new MediaConstraints();
            constraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
            constraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo", isVideo() ? "true" : "false"));
            mPeerConnection.createAnswer(new SdpObserver() {

                @Override
                public void onCreateSuccess(SessionDescription sessionDescription) {
                    Log.d(LOG_TAG, "createAnswer onCreateSuccess");
                    final SessionDescription sdp = new SessionDescription(sessionDescription.type, sessionDescription.description);
                    mUIThreadHandler.post(() -> {
                        if (mPeerConnection != null) {
                            // must be done to before sending the invitation message
                            mPeerConnection.setLocalDescription(new SdpObserver() {

                                @Override
                                public void onCreateSuccess(SessionDescription sessionDescription1) {
                                    Log.d(LOG_TAG, "setLocalDescription onCreateSuccess");
                                }

                                @Override
                                public void onSetSuccess() {
                                    Log.d(LOG_TAG, "setLocalDescription onSetSuccess");
                                    sendAnswer(sdp);
                                    dispatchOnStateDidChange(IMXCall.CALL_STATE_CONNECTING);
                                }

                                @Override
                                public void onCreateFailure(String s) {
                                    Log.e(LOG_TAG, "setLocalDescription onCreateFailure " + s);
                                    dispatchOnCallError(CALL_ERROR_CAMERA_INIT_FAILED);
                                    hangup(null);
                                }

                                @Override
                                public void onSetFailure(String s) {
                                    Log.e(LOG_TAG, "setLocalDescription onSetFailure " + s);
                                    dispatchOnCallError(CALL_ERROR_CAMERA_INIT_FAILED);
                                    hangup(null);
                                }
                            }, sdp);
                        }
                    });
                }

                @Override
                public void onSetSuccess() {
                    Log.d(LOG_TAG, "createAnswer onSetSuccess");
                }

                @Override
                public void onCreateFailure(String s) {
                    Log.e(LOG_TAG, "createAnswer onCreateFailure " + s);
                    dispatchOnCallError(CALL_ERROR_CAMERA_INIT_FAILED);
                    hangup(null);
                }

                @Override
                public void onSetFailure(String s) {
                    Log.e(LOG_TAG, "createAnswer onSetFailure " + s);
                    dispatchOnCallError(CALL_ERROR_CAMERA_INIT_FAILED);
                    hangup(null);
                }
            }, constraints);
        });
    }
}
Also used : SessionDescription(org.webrtc.SessionDescription) MediaConstraints(org.webrtc.MediaConstraints) SdpObserver(org.webrtc.SdpObserver)

Example 27 with SessionDescription

use of org.webrtc.SessionDescription in project matrix-android-sdk by matrix-org.

the class MXWebRtcCall method onCallAnswer.

/**
 * The callee accepts the call.
 *
 * @param event the event
 */
private void onCallAnswer(final Event event) {
    Log.d(LOG_TAG, "onCallAnswer : call state " + getCallState());
    if (!CALL_STATE_CREATED.equals(getCallState()) && (null != mPeerConnection)) {
        mUIThreadHandler.post(() -> {
            dispatchOnStateDidChange(IMXCall.CALL_STATE_CONNECTING);
            SessionDescription aDescription = null;
            // extract the description
            try {
                JsonObject eventContent = event.getContentAsJsonObject();
                if (eventContent.has("answer")) {
                    JsonObject answer = eventContent.getAsJsonObject("answer");
                    String type = answer.get("type").getAsString();
                    String sdp = answer.get("sdp").getAsString();
                    if (!TextUtils.isEmpty(type) && !TextUtils.isEmpty(sdp) && type.equals("answer")) {
                        aDescription = new SessionDescription(SessionDescription.Type.ANSWER, sdp);
                    }
                }
            } catch (Exception e) {
                Log.e(LOG_TAG, "onCallAnswer : " + e.getMessage(), e);
            }
            mPeerConnection.setRemoteDescription(new SdpObserver() {

                @Override
                public void onCreateSuccess(SessionDescription sessionDescription) {
                    Log.d(LOG_TAG, "setRemoteDescription onCreateSuccess");
                }

                @Override
                public void onSetSuccess() {
                    Log.d(LOG_TAG, "setRemoteDescription onSetSuccess");
                }

                @Override
                public void onCreateFailure(String s) {
                    Log.e(LOG_TAG, "setRemoteDescription onCreateFailure " + s);
                    dispatchOnCallError(CALL_ERROR_CAMERA_INIT_FAILED);
                }

                @Override
                public void onSetFailure(String s) {
                    Log.e(LOG_TAG, "setRemoteDescription onSetFailure " + s);
                    dispatchOnCallError(CALL_ERROR_CAMERA_INIT_FAILED);
                }
            }, aDescription);
        });
    }
}
Also used : SessionDescription(org.webrtc.SessionDescription) JsonObject(com.google.gson.JsonObject) SdpObserver(org.webrtc.SdpObserver)

Example 28 with SessionDescription

use of org.webrtc.SessionDescription in project matrix-android-sdk by matrix-org.

the class MXWebRtcCall method createLocalStream.

/**
 * create the local stream
 */
private void createLocalStream() {
    Log.d(LOG_TAG, "## createLocalStream(): IN");
    // check there is at least one stream to start a call
    if ((null == mLocalVideoTrack) && (null == mLocalAudioTrack)) {
        Log.d(LOG_TAG, "## createLocalStream(): CALL_ERROR_CALL_INIT_FAILED");
        dispatchOnCallError(CALL_ERROR_CALL_INIT_FAILED);
        hangup("no_stream");
        terminate(IMXCall.END_CALL_REASON_UNDEFINED);
        return;
    }
    // create our local stream to add our audio and video tracks
    mLocalMediaStream = mPeerConnectionFactory.createLocalMediaStream("ARDAMS");
    // add video track to local stream
    if (null != mLocalVideoTrack) {
        mLocalMediaStream.addTrack(mLocalVideoTrack);
    }
    // add audio track to local stream
    if (null != mLocalAudioTrack) {
        mLocalMediaStream.addTrack(mLocalAudioTrack);
    }
    if (null != mFullScreenRTCView) {
        mFullScreenRTCView.setStream(mLocalMediaStream);
        mFullScreenRTCView.setVisibility(View.VISIBLE);
    }
    // build ICE servers list
    List<PeerConnection.IceServer> iceServers = getIceServers();
    if (iceServers.isEmpty() && defaultIceServer != null) {
        iceServers.add(defaultIceServer);
    }
    // define at least on server
    if (iceServers.isEmpty()) {
        Log.d(LOG_TAG, "## createLocalStream(): No iceServers found ");
    }
    // define constraints
    PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);
    rtcConfig.enableRtpDataChannel = true;
    // start connecting to the other peer by creating the peer connection
    mPeerConnection = mPeerConnectionFactory.createPeerConnection(rtcConfig, new PeerConnection.Observer() {

        @Override
        public void onSignalingChange(PeerConnection.SignalingState signalingState) {
            Log.d(LOG_TAG, "## mPeerConnection creation: onSignalingChange state=" + signalingState);
        }

        @Override
        public void onIceConnectionChange(final PeerConnection.IceConnectionState iceConnectionState) {
            Log.d(LOG_TAG, "## mPeerConnection creation: onIceConnectionChange " + iceConnectionState);
            mUIThreadHandler.post(() -> {
                if (iceConnectionState == PeerConnection.IceConnectionState.CONNECTED) {
                    if ((null != mLocalVideoTrack) && mUsingLargeLocalRenderer && isVideo()) {
                        mLocalVideoTrack.setEnabled(false);
                        // the local attendee video is sent by the server among the others conference attendees.
                        if (!isConference()) {
                            // add local preview, only for 1:1 call
                            // mLocalVideoTrack.addRenderer(mSmallLocalRenderer);
                            mPipRTCView.setStream(mLocalMediaStream);
                            mPipRTCView.setVisibility(View.VISIBLE);
                            // to be able to display the avatar video above the large one
                            mPipRTCView.setZOrder(1);
                        }
                        mLocalVideoTrack.setEnabled(true);
                        mUsingLargeLocalRenderer = false;
                        mCallView.post(() -> {
                            if (null != mCallView) {
                                mCallView.invalidate();
                            }
                        });
                    }
                    dispatchOnStateDidChange(IMXCall.CALL_STATE_CONNECTED);
                } else /*else if (iceConnectionState == PeerConnection.IceConnectionState.DISCONNECTED) {
                                // TODO warn the user ?
                                hangup(null);
                            } else if (iceConnectionState == PeerConnection.IceConnectionState.CLOSED) {
                                // TODO warn the user ?
                                terminate();
                            }*/
                if (iceConnectionState == PeerConnection.IceConnectionState.FAILED) {
                    dispatchOnCallError(CALL_ERROR_ICE_FAILED);
                    hangup("ice_failed");
                }
            });
        }

        @Override
        public void onIceConnectionReceivingChange(boolean var1) {
            Log.d(LOG_TAG, "## mPeerConnection creation: onIceConnectionReceivingChange " + var1);
        }

        @Override
        public void onIceCandidatesRemoved(IceCandidate[] var1) {
            Log.d(LOG_TAG, "## mPeerConnection creation: onIceCandidatesRemoved " + Arrays.toString(var1));
        }

        @Override
        public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
            Log.d(LOG_TAG, "## mPeerConnection creation: onIceGatheringChange " + iceGatheringState);
        }

        @Override
        public void onAddTrack(RtpReceiver var1, MediaStream[] var2) {
            Log.d(LOG_TAG, "## mPeerConnection creation: onAddTrack " + var1 + " -- " + Arrays.toString(var2));
        }

        @Override
        public void onIceCandidate(final IceCandidate iceCandidate) {
            Log.d(LOG_TAG, "## mPeerConnection creation: onIceCandidate " + iceCandidate);
            mUIThreadHandler.post(() -> {
                if (!isCallEnded()) {
                    JsonObject content = new JsonObject();
                    content.addProperty("version", 0);
                    content.addProperty("call_id", mCallId);
                    JsonArray candidates = new JsonArray();
                    JsonObject cand = new JsonObject();
                    cand.addProperty("sdpMLineIndex", iceCandidate.sdpMLineIndex);
                    cand.addProperty("sdpMid", iceCandidate.sdpMid);
                    cand.addProperty("candidate", iceCandidate.sdp);
                    candidates.add(cand);
                    content.add("candidates", candidates);
                    boolean addIt = true;
                    // merge candidates
                    if (mPendingEvents.size() > 0) {
                        try {
                            Event lastEvent = mPendingEvents.get(mPendingEvents.size() - 1);
                            if (TextUtils.equals(lastEvent.getType(), Event.EVENT_TYPE_CALL_CANDIDATES)) {
                                // return the content cast as a JsonObject
                                // it is not a copy
                                JsonObject lastContent = lastEvent.getContentAsJsonObject();
                                JsonArray lastContentCandidates = lastContent.get("candidates").getAsJsonArray();
                                JsonArray newContentCandidates = content.get("candidates").getAsJsonArray();
                                Log.d(LOG_TAG, "Merge candidates from " + lastContentCandidates.size() + " to " + (lastContentCandidates.size() + newContentCandidates.size() + " items."));
                                lastContentCandidates.addAll(newContentCandidates);
                                // replace the candidates list
                                lastContent.remove("candidates");
                                lastContent.add("candidates", lastContentCandidates);
                                // don't need to save anything, lastContent is a reference not a copy
                                addIt = false;
                            }
                        } catch (Exception e) {
                            Log.e(LOG_TAG, "## createLocalStream(): createPeerConnection - onIceCandidate() Exception Msg=" + e.getMessage(), e);
                        }
                    }
                    if (addIt) {
                        Event event = new Event(Event.EVENT_TYPE_CALL_CANDIDATES, content, mSession.getCredentials().userId, mCallSignalingRoom.getRoomId());
                        mPendingEvents.add(event);
                        sendNextEvent();
                    }
                }
            });
        }

        @Override
        public void onAddStream(final MediaStream mediaStream) {
            Log.d(LOG_TAG, "## mPeerConnection creation: onAddStream " + mediaStream);
            mUIThreadHandler.post(() -> {
                if ((mediaStream.videoTracks.size() == 1) && !isCallEnded()) {
                    mRemoteVideoTrack = mediaStream.videoTracks.get(0);
                    mRemoteVideoTrack.setEnabled(true);
                    mFullScreenRTCView.setStream(mediaStream);
                    mFullScreenRTCView.setVisibility(View.VISIBLE);
                }
            });
        }

        @Override
        public void onRemoveStream(final MediaStream mediaStream) {
            Log.d(LOG_TAG, "## mPeerConnection creation: onRemoveStream " + mediaStream);
            mUIThreadHandler.post(() -> {
                if (null != mRemoteVideoTrack) {
                    mRemoteVideoTrack.dispose();
                    mRemoteVideoTrack = null;
                    mediaStream.videoTracks.get(0).dispose();
                }
            });
        }

        @Override
        public void onDataChannel(DataChannel dataChannel) {
            Log.d(LOG_TAG, "## mPeerConnection creation: onDataChannel " + dataChannel);
        }

        @Override
        public void onRenegotiationNeeded() {
            Log.d(LOG_TAG, "## mPeerConnection creation: onRenegotiationNeeded");
        }
    });
    if (null == mPeerConnection) {
        dispatchOnCallError(CALL_ERROR_ICE_FAILED);
        hangup("cannot create peer connection");
        return;
    }
    // send our local video and audio stream to make it seen by the other part
    mPeerConnection.addStream(mLocalMediaStream);
    MediaConstraints constraints = new MediaConstraints();
    constraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
    constraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo", isVideo() ? "true" : "false"));
    // call createOffer only for outgoing calls
    if (!isIncoming()) {
        Log.d(LOG_TAG, "## createLocalStream(): !isIncoming() -> createOffer");
        mPeerConnection.createOffer(new SdpObserver() {

            @Override
            public void onCreateSuccess(SessionDescription sessionDescription) {
                Log.d(LOG_TAG, "createOffer onCreateSuccess");
                final SessionDescription sdp = new SessionDescription(sessionDescription.type, sessionDescription.description);
                mUIThreadHandler.post(() -> {
                    if (mPeerConnection != null) {
                        // must be done to before sending the invitation message
                        mPeerConnection.setLocalDescription(new SdpObserver() {

                            @Override
                            public void onCreateSuccess(SessionDescription sessionDescription1) {
                                Log.d(LOG_TAG, "setLocalDescription onCreateSuccess");
                            }

                            @Override
                            public void onSetSuccess() {
                                Log.d(LOG_TAG, "setLocalDescription onSetSuccess");
                                sendInvite(sdp);
                                dispatchOnStateDidChange(IMXCall.CALL_STATE_INVITE_SENT);
                            }

                            @Override
                            public void onCreateFailure(String s) {
                                Log.e(LOG_TAG, "setLocalDescription onCreateFailure " + s);
                                dispatchOnCallError(CALL_ERROR_CAMERA_INIT_FAILED);
                                hangup(null);
                            }

                            @Override
                            public void onSetFailure(String s) {
                                Log.e(LOG_TAG, "setLocalDescription onSetFailure " + s);
                                dispatchOnCallError(CALL_ERROR_CAMERA_INIT_FAILED);
                                hangup(null);
                            }
                        }, sdp);
                    }
                });
            }

            @Override
            public void onSetSuccess() {
                Log.d(LOG_TAG, "createOffer onSetSuccess");
            }

            @Override
            public void onCreateFailure(String s) {
                Log.d(LOG_TAG, "createOffer onCreateFailure " + s);
                dispatchOnCallError(CALL_ERROR_CAMERA_INIT_FAILED);
            }

            @Override
            public void onSetFailure(String s) {
                Log.d(LOG_TAG, "createOffer onSetFailure " + s);
                dispatchOnCallError(CALL_ERROR_CAMERA_INIT_FAILED);
            }
        }, constraints);
        dispatchOnStateDidChange(IMXCall.CALL_STATE_WAIT_CREATE_OFFER);
    }
}
Also used : RtpReceiver(org.webrtc.RtpReceiver) SessionDescription(org.webrtc.SessionDescription) PeerConnection(org.webrtc.PeerConnection) JsonObject(com.google.gson.JsonObject) IceCandidate(org.webrtc.IceCandidate) JsonArray(com.google.gson.JsonArray) DataChannel(org.webrtc.DataChannel) MediaStream(org.webrtc.MediaStream) MediaConstraints(org.webrtc.MediaConstraints) SdpObserver(org.webrtc.SdpObserver) Event(org.matrix.androidsdk.rest.model.Event) SdpObserver(org.webrtc.SdpObserver)

Example 29 with SessionDescription

use of org.webrtc.SessionDescription in project matrix-android-sdk by matrix-org.

the class MXWebRtcCall method setRemoteDescription.

/**
 * Set the remote description
 *
 * @param callInviteParams the invitation params
 */
private void setRemoteDescription(final JsonObject callInviteParams) {
    Log.d(LOG_TAG, "setRemoteDescription " + callInviteParams);
    SessionDescription aDescription = null;
    // extract the description
    try {
        if (callInviteParams.has("offer")) {
            JsonObject answer = callInviteParams.getAsJsonObject("offer");
            String type = answer.get("type").getAsString();
            String sdp = answer.get("sdp").getAsString();
            if (!TextUtils.isEmpty(type) && !TextUtils.isEmpty(sdp)) {
                aDescription = new SessionDescription(SessionDescription.Type.OFFER, sdp);
            }
        }
    } catch (Exception e) {
        Log.e(LOG_TAG, "## setRemoteDescription(): Exception Msg=" + e.getMessage(), e);
    }
    mPeerConnection.setRemoteDescription(new SdpObserver() {

        @Override
        public void onCreateSuccess(SessionDescription sessionDescription) {
            Log.d(LOG_TAG, "setRemoteDescription onCreateSuccess");
        }

        @Override
        public void onSetSuccess() {
            Log.d(LOG_TAG, "setRemoteDescription onSetSuccess");
            mIsIncomingPrepared = true;
            mUIThreadHandler.post(() -> checkPendingCandidates());
        }

        @Override
        public void onCreateFailure(String s) {
            Log.e(LOG_TAG, "setRemoteDescription onCreateFailure " + s);
            dispatchOnCallError(CALL_ERROR_CAMERA_INIT_FAILED);
        }

        @Override
        public void onSetFailure(String s) {
            Log.e(LOG_TAG, "setRemoteDescription onSetFailure " + s);
            dispatchOnCallError(CALL_ERROR_CAMERA_INIT_FAILED);
        }
    }, aDescription);
}
Also used : SessionDescription(org.webrtc.SessionDescription) JsonObject(com.google.gson.JsonObject) SdpObserver(org.webrtc.SdpObserver)

Example 30 with SessionDescription

use of org.webrtc.SessionDescription in project flutter-webrtc by flutter-webrtc.

the class MethodCallHandlerImpl method peerConnectionSetLocalDescription.

public void peerConnectionSetLocalDescription(ConstraintsMap sdpMap, final String id, final Result result) {
    PeerConnection peerConnection = getPeerConnection(id);
    if (peerConnection != null) {
        SessionDescription sdp = new SessionDescription(Type.fromCanonicalForm(sdpMap.getString("type")), sdpMap.getString("sdp"));
        peerConnection.setLocalDescription(new SdpObserver() {

            @Override
            public void onCreateSuccess(final SessionDescription sdp) {
            }

            @Override
            public void onSetSuccess() {
                result.success(null);
            }

            @Override
            public void onCreateFailure(String s) {
            }

            @Override
            public void onSetFailure(String s) {
                resultError("peerConnectionSetLocalDescription", "WEBRTC_SET_LOCAL_DESCRIPTION_ERROR: " + s, result);
            }
        }, sdp);
    } else {
        resultError("peerConnectionSetLocalDescription", "WEBRTC_SET_LOCAL_DESCRIPTION_ERROR: peerConnection is null", result);
    }
}
Also used : SessionDescription(org.webrtc.SessionDescription) PeerConnection(org.webrtc.PeerConnection) SdpObserver(org.webrtc.SdpObserver)

Aggregations

SessionDescription (org.webrtc.SessionDescription)32 SdpObserver (org.webrtc.SdpObserver)14 MediaConstraints (org.webrtc.MediaConstraints)9 ExecutionException (java.util.concurrent.ExecutionException)8 SettableFuture (org.thoughtcrime.securesms.util.concurrent.SettableFuture)8 PeerConnection (org.webrtc.PeerConnection)8 PeerConnectionException (org.thoughtcrime.securesms.webrtc.PeerConnectionWrapper.PeerConnectionException)6 List (java.util.List)5 WritableMap (com.facebook.react.bridge.WritableMap)4 LinkedList (java.util.LinkedList)4 ListenableFutureTask (org.thoughtcrime.securesms.util.ListenableFutureTask)4 PeerConnectionWrapper (org.thoughtcrime.securesms.webrtc.PeerConnectionWrapper)4 CustomSdpObserver (com.example.webrtcandroidapp.observers.CustomSdpObserver)3 JsonObject (com.google.gson.JsonObject)3 LinkedTreeMap (com.google.gson.internal.LinkedTreeMap)3 AudioTrack (org.webrtc.AudioTrack)3 IceCandidate (org.webrtc.IceCandidate)3 MediaStream (org.webrtc.MediaStream)3 VideoTrack (org.webrtc.VideoTrack)3 IOException (java.io.IOException)2