negotiation-encodings.https.html (22277B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <title>RTCPeerConnection Simulcast Tests - negotiation/encodings</title> 4 <meta name="timeout" content="long"> 5 <script src="../third_party/sdp/sdp.js"></script> 6 <script src="simulcast.js"></script> 7 <script src="../RTCPeerConnection-helper.js"></script> 8 <script src="/resources/testharness.js"></script> 9 <script src="/resources/testharnessreport.js"></script> 10 <script src="/resources/testdriver.js"></script> 11 <script src="/resources/testdriver-vendor.js"></script> 12 <script src="../../mediacapture-streams/permission-helper.js"></script> 13 <script> 14 15 promise_test(async t => { 16 const pc1 = new RTCPeerConnection(); 17 t.add_cleanup(() => pc1.close()); 18 const pc2 = new RTCPeerConnection(); 19 t.add_cleanup(() => pc2.close()); 20 21 const stream = await getNoiseStream({video: true}); 22 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); 23 const sender = pc1.addTrack(stream.getTracks()[0]); 24 // pc1 is unicast right now 25 pc2.addTrack(stream.getTracks()[0]); 26 27 await doOfferToRecvSimulcastAndAnswer(pc2, pc1, ["foo", "bar"]); 28 assert_equals(pc1.getTransceivers().length, 1); 29 const {encodings} = sender.getParameters(); 30 const rids = encodings.map(({rid}) => rid); 31 assert_array_equals(rids, ["foo", "bar"]); 32 }, 'addTrack, then sRD(simulcast recv offer) results in simulcast'); 33 34 promise_test(async t => { 35 const pc1 = new RTCPeerConnection(); 36 t.add_cleanup(() => pc1.close()); 37 const pc2 = new RTCPeerConnection(); 38 t.add_cleanup(() => pc2.close()); 39 40 const stream = await getNoiseStream({audio: true}); 41 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); 42 const sender = pc1.addTrack(stream.getTracks()[0]); 43 // pc1 is unicast right now 44 pc2.addTrack(stream.getTracks()[0]); 45 46 await doOfferToRecvSimulcastAndAnswer(pc2, pc1, ["foo", "bar"]); 47 assert_equals(pc1.getTransceivers().length, 1); 48 const {encodings} = sender.getParameters(); 49 const rids = encodings.map(({rid}) => rid); 50 assert_array_equals(rids, [undefined]); 51 }, 'simulcast is not supported for audio'); 52 53 // We do not have a test case for sRD(offer) narrowing a simulcast envelope 54 // from addTransceiver, since that transceiver cannot be paired up with a remote 55 // offer m-section 56 promise_test(async t => { 57 const pc1 = new RTCPeerConnection(); 58 t.add_cleanup(() => pc1.close()); 59 const pc2 = new RTCPeerConnection(); 60 t.add_cleanup(() => pc2.close()); 61 62 const {sender} = pc1.addTransceiver("video", {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 63 let {encodings} = sender.getParameters(); 64 65 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo"]); 66 67 assert_equals(pc1.getTransceivers().length, 1); 68 encodings = sender.getParameters().encodings; 69 const rids = encodings.map(({rid}) => rid); 70 assert_array_equals(rids, ["foo"]); 71 const scaleDownByValues = encodings.map(({scaleResolutionDownBy}) => scaleResolutionDownBy); 72 assert_array_equals(scaleDownByValues, [2]); 73 }, 'sRD(recv simulcast answer) can narrow the simulcast envelope specified by addTransceiver'); 74 75 promise_test(async t => { 76 const pc1 = new RTCPeerConnection(); 77 t.add_cleanup(() => pc1.close()); 78 const pc2 = new RTCPeerConnection(); 79 t.add_cleanup(() => pc2.close()); 80 81 const {sender} = pc1.addTransceiver("video", {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 82 let {encodings} = sender.getParameters(); 83 84 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 85 86 assert_equals(pc1.getTransceivers().length, 1); 87 encodings = sender.getParameters().encodings; 88 let rids = encodings.map(({rid}) => rid); 89 assert_array_equals(rids, ["foo", "bar"]); 90 91 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo"]); 92 93 assert_equals(pc1.getTransceivers().length, 1); 94 encodings = sender.getParameters().encodings; 95 rids = encodings.map(({rid}) => rid); 96 assert_array_equals(rids, ["foo"]); 97 const scaleDownByValues = encodings.map(({scaleResolutionDownBy}) => scaleResolutionDownBy); 98 assert_array_equals(scaleDownByValues, [2]); 99 }, 'sRD(recv simulcast answer) can narrow the simulcast envelope from a previous negotiation'); 100 101 promise_test(async t => { 102 const pc1 = new RTCPeerConnection(); 103 t.add_cleanup(() => pc1.close()); 104 const pc2 = new RTCPeerConnection(); 105 t.add_cleanup(() => pc2.close()); 106 107 const {sender} = pc1.addTransceiver("video", {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 108 let {encodings} = sender.getParameters(); 109 110 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 111 112 assert_equals(pc1.getTransceivers().length, 1); 113 encodings = sender.getParameters().encodings; 114 let rids = encodings.map(({rid}) => rid); 115 assert_array_equals(rids, ["foo", "bar"]); 116 117 // doAnswerToSendSimulcast causes pc2 to barf unless we set the direction to 118 // sendrecv 119 pc2.getTransceivers()[0].direction = "sendrecv"; 120 pc2.getTransceivers()[1].direction = "sendrecv"; 121 122 await doOfferToRecvSimulcast(pc2, pc1, ["foo"]); 123 assert_equals(pc1.getTransceivers().length, 1); 124 encodings = sender.getParameters().encodings; 125 rids = encodings.map(({rid}) => rid); 126 assert_array_equals(rids, ["foo", "bar"], "[[SendEncodings]] is not updated in have-remote-offer for reoffers"); 127 128 await doAnswerToSendSimulcast(pc2, pc1); 129 130 assert_equals(pc1.getTransceivers().length, 1); 131 encodings = sender.getParameters().encodings; 132 rids = encodings.map(({rid}) => rid); 133 assert_array_equals(rids, ["foo"]); 134 const scaleDownByValues = encodings.map(({scaleResolutionDownBy}) => scaleResolutionDownBy); 135 assert_array_equals(scaleDownByValues, [2]); 136 }, 'sRD(simulcast offer) can narrow the simulcast envelope from a previous negotiation'); 137 138 // https://github.com/w3c/webrtc-pc/issues/2780 139 promise_test(async t => { 140 const pc1 = new RTCPeerConnection(); 141 t.add_cleanup(() => pc1.close()); 142 const pc2 = new RTCPeerConnection(); 143 t.add_cleanup(() => pc2.close()); 144 145 const stream = await getNoiseStream({video: true}); 146 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); 147 const sender = pc1.addTrack(stream.getTracks()[0]); 148 pc2.addTrack(stream.getTracks()[0]); 149 150 await doOfferToRecvSimulcastAndAnswer(pc2, pc1, ["foo", "bar", "foo"]); 151 assert_equals(pc1.getTransceivers().length, 1); 152 let {encodings} = sender.getParameters(); 153 let rids = encodings.map(({rid}) => rid); 154 assert_array_equals(rids, ["foo", "bar"]); 155 assert_true(pc1.remoteDescription.sdp.includes("a=simulcast:recv foo;bar;foo"), "Duplicate rids should be present in offer"); 156 assert_false(pc1.localDescription.sdp.includes("a=simulcast:send foo;bar;foo"), "Duplicate rids should not be present in answer"); 157 assert_true(pc1.localDescription.sdp.includes("a=simulcast:send foo;bar"), "Answer should use the correct rids"); 158 assert_equals(pc1.getTransceivers().length, 1); 159 encodings = sender.getParameters().encodings; 160 rids = encodings.map(({rid}) => rid); 161 assert_array_equals(rids, ["foo", "bar"]); 162 }, 'Duplicate rids in sRD(offer) are ignored'); 163 164 // https://github.com/w3c/webrtc-pc/issues/2769 165 promise_test(async t => { 166 const pc1 = new RTCPeerConnection(); 167 t.add_cleanup(() => pc1.close()); 168 const pc2 = new RTCPeerConnection(); 169 t.add_cleanup(() => pc2.close()); 170 171 const stream = await getNoiseStream({video: true}); 172 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); 173 const sender = pc1.addTrack(stream.getTracks()[0]); 174 pc2.addTrack(stream.getTracks()[0]); 175 176 await doOfferToRecvSimulcastAndAnswer(pc2, pc1, ["foo,bar", "1,2"]); 177 assert_equals(pc1.getTransceivers().length, 1); 178 let {encodings} = sender.getParameters(); 179 let rids = encodings.map(({rid}) => rid); 180 assert_array_equals(rids, ["foo", "1"]); 181 assert_true(pc1.remoteDescription.sdp.includes("a=simulcast:recv foo,bar;1,2"), "Choices of rids should be present in offer"); 182 assert_true(pc1.localDescription.sdp.includes("a=simulcast:send foo;1\r\n"), "Choices of rids should not be present in answer"); 183 assert_equals(pc1.getTransceivers().length, 1); 184 encodings = sender.getParameters().encodings; 185 rids = encodings.map(({rid}) => rid); 186 assert_array_equals(rids, ["foo", "1"]); 187 }, 'Choices in rids in sRD(offer) are ignored'); 188 189 // https://github.com/w3c/webrtc-pc/issues/2764 190 promise_test(async t => { 191 const pc1 = new RTCPeerConnection(); 192 t.add_cleanup(() => pc1.close()); 193 const pc2 = new RTCPeerConnection(); 194 t.add_cleanup(() => pc2.close()); 195 196 const stream = await getNoiseStream({video: true}); 197 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); 198 const sender = pc1.addTrack(stream.getTracks()[0]); 199 pc2.addTrack(stream.getTracks()[0]); 200 201 await doOfferToRecvSimulcast(pc2, pc1, ["foo", "bar"]); 202 assert_equals(pc1.getTransceivers().length, 1); 203 let {encodings} = sender.getParameters(); 204 let rids = encodings.map(({rid}) => rid); 205 assert_array_equals(rids, ["foo", "bar"]); 206 207 await pc1.setRemoteDescription({sdp: "", type: "rollback"}); 208 209 assert_equals(pc1.getTransceivers().length, 1); 210 encodings = sender.getParameters().encodings; 211 rids = encodings.map(({rid}) => rid); 212 assert_array_equals(rids, [undefined]); 213 }, 'addTrack, then rollback of sRD(simulcast offer), brings us back to having a single encoding without a rid'); 214 215 promise_test(async t => { 216 const pc1 = new RTCPeerConnection(); 217 t.add_cleanup(() => pc1.close()); 218 const pc2 = new RTCPeerConnection(); 219 t.add_cleanup(() => pc2.close()); 220 221 const stream = await getNoiseStream({video: true}); 222 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); 223 pc2.addTrack(stream.getTracks()[0]); 224 await doOfferToRecvSimulcast(pc2, pc1, ["foo", "bar"]); 225 const sender = pc1.addTrack(stream.getTracks()[0]); 226 assert_equals(pc1.getTransceivers().length, 1); 227 228 assert_equals(pc1.getTransceivers().length, 1); 229 let {encodings} = sender.getParameters(); 230 let rids = encodings.map(({rid}) => rid); 231 assert_array_equals(rids, ["foo", "bar"]); 232 233 await pc1.setRemoteDescription({sdp: "", type: "rollback"}); 234 235 assert_equals(pc1.getTransceivers().length, 1); 236 encodings = sender.getParameters().encodings; 237 rids = encodings.map(({rid}) => rid); 238 assert_array_equals(rids, [undefined]); 239 }, 'sRD(simulcast offer), addTrack, then rollback brings us back to having a single encoding'); 240 241 promise_test(async t => { 242 const pc1 = new RTCPeerConnection(); 243 t.add_cleanup(() => pc1.close()); 244 const pc2 = new RTCPeerConnection(); 245 t.add_cleanup(() => pc2.close()); 246 247 const stream = await getNoiseStream({video: true}); 248 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); 249 const {sender} = pc1.addTransceiver(stream.getTracks()[0], {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 250 251 await doOfferToSendSimulcast(pc1, pc2); 252 await doAnswerToRecvSimulcast(pc1, pc2, ["bar", "foo"]); 253 assert_true(pc1.remoteDescription.sdp.includes("a=simulcast:recv bar;foo"), "Answer should have reordered rids"); 254 255 assert_equals(pc1.getTransceivers().length, 1); 256 const {encodings} = sender.getParameters(); 257 const rids = encodings.map(({rid}) => rid); 258 assert_array_equals(rids, ["foo", "bar"]); 259 }, 'Reordering of rids in sRD(answer) is ignored'); 260 261 promise_test(async t => { 262 const pc1 = new RTCPeerConnection(); 263 t.add_cleanup(() => pc1.close()); 264 const pc2 = new RTCPeerConnection(); 265 t.add_cleanup(() => pc2.close()); 266 267 const stream = await getNoiseStream({video: true}); 268 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); 269 const {sender} = pc1.addTransceiver(stream.getTracks()[0], {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 270 271 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 272 273 assert_equals(pc1.getTransceivers().length, 1); 274 let {encodings} = sender.getParameters(); 275 let rids = encodings.map(({rid}) => rid); 276 assert_array_equals(rids, ["foo", "bar"]); 277 278 await doOfferToSendSimulcast(pc1, pc2); 279 await doAnswerToRecvSimulcast(pc1, pc2, ["bar", "foo"]); 280 assert_true(pc1.remoteDescription.sdp.includes("a=simulcast:recv bar;foo"), "Answer should have reordered rids"); 281 282 assert_equals(pc1.getTransceivers().length, 1); 283 encodings = sender.getParameters().encodings; 284 rids = encodings.map(({rid}) => rid); 285 assert_array_equals(rids, ["foo", "bar"]); 286 }, 'Reordering of rids in sRD(reanswer) is ignored'); 287 288 promise_test(async t => { 289 const pc1 = new RTCPeerConnection(); 290 t.add_cleanup(() => pc1.close()); 291 const pc2 = new RTCPeerConnection(); 292 t.add_cleanup(() => pc2.close()); 293 294 const stream = await getNoiseStream({video: true}); 295 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); 296 const {sender} = pc1.addTransceiver(stream.getTracks()[0], {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 297 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 298 299 assert_equals(pc1.getTransceivers().length, 1); 300 let {encodings} = sender.getParameters(); 301 let rids = encodings.map(({rid}) => rid); 302 assert_array_equals(rids, ["foo", "bar"]); 303 304 // doAnswerToSendSimulcast causes pc2 to barf unless we set the direction to 305 // sendrecv 306 pc2.getTransceivers()[0].direction = "sendrecv"; 307 pc2.getTransceivers()[1].direction = "sendrecv"; 308 309 await doOfferToRecvSimulcast(pc2, pc1, ["bar", "foo"]); 310 await doAnswerToSendSimulcast(pc2, pc1); 311 assert_true(pc1.remoteDescription.sdp.includes("a=simulcast:recv bar;foo"), "Reoffer should have reordered rids"); 312 313 assert_equals(pc1.getTransceivers().length, 1); 314 encodings = sender.getParameters().encodings; 315 rids = encodings.map(({rid}) => rid); 316 assert_array_equals(rids, ["foo", "bar"]); 317 }, 'Reordering of rids in sRD(reoffer) is ignored'); 318 319 promise_test(async t => { 320 const pc1 = new RTCPeerConnection(); 321 t.add_cleanup(() => pc1.close()); 322 const pc2 = new RTCPeerConnection(); 323 t.add_cleanup(() => pc2.close()); 324 325 const stream = await getNoiseStream({video: true}); 326 t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); 327 const {sender} = pc1.addTransceiver(stream.getTracks()[0], {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 328 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 329 330 assert_equals(pc1.getTransceivers().length, 1); 331 let encodings = sender.getParameters().encodings; 332 let rids = encodings.map(({rid}) => rid); 333 assert_array_equals(rids, ["foo", "bar"]); 334 335 // doAnswerToSendSimulcast causes pc2 to barf unless we set the direction to 336 // sendrecv 337 pc2.getTransceivers()[0].direction = "sendrecv"; 338 pc2.getTransceivers()[1].direction = "sendrecv"; 339 340 // Keep the second encoding! 341 await doOfferToRecvSimulcast(pc2, pc1, ["bar"]); 342 assert_equals(pc1.getTransceivers().length, 1); 343 encodings = sender.getParameters().encodings; 344 rids = encodings.map(({rid}) => rid); 345 assert_array_equals(rids, ["foo", "bar"]); 346 347 await pc1.setRemoteDescription({sdp: "", type: "rollback"}); 348 349 encodings = sender.getParameters().encodings; 350 rids = encodings.map(({rid}) => rid); 351 assert_array_equals(rids, ["foo", "bar"]); 352 }, 'Rollback of sRD(reoffer) with a single rid results in all previous encodings'); 353 354 promise_test(async t => { 355 const pc1 = new RTCPeerConnection(); 356 t.add_cleanup(() => pc1.close()); 357 const pc2 = new RTCPeerConnection(); 358 t.add_cleanup(() => pc2.close()); 359 360 const {sender} = pc1.addTransceiver("video", {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 361 let {encodings} = sender.getParameters(); 362 363 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["bar"]); 364 365 assert_equals(pc1.getTransceivers().length, 1); 366 encodings = sender.getParameters().encodings; 367 const rids = encodings.map(({rid}) => rid); 368 assert_array_equals(rids, ["bar"]); 369 const scaleDownByValues = encodings.map(({scaleResolutionDownBy}) => scaleResolutionDownBy); 370 assert_array_equals(scaleDownByValues, [1]); 371 }, 'sRD(recv simulcast answer) can narrow the simulcast envelope specified by addTransceiver by removing the first encoding'); 372 373 promise_test(async t => { 374 const pc1 = new RTCPeerConnection(); 375 t.add_cleanup(() => pc1.close()); 376 const pc2 = new RTCPeerConnection(); 377 t.add_cleanup(() => pc2.close()); 378 379 const {sender} = pc1.addTransceiver("video", {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 380 let {encodings} = sender.getParameters(); 381 382 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 383 384 assert_equals(pc1.getTransceivers().length, 1); 385 encodings = sender.getParameters().encodings; 386 let rids = encodings.map(({rid}) => rid); 387 assert_array_equals(rids, ["foo", "bar"]); 388 389 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["bar"]); 390 391 assert_equals(pc1.getTransceivers().length, 1); 392 encodings = sender.getParameters().encodings; 393 rids = encodings.map(({rid}) => rid); 394 assert_array_equals(rids, ["bar"]); 395 const scaleDownByValues = encodings.map(({scaleResolutionDownBy}) => scaleResolutionDownBy); 396 assert_array_equals(scaleDownByValues, [1]); 397 }, 'sRD(recv simulcast answer) can narrow the simulcast envelope from a previous negotiation by removing the first encoding'); 398 399 promise_test(async t => { 400 const pc1 = new RTCPeerConnection(); 401 t.add_cleanup(() => pc1.close()); 402 const pc2 = new RTCPeerConnection(); 403 t.add_cleanup(() => pc2.close()); 404 405 const {sender} = pc1.addTransceiver("video", {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 406 let {encodings} = sender.getParameters(); 407 408 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 409 410 assert_equals(pc1.getTransceivers().length, 1); 411 encodings = sender.getParameters().encodings; 412 let rids = encodings.map(({rid}) => rid); 413 assert_array_equals(rids, ["foo", "bar"]); 414 415 // doAnswerToSendSimulcast causes pc2 to barf unless we set the direction to 416 // sendrecv 417 pc2.getTransceivers()[0].direction = "sendrecv"; 418 pc2.getTransceivers()[1].direction = "sendrecv"; 419 420 await doOfferToRecvSimulcast(pc2, pc1, ["bar"]); 421 assert_equals(pc1.getTransceivers().length, 1); 422 encodings = sender.getParameters().encodings; 423 rids = encodings.map(({rid}) => rid); 424 assert_array_equals(rids, ["foo", "bar"], "[[SendEncodings]] is not updated in have-remote-offer for reoffers"); 425 426 await doAnswerToSendSimulcast(pc2, pc1); 427 428 assert_equals(pc1.getTransceivers().length, 1); 429 encodings = sender.getParameters().encodings; 430 rids = encodings.map(({rid}) => rid); 431 assert_array_equals(rids, ["bar"]); 432 const scaleDownByValues = encodings.map(({scaleResolutionDownBy}) => scaleResolutionDownBy); 433 assert_array_equals(scaleDownByValues, [1]); 434 }, 'sRD(simulcast offer) can narrow the simulcast envelope from a previous negotiation by removing the first encoding'); 435 436 promise_test(async t => { 437 const pc1 = new RTCPeerConnection(); 438 t.add_cleanup(() => pc1.close()); 439 const pc2 = new RTCPeerConnection(); 440 t.add_cleanup(() => pc2.close()); 441 442 const {sender} = pc1.addTransceiver("video", {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 443 let {encodings} = sender.getParameters(); 444 445 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 446 447 assert_equals(pc1.getTransceivers().length, 1); 448 encodings = sender.getParameters().encodings; 449 let rids = encodings.map(({rid}) => rid); 450 assert_array_equals(rids, ["foo", "bar"]); 451 452 pc1.getTransceivers()[0].direction = "inactive"; 453 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 454 assert_equals(pc1.getTransceivers().length, 1); 455 encodings = sender.getParameters().encodings; 456 rids = encodings.map(({rid}) => rid); 457 assert_array_equals(rids, ["foo", "bar"]); 458 }, 'sender renegotiation to inactive does not disable simulcast'); 459 460 promise_test(async t => { 461 const pc1 = new RTCPeerConnection(); 462 t.add_cleanup(() => pc1.close()); 463 const pc2 = new RTCPeerConnection(); 464 t.add_cleanup(() => pc2.close()); 465 466 const {sender} = pc1.addTransceiver("video", {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 467 let {encodings} = sender.getParameters(); 468 469 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 470 471 assert_equals(pc1.getTransceivers().length, 1); 472 encodings = sender.getParameters().encodings; 473 let rids = encodings.map(({rid}) => rid); 474 assert_array_equals(rids, ["foo", "bar"]); 475 476 pc1.getTransceivers()[0].direction = "recvonly"; 477 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 478 assert_equals(pc1.getTransceivers().length, 1); 479 encodings = sender.getParameters().encodings; 480 rids = encodings.map(({rid}) => rid); 481 assert_array_equals(rids, ["foo", "bar"]); 482 }, 'sender renegotiation to recvonly does not disable simulcast'); 483 484 promise_test(async t => { 485 const pc1 = new RTCPeerConnection(); 486 t.add_cleanup(() => pc1.close()); 487 const pc2 = new RTCPeerConnection(); 488 t.add_cleanup(() => pc2.close()); 489 490 const {sender} = pc1.addTransceiver("video", {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 491 let {encodings} = sender.getParameters(); 492 493 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 494 495 assert_equals(pc1.getTransceivers().length, 1); 496 encodings = sender.getParameters().encodings; 497 let rids = encodings.map(({rid}) => rid); 498 assert_array_equals(rids, ["foo", "bar"]); 499 500 pc2.getTransceivers()[0].direction = "inactive"; 501 pc2.getTransceivers()[1].direction = "inactive"; 502 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 503 assert_equals(pc1.getTransceivers().length, 1); 504 encodings = sender.getParameters().encodings; 505 rids = encodings.map(({rid}) => rid); 506 assert_array_equals(rids, ["foo", "bar"]); 507 }, 'receiver renegotiation to inactive does not disable simulcast'); 508 509 promise_test(async t => { 510 const pc1 = new RTCPeerConnection(); 511 t.add_cleanup(() => pc1.close()); 512 const pc2 = new RTCPeerConnection(); 513 t.add_cleanup(() => pc2.close()); 514 515 const {sender} = pc1.addTransceiver("video", {sendEncodings: [{rid: "foo"}, {rid: "bar"}]}); 516 let {encodings} = sender.getParameters(); 517 518 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 519 520 assert_equals(pc1.getTransceivers().length, 1); 521 encodings = sender.getParameters().encodings; 522 let rids = encodings.map(({rid}) => rid); 523 assert_array_equals(rids, ["foo", "bar"]); 524 525 pc2.getTransceivers()[0].direction = "sendonly"; 526 pc2.getTransceivers()[1].direction = "sendonly"; 527 await doOfferToSendSimulcastAndAnswer(pc1, pc2, ["foo", "bar"]); 528 assert_equals(pc1.getTransceivers().length, 1); 529 encodings = sender.getParameters().encodings; 530 rids = encodings.map(({rid}) => rid); 531 assert_array_equals(rids, ["foo", "bar"]); 532 }, 'receiver renegotiation to sendonly does not disable simulcast'); 533 534 </script>