blob: 5fc1401badf49d6fbc2f46c9936b3711cd3c2466 [file] [log] [blame]
Florent Castelli9f783ba2023-05-16 13:09:151<!DOCTYPE html>
2<meta charset="utf-8">
3<title>RTCRtpEncodingParameters codec property</title>
Philipp Hanckeeeb00b02024-02-12 10:56:414<meta name="timeout" content="long">
Florent Castelli9f783ba2023-05-16 13:09:155<script src="/resources/testharness.js"></script>
6<script src="/resources/testharnessreport.js"></script>
7<script src="../webrtc/RTCPeerConnection-helper.js"></script>
8<script src="../webrtc/third_party/sdp/sdp.js"></script>
9<script src="../webrtc/simulcast/simulcast.js"></script>
10<script>
11 'use strict';
12
Blink WPT Bot396bc8e2023-09-01 20:33:4613 function arrayEquals(a, b) {
14 return Array.isArray(a) && Array.isArray(b) &&
15 a.length === b.length &&
16 a.every((val, i) => val === b[i]);
17 }
18
19 async function sleep(timeout) {
20 return new Promise(resolve => {
21 step_timeout(() => {
22 resolve();
23 }, timeout);
24 });
25 }
26
Florent Castelli9f783ba2023-05-16 13:09:1527 function findFirstCodec(name) {
Philipp Hanckeeeb00b02024-02-12 10:56:4128 return RTCRtpReceiver.getCapabilities(name.split('/')[0]).codecs.filter(c => c.mimeType.localeCompare(name, undefined, { sensitivity: 'base' }) === 0)[0];
Florent Castelli9f783ba2023-05-16 13:09:1529 }
30
31 function codecsNotMatching(mimeType) {
Philipp Hanckeeeb00b02024-02-12 10:56:4132 return RTCRtpReceiver.getCapabilities(mimeType.split('/')[0]).codecs.filter(c => c.mimeType.localeCompare(mimeType, undefined, {sensitivity: 'base'}) !== 0);
Florent Castelli9f783ba2023-05-16 13:09:1533 }
34
35 function assertCodecEquals(a, b) {
36 assert_equals(a.mimeType, b.mimeType);
37 assert_equals(a.clockRate, b.clockRate);
38 assert_equals(a.channels, b.channels);
39 assert_equals(a.sdpFmtpLine, b.sdpFmtpLine);
40 }
41
42 async function codecsForSender(sender) {
43 const rids = sender.getParameters().encodings.map(e => e.rid);
44 const stats = await sender.getStats();
45 const codecs = [...stats]
46 .filter(([k, v]) => v.type === 'outbound-rtp')
47 .sort(([k, v], [k2, v2]) => rids.indexOf(v.rid) - rids.indexOf(v2.rid))
48 .map(([k, v]) => stats.get(v.codecId).mimeType);
49 return codecs;
50 }
51
Blink WPT Bot396bc8e2023-09-01 20:33:4652 async function waitForAllLayers(t, sender) {
53 const encodings_count = sender.getParameters().encodings.length;
54 return step_wait_async(t, async () => {
55 const stats = await sender.getStats();
56 return [...stats]
57 .filter(([k, v]) => v.type === 'outbound-rtp').length == encodings_count;
58 }, `Wait for ${encodings_count} layers to start`);
59 }
60
61 function step_wait_async(t, cond, description, timeout=3000, interval=100) {
62 return new Promise(resolve => {
63 var timeout_full = timeout * t.timeout_multiplier;
64 var remaining = Math.ceil(timeout_full / interval);
65
66 var wait_for_inner = t.step_func(async () => {
67 if (await cond()) {
68 resolve();
69 } else {
70 if(remaining === 0) {
71 assert(false, "step_wait_async", description,
72 "Timed out waiting on condition");
73 }
74 remaining--;
75 await sleep(interval);
76 wait_for_inner();
77 }
78 });
79
80 wait_for_inner();
81 });
82 }
83
Florent Castelli9f783ba2023-05-16 13:09:1584 promise_test(async t => {
85 const pc = new RTCPeerConnection();
86 t.add_cleanup(() => pc.close());
87
88 const { sender } = pc.addTransceiver('audio');
89
90 let param = sender.getParameters();
91 let encoding = param.encodings[0];
92
93 assert_equals(encoding.codec, undefined);
94 }, `Codec should be undefined by default on audio encodings`);
95
96 promise_test(async t => {
97 const pc = new RTCPeerConnection();
98 t.add_cleanup(() => pc.close());
99
100 const { sender } = pc.addTransceiver('video');
101
102 let param = sender.getParameters();
103 let encoding = param.encodings[0];
104
105 assert_equals(encoding.codec, undefined);
106 }, `Codec should be undefined by default on video encodings`);
107
108 promise_test(async t => {
109 const pc = new RTCPeerConnection();
110 t.add_cleanup(() => pc.close());
111
112 const opus = findFirstCodec('audio/opus');
113
114 const { sender } = pc.addTransceiver('audio', {
115 sendEncodings: [{codec: opus}],
116 });
117
118 let param = sender.getParameters();
119 let encoding = param.encodings[0];
120
121 assertCodecEquals(opus, encoding.codec);
122 }, `Creating an audio sender with addTransceiver and codec should work`);
123
124 promise_test(async t => {
125 const pc = new RTCPeerConnection();
126 t.add_cleanup(() => pc.close());
127
128 const vp8 = findFirstCodec('video/VP8');
129
130 const { sender } = pc.addTransceiver('video', {
131 sendEncodings: [{codec: vp8}],
132 });
133
134 let param = sender.getParameters();
135 let encoding = param.encodings[0];
136
137 assertCodecEquals(vp8, encoding.codec);
138 }, `Creating a video sender with addTransceiver and codec should work`);
139
140 promise_test(async t => {
141 const pc = new RTCPeerConnection();
142 t.add_cleanup(() => pc.close());
143
144 const opus = findFirstCodec('audio/opus');
145
146 const { sender } = pc.addTransceiver('audio');
147
148 let param = sender.getParameters();
149 let encoding = param.encodings[0];
150
151 encoding.codec = opus;
152 await sender.setParameters(param);
153 param = sender.getParameters();
154 encoding = param.encodings[0];
155
156 assertCodecEquals(opus, encoding.codec);
157
158 delete encoding.codec;
159 await sender.setParameters(param);
160 param = sender.getParameters();
161 encoding = param.encodings[0];
162
163 assert_equals(encoding.codec, undefined);
164 }, `Setting codec on an audio sender with setParameters should work`);
165
166 promise_test(async t => {
167 const pc = new RTCPeerConnection();
168 t.add_cleanup(() => pc.close());
169
170 const vp8 = findFirstCodec('video/VP8');
171
172 const { sender } = pc.addTransceiver('video');
173
174 let param = sender.getParameters();
175 let encoding = param.encodings[0];
176
177 encoding.codec = vp8;
178 await sender.setParameters(param);
179 param = sender.getParameters();
180 encoding = param.encodings[0];
181
182 assertCodecEquals(vp8, encoding.codec);
183
184 delete encoding.codec;
185 await sender.setParameters(param);
186 param = sender.getParameters();
187 encoding = param.encodings[0];
188
189 assert_equals(encoding.codec, undefined);
190 }, `Setting codec on a video sender with setParameters should work`);
191
192 promise_test(async t => {
193 const pc = new RTCPeerConnection();
194 t.add_cleanup(() => pc.close());
195
196 const newCodec = {
197 mimeType: "audio/newCodec",
198 clockRate: 90000,
199 channel: 2,
200 };
201
Blink WPT Bot396bc8e2023-09-01 20:33:46202 assert_throws_dom('OperationError', () => pc.addTransceiver('audio', {
Florent Castelli9f783ba2023-05-16 13:09:15203 sendEncodings: [{codec: newCodec}],
204 }));
205 }, `Creating an audio sender with addTransceiver and non-existing codec should throw OperationError`);
206
207 promise_test(async t => {
208 const pc = new RTCPeerConnection();
209 t.add_cleanup(() => pc.close());
210
211 const newCodec = {
Blink WPT Bot396bc8e2023-09-01 20:33:46212 mimeType: "dummy/newCodec",
213 clockRate: 90000,
214 channel: 2,
215 };
216
217 assert_throws_dom('OperationError', () => pc.addTransceiver('audio', {
218 sendEncodings: [{codec: newCodec}],
219 }));
220 }, `Creating an audio sender with addTransceiver and non-existing codec type should throw OperationError`);
221
222 promise_test(async t => {
223 const pc = new RTCPeerConnection();
224 t.add_cleanup(() => pc.close());
225
226 const newCodec = {
Florent Castelli9f783ba2023-05-16 13:09:15227 mimeType: "video/newCodec",
228 clockRate: 90000,
229 };
230
231 assert_throws_dom('OperationError', () => pc.addTransceiver('video', {
232 sendEncodings: [{codec: newCodec}],
233 }));
234 }, `Creating a video sender with addTransceiver and non-existing codec should throw OperationError`);
235
236 promise_test(async t => {
237 const pc = new RTCPeerConnection();
238 t.add_cleanup(() => pc.close());
239
240 const newCodec = {
Blink WPT Bot396bc8e2023-09-01 20:33:46241 mimeType: "dummy/newCodec",
242 clockRate: 90000,
243 };
244
245 assert_throws_dom('OperationError', () => pc.addTransceiver('video', {
246 sendEncodings: [{codec: newCodec}],
247 }));
248 }, `Creating a video sender with addTransceiver and non-existing codec type should throw OperationError`);
249
250 promise_test(async t => {
251 const pc = new RTCPeerConnection();
252 t.add_cleanup(() => pc.close());
253
254 const newCodec = {
Florent Castelli9f783ba2023-05-16 13:09:15255 mimeType: "audio/newCodec",
256 clockRate: 90000,
257 channel: 2,
258 };
259
260 const { sender } = pc.addTransceiver('audio');
261
262 let param = sender.getParameters();
263 let encoding = param.encodings[0];
264
265 encoding.codec = newCodec;
266 await promise_rejects_dom(t, "InvalidModificationError", sender.setParameters(param));
267 }, `Setting a non-existing codec on an audio sender with setParameters should throw InvalidModificationError`);
268
269 promise_test(async t => {
270 const pc = new RTCPeerConnection();
271 t.add_cleanup(() => pc.close());
272
273 const newCodec = {
274 mimeType: "video/newCodec",
275 clockRate: 90000,
276 };
277
278 const { sender } = pc.addTransceiver('video');
279
280 let param = sender.getParameters();
281 let encoding = param.encodings[0];
282
283 encoding.codec = newCodec;
284 await promise_rejects_dom(t, "InvalidModificationError", sender.setParameters(param));
285 }, `Setting a non-existing codec on a video sender with setParameters should throw InvalidModificationError`);
286
287 promise_test(async t => {
Philipp Hanckeeeb00b02024-02-12 10:56:41288 const pc1 = new RTCPeerConnection();
289 t.add_cleanup(() => pc1.close());
290 const pc2 = new RTCPeerConnection();
291 t.add_cleanup(() => pc2.close());
Florent Castelli9f783ba2023-05-16 13:09:15292
293 const opus = findFirstCodec('audio/opus');
294 const nonOpus = codecsNotMatching(opus.mimeType);
Philipp Hanckeeeb00b02024-02-12 10:56:41295 pc2.ontrack = e => {
296 e.transceiver.setCodecPreferences(nonOpus);
297 };
Florent Castelli9f783ba2023-05-16 13:09:15298
Philipp Hanckeeeb00b02024-02-12 10:56:41299 const transceiver = pc1.addTransceiver('audio');
300 exchangeIceCandidates(pc1, pc2);
301 await exchangeOfferAnswer(pc1, pc2);
302
Florent Castelli9f783ba2023-05-16 13:09:15303 const sender = transceiver.sender;
Florent Castelli9f783ba2023-05-16 13:09:15304 let param = sender.getParameters();
305 let encoding = param.encodings[0];
306
307 encoding.codec = opus;
308 await promise_rejects_dom(t, "InvalidModificationError", sender.setParameters(param));
309 }, `Setting a non-preferred codec on an audio sender with setParameters should throw InvalidModificationError`);
310
311 promise_test(async t => {
Philipp Hanckeeeb00b02024-02-12 10:56:41312 const pc1 = new RTCPeerConnection();
313 t.add_cleanup(() => pc1.close());
314 const pc2 = new RTCPeerConnection();
315 t.add_cleanup(() => pc2.close());
Florent Castelli9f783ba2023-05-16 13:09:15316
317 const vp8 = findFirstCodec('video/VP8');
318 const nonVP8 = codecsNotMatching(vp8.mimeType);
Philipp Hanckeeeb00b02024-02-12 10:56:41319 pc2.ontrack = e => {
320 e.transceiver.setCodecPreferences(nonVP8);
321 };
Florent Castelli9f783ba2023-05-16 13:09:15322
Philipp Hanckeeeb00b02024-02-12 10:56:41323 const transceiver = pc1.addTransceiver('video');
324 exchangeIceCandidates(pc1, pc2);
325 await exchangeOfferAnswer(pc1, pc2);
326
Florent Castelli9f783ba2023-05-16 13:09:15327 const sender = transceiver.sender;
Florent Castelli9f783ba2023-05-16 13:09:15328 let param = sender.getParameters();
329 let encoding = param.encodings[0];
330
331 encoding.codec = vp8;
332 await promise_rejects_dom(t, "InvalidModificationError", sender.setParameters(param));
333 }, `Setting a non-preferred codec on a video sender with setParameters should throw InvalidModificationError`);
334
335 promise_test(async (t) => {
336 const pc1 = new RTCPeerConnection();
337 const pc2 = new RTCPeerConnection();
338 t.add_cleanup(() => pc1.close());
339 t.add_cleanup(() => pc2.close());
340
341 const opus = findFirstCodec('audio/opus');
342 const nonOpus = codecsNotMatching(opus.mimeType);
Philipp Hanckeeeb00b02024-02-12 10:56:41343 pc2.ontrack = e => {
344 e.transceiver.setCodecPreferences(nonOpus);
345 };
Florent Castelli9f783ba2023-05-16 13:09:15346
347 const transceiver = pc1.addTransceiver('audio');
Florent Castelli9f783ba2023-05-16 13:09:15348
349 exchangeIceCandidates(pc1, pc2);
350 await exchangeOfferAnswer(pc1, pc2);
351
Philipp Hanckeeeb00b02024-02-12 10:56:41352 const sender = transceiver.sender;
Florent Castelli9f783ba2023-05-16 13:09:15353 let param = sender.getParameters();
354 let encoding = param.encodings[0];
355
356 encoding.codec = opus;
357 await promise_rejects_dom(t, "InvalidModificationError", sender.setParameters(param));
358 }, `Setting a non-negotiated codec on an audio sender with setParameters should throw InvalidModificationError`);
359
360 promise_test(async (t) => {
361 const pc1 = new RTCPeerConnection();
362 const pc2 = new RTCPeerConnection();
363 t.add_cleanup(() => pc1.close());
364 t.add_cleanup(() => pc2.close());
365
366 const vp8 = findFirstCodec('video/VP8');
367 const nonVP8 = codecsNotMatching(vp8.mimeType);
Philipp Hanckeeeb00b02024-02-12 10:56:41368 pc2.ontrack = e => {
369 e.transceiver.setCodecPreferences(nonVP8);
370 };
Florent Castelli9f783ba2023-05-16 13:09:15371
372 const transceiver = pc1.addTransceiver('video');
Florent Castelli9f783ba2023-05-16 13:09:15373 exchangeIceCandidates(pc1, pc2);
374 await exchangeOfferAnswer(pc1, pc2);
375
Philipp Hanckeeeb00b02024-02-12 10:56:41376 const sender = transceiver.sender;
Florent Castelli9f783ba2023-05-16 13:09:15377 let param = sender.getParameters();
378 let encoding = param.encodings[0];
379
380 encoding.codec = vp8;
381 await promise_rejects_dom(t, "InvalidModificationError", sender.setParameters(param));
382 }, `Setting a non-negotiated codec on a video sender with setParameters should throw InvalidModificationError`);
383
384 promise_test(async (t) => {
385 const pc1 = new RTCPeerConnection();
386 const pc2 = new RTCPeerConnection();
387 t.add_cleanup(() => pc1.close());
388 t.add_cleanup(() => pc2.close());
389
390 const opus = findFirstCodec('audio/opus');
391 const nonOpus = codecsNotMatching(opus.mimeType);
392
393 const transceiver = pc1.addTransceiver('audio', {
394 sendEncodings: [{codec: opus}],
395 });
396 const sender = transceiver.sender;
397
398 exchangeIceCandidates(pc1, pc2);
399 await exchangeOfferAnswer(pc1, pc2);
400
401 let param = sender.getParameters();
402 let encoding = param.encodings[0];
403
404 assertCodecEquals(opus, encoding.codec);
405
Philipp Hanckeeeb00b02024-02-12 10:56:41406 pc2.getTransceivers()[0].setCodecPreferences(nonOpus);
Florent Castelli9f783ba2023-05-16 13:09:15407 await exchangeOfferAnswer(pc1, pc2);
408
409 param = sender.getParameters();
410 encoding = param.encodings[0];
411
412 assert_equals(encoding.codec, undefined);
413 }, `Codec should be undefined after negotiating away the currently set codec on an audio sender`);
Florent Castelli9f783ba2023-05-16 13:09:15414 promise_test(async (t) => {
415 const pc1 = new RTCPeerConnection();
416 const pc2 = new RTCPeerConnection();
417 t.add_cleanup(() => pc1.close());
418 t.add_cleanup(() => pc2.close());
419
420 const vp8 = findFirstCodec('video/VP8');
421 const nonVP8 = codecsNotMatching(vp8.mimeType);
422
423 const transceiver = pc1.addTransceiver('video', {
424 sendEncodings: [{codec: vp8}],
425 });
426 const sender = transceiver.sender;
427
428 exchangeIceCandidates(pc1, pc2);
429 await exchangeOfferAnswer(pc1, pc2);
430
431 let param = sender.getParameters();
432 let encoding = param.encodings[0];
433
434 assertCodecEquals(vp8, encoding.codec);
435
Philipp Hanckeeeb00b02024-02-12 10:56:41436 pc2.getTransceivers()[0].setCodecPreferences(nonVP8);
Florent Castelli9f783ba2023-05-16 13:09:15437 await exchangeOfferAnswer(pc1, pc2);
438
439 param = sender.getParameters();
440 encoding = param.encodings[0];
441
442 assert_equals(encoding.codec, undefined);
443 }, `Codec should be undefined after negotiating away the currently set codec on a video sender`);
444
445 promise_test(async (t) => {
446 const pc1 = new RTCPeerConnection();
447 const pc2 = new RTCPeerConnection();
448 t.add_cleanup(() => pc1.close());
449 t.add_cleanup(() => pc2.close());
450 const stream = await getNoiseStream({audio:true});
451 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
452
453 const opus = findFirstCodec('audio/opus');
454 const nonOpus = codecsNotMatching(opus.mimeType);
Philipp Hanckeeeb00b02024-02-12 10:56:41455 pc2.ontrack = e => {
456 e.transceiver.setCodecPreferences(nonOpus.concat([opus]));
457 };
Florent Castelli9f783ba2023-05-16 13:09:15458
459 const transceiver = pc1.addTransceiver(stream.getTracks()[0]);
460 const sender = transceiver.sender;
461
Florent Castelli9f783ba2023-05-16 13:09:15462 exchangeIceCandidates(pc1, pc2);
463 await exchangeOfferAnswer(pc1, pc2);
464
465 let codecs = await codecsForSender(sender);
466 assert_not_equals(codecs[0], opus.mimeType);
467
468 let param = sender.getParameters();
469 let encoding = param.encodings[0];
470 encoding.codec = opus;
471
472 await sender.setParameters(param);
473
Blink WPT Bot396bc8e2023-09-01 20:33:46474 await step_wait_async(t, async () => {
475 let old_codecs = codecs;
476 codecs = await codecsForSender(sender);
477 return !arrayEquals(codecs, old_codecs);
478 }, 'Waiting for current codecs to change', 5000, 200);
479
Florent Castelli9f783ba2023-05-16 13:09:15480 assert_array_equals(codecs, [opus.mimeType]);
481 }, `Stats output-rtp should match the selected codec in non-simulcast usecase on an audio sender`);
482
483 promise_test(async (t) => {
484 const pc1 = new RTCPeerConnection();
485 const pc2 = new RTCPeerConnection();
486 t.add_cleanup(() => pc1.close());
487 t.add_cleanup(() => pc2.close());
488 const stream = await getNoiseStream({video:true});
489 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
490
491 const vp8 = findFirstCodec('video/VP8');
492 const nonVP8 = codecsNotMatching(vp8.mimeType);
Philipp Hanckeeeb00b02024-02-12 10:56:41493 pc2.ontrack = e => {
494 e.transceiver.setCodecPreferences(nonVP8.concat([vp8]));
495 };
Florent Castelli9f783ba2023-05-16 13:09:15496
497 const transceiver = pc1.addTransceiver(stream.getTracks()[0]);
498 const sender = transceiver.sender;
499
Florent Castelli9f783ba2023-05-16 13:09:15500 exchangeIceCandidates(pc1, pc2);
501 await exchangeOfferAnswer(pc1, pc2);
502
503 let codecs = await codecsForSender(sender);
504 assert_not_equals(codecs[0], vp8.mimeType);
505
506 let param = sender.getParameters();
507 let encoding = param.encodings[0];
508 encoding.codec = vp8;
509
510 await sender.setParameters(param);
511
Blink WPT Bot396bc8e2023-09-01 20:33:46512 await step_wait_async(t, async () => {
513 let old_codecs = codecs;
514 codecs = await codecsForSender(sender);
515 return !arrayEquals(codecs, old_codecs);
516 }, 'Waiting for current codecs to change', 5000, 200);
517
Florent Castelli9f783ba2023-05-16 13:09:15518 assert_array_equals(codecs, [vp8.mimeType]);
519 }, `Stats output-rtp should match the selected codec in non-simulcast usecase on a video sender`);
Blink WPT Bot396bc8e2023-09-01 20:33:46520
521 promise_test(async (t) => {
522 const pc1 = new RTCPeerConnection();
523 const pc2 = new RTCPeerConnection();
524 t.add_cleanup(() => pc1.close());
525 t.add_cleanup(() => pc2.close());
526 const stream = await getNoiseStream({video:true});
527 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
528
529 const vp8 = findFirstCodec('video/VP8');
Philipp Hanckeeeb00b02024-02-12 10:56:41530 const h264 = findFirstCodec('video/H264');
531 pc2.ontrack = e => {
532 e.transceiver.setCodecPreferences([h264, vp8]);
533 };
Blink WPT Bot396bc8e2023-09-01 20:33:46534 const transceiver = pc1.addTransceiver(stream.getTracks()[0], {
535 sendEncodings: [{rid: '0'}, {rid: '1'}, {rid: '2'}],
536 });
537 const sender = transceiver.sender;
538
Blink WPT Bot396bc8e2023-09-01 20:33:46539 exchangeIceCandidates(pc1, pc2);
540 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ['0', '1', '2']);
541
542 await waitForAllLayers(t, sender);
543
544 let codecs = await codecsForSender(sender);
545 assert_not_equals(codecs[0], vp8.mimeType);
546 assert_not_equals(codecs[1], vp8.mimeType);
547 assert_not_equals(codecs[2], vp8.mimeType);
548
549 let param = sender.getParameters();
550 param.encodings[0].codec = vp8;
551 param.encodings[1].codec = vp8;
552 param.encodings[2].codec = vp8;
553
554 await sender.setParameters(param);
555
556 // Waiting for 10s as ramp-up time can be slow in the runners.
557 await step_wait_async(t, async () => {
558 let old_codecs = codecs;
559 codecs = await codecsForSender(sender);
560 return !arrayEquals(codecs, old_codecs);
561 }, 'Waiting for current codecs to change', 10000, 200);
562
563 assert_array_equals(codecs, [vp8.mimeType, vp8.mimeType, vp8.mimeType]);
564 }, `Stats output-rtp should match the selected codec in simulcast usecase on a video sender`);
565
566 promise_test(async (t) => {
567 const pc1 = new RTCPeerConnection();
568 const pc2 = new RTCPeerConnection();
569 t.add_cleanup(() => pc1.close());
570 t.add_cleanup(() => pc2.close());
571 const stream = await getNoiseStream({video:true});
572 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
573
574 const vp8 = findFirstCodec('video/VP8');
Philipp Hanckeeeb00b02024-02-12 10:56:41575 const h264 = findFirstCodec('video/H264');
576 pc2.ontrack = e => {
577 e.transceiver.setCodecPreferences([h264, vp8]);
578 };
Blink WPT Bot396bc8e2023-09-01 20:33:46579
580 const transceiver = pc1.addTransceiver(stream.getTracks()[0], {
581 sendEncodings: [{rid: '0'}, {rid: '1'}, {rid: '2'}],
582 });
583 const sender = transceiver.sender;
584
Blink WPT Bot396bc8e2023-09-01 20:33:46585 exchangeIceCandidates(pc1, pc2);
586 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ['0', '1', '2']);
587
588 await waitForAllLayers(t, sender);
589
590 let codecs = await codecsForSender(sender);
591 assert_not_equals(codecs[0], vp8.mimeType);
592 assert_not_equals(codecs[1], vp8.mimeType);
593 assert_not_equals(codecs[2], vp8.mimeType);
594
595 let param = sender.getParameters();
596 param.encodings[1].codec = vp8;
597
598 await sender.setParameters(param);
599
600 await step_wait_async(t, async () => {
601 let old_codecs = codecs;
602 codecs = await codecsForSender(sender);
603 return !arrayEquals(codecs, old_codecs);
604 }, 'Waiting for current codecs to change', 5000, 200);
605
606 assert_not_equals(codecs[0], vp8.mimeType);
607 assert_equals(codecs[1], vp8.mimeType);
608 assert_not_equals(codecs[2], vp8.mimeType);
609 }, `Stats output-rtp should match the selected mixed codecs in simulcast usecase on a video sender`);
610
Florent Castelli9f783ba2023-05-16 13:09:15611</script>