@webex/plugin-meetings 3.0.0-beta.6 → 3.0.0-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/multistream/remoteMedia.js +7 -2
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/package.json +17 -18
- package/src/multistream/remoteMedia.ts +10 -1
- package/test/unit/spec/multistream/remoteMedia.ts +8 -0
- package/test/unit/spec/multistream/remoteMediaManager.ts +58 -0
- package/dist/peer-connection-manager/util.js +0 -124
- package/dist/peer-connection-manager/util.js.map +0 -1
- package/src/peer-connection-manager/util.ts +0 -117
- package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -389
|
@@ -38,7 +38,8 @@ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflec
|
|
|
38
38
|
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !_Reflect$construct) return false; if (_Reflect$construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
39
39
|
|
|
40
40
|
var RemoteMediaEvents = {
|
|
41
|
-
SourceUpdate: _receiveSlot.ReceiveSlotEvents.SourceUpdate
|
|
41
|
+
SourceUpdate: _receiveSlot.ReceiveSlotEvents.SourceUpdate,
|
|
42
|
+
Stopped: 'stopped'
|
|
42
43
|
};
|
|
43
44
|
exports.RemoteMediaEvents = RemoteMediaEvents;
|
|
44
45
|
|
|
@@ -146,6 +147,10 @@ var RemoteMedia = /*#__PURE__*/function (_EventsScope) {
|
|
|
146
147
|
this.cancelMediaRequest(commit);
|
|
147
148
|
(_this$receiveSlot = this.receiveSlot) === null || _this$receiveSlot === void 0 ? void 0 : _this$receiveSlot.removeAllListeners();
|
|
148
149
|
this.receiveSlot = undefined;
|
|
150
|
+
this.emit({
|
|
151
|
+
file: 'multistream/remoteMedia',
|
|
152
|
+
function: 'stop'
|
|
153
|
+
}, RemoteMediaEvents.Stopped, {});
|
|
149
154
|
}
|
|
150
155
|
/**
|
|
151
156
|
* Sends a new media request. This method can only be used for receiver-selected policy,
|
|
@@ -203,7 +208,7 @@ var RemoteMedia = /*#__PURE__*/function (_EventsScope) {
|
|
|
203
208
|
|
|
204
209
|
if (this.receiveSlot) {
|
|
205
210
|
var scope = {
|
|
206
|
-
file: '
|
|
211
|
+
file: 'multistream/remoteMedia',
|
|
207
212
|
function: 'setupEventListeners'
|
|
208
213
|
};
|
|
209
214
|
this.receiveSlot.on(_receiveSlot.ReceiveSlotEvents.SourceUpdate, function (data) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["RemoteMediaEvents","SourceUpdate","ReceiveSlotEvents","getMaxFs","paneSize","maxFs","LoggerProxy","logger","warn","remoteMediaCounter","RemoteMedia","receiveSlot","mediaRequestManager","options","setupEventListeners","id","commit","cancelMediaRequest","removeAllListeners","undefined","csi","mediaRequestId","Error","addRequest","policyInfo","policy","receiveSlots","codecInfo","resolution","codec","cancelRequest","scope","
|
|
1
|
+
{"version":3,"names":["RemoteMediaEvents","SourceUpdate","ReceiveSlotEvents","Stopped","getMaxFs","paneSize","maxFs","LoggerProxy","logger","warn","remoteMediaCounter","RemoteMedia","receiveSlot","mediaRequestManager","options","setupEventListeners","id","commit","cancelMediaRequest","removeAllListeners","undefined","emit","file","function","csi","mediaRequestId","Error","addRequest","policyInfo","policy","receiveSlots","codecInfo","resolution","codec","cancelRequest","scope","on","data","mediaType","memberId","sourceState","stream","EventsScope"],"sources":["remoteMedia.ts"],"sourcesContent":["/* eslint-disable valid-jsdoc */\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport EventsScope from '../common/events/events-scope';\n\nimport {MediaRequestId, MediaRequestManager} from './mediaRequestManager';\nimport {CSI, ReceiveSlot, ReceiveSlotEvents} from './receiveSlot';\n\nexport const RemoteMediaEvents = {\n SourceUpdate: ReceiveSlotEvents.SourceUpdate,\n Stopped: 'stopped',\n};\n\nexport type RemoteVideoResolution =\n | 'thumbnail' // the smallest possible resolution, 90p or less\n | 'very small' // 180p or less\n | 'small' // 360p or less\n | 'medium' // 720p or less\n | 'large' // 1080p or less\n | 'best'; // highest possible resolution\n\n/**\n * Converts pane size into h264 maxFs\n * @param {PaneSize} paneSize\n * @returns {number}\n */\nexport function getMaxFs(paneSize: RemoteVideoResolution): number {\n let maxFs;\n\n switch (paneSize) {\n case 'thumbnail':\n maxFs = 60;\n break;\n case 'very small':\n maxFs = 240;\n break;\n case 'small':\n maxFs = 920;\n break;\n case 'medium':\n maxFs = 3600;\n break;\n case 'large':\n maxFs = 8192;\n break;\n case 'best':\n maxFs = 8192; // for now 'best' is 1080p, so same as 'large'\n break;\n default:\n LoggerProxy.logger.warn(\n `RemoteMedia#getMaxFs --> unsupported paneSize: ${paneSize}, using \"medium\" instead`\n );\n maxFs = 3600;\n }\n\n return maxFs;\n}\n\ntype Options = {\n resolution?: RemoteVideoResolution; // applies only to groups of type MC.MediaType.VideoMain and MC.MediaType.VideoSlides\n};\n\nexport type RemoteMediaId = string;\n\nlet remoteMediaCounter = 0;\n\n/**\n * Class representing a remote audio/video stream.\n *\n * Internally it is associated with a specific receive slot\n * and a media request for it.\n */\nexport class RemoteMedia extends EventsScope {\n private receiveSlot?: ReceiveSlot;\n\n private readonly mediaRequestManager: MediaRequestManager;\n\n private readonly options: Options;\n\n private mediaRequestId?: MediaRequestId;\n\n public readonly id: RemoteMediaId;\n\n /**\n * Constructs RemoteMedia instance\n *\n * @param receiveSlot\n * @param mediaRequestManager\n * @param options\n */\n constructor(\n receiveSlot: ReceiveSlot,\n mediaRequestManager: MediaRequestManager,\n options?: Options\n ) {\n super();\n remoteMediaCounter += 1;\n this.receiveSlot = receiveSlot;\n this.mediaRequestManager = mediaRequestManager;\n this.options = options || {};\n this.setupEventListeners();\n this.id = `RM${remoteMediaCounter}-${this.receiveSlot.id}`;\n }\n\n /**\n * Invalidates the remote media by clearing the reference to a receive slot and\n * cancelling the media request.\n * After this call the remote media is unusable.\n *\n * @param {boolean} commit - whether to commit the cancellation of the media request\n * @internal\n */\n public stop(commit: boolean = true) {\n this.cancelMediaRequest(commit);\n this.receiveSlot?.removeAllListeners();\n this.receiveSlot = undefined;\n this.emit(\n {\n file: 'multistream/remoteMedia',\n function: 'stop',\n },\n RemoteMediaEvents.Stopped,\n {}\n );\n }\n\n /**\n * Sends a new media request. This method can only be used for receiver-selected policy,\n * because only in that policy we have a 1-1 relationship between RemoteMedia and MediaRequest\n * and the request id is then stored in this RemoteMedia instance.\n * For active-speaker policy, the same request is shared among many RemoteMedia instances,\n * so it's managed through RemoteMediaGroup\n *\n * @internal\n */\n public sendMediaRequest(csi: CSI, commit: boolean) {\n if (this.mediaRequestId) {\n this.cancelMediaRequest(false);\n }\n\n if (!this.receiveSlot) {\n throw new Error('sendMediaRequest() called on an invalidated RemoteMedia instance');\n }\n\n this.mediaRequestId = this.mediaRequestManager.addRequest(\n {\n policyInfo: {\n policy: 'receiver-selected',\n csi,\n },\n receiveSlots: [this.receiveSlot],\n codecInfo: this.options.resolution && {\n codec: 'h264',\n maxFs: getMaxFs(this.options.resolution),\n },\n },\n commit\n );\n }\n\n /**\n * @internal\n */\n public cancelMediaRequest(commit: boolean) {\n if (this.mediaRequestId) {\n this.mediaRequestManager.cancelRequest(this.mediaRequestId, commit);\n this.mediaRequestId = undefined;\n }\n }\n\n /**\n * registers event listeners on the receive slot and forwards all the events\n */\n private setupEventListeners() {\n if (this.receiveSlot) {\n const scope = {\n file: 'multistream/remoteMedia',\n function: 'setupEventListeners',\n };\n\n this.receiveSlot.on(ReceiveSlotEvents.SourceUpdate, (data) => {\n this.emit(scope, RemoteMediaEvents.SourceUpdate, data);\n });\n }\n }\n\n /**\n * Getter for mediaType\n */\n public get mediaType() {\n return this.receiveSlot?.mediaType;\n }\n\n /**\n * Getter for memberId\n */\n public get memberId() {\n return this.receiveSlot?.memberId;\n }\n\n /**\n * Getter for csi\n */\n public get csi() {\n return this.receiveSlot?.csi;\n }\n\n /**\n * Getter for source state\n */\n public get sourceState() {\n return this.receiveSlot?.sourceState;\n }\n\n /**\n * Getter for remote media stream\n */\n public get stream() {\n return this.receiveSlot?.stream;\n }\n\n /**\n * @internal\n * @returns {ReceiveSlot}\n */\n public getUnderlyingReceiveSlot() {\n return this.receiveSlot;\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/plugin-meetings",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
|
|
6
6
|
"contributors": [
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
]
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@webex/plugin-meetings": "3.0.0-beta.
|
|
32
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
33
|
-
"@webex/test-helper-mocha": "3.0.0-beta.
|
|
34
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
35
|
-
"@webex/test-helper-retry": "3.0.0-beta.
|
|
36
|
-
"@webex/test-helper-test-users": "3.0.0-beta.
|
|
31
|
+
"@webex/plugin-meetings": "3.0.0-beta.8",
|
|
32
|
+
"@webex/test-helper-chai": "3.0.0-beta.8",
|
|
33
|
+
"@webex/test-helper-mocha": "3.0.0-beta.8",
|
|
34
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.8",
|
|
35
|
+
"@webex/test-helper-retry": "3.0.0-beta.8",
|
|
36
|
+
"@webex/test-helper-test-users": "3.0.0-beta.8",
|
|
37
37
|
"chai": "^4.3.4",
|
|
38
38
|
"chai-as-promised": "^7.1.1",
|
|
39
39
|
"jsdom-global": "3.0.2",
|
|
@@ -41,18 +41,17 @@
|
|
|
41
41
|
"typed-emitter": "^2.1.0"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@webex/common": "3.0.0-beta.
|
|
44
|
+
"@webex/common": "3.0.0-beta.8",
|
|
45
45
|
"@webex/internal-media-core": "^0.0.17-beta",
|
|
46
|
-
"@webex/internal-plugin-conversation": "3.0.0-beta.
|
|
47
|
-
"@webex/internal-plugin-device": "3.0.0-beta.
|
|
48
|
-
"@webex/internal-plugin-mercury": "3.0.0-beta.
|
|
49
|
-
"@webex/internal-plugin-metrics": "3.0.0-beta.
|
|
50
|
-
"@webex/internal-plugin-support": "3.0.0-beta.
|
|
51
|
-
"@webex/internal-plugin-user": "3.0.0-beta.
|
|
52
|
-
"@webex/plugin-people": "3.0.0-beta.
|
|
53
|
-
"@webex/plugin-rooms": "3.0.0-beta.
|
|
54
|
-
"@webex/
|
|
55
|
-
"@webex/webex-core": "3.0.0-beta.6",
|
|
46
|
+
"@webex/internal-plugin-conversation": "3.0.0-beta.8",
|
|
47
|
+
"@webex/internal-plugin-device": "3.0.0-beta.8",
|
|
48
|
+
"@webex/internal-plugin-mercury": "3.0.0-beta.8",
|
|
49
|
+
"@webex/internal-plugin-metrics": "3.0.0-beta.8",
|
|
50
|
+
"@webex/internal-plugin-support": "3.0.0-beta.8",
|
|
51
|
+
"@webex/internal-plugin-user": "3.0.0-beta.8",
|
|
52
|
+
"@webex/plugin-people": "3.0.0-beta.8",
|
|
53
|
+
"@webex/plugin-rooms": "3.0.0-beta.8",
|
|
54
|
+
"@webex/webex-core": "3.0.0-beta.8",
|
|
56
55
|
"bowser": "^2.11.0",
|
|
57
56
|
"btoa": "^1.2.1",
|
|
58
57
|
"dotenv": "^4.0.0",
|
|
@@ -7,6 +7,7 @@ import {CSI, ReceiveSlot, ReceiveSlotEvents} from './receiveSlot';
|
|
|
7
7
|
|
|
8
8
|
export const RemoteMediaEvents = {
|
|
9
9
|
SourceUpdate: ReceiveSlotEvents.SourceUpdate,
|
|
10
|
+
Stopped: 'stopped',
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
export type RemoteVideoResolution =
|
|
@@ -112,6 +113,14 @@ export class RemoteMedia extends EventsScope {
|
|
|
112
113
|
this.cancelMediaRequest(commit);
|
|
113
114
|
this.receiveSlot?.removeAllListeners();
|
|
114
115
|
this.receiveSlot = undefined;
|
|
116
|
+
this.emit(
|
|
117
|
+
{
|
|
118
|
+
file: 'multistream/remoteMedia',
|
|
119
|
+
function: 'stop',
|
|
120
|
+
},
|
|
121
|
+
RemoteMediaEvents.Stopped,
|
|
122
|
+
{}
|
|
123
|
+
);
|
|
115
124
|
}
|
|
116
125
|
|
|
117
126
|
/**
|
|
@@ -164,7 +173,7 @@ export class RemoteMedia extends EventsScope {
|
|
|
164
173
|
private setupEventListeners() {
|
|
165
174
|
if (this.receiveSlot) {
|
|
166
175
|
const scope = {
|
|
167
|
-
file: '
|
|
176
|
+
file: 'multistream/remoteMedia',
|
|
168
177
|
function: 'setupEventListeners',
|
|
169
178
|
};
|
|
170
179
|
|
|
@@ -184,8 +184,16 @@ describe('RemoteMedia', () => {
|
|
|
184
184
|
it('cancels media request, unsets the receive slot and removes all the listeners from it', () => {
|
|
185
185
|
const cancelMediaRequestSpy = sinon.spy(remoteMedia, 'cancelMediaRequest');
|
|
186
186
|
|
|
187
|
+
let stoppedListenerCalled = false;
|
|
188
|
+
|
|
189
|
+
remoteMedia.on(RemoteMediaEvents.Stopped, () => {
|
|
190
|
+
stoppedListenerCalled = true;
|
|
191
|
+
});
|
|
192
|
+
|
|
187
193
|
remoteMedia.stop(true);
|
|
188
194
|
|
|
195
|
+
assert.isTrue(stoppedListenerCalled);
|
|
196
|
+
|
|
189
197
|
assert.calledOnce(cancelMediaRequestSpy);
|
|
190
198
|
assert.calledWith(cancelMediaRequestSpy, true);
|
|
191
199
|
|
|
@@ -542,6 +542,64 @@ describe('RemoteMediaManager', () => {
|
|
|
542
542
|
});
|
|
543
543
|
});
|
|
544
544
|
|
|
545
|
+
it('stops all current video remoteMedia instances when switching to new layout', async () => {
|
|
546
|
+
const audioStopStubs = [];
|
|
547
|
+
const videoStopStubs = [];
|
|
548
|
+
|
|
549
|
+
const config = cloneDeep(DefaultTestConfiguration);
|
|
550
|
+
|
|
551
|
+
// start with the stage layout because it has both active speaker and receiver selected panes
|
|
552
|
+
config.video.initialLayoutId = 'Stage';
|
|
553
|
+
|
|
554
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
555
|
+
fakeReceiveSlotManager,
|
|
556
|
+
fakeMediaRequestManagers,
|
|
557
|
+
config
|
|
558
|
+
);
|
|
559
|
+
|
|
560
|
+
// mock all stop() methods for all remote audio objects we get with AudioCreated event
|
|
561
|
+
remoteMediaManager.on(Event.AudioCreated, (audio: RemoteMediaGroup) => {
|
|
562
|
+
audio
|
|
563
|
+
.getRemoteMedia()
|
|
564
|
+
.forEach((remoteAudio) => audioStopStubs.push(sinon.stub(remoteAudio, 'stop')));
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
// mock all stop() methods for all remote video objects we get with VideoLayoutChanged event
|
|
568
|
+
remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
|
|
569
|
+
Object.values(layoutInfo.activeSpeakerVideoPanes).forEach((group) =>
|
|
570
|
+
group
|
|
571
|
+
.getRemoteMedia()
|
|
572
|
+
.forEach((remoteMedia) => videoStopStubs.push(sinon.stub(remoteMedia, 'stop')))
|
|
573
|
+
);
|
|
574
|
+
|
|
575
|
+
Object.values(layoutInfo.memberVideoPanes).forEach((pane) => {
|
|
576
|
+
videoStopStubs.push(sinon.stub(pane, 'stop'));
|
|
577
|
+
});
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
await remoteMediaManager.start();
|
|
581
|
+
|
|
582
|
+
// sanity check that we've got all our stop() mocks setup correctly
|
|
583
|
+
assert.strictEqual(audioStopStubs.length, 3);
|
|
584
|
+
assert.strictEqual(videoStopStubs.length, 10); // 10 = 6 thumbnail panes + 4 stage panes
|
|
585
|
+
|
|
586
|
+
// next, we'll change the layout, we don't care about the new video panes from the new layout, so unregister the event listeners
|
|
587
|
+
remoteMediaManager.removeAllListeners();
|
|
588
|
+
|
|
589
|
+
await remoteMediaManager.setLayout('AllEqual');
|
|
590
|
+
|
|
591
|
+
// check that NONE of the audio RemoteMedia instances were stopped
|
|
592
|
+
audioStopStubs.forEach((audioStopStub) => {
|
|
593
|
+
assert.notCalled(audioStopStub);
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
// check that ALL of the video RemoteMedia instances were stopped
|
|
597
|
+
videoStopStubs.forEach((videoStopStub) => {
|
|
598
|
+
assert.calledOnce(videoStopStub);
|
|
599
|
+
assert.calledWith(videoStopStub, false);
|
|
600
|
+
});
|
|
601
|
+
});
|
|
602
|
+
|
|
545
603
|
describe('switching between different receiver selected layouts', () => {
|
|
546
604
|
let fakeSlots: {[key: ReceiveSlotId]: FakeSlot};
|
|
547
605
|
let slotCounter: number;
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
|
|
4
|
-
|
|
5
|
-
var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
|
|
6
|
-
|
|
7
|
-
_Object$defineProperty(exports, "__esModule", {
|
|
8
|
-
value: true
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
exports.default = void 0;
|
|
12
|
-
|
|
13
|
-
var _parseInt2 = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/parse-int"));
|
|
14
|
-
|
|
15
|
-
var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
|
|
16
|
-
|
|
17
|
-
var _tsSdp = require("@webex/ts-sdp");
|
|
18
|
-
|
|
19
|
-
var PeerConnectionUtils = {}; // max-fs values for all H264 profile levels
|
|
20
|
-
|
|
21
|
-
var maxFsForProfileLevel = {
|
|
22
|
-
10: 99,
|
|
23
|
-
11: 396,
|
|
24
|
-
12: 396,
|
|
25
|
-
13: 396,
|
|
26
|
-
20: 396,
|
|
27
|
-
21: 792,
|
|
28
|
-
22: 1620,
|
|
29
|
-
30: 1620,
|
|
30
|
-
31: 3600,
|
|
31
|
-
32: 5120,
|
|
32
|
-
40: 8192,
|
|
33
|
-
41: 8192,
|
|
34
|
-
42: 8704,
|
|
35
|
-
50: 22080,
|
|
36
|
-
51: 36864,
|
|
37
|
-
52: 36864,
|
|
38
|
-
60: 139264,
|
|
39
|
-
61: 139264,
|
|
40
|
-
62: 139264
|
|
41
|
-
};
|
|
42
|
-
var framesPerSecond = 30;
|
|
43
|
-
/**
|
|
44
|
-
* Convert C line to IPv4
|
|
45
|
-
* @param {string} sdp
|
|
46
|
-
* @returns {string}
|
|
47
|
-
*/
|
|
48
|
-
|
|
49
|
-
PeerConnectionUtils.convertCLineToIpv4 = function (sdp) {
|
|
50
|
-
var replaceSdp = sdp; // TODO: remove this once linus supports Ipv6 c line.currently linus rejects SDP with c line having ipv6 candidates we are
|
|
51
|
-
// mocking ipv6 to ipv4 candidates
|
|
52
|
-
// https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-299232
|
|
53
|
-
|
|
54
|
-
replaceSdp = replaceSdp.replace(/c=IN IP6 .*/gi, 'c=IN IP4 0.0.0.0');
|
|
55
|
-
return replaceSdp;
|
|
56
|
-
};
|
|
57
|
-
/**
|
|
58
|
-
* estimate profile levels for max-fs & max-mbps values
|
|
59
|
-
* @param {string} sdp
|
|
60
|
-
* @param {number} maxFsValue
|
|
61
|
-
* @returns {string}
|
|
62
|
-
*/
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
PeerConnectionUtils.adjustH264Profile = function (sdp, maxFsValue) {
|
|
66
|
-
// converting with ts-sdp parser, no munging
|
|
67
|
-
var parsedSdp = (0, _tsSdp.parse)(sdp);
|
|
68
|
-
parsedSdp.avMedia.forEach(function (media) {
|
|
69
|
-
if (media.type === 'video') {
|
|
70
|
-
media.codecs.forEach(function (codec) {
|
|
71
|
-
var _codec$name;
|
|
72
|
-
|
|
73
|
-
if (((_codec$name = codec.name) === null || _codec$name === void 0 ? void 0 : _codec$name.toUpperCase()) === 'H264') {
|
|
74
|
-
// there should really be just 1 fmtp line, but just in case, we process all of them
|
|
75
|
-
codec.fmtParams = codec.fmtParams.map(function (fmtp) {
|
|
76
|
-
var parsedRegex = fmtp.match(/(.*)profile-level-id=(\w{4})(\w{2})(.*)/);
|
|
77
|
-
|
|
78
|
-
if (parsedRegex && parsedRegex.length === 5) {
|
|
79
|
-
var stuffBeforeProfileLevelId = parsedRegex[1];
|
|
80
|
-
var profile = parsedRegex[2].toLowerCase();
|
|
81
|
-
var levelId = (0, _parseInt2.default)(parsedRegex[3], 16);
|
|
82
|
-
var stuffAfterProfileLevelId = parsedRegex[4];
|
|
83
|
-
|
|
84
|
-
if (!maxFsForProfileLevel[levelId]) {
|
|
85
|
-
throw new Error("found unsupported h264 profile level id value in the SDP: ".concat(levelId));
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (maxFsForProfileLevel[levelId] === maxFsValue) {
|
|
89
|
-
// profile level already matches our desired max-fs value, so we don't need to do anything
|
|
90
|
-
return fmtp;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (maxFsForProfileLevel[levelId] < maxFsValue) {
|
|
94
|
-
// profile level has too low max-fs, so we need to override it (this is upgrading)
|
|
95
|
-
return "".concat(fmtp, ";max-fs=").concat(maxFsValue, ";max-mbps=").concat(maxFsValue * framesPerSecond);
|
|
96
|
-
} // profile level has too high max-fs value, so we need to use a lower level
|
|
97
|
-
// find highest level that has the matching maxFs
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
var newLevelId = (0, _keys.default)(maxFsForProfileLevel).reverse().find(function (key) {
|
|
101
|
-
return maxFsForProfileLevel[key] === maxFsValue;
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
if (newLevelId) {
|
|
105
|
-
// Object.keys returns keys as strings, so we need to parse it to an int again and then convert to hex
|
|
106
|
-
var newLevelIdHex = (0, _parseInt2.default)(newLevelId, 10).toString(16);
|
|
107
|
-
return "".concat(stuffBeforeProfileLevelId, "profile-level-id=").concat(profile).concat(newLevelIdHex, ";max-mbps=").concat(maxFsValue * framesPerSecond).concat(stuffAfterProfileLevelId);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
throw new Error("unsupported maxFsValue: ".concat(maxFsValue));
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return fmtp;
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
return parsedSdp.toString();
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
var _default = PeerConnectionUtils;
|
|
123
|
-
exports.default = _default;
|
|
124
|
-
//# sourceMappingURL=util.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["PeerConnectionUtils","maxFsForProfileLevel","framesPerSecond","convertCLineToIpv4","sdp","replaceSdp","replace","adjustH264Profile","maxFsValue","parsedSdp","parse","avMedia","forEach","media","type","codecs","codec","name","toUpperCase","fmtParams","map","fmtp","parsedRegex","match","length","stuffBeforeProfileLevelId","profile","toLowerCase","levelId","stuffAfterProfileLevelId","Error","newLevelId","reverse","find","key","newLevelIdHex","toString"],"sources":["util.ts"],"sourcesContent":["import { parse } from '@webex/ts-sdp';\n\ninterface IPeerConnectionUtils {\n convertCLineToIpv4: (sdp: string) => string;\n adjustH264Profile: (sdp: string, maxFsValue: number) => string;\n}\n\nconst PeerConnectionUtils = {} as IPeerConnectionUtils;\n\n// max-fs values for all H264 profile levels\nconst maxFsForProfileLevel = {\n 10: 99,\n 11: 396,\n 12: 396,\n 13: 396,\n 20: 396,\n 21: 792,\n 22: 1620,\n 30: 1620,\n 31: 3600,\n 32: 5120,\n 40: 8192,\n 41: 8192,\n 42: 8704,\n 50: 22080,\n 51: 36864,\n 52: 36864,\n 60: 139264,\n 61: 139264,\n 62: 139264,\n};\n\nconst framesPerSecond = 30;\n\n/**\n * Convert C line to IPv4\n * @param {string} sdp\n * @returns {string}\n */\nPeerConnectionUtils.convertCLineToIpv4 = (sdp: string) => {\n let replaceSdp = sdp;\n\n // TODO: remove this once linus supports Ipv6 c line.currently linus rejects SDP with c line having ipv6 candidates we are\n // mocking ipv6 to ipv4 candidates\n // https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-299232\n replaceSdp = replaceSdp.replace(/c=IN IP6 .*/gi, 'c=IN IP4 0.0.0.0');\n\n return replaceSdp;\n};\n\n/**\n * estimate profile levels for max-fs & max-mbps values\n * @param {string} sdp\n * @param {number} maxFsValue\n * @returns {string}\n */\nPeerConnectionUtils.adjustH264Profile = (sdp: string, maxFsValue: number) => {\n // converting with ts-sdp parser, no munging\n const parsedSdp = parse(sdp);\n\n parsedSdp.avMedia.forEach((media) => {\n if (media.type === 'video') {\n media.codecs.forEach((codec) => {\n if (codec.name?.toUpperCase() === 'H264') {\n // there should really be just 1 fmtp line, but just in case, we process all of them\n codec.fmtParams = codec.fmtParams.map((fmtp) => {\n const parsedRegex = fmtp.match(/(.*)profile-level-id=(\\w{4})(\\w{2})(.*)/);\n\n if (parsedRegex && parsedRegex.length === 5) {\n const stuffBeforeProfileLevelId = parsedRegex[1];\n const profile = parsedRegex[2].toLowerCase();\n const levelId = parseInt(parsedRegex[3], 16);\n const stuffAfterProfileLevelId = parsedRegex[4];\n\n if (!maxFsForProfileLevel[levelId]) {\n throw new Error(\n `found unsupported h264 profile level id value in the SDP: ${levelId}`\n );\n }\n\n if (maxFsForProfileLevel[levelId] === maxFsValue) {\n // profile level already matches our desired max-fs value, so we don't need to do anything\n return fmtp;\n }\n if (maxFsForProfileLevel[levelId] < maxFsValue) {\n // profile level has too low max-fs, so we need to override it (this is upgrading)\n return `${fmtp};max-fs=${maxFsValue};max-mbps=${maxFsValue * framesPerSecond}`;\n }\n\n // profile level has too high max-fs value, so we need to use a lower level\n\n // find highest level that has the matching maxFs\n const newLevelId = Object.keys(maxFsForProfileLevel)\n .reverse()\n .find((key) => maxFsForProfileLevel[key] === maxFsValue);\n\n if (newLevelId) {\n // Object.keys returns keys as strings, so we need to parse it to an int again and then convert to hex\n const newLevelIdHex = parseInt(newLevelId, 10).toString(16);\n\n return `${stuffBeforeProfileLevelId}profile-level-id=${profile}${newLevelIdHex};max-mbps=${maxFsValue * framesPerSecond}${stuffAfterProfileLevelId}`;\n }\n\n throw new Error(`unsupported maxFsValue: ${maxFsValue}`);\n }\n\n return fmtp;\n });\n }\n });\n }\n });\n\n return parsedSdp.toString();\n};\n\nexport default PeerConnectionUtils;\n"],"mappings":"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"}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { parse } from '@webex/ts-sdp';
|
|
2
|
-
|
|
3
|
-
interface IPeerConnectionUtils {
|
|
4
|
-
convertCLineToIpv4: (sdp: string) => string;
|
|
5
|
-
adjustH264Profile: (sdp: string, maxFsValue: number) => string;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const PeerConnectionUtils = {} as IPeerConnectionUtils;
|
|
9
|
-
|
|
10
|
-
// max-fs values for all H264 profile levels
|
|
11
|
-
const maxFsForProfileLevel = {
|
|
12
|
-
10: 99,
|
|
13
|
-
11: 396,
|
|
14
|
-
12: 396,
|
|
15
|
-
13: 396,
|
|
16
|
-
20: 396,
|
|
17
|
-
21: 792,
|
|
18
|
-
22: 1620,
|
|
19
|
-
30: 1620,
|
|
20
|
-
31: 3600,
|
|
21
|
-
32: 5120,
|
|
22
|
-
40: 8192,
|
|
23
|
-
41: 8192,
|
|
24
|
-
42: 8704,
|
|
25
|
-
50: 22080,
|
|
26
|
-
51: 36864,
|
|
27
|
-
52: 36864,
|
|
28
|
-
60: 139264,
|
|
29
|
-
61: 139264,
|
|
30
|
-
62: 139264,
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const framesPerSecond = 30;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Convert C line to IPv4
|
|
37
|
-
* @param {string} sdp
|
|
38
|
-
* @returns {string}
|
|
39
|
-
*/
|
|
40
|
-
PeerConnectionUtils.convertCLineToIpv4 = (sdp: string) => {
|
|
41
|
-
let replaceSdp = sdp;
|
|
42
|
-
|
|
43
|
-
// TODO: remove this once linus supports Ipv6 c line.currently linus rejects SDP with c line having ipv6 candidates we are
|
|
44
|
-
// mocking ipv6 to ipv4 candidates
|
|
45
|
-
// https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-299232
|
|
46
|
-
replaceSdp = replaceSdp.replace(/c=IN IP6 .*/gi, 'c=IN IP4 0.0.0.0');
|
|
47
|
-
|
|
48
|
-
return replaceSdp;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* estimate profile levels for max-fs & max-mbps values
|
|
53
|
-
* @param {string} sdp
|
|
54
|
-
* @param {number} maxFsValue
|
|
55
|
-
* @returns {string}
|
|
56
|
-
*/
|
|
57
|
-
PeerConnectionUtils.adjustH264Profile = (sdp: string, maxFsValue: number) => {
|
|
58
|
-
// converting with ts-sdp parser, no munging
|
|
59
|
-
const parsedSdp = parse(sdp);
|
|
60
|
-
|
|
61
|
-
parsedSdp.avMedia.forEach((media) => {
|
|
62
|
-
if (media.type === 'video') {
|
|
63
|
-
media.codecs.forEach((codec) => {
|
|
64
|
-
if (codec.name?.toUpperCase() === 'H264') {
|
|
65
|
-
// there should really be just 1 fmtp line, but just in case, we process all of them
|
|
66
|
-
codec.fmtParams = codec.fmtParams.map((fmtp) => {
|
|
67
|
-
const parsedRegex = fmtp.match(/(.*)profile-level-id=(\w{4})(\w{2})(.*)/);
|
|
68
|
-
|
|
69
|
-
if (parsedRegex && parsedRegex.length === 5) {
|
|
70
|
-
const stuffBeforeProfileLevelId = parsedRegex[1];
|
|
71
|
-
const profile = parsedRegex[2].toLowerCase();
|
|
72
|
-
const levelId = parseInt(parsedRegex[3], 16);
|
|
73
|
-
const stuffAfterProfileLevelId = parsedRegex[4];
|
|
74
|
-
|
|
75
|
-
if (!maxFsForProfileLevel[levelId]) {
|
|
76
|
-
throw new Error(
|
|
77
|
-
`found unsupported h264 profile level id value in the SDP: ${levelId}`
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (maxFsForProfileLevel[levelId] === maxFsValue) {
|
|
82
|
-
// profile level already matches our desired max-fs value, so we don't need to do anything
|
|
83
|
-
return fmtp;
|
|
84
|
-
}
|
|
85
|
-
if (maxFsForProfileLevel[levelId] < maxFsValue) {
|
|
86
|
-
// profile level has too low max-fs, so we need to override it (this is upgrading)
|
|
87
|
-
return `${fmtp};max-fs=${maxFsValue};max-mbps=${maxFsValue * framesPerSecond}`;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// profile level has too high max-fs value, so we need to use a lower level
|
|
91
|
-
|
|
92
|
-
// find highest level that has the matching maxFs
|
|
93
|
-
const newLevelId = Object.keys(maxFsForProfileLevel)
|
|
94
|
-
.reverse()
|
|
95
|
-
.find((key) => maxFsForProfileLevel[key] === maxFsValue);
|
|
96
|
-
|
|
97
|
-
if (newLevelId) {
|
|
98
|
-
// Object.keys returns keys as strings, so we need to parse it to an int again and then convert to hex
|
|
99
|
-
const newLevelIdHex = parseInt(newLevelId, 10).toString(16);
|
|
100
|
-
|
|
101
|
-
return `${stuffBeforeProfileLevelId}profile-level-id=${profile}${newLevelIdHex};max-mbps=${maxFsValue * framesPerSecond}${stuffAfterProfileLevelId}`;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
throw new Error(`unsupported maxFsValue: ${maxFsValue}`);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return fmtp;
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
return parsedSdp.toString();
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
export default PeerConnectionUtils;
|
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
// SDPs generated by browsers always have CRLF (\r\n) endings,
|
|
2
|
-
// here we're using tagged template literals to ensures that our SDP fixtures also have CRLF endings
|
|
3
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
|
-
const ensureCRLF = (strings: any, ...tags: string[]) => {
|
|
5
|
-
const stringsWithCRLF = strings.raw.map((str: string) => str.replace(/\n/g, '\r\n'));
|
|
6
|
-
|
|
7
|
-
// now construct the output the same way as it's done by default for template literals
|
|
8
|
-
let output = stringsWithCRLF[0];
|
|
9
|
-
|
|
10
|
-
tags.forEach((tag, index) => {
|
|
11
|
-
output += tag + stringsWithCRLF[index + 1];
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
return output;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
// example SDP that has an audio and 2 video m-lines, video contains multiple codecs
|
|
18
|
-
// it's basically a trimmed down version of an SDP example from Chrome
|
|
19
|
-
export const SDP_MULTIPLE_VIDEO_CODECS = ensureCRLF`v=0
|
|
20
|
-
o=- 3328550572590672467 2 IN IP4 127.0.0.1
|
|
21
|
-
s=-
|
|
22
|
-
t=0 0
|
|
23
|
-
a=group:BUNDLE 0 1 2
|
|
24
|
-
a=extmap-allow-mixed
|
|
25
|
-
a=msid-semantic: WMS 38872d1a-f4c3-4234-b162-bb47bc55ec57
|
|
26
|
-
m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 106
|
|
27
|
-
c=IN IP4 0.0.0.0
|
|
28
|
-
a=ice-ufrag:vPie
|
|
29
|
-
a=ice-pwd:QWp1jfvbc4iUBXfLVSxhDFIN
|
|
30
|
-
a=ice-options:trickle
|
|
31
|
-
a=candidate:1 1 udp 2130706431 10.50.173.46 56821 typ host
|
|
32
|
-
a=fingerprint:sha-256 60:00:B9:57:5D:EC:CE:C7:7D:57:EA:EF:AF:37:23:64:63:39:F7:F3:D5:01:C7:18:C7:6E:B9:B4:46:19:40:06
|
|
33
|
-
a=setup:actpass
|
|
34
|
-
a=mid:0
|
|
35
|
-
a=rtcp-mux
|
|
36
|
-
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
|
|
37
|
-
a=sendrecv
|
|
38
|
-
a=rtpmap:111 opus/48000/2
|
|
39
|
-
a=rtcp-fb:111 transport-cc
|
|
40
|
-
a=fmtp:111 minptime=10;useinbandfec=1
|
|
41
|
-
a=rtpmap:63 red/48000/2
|
|
42
|
-
a=fmtp:63 111/111
|
|
43
|
-
a=rtpmap:9 G722/8000
|
|
44
|
-
a=rtpmap:0 PCMU/8000
|
|
45
|
-
a=rtpmap:8 PCMA/8000
|
|
46
|
-
a=rtpmap:106 CN/32000
|
|
47
|
-
a=rtcp:9 IN IP4 0.0.0.0
|
|
48
|
-
a=msid:38872d1a-f4c3-4234-b162-bb47bc55ec57 0283c960-c78d-4164-a6f3-394342273ad4
|
|
49
|
-
a=ssrc:3693867886 cname:TGydLcYyPoQiRBlB
|
|
50
|
-
a=ssrc:3693867886 msid:38872d1a-f4c3-4234-b162-bb47bc55ec57 0283c960-c78d-4164-a6f3-394342273ad4
|
|
51
|
-
m=video 9 UDP/TLS/RTP/SAVPF 100 101 127 121 114 115 116 117 118
|
|
52
|
-
c=IN IP4 0.0.0.0
|
|
53
|
-
a=ice-ufrag:vPie
|
|
54
|
-
a=ice-pwd:QWp1jfvbc4iUBXfLVSxhDFIN
|
|
55
|
-
a=ice-options:trickle
|
|
56
|
-
a=candidate:1 1 udp 2130706431 10.50.173.46 56821 typ host
|
|
57
|
-
a=fingerprint:sha-256 60:00:B9:57:5D:EC:CE:C7:7D:57:EA:EF:AF:37:23:64:63:39:F7:F3:D5:01:C7:18:C7:6E:B9:B4:46:19:40:06
|
|
58
|
-
a=setup:actpass
|
|
59
|
-
a=mid:1
|
|
60
|
-
a=rtcp-mux
|
|
61
|
-
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
|
|
62
|
-
a=sendrecv
|
|
63
|
-
a=rtpmap:100 VP9/90000
|
|
64
|
-
a=rtcp-fb:100 goog-remb
|
|
65
|
-
a=rtcp-fb:100 transport-cc
|
|
66
|
-
a=rtcp-fb:100 ccm fir
|
|
67
|
-
a=rtcp-fb:100 nack
|
|
68
|
-
a=rtcp-fb:100 nack pli
|
|
69
|
-
a=fmtp:100 profile-id=2
|
|
70
|
-
a=rtpmap:101 rtx/90000
|
|
71
|
-
a=fmtp:101 apt=100
|
|
72
|
-
a=rtpmap:127 H264/90000
|
|
73
|
-
a=rtcp-fb:127 goog-remb
|
|
74
|
-
a=rtcp-fb:127 transport-cc
|
|
75
|
-
a=rtcp-fb:127 ccm fir
|
|
76
|
-
a=rtcp-fb:127 nack
|
|
77
|
-
a=rtcp-fb:127 nack pli
|
|
78
|
-
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
|
|
79
|
-
a=rtpmap:121 rtx/90000
|
|
80
|
-
a=fmtp:121 apt=127
|
|
81
|
-
a=rtpmap:114 H264/90000
|
|
82
|
-
a=rtcp-fb:114 goog-remb
|
|
83
|
-
a=rtcp-fb:114 transport-cc
|
|
84
|
-
a=rtcp-fb:114 ccm fir
|
|
85
|
-
a=rtcp-fb:114 nack
|
|
86
|
-
a=rtcp-fb:114 nack pli
|
|
87
|
-
a=fmtp:114 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f
|
|
88
|
-
a=rtpmap:115 rtx/90000
|
|
89
|
-
a=fmtp:115 apt=114
|
|
90
|
-
a=rtpmap:116 red/90000
|
|
91
|
-
a=rtpmap:117 rtx/90000
|
|
92
|
-
a=fmtp:117 apt=116
|
|
93
|
-
a=rtpmap:118 ulpfec/90000
|
|
94
|
-
a=rtcp-rsize
|
|
95
|
-
a=rtcp:9 IN IP4 0.0.0.0
|
|
96
|
-
a=msid:38872d1a-f4c3-4234-b162-bb47bc55ec57 c0ea0a74-c991-4005-ab6a-3a29f23e67b7
|
|
97
|
-
a=ssrc:597013044 cname:TGydLcYyPoQiRBlB
|
|
98
|
-
a=ssrc:597013044 msid:38872d1a-f4c3-4234-b162-bb47bc55ec57 c0ea0a74-c991-4005-ab6a-3a29f23e67b7
|
|
99
|
-
m=video 9 UDP/TLS/RTP/SAVPF 102 122 127 121 108 109
|
|
100
|
-
c=IN IP4 0.0.0.0
|
|
101
|
-
a=ice-ufrag:vPie
|
|
102
|
-
a=ice-pwd:QWp1jfvbc4iUBXfLVSxhDFIN
|
|
103
|
-
a=ice-options:trickle
|
|
104
|
-
a=candidate:1 1 udp 2130706431 10.50.173.46 56821 typ host
|
|
105
|
-
a=fingerprint:sha-256 60:00:B9:57:5D:EC:CE:C7:7D:57:EA:EF:AF:37:23:64:63:39:F7:F3:D5:01:C7:18:C7:6E:B9:B4:46:19:40:06
|
|
106
|
-
a=setup:actpass
|
|
107
|
-
a=mid:2
|
|
108
|
-
a=rtcp-mux
|
|
109
|
-
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
|
|
110
|
-
a=recvonly
|
|
111
|
-
a=rtpmap:102 VP9/90000
|
|
112
|
-
a=rtcp-fb:102 goog-remb
|
|
113
|
-
a=rtcp-fb:102 transport-cc
|
|
114
|
-
a=rtcp-fb:102 ccm fir
|
|
115
|
-
a=rtcp-fb:102 nack
|
|
116
|
-
a=rtcp-fb:102 nack pli
|
|
117
|
-
a=fmtp:102 profile-id=1
|
|
118
|
-
a=rtpmap:122 rtx/90000
|
|
119
|
-
a=fmtp:122 apt=102
|
|
120
|
-
a=rtpmap:127 H264/90000
|
|
121
|
-
a=rtcp-fb:127 goog-remb
|
|
122
|
-
a=rtcp-fb:127 transport-cc
|
|
123
|
-
a=rtcp-fb:127 ccm fir
|
|
124
|
-
a=rtcp-fb:127 nack
|
|
125
|
-
a=rtcp-fb:127 nack pli
|
|
126
|
-
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
|
|
127
|
-
a=rtpmap:121 rtx/90000
|
|
128
|
-
a=fmtp:121 apt=127
|
|
129
|
-
a=rtpmap:108 H264/90000
|
|
130
|
-
a=rtcp-fb:108 goog-remb
|
|
131
|
-
a=rtcp-fb:108 transport-cc
|
|
132
|
-
a=rtcp-fb:108 ccm fir
|
|
133
|
-
a=rtcp-fb:108 nack
|
|
134
|
-
a=rtcp-fb:108 nack pli
|
|
135
|
-
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
|
|
136
|
-
a=rtpmap:109 rtx/90000
|
|
137
|
-
a=fmtp:109 apt=108
|
|
138
|
-
a=rtcp-rsize
|
|
139
|
-
a=rtcp:9 IN IP4 0.0.0.0
|
|
140
|
-
`;
|
|
141
|
-
|
|
142
|
-
// same as SDP_MULTIPLE_VIDEO_CODECS but with h264 profile level changed from 3.1 to 3.0
|
|
143
|
-
export const SDP_MULTIPLE_VIDEO_CODECS_WITH_LOWERED_H264_PROFILE_LEVEL = ensureCRLF`v=0
|
|
144
|
-
o=- 3328550572590672467 2 IN IP4 127.0.0.1
|
|
145
|
-
s=-
|
|
146
|
-
t=0 0
|
|
147
|
-
a=group:BUNDLE 0 1 2
|
|
148
|
-
a=extmap-allow-mixed
|
|
149
|
-
a=msid-semantic: WMS 38872d1a-f4c3-4234-b162-bb47bc55ec57
|
|
150
|
-
m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 106
|
|
151
|
-
c=IN IP4 0.0.0.0
|
|
152
|
-
a=ice-ufrag:vPie
|
|
153
|
-
a=ice-pwd:QWp1jfvbc4iUBXfLVSxhDFIN
|
|
154
|
-
a=ice-options:trickle
|
|
155
|
-
a=candidate:1 1 udp 2130706431 10.50.173.46 56821 typ host
|
|
156
|
-
a=fingerprint:sha-256 60:00:B9:57:5D:EC:CE:C7:7D:57:EA:EF:AF:37:23:64:63:39:F7:F3:D5:01:C7:18:C7:6E:B9:B4:46:19:40:06
|
|
157
|
-
a=setup:actpass
|
|
158
|
-
a=mid:0
|
|
159
|
-
a=rtcp-mux
|
|
160
|
-
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
|
|
161
|
-
a=sendrecv
|
|
162
|
-
a=rtpmap:111 opus/48000/2
|
|
163
|
-
a=rtcp-fb:111 transport-cc
|
|
164
|
-
a=fmtp:111 minptime=10;useinbandfec=1
|
|
165
|
-
a=rtpmap:63 red/48000/2
|
|
166
|
-
a=fmtp:63 111/111
|
|
167
|
-
a=rtpmap:9 G722/8000
|
|
168
|
-
a=rtpmap:0 PCMU/8000
|
|
169
|
-
a=rtpmap:8 PCMA/8000
|
|
170
|
-
a=rtpmap:106 CN/32000
|
|
171
|
-
a=rtcp:9 IN IP4 0.0.0.0
|
|
172
|
-
a=msid:38872d1a-f4c3-4234-b162-bb47bc55ec57 0283c960-c78d-4164-a6f3-394342273ad4
|
|
173
|
-
a=ssrc:3693867886 cname:TGydLcYyPoQiRBlB
|
|
174
|
-
a=ssrc:3693867886 msid:38872d1a-f4c3-4234-b162-bb47bc55ec57 0283c960-c78d-4164-a6f3-394342273ad4
|
|
175
|
-
m=video 9 UDP/TLS/RTP/SAVPF 100 101 127 121 114 115 116 117 118
|
|
176
|
-
c=IN IP4 0.0.0.0
|
|
177
|
-
a=ice-ufrag:vPie
|
|
178
|
-
a=ice-pwd:QWp1jfvbc4iUBXfLVSxhDFIN
|
|
179
|
-
a=ice-options:trickle
|
|
180
|
-
a=candidate:1 1 udp 2130706431 10.50.173.46 56821 typ host
|
|
181
|
-
a=fingerprint:sha-256 60:00:B9:57:5D:EC:CE:C7:7D:57:EA:EF:AF:37:23:64:63:39:F7:F3:D5:01:C7:18:C7:6E:B9:B4:46:19:40:06
|
|
182
|
-
a=setup:actpass
|
|
183
|
-
a=mid:1
|
|
184
|
-
a=rtcp-mux
|
|
185
|
-
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
|
|
186
|
-
a=sendrecv
|
|
187
|
-
a=rtpmap:100 VP9/90000
|
|
188
|
-
a=rtcp-fb:100 goog-remb
|
|
189
|
-
a=rtcp-fb:100 transport-cc
|
|
190
|
-
a=rtcp-fb:100 ccm fir
|
|
191
|
-
a=rtcp-fb:100 nack
|
|
192
|
-
a=rtcp-fb:100 nack pli
|
|
193
|
-
a=fmtp:100 profile-id=2
|
|
194
|
-
a=rtpmap:101 rtx/90000
|
|
195
|
-
a=fmtp:101 apt=100
|
|
196
|
-
a=rtpmap:127 H264/90000
|
|
197
|
-
a=rtcp-fb:127 goog-remb
|
|
198
|
-
a=rtcp-fb:127 transport-cc
|
|
199
|
-
a=rtcp-fb:127 ccm fir
|
|
200
|
-
a=rtcp-fb:127 nack
|
|
201
|
-
a=rtcp-fb:127 nack pli
|
|
202
|
-
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001e;max-mbps=48600
|
|
203
|
-
a=rtpmap:121 rtx/90000
|
|
204
|
-
a=fmtp:121 apt=127
|
|
205
|
-
a=rtpmap:114 H264/90000
|
|
206
|
-
a=rtcp-fb:114 goog-remb
|
|
207
|
-
a=rtcp-fb:114 transport-cc
|
|
208
|
-
a=rtcp-fb:114 ccm fir
|
|
209
|
-
a=rtcp-fb:114 nack
|
|
210
|
-
a=rtcp-fb:114 nack pli
|
|
211
|
-
a=fmtp:114 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001e;max-mbps=48600
|
|
212
|
-
a=rtpmap:115 rtx/90000
|
|
213
|
-
a=fmtp:115 apt=114
|
|
214
|
-
a=rtpmap:116 red/90000
|
|
215
|
-
a=rtpmap:117 rtx/90000
|
|
216
|
-
a=fmtp:117 apt=116
|
|
217
|
-
a=rtpmap:118 ulpfec/90000
|
|
218
|
-
a=rtcp-rsize
|
|
219
|
-
a=rtcp:9 IN IP4 0.0.0.0
|
|
220
|
-
a=msid:38872d1a-f4c3-4234-b162-bb47bc55ec57 c0ea0a74-c991-4005-ab6a-3a29f23e67b7
|
|
221
|
-
a=ssrc:597013044 cname:TGydLcYyPoQiRBlB
|
|
222
|
-
a=ssrc:597013044 msid:38872d1a-f4c3-4234-b162-bb47bc55ec57 c0ea0a74-c991-4005-ab6a-3a29f23e67b7
|
|
223
|
-
m=video 9 UDP/TLS/RTP/SAVPF 102 122 127 121 108 109
|
|
224
|
-
c=IN IP4 0.0.0.0
|
|
225
|
-
a=ice-ufrag:vPie
|
|
226
|
-
a=ice-pwd:QWp1jfvbc4iUBXfLVSxhDFIN
|
|
227
|
-
a=ice-options:trickle
|
|
228
|
-
a=candidate:1 1 udp 2130706431 10.50.173.46 56821 typ host
|
|
229
|
-
a=fingerprint:sha-256 60:00:B9:57:5D:EC:CE:C7:7D:57:EA:EF:AF:37:23:64:63:39:F7:F3:D5:01:C7:18:C7:6E:B9:B4:46:19:40:06
|
|
230
|
-
a=setup:actpass
|
|
231
|
-
a=mid:2
|
|
232
|
-
a=rtcp-mux
|
|
233
|
-
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
|
|
234
|
-
a=recvonly
|
|
235
|
-
a=rtpmap:102 VP9/90000
|
|
236
|
-
a=rtcp-fb:102 goog-remb
|
|
237
|
-
a=rtcp-fb:102 transport-cc
|
|
238
|
-
a=rtcp-fb:102 ccm fir
|
|
239
|
-
a=rtcp-fb:102 nack
|
|
240
|
-
a=rtcp-fb:102 nack pli
|
|
241
|
-
a=fmtp:102 profile-id=1
|
|
242
|
-
a=rtpmap:122 rtx/90000
|
|
243
|
-
a=fmtp:122 apt=102
|
|
244
|
-
a=rtpmap:127 H264/90000
|
|
245
|
-
a=rtcp-fb:127 goog-remb
|
|
246
|
-
a=rtcp-fb:127 transport-cc
|
|
247
|
-
a=rtcp-fb:127 ccm fir
|
|
248
|
-
a=rtcp-fb:127 nack
|
|
249
|
-
a=rtcp-fb:127 nack pli
|
|
250
|
-
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001e;max-mbps=48600
|
|
251
|
-
a=rtpmap:121 rtx/90000
|
|
252
|
-
a=fmtp:121 apt=127
|
|
253
|
-
a=rtpmap:108 H264/90000
|
|
254
|
-
a=rtcp-fb:108 goog-remb
|
|
255
|
-
a=rtcp-fb:108 transport-cc
|
|
256
|
-
a=rtcp-fb:108 ccm fir
|
|
257
|
-
a=rtcp-fb:108 nack
|
|
258
|
-
a=rtcp-fb:108 nack pli
|
|
259
|
-
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01e;max-mbps=48600
|
|
260
|
-
a=rtpmap:109 rtx/90000
|
|
261
|
-
a=fmtp:109 apt=108
|
|
262
|
-
a=rtcp-rsize
|
|
263
|
-
a=rtcp:9 IN IP4 0.0.0.0
|
|
264
|
-
`;
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
// same as SDP_MULTIPLE_VIDEO_CODECS, but has max-fs appended to all H264 fmtp lines
|
|
268
|
-
export const SDP_MULTIPLE_VIDEO_CODECS_WITH_MAX_FS = ensureCRLF`v=0
|
|
269
|
-
o=- 3328550572590672467 2 IN IP4 127.0.0.1
|
|
270
|
-
s=-
|
|
271
|
-
t=0 0
|
|
272
|
-
a=group:BUNDLE 0 1 2
|
|
273
|
-
a=extmap-allow-mixed
|
|
274
|
-
a=msid-semantic: WMS 38872d1a-f4c3-4234-b162-bb47bc55ec57
|
|
275
|
-
m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 106
|
|
276
|
-
c=IN IP4 0.0.0.0
|
|
277
|
-
a=ice-ufrag:vPie
|
|
278
|
-
a=ice-pwd:QWp1jfvbc4iUBXfLVSxhDFIN
|
|
279
|
-
a=ice-options:trickle
|
|
280
|
-
a=candidate:1 1 udp 2130706431 10.50.173.46 56821 typ host
|
|
281
|
-
a=fingerprint:sha-256 60:00:B9:57:5D:EC:CE:C7:7D:57:EA:EF:AF:37:23:64:63:39:F7:F3:D5:01:C7:18:C7:6E:B9:B4:46:19:40:06
|
|
282
|
-
a=setup:actpass
|
|
283
|
-
a=mid:0
|
|
284
|
-
a=rtcp-mux
|
|
285
|
-
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
|
|
286
|
-
a=sendrecv
|
|
287
|
-
a=rtpmap:111 opus/48000/2
|
|
288
|
-
a=rtcp-fb:111 transport-cc
|
|
289
|
-
a=fmtp:111 minptime=10;useinbandfec=1
|
|
290
|
-
a=rtpmap:63 red/48000/2
|
|
291
|
-
a=fmtp:63 111/111
|
|
292
|
-
a=rtpmap:9 G722/8000
|
|
293
|
-
a=rtpmap:0 PCMU/8000
|
|
294
|
-
a=rtpmap:8 PCMA/8000
|
|
295
|
-
a=rtpmap:106 CN/32000
|
|
296
|
-
a=rtcp:9 IN IP4 0.0.0.0
|
|
297
|
-
a=msid:38872d1a-f4c3-4234-b162-bb47bc55ec57 0283c960-c78d-4164-a6f3-394342273ad4
|
|
298
|
-
a=ssrc:3693867886 cname:TGydLcYyPoQiRBlB
|
|
299
|
-
a=ssrc:3693867886 msid:38872d1a-f4c3-4234-b162-bb47bc55ec57 0283c960-c78d-4164-a6f3-394342273ad4
|
|
300
|
-
m=video 9 UDP/TLS/RTP/SAVPF 100 101 127 121 114 115 116 117 118
|
|
301
|
-
c=IN IP4 0.0.0.0
|
|
302
|
-
a=ice-ufrag:vPie
|
|
303
|
-
a=ice-pwd:QWp1jfvbc4iUBXfLVSxhDFIN
|
|
304
|
-
a=ice-options:trickle
|
|
305
|
-
a=candidate:1 1 udp 2130706431 10.50.173.46 56821 typ host
|
|
306
|
-
a=fingerprint:sha-256 60:00:B9:57:5D:EC:CE:C7:7D:57:EA:EF:AF:37:23:64:63:39:F7:F3:D5:01:C7:18:C7:6E:B9:B4:46:19:40:06
|
|
307
|
-
a=setup:actpass
|
|
308
|
-
a=mid:1
|
|
309
|
-
a=rtcp-mux
|
|
310
|
-
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
|
|
311
|
-
a=sendrecv
|
|
312
|
-
a=rtpmap:100 VP9/90000
|
|
313
|
-
a=rtcp-fb:100 goog-remb
|
|
314
|
-
a=rtcp-fb:100 transport-cc
|
|
315
|
-
a=rtcp-fb:100 ccm fir
|
|
316
|
-
a=rtcp-fb:100 nack
|
|
317
|
-
a=rtcp-fb:100 nack pli
|
|
318
|
-
a=fmtp:100 profile-id=2
|
|
319
|
-
a=rtpmap:101 rtx/90000
|
|
320
|
-
a=fmtp:101 apt=100
|
|
321
|
-
a=rtpmap:127 H264/90000
|
|
322
|
-
a=rtcp-fb:127 goog-remb
|
|
323
|
-
a=rtcp-fb:127 transport-cc
|
|
324
|
-
a=rtcp-fb:127 ccm fir
|
|
325
|
-
a=rtcp-fb:127 nack
|
|
326
|
-
a=rtcp-fb:127 nack pli
|
|
327
|
-
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f;max-fs=8192;max-mbps=245760
|
|
328
|
-
a=rtpmap:121 rtx/90000
|
|
329
|
-
a=fmtp:121 apt=127
|
|
330
|
-
a=rtpmap:114 H264/90000
|
|
331
|
-
a=rtcp-fb:114 goog-remb
|
|
332
|
-
a=rtcp-fb:114 transport-cc
|
|
333
|
-
a=rtcp-fb:114 ccm fir
|
|
334
|
-
a=rtcp-fb:114 nack
|
|
335
|
-
a=rtcp-fb:114 nack pli
|
|
336
|
-
a=fmtp:114 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f;max-fs=8192;max-mbps=245760
|
|
337
|
-
a=rtpmap:115 rtx/90000
|
|
338
|
-
a=fmtp:115 apt=114
|
|
339
|
-
a=rtpmap:116 red/90000
|
|
340
|
-
a=rtpmap:117 rtx/90000
|
|
341
|
-
a=fmtp:117 apt=116
|
|
342
|
-
a=rtpmap:118 ulpfec/90000
|
|
343
|
-
a=rtcp-rsize
|
|
344
|
-
a=rtcp:9 IN IP4 0.0.0.0
|
|
345
|
-
a=msid:38872d1a-f4c3-4234-b162-bb47bc55ec57 c0ea0a74-c991-4005-ab6a-3a29f23e67b7
|
|
346
|
-
a=ssrc:597013044 cname:TGydLcYyPoQiRBlB
|
|
347
|
-
a=ssrc:597013044 msid:38872d1a-f4c3-4234-b162-bb47bc55ec57 c0ea0a74-c991-4005-ab6a-3a29f23e67b7
|
|
348
|
-
m=video 9 UDP/TLS/RTP/SAVPF 102 122 127 121 108 109
|
|
349
|
-
c=IN IP4 0.0.0.0
|
|
350
|
-
a=ice-ufrag:vPie
|
|
351
|
-
a=ice-pwd:QWp1jfvbc4iUBXfLVSxhDFIN
|
|
352
|
-
a=ice-options:trickle
|
|
353
|
-
a=candidate:1 1 udp 2130706431 10.50.173.46 56821 typ host
|
|
354
|
-
a=fingerprint:sha-256 60:00:B9:57:5D:EC:CE:C7:7D:57:EA:EF:AF:37:23:64:63:39:F7:F3:D5:01:C7:18:C7:6E:B9:B4:46:19:40:06
|
|
355
|
-
a=setup:actpass
|
|
356
|
-
a=mid:2
|
|
357
|
-
a=rtcp-mux
|
|
358
|
-
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
|
|
359
|
-
a=recvonly
|
|
360
|
-
a=rtpmap:102 VP9/90000
|
|
361
|
-
a=rtcp-fb:102 goog-remb
|
|
362
|
-
a=rtcp-fb:102 transport-cc
|
|
363
|
-
a=rtcp-fb:102 ccm fir
|
|
364
|
-
a=rtcp-fb:102 nack
|
|
365
|
-
a=rtcp-fb:102 nack pli
|
|
366
|
-
a=fmtp:102 profile-id=1
|
|
367
|
-
a=rtpmap:122 rtx/90000
|
|
368
|
-
a=fmtp:122 apt=102
|
|
369
|
-
a=rtpmap:127 H264/90000
|
|
370
|
-
a=rtcp-fb:127 goog-remb
|
|
371
|
-
a=rtcp-fb:127 transport-cc
|
|
372
|
-
a=rtcp-fb:127 ccm fir
|
|
373
|
-
a=rtcp-fb:127 nack
|
|
374
|
-
a=rtcp-fb:127 nack pli
|
|
375
|
-
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f;max-fs=8192;max-mbps=245760
|
|
376
|
-
a=rtpmap:121 rtx/90000
|
|
377
|
-
a=fmtp:121 apt=127
|
|
378
|
-
a=rtpmap:108 H264/90000
|
|
379
|
-
a=rtcp-fb:108 goog-remb
|
|
380
|
-
a=rtcp-fb:108 transport-cc
|
|
381
|
-
a=rtcp-fb:108 ccm fir
|
|
382
|
-
a=rtcp-fb:108 nack
|
|
383
|
-
a=rtcp-fb:108 nack pli
|
|
384
|
-
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f;max-fs=8192;max-mbps=245760
|
|
385
|
-
a=rtpmap:109 rtx/90000
|
|
386
|
-
a=fmtp:109 apt=108
|
|
387
|
-
a=rtcp-rsize
|
|
388
|
-
a=rtcp:9 IN IP4 0.0.0.0
|
|
389
|
-
`;
|