Adds support for FF/multistream.

This commit is contained in:
George Politis 2015-03-04 21:33:06 +01:00
parent e465b3ed90
commit 05bbfda5bb
6 changed files with 18131 additions and 17011 deletions

View File

@ -19,7 +19,7 @@
<script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib --> <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
<script src="libs/toastr.js?v=1"></script><!-- notifications lib --> <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
<script src="interface_config.js?v=5"></script> <script src="interface_config.js?v=5"></script>
<script src="libs/app.bundle.js?v=27"></script> <script src="libs/app.bundle.js?v=28"></script>
<script src="analytics.js?v=1"></script><!-- google analytics plugin --> <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
<link rel="stylesheet" href="css/font.css?v=6"/> <link rel="stylesheet" href="css/font.css?v=6"/>
<link rel="stylesheet" href="css/toastr.css?v=1"> <link rel="stylesheet" href="css/toastr.css?v=1">

File diff suppressed because it is too large Load Diff

View File

@ -33,13 +33,6 @@ function MediaStream(data, sid, ssrc, browser) {
MediaStreamType.VIDEO_TYPE : MediaStreamType.AUDIO_TYPE; MediaStreamType.VIDEO_TYPE : MediaStreamType.AUDIO_TYPE;
this.videoType = null; this.videoType = null;
this.muted = false; this.muted = false;
if(browser == RTCBrowserType.RTC_BROWSER_FIREFOX)
{
if (!this.getVideoTracks)
this.getVideoTracks = function () { return []; };
if (!this.getAudioTracks)
this.getAudioTracks = function () { return []; };
}
} }

View File

@ -736,7 +736,7 @@ JingleSession.prototype.addSource = function (elem, fromJid) {
$(elem).each(function (idx, content) { $(elem).each(function (idx, content) {
var name = $(content).attr('name'); var name = $(content).attr('name');
var lines = ''; var lines = '';
tmp = $(content).find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() { $(content).find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
var semantics = this.getAttribute('semantics'); var semantics = this.getAttribute('semantics');
var ssrcs = $(this).find('>source').map(function () { var ssrcs = $(this).find('>source').map(function () {
return this.getAttribute('ssrc'); return this.getAttribute('ssrc');
@ -746,7 +746,7 @@ JingleSession.prototype.addSource = function (elem, fromJid) {
lines += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\r\n'; lines += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\r\n';
} }
}); });
tmp = $(content).find('source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]'); // can handle both >source and >description>source var tmp = $(content).find('source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]'); // can handle both >source and >description>source
tmp.each(function () { tmp.each(function () {
var ssrc = $(this).attr('ssrc'); var ssrc = $(this).attr('ssrc');
if(mySdp.containsSSRC(ssrc)){ if(mySdp.containsSSRC(ssrc)){
@ -801,7 +801,7 @@ JingleSession.prototype.removeSource = function (elem, fromJid) {
$(elem).each(function (idx, content) { $(elem).each(function (idx, content) {
var name = $(content).attr('name'); var name = $(content).attr('name');
var lines = ''; var lines = '';
tmp = $(content).find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() { $(content).find('ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
var semantics = this.getAttribute('semantics'); var semantics = this.getAttribute('semantics');
var ssrcs = $(this).find('>source').map(function () { var ssrcs = $(this).find('>source').map(function () {
return this.getAttribute('ssrc'); return this.getAttribute('ssrc');
@ -811,7 +811,7 @@ JingleSession.prototype.removeSource = function (elem, fromJid) {
lines += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\r\n'; lines += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\r\n';
} }
}); });
tmp = $(content).find('source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]'); // can handle both >source and >description>source var tmp = $(content).find('source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]'); // can handle both >source and >description>source
tmp.each(function () { tmp.each(function () {
var ssrc = $(this).attr('ssrc'); var ssrc = $(this).attr('ssrc');
// This should never happen, but can be useful for bug detection // This should never happen, but can be useful for bug detection
@ -1310,7 +1310,7 @@ function sendKeyframe(pc) {
} }
JingleSession.prototype.remoteStreamAdded = function (data) { JingleSession.prototype.remoteStreamAdded = function (data, times) {
var self = this; var self = this;
var thessrc; var thessrc;
var ssrc2jid = this.connection.emuc.ssrc2jid; var ssrc2jid = this.connection.emuc.ssrc2jid;
@ -1339,12 +1339,24 @@ JingleSession.prototype.remoteStreamAdded = function (data) {
// presence to arrive. // presence to arrive.
if (!ssrc2jid[thessrc]) { if (!ssrc2jid[thessrc]) {
// TODO(gp) limit wait duration to 1 sec.
setTimeout(function(d) { if (typeof times === 'undefined')
return function() { {
self.remoteStreamAdded(d); times = 0;
} }
}(data), 250);
if (times > 10)
{
console.warning('Waiting for jid timed out', thessrc);
}
else
{
setTimeout(function(d) {
return function() {
self.remoteStreamAdded(d, times++);
}
}(data), 250);
}
return; return;
} }
@ -1356,27 +1368,6 @@ JingleSession.prototype.remoteStreamAdded = function (data) {
} }
} }
//TODO: this code should be removed when firefox implement multistream support
if(APP.RTC.getBrowserType() == RTCBrowserType.RTC_BROWSER_FIREFOX)
{
if((JingleSession.notReceivedSSRCs.length == 0) ||
!ssrc2jid[JingleSession.notReceivedSSRCs[JingleSession.notReceivedSSRCs.length - 1]])
{
// TODO(gp) limit wait duration to 1 sec.
setTimeout(function(d) {
return function() {
self.remoteStreamAdded(d);
}
}(data), 250);
return;
}
thessrc = JingleSession.notReceivedSSRCs.pop();
if (ssrc2jid[thessrc]) {
data.peerjid = ssrc2jid[thessrc];
}
}
APP.RTC.createRemoteStream(data, this.sid, thessrc); APP.RTC.createRemoteStream(data, this.sid, thessrc);
var isVideo = data.stream.getVideoTracks().length > 0; var isVideo = data.stream.getVideoTracks().length > 0;

View File

@ -6,6 +6,8 @@ function TraceablePeerConnection(ice_config, constraints) {
this.stats = {}; this.stats = {};
this.statsinterval = null; this.statsinterval = null;
this.maxstats = 0; // limit to 300 values, i.e. 5 minutes; set to 0 to disable this.maxstats = 0; // limit to 300 values, i.e. 5 minutes; set to 0 to disable
var Interop = require('sdp-interop').Interop;
this.interop = new Interop();
// override as desired // override as desired
this.trace = function (what, info) { this.trace = function (what, info) {
@ -98,19 +100,39 @@ function TraceablePeerConnection(ice_config, constraints) {
}; };
dumpSDP = function(description) { dumpSDP = function(description) {
if (typeof description === 'undefined' || description == null) {
return '';
}
return 'type: ' + description.type + '\r\n' + description.sdp; return 'type: ' + description.type + '\r\n' + description.sdp;
} };
if (TraceablePeerConnection.prototype.__defineGetter__ !== undefined) { if (TraceablePeerConnection.prototype.__defineGetter__ !== undefined) {
TraceablePeerConnection.prototype.__defineGetter__('signalingState', function() { return this.peerconnection.signalingState; }); TraceablePeerConnection.prototype.__defineGetter__('signalingState', function() { return this.peerconnection.signalingState; });
TraceablePeerConnection.prototype.__defineGetter__('iceConnectionState', function() { return this.peerconnection.iceConnectionState; }); TraceablePeerConnection.prototype.__defineGetter__('iceConnectionState', function() { return this.peerconnection.iceConnectionState; });
TraceablePeerConnection.prototype.__defineGetter__('localDescription', function() { TraceablePeerConnection.prototype.__defineGetter__('localDescription', function() {
var publicLocalDescription = APP.simulcast.reverseTransformLocalDescription(this.peerconnection.localDescription); this.trace('getLocalDescription::preTransform (Plan A)', dumpSDP(this.peerconnection.localDescription));
return publicLocalDescription; // if we're running on FF, transform to Plan B first.
var desc = this.peerconnection.localDescription;
if (navigator.mozGetUserMedia) {
desc = this.interop.toPlanB(desc);
} else {
desc = APP.simulcast.reverseTransformLocalDescription(this.peerconnection.localDescription);
}
this.trace('getLocalDescription::postTransform (Plan B)', dumpSDP(desc));
return desc;
}); });
TraceablePeerConnection.prototype.__defineGetter__('remoteDescription', function() { TraceablePeerConnection.prototype.__defineGetter__('remoteDescription', function() {
var publicRemoteDescription = APP.simulcast.reverseTransformRemoteDescription(this.peerconnection.remoteDescription); this.trace('getRemoteDescription::preTransform (Plan A)', dumpSDP(this.peerconnection.remoteDescription));
return publicRemoteDescription; // if we're running on FF, transform to Plan B first.
var desc = this.peerconnection.remoteDescription;
if (navigator.mozGetUserMedia) {
desc = this.interop.toPlanB(desc);
} else {
desc = APP.simulcast.reverseTransformRemoteDescription(this.peerconnection.remoteDescription);
}
this.trace('getRemoteDescription::postTransform (Plan B)', dumpSDP(desc));
return desc;
}); });
} }
@ -148,9 +170,15 @@ TraceablePeerConnection.prototype.createDataChannel = function (label, opts) {
}; };
TraceablePeerConnection.prototype.setLocalDescription = function (description, successCallback, failureCallback) { TraceablePeerConnection.prototype.setLocalDescription = function (description, successCallback, failureCallback) {
this.trace('setLocalDescription::preTransform (Plan B)', dumpSDP(description));
// if we're running on FF, transform to Plan A first.
if (navigator.mozGetUserMedia) {
description = this.interop.toPlanA(description);
} else {
description = APP.simulcast.transformLocalDescription(description);
}
this.trace('setLocalDescription::postTransform (Plan A)', dumpSDP(description));
var self = this; var self = this;
description = APP.simulcast.transformLocalDescription(description);
this.trace('setLocalDescription', dumpSDP(description));
this.peerconnection.setLocalDescription(description, this.peerconnection.setLocalDescription(description,
function () { function () {
self.trace('setLocalDescriptionOnSuccess'); self.trace('setLocalDescriptionOnSuccess');
@ -169,9 +197,16 @@ TraceablePeerConnection.prototype.setLocalDescription = function (description, s
}; };
TraceablePeerConnection.prototype.setRemoteDescription = function (description, successCallback, failureCallback) { TraceablePeerConnection.prototype.setRemoteDescription = function (description, successCallback, failureCallback) {
this.trace('setRemoteDescription::preTransform (Plan B)', dumpSDP(description));
// if we're running on FF, transform to Plan A first.
if (navigator.mozGetUserMedia) {
description = this.interop.toPlanA(description);
}
else {
description = APP.simulcast.transformRemoteDescription(description);
}
this.trace('setRemoteDescription::postTransform (Plan A)', dumpSDP(description));
var self = this; var self = this;
description = APP.simulcast.transformRemoteDescription(description);
this.trace('setRemoteDescription', dumpSDP(description));
this.peerconnection.setRemoteDescription(description, this.peerconnection.setRemoteDescription(description,
function () { function () {
self.trace('setRemoteDescriptionOnSuccess'); self.trace('setRemoteDescriptionOnSuccess');
@ -203,7 +238,12 @@ TraceablePeerConnection.prototype.createOffer = function (successCallback, failu
this.trace('createOffer', JSON.stringify(constraints, null, ' ')); this.trace('createOffer', JSON.stringify(constraints, null, ' '));
this.peerconnection.createOffer( this.peerconnection.createOffer(
function (offer) { function (offer) {
self.trace('createOfferOnSuccess', dumpSDP(offer)); self.trace('createOfferOnSuccess::preTransform (Plan A)', dumpSDP(offer));
// if we're running on FF, transform to Plan B first.
if (navigator.mozGetUserMedia) {
offer = self.interop.toPlanB(offer);
}
self.trace('createOfferOnSuccess::postTransform (Plan B)', dumpSDP(offer));
successCallback(offer); successCallback(offer);
}, },
function(err) { function(err) {
@ -219,8 +259,14 @@ TraceablePeerConnection.prototype.createAnswer = function (successCallback, fail
this.trace('createAnswer', JSON.stringify(constraints, null, ' ')); this.trace('createAnswer', JSON.stringify(constraints, null, ' '));
this.peerconnection.createAnswer( this.peerconnection.createAnswer(
function (answer) { function (answer) {
answer = APP.simulcast.transformAnswer(answer); self.trace('createAnswerOnSuccess::preTransfom (Plan A)', dumpSDP(answer));
self.trace('createAnswerOnSuccess', dumpSDP(answer)); // if we're running on FF, transform to Plan A first.
if (navigator.mozGetUserMedia) {
answer = self.interop.toPlanB(answer);
} else {
answer = APP.simulcast.transformAnswer(answer);
}
self.trace('createAnswerOnSuccess::postTransfom (Plan B)', dumpSDP(answer));
successCallback(answer); successCallback(answer);
}, },
function(err) { function(err) {

View File

@ -17,7 +17,8 @@
"dependencies": { "dependencies": {
"events": "*", "events": "*",
"pako": "*", "pako": "*",
"i18next-client": "*" "i18next-client": "*",
"sdp-interop": "https://github.com/jitsi/sdp-interop/tarball/master"
}, },
"devDependencies": { "devDependencies": {
}, },