diff --git a/index.html b/index.html index 1ac63ca17..2dea8b02e 100644 --- a/index.html +++ b/index.html @@ -19,7 +19,7 @@ - + diff --git a/libs/app.bundle.js b/libs/app.bundle.js index cbab99770..8c74ac418 100644 --- a/libs/app.bundle.js +++ b/libs/app.bundle.js @@ -12672,8 +12672,21 @@ function JingleSession(me, sid, connection, service) { */ this.videoMuteByUser = false; this.modifySourcesQueue = async.queue(this._modifySources.bind(this), 1); + // We start with the queue paused. We resume it when the signaling state is + // stable and the ice connection state is connected. + this.modifySourcesQueue.pause(); } +JingleSession.prototype.updateModifySourcesQueue = function() { + var signalingState = this.peerconnection.signalingState; + var iceConnectionState = this.peerconnection.iceConnectionState; + if (signalingState === 'stable' && iceConnectionState === 'connected') { + this.modifySourcesQueue.resume(); + } else { + this.modifySourcesQueue.pause(); + } +}; + //TODO: this array must be removed when firefox implement multistream support JingleSession.notReceivedSSRCs = []; @@ -12712,9 +12725,11 @@ JingleSession.prototype.initiate = function (peerjid, isInitiator) { }; this.peerconnection.onsignalingstatechange = function (event) { if (!(self && self.peerconnection)) return; + self.updateModifySourcesQueue(); }; this.peerconnection.oniceconnectionstatechange = function (event) { if (!(self && self.peerconnection)) return; + self.updateModifySourcesQueue(); switch (self.peerconnection.iceConnectionState) { case 'connected': this.startTime = new Date(); @@ -13394,7 +13409,17 @@ JingleSession.prototype.addSource = function (elem, fromJid) { }); sdp.raw = sdp.session + sdp.media.join(''); }); - this.modifySourcesQueue.push(); + + this.modifySourcesQueue.push(function() { + // When a source is added and if this is FF, a new channel is allocated + // for receiving the added source. We need to diffuse the SSRC of this + // new recvonly channel to the rest of the peers. + console.log('modify sources done'); + + var newSdp = new SDP(self.peerconnection.localDescription.sdp); + console.log("SDPs", mySdp, newSdp); + self.notifyMySSRCUpdate(mySdp, newSdp); + }); }; JingleSession.prototype.removeSource = function (elem, fromJid) { @@ -13455,7 +13480,17 @@ JingleSession.prototype.removeSource = function (elem, fromJid) { }); sdp.raw = sdp.session + sdp.media.join(''); }); - this.modifySourcesQueue.push(); + + this.modifySourcesQueue.push(function() { + // When a source is removed and if this is FF, the recvonly channel that + // receives the remote stream is deactivated . We need to diffuse the + // recvonly SSRC removal to the rest of the peers. + console.log('modify sources done'); + + var newSdp = new SDP(self.peerconnection.localDescription.sdp); + console.log("SDPs", mySdp, newSdp); + self.notifyMySSRCUpdate(mySdp, newSdp); + }); }; JingleSession.prototype._modifySources = function (successCallback, queueCallback) { @@ -28287,7 +28322,7 @@ Interop.prototype.toUnifiedPlan = function(desc) { // A helper map that sends mids to m-line objects. We use it later to // rebuild the Unified Plan style session.media array. - var media = {}; + var mid2ml = {}; session.media.forEach(function(channel) { if (typeof channel.rtcpMux !== 'string' || channel.rtcpMux !== 'rtcp-mux') { @@ -28317,7 +28352,7 @@ Interop.prototype.toUnifiedPlan = function(desc) { delete channel.mid; // inverted ssrc group map - var invertedGroups = {}; + var ssrc2group = {}; if (typeof ssrcGroups !== 'undefined' && Array.isArray(ssrcGroups)) { ssrcGroups.forEach(function (ssrcGroup) { @@ -28330,33 +28365,37 @@ Interop.prototype.toUnifiedPlan = function(desc) { if (typeof ssrcGroup.ssrcs !== 'undefined' && Array.isArray(ssrcGroup.ssrcs)) { ssrcGroup.ssrcs.forEach(function (ssrc) { - if (typeof invertedGroups[ssrc] === 'undefined') { - invertedGroups[ssrc] = []; + if (typeof ssrc2group[ssrc] === 'undefined') { + ssrc2group[ssrc] = []; } - invertedGroups[ssrc].push(ssrcGroup); + ssrc2group[ssrc].push(ssrcGroup); }); } }); } // ssrc to m-line index. - var mLines = {}; + var ssrc2ml = {}; if (typeof sources === 'object') { // Explode the Plan B channel sources with one m-line per source. Object.keys(sources).forEach(function(ssrc) { + // The m-line for this SSRC. We either create it from scratch + // or, if it's a grouped SSRC, we re-use a related mline. In + // other words, if the source is grouped with another source, + // put the two together in the same m-line. var mLine; - if (typeof invertedGroups[ssrc] !== 'undefined' && - Array.isArray(invertedGroups[ssrc])) { - invertedGroups[ssrc].some(function (ssrcGroup) { + if (typeof ssrc2group[ssrc] !== 'undefined' && + Array.isArray(ssrc2group[ssrc])) { + ssrc2group[ssrc].some(function (ssrcGroup) { // ssrcGroup.ssrcs *is* an Array, no need to check // again here. return ssrcGroup.ssrcs.some(function (related) { - if (typeof mLines[related] === 'object') { - mLine = mLines[related]; + if (typeof ssrc2ml[related] === 'object') { + mLine = ssrc2ml[related]; return true; } }); @@ -28370,7 +28409,7 @@ Interop.prototype.toUnifiedPlan = function(desc) { } else { // Use the "channel" as a prototype for the "mLine". mLine = Object.create(channel); - mLines[ssrc] = mLine; + ssrc2ml[ssrc] = mLine; if (typeof sources[ssrc].msid !== 'undefined') { // Assign the msid of the source to the m-line. Note @@ -28385,7 +28424,7 @@ Interop.prototype.toUnifiedPlan = function(desc) { // We assign one SSRC per media line. mLine.sources = {}; mLine.sources[ssrc] = sources[ssrc]; - mLine.ssrcGroups = invertedGroups[ssrc]; + mLine.ssrcGroups = ssrc2group[ssrc]; // Use the cached Unified Plan SDP (if it exists) to assign // SSRCs to mids. @@ -28393,9 +28432,9 @@ Interop.prototype.toUnifiedPlan = function(desc) { typeof cached.media !== 'undefined' && Array.isArray(cached.media)) { - cached.media.forEach(function(m) { + cached.media.forEach(function (m) { if (typeof m.sources === 'object') { - Object.keys(m.sources).forEach(function(s) { + Object.keys(m.sources).forEach(function (s) { if (s === ssrc) { mLine.mid = m.mid; } @@ -28433,7 +28472,7 @@ Interop.prototype.toUnifiedPlan = function(desc) { mLine.fingerprint = fingerprint; mLine.port = port; - media[mLine.mid] = mLine; + mid2ml[mLine.mid] = mLine; } }); } @@ -28470,7 +28509,7 @@ Interop.prototype.toUnifiedPlan = function(desc) { var mLine; cached.media.some(function(ma) { if (mo.mid == ma.mid) { - if (typeof media[mo.mid] === 'undefined') { + if (typeof mid2ml[mo.mid] === 'undefined') { // This is either an m-line containing a remote // track only, or an m-line containing a remote @@ -28527,8 +28566,8 @@ Interop.prototype.toUnifiedPlan = function(desc) { Array.isArray(cached.media)) { cached.media.forEach(function(pm) { mids.push(pm.mid); - if (typeof media[pm.mid] !== 'undefined') { - session.media.push(media[pm.mid]); + if (typeof mid2ml[pm.mid] !== 'undefined') { + session.media.push(mid2ml[pm.mid]); } else { delete pm.msid; delete pm.sources; @@ -28540,10 +28579,27 @@ Interop.prototype.toUnifiedPlan = function(desc) { } // Add all the remaining (new) m-lines of the transformed SDP. - Object.keys(media).forEach(function(mid) { + Object.keys(mid2ml).forEach(function(mid) { if (mids.indexOf(mid) === -1) { mids.push(mid); - session.media.push(media[mid]); + if (typeof mid2ml[mid].msid === 'undefined') { + // This is a remote recvonly channel. Add its SSRC to the + // sendrecv channel. + // TODO(gp) what if there is no sendrecv channel? + session.media.some(function (ml) { + if (ml.direction === 'sendrecv' && ml.type == mid2ml[mid].type) { + + // this shouldn't have any ssrc-groups + Object.keys(mid2ml[mid].sources).forEach(function (ssrc) { + ml.sources[ssrc] = mid2ml[mid].sources[ssrc]; + }); + + return true; + } + }); + } else { + session.media.push(mid2ml[mid]); + } } }); }