tor-browser

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

test_peerConnection_simulcastAnswer.html (4893B)


      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",
     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    const offer = await offerer.createOffer();
     49 
     50    const mungedOffer = midToRid(offer);
     51    info(`Transformed recv offer to simulcast: ${offer.sdp} to ${mungedOffer}`);
     52 
     53    await answerer.setRemoteDescription({type: 'offer', sdp: mungedOffer});
     54 
     55    // One send transceiver, that will be used to send both simulcast streams
     56    const emitter = new VideoFrameEmitter();
     57    const videoStream = emitter.stream();
     58    const sender = answerer.addTrack(videoStream.getVideoTracks()[0], videoStream);
     59    let parameters = sender.getParameters();
     60    is(parameters.encodings.length, 2);
     61    is(answerer.getSenders().length, 1);
     62    emitter.start();
     63 
     64    await offerer.setLocalDescription(offer);
     65 
     66    const rids = offerer.getTransceivers().map(t => t.mid);
     67    is(rids.length, 2, 'Should have 2 mids in offer');
     68    ok(rids[0] != '', 'First mid should be non-empty');
     69    ok(rids[1] != '', 'Second mid should be non-empty');
     70    info(`rids: ${JSON.stringify(rids)}`);
     71 
     72    parameters = sender.getParameters();
     73    info(`parameters: ${JSON.stringify(parameters)}`);
     74    const observedRids = parameters.encodings.map(({rid}) => rid);
     75    isDeeply(observedRids, rids);
     76    parameters.encodings[0].maxBitrate = 40000;
     77    parameters.encodings[0].scaleResolutionDownBy = 1;
     78    parameters.encodings[1].maxBitrate = 40000;
     79    parameters.encodings[1].scaleResolutionDownBy = 2;
     80    await sender.setParameters(parameters);
     81 
     82    const answer = await answerer.createAnswer();
     83 
     84    const mungedAnswer = ridToMid(answer);
     85    info(`Transformed send simulcast answer to multiple m-sections: ${answer.sdp} to ${mungedAnswer}`);
     86    await offerer.setRemoteDescription({type: 'answer', sdp: mungedAnswer});
     87    await answerer.setLocalDescription(answer);
     88 
     89    is(metadataToBeLoaded.length, 2, 'Offerer should have gotten 2 ontrack events');
     90    info('Waiting for 2 loadedmetadata events');
     91    const videoElems = await Promise.all(metadataToBeLoaded);
     92 
     93    const statsReady =
     94      Promise.all([waitForSyncedRtcp(offerer), waitForSyncedRtcp(answerer)]);
     95 
     96    const helper = new VideoStreamHelper();
     97    info('Waiting for first video element to start playing');
     98    await helper.checkVideoPlaying(videoElems[0]);
     99    info('Waiting for second video element to start playing');
    100    await helper.checkVideoPlaying(videoElems[1]);
    101 
    102    is(videoElems[0].videoWidth, 64,
    103       "sink is same width as source, modulo our cropping algorithm");
    104    is(videoElems[0].videoHeight, 64,
    105       "sink is same height as source, modulo our cropping algorithm");
    106    is(videoElems[1].videoWidth, 32,
    107       "sink is 1/2 width of source, modulo our cropping algorithm");
    108    is(videoElems[1].videoHeight, 32,
    109       "sink is 1/2 height of source, modulo our cropping algorithm");
    110 
    111    await statsReady;
    112    info("Stats ready");
    113    const senderStats = await sender.getStats();
    114    checkSenderStats(senderStats, 2);
    115    checkExpectedFields(senderStats);
    116    pedanticChecks(senderStats);
    117 
    118    emitter.stop();
    119    videoStream.getVideoTracks()[0].stop();
    120    offerer.close();
    121    answerer.close();
    122  });
    123 </script>
    124 </pre>
    125 </body>
    126 </html>