tor-browser

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

request-video-frame-callback-webrtc.https.html (5621B)


      1 <!doctype html>
      2 <html>
      3 <head>
      4  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      5  <title>WebRTC video.requestVideoFrameCallback() test</title>
      6  <script src="/webrtc/RTCPeerConnection-helper.js"></script>
      7 </head>
      8 <body>
      9  <div id="log"></div>
     10  <div>
     11    <video id="local-view" muted autoplay="autoplay"></video>
     12    <video id="remote-view" muted autoplay="autoplay"></video>
     13  </div>
     14 
     15  <!-- These files are in place when executing on W3C. -->
     16  <script src="/resources/testharness.js"></script>
     17  <script src="/resources/testharnessreport.js"></script>
     18  <script type="text/javascript">
     19  var test = async_test('Test video.requestVideoFrameCallback() parameters for WebRTC applications.');
     20 
     21  //
     22  // This test is based on /webrtc/simplecall.https.html, but it calls to
     23  // video.requestVideoFrameCallback() before ending, to verify WebRTC required
     24  // and optional parameters.
     25  //
     26 
     27  var gFirstConnection = null;
     28  var gSecondConnection = null;
     29  var verify_params = (now, metadata) => {
     30    assert_greater_than(now, 0);
     31 
     32    // Verify all required fields
     33    assert_greater_than(metadata.presentationTime, 0);
     34    assert_greater_than(metadata.expectedDisplayTime, 0);
     35    assert_greater_than(metadata.presentedFrames, 0);
     36    assert_greater_than(metadata.width, 0);
     37    assert_greater_than(metadata.height, 0);
     38    assert_true("mediaTime" in metadata, "mediaTime should be present");
     39 
     40    // Verify WebRTC only fields.
     41    assert_true("rtpTimestamp" in metadata, "rtpTimestamp should be present");
     42    assert_true("receiveTime" in metadata, "receiveTime should be present");
     43    // Verifying that captureTime is too unreliable to be included in tests.
     44  }
     45 
     46  var verify_local_metadata = (now, metadata) => {
     47    assert_greater_than(metadata.expectedDisplayTime, 0);
     48    assert_greater_than(metadata.presentedFrames, 0);
     49    assert_greater_than(metadata.width, 0);
     50    assert_greater_than(metadata.height, 0);
     51    assert_true("captureTime" in metadata, "captureTime should always be present for local sources.");
     52    assert_greater_than(metadata.captureTime, 0);
     53  }
     54 
     55  // If the remote video gets video data that implies the negotiation
     56  // as well as the ICE and DTLS connection are up.
     57  document.getElementById('remote-view')
     58      .addEventListener('loadedmetadata', function() {
     59    document.getElementById('remote-view').requestVideoFrameCallback(test.step_func_done(verify_params));
     60  });
     61 
     62  document.getElementById('local-view')
     63      .addEventListener('loadmetadata', function() {
     64    document.getElementById('local-view').requestVideoFrameCallback(test.step_func_done(verify_local_metadata));
     65  });
     66 
     67 
     68  function getNoiseStreamOkCallback(localStream) {
     69    gFirstConnection = new RTCPeerConnection(null);
     70    test.add_cleanup(() => gFirstConnection.close());
     71    gFirstConnection.onicecandidate = onIceCandidateToFirst;
     72 
     73    gSecondConnection = new RTCPeerConnection(null);
     74    test.add_cleanup(() => gSecondConnection.close());
     75    gSecondConnection.onicecandidate = onIceCandidateToSecond;
     76    gSecondConnection.ontrack = onRemoteTrack;
     77 
     78    localStream.getTracks().forEach(function(track) {
     79      // Bidirectional streams are needed in order for captureTime to be
     80      // populated. Use the same source in both directions.
     81      gFirstConnection.addTrack(track, localStream);
     82      gSecondConnection.addTrack(track, localStream);
     83    });
     84 
     85    gFirstConnection.createOffer().then(onOfferCreated, failed('createOffer'));
     86 
     87    var videoTag = document.getElementById('local-view');
     88    videoTag.srcObject = localStream;
     89  };
     90 
     91  var onOfferCreated = test.step_func(function(offer) {
     92    gFirstConnection.setLocalDescription(offer);
     93 
     94    // This would normally go across the application's signaling solution.
     95    // In our case, the "signaling" is to call this function.
     96    receiveCall(offer.sdp);
     97  });
     98 
     99  function receiveCall(offerSdp) {
    100    var parsedOffer = new RTCSessionDescription({ type: 'offer',
    101                                                  sdp: offerSdp });
    102    gSecondConnection.setRemoteDescription(parsedOffer);
    103 
    104    gSecondConnection.createAnswer().then(onAnswerCreated,
    105                                   failed('createAnswer'));
    106  };
    107 
    108  var onAnswerCreated = test.step_func(function(answer) {
    109    gSecondConnection.setLocalDescription(answer);
    110 
    111    // Similarly, this would go over the application's signaling solution.
    112    handleAnswer(answer.sdp);
    113  });
    114 
    115  function handleAnswer(answerSdp) {
    116    var parsedAnswer = new RTCSessionDescription({ type: 'answer',
    117                                                   sdp: answerSdp });
    118    gFirstConnection.setRemoteDescription(parsedAnswer);
    119  };
    120 
    121  var onIceCandidateToFirst = test.step_func(function(event) {
    122    // If event.candidate is null = no more candidates.
    123    if (event.candidate) {
    124      gSecondConnection.addIceCandidate(event.candidate);
    125    }
    126  });
    127 
    128  var onIceCandidateToSecond = test.step_func(function(event) {
    129    if (event.candidate) {
    130      gFirstConnection.addIceCandidate(event.candidate);
    131    }
    132  });
    133 
    134  var onRemoteTrack = test.step_func(function(event) {
    135    var videoTag = document.getElementById('remote-view');
    136    if (!videoTag.srcObject) {
    137      videoTag.srcObject = event.streams[0];
    138    }
    139  });
    140 
    141  // Returns a suitable error callback.
    142  function failed(function_name) {
    143    return test.unreached_func('WebRTC called error callback for ' + function_name);
    144  }
    145 
    146  // This function starts the test.
    147  test.step(function() {
    148    getNoiseStream({ video: true, audio: true })
    149      .then(test.step_func(getNoiseStreamOkCallback), failed('getNoiseStream'));
    150  });
    151 </script>
    152 
    153 </body>
    154 </html>