tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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>