|
@@ -25733,11 +25733,28 @@ Interop.prototype.toPlanB = function(desc) {
|
25733
|
25733
|
// Assign the sources to the channel.
|
25734
|
25734
|
channels[mLine.type].sources[ssrc] = mLine.sources[ssrc];
|
25735
|
25735
|
|
25736
|
|
- // In Plan B the msid is an SSRC attribute.
|
|
25736
|
+ // In Plan B the msid is an SSRC attribute. Also, we don't care
|
|
25737
|
+ // about the obsolete label and mslabel attributes.
|
25737
|
25738
|
channels[mLine.type].sources[ssrc].msid = mLine.msid;
|
|
25739
|
+
|
|
25740
|
+ // NOTE ssrcs in ssrc groups will share msids, as
|
|
25741
|
+ // draft-uberti-rtcweb-plan-00 mandates.
|
25738
|
25742
|
});
|
25739
|
25743
|
}
|
25740
|
25744
|
|
|
25745
|
+ // Add ssrc groups to the channel.
|
|
25746
|
+ if (typeof mLine.ssrcGroups !== 'undefined' &&
|
|
25747
|
+ Array.isArray(mLine.ssrcGroups)) {
|
|
25748
|
+
|
|
25749
|
+ // Create the ssrcGroups array, if it's not defined.
|
|
25750
|
+ if (typeof channel.ssrcGroups === 'undefined' ||
|
|
25751
|
+ !Array.isArray(channel.ssrcGroups)) {
|
|
25752
|
+ channel.ssrcGroups = [];
|
|
25753
|
+ }
|
|
25754
|
+
|
|
25755
|
+ channel.ssrcGroups = channel.ssrcGroups.concat(mLine.ssrcGroups);
|
|
25756
|
+ }
|
|
25757
|
+
|
25741
|
25758
|
if (channels[mLine.type] === mLine) {
|
25742
|
25759
|
// Copy ICE related stuff from the principal media line.
|
25743
|
25760
|
mLine.candidates = media[0].candidates;
|
|
@@ -25760,8 +25777,6 @@ Interop.prototype.toPlanB = function(desc) {
|
25760
|
25777
|
// Add the channel to the new media array.
|
25761
|
25778
|
session.media.push(mLine);
|
25762
|
25779
|
}
|
25763
|
|
-
|
25764
|
|
- // TODO(gp) add support for ssrc-group.
|
25765
|
25780
|
});
|
25766
|
25781
|
|
25767
|
25782
|
// We regenerate the BUNDLE group with the new mids.
|
|
@@ -25888,6 +25903,7 @@ Interop.prototype.toPlanA = function(desc) {
|
25888
|
25903
|
// With rtcp-mux and bundle all the channels should have the same ICE
|
25889
|
25904
|
// stuff.
|
25890
|
25905
|
var sources = channel.sources;
|
|
25906
|
+ var ssrcGroups = channel.ssrcGroups;
|
25891
|
25907
|
var candidates = channel.candidates;
|
25892
|
25908
|
var iceUfrag = channel.iceUfrag;
|
25893
|
25909
|
var icePwd = channel.icePwd;
|
|
@@ -25897,6 +25913,7 @@ Interop.prototype.toPlanA = function(desc) {
|
25897
|
25913
|
// We'll use the "channel" object as a prototype for each new "mLine"
|
25898
|
25914
|
// that we create, but first we need to clean it up a bit.
|
25899
|
25915
|
delete channel.sources;
|
|
25916
|
+ delete channel.ssrcGroups;
|
25900
|
25917
|
delete channel.candidates;
|
25901
|
25918
|
delete channel.iceUfrag;
|
25902
|
25919
|
delete channel.icePwd;
|
|
@@ -25904,13 +25921,63 @@ Interop.prototype.toPlanA = function(desc) {
|
25904
|
25921
|
delete channel.port;
|
25905
|
25922
|
delete channel.mid;
|
25906
|
25923
|
|
|
25924
|
+ // inverted ssrc group map
|
|
25925
|
+ var invertedGroups = {};
|
|
25926
|
+ if (typeof ssrcGroups !== 'undefined' && Array.isArray(ssrcGroups)) {
|
|
25927
|
+ ssrcGroups.forEach(function (ssrcGroup) {
|
|
25928
|
+
|
|
25929
|
+ // TODO(gp) find out how to receive simulcast with FF. For the
|
|
25930
|
+ // time being, hide it.
|
|
25931
|
+ if (ssrcGroup.semantics === 'SIM') {
|
|
25932
|
+ return;
|
|
25933
|
+ }
|
|
25934
|
+
|
|
25935
|
+ if (typeof ssrcGroup.ssrcs !== 'undefined' &&
|
|
25936
|
+ Array.isArray(ssrcGroup.ssrcs)) {
|
|
25937
|
+ ssrcGroup.ssrcs.forEach(function (ssrc) {
|
|
25938
|
+ if (typeof invertedGroups[ssrc] === 'undefined') {
|
|
25939
|
+ invertedGroups[ssrc] = [];
|
|
25940
|
+ }
|
|
25941
|
+
|
|
25942
|
+ invertedGroups[ssrc].push(ssrcGroup);
|
|
25943
|
+ });
|
|
25944
|
+ }
|
|
25945
|
+ });
|
|
25946
|
+ }
|
|
25947
|
+
|
|
25948
|
+ // ssrc to m-line index.
|
|
25949
|
+ var mLines = {};
|
|
25950
|
+
|
25907
|
25951
|
if (typeof sources === 'object') {
|
25908
|
25952
|
|
25909
|
25953
|
// Explode the Plan B channel sources with one m-line per source.
|
25910
|
25954
|
Object.keys(sources).forEach(function(ssrc) {
|
25911
|
25955
|
|
|
25956
|
+ var mLine;
|
|
25957
|
+ if (typeof invertedGroups[ssrc] !== 'undefined' &&
|
|
25958
|
+ Array.isArray(invertedGroups[ssrc])) {
|
|
25959
|
+ invertedGroups[ssrc].every(function (ssrcGroup) {
|
|
25960
|
+ // ssrcGroup.ssrcs *is* an Array, no need to check
|
|
25961
|
+ // again here.
|
|
25962
|
+ return ssrcGroup.ssrcs.every(function (related) {
|
|
25963
|
+ if (typeof mLines[related] === 'object') {
|
|
25964
|
+ mLine = mLines[related];
|
|
25965
|
+ return false;
|
|
25966
|
+ } else {
|
|
25967
|
+ return true;
|
|
25968
|
+ }
|
|
25969
|
+ });
|
|
25970
|
+ });
|
|
25971
|
+ }
|
|
25972
|
+
|
|
25973
|
+ if (typeof mLine === 'object') {
|
|
25974
|
+ // the m-line already exists. Just add the source.
|
|
25975
|
+ mLine.sources[ssrc] = sources[ssrc];
|
|
25976
|
+ delete sources[ssrc].msid;
|
|
25977
|
+ } else {
|
25912
|
25978
|
// Use the "channel" as a prototype for the "mLine".
|
25913
|
|
- var mLine = Object.create(channel);
|
|
25979
|
+ mLine = Object.create(channel);
|
|
25980
|
+ mLines[ssrc] = mLine;
|
25914
|
25981
|
|
25915
|
25982
|
// Assign the msid of the source to the m-line.
|
25916
|
25983
|
mLine.msid = sources[ssrc].msid;
|
|
@@ -25919,6 +25986,7 @@ Interop.prototype.toPlanA = function(desc) {
|
25919
|
25986
|
// We assign one SSRC per media line.
|
25920
|
25987
|
mLine.sources = {};
|
25921
|
25988
|
mLine.sources[ssrc] = sources[ssrc];
|
|
25989
|
+ mLine.ssrcGroups = invertedGroups[ssrc];
|
25922
|
25990
|
|
25923
|
25991
|
// Use the cached Plan A SDP (if it exists) to assign SSRCs to
|
25924
|
25992
|
// mids.
|
|
@@ -25966,9 +26034,9 @@ Interop.prototype.toPlanA = function(desc) {
|
25966
|
26034
|
mLine.port = port;
|
25967
|
26035
|
|
25968
|
26036
|
media[mLine.mid] = mLine;
|
|
26037
|
+ }
|
25969
|
26038
|
});
|
25970
|
26039
|
}
|
25971
|
|
- // TODO(gp) add support for ssrc-groups
|
25972
|
26040
|
});
|
25973
|
26041
|
|
25974
|
26042
|
// Rebuild the media array in the right order and add the missing mLines
|
|
@@ -26047,7 +26115,7 @@ Interop.prototype.toPlanA = function(desc) {
|
26047
|
26115
|
} else {
|
26048
|
26116
|
delete pm.msid;
|
26049
|
26117
|
delete pm.sources;
|
26050
|
|
- // TODO(gp) delete ssrc-groups
|
|
26118
|
+ delete pm.ssrcGroups;
|
26051
|
26119
|
pm.direction = 'recvonly';
|
26052
|
26120
|
session.media.push(pm);
|
26053
|
26121
|
}
|
|
@@ -26097,12 +26165,12 @@ var transform = require('sdp-transform');
|
26097
|
26165
|
|
26098
|
26166
|
exports.write = function(session, opts) {
|
26099
|
26167
|
|
26100
|
|
- // expand sources to ssrcs
|
26101
|
26168
|
if (typeof session !== 'undefined' &&
|
26102
|
26169
|
typeof session.media !== 'undefined' &&
|
26103
|
26170
|
Array.isArray(session.media)) {
|
26104
|
26171
|
|
26105
|
26172
|
session.media.forEach(function (mLine) {
|
|
26173
|
+ // expand sources to ssrcs
|
26106
|
26174
|
if (typeof mLine.sources !== 'undefined' &&
|
26107
|
26175
|
Object.keys(mLine.sources).length !== 0) {
|
26108
|
26176
|
mLine.ssrcs = [];
|
|
@@ -26118,6 +26186,17 @@ exports.write = function(session, opts) {
|
26118
|
26186
|
});
|
26119
|
26187
|
delete mLine.sources;
|
26120
|
26188
|
}
|
|
26189
|
+
|
|
26190
|
+ // join ssrcs in ssrc groups
|
|
26191
|
+ if (typeof mLine.ssrcGroups !== 'undefined' &&
|
|
26192
|
+ Array.isArray(mLine.ssrcGroups)) {
|
|
26193
|
+ mLine.ssrcGroups.forEach(function (ssrcGroup) {
|
|
26194
|
+ if (typeof ssrcGroup.ssrcs !== 'undefined' &&
|
|
26195
|
+ Array.isArray(ssrcGroup.ssrcs)) {
|
|
26196
|
+ ssrcGroup.ssrcs = ssrcGroup.ssrcs.join(' ');
|
|
26197
|
+ }
|
|
26198
|
+ });
|
|
26199
|
+ }
|
26121
|
26200
|
});
|
26122
|
26201
|
}
|
26123
|
26202
|
|
|
@@ -26141,8 +26220,8 @@ exports.parse = function(sdp) {
|
26141
|
26220
|
if (typeof session !== 'undefined' && typeof session.media !== 'undefined' &&
|
26142
|
26221
|
Array.isArray(session.media)) {
|
26143
|
26222
|
|
26144
|
|
- // group sources attributes by ssrc
|
26145
|
26223
|
session.media.forEach(function (mLine) {
|
|
26224
|
+ // group sources attributes by ssrc
|
26146
|
26225
|
if (typeof mLine.ssrcs !== 'undefined' && Array.isArray(mLine.ssrcs)) {
|
26147
|
26226
|
mLine.sources = {};
|
26148
|
26227
|
mLine.ssrcs.forEach(function (ssrc) {
|
|
@@ -26153,6 +26232,16 @@ exports.parse = function(sdp) {
|
26153
|
26232
|
|
26154
|
26233
|
delete mLine.ssrcs;
|
26155
|
26234
|
}
|
|
26235
|
+
|
|
26236
|
+ // split ssrcs in ssrc groups
|
|
26237
|
+ if (typeof mLine.ssrcGroups !== 'undefined' &&
|
|
26238
|
+ Array.isArray(mLine.ssrcGroups)) {
|
|
26239
|
+ mLine.ssrcGroups.forEach(function (ssrcGroup) {
|
|
26240
|
+ if (typeof ssrcGroup.ssrcs === 'string') {
|
|
26241
|
+ ssrcGroup.ssrcs = ssrcGroup.ssrcs.split(' ');
|
|
26242
|
+ }
|
|
26243
|
+ });
|
|
26244
|
+ }
|
26156
|
26245
|
});
|
26157
|
26246
|
}
|
26158
|
26247
|
// split group mids
|
|
@@ -26316,10 +26405,6 @@ var grammar = module.exports = {
|
26316
|
26405
|
name: 'direction',
|
26317
|
26406
|
reg: /^(sendrecv|recvonly|sendonly|inactive)/
|
26318
|
26407
|
},
|
26319
|
|
- { //a=bundle-only
|
26320
|
|
- name: 'bundleOnly',
|
26321
|
|
- reg: /^(bundle-only)/
|
26322
|
|
- },
|
26323
|
26408
|
{ //a=ice-lite
|
26324
|
26409
|
name: 'icelite',
|
26325
|
26410
|
reg: /^(ice-lite)/
|
|
@@ -26373,6 +26458,12 @@ var grammar = module.exports = {
|
26373
|
26458
|
names: ['id', 'attribute', 'value'],
|
26374
|
26459
|
format: "ssrc:%d %s:%s"
|
26375
|
26460
|
},
|
|
26461
|
+ { //a=ssrc-group:FEC 1 2
|
|
26462
|
+ push: "ssrcGroups",
|
|
26463
|
+ reg: /^ssrc-group:(\w*) (.*)/,
|
|
26464
|
+ names: ['semantics', 'ssrcs'],
|
|
26465
|
+ format: "ssrc-group:%s %s"
|
|
26466
|
+ },
|
26376
|
26467
|
{ //a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV
|
26377
|
26468
|
name: "msidSemantic",
|
26378
|
26469
|
reg: /^msid-semantic:\s?(\w*) (\S*)/,
|
|
@@ -26482,30 +26573,6 @@ exports.parse = function (sdp) {
|
26482
|
26573
|
});
|
26483
|
26574
|
|
26484
|
26575
|
session.media = media; // link it up
|
26485
|
|
-
|
26486
|
|
- // group sources attributes by ssrc
|
26487
|
|
- media.forEach(function (mLine) {
|
26488
|
|
- if (typeof mLine.ssrcs !== 'undefined' && Array.isArray(mLine.ssrcs)) {
|
26489
|
|
- mLine.sources = {};
|
26490
|
|
- mLine.ssrcs.forEach(function (ssrc) {
|
26491
|
|
- if (!mLine.sources[ssrc.id])
|
26492
|
|
- mLine.sources[ssrc.id] = {};
|
26493
|
|
- mLine.sources[ssrc.id][ssrc.attribute] = ssrc.value;
|
26494
|
|
- });
|
26495
|
|
-
|
26496
|
|
- delete mLine.ssrcs;
|
26497
|
|
- }
|
26498
|
|
- });
|
26499
|
|
-
|
26500
|
|
- // split group mids
|
26501
|
|
- if (typeof session.groups !== 'undefined' && Array.isArray(session.groups)) {
|
26502
|
|
- session.groups.forEach(function (g) {
|
26503
|
|
- if (typeof g.mids === 'string') {
|
26504
|
|
- g.mids = g.mids.split(' ');
|
26505
|
|
- }
|
26506
|
|
- });
|
26507
|
|
- }
|
26508
|
|
-
|
26509
|
26576
|
return session;
|
26510
|
26577
|
};
|
26511
|
26578
|
|
|
@@ -26613,29 +26680,8 @@ module.exports = function (session, opts) {
|
26613
|
26680
|
if (mLine.payloads == null) {
|
26614
|
26681
|
mLine.payloads = "";
|
26615
|
26682
|
}
|
26616
|
|
-
|
26617
|
|
- // expand sources to ssrcs
|
26618
|
|
- if (typeof mLine.sources !== 'undefined' && Object.keys(mLine.sources).length !== 0) {
|
26619
|
|
- mLine.ssrcs = [];
|
26620
|
|
- Object.keys(mLine.sources).forEach(function (ssrc) {
|
26621
|
|
- var source = mLine.sources[ssrc];
|
26622
|
|
- Object.keys(source).forEach(function (attribute) {
|
26623
|
|
- mLine.ssrcs.push({id: ssrc, attribute: attribute, value: source[attribute]})
|
26624
|
|
- });
|
26625
|
|
- });
|
26626
|
|
- delete mLine.sources;
|
26627
|
|
- }
|
26628
|
26683
|
});
|
26629
|
26684
|
|
26630
|
|
- // join group mids
|
26631
|
|
- if (typeof session.groups !== 'undefined' && Array.isArray(session.groups)) {
|
26632
|
|
- session.groups.forEach(function (g) {
|
26633
|
|
- if (typeof g.mids !== 'undefined' && Array.isArray(g.mids)) {
|
26634
|
|
- g.mids = g.mids.join(' ');
|
26635
|
|
- }
|
26636
|
|
- });
|
26637
|
|
- }
|
26638
|
|
-
|
26639
|
26685
|
var outerOrder = opts.outerOrder || defaultOuterOrder;
|
26640
|
26686
|
var innerOrder = opts.innerOrder || defaultInnerOrder;
|
26641
|
26687
|
var sdp = [];
|
|
@@ -26643,10 +26689,10 @@ module.exports = function (session, opts) {
|
26643
|
26689
|
// loop through outerOrder for matching properties on session
|
26644
|
26690
|
outerOrder.forEach(function (type) {
|
26645
|
26691
|
grammar[type].forEach(function (obj) {
|
26646
|
|
- if (obj.name in session && typeof session[obj.name] !== 'undefined') {
|
|
26692
|
+ if (obj.name in session && session[obj.name] != null) {
|
26647
|
26693
|
sdp.push(makeLine(type, obj, session));
|
26648
|
26694
|
}
|
26649
|
|
- else if (obj.push in session && typeof session[obj.push] !== 'undefined') {
|
|
26695
|
+ else if (obj.push in session && session[obj.push] != null) {
|
26650
|
26696
|
session[obj.push].forEach(function (el) {
|
26651
|
26697
|
sdp.push(makeLine(type, obj, el));
|
26652
|
26698
|
});
|
|
@@ -26660,10 +26706,10 @@ module.exports = function (session, opts) {
|
26660
|
26706
|
|
26661
|
26707
|
innerOrder.forEach(function (type) {
|
26662
|
26708
|
grammar[type].forEach(function (obj) {
|
26663
|
|
- if (obj.name in mLine && typeof mLine[obj.name] !== 'undefined') {
|
|
26709
|
+ if (obj.name in mLine && mLine[obj.name] != null) {
|
26664
|
26710
|
sdp.push(makeLine(type, obj, mLine));
|
26665
|
26711
|
}
|
26666
|
|
- else if (obj.push in mLine && typeof mLine[obj.push] !== 'undefined') {
|
|
26712
|
+ else if (obj.push in mLine && mLine[obj.push] != null) {
|
26667
|
26713
|
mLine[obj.push].forEach(function (el) {
|
26668
|
26714
|
sdp.push(makeLine(type, obj, el));
|
26669
|
26715
|
});
|