tor-browser

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

test_peerConnection_simulcastAnswer_lowResFirst.html (4599B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <script type="application/javascript" src="pc.js"></script>
      5  <script type="application/javascript" src="/tests/dom/canvas/test/captureStream_common.js"></script>
      6  <script type="application/javascript" src="helpers_from_wpt/sdp.js"></script>
      7  <script type="application/javascript" src="simulcast.js"></script>
      8  <script type="application/javascript" src="stats.js"></script>
      9 </head>
     10 <body>
     11 <pre id="test">
     12 <script type="application/javascript">
     13  createHTML({
     14    bug: "1231507",
     15    title: "Basic video-only peer connection with Simulcast answer, first rid has lowest resolution",
     16    visible: true
     17  });
     18 
     19  runNetworkTest(async () => {
     20    await pushPrefs(
     21        // 180Kbps was determined empirically, set well-higher than
     22        // the 80Kbps+overhead needed for the two simulcast streams.
     23        // 100Kbps was apparently too low.
     24        ['media.peerconnection.video.min_bitrate_estimate', 180*1000]);
     25 
     26    // [TODO] re-enable HW decoder after bug 1526207 is fixed.
     27    if (navigator.userAgent.includes("Android")) {
     28      await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
     29    }
     30 
     31 
     32    const offerer = new RTCPeerConnection();
     33    const answerer = new RTCPeerConnection();
     34 
     35    const add = (pc, can, failed) => can && pc.addIceCandidate(can).catch(failed);
     36    offerer.onicecandidate = e => add(answerer, e.candidate, generateErrorCallback());
     37    answerer.onicecandidate = e => add(offerer, e.candidate, generateErrorCallback());
     38 
     39    const metadataToBeLoaded = [];
     40    offerer.ontrack = (e) => {
     41      metadataToBeLoaded.push(getPlaybackWithLoadedMetadata(e.track));
     42    };
     43 
     44    // Two recv transceivers, one for each simulcast stream
     45    offerer.addTransceiver('video', { direction: 'recvonly' });
     46    offerer.addTransceiver('video', { direction: 'recvonly' });
     47 
     48    // One send transceiver, that will be used to send both simulcast streams
     49    const emitter = new VideoFrameEmitter();
     50    const videoStream = emitter.stream();
     51    answerer.addTrack(videoStream.getVideoTracks()[0], videoStream);
     52    emitter.start();
     53 
     54    const offer = await offerer.createOffer();
     55 
     56    const mungedOffer = midToRid(offer);
     57    info(`Transformed recv offer to simulcast: ${offer.sdp} to ${mungedOffer}`);
     58 
     59    await answerer.setRemoteDescription({type: 'offer', sdp: mungedOffer});
     60    await offerer.setLocalDescription(offer);
     61 
     62    const rids = offerer.getTransceivers().map(t => t.mid);
     63    is(rids.length, 2, 'Should have 2 mids in offer');
     64    ok(rids[0] != '', 'First mid should be non-empty');
     65    ok(rids[1] != '', 'Second mid should be non-empty');
     66    info(`rids: ${JSON.stringify(rids)}`);
     67 
     68    const sender = answerer.getSenders()[0];
     69    const parameters = sender.getParameters();
     70    parameters.encodings[0].maxBitrate = 40000;
     71    parameters.encodings[0].scaleResolutionDownBy = 2;
     72    parameters.encodings[1].maxBitrate = 40000;
     73    await sender.setParameters(parameters);
     74 
     75    const answer = await answerer.createAnswer();
     76 
     77    const mungedAnswer = ridToMid(answer);
     78    info(`Transformed send simulcast answer to multiple m-sections: ${answer.sdp} to ${mungedAnswer}`);
     79    await offerer.setRemoteDescription({type: 'answer', sdp: mungedAnswer});
     80    await answerer.setLocalDescription(answer);
     81 
     82    is(metadataToBeLoaded.length, 2, 'Offerer should have gotten 2 ontrack events');
     83    info('Waiting for 2 loadedmetadata events');
     84    const videoElems = await Promise.all(metadataToBeLoaded);
     85 
     86    const statsReady =
     87      Promise.all([waitForSyncedRtcp(offerer), waitForSyncedRtcp(answerer)]);
     88 
     89    const helper = new VideoStreamHelper();
     90    info('Waiting for first video element to start playing');
     91    await helper.checkVideoPlaying(videoElems[0]);
     92    info('Waiting for second video element to start playing');
     93    await helper.checkVideoPlaying(videoElems[1]);
     94 
     95    is(videoElems[1].videoWidth, 64,
     96       "sink is same width as source, modulo our cropping algorithm");
     97    is(videoElems[1].videoHeight, 64,
     98       "sink is same height as source, modulo our cropping algorithm");
     99    is(videoElems[0].videoWidth, 32,
    100       "sink is 1/2 width of source, modulo our cropping algorithm");
    101    is(videoElems[0].videoHeight, 32,
    102       "sink is 1/2 height of source, modulo our cropping algorithm");
    103 
    104    await statsReady;
    105    const senderStats = await sender.getStats();
    106    checkSenderStats(senderStats, 2);
    107    checkExpectedFields(senderStats);
    108    pedanticChecks(senderStats);
    109 
    110    emitter.stop();
    111    videoStream.getVideoTracks()[0].stop();
    112    offerer.close();
    113    answerer.close();
    114  });
    115 </script>
    116 </pre>
    117 </body>
    118 </html>