tor-browser

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

setParameters-maxFramerate.https.html (4197B)


      1 <!doctype html>
      2 <meta charset=utf-8>
      3 <title>RTCPeerConnection Simulcast Tests - setParameters/maxFramerate</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 async function queryReceiverStats(pc) {
     15  const inboundStats = [];
     16  await Promise.all(pc.getReceivers().map(async receiver => {
     17    const receiverStats = await receiver.getStats();
     18    receiverStats.forEach(stat => {
     19      if (stat.type === 'inbound-rtp') {
     20        inboundStats.push(stat);
     21      }
     22    });
     23  }));
     24  return inboundStats;
     25 }
     26 
     27 async function statsDelta(pc, t) {
     28  const initialStats = await queryReceiverStats(pc);
     29  await new Promise(resolve => t.step_timeout(resolve, 1000)); // Wait more.
     30  const subsequentStats = await queryReceiverStats(pc);
     31  return {initialStats, subsequentStats};
     32 }
     33 
     34 function calculateFramerate(newStats, oldStats) {
     35  const deltaF = newStats.framesDecoded - oldStats.framesDecoded;
     36  const deltaT = newStats.timestamp - oldStats.timestamp;
     37  return deltaF / deltaT * 1000;
     38 }
     39 
     40 function calculateConservativeFramerate(newStats, oldStats) {
     41  // The timestamp represents the exact point in time that the integer
     42  // framesDecoded was sampled. For both samples, one time unit (say a
     43  // nanosecond, i.e. virtually 0) could sway the integer framesDecoded value
     44  // up to 1 frame. For checking that we don't exceed maxFramerate, in the worst
     45  // case, the old timestamp is then at the end of a frame period (right before
     46  // framesDecoded gets incremented) while the new timestamp is at the beginning
     47  // of a frame period. Thus for avoiding intermittents we need to allow up to
     48  // two frames more for the given sampling period, regardless of length.
     49  const deltaF = newStats.framesDecoded - oldStats.framesDecoded - 2;
     50  const deltaT = newStats.timestamp - oldStats.timestamp;
     51  return deltaF / deltaT * 1000;
     52 }
     53 
     54 promise_test(async t => {
     55  const expectedFramerates = [15, 10, 5];
     56  const rids = [0, 1, 2];
     57  const pc1 = new RTCPeerConnection();
     58  t.add_cleanup(() => pc1.close());
     59  const pc2 = new RTCPeerConnection();
     60  t.add_cleanup(() => pc2.close());
     61 
     62  await negotiateSimulcastAndWaitForVideo(
     63    t,
     64    await getCameraStream(t),
     65    rids,
     66    pc1,
     67    pc2
     68  );
     69 
     70  // Wait for framerate to stabilize.
     71  await new Promise(resolve => t.step_timeout(resolve, 1000));
     72 
     73  // Assert that our framerate is bigger than 20, otherwise this test does not
     74  // assert anything useful.
     75  const defaultStats = await statsDelta(pc2, t);
     76  defaultStats.subsequentStats.forEach((_, idx) => {
     77    const actualFramerate = calculateFramerate(
     78      defaultStats.subsequentStats[idx],
     79      defaultStats.initialStats[idx]
     80    );
     81    assert_greater_than(actualFramerate, 20);
     82  });
     83 
     84  // Change the framerate on all layers.
     85  const parameters = pc1.getSenders()[0].getParameters();
     86  parameters.encodings.forEach((e, idx) => {
     87    e.maxFramerate = expectedFramerates[idx];
     88  });
     89  await pc1.getSenders()[0].setParameters(parameters);
     90  // Wait for the change to propagate to the receiver.
     91  await new Promise(resolve => t.step_timeout(resolve, 100));
     92 
     93  // Assert the approximate framerate
     94  const newStats = await statsDelta(pc2, t);
     95 
     96  const framerates = [];
     97  newStats.subsequentStats.forEach((_, idx) => {
     98    const expectedFramerate = expectedFramerates[idx];
     99    const actualFramerate = calculateConservativeFramerate(
    100      newStats.subsequentStats[idx],
    101      newStats.initialStats[idx]
    102    );
    103    // Assert that the framerate is at most the expected framerate.
    104    assert_less_than(actualFramerate, expectedFramerate);
    105    framerates.push(actualFramerate);
    106  });
    107  // Assert that the framerates are ordered as configured.
    108  assert_array_equals(framerates, framerates.toSorted((a, b) => a < b));
    109 }, 'Simulcast setParameters maxFramerate reduces the framerate');
    110 </script>