tor-browser

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

test_peerConnection_simulcastOddResolution.html (8090B)


      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: "1432793",
     15    title: "Simulcast with odd resolution",
     16    visible: true
     17  });
     18 
     19  runNetworkTest(async () => {
     20    const helper = new VideoStreamHelper();
     21    const emitter = new VideoFrameEmitter(helper.green, helper.red, 705, 528);
     22 
     23    async function checkVideoElement(senderElement, receiverElement, encoding) {
     24      info(`Waiting for receiver video element ${encoding.rid} to start playing`);
     25      await helper.checkVideoPlaying(receiverElement);
     26      const srcWidth = senderElement.videoWidth;
     27      const srcHeight = senderElement.videoHeight;
     28      info(`Source resolution is ${srcWidth}x${srcHeight}`);
     29 
     30      const scaleDownBy = encoding.scaleResolutionDownBy;
     31      const expectedWidth = srcWidth / scaleDownBy;
     32      const expectedHeight = srcHeight / scaleDownBy;
     33      const margin = srcWidth * 0.1;
     34      const width = receiverElement.videoWidth;
     35      const height = receiverElement.videoHeight;
     36      const rid = encoding.rid;
     37      ok(width >= expectedWidth - margin && width <= expectedWidth + margin,
     38        `Width ${width} should be within 10% of ${expectedWidth} for rid '${rid}'`);
     39      ok(height >= expectedHeight - margin && height <= expectedHeight + margin,
     40        `Height ${height} should be within 10% of ${expectedHeight} for rid '${rid}'`);
     41    }
     42 
     43    async function checkVideoElements(senderElement, receiverElements, encodings) {
     44      is(receiverElements.length, encodings.length, 'Number of video elements should match number of encodings');
     45      info('Waiting for sender video element to start playing');
     46      await helper.checkVideoPlaying(senderElement);
     47      for (let i = 0; i < encodings.length; i++) {
     48        await checkVideoElement(senderElement, receiverElements[i], encodings[i]);
     49      }
     50    }
     51 
     52    const sendEncodings = [{ rid: "0", maxBitrate: 40000, scaleResolutionDownBy: 1.9 },
     53                           { rid: "1", maxBitrate: 40000, scaleResolutionDownBy: 3.5 },
     54                           { rid: "2", maxBitrate: 40000, scaleResolutionDownBy: 6.8 }];
     55 
     56    async function checkSenderStats(sender) {
     57      const senderStats = await sender.getStats();
     58      checkSenderStats(senderStats, sendEncodings.length);
     59      checkExpectedFields(senderStats);
     60      pedanticChecks(senderStats);
     61    }
     62 
     63    async function waitForResizeEvents(elements) {
     64      return Promise.all(elements.map(elem => haveEvent(elem, 'resize')));
     65    }
     66 
     67    await pushPrefs(
     68        // 180Kbps was determined empirically, set well-higher than
     69        // the 80Kbps+overhead needed for the two simulcast streams.
     70        // 100Kbps was apparently too low.
     71        ['media.peerconnection.video.min_bitrate_estimate', 180*1000]);
     72 
     73    // [TODO] re-enable HW decoder after bug 1526207 is fixed.
     74    if (navigator.userAgent.includes("Android")) {
     75      await pushPrefs(["media.navigator.mediadatadecoder_vpx_enabled", false]);
     76    }
     77 
     78 
     79    const offerer = new RTCPeerConnection();
     80    const answerer = new RTCPeerConnection();
     81 
     82    const add = (pc, can, failed) => can && pc.addIceCandidate(can).catch(failed);
     83    offerer.onicecandidate = e => add(answerer, e.candidate, generateErrorCallback());
     84    answerer.onicecandidate = e => add(offerer, e.candidate, generateErrorCallback());
     85 
     86    const metadataToBeLoaded = [];
     87    answerer.ontrack = (e) => {
     88      metadataToBeLoaded.push(getPlaybackWithLoadedMetadata(e.track));
     89    };
     90 
     91    // One send transceiver, that will be used to send both simulcast streams
     92    const videoStream = emitter.stream();
     93    offerer.addTransceiver(videoStream.getVideoTracks()[0], {sendEncodings});
     94    const senderElement = document.createElement('video');
     95    senderElement.autoplay = true;
     96    senderElement.srcObject = videoStream;
     97    senderElement.id = videoStream.id
     98 
     99    const sender = offerer.getSenders()[0];
    100    let parameters = sender.getParameters();
    101    is(parameters.encodings[0].maxBitrate, sendEncodings[0].maxBitrate);
    102    isfuzzy(parameters.encodings[0].scaleResolutionDownBy,
    103      sendEncodings[0].scaleResolutionDownBy, 0.01);
    104    is(parameters.encodings[1].maxBitrate, sendEncodings[1].maxBitrate);
    105    isfuzzy(parameters.encodings[1].scaleResolutionDownBy,
    106      sendEncodings[1].scaleResolutionDownBy, 0.01);
    107    is(parameters.encodings[2].maxBitrate, sendEncodings[2].maxBitrate);
    108    isfuzzy(parameters.encodings[2].scaleResolutionDownBy,
    109      sendEncodings[2].scaleResolutionDownBy, 0.01);
    110 
    111    const offer = await offerer.createOffer();
    112 
    113    const mungedOffer = ridToMid(offer);
    114    info(`Transformed send simulcast offer to multiple m-sections: ${offer.sdp} to ${mungedOffer}`);
    115 
    116    await answerer.setRemoteDescription({type: 'offer', sdp: mungedOffer});
    117    await offerer.setLocalDescription(offer);
    118 
    119    const rids = answerer.getTransceivers().map(t => t.mid);
    120    is(rids.length, 3, 'Should have 3 mids in offer');
    121    ok(rids[0], 'First mid should be non-empty');
    122    ok(rids[1], 'Second mid should be non-empty');
    123    ok(rids[2], 'Third mid should be non-empty');
    124    info(`rids: ${JSON.stringify(rids)}`);
    125 
    126    const answer = await answerer.createAnswer();
    127 
    128    const mungedAnswer = midToRid(answer);
    129    info(`Transformed recv answer to simulcast: ${answer.sdp} to ${mungedAnswer}`);
    130    await offerer.setRemoteDescription({type: 'answer', sdp: mungedAnswer});
    131    await answerer.setLocalDescription(answer);
    132 
    133    is(metadataToBeLoaded.length, 3, 'Offerer should have gotten 3 ontrack events');
    134    emitter.start();
    135    info('Waiting for 3 loadedmetadata events');
    136    const videoElems = await Promise.all(metadataToBeLoaded);
    137    await checkVideoElements(senderElement, videoElems, parameters.encodings);
    138    emitter.stop();
    139 
    140    await Promise.all([waitForSyncedRtcp(offerer), waitForSyncedRtcp(answerer)]);
    141 
    142    info(`Changing source resolution to 1280x720`);
    143    emitter.size(1280, 720);
    144    emitter.start();
    145    await waitForResizeEvents([senderElement, ...videoElems]);
    146    await checkVideoElements(senderElement, videoElems, parameters.encodings);
    147    await checkSenderStats(sender);
    148 
    149    parameters = sender.getParameters();
    150    parameters.encodings[0].scaleResolutionDownBy = 1;
    151    parameters.encodings[1].scaleResolutionDownBy = 2;
    152    parameters.encodings[2].scaleResolutionDownBy = 3;
    153    info(`Changing encodings to ${JSON.stringify(parameters.encodings)}`);
    154    await sender.setParameters(parameters);
    155    await waitForResizeEvents(videoElems);
    156    await checkVideoElements(senderElement, videoElems, parameters.encodings);
    157    await checkSenderStats(sender);
    158 
    159    parameters = sender.getParameters();
    160    parameters.encodings[0].scaleResolutionDownBy = 6;
    161    parameters.encodings[1].scaleResolutionDownBy = 5;
    162    parameters.encodings[2].scaleResolutionDownBy = 4;
    163    info(`Changing encodings to ${JSON.stringify(parameters.encodings)}`);
    164    await sender.setParameters(parameters);
    165    await waitForResizeEvents(videoElems);
    166    await checkVideoElements(senderElement, videoElems, parameters.encodings);
    167    await checkSenderStats(sender);
    168 
    169    parameters = sender.getParameters();
    170    parameters.encodings[0].scaleResolutionDownBy = 4;
    171    parameters.encodings[1].scaleResolutionDownBy = 1;
    172    parameters.encodings[2].scaleResolutionDownBy = 2;
    173    info(`Changing encodings to ${JSON.stringify(parameters.encodings)}`);
    174    await sender.setParameters(parameters);
    175    await waitForResizeEvents(videoElems);
    176    await checkVideoElements(senderElement, videoElems, parameters.encodings);
    177    await checkSenderStats(sender);
    178 
    179    emitter.stop();
    180    videoStream.getVideoTracks()[0].stop();
    181    offerer.close();
    182    answerer.close();
    183  });
    184 
    185 </script>
    186 </pre>
    187 </body>
    188 </html>