Skip to content
Permalink
Browse files

New way to handle Streams

- Commit for SIPit
  • Loading branch information
jmillan committed Feb 18, 2013
1 parent 8aff36f commit 88fa9b6b2aedbf7d3038362f0e776aed9333980a
Showing with 359 additions and 299 deletions.
  1. +103 −132 src/MediaSession.js
  2. +256 −167 src/Session.js
@@ -7,107 +7,90 @@
* @augments JsSIP
* @class PeerConnection helper Class.
* @param {JsSIP.Session} session
* @param {HTMLVideoElement} selfView
* @param {HTMLVideoElement} remoteView
*/
JsSIP.MediaSession = function(session, selfView, remoteView) {
JsSIP.MediaSession = function(session, RTCConstraints) {
RTCConstraints = RTCConstraints || {};

this.session = session;
this.selfView = selfView || null;
this.remoteView = remoteView || null;
this.localMedia = null;
this.peerConnection = null;

this.init(RTCConstraints);
};

JsSIP.MediaSession.prototype = {
/**
* Establish peerConnection for Caller.
* <br> - Prompt the user for permission to use the Web cam or other video or audio input.
* <br> -- If the user consents, create a peerConnection.
* <br> -- If the user doesn't consent, fire onFailure callback.
*
* @param {Object} mediaTypes {audio:true/false, video:true/false}
* @param {Function} onSuccess
* @param {Function} onFailure
*/
startCaller: function(mediaTypes, onSuccess, onFailure) {
var self = this;

/** @private */
function onGetUserMediaSuccess(stream) {
// Start peerConnection
self.start(onSuccess);
createOffer: function(onSuccess, onFailure, constraints) {
var
self = this,
sent = false;

// add stream to peerConnection
self.peerConnection.addStream(stream);
this.onIceCompleted = function() {
if (!sent) {
sent = true;
onSuccess(self.peerConnection.localDescription.sdp);
}
};

// Set local description and start Ice.
self.peerConnection.createOffer(function(sessionDescription){
self.peerConnection.setLocalDescription(sessionDescription);
});
}
this.peerConnection.createOffer(
function(sessionDescription){
self.peerConnection.setLocalDescription(
sessionDescription,
null,
onFailure
);
},
onFailure,
constraints.offerConstraints
);
},

/** @private */
function onGetUserMediaFailure(e) {
onFailure(e);
}
createAnswer: function(onSuccess, onFailure, constraints) {
var
self = this,
sent = false;

this.getUserMedia(mediaTypes, onGetUserMediaSuccess, onGetUserMediaFailure);
this.onIceCompleted = function() {
if (!sent) {
sent = true;
onSuccess(self.peerConnection.localDescription.sdp);
}
};

this.peerConnection.createAnswer(
function(sessionDescription){
self.peerConnection.setLocalDescription(
sessionDescription,
null,
onFailure
);
},
onFailure,
constraints.answerConstraints
);
},

/**
* Establish peerConnection for Callee.
* <br> - Prompt the user for permission to use the Web cam or other video or audio input.
* <br> -- If the user consents, create a peerConnection.
* <br> -- If the user doesn't consent, fire onMediaFailure callback.
* <br>
* <br> - Set the received SDP offer to the just created peerConnection.
* <br> -- If the SDP offer is not valid, fire onSdpFailure callback.
* <br> -- If the SDP offer is valid, fire onSuccess callback
*
* @param {Function} onSuccess
* @param {Function} onMediaFailure
* @param {Function} onSdpFailure
* @param {String} sdp
*/
startCallee: function(onSuccess, onMediaFailure, onSdpFailure, sdp) {
addStream: function(onSuccess, onFailure, constraints) {
var self = this;

function onGetUserMediaSuccess(stream) {
// Start peerConnection
self.start(onSuccess);

// add stream to peerConnection
self.peerConnection.addStream(stream);

self.peerConnection.setRemoteDescription(
new JsSIP.WebRTC.RTCSessionDescription({type:'offer', sdp:sdp}),
function() {
self.peerConnection.createAnswer(
function(sessionDescription){
self.peerConnection.setLocalDescription(sessionDescription);
},
onSdpFailure
);
},
onSdpFailure
);
}

function onGetUserMediaFailure(e) {
onMediaFailure(e);
}

self.getUserMedia({'audio':true, 'video':true}, onGetUserMediaSuccess, onGetUserMediaFailure);
},
this.getUserMedia(constraints.userMediaConstraints,
function(stream) {
self.peerConnection.addStream(stream, constraints.streamConstraints);
onSuccess();
},
function(e) {
onFailure(e);
}
);
},

/**
* peerConnection creation.
* @param {Function} onSuccess Fired when there are no more ICE candidates
*/
start: function(onSuccess) {
init: function(RTCConstraints) {
var idx, server, scheme, url,
session = this,
sent = false,
self = this,
servers = [];

for (idx in this.session.ua.configuration.stun_servers) {
@@ -125,41 +108,40 @@ JsSIP.MediaSession.prototype = {
});
}

this.peerConnection = new JsSIP.WebRTC.RTCPeerConnection({'iceServers': servers});

this.peerConnection.onicecandidate = function(event) {
if (event.candidate) {
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'ICE candidate received: '+ event.candidate.candidate);
} else {
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'no more ICE candidates');
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'PeerConnection state: '+ this.readyState);
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'ICE state: '+ this.iceState);
if (!sent) { // Execute onSuccess just once.
sent = true;
onSuccess();
}
}
};
this.peerConnection = new JsSIP.WebRTC.RTCPeerConnection({'iceServers': servers}, RTCConstraints);

this.peerConnection.mediaSession = self;

this.peerConnection.onopen = function() {
console.log(JsSIP.C.LOG_MEDIA_SESSION +'media session opened');
};

this.peerConnection.onaddstream = function(mediaStreamEvent) {
console.log(JsSIP.C.LOG_MEDIA_SESSION +'stream added');
this.peerConnection.onaddstream = function(e) {
console.log(JsSIP.C.LOG_MEDIA_SESSION +'stream added: '+ e.stream.id);
};

this.peerConnection.onremovestream = function(e) {
console.log(JsSIP.C.LOG_MEDIA_SESSION +'stream removed: '+ e.stream.id);
};

this.peerConnection.onicecandidate = function(e) {
if (e.candidate) {
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'ICE candidate received: '+ e.candidate.candidate);
}
};

if (session.remoteView && this.getRemoteStreams().length > 0) {
session.remoteView.src = window.URL.createObjectURL(mediaStreamEvent.stream);
this.peerConnection.ongatheringchange = function(e) {
if (e.currentTarget.iceGatheringState === 'complete' && this.iceConnectionState !== 'closed') {
this.mediaSession.onIceCompleted();
}
};

this.peerConnection.onremovestream = function(stream) {
console.log(JsSIP.C.LOG_MEDIA_SESSION +'stream removed: '+ stream);
this.peerConnection.onicechange = function() {
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'ICE connection state changed to "'+ this.iceConnectionState +'"');
};

this.peerConnection.onstatechange = function() {
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'PeerConnection state changed to '+ this.readyState);
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'ICE state: '+ this.iceState);
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'PeerConnection state changed to "'+ this.readyState +'"');
};
},

@@ -175,50 +157,39 @@ JsSIP.MediaSession.prototype = {
},

/**
* @param {Object} mediaTypes
* @param {Object} mediaConstraints
* @param {Function} onSuccess
* @param {Function} onFailure
*/
getUserMedia: function(mediaTypes, onSuccess, onFailure) {
getUserMedia: function(mediaConstraints, onSuccess, onFailure) {
var self = this;

function getSuccess(stream) {
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'got stream: ' + stream);

//Save the localMedia in order to revoke access to devices later.
self.localMedia = stream;

// Attach the stream to the view if it exists.
if (self.selfView){
self.selfView.src = window.URL.createObjectURL(stream);
}

onSuccess(stream);
}

function getFailure(e) {
onFailure(e);
}

// Get User Media
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'requesting access to local media');
JsSIP.WebRTC.getUserMedia(mediaTypes, getSuccess, getFailure);

JsSIP.WebRTC.getUserMedia(mediaConstraints,
function(stream) {
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'got stream');
self.localMedia = stream;
onSuccess(stream);
},
function(e) {
onFailure(e);
}
);
},

/**
* Message reception once PeerConnection is active.
* Message reception.
* @param {String} type
* @param {String} sdp
* @param {Function} onSuccess
* @param {Function} onFailure
*/
onMessage: function(type, sdp, onSuccess, onFailure) {
if (type === 'offer') {
console.log(JsSIP.C.LOG_MEDIA_SESSION +'new SDP offer received');
} else if (type === 'answer') {
this.peerConnection.setRemoteDescription(
new JsSIP.WebRTC.RTCSessionDescription({type:'answer', sdp:sdp}), onSuccess, onFailure);
}
onMessage: function(type, body, onSuccess, onFailure) {
this.peerConnection.setRemoteDescription(
new JsSIP.WebRTC.RTCSessionDescription({type: type, sdp:body}),
onSuccess,
onFailure
);
}
};

3 comments on commit 88fa9b6

@saghul

This comment has been minimized.

Copy link
Contributor

saghul replied Feb 19, 2013

What. The. Fuck.

@rvulpescu

This comment has been minimized.

Copy link

rvulpescu replied Feb 19, 2013

A much better rewrite, great job!

@saghul

This comment has been minimized.

Copy link
Contributor

saghul replied Feb 19, 2013

Don't get too attached to it, this was prematurely committed and API will change a bit.

Please sign in to comment.
You can’t perform that action at this time.