tor-browser

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

test_peerConnection_videoCodecs.html (6658B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <script type="application/javascript" src="pc.js"></script>
      5  <script type="application/javascript" src="stats.js"></script>
      6  <script type="application/javascript" src="/tests/dom/canvas/test/captureStream_common.js"></script>
      7 </head>
      8 <body>
      9 <pre id="test">
     10 <script type="application/javascript">
     11  createHTML({
     12    bug: "1395853",
     13    title: "Verify video content over WebRTC for every video codec",
     14  });
     15 
     16  async function testVideoCodec(options = {}, codec) {
     17    const test = new PeerConnectionTest(options);
     18    test.setMediaConstraints([{video: true}], []);
     19 
     20    let payloadType;
     21    test.chain.insertBefore("PC_LOCAL_SET_LOCAL_DESCRIPTION", [
     22      function PC_LOCAL_FILTER_OUT_CODECS() {
     23        const id = sdputils.findCodecId(test.originalOffer.sdp, codec.name, codec.offset);
     24        payloadType = Number(id);
     25        const otherIds = [];
     26        for (const otherCodec of codecs) {
     27          const otherId = sdputils.findCodecId(test.originalOffer.sdp, otherCodec.name, otherCodec.offset);
     28          const otherRtpmapMatcher = new RegExp(`a=rtpmap:${otherId}.*\\r\\n`, "gi");
     29 
     30          if (codec.offset) {
     31            isnot(id, sdputils.findCodecId(test.originalOffer.sdp, codec.name, 0),
     32              "Different offsets should return different payload types");
     33          }
     34          if (Number(otherId) != id) {
     35            otherIds.push(otherId);
     36          }
     37        }
     38 
     39        test.originalOffer.sdp =
     40          sdputils.removeAllButPayloadType(test.originalOffer.sdp, id);
     41 
     42        // Bug 1901160 test receiving signaling with no H264 profile-level-id fmtp.
     43        if (codec.hasOwnProperty("fmtpOverride")) {
     44          test.originalOffer.sdp = test.originalOffer.sdp.replace(new RegExp(`(a=fmtp:${id}).*(\\r\\n)`, "gi"), `$1 ${codec.fmtpOverride}$2`);
     45        }
     46 
     47        for (const otherId of otherIds) {
     48          ok(!test.originalOffer.sdp.match(new RegExp(`m=.*UDP/TLS/RTP/SAVPF.* ${otherId}[^0-9]`, "gi")),
     49            `Other codec ${otherId} should be removed after filtering`);
     50        }
     51        ok(test.originalOffer.sdp.match(new RegExp(`m=.*UDP/TLS/RTP/SAVPF.* ${id}[^0-9]`, "gi")),
     52          `Tested codec ${id} should remain after filtering`);
     53 
     54        // We only set it now, or the framework would remove non-H264 codecs
     55        // for us.
     56        options.h264 = codec.name == "H264";
     57        // Ditto for AV1.
     58        options.av1 = codec.name == "AV1";
     59      },
     60    ]);
     61 
     62    test.chain.insertAfter("PC_LOCAL_WAIT_FOR_MEDIA_FLOW",
     63      [PC_LOCAL_TEST_LOCAL_STATS]);
     64 
     65    test.chain.insertAfter("PC_REMOTE_WAIT_FOR_MEDIA_FLOW",
     66      [PC_REMOTE_TEST_REMOTE_STATS]);
     67 
     68    test.chain.append([
     69      async function PC_LOCAL_TEST_CODEC() {
     70        const stats = await test.pcLocal._pc.getStats();
     71        let codecCount = 0;
     72        stats.forEach(stat => {
     73          if (stat.type == "codec") {
     74            is(codecCount++, 0, "expected only one encode codec stat");
     75            is(stat.payloadType, payloadType, "payloadType as expected");
     76            is(stat.mimeType, `video/${codec.name}`, "mimeType as expected");
     77            is(stat.codecType, "encode", "codecType as expected");
     78          }
     79        });
     80      },
     81      async function PC_REMOTE_TEST_CODEC() {
     82        const stats = await test.pcRemote._pc.getStats();
     83        let codecCount = 0;
     84        stats.forEach(stat => {
     85          if (stat.type == "codec") {
     86            is(codecCount++, 0, "expected only one decode codec stat");
     87            is(stat.payloadType, payloadType, "payloadType as expected");
     88            is(stat.mimeType, `video/${codec.name}`, "mimeType as expected");
     89            is(stat.codecType, "decode", "codecType as expected");
     90          }
     91        });
     92      },
     93    ]);
     94 
     95    if (!navigator.userAgent.includes("Android")) {
     96      // TODO: enable on Android when bug 1526207 is fixed.
     97      test.chain.append([
     98        async function CHECK_VIDEO_FLOW() {
     99          try {
    100            const h = new VideoStreamHelper();
    101            await h.checkVideoPlaying(
    102                test.pcRemote.remoteMediaElements[0],
    103                10, 10, 128);
    104            ok(true, `Got video flow for codec ${codec.name}, offset ${codec.offset}`);
    105          } catch(e) {
    106            ok(false, `No video flow for codec ${codec.name}, offset ${codec.offset}: ${e}`);
    107          }
    108        },
    109      ]);
    110    }
    111 
    112    await test.run();
    113  }
    114 
    115  // We match the name against the sdp to figure out the payload type,
    116  // so all other present codecs can be removed.
    117  // Use `offset` when there are multiple instances of a codec expected in an sdp.
    118  const codecs = [
    119    { name: "VP8" },
    120    { name: "VP9" },
    121    { name: "H264" },
    122    { name: "AV1" },
    123  ];
    124 
    125  runNetworkTest(async (options) => {
    126    const h264Support = checkPlatformH264CodecPrefs();
    127 
    128    // This test expects the video being captured will change color. Use fake
    129    // video device as loopback does not currently change.
    130    await pushPrefs(
    131      ['media.video_loopback_dev', ''],
    132      ['media.navigator.streams.fake', true],
    133      ["media.navigator.video.disable_h264_baseline", false],
    134    );
    135 
    136    if (h264Support.webrtc) {
    137      codecs.push(
    138        { name: "H264", offset: 1 },
    139        { name: "H264", offset: 2 },
    140        { name: "H264", offset: 2, fmtpOverride: "packetization-mode=1" },
    141        { name: "H264", offset: 3 },
    142        { name: "H264", offset: 3, fmtpOverride: "packetization-mode=0" },
    143        { name: "H264", offset: 3, fmtpOverride: "" }
    144      );
    145    } else {
    146      // With only platform encoders we don't signal packetization-mode=0 as
    147      // not all platforms support slice size control.
    148      codecs.push(
    149        { name: "H264", offset: 1 },
    150        { name: "H264", offset: 1, fmtpOverride: "packetization-mode=1" },
    151      );
    152    }
    153 
    154    for (const codec of codecs) {
    155      let libWebrtcCodec = true;
    156      if (codec.name == "H264") {
    157        libWebrtcCodec = h264Support.webrtc;
    158      }
    159      // Use builtin webrtc encoders where possible.
    160      await pushPrefs(
    161        ['media.webrtc.encoder_creation_strategy', !libWebrtcCodec],
    162        // Don't use MediaDataDecoder with fakeopenh264. Remove this when we
    163        // return a valid bitstream from fakeopenh264(bug 1509012).
    164        ['media.navigator.mediadatadecoder_h264_enabled', !libWebrtcCodec],
    165      );
    166 
    167      info(`Testing video for codec ${codec.name} offset ${codec.offset}`);
    168      try {
    169        await timerGuard(testVideoCodec(options, codec), 20000, `codec=${JSON.stringify(codec)}`);
    170      } catch(e) {
    171        ok(false, `Error in test for codec ${codec.name}: ${e}\n${e.stack}`);
    172      }
    173      info(`Tested video for codec ${codec.name}`);
    174    }
    175  });
    176 </script>
    177 </pre>
    178 </body>
    179 </html>