|
|
@@ -10,6 +10,21 @@ import { XEP } from '../../service/xmpp/XMPPExtensioProtocols';
|
|
10
|
10
|
|
|
11
|
11
|
const logger = getLogger('modules/xmpp/JingleHelperFunctions');
|
|
12
|
12
|
|
|
|
13
|
+export interface ISourceCompactJson {
|
|
|
14
|
+ m?: string;
|
|
|
15
|
+ n: string;
|
|
|
16
|
+ s: string;
|
|
|
17
|
+ v?: any;
|
|
|
18
|
+}
|
|
|
19
|
+
|
|
|
20
|
+export interface ICompactSsrcGroup extends Array<string> { }
|
|
|
21
|
+
|
|
|
22
|
+export interface IJsonMessage {
|
|
|
23
|
+ sources: {
|
|
|
24
|
+ [owner: string]: [ISourceCompactJson[], ICompactSsrcGroup[], ISourceCompactJson[], ICompactSsrcGroup[]];
|
|
|
25
|
+ };
|
|
|
26
|
+}
|
|
|
27
|
+
|
|
13
|
28
|
/**
|
|
14
|
29
|
* Creates a "source" XML element for the source described in compact JSON format in [sourceCompactJson].
|
|
15
|
30
|
* @param {*} owner the endpoint ID of the owner of the source.
|
|
|
@@ -17,7 +32,7 @@ const logger = getLogger('modules/xmpp/JingleHelperFunctions');
|
|
17
|
32
|
* @param {boolean} isVideo whether the source is a video source
|
|
18
|
33
|
* @returns the created "source" XML element.
|
|
19
|
34
|
*/
|
|
20
|
|
-function _createSourceExtension(owner, sourceCompactJson, isVideo = false) {
|
|
|
35
|
+function _createSourceExtension(owner: string, sourceCompactJson: ISourceCompactJson, isVideo: boolean = false): Node {
|
|
21
|
36
|
let videoType = sourceCompactJson.v ? VideoType.DESKTOP : undefined;
|
|
22
|
37
|
|
|
23
|
38
|
// If the video type is not specified, it is assumed to be a camera for video sources.
|
|
|
@@ -52,7 +67,7 @@ function _createSourceExtension(owner, sourceCompactJson, isVideo = false) {
|
|
52
|
67
|
* @param {*} ssrcGroupCompactJson the compact JSON representation of the SSRC group.
|
|
53
|
68
|
* @returns the created "ssrc-group" element.
|
|
54
|
69
|
*/
|
|
55
|
|
-function _createSsrcGroupExtension(ssrcGroupCompactJson) {
|
|
|
70
|
+function _createSsrcGroupExtension(ssrcGroupCompactJson: ICompactSsrcGroup): Node {
|
|
56
|
71
|
const node = $build('ssrc-group', {
|
|
57
|
72
|
xmlns: XEP.SOURCE_ATTRIBUTES,
|
|
58
|
73
|
semantics: _getSemantics(ssrcGroupCompactJson[0])
|
|
|
@@ -75,10 +90,10 @@ function _createSsrcGroupExtension(ssrcGroupCompactJson) {
|
|
75
|
90
|
* @param {*} mediaType The media type, "audio" or "video".
|
|
76
|
91
|
* @returns the RTP description element with the given media type.
|
|
77
|
92
|
*/
|
|
78
|
|
-function _getOrCreateRtpDescription(iq, mediaType) {
|
|
|
93
|
+function _getOrCreateRtpDescription(iq: Element, mediaType: string): Element {
|
|
79
|
94
|
const jingle = $(iq).find('jingle')[0];
|
|
80
|
95
|
let content = $(jingle).find(`content[name="${mediaType}"]`);
|
|
81
|
|
- let description;
|
|
|
96
|
+ let description: Element;
|
|
82
|
97
|
|
|
83
|
98
|
if (content.length) {
|
|
84
|
99
|
content = content[0];
|
|
|
@@ -90,10 +105,10 @@ function _getOrCreateRtpDescription(iq, mediaType) {
|
|
90
|
105
|
jingle.appendChild(content);
|
|
91
|
106
|
}
|
|
92
|
107
|
|
|
93
|
|
- description = $(content).find('description');
|
|
|
108
|
+ const descriptionElements = $(content).find('description');
|
|
94
|
109
|
|
|
95
|
|
- if (description.length) {
|
|
96
|
|
- description = description[0];
|
|
|
110
|
+ if (descriptionElements.length) {
|
|
|
111
|
+ description = descriptionElements[0];
|
|
97
|
112
|
} else {
|
|
98
|
113
|
description = $build('description', {
|
|
99
|
114
|
xmlns: XEP.RTP_MEDIA,
|
|
|
@@ -111,7 +126,7 @@ function _getOrCreateRtpDescription(iq, mediaType) {
|
|
111
|
126
|
* @param {*} str the compact JSON format representation of an SSRC group's semantics.
|
|
112
|
127
|
* @returns the SSRC group semantics corresponding to [str].
|
|
113
|
128
|
*/
|
|
114
|
|
-function _getSemantics(str) {
|
|
|
129
|
+function _getSemantics(str: string): string | null {
|
|
115
|
130
|
if (str === 'f') {
|
|
116
|
131
|
return SSRC_GROUP_SEMANTICS.FID;
|
|
117
|
132
|
} else if (str === 's') {
|
|
|
@@ -133,11 +148,11 @@ function _getSemantics(str) {
|
|
133
|
148
|
* @returns {Map<string, Array<string>} The audio and video ssrcs extracted from the JSON-encoded message with remote
|
|
134
|
149
|
* endpoint id as the key.
|
|
135
|
150
|
*/
|
|
136
|
|
-export function expandSourcesFromJson(iq, jsonMessageXml) {
|
|
137
|
|
- let json;
|
|
|
151
|
+export function expandSourcesFromJson(iq: Element, jsonMessageXml: Element): Map<string, string[]> | null {
|
|
|
152
|
+ let json: any;
|
|
138
|
153
|
|
|
139
|
154
|
try {
|
|
140
|
|
- json = safeJsonParse(jsonMessageXml.textContent);
|
|
|
155
|
+ json = safeJsonParse(jsonMessageXml.textContent || '');
|
|
141
|
156
|
} catch (error) {
|
|
142
|
157
|
logger.error(`json-message XML contained invalid JSON, ignoring: ${jsonMessageXml.textContent}`);
|
|
143
|
158
|
|
|
|
@@ -152,19 +167,19 @@ export function expandSourcesFromJson(iq, jsonMessageXml) {
|
|
152
|
167
|
// This is where we'll add "source" and "ssrc-group" elements. Create them elements if they don't exist.
|
|
153
|
168
|
const audioRtpDescription = _getOrCreateRtpDescription(iq, MediaType.AUDIO);
|
|
154
|
169
|
const videoRtpDescription = _getOrCreateRtpDescription(iq, MediaType.VIDEO);
|
|
155
|
|
- const ssrcMap = new Map();
|
|
|
170
|
+ const ssrcMap = new Map<string, string[]>();
|
|
156
|
171
|
|
|
157
|
172
|
for (const owner in json.sources) {
|
|
158
|
173
|
if (json.sources.hasOwnProperty(owner)) {
|
|
159
|
|
- const ssrcs = [];
|
|
160
|
|
- const ownerSources = json.sources[owner];
|
|
|
174
|
+ const ssrcs: string[] = [];
|
|
|
175
|
+ const ownerSources = json.sources[owner] as [ISourceCompactJson[], ICompactSsrcGroup[], ISourceCompactJson[], ICompactSsrcGroup[]];
|
|
161
|
176
|
|
|
162
|
177
|
// The video sources, video ssrc-groups, audio sources and audio ssrc-groups are encoded in that order in
|
|
163
|
178
|
// the elements of the array.
|
|
164
|
|
- const videoSources = ownerSources?.length && ownerSources[0];
|
|
165
|
|
- const videoSsrcGroups = ownerSources?.length > 1 && ownerSources[1];
|
|
166
|
|
- const audioSources = ownerSources?.length > 2 && ownerSources[2];
|
|
167
|
|
- const audioSsrcGroups = ownerSources?.length > 3 && ownerSources[3];
|
|
|
179
|
+ const videoSources = ownerSources?.length ? ownerSources[0] : [];
|
|
|
180
|
+ const videoSsrcGroups = ownerSources?.length > 1 ? ownerSources[1] : [];
|
|
|
181
|
+ const audioSources = ownerSources?.length > 2 ? ownerSources[2] : [];
|
|
|
182
|
+ const audioSsrcGroups = ownerSources?.length > 3 ? ownerSources[3] : [];
|
|
168
|
183
|
|
|
169
|
184
|
if (videoSources?.length) {
|
|
170
|
185
|
for (let i = 0; i < videoSources.length; i++) {
|