@stream-io/video-client 1.36.0 → 1.36.1

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.
@@ -0,0 +1,628 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { removeCodecsExcept } from '../sdp';
3
+
4
+ const sdp = `v=0
5
+ o=- 6339689900541563983 2 IN IP4 127.0.0.1
6
+ s=-
7
+ t=0 0
8
+ a=group:BUNDLE 0 1
9
+ a=extmap-allow-mixed
10
+ a=msid-semantic: WMS
11
+ m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 35 36 37 38 103 104 107 108 109 114 115 116 117 118 39 40 41 42 43 44 45 46 47 48 119 120 121 122 49 50 51 52 123 124 125 53
12
+ c=IN IP4 0.0.0.0
13
+ a=rtcp:9 IN IP4 0.0.0.0
14
+ a=ice-ufrag:BRD8
15
+ a=ice-pwd:8e+C7eV4BeLTWG9HvRNQZ52S
16
+ a=ice-options:trickle
17
+ a=fingerprint:sha-256 7B:A4:54:EF:70:A8:30:82:F6:88:A6:DC:E9:8A:7E:6E:59:5C:53:32:D7:AD:4F:C9:4D:DB:6C:DD:0B:DD:03:04
18
+ a=setup:actpass
19
+ a=mid:0
20
+ a=extmap:1 urn:ietf:params:rtp-hdrext:toffset
21
+ a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
22
+ a=extmap:3 urn:3gpp:video-orientation
23
+ a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
24
+ a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
25
+ a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
26
+ a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
27
+ a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
28
+ a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
29
+ a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
30
+ a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
31
+ a=recvonly
32
+ a=rtcp-mux
33
+ a=rtcp-rsize
34
+ a=rtpmap:96 VP8/90000
35
+ a=rtcp-fb:96 goog-remb
36
+ a=rtcp-fb:96 transport-cc
37
+ a=rtcp-fb:96 ccm fir
38
+ a=rtcp-fb:96 nack
39
+ a=rtcp-fb:96 nack pli
40
+ a=rtpmap:97 rtx/90000
41
+ a=fmtp:97 apt=96
42
+ a=rtpmap:98 VP9/90000
43
+ a=rtcp-fb:98 goog-remb
44
+ a=rtcp-fb:98 transport-cc
45
+ a=rtcp-fb:98 ccm fir
46
+ a=rtcp-fb:98 nack
47
+ a=rtcp-fb:98 nack pli
48
+ a=fmtp:98 profile-id=0
49
+ a=rtpmap:99 rtx/90000
50
+ a=fmtp:99 apt=98
51
+ a=rtpmap:100 VP9/90000
52
+ a=rtcp-fb:100 goog-remb
53
+ a=rtcp-fb:100 transport-cc
54
+ a=rtcp-fb:100 ccm fir
55
+ a=rtcp-fb:100 nack
56
+ a=rtcp-fb:100 nack pli
57
+ a=fmtp:100 profile-id=2
58
+ a=rtpmap:101 rtx/90000
59
+ a=fmtp:101 apt=100
60
+ a=rtpmap:35 VP9/90000
61
+ a=rtcp-fb:35 goog-remb
62
+ a=rtcp-fb:35 transport-cc
63
+ a=rtcp-fb:35 ccm fir
64
+ a=rtcp-fb:35 nack
65
+ a=rtcp-fb:35 nack pli
66
+ a=fmtp:35 profile-id=1
67
+ a=rtpmap:36 rtx/90000
68
+ a=fmtp:36 apt=35
69
+ a=rtpmap:37 VP9/90000
70
+ a=rtcp-fb:37 goog-remb
71
+ a=rtcp-fb:37 transport-cc
72
+ a=rtcp-fb:37 ccm fir
73
+ a=rtcp-fb:37 nack
74
+ a=rtcp-fb:37 nack pli
75
+ a=fmtp:37 profile-id=3
76
+ a=rtpmap:38 rtx/90000
77
+ a=fmtp:38 apt=37
78
+ a=rtpmap:103 H264/90000
79
+ a=rtcp-fb:103 goog-remb
80
+ a=rtcp-fb:103 transport-cc
81
+ a=rtcp-fb:103 ccm fir
82
+ a=rtcp-fb:103 nack
83
+ a=rtcp-fb:103 nack pli
84
+ a=fmtp:103 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
85
+ a=rtpmap:104 rtx/90000
86
+ a=fmtp:104 apt=103
87
+ a=rtpmap:107 H264/90000
88
+ a=rtcp-fb:107 goog-remb
89
+ a=rtcp-fb:107 transport-cc
90
+ a=rtcp-fb:107 ccm fir
91
+ a=rtcp-fb:107 nack
92
+ a=rtcp-fb:107 nack pli
93
+ a=fmtp:107 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
94
+ a=rtpmap:108 rtx/90000
95
+ a=fmtp:108 apt=107
96
+ a=rtpmap:109 H264/90000
97
+ a=rtcp-fb:109 goog-remb
98
+ a=rtcp-fb:109 transport-cc
99
+ a=rtcp-fb:109 ccm fir
100
+ a=rtcp-fb:109 nack
101
+ a=rtcp-fb:109 nack pli
102
+ a=fmtp:109 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
103
+ a=rtpmap:114 rtx/90000
104
+ a=fmtp:114 apt=109
105
+ a=rtpmap:115 H264/90000
106
+ a=rtcp-fb:115 goog-remb
107
+ a=rtcp-fb:115 transport-cc
108
+ a=rtcp-fb:115 ccm fir
109
+ a=rtcp-fb:115 nack
110
+ a=rtcp-fb:115 nack pli
111
+ a=fmtp:115 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
112
+ a=rtpmap:116 rtx/90000
113
+ a=fmtp:116 apt=115
114
+ a=rtpmap:117 H264/90000
115
+ a=rtcp-fb:117 goog-remb
116
+ a=rtcp-fb:117 transport-cc
117
+ a=rtcp-fb:117 ccm fir
118
+ a=rtcp-fb:117 nack
119
+ a=rtcp-fb:117 nack pli
120
+ a=fmtp:117 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d001f
121
+ a=rtpmap:118 rtx/90000
122
+ a=fmtp:118 apt=117
123
+ a=rtpmap:39 H264/90000
124
+ a=rtcp-fb:39 goog-remb
125
+ a=rtcp-fb:39 transport-cc
126
+ a=rtcp-fb:39 ccm fir
127
+ a=rtcp-fb:39 nack
128
+ a=rtcp-fb:39 nack pli
129
+ a=fmtp:39 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=4d001f
130
+ a=rtpmap:40 rtx/90000
131
+ a=fmtp:40 apt=39
132
+ a=rtpmap:41 H264/90000
133
+ a=rtcp-fb:41 goog-remb
134
+ a=rtcp-fb:41 transport-cc
135
+ a=rtcp-fb:41 ccm fir
136
+ a=rtcp-fb:41 nack
137
+ a=rtcp-fb:41 nack pli
138
+ a=fmtp:41 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=f4001f
139
+ a=rtpmap:42 rtx/90000
140
+ a=fmtp:42 apt=41
141
+ a=rtpmap:43 H264/90000
142
+ a=rtcp-fb:43 goog-remb
143
+ a=rtcp-fb:43 transport-cc
144
+ a=rtcp-fb:43 ccm fir
145
+ a=rtcp-fb:43 nack
146
+ a=rtcp-fb:43 nack pli
147
+ a=fmtp:43 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=f4001f
148
+ a=rtpmap:44 rtx/90000
149
+ a=fmtp:44 apt=43
150
+ a=rtpmap:45 AV1/90000
151
+ a=rtcp-fb:45 goog-remb
152
+ a=rtcp-fb:45 transport-cc
153
+ a=rtcp-fb:45 ccm fir
154
+ a=rtcp-fb:45 nack
155
+ a=rtcp-fb:45 nack pli
156
+ a=fmtp:45 level-idx=5;profile=0;tier=0
157
+ a=rtpmap:46 rtx/90000
158
+ a=fmtp:46 apt=45
159
+ a=rtpmap:47 AV1/90000
160
+ a=rtcp-fb:47 goog-remb
161
+ a=rtcp-fb:47 transport-cc
162
+ a=rtcp-fb:47 ccm fir
163
+ a=rtcp-fb:47 nack
164
+ a=rtcp-fb:47 nack pli
165
+ a=fmtp:47 level-idx=5;profile=1;tier=0
166
+ a=rtpmap:48 rtx/90000
167
+ a=fmtp:48 apt=47
168
+ a=rtpmap:119 H264/90000
169
+ a=rtcp-fb:119 goog-remb
170
+ a=rtcp-fb:119 transport-cc
171
+ a=rtcp-fb:119 ccm fir
172
+ a=rtcp-fb:119 nack
173
+ a=rtcp-fb:119 nack pli
174
+ a=fmtp:119 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f
175
+ a=rtpmap:120 rtx/90000
176
+ a=fmtp:120 apt=119
177
+ a=rtpmap:121 H264/90000
178
+ a=rtcp-fb:121 goog-remb
179
+ a=rtcp-fb:121 transport-cc
180
+ a=rtcp-fb:121 ccm fir
181
+ a=rtcp-fb:121 nack
182
+ a=rtcp-fb:121 nack pli
183
+ a=fmtp:121 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=64001f
184
+ a=rtpmap:122 rtx/90000
185
+ a=fmtp:122 apt=121
186
+ a=rtpmap:49 H265/90000
187
+ a=rtcp-fb:49 goog-remb
188
+ a=rtcp-fb:49 transport-cc
189
+ a=rtcp-fb:49 ccm fir
190
+ a=rtcp-fb:49 nack
191
+ a=rtcp-fb:49 nack pli
192
+ a=fmtp:49 level-id=180;profile-id=1;tier-flag=0;tx-mode=SRST
193
+ a=rtpmap:50 rtx/90000
194
+ a=fmtp:50 apt=49
195
+ a=rtpmap:51 H265/90000
196
+ a=rtcp-fb:51 goog-remb
197
+ a=rtcp-fb:51 transport-cc
198
+ a=rtcp-fb:51 ccm fir
199
+ a=rtcp-fb:51 nack
200
+ a=rtcp-fb:51 nack pli
201
+ a=fmtp:51 level-id=180;profile-id=2;tier-flag=0;tx-mode=SRST
202
+ a=rtpmap:52 rtx/90000
203
+ a=fmtp:52 apt=51
204
+ a=rtpmap:123 red/90000
205
+ a=rtpmap:124 rtx/90000
206
+ a=fmtp:124 apt=123
207
+ a=rtpmap:125 ulpfec/90000
208
+ a=rtpmap:53 flexfec-03/90000
209
+ a=rtcp-fb:53 goog-remb
210
+ a=rtcp-fb:53 transport-cc
211
+ a=fmtp:53 repair-window=10000000
212
+ m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126
213
+ c=IN IP4 0.0.0.0
214
+ a=rtcp:9 IN IP4 0.0.0.0
215
+ a=ice-ufrag:BRD8
216
+ a=ice-pwd:8e+C7eV4BeLTWG9HvRNQZ52S
217
+ a=ice-options:trickle
218
+ a=fingerprint:sha-256 7B:A4:54:EF:70:A8:30:82:F6:88:A6:DC:E9:8A:7E:6E:59:5C:53:32:D7:AD:4F:C9:4D:DB:6C:DD:0B:DD:03:04
219
+ a=setup:actpass
220
+ a=mid:1
221
+ a=extmap:14 urn:ietf:params:rtp-hdrext:ssrc-audio-level
222
+ a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
223
+ a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
224
+ a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
225
+ a=recvonly
226
+ a=rtcp-mux
227
+ a=rtcp-rsize
228
+ a=rtpmap:111 opus/48000/2
229
+ a=rtcp-fb:111 transport-cc
230
+ a=fmtp:111 minptime=10;useinbandfec=1
231
+ a=rtpmap:63 red/48000/2
232
+ a=fmtp:63 111/111
233
+ a=rtpmap:9 G722/8000
234
+ a=rtpmap:0 PCMU/8000
235
+ a=rtpmap:8 PCMA/8000
236
+ a=rtpmap:13 CN/8000
237
+ a=rtpmap:110 telephone-event/48000
238
+ a=rtpmap:126 telephone-event/8000
239
+ `;
240
+
241
+ const expectedSdpVP8 = `v=0
242
+ o=- 6339689900541563983 2 IN IP4 127.0.0.1
243
+ s=-
244
+ t=0 0
245
+ a=extmap-allow-mixed
246
+ a=msid-semantic: WMS
247
+ a=group:BUNDLE 0 1
248
+ m=video 9 UDP/TLS/RTP/SAVPF 96 97
249
+ c=IN IP4 0.0.0.0
250
+ a=rtpmap:96 VP8/90000
251
+ a=rtpmap:97 rtx/90000
252
+ a=fmtp:97 apt=96
253
+ a=rtcp:9 IN IP4 0.0.0.0
254
+ a=rtcp-fb:96 goog-remb
255
+ a=rtcp-fb:96 transport-cc
256
+ a=rtcp-fb:96 ccm fir
257
+ a=rtcp-fb:96 nack
258
+ a=rtcp-fb:96 nack pli
259
+ a=extmap:1 urn:ietf:params:rtp-hdrext:toffset
260
+ a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
261
+ a=extmap:3 urn:3gpp:video-orientation
262
+ a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
263
+ a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
264
+ a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
265
+ a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
266
+ a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
267
+ a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
268
+ a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
269
+ a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
270
+ a=setup:actpass
271
+ a=mid:0
272
+ a=recvonly
273
+ a=ice-ufrag:BRD8
274
+ a=ice-pwd:8e+C7eV4BeLTWG9HvRNQZ52S
275
+ a=fingerprint:sha-256 7B:A4:54:EF:70:A8:30:82:F6:88:A6:DC:E9:8A:7E:6E:59:5C:53:32:D7:AD:4F:C9:4D:DB:6C:DD:0B:DD:03:04
276
+ a=ice-options:trickle
277
+ a=rtcp-mux
278
+ a=rtcp-rsize
279
+ m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126
280
+ c=IN IP4 0.0.0.0
281
+ a=rtpmap:111 opus/48000/2
282
+ a=rtpmap:63 red/48000/2
283
+ a=rtpmap:9 G722/8000
284
+ a=rtpmap:0 PCMU/8000
285
+ a=rtpmap:8 PCMA/8000
286
+ a=rtpmap:13 CN/8000
287
+ a=rtpmap:110 telephone-event/48000
288
+ a=rtpmap:126 telephone-event/8000
289
+ a=fmtp:111 minptime=10;useinbandfec=1
290
+ a=fmtp:63 111/111
291
+ a=rtcp:9 IN IP4 0.0.0.0
292
+ a=rtcp-fb:111 transport-cc
293
+ a=extmap:14 urn:ietf:params:rtp-hdrext:ssrc-audio-level
294
+ a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
295
+ a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
296
+ a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
297
+ a=setup:actpass
298
+ a=mid:1
299
+ a=recvonly
300
+ a=ice-ufrag:BRD8
301
+ a=ice-pwd:8e+C7eV4BeLTWG9HvRNQZ52S
302
+ a=fingerprint:sha-256 7B:A4:54:EF:70:A8:30:82:F6:88:A6:DC:E9:8A:7E:6E:59:5C:53:32:D7:AD:4F:C9:4D:DB:6C:DD:0B:DD:03:04
303
+ a=ice-options:trickle
304
+ a=rtcp-mux
305
+ a=rtcp-rsize
306
+ `;
307
+
308
+ const expectedSdpH264 = `v=0
309
+ o=- 6339689900541563983 2 IN IP4 127.0.0.1
310
+ s=-
311
+ t=0 0
312
+ a=extmap-allow-mixed
313
+ a=msid-semantic: WMS
314
+ a=group:BUNDLE 0 1
315
+ m=video 9 UDP/TLS/RTP/SAVPF 103 104 107 108 109 114 115 116 117 118 39 40 41 42 43 44 119 120 121 122
316
+ c=IN IP4 0.0.0.0
317
+ a=rtpmap:103 H264/90000
318
+ a=rtpmap:104 rtx/90000
319
+ a=rtpmap:107 H264/90000
320
+ a=rtpmap:108 rtx/90000
321
+ a=rtpmap:109 H264/90000
322
+ a=rtpmap:114 rtx/90000
323
+ a=rtpmap:115 H264/90000
324
+ a=rtpmap:116 rtx/90000
325
+ a=rtpmap:117 H264/90000
326
+ a=rtpmap:118 rtx/90000
327
+ a=rtpmap:39 H264/90000
328
+ a=rtpmap:40 rtx/90000
329
+ a=rtpmap:41 H264/90000
330
+ a=rtpmap:42 rtx/90000
331
+ a=rtpmap:43 H264/90000
332
+ a=rtpmap:44 rtx/90000
333
+ a=rtpmap:119 H264/90000
334
+ a=rtpmap:120 rtx/90000
335
+ a=rtpmap:121 H264/90000
336
+ a=rtpmap:122 rtx/90000
337
+ a=fmtp:103 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
338
+ a=fmtp:104 apt=103
339
+ a=fmtp:107 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
340
+ a=fmtp:108 apt=107
341
+ a=fmtp:109 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
342
+ a=fmtp:114 apt=109
343
+ a=fmtp:115 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
344
+ a=fmtp:116 apt=115
345
+ a=fmtp:117 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d001f
346
+ a=fmtp:118 apt=117
347
+ a=fmtp:39 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=4d001f
348
+ a=fmtp:40 apt=39
349
+ a=fmtp:41 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=f4001f
350
+ a=fmtp:42 apt=41
351
+ a=fmtp:43 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=f4001f
352
+ a=fmtp:44 apt=43
353
+ a=fmtp:119 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f
354
+ a=fmtp:120 apt=119
355
+ a=fmtp:121 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=64001f
356
+ a=fmtp:122 apt=121
357
+ a=rtcp:9 IN IP4 0.0.0.0
358
+ a=rtcp-fb:103 goog-remb
359
+ a=rtcp-fb:103 transport-cc
360
+ a=rtcp-fb:103 ccm fir
361
+ a=rtcp-fb:103 nack
362
+ a=rtcp-fb:103 nack pli
363
+ a=rtcp-fb:107 goog-remb
364
+ a=rtcp-fb:107 transport-cc
365
+ a=rtcp-fb:107 ccm fir
366
+ a=rtcp-fb:107 nack
367
+ a=rtcp-fb:107 nack pli
368
+ a=rtcp-fb:109 goog-remb
369
+ a=rtcp-fb:109 transport-cc
370
+ a=rtcp-fb:109 ccm fir
371
+ a=rtcp-fb:109 nack
372
+ a=rtcp-fb:109 nack pli
373
+ a=rtcp-fb:115 goog-remb
374
+ a=rtcp-fb:115 transport-cc
375
+ a=rtcp-fb:115 ccm fir
376
+ a=rtcp-fb:115 nack
377
+ a=rtcp-fb:115 nack pli
378
+ a=rtcp-fb:117 goog-remb
379
+ a=rtcp-fb:117 transport-cc
380
+ a=rtcp-fb:117 ccm fir
381
+ a=rtcp-fb:117 nack
382
+ a=rtcp-fb:117 nack pli
383
+ a=rtcp-fb:39 goog-remb
384
+ a=rtcp-fb:39 transport-cc
385
+ a=rtcp-fb:39 ccm fir
386
+ a=rtcp-fb:39 nack
387
+ a=rtcp-fb:39 nack pli
388
+ a=rtcp-fb:41 goog-remb
389
+ a=rtcp-fb:41 transport-cc
390
+ a=rtcp-fb:41 ccm fir
391
+ a=rtcp-fb:41 nack
392
+ a=rtcp-fb:41 nack pli
393
+ a=rtcp-fb:43 goog-remb
394
+ a=rtcp-fb:43 transport-cc
395
+ a=rtcp-fb:43 ccm fir
396
+ a=rtcp-fb:43 nack
397
+ a=rtcp-fb:43 nack pli
398
+ a=rtcp-fb:119 goog-remb
399
+ a=rtcp-fb:119 transport-cc
400
+ a=rtcp-fb:119 ccm fir
401
+ a=rtcp-fb:119 nack
402
+ a=rtcp-fb:119 nack pli
403
+ a=rtcp-fb:121 goog-remb
404
+ a=rtcp-fb:121 transport-cc
405
+ a=rtcp-fb:121 ccm fir
406
+ a=rtcp-fb:121 nack
407
+ a=rtcp-fb:121 nack pli
408
+ a=extmap:1 urn:ietf:params:rtp-hdrext:toffset
409
+ a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
410
+ a=extmap:3 urn:3gpp:video-orientation
411
+ a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
412
+ a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
413
+ a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
414
+ a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
415
+ a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
416
+ a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
417
+ a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
418
+ a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
419
+ a=setup:actpass
420
+ a=mid:0
421
+ a=recvonly
422
+ a=ice-ufrag:BRD8
423
+ a=ice-pwd:8e+C7eV4BeLTWG9HvRNQZ52S
424
+ a=fingerprint:sha-256 7B:A4:54:EF:70:A8:30:82:F6:88:A6:DC:E9:8A:7E:6E:59:5C:53:32:D7:AD:4F:C9:4D:DB:6C:DD:0B:DD:03:04
425
+ a=ice-options:trickle
426
+ a=rtcp-mux
427
+ a=rtcp-rsize
428
+ m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126
429
+ c=IN IP4 0.0.0.0
430
+ a=rtpmap:111 opus/48000/2
431
+ a=rtpmap:63 red/48000/2
432
+ a=rtpmap:9 G722/8000
433
+ a=rtpmap:0 PCMU/8000
434
+ a=rtpmap:8 PCMA/8000
435
+ a=rtpmap:13 CN/8000
436
+ a=rtpmap:110 telephone-event/48000
437
+ a=rtpmap:126 telephone-event/8000
438
+ a=fmtp:111 minptime=10;useinbandfec=1
439
+ a=fmtp:63 111/111
440
+ a=rtcp:9 IN IP4 0.0.0.0
441
+ a=rtcp-fb:111 transport-cc
442
+ a=extmap:14 urn:ietf:params:rtp-hdrext:ssrc-audio-level
443
+ a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
444
+ a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
445
+ a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
446
+ a=setup:actpass
447
+ a=mid:1
448
+ a=recvonly
449
+ a=ice-ufrag:BRD8
450
+ a=ice-pwd:8e+C7eV4BeLTWG9HvRNQZ52S
451
+ a=fingerprint:sha-256 7B:A4:54:EF:70:A8:30:82:F6:88:A6:DC:E9:8A:7E:6E:59:5C:53:32:D7:AD:4F:C9:4D:DB:6C:DD:0B:DD:03:04
452
+ a=ice-options:trickle
453
+ a=rtcp-mux
454
+ a=rtcp-rsize
455
+ `;
456
+
457
+ const expectedSdpH264Profile64001f = `v=0
458
+ o=- 6339689900541563983 2 IN IP4 127.0.0.1
459
+ s=-
460
+ t=0 0
461
+ a=extmap-allow-mixed
462
+ a=msid-semantic: WMS
463
+ a=group:BUNDLE 0 1
464
+ m=video 9 UDP/TLS/RTP/SAVPF 119 120
465
+ c=IN IP4 0.0.0.0
466
+ a=rtpmap:119 H264/90000
467
+ a=rtpmap:120 rtx/90000
468
+ a=fmtp:119 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f
469
+ a=fmtp:120 apt=119
470
+ a=rtcp:9 IN IP4 0.0.0.0
471
+ a=rtcp-fb:119 goog-remb
472
+ a=rtcp-fb:119 transport-cc
473
+ a=rtcp-fb:119 ccm fir
474
+ a=rtcp-fb:119 nack
475
+ a=rtcp-fb:119 nack pli
476
+ a=extmap:1 urn:ietf:params:rtp-hdrext:toffset
477
+ a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
478
+ a=extmap:3 urn:3gpp:video-orientation
479
+ a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
480
+ a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
481
+ a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
482
+ a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
483
+ a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
484
+ a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
485
+ a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
486
+ a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
487
+ a=setup:actpass
488
+ a=mid:0
489
+ a=recvonly
490
+ a=ice-ufrag:BRD8
491
+ a=ice-pwd:8e+C7eV4BeLTWG9HvRNQZ52S
492
+ a=fingerprint:sha-256 7B:A4:54:EF:70:A8:30:82:F6:88:A6:DC:E9:8A:7E:6E:59:5C:53:32:D7:AD:4F:C9:4D:DB:6C:DD:0B:DD:03:04
493
+ a=ice-options:trickle
494
+ a=rtcp-mux
495
+ a=rtcp-rsize
496
+ m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126
497
+ c=IN IP4 0.0.0.0
498
+ a=rtpmap:111 opus/48000/2
499
+ a=rtpmap:63 red/48000/2
500
+ a=rtpmap:9 G722/8000
501
+ a=rtpmap:0 PCMU/8000
502
+ a=rtpmap:8 PCMA/8000
503
+ a=rtpmap:13 CN/8000
504
+ a=rtpmap:110 telephone-event/48000
505
+ a=rtpmap:126 telephone-event/8000
506
+ a=fmtp:111 minptime=10;useinbandfec=1
507
+ a=fmtp:63 111/111
508
+ a=rtcp:9 IN IP4 0.0.0.0
509
+ a=rtcp-fb:111 transport-cc
510
+ a=extmap:14 urn:ietf:params:rtp-hdrext:ssrc-audio-level
511
+ a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
512
+ a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
513
+ a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
514
+ a=setup:actpass
515
+ a=mid:1
516
+ a=recvonly
517
+ a=ice-ufrag:BRD8
518
+ a=ice-pwd:8e+C7eV4BeLTWG9HvRNQZ52S
519
+ a=fingerprint:sha-256 7B:A4:54:EF:70:A8:30:82:F6:88:A6:DC:E9:8A:7E:6E:59:5C:53:32:D7:AD:4F:C9:4D:DB:6C:DD:0B:DD:03:04
520
+ a=ice-options:trickle
521
+ a=rtcp-mux
522
+ a=rtcp-rsize
523
+ `;
524
+
525
+ const expectedSdpH264Profile64001fOnly = `v=0
526
+ o=- 6339689900541563983 2 IN IP4 127.0.0.1
527
+ s=-
528
+ t=0 0
529
+ a=extmap-allow-mixed
530
+ a=msid-semantic: WMS
531
+ a=group:BUNDLE 0 1
532
+ m=video 9 UDP/TLS/RTP/SAVPF 119 120 121 122
533
+ c=IN IP4 0.0.0.0
534
+ a=rtpmap:119 H264/90000
535
+ a=rtpmap:120 rtx/90000
536
+ a=rtpmap:121 H264/90000
537
+ a=rtpmap:122 rtx/90000
538
+ a=fmtp:119 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f
539
+ a=fmtp:120 apt=119
540
+ a=fmtp:121 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=64001f
541
+ a=fmtp:122 apt=121
542
+ a=rtcp:9 IN IP4 0.0.0.0
543
+ a=rtcp-fb:119 goog-remb
544
+ a=rtcp-fb:119 transport-cc
545
+ a=rtcp-fb:119 ccm fir
546
+ a=rtcp-fb:119 nack
547
+ a=rtcp-fb:119 nack pli
548
+ a=rtcp-fb:121 goog-remb
549
+ a=rtcp-fb:121 transport-cc
550
+ a=rtcp-fb:121 ccm fir
551
+ a=rtcp-fb:121 nack
552
+ a=rtcp-fb:121 nack pli
553
+ a=extmap:1 urn:ietf:params:rtp-hdrext:toffset
554
+ a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
555
+ a=extmap:3 urn:3gpp:video-orientation
556
+ a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
557
+ a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
558
+ a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
559
+ a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
560
+ a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
561
+ a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
562
+ a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
563
+ a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
564
+ a=setup:actpass
565
+ a=mid:0
566
+ a=recvonly
567
+ a=ice-ufrag:BRD8
568
+ a=ice-pwd:8e+C7eV4BeLTWG9HvRNQZ52S
569
+ a=fingerprint:sha-256 7B:A4:54:EF:70:A8:30:82:F6:88:A6:DC:E9:8A:7E:6E:59:5C:53:32:D7:AD:4F:C9:4D:DB:6C:DD:0B:DD:03:04
570
+ a=ice-options:trickle
571
+ a=rtcp-mux
572
+ a=rtcp-rsize
573
+ m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126
574
+ c=IN IP4 0.0.0.0
575
+ a=rtpmap:111 opus/48000/2
576
+ a=rtpmap:63 red/48000/2
577
+ a=rtpmap:9 G722/8000
578
+ a=rtpmap:0 PCMU/8000
579
+ a=rtpmap:8 PCMA/8000
580
+ a=rtpmap:13 CN/8000
581
+ a=rtpmap:110 telephone-event/48000
582
+ a=rtpmap:126 telephone-event/8000
583
+ a=fmtp:111 minptime=10;useinbandfec=1
584
+ a=fmtp:63 111/111
585
+ a=rtcp:9 IN IP4 0.0.0.0
586
+ a=rtcp-fb:111 transport-cc
587
+ a=extmap:14 urn:ietf:params:rtp-hdrext:ssrc-audio-level
588
+ a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
589
+ a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
590
+ a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
591
+ a=setup:actpass
592
+ a=mid:1
593
+ a=recvonly
594
+ a=ice-ufrag:BRD8
595
+ a=ice-pwd:8e+C7eV4BeLTWG9HvRNQZ52S
596
+ a=fingerprint:sha-256 7B:A4:54:EF:70:A8:30:82:F6:88:A6:DC:E9:8A:7E:6E:59:5C:53:32:D7:AD:4F:C9:4D:DB:6C:DD:0B:DD:03:04
597
+ a=ice-options:trickle
598
+ a=rtcp-mux
599
+ a=rtcp-rsize
600
+ `;
601
+
602
+ describe('sdp - remove codecs', () => {
603
+ it('it should remove non-matching codecs', () => {
604
+ expect(removeCodecsExcept(sdp, 'video/vp8', undefined)).toEqual(
605
+ expectedSdpVP8.replace(/\n/g, '\r\n'),
606
+ );
607
+ expect(removeCodecsExcept(sdp, 'video/h264', undefined)).toEqual(
608
+ expectedSdpH264.replace(/\n/g, '\r\n'),
609
+ );
610
+ expect(
611
+ removeCodecsExcept(
612
+ sdp,
613
+ 'video/h264',
614
+ 'level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f',
615
+ ),
616
+ ).toEqual(expectedSdpH264Profile64001f.replace(/\n/g, '\r\n'));
617
+ expect(
618
+ removeCodecsExcept(
619
+ sdp,
620
+ 'video/h264',
621
+ 'level-asymmetry-allowed=1;profile-level-id=64001f;packetization-mode=1',
622
+ ),
623
+ ).toEqual(expectedSdpH264Profile64001f.replace(/\n/g, '\r\n'));
624
+ expect(
625
+ removeCodecsExcept(sdp, 'video/h264', 'profile-level-id=64001f'),
626
+ ).toEqual(expectedSdpH264Profile64001fOnly.replace(/\n/g, '\r\n'));
627
+ });
628
+ });
@@ -70,3 +70,85 @@ export const enableStereo = (offerSdp: string, answerSdp: string): string => {
70
70
 
71
71
  return write(parsedAnswerSdp);
72
72
  };
73
+
74
+ /**
75
+ * Removes all codecs from the SDP except the specified codec.
76
+ *
77
+ * @param sdp the SDP to modify.
78
+ * @param codecMimeTypeToKeep the codec mime type to keep (video/h264 or audio/opus).
79
+ * @param fmtpProfileToKeep the fmtp profile to keep (e.g. 'profile-level-id=42e01f' or multiple segments like 'profile-level-id=64001f;packetization-mode=1').
80
+ */
81
+ export const removeCodecsExcept = (
82
+ sdp: string,
83
+ codecMimeTypeToKeep: string,
84
+ fmtpProfileToKeep: string | undefined,
85
+ ): string => {
86
+ const [kind, codec] = toMimeType(codecMimeTypeToKeep).split('/');
87
+ if (!kind || !codec) return sdp;
88
+
89
+ const parsed = parse(sdp);
90
+ for (const media of parsed.media) {
91
+ if (media.type !== kind) continue;
92
+
93
+ // Build a set of payloads to KEEP: all payloads whose rtp.codec matches codec
94
+ let payloadsToKeep = new Set<number>();
95
+ for (const rtp of media.rtp) {
96
+ if (rtp.codec.toLowerCase() !== codec) continue;
97
+ payloadsToKeep.add(rtp.payload);
98
+ }
99
+
100
+ // If a specific fmtp profile is requested, only keep payloads whose fmtp config matches it
101
+ if (fmtpProfileToKeep) {
102
+ const filtered = new Set<number>();
103
+ const required = new Set(fmtpProfileToKeep.split(';'));
104
+ for (const fmtp of media.fmtp) {
105
+ if (
106
+ payloadsToKeep.has(fmtp.payload) &&
107
+ required.difference(new Set(fmtp.config.split(';'))).size === 0
108
+ ) {
109
+ filtered.add(fmtp.payload);
110
+ }
111
+ }
112
+ payloadsToKeep = filtered;
113
+ }
114
+
115
+ // If no payloads to keep AND no fmtpProfile was specified, skip modifications (preserve SDP as-is)
116
+ if (payloadsToKeep.size === 0 && !fmtpProfileToKeep) continue;
117
+
118
+ // Keep RTX payloads that are associated with kept primary payloads via apt
119
+ // RTX mappings look like: a=fmtp:<rtxPayload> apt=<primaryPayload>
120
+ for (const fmtp of media.fmtp) {
121
+ const matches = /\s*apt\s*=\s*(\d+)\s*/i.exec(fmtp.config);
122
+ if (!matches) continue;
123
+
124
+ const primaryPayloadApt = Number(matches[1]);
125
+ if (!payloadsToKeep.has(primaryPayloadApt)) continue;
126
+ payloadsToKeep.add(fmtp.payload);
127
+ }
128
+
129
+ // Filter rtp, fmtp and rtcpFb entries
130
+ media.rtp = media.rtp.filter((rtp) => payloadsToKeep.has(rtp.payload));
131
+ media.fmtp = media.fmtp.filter((fmtp) => payloadsToKeep.has(fmtp.payload));
132
+ media.rtcpFb = media.rtcpFb?.filter((fb) =>
133
+ typeof fb.payload === 'number' ? payloadsToKeep.has(fb.payload) : true,
134
+ );
135
+
136
+ // Update the m= line payload list to only the kept payloads, preserving original order
137
+ const payloads: number[] = [];
138
+ for (const id of (media.payloads || '').split(/\s+/)) {
139
+ const payload = Number(id);
140
+ if (!payloadsToKeep.has(payload)) continue;
141
+ payloads.push(payload);
142
+ }
143
+ media.payloads = payloads.join(' ');
144
+ }
145
+
146
+ return write(parsed);
147
+ };
148
+
149
+ /**
150
+ * Converts the given codec to a mime-type format when necessary.
151
+ * e.g.: `vp9` -> `video/vp9`
152
+ */
153
+ const toMimeType = (codec: string, kind: 'video' | 'audio' = 'video') =>
154
+ codec.includes('/') ? codec : `${kind}/${codec}`;