blob: 22abbb3718a91fca24ca4c0c378c7cc5b265ee05 [file] [log] [blame]
Soares Chen172fe9d2017-07-18 09:30:181<!doctype html>
2<meta charset=utf-8>
3<title>RTCRtpParameters encodings</title>
4<script src="/resources/testharness.js"></script>
5<script src="/resources/testharnessreport.js"></script>
6<script src="dictionary-helper.js"></script>
7<script src="RTCRtpParameters-helper.js"></script>
8<script>
9 'use strict';
10
11 // Test is based on the following editor draft:
12 // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
13
14 // The following helper functions are called from RTCRtpParameters-helper.js:
Soares Chen172fe9d2017-07-18 09:30:1815 // validateSenderRtpParameters
16
17 /*
18 5.1. RTCPeerConnection Interface Extensions
19 partial interface RTCPeerConnection {
20 RTCRtpTransceiver addTransceiver((MediaStreamTrack or DOMString) trackOrKind,
21 optional RTCRtpTransceiverInit init);
22 ...
23 };
24
25 dictionary RTCRtpTransceiverInit {
26 RTCRtpTransceiverDirection direction = "sendrecv";
27 sequence<MediaStream> streams;
28 sequence<RTCRtpEncodingParameters> sendEncodings;
29 };
30
31 5.2. RTCRtpSender Interface
32 interface RTCRtpSender {
33 Promise<void> setParameters(optional RTCRtpParameters parameters);
34 RTCRtpParameters getParameters();
35 };
36
37 dictionary RTCRtpParameters {
38 DOMString transactionId;
39 sequence<RTCRtpEncodingParameters> encodings;
40 sequence<RTCRtpHeaderExtensionParameters> headerExtensions;
41 RTCRtcpParameters rtcp;
42 sequence<RTCRtpCodecParameters> codecs;
Soares Chen172fe9d2017-07-18 09:30:1843 };
44
45 dictionary RTCRtpEncodingParameters {
Soares Chen172fe9d2017-07-18 09:30:1846 boolean active;
Soares Chen172fe9d2017-07-18 09:30:1847 unsigned long maxBitrate;
Soares Chen172fe9d2017-07-18 09:30:1848
49 [readonly]
50 DOMString rid;
51
52 double scaleResolutionDownBy;
53 };
54
Soares Chen172fe9d2017-07-18 09:30:1855 getParameters
56 - encodings is set to the value of the [[send encodings]] internal slot.
57 */
58
Byron Campen45fa2f22022-12-14 01:52:5959 promise_test(async t => {
60 const pc = new RTCPeerConnection();
61 t.add_cleanup(() => pc.close());
62 const transceiver = pc.addTransceiver('video');
63
64 const param = transceiver.sender.getParameters();
65 assert_equals(param.encodings.length, 1);
66 // Do not call this in every test; it does not make sense to disable all of
67 // the tests below for an implementation that is missing support for
68 // fields that are not related to the test.
69 validateSenderRtpParameters(param);
70 }, `getParameters should return RTCRtpEncodingParameters with all required fields`);
71
Soares Chen172fe9d2017-07-18 09:30:1872 /*
73 5.1. addTransceiver
74 7. Create an RTCRtpSender with track, streams and sendEncodings and let sender
75 be the result.
76
77 5.2. create an RTCRtpSender
78 5. Let sender have a [[send encodings]] internal slot, representing a list
79 of RTCRtpEncodingParameters dictionaries.
80 6. If sendEncodings is given as input to this algorithm, and is non-empty,
81 set the [[send encodings]] slot to sendEncodings.
82
83 Otherwise, set it to a list containing a single RTCRtpEncodingParameters
84 with active set to true.
85 */
Henrik Boström36fb0332018-06-29 09:09:0486 promise_test(async t => {
Soares Chen172fe9d2017-07-18 09:30:1887 const pc = new RTCPeerConnection();
Henrik Boström36fb0332018-06-29 09:09:0488 t.add_cleanup(() => pc.close());
Soares Chen172fe9d2017-07-18 09:30:1889 const transceiver = pc.addTransceiver('audio');
Henrik Boström36fb0332018-06-29 09:09:0490
Soares Chen172fe9d2017-07-18 09:30:1891 const param = transceiver.sender.getParameters();
Soares Chen172fe9d2017-07-18 09:30:1892 const { encodings } = param;
Byron Campen45fa2f22022-12-14 01:52:5993 assert_equals(encodings.length, 1);
94 const encoding = param.encodings[0];
Soares Chen172fe9d2017-07-18 09:30:1895
96 assert_equals(encoding.active, true);
Byron Campen45fa2f22022-12-14 01:52:5997 assert_not_own_property(encoding, "maxBitrate");
98 assert_not_own_property(encoding, "rid");
99 assert_not_own_property(encoding, "scaleResolutionDownBy");
100 // We do not check props from extension specifications here; those checks
101 // need to go in a test-case for that extension specification.
102 }, 'addTransceiver(audio) with undefined sendEncodings should have default encoding parameter with active set to true');
103
104 promise_test(async t => {
105 const pc = new RTCPeerConnection();
106 t.add_cleanup(() => pc.close());
107 const transceiver = pc.addTransceiver('video');
108
109 const param = transceiver.sender.getParameters();
110 const { encodings } = param;
111 assert_equals(encodings.length, 1);
112 const encoding = param.encodings[0];
113
114 assert_equals(encoding.active, true);
115 // spec says to return an encoding without a scaleResolutionDownBy value
116 // when addTransceiver does not pass any encodings, however spec also says
117 // to throw if setParameters is missing a scaleResolutionDownBy. One of
118 // these two requirements needs to be removed, but it is unclear right now
119 // which will be removed. For now, allow scaleResolutionDownBy, but don't
120 // require it.
121 // https://github.com/w3c/webrtc-pc/issues/2730
122 assert_not_own_property(encoding, "maxBitrate");
123 assert_not_own_property(encoding, "rid");
124 assert_equals(encoding.scaleResolutionDownBy, 1.0);
125 // We do not check props from extension specifications here; those checks
126 // need to go in a test-case for that extension specification.
127 }, 'addTransceiver(video) with undefined sendEncodings should have default encoding parameter with active set to true and scaleResolutionDownBy set to 1');
Soares Chen172fe9d2017-07-18 09:30:18128
Henrik Boström36fb0332018-06-29 09:09:04129 promise_test(async t => {
Soares Chen172fe9d2017-07-18 09:30:18130 const pc = new RTCPeerConnection();
Henrik Boström36fb0332018-06-29 09:09:04131 t.add_cleanup(() => pc.close());
Soares Chen172fe9d2017-07-18 09:30:18132 const transceiver = pc.addTransceiver('audio', { sendEncodings: [] });
Soares Chen172fe9d2017-07-18 09:30:18133
134 const param = transceiver.sender.getParameters();
Soares Chen172fe9d2017-07-18 09:30:18135 const { encodings } = param;
Byron Campen45fa2f22022-12-14 01:52:59136 assert_equals(encodings.length, 1);
137 const encoding = param.encodings[0];
Soares Chen172fe9d2017-07-18 09:30:18138
139 assert_equals(encoding.active, true);
Byron Campen45fa2f22022-12-14 01:52:59140 assert_not_own_property(encoding, "maxBitrate");
141 assert_not_own_property(encoding, "rid");
142 assert_not_own_property(encoding, "scaleResolutionDownBy");
143 // We do not check props from extension specifications here; those checks
144 // need to go in a test-case for that extension specification.
145 }, 'addTransceiver(audio) with empty list sendEncodings should have default encoding parameter with active set to true');
146
147 promise_test(async t => {
148 const pc = new RTCPeerConnection();
149 t.add_cleanup(() => pc.close());
150 const transceiver = pc.addTransceiver('video', { sendEncodings: [] });
151
152 const param = transceiver.sender.getParameters();
153 const { encodings } = param;
154 assert_equals(encodings.length, 1);
155 const encoding = param.encodings[0];
156
157 assert_equals(encoding.active, true);
158 assert_not_own_property(encoding, "maxBitrate");
159 assert_not_own_property(encoding, "rid");
160 assert_equals(encoding.scaleResolutionDownBy, 1.0);
161 // We do not check props from extension specifications here; those checks
162 // need to go in a test-case for that extension specification.
163 }, 'addTransceiver(video) with empty list sendEncodings should have default encoding parameter with active set to true and scaleResolutionDownBy set to 1');
164
165 promise_test(async t => {
166 const pc = new RTCPeerConnection();
167 t.add_cleanup(() => pc.close());
168 const transceiver = pc.addTransceiver('video', {sendEncodings: [{rid: "foo"}, {rid: "bar", scaleResolutionDownBy: 3.0}]});
169
170 const param = transceiver.sender.getParameters();
171 const { encodings } = param;
172 assert_equals(encodings.length, 2);
173 assert_equals(encodings[0].scaleResolutionDownBy, 1.0);
174 assert_equals(encodings[1].scaleResolutionDownBy, 3.0);
175 }, `addTransceiver(video) should auto-set scaleResolutionDownBy to 1 when some encodings have it, but not all`);
176
177 promise_test(async t => {
178 const pc = new RTCPeerConnection();
179 t.add_cleanup(() => pc.close());
180 const transceiver = pc.addTransceiver('video', {sendEncodings: [{rid: "foo"}, {rid: "bar"}]});
181
182 const param = transceiver.sender.getParameters();
183 const { encodings } = param;
184 assert_equals(encodings.length, 2);
185 assert_equals(encodings[0].scaleResolutionDownBy, 2.0);
186 assert_equals(encodings[1].scaleResolutionDownBy, 1.0);
187 }, `addTransceiver should auto-set scaleResolutionDownBy to powers of 2 (descending) when absent`);
188
189 promise_test(async t => {
190 const pc = new RTCPeerConnection();
191 t.add_cleanup(() => pc.close());
192 const sendEncodings = [];
193 for (let i = 0; i < 1000; i++) {
194 sendEncodings.push({rid: i});
195 }
196 const transceiver = pc.addTransceiver('video', {sendEncodings});
197
198 const param = transceiver.sender.getParameters();
199 const { encodings } = param;
200 assert_less_than(encodings.length, 1000, `1000 encodings is clearly too many`);
201 }, `addTransceiver with a ridiculous number of encodings should truncate the list`);
202
203 promise_test(async t => {
204 const pc = new RTCPeerConnection();
205 t.add_cleanup(() => pc.close());
206 const transceiver = pc.addTransceiver('audio', {sendEncodings: [{rid: "foo"}, {rid: "bar"}]});
207
208 const param = transceiver.sender.getParameters();
209 const { encodings } = param;
210 assert_equals(encodings.length, 1);
211 assert_not_own_property(encodings[0], "maxBitrate");
212 assert_not_own_property(encodings[0], "rid");
213 assert_not_own_property(encodings[0], "scaleResolutionDownBy");
214 // We do not check props from extension specifications here; those checks
215 // need to go in a test-case for that extension specification.
216 }, `addTransceiver(audio) with multiple encodings should result in one encoding with no properties other than active`);
217
218 promise_test(async t => {
219 const pc = new RTCPeerConnection();
220 t.add_cleanup(() => pc.close());
221 const {sender} = pc.addTransceiver('audio', {sendEncodings: [{rid: "foo", scaleResolutionDownBy: 2.0}]});
222 const {encodings} = sender.getParameters();
223 assert_equals(encodings.length, 1);
224 assert_not_own_property(encodings[0], "scaleResolutionDownBy");
225 }, `addTransceiver(audio) should remove valid scaleResolutionDownBy`);
226
227 promise_test(async t => {
228 const pc = new RTCPeerConnection();
229 t.add_cleanup(() => pc.close());
230 const {sender} = pc.addTransceiver('audio', {sendEncodings: [{rid: "foo", scaleResolutionDownBy: -1.0}]});
231 const {encodings} = sender.getParameters();
232 assert_equals(encodings.length, 1);
233 assert_not_own_property(encodings[0], "scaleResolutionDownBy");
234 }, `addTransceiver(audio) should remove invalid scaleResolutionDownBy`);
235
236 promise_test(async t => {
237 const pc = new RTCPeerConnection();
238 t.add_cleanup(() => pc.close());
239 const {sender} = pc.addTransceiver('audio');
240 let params = sender.getParameters();
241 assert_equals(params.encodings.length, 1);
242 params.encodings[0].scaleResolutionDownBy = 2;
243 await sender.setParameters(params);
244 const {encodings} = sender.getParameters();
245 assert_equals(encodings.length, 1);
246 assert_not_own_property(encodings[0], "scaleResolutionDownBy");
247 }, `setParameters with scaleResolutionDownBy on an audio sender should succeed, but remove the scaleResolutionDownBy`);
248
249 promise_test(async t => {
250 const pc = new RTCPeerConnection();
251 t.add_cleanup(() => pc.close());
252 const {sender} = pc.addTransceiver('audio');
253 let params = sender.getParameters();
254 assert_equals(params.encodings.length, 1);
255 params.encodings[0].scaleResolutionDownBy = -1;
256 await sender.setParameters(params);
257 const {encodings} = sender.getParameters();
258 assert_equals(encodings.length, 1);
259 assert_not_own_property(encodings[0], "scaleResolutionDownBy");
260 }, `setParameters with an invalid scaleResolutionDownBy on an audio sender should succeed, but remove the scaleResolutionDownBy`);
261
262 promise_test(async t => {
263 const pc = new RTCPeerConnection();
264 t.add_cleanup(() => pc.close());
265
266 assert_throws_js(TypeError, () => pc.addTransceiver('video', { sendEncodings: [{rid: "foo"}, {rid: "foo"}] }));
267 }, 'addTransceiver with duplicate rid and multiple encodings throws TypeError');
268
269 promise_test(async t => {
270 const pc = new RTCPeerConnection();
271 t.add_cleanup(() => pc.close());
272
273 assert_throws_js(TypeError, () => pc.addTransceiver('video', { sendEncodings: [{rid: "foo"}, {}] }));
274 }, 'addTransceiver with missing rid and multiple encodings throws TypeError');
275
276 promise_test(async t => {
277 const pc = new RTCPeerConnection();
278 t.add_cleanup(() => pc.close());
279
280 assert_throws_js(TypeError, () => pc.addTransceiver('video', { sendEncodings: [{rid: ""}] }));
281 }, 'addTransceiver with empty rid throws TypeError');
282
283 promise_test(async t => {
284 const pc = new RTCPeerConnection();
285 t.add_cleanup(() => pc.close());
286
287 assert_throws_js(TypeError, () => pc.addTransceiver('video', { sendEncodings: [{rid: "!?"}] }));
288 assert_throws_js(TypeError, () => pc.addTransceiver('video', { sendEncodings: [{rid: "(╯°□°)╯︵ ┻━┻"}] }));
289 // RFC 8851 says '-' and '_' are allowed, but RFC 8852 says they are not.
290 // RFC 8852 needs to be adhered to, otherwise we can't put the rid in RTP
291 // https://github.com/w3c/webrtc-pc/issues/2732
292 // https://www.rfc-editor.org/errata/eid7132
293 assert_throws_js(TypeError, () => pc.addTransceiver('video', { sendEncodings: [{rid: "foo-bar"}] }));
294 assert_throws_js(TypeError, () => pc.addTransceiver('video', { sendEncodings: [{rid: "foo_bar"}] }));
295 }, 'addTransceiver with invalid rid characters throws TypeError');
296
297 promise_test(async t => {
298 const pc = new RTCPeerConnection();
299 t.add_cleanup(() => pc.close());
300
301 // https://github.com/w3c/webrtc-pc/issues/2732
302 assert_throws_js(TypeError, () => pc.addTransceiver('video', { sendEncodings: [{rid: 'a'.repeat(256)}] }));
303 }, 'addTransceiver with rid longer than 255 characters throws TypeError');
304
305 promise_test(async t => {
306 const pc = new RTCPeerConnection();
307 t.add_cleanup(() => pc.close());
308
309 assert_throws_js(RangeError, () => pc.addTransceiver('video', { sendEncodings: [{scaleResolutionDownBy: -1}] }));
310 assert_throws_js(RangeError, () => pc.addTransceiver('video', { sendEncodings: [{scaleResolutionDownBy: 0}] }));
311 assert_throws_js(RangeError, () => pc.addTransceiver('video', { sendEncodings: [{scaleResolutionDownBy: 0.5}] }));
312 }, `addTransceiver with scaleResolutionDownBy < 1 throws RangeError`);
Soares Chen172fe9d2017-07-18 09:30:18313
314 /*
315 5.2. create an RTCRtpSender
316 To create an RTCRtpSender with a MediaStreamTrack , track, a list of MediaStream
317 objects, streams, and optionally a list of RTCRtpEncodingParameters objects,
318 sendEncodings, run the following steps:
319 5. Let sender have a [[send encodings]] internal slot, representing a list
320 of RTCRtpEncodingParameters dictionaries.
321
322 6. If sendEncodings is given as input to this algorithm, and is non-empty,
323 set the [[send encodings]] slot to sendEncodings.
324
325 5.2. getParameters
326 - encodings is set to the value of the [[send encodings]] internal slot.
327 */
Henrik Boström36fb0332018-06-29 09:09:04328 promise_test(async t => {
Soares Chen172fe9d2017-07-18 09:30:18329 const pc = new RTCPeerConnection();
Henrik Boström36fb0332018-06-29 09:09:04330 t.add_cleanup(() => pc.close());
Florent Castelliea0c6132020-01-16 16:33:29331 const { sender } = pc.addTransceiver('video', {
Soares Chen172fe9d2017-07-18 09:30:18332 sendEncodings: [{
Soares Chen172fe9d2017-07-18 09:30:18333 active: false,
Soares Chen172fe9d2017-07-18 09:30:18334 maxBitrate: 8,
Soares Chen172fe9d2017-07-18 09:30:18335 rid: 'foo'
336 }]
337 });
Soares Chen172fe9d2017-07-18 09:30:18338
339 const param = sender.getParameters();
Byron Campen45fa2f22022-12-14 01:52:59340 const encoding = param.encodings[0];
Soares Chen172fe9d2017-07-18 09:30:18341
Soares Chen172fe9d2017-07-18 09:30:18342 assert_equals(encoding.active, false);
Soares Chen172fe9d2017-07-18 09:30:18343 assert_equals(encoding.maxBitrate, 8);
Florent Castelliea0c6132020-01-16 16:33:29344 assert_not_own_property(encoding, "rid", "rid should be removed with a single encoding");
Soares Chen172fe9d2017-07-18 09:30:18345
346 }, `sender.getParameters() should return sendEncodings set by addTransceiver()`);
347
348 /*
349 5.2. setParameters
350 3. Let N be the number of RTCRtpEncodingParameters stored in sender's internal
351 [[send encodings]] slot.
352 7. If parameters.encodings.length is different from N, or if any parameter
353 in the parameters argument, marked as a Read-only parameter, has a value
354 that is different from the corresponding parameter value returned from
355 sender.getParameters(), abort these steps and return a promise rejected
356 with a newly created InvalidModificationError. Note that this also applies
357 to transactionId.
358 */
Henrik Boström36fb0332018-06-29 09:09:04359 promise_test(async t => {
Soares Chen172fe9d2017-07-18 09:30:18360 const pc = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53361 t.add_cleanup(() => pc.close());
Byron Campen45fa2f22022-12-14 01:52:59362 const { sender } = pc.addTransceiver('video');
Henrik Boström36fb0332018-06-29 09:09:04363
Soares Chen172fe9d2017-07-18 09:30:18364 const param = sender.getParameters();
Soares Chen172fe9d2017-07-18 09:30:18365
366 const { encodings } = param;
367 assert_equals(encodings.length, 1);
368
Byron Campen45fa2f22022-12-14 01:52:59369 // While {} is valid RTCRtpEncodingParameters because all fields are
370 // optional, it is still invalid to be missing a rid when there are multiple
371 // encodings. Only trigger one kind of error here.
372 encodings.push({ rid: "foo" });
Soares Chen172fe9d2017-07-18 09:30:18373 assert_equals(param.encodings.length, 2);
374
Boris Zbarskyb7f2dd32020-02-04 21:26:48375 return promise_rejects_dom(t, 'InvalidModificationError',
Soares Chen172fe9d2017-07-18 09:30:18376 sender.setParameters(param));
Byron Campen45fa2f22022-12-14 01:52:59377 }, `sender.setParameters() with added encodings should reject with InvalidModificationError`);
Soares Chen172fe9d2017-07-18 09:30:18378
Henrik Boström36fb0332018-06-29 09:09:04379 promise_test(async t => {
Soares Chen172fe9d2017-07-18 09:30:18380 const pc = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53381 t.add_cleanup(() => pc.close());
Byron Campen45fa2f22022-12-14 01:52:59382 const { sender } = pc.addTransceiver('video', {sendEncodings: [{rid: "foo"}, {rid: "bar"}]});
Henrik Boström36fb0332018-06-29 09:09:04383
Soares Chen172fe9d2017-07-18 09:30:18384 const param = sender.getParameters();
Soares Chen172fe9d2017-07-18 09:30:18385
Byron Campen45fa2f22022-12-14 01:52:59386 const { encodings } = param;
387 assert_equals(encodings.length, 2);
388
389 encodings.pop();
390 assert_equals(param.encodings.length, 1);
391
392 return promise_rejects_dom(t, 'InvalidModificationError',
393 sender.setParameters(param));
394 }, `sender.setParameters() with removed encodings should reject with InvalidModificationError`);
395
396 promise_test(async t => {
397 const pc = new RTCPeerConnection();
398 t.add_cleanup(() => pc.close());
399 const { sender } = pc.addTransceiver('video', {sendEncodings: [{rid: "foo"}, {rid: "bar"}]});
400
401 const param = sender.getParameters();
402
403 const { encodings } = param;
404 assert_equals(encodings.length, 2);
405 encodings.push(encodings.shift());
406 assert_equals(param.encodings.length, 2);
407
408 return promise_rejects_dom(t, 'InvalidModificationError',
409 sender.setParameters(param));
410 }, `sender.setParameters() with reordered encodings should reject with InvalidModificationError`);
411
412 promise_test(async t => {
413 const pc = new RTCPeerConnection();
414 t.add_cleanup(() => pc.close());
415 const { sender } = pc.addTransceiver('video');
416
417 const param = sender.getParameters();
418
419 delete param.encodings;
Soares Chen172fe9d2017-07-18 09:30:18420
Boris Zbarskyab733fd2020-02-04 21:19:03421 return promise_rejects_js(t, TypeError,
Soares Chen172fe9d2017-07-18 09:30:18422 sender.setParameters(param));
Florent Castellica3d6282018-10-03 19:30:10423 }, `sender.setParameters() with encodings unset should reject with TypeError`);
Soares Chen172fe9d2017-07-18 09:30:18424
Henrik Boström36fb0332018-06-29 09:09:04425 promise_test(async t => {
Soares Chen172fe9d2017-07-18 09:30:18426 const pc = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53427 t.add_cleanup(() => pc.close());
Byron Campenffc4bd12023-02-11 00:18:05428 const { sender } = pc.addTransceiver('video');
429
430 const param = sender.getParameters();
431
432 param.encodings = [];
433
434 return promise_rejects_dom(t, 'InvalidModificationError',
435 sender.setParameters(param));
436 }, `sender.setParameters() with empty encodings should reject with InvalidModificationError (video)`);
437
438 promise_test(async t => {
439 const pc = new RTCPeerConnection();
440 t.add_cleanup(() => pc.close());
441 const { sender } = pc.addTransceiver('audio');
442
443 const param = sender.getParameters();
444
445 param.encodings = [];
446
447 return promise_rejects_dom(t, 'InvalidModificationError',
448 sender.setParameters(param));
449 }, `sender.setParameters() with empty encodings should reject with InvalidModificationError (audio)`);
450
451 promise_test(async t => {
452 const pc = new RTCPeerConnection();
453 t.add_cleanup(() => pc.close());
Amit Hilbuch8fb93e82019-03-04 17:56:57454 const { sender } = pc.addTransceiver('video', {
455 sendEncodings: [{ rid: 'foo' }, { rid: 'baz' }],
Soares Chen172fe9d2017-07-18 09:30:18456 });
Soares Chen172fe9d2017-07-18 09:30:18457
458 const param = sender.getParameters();
Byron Campen45fa2f22022-12-14 01:52:59459 const encoding = param.encodings[0];
Soares Chen172fe9d2017-07-18 09:30:18460
461 assert_equals(encoding.rid, 'foo');
462
463 encoding.rid = 'bar';
Boris Zbarskyb7f2dd32020-02-04 21:26:48464 return promise_rejects_dom(t, 'InvalidModificationError',
Soares Chen172fe9d2017-07-18 09:30:18465 sender.setParameters(param));
Soares Chen172fe9d2017-07-18 09:30:18466 }, `setParameters() with modified encoding.rid field should reject with InvalidModificationError`);
467
468 /*
469 5.2. setParameters
470 8. If the scaleResolutionDownBy parameter in the parameters argument has a
471 value less than 1.0, abort these steps and return a promise rejected with
472 a newly created RangeError.
473 */
Henrik Boström36fb0332018-06-29 09:09:04474 promise_test(async t => {
Soares Chen172fe9d2017-07-18 09:30:18475 const pc = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53476 t.add_cleanup(() => pc.close());
Byron Campen45fa2f22022-12-14 01:52:59477 const { sender } = pc.addTransceiver('video');
Soares Chen172fe9d2017-07-18 09:30:18478
479 const param = sender.getParameters();
Byron Campen45fa2f22022-12-14 01:52:59480 const encoding = param.encodings[0];
Soares Chen172fe9d2017-07-18 09:30:18481
482 encoding.scaleResolutionDownBy = 0.5;
Byron Campen45fa2f22022-12-14 01:52:59483 await promise_rejects_js(t, RangeError, sender.setParameters(param));
484 encoding.scaleResolutionDownBy = 0;
485 await promise_rejects_js(t, RangeError, sender.setParameters(param));
486 encoding.scaleResolutionDownBy = -1;
487 await promise_rejects_js(t, RangeError, sender.setParameters(param));
Soares Chen172fe9d2017-07-18 09:30:18488 }, `setParameters() with encoding.scaleResolutionDownBy field set to less than 1.0 should reject with RangeError`);
489
Henrik Boström36fb0332018-06-29 09:09:04490 promise_test(async t => {
Soares Chen172fe9d2017-07-18 09:30:18491 const pc = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53492 t.add_cleanup(() => pc.close());
Florent Castelliea0c6132020-01-16 16:33:29493 const { sender } = pc.addTransceiver('video');
Byron Campen45fa2f22022-12-14 01:52:59494
495 let param = sender.getParameters();
496 const encoding = param.encodings[0];
497
498 delete encoding.scaleResolutionDownBy;
499 await sender.setParameters(param);
500 param = sender.getParameters();
501 assert_equals(param.encodings[0].scaleResolutionDownBy, 1.0);
502 }, `setParameters() with missing encoding.scaleResolutionDownBy field should succeed, and set the value back to 1`);
503
504 promise_test(async t => {
505 const pc = new RTCPeerConnection();
506 t.add_cleanup(() => pc.close());
507 const { sender } = pc.addTransceiver('video');
Soares Chen172fe9d2017-07-18 09:30:18508
509 const param = sender.getParameters();
Byron Campen45fa2f22022-12-14 01:52:59510 const encoding = param.encodings[0];
Soares Chen172fe9d2017-07-18 09:30:18511
512 encoding.scaleResolutionDownBy = 1.5;
513 return sender.setParameters(param)
514 .then(() => {
515 const param = sender.getParameters();
Byron Campen45fa2f22022-12-14 01:52:59516 const encoding = param.encodings[0];
Soares Chen172fe9d2017-07-18 09:30:18517
518 assert_approx_equals(encoding.scaleResolutionDownBy, 1.5, 0.01);
519 });
Soares Chen172fe9d2017-07-18 09:30:18520 }, `setParameters() with encoding.scaleResolutionDownBy field set to greater than 1.0 should succeed`);
521
Byron Campen45fa2f22022-12-14 01:52:59522 test_modified_encoding('video', 'active', false, true,
523 'setParameters() with encoding.active false->true should succeed (video)');
524
525 test_modified_encoding('video', 'active', true, false,
526 'setParameters() with encoding.active true->false should succeed (video)');
527
528 test_modified_encoding('video', 'maxBitrate', 10000, 20000,
529 'setParameters() with modified encoding.maxBitrate should succeed (video)');
530
Henrik Boström36fb0332018-06-29 09:09:04531 test_modified_encoding('audio', 'active', false, true,
Byron Campen45fa2f22022-12-14 01:52:59532 'setParameters() with encoding.active false->true should succeed (audio)');
533
534 test_modified_encoding('audio', 'active', true, false,
535 'setParameters() with encoding.active true->false should succeed (audio)');
Soares Chen172fe9d2017-07-18 09:30:18536
Henrik Boström36fb0332018-06-29 09:09:04537 test_modified_encoding('audio', 'maxBitrate', 10000, 20000,
Byron Campen45fa2f22022-12-14 01:52:59538 'setParameters() with modified encoding.maxBitrate should succeed (audio)');
Soares Chen172fe9d2017-07-18 09:30:18539
Florent Castelliea0c6132020-01-16 16:33:29540 test_modified_encoding('video', 'scaleResolutionDownBy', 2, 4,
541 'setParameters() with modified encoding.scaleResolutionDownBy should succeed');
542
Soares Chen172fe9d2017-07-18 09:30:18543</script>