|
@@ -12672,8 +12672,21 @@ function JingleSession(me, sid, connection, service) {
|
12672
|
12672
|
*/
|
12673
|
12673
|
this.videoMuteByUser = false;
|
12674
|
12674
|
this.modifySourcesQueue = async.queue(this._modifySources.bind(this), 1);
|
|
12675
|
+ // We start with the queue paused. We resume it when the signaling state is
|
|
12676
|
+ // stable and the ice connection state is connected.
|
|
12677
|
+ this.modifySourcesQueue.pause();
|
12675
|
12678
|
}
|
12676
|
12679
|
|
|
12680
|
+JingleSession.prototype.updateModifySourcesQueue = function() {
|
|
12681
|
+ var signalingState = this.peerconnection.signalingState;
|
|
12682
|
+ var iceConnectionState = this.peerconnection.iceConnectionState;
|
|
12683
|
+ if (signalingState === 'stable' && iceConnectionState === 'connected') {
|
|
12684
|
+ this.modifySourcesQueue.resume();
|
|
12685
|
+ } else {
|
|
12686
|
+ this.modifySourcesQueue.pause();
|
|
12687
|
+ }
|
|
12688
|
+};
|
|
12689
|
+
|
12677
|
12690
|
//TODO: this array must be removed when firefox implement multistream support
|
12678
|
12691
|
JingleSession.notReceivedSSRCs = [];
|
12679
|
12692
|
|
|
@@ -12712,9 +12725,11 @@ JingleSession.prototype.initiate = function (peerjid, isInitiator) {
|
12712
|
12725
|
};
|
12713
|
12726
|
this.peerconnection.onsignalingstatechange = function (event) {
|
12714
|
12727
|
if (!(self && self.peerconnection)) return;
|
|
12728
|
+ self.updateModifySourcesQueue();
|
12715
|
12729
|
};
|
12716
|
12730
|
this.peerconnection.oniceconnectionstatechange = function (event) {
|
12717
|
12731
|
if (!(self && self.peerconnection)) return;
|
|
12732
|
+ self.updateModifySourcesQueue();
|
12718
|
12733
|
switch (self.peerconnection.iceConnectionState) {
|
12719
|
12734
|
case 'connected':
|
12720
|
12735
|
this.startTime = new Date();
|
|
@@ -13394,7 +13409,17 @@ JingleSession.prototype.addSource = function (elem, fromJid) {
|
13394
|
13409
|
});
|
13395
|
13410
|
sdp.raw = sdp.session + sdp.media.join('');
|
13396
|
13411
|
});
|
13397
|
|
- this.modifySourcesQueue.push();
|
|
13412
|
+
|
|
13413
|
+ this.modifySourcesQueue.push(function() {
|
|
13414
|
+ // When a source is added and if this is FF, a new channel is allocated
|
|
13415
|
+ // for receiving the added source. We need to diffuse the SSRC of this
|
|
13416
|
+ // new recvonly channel to the rest of the peers.
|
|
13417
|
+ console.log('modify sources done');
|
|
13418
|
+
|
|
13419
|
+ var newSdp = new SDP(self.peerconnection.localDescription.sdp);
|
|
13420
|
+ console.log("SDPs", mySdp, newSdp);
|
|
13421
|
+ self.notifyMySSRCUpdate(mySdp, newSdp);
|
|
13422
|
+ });
|
13398
|
13423
|
};
|
13399
|
13424
|
|
13400
|
13425
|
JingleSession.prototype.removeSource = function (elem, fromJid) {
|
|
@@ -13455,7 +13480,17 @@ JingleSession.prototype.removeSource = function (elem, fromJid) {
|
13455
|
13480
|
});
|
13456
|
13481
|
sdp.raw = sdp.session + sdp.media.join('');
|
13457
|
13482
|
});
|
13458
|
|
- this.modifySourcesQueue.push();
|
|
13483
|
+
|
|
13484
|
+ this.modifySourcesQueue.push(function() {
|
|
13485
|
+ // When a source is removed and if this is FF, the recvonly channel that
|
|
13486
|
+ // receives the remote stream is deactivated . We need to diffuse the
|
|
13487
|
+ // recvonly SSRC removal to the rest of the peers.
|
|
13488
|
+ console.log('modify sources done');
|
|
13489
|
+
|
|
13490
|
+ var newSdp = new SDP(self.peerconnection.localDescription.sdp);
|
|
13491
|
+ console.log("SDPs", mySdp, newSdp);
|
|
13492
|
+ self.notifyMySSRCUpdate(mySdp, newSdp);
|
|
13493
|
+ });
|
13459
|
13494
|
};
|
13460
|
13495
|
|
13461
|
13496
|
JingleSession.prototype._modifySources = function (successCallback, queueCallback) {
|
|
@@ -28287,7 +28322,7 @@ Interop.prototype.toUnifiedPlan = function(desc) {
|
28287
|
28322
|
|
28288
|
28323
|
// A helper map that sends mids to m-line objects. We use it later to
|
28289
|
28324
|
// rebuild the Unified Plan style session.media array.
|
28290
|
|
- var media = {};
|
|
28325
|
+ var mid2ml = {};
|
28291
|
28326
|
session.media.forEach(function(channel) {
|
28292
|
28327
|
if (typeof channel.rtcpMux !== 'string' ||
|
28293
|
28328
|
channel.rtcpMux !== 'rtcp-mux') {
|
|
@@ -28317,7 +28352,7 @@ Interop.prototype.toUnifiedPlan = function(desc) {
|
28317
|
28352
|
delete channel.mid;
|
28318
|
28353
|
|
28319
|
28354
|
// inverted ssrc group map
|
28320
|
|
- var invertedGroups = {};
|
|
28355
|
+ var ssrc2group = {};
|
28321
|
28356
|
if (typeof ssrcGroups !== 'undefined' && Array.isArray(ssrcGroups)) {
|
28322
|
28357
|
ssrcGroups.forEach(function (ssrcGroup) {
|
28323
|
28358
|
|
|
@@ -28330,33 +28365,37 @@ Interop.prototype.toUnifiedPlan = function(desc) {
|
28330
|
28365
|
if (typeof ssrcGroup.ssrcs !== 'undefined' &&
|
28331
|
28366
|
Array.isArray(ssrcGroup.ssrcs)) {
|
28332
|
28367
|
ssrcGroup.ssrcs.forEach(function (ssrc) {
|
28333
|
|
- if (typeof invertedGroups[ssrc] === 'undefined') {
|
28334
|
|
- invertedGroups[ssrc] = [];
|
|
28368
|
+ if (typeof ssrc2group[ssrc] === 'undefined') {
|
|
28369
|
+ ssrc2group[ssrc] = [];
|
28335
|
28370
|
}
|
28336
|
28371
|
|
28337
|
|
- invertedGroups[ssrc].push(ssrcGroup);
|
|
28372
|
+ ssrc2group[ssrc].push(ssrcGroup);
|
28338
|
28373
|
});
|
28339
|
28374
|
}
|
28340
|
28375
|
});
|
28341
|
28376
|
}
|
28342
|
28377
|
|
28343
|
28378
|
// ssrc to m-line index.
|
28344
|
|
- var mLines = {};
|
|
28379
|
+ var ssrc2ml = {};
|
28345
|
28380
|
|
28346
|
28381
|
if (typeof sources === 'object') {
|
28347
|
28382
|
|
28348
|
28383
|
// Explode the Plan B channel sources with one m-line per source.
|
28349
|
28384
|
Object.keys(sources).forEach(function(ssrc) {
|
28350
|
28385
|
|
|
28386
|
+ // The m-line for this SSRC. We either create it from scratch
|
|
28387
|
+ // or, if it's a grouped SSRC, we re-use a related mline. In
|
|
28388
|
+ // other words, if the source is grouped with another source,
|
|
28389
|
+ // put the two together in the same m-line.
|
28351
|
28390
|
var mLine;
|
28352
|
|
- if (typeof invertedGroups[ssrc] !== 'undefined' &&
|
28353
|
|
- Array.isArray(invertedGroups[ssrc])) {
|
28354
|
|
- invertedGroups[ssrc].some(function (ssrcGroup) {
|
|
28391
|
+ if (typeof ssrc2group[ssrc] !== 'undefined' &&
|
|
28392
|
+ Array.isArray(ssrc2group[ssrc])) {
|
|
28393
|
+ ssrc2group[ssrc].some(function (ssrcGroup) {
|
28355
|
28394
|
// ssrcGroup.ssrcs *is* an Array, no need to check
|
28356
|
28395
|
// again here.
|
28357
|
28396
|
return ssrcGroup.ssrcs.some(function (related) {
|
28358
|
|
- if (typeof mLines[related] === 'object') {
|
28359
|
|
- mLine = mLines[related];
|
|
28397
|
+ if (typeof ssrc2ml[related] === 'object') {
|
|
28398
|
+ mLine = ssrc2ml[related];
|
28360
|
28399
|
return true;
|
28361
|
28400
|
}
|
28362
|
28401
|
});
|
|
@@ -28370,7 +28409,7 @@ Interop.prototype.toUnifiedPlan = function(desc) {
|
28370
|
28409
|
} else {
|
28371
|
28410
|
// Use the "channel" as a prototype for the "mLine".
|
28372
|
28411
|
mLine = Object.create(channel);
|
28373
|
|
- mLines[ssrc] = mLine;
|
|
28412
|
+ ssrc2ml[ssrc] = mLine;
|
28374
|
28413
|
|
28375
|
28414
|
if (typeof sources[ssrc].msid !== 'undefined') {
|
28376
|
28415
|
// Assign the msid of the source to the m-line. Note
|
|
@@ -28385,7 +28424,7 @@ Interop.prototype.toUnifiedPlan = function(desc) {
|
28385
|
28424
|
// We assign one SSRC per media line.
|
28386
|
28425
|
mLine.sources = {};
|
28387
|
28426
|
mLine.sources[ssrc] = sources[ssrc];
|
28388
|
|
- mLine.ssrcGroups = invertedGroups[ssrc];
|
|
28427
|
+ mLine.ssrcGroups = ssrc2group[ssrc];
|
28389
|
28428
|
|
28390
|
28429
|
// Use the cached Unified Plan SDP (if it exists) to assign
|
28391
|
28430
|
// SSRCs to mids.
|
|
@@ -28393,9 +28432,9 @@ Interop.prototype.toUnifiedPlan = function(desc) {
|
28393
|
28432
|
typeof cached.media !== 'undefined' &&
|
28394
|
28433
|
Array.isArray(cached.media)) {
|
28395
|
28434
|
|
28396
|
|
- cached.media.forEach(function(m) {
|
|
28435
|
+ cached.media.forEach(function (m) {
|
28397
|
28436
|
if (typeof m.sources === 'object') {
|
28398
|
|
- Object.keys(m.sources).forEach(function(s) {
|
|
28437
|
+ Object.keys(m.sources).forEach(function (s) {
|
28399
|
28438
|
if (s === ssrc) {
|
28400
|
28439
|
mLine.mid = m.mid;
|
28401
|
28440
|
}
|
|
@@ -28433,7 +28472,7 @@ Interop.prototype.toUnifiedPlan = function(desc) {
|
28433
|
28472
|
mLine.fingerprint = fingerprint;
|
28434
|
28473
|
mLine.port = port;
|
28435
|
28474
|
|
28436
|
|
- media[mLine.mid] = mLine;
|
|
28475
|
+ mid2ml[mLine.mid] = mLine;
|
28437
|
28476
|
}
|
28438
|
28477
|
});
|
28439
|
28478
|
}
|
|
@@ -28470,7 +28509,7 @@ Interop.prototype.toUnifiedPlan = function(desc) {
|
28470
|
28509
|
var mLine;
|
28471
|
28510
|
cached.media.some(function(ma) {
|
28472
|
28511
|
if (mo.mid == ma.mid) {
|
28473
|
|
- if (typeof media[mo.mid] === 'undefined') {
|
|
28512
|
+ if (typeof mid2ml[mo.mid] === 'undefined') {
|
28474
|
28513
|
|
28475
|
28514
|
// This is either an m-line containing a remote
|
28476
|
28515
|
// track only, or an m-line containing a remote
|
|
@@ -28527,8 +28566,8 @@ Interop.prototype.toUnifiedPlan = function(desc) {
|
28527
|
28566
|
Array.isArray(cached.media)) {
|
28528
|
28567
|
cached.media.forEach(function(pm) {
|
28529
|
28568
|
mids.push(pm.mid);
|
28530
|
|
- if (typeof media[pm.mid] !== 'undefined') {
|
28531
|
|
- session.media.push(media[pm.mid]);
|
|
28569
|
+ if (typeof mid2ml[pm.mid] !== 'undefined') {
|
|
28570
|
+ session.media.push(mid2ml[pm.mid]);
|
28532
|
28571
|
} else {
|
28533
|
28572
|
delete pm.msid;
|
28534
|
28573
|
delete pm.sources;
|
|
@@ -28540,10 +28579,27 @@ Interop.prototype.toUnifiedPlan = function(desc) {
|
28540
|
28579
|
}
|
28541
|
28580
|
|
28542
|
28581
|
// Add all the remaining (new) m-lines of the transformed SDP.
|
28543
|
|
- Object.keys(media).forEach(function(mid) {
|
|
28582
|
+ Object.keys(mid2ml).forEach(function(mid) {
|
28544
|
28583
|
if (mids.indexOf(mid) === -1) {
|
28545
|
28584
|
mids.push(mid);
|
28546
|
|
- session.media.push(media[mid]);
|
|
28585
|
+ if (typeof mid2ml[mid].msid === 'undefined') {
|
|
28586
|
+ // This is a remote recvonly channel. Add its SSRC to the
|
|
28587
|
+ // sendrecv channel.
|
|
28588
|
+ // TODO(gp) what if there is no sendrecv channel?
|
|
28589
|
+ session.media.some(function (ml) {
|
|
28590
|
+ if (ml.direction === 'sendrecv' && ml.type == mid2ml[mid].type) {
|
|
28591
|
+
|
|
28592
|
+ // this shouldn't have any ssrc-groups
|
|
28593
|
+ Object.keys(mid2ml[mid].sources).forEach(function (ssrc) {
|
|
28594
|
+ ml.sources[ssrc] = mid2ml[mid].sources[ssrc];
|
|
28595
|
+ });
|
|
28596
|
+
|
|
28597
|
+ return true;
|
|
28598
|
+ }
|
|
28599
|
+ });
|
|
28600
|
+ } else {
|
|
28601
|
+ session.media.push(mid2ml[mid]);
|
|
28602
|
+ }
|
28547
|
28603
|
}
|
28548
|
28604
|
});
|
28549
|
28605
|
}
|