tor-browser

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

test_peerConnection_audioChannels.html (3700B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <script type="application/javascript" src="pc.js"></script>
      5 </head>
      6 <body>
      7 <pre id="test">
      8 <script type="application/javascript">
      9 
     10 createHTML({
     11  bug: "1765005",
     12  title: "Verify audio channel limits for each negotiated audio codec",
     13 });
     14 
     15 const matchesChannels = (sdp, codec, channels) =>
     16  !!sdp.match(new RegExp(`a=rtpmap:\\d* ${codec}\/\\d*\/${channels}\r\n`, "g")) ||
     17  (channels <= 1 &&
     18   !!sdp.match(new RegExp(`a=rtpmap:\\d* ${codec}\/\\d*\r\n`, "g")));
     19 
     20 async function testAudioChannels(track, codec, channels, accepted, expectedChannels) {
     21  const pc1 = new RTCPeerConnection();
     22  const pc2 = new RTCPeerConnection();
     23  try {
     24    pc1.addTrack(track);
     25    pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
     26    pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);
     27    await pc1.setLocalDescription();
     28    await pc2.setRemoteDescription(pc1.localDescription);
     29    let {type, sdp} = await pc2.createAnswer();
     30    sdp = sdp.replace(new RegExp(`a=rtpmap:(\\d*) ${codec}\/(\\d*)\/?\\d*\r\n`, "g"),
     31                                 `a=rtpmap:$1 ${codec}/$2/${channels}\r\n`);
     32    const payloadType = Number(sdputils.findCodecId(sdp, codec));
     33    sdp = sdputils.removeAllButPayloadType(sdp, payloadType);
     34    ok(matchesChannels(sdp, codec, channels), "control");
     35    await pc2.setLocalDescription({type, sdp});
     36    is(matchesChannels(pc2.localDescription.sdp, codec, channels),
     37       accepted,
     38       `test pc2.localDescription`);
     39    try {
     40      await pc1.setRemoteDescription(pc2.localDescription);
     41      ok(expectedChannels, "SRD should succeed iff we're expecting channels");
     42      const [receiver] = pc2.getReceivers();
     43      await new Promise(r => receiver.track.onunmute = r);
     44      let stats = await receiver.getStats();
     45      let inboundStat = [...stats.values()].find(({type}) => type == "inbound-rtp");
     46      if (!inboundStat) {
     47        info("work around bug 1765215"); // TODO bug 1765215
     48        await new Promise(r => setTimeout(r, 200));
     49        stats = await receiver.getStats();
     50        inboundStat = [...stats.values()].find(({type}) => type == "inbound-rtp");
     51      }
     52      ok(inboundStat, "has inbound-rtp stats after track unmute (w/workaround)");
     53      const codecStat = stats.get(inboundStat.codecId);
     54      ok(codecStat.mimeType.includes(codec), "correct codec");
     55      is(codecStat.payloadType, payloadType, "correct payloadType");
     56      is(codecStat.channels, expectedChannels, "expected channels");
     57    } catch (e) {
     58      ok(!expectedChannels, "SRD should fail iff we're not expecting channels");
     59    }
     60  } finally {
     61    pc1.close();
     62    pc2.close();
     63  }
     64 }
     65 
     66 runNetworkTest(async () => {
     67  const [track] = (await navigator.mediaDevices.getUserMedia({audio: true}))
     68      .getAudioTracks();
     69  try {
     70    for (let [codec, channels, accepted, expectedChannels] of [
     71      ["opus", 2, true, 2],
     72      ["opus", 1, true, 0],
     73      ["opus", 1000, true, 0],
     74      ["G722", 1, true, 1],
     75      ["G722", 2, true, 0],
     76      ["G722", 1000, true, 0],
     77      ["PCMU", 1, true, 1],
     78      ["PCMU", 2, false, 1],
     79      ["PCMU", 1000, false, 1],
     80      ["PCMA", 1, true, 1],
     81      ["PCMA", 2, false, 1],
     82      ["PCMA", 1000, false, 1]
     83    ]) {
     84      const testName = `${codec} with ${channels} channel(s) is ` +
     85          `${accepted? "accepted" : "ignored"} and produces ` +
     86          `${expectedChannels || "no"} channels`;
     87      try {
     88        info(`Testing that ${testName}`);
     89        await testAudioChannels(track, codec, channels, accepted, expectedChannels);
     90      } catch (e) {
     91        ok(false, `Error testing that ${testName}: ${e}\n${e.stack}`);
     92      }
     93    }
     94  } finally {
     95    track.stop();
     96  }
     97 });
     98 
     99 </script>
    100 </pre>
    101 </body>
    102 </html>