tor-browser

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

h265-loopback.https.html (2722B)


      1 <!doctype html>
      2 <meta charset=utf-8>
      3 <meta name="timeout" content="long">
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <script src="../RTCPeerConnection-helper.js"></script>
      7 <script>
      8 'use strict';
      9 
     10 async function pollGetStatsUntil(t, pc, condition, pollingMs = 100) {
     11  while (true) {
     12    const report = await pc.getStats();
     13    for (const stats of report.values()) {
     14      if (condition(report, stats) == true) {
     15        // Condition satisfied, stop polling.
     16        return;
     17      }
     18    }
     19    await new Promise(r => t.step_timeout(r, pollingMs));
     20  }
     21 }
     22 
     23 function isRtpWithCodec(report, stats, mimeType) {
     24  if (stats.type != 'outbound-rtp' && stats.type != 'inbound-rtp') {
     25    return false;  // Not an RTP stats object.
     26  }
     27  const codec = report.get(stats.codecId);
     28  return codec && codec.mimeType == mimeType;
     29 }
     30 
     31 promise_test(async t => {
     32  const sendCodec = RTCRtpSender.getCapabilities('video').codecs.find(
     33      codec => codec.mimeType == 'video/H265');
     34  const recvCodec = RTCRtpReceiver.getCapabilities('video').codecs.find(
     35      codec => codec.mimeType == 'video/H265');
     36  assert_implements_optional(
     37      sendCodec != undefined && recvCodec != undefined,
     38      'H265 not available for sending or receiving. Loopback requires both.');
     39 
     40  const pc1 = new RTCPeerConnection();
     41  t.add_cleanup(() => pc1.close());
     42  const pc2 = new RTCPeerConnection();
     43  t.add_cleanup(() => pc2.close());
     44  pc1.onicecandidate = (e) => pc2.addIceCandidate(e.candidate);
     45  pc2.onicecandidate = (e) => pc1.addIceCandidate(e.candidate);
     46 
     47  const stream = await getNoiseStream({video:{width:640, height:360}});
     48  const [track] = stream.getVideoTracks();
     49  t.add_cleanup(() => track.stop());
     50 
     51  // Negotiate H265.
     52  const transceiver = pc1.addTransceiver(track);
     53  transceiver.setCodecPreferences([sendCodec]);
     54  await pc1.setLocalDescription();
     55  await pc2.setRemoteDescription(pc1.localDescription);
     56  await pc2.setLocalDescription();
     57  await pc1.setRemoteDescription(pc2.localDescription);
     58 
     59  // Wait for H265 frames to be encoded and sent.
     60  await pollGetStatsUntil(t, pc1, (report, stats) => {
     61    if (!isRtpWithCodec(report, stats, 'video/H265')) {
     62      return false;
     63    }
     64    assert_equals(stats.type, 'outbound-rtp');
     65    return stats.framesEncoded > 0 && stats.framesSent > 0;
     66  });
     67  // Wait for H265 frames to be received and decoded.
     68  await pollGetStatsUntil(t, pc2, (report, stats) => {
     69    if (!isRtpWithCodec(report, stats, 'video/H265')) {
     70      return false;
     71    }
     72    assert_equals(stats.type, 'inbound-rtp');
     73    return stats.framesReceived > 0 && stats.framesDecoded > 0;
     74  });
     75 }, `Negotiate H265 loopback and verify frames are flowing`);
     76 </script>