tor-browser

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

test_mediarecorder_record_audionode.html (4426B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <title>Test MediaRecorder Record AudioContext Node</title>
      5  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
      7  <script type="text/javascript" src="manifest.js"></script>
      8 </head>
      9 <body>
     10 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=968109">Mozilla Bug 968109</a>
     11 
     12 <script class="testbody" type="text/javascript">
     13 
     14 SimpleTest.waitForExplicitFinish();
     15 
     16 function setUpSource(contextType, nodeType) {
     17  // Use contextType to choose offline or real-time context.
     18  const context = contextType == "offline"?
     19    new OfflineAudioContext(2 , 80920, 44100) : new AudioContext();
     20  const buffer = context.createBuffer(2, 80920, context.sampleRate);
     21  for (let i = 0; i < 80920; ++i) {
     22    buffer.getChannelData(0)[i] = Math.sin(1000 * 2 * Math.PI * i / context.sampleRate);
     23    buffer.getChannelData(1)[i] = Math.sin(1000 * 2 * Math.PI * i / context.sampleRate);
     24  }
     25 
     26  const source = context.createBufferSource();
     27  source.buffer = buffer;
     28  source.loop = true;
     29 
     30  source.start(0);
     31 
     32  // nodeType decides which node in graph should be the source of recording.
     33  let node;
     34  if (nodeType == "source") {
     35    node = source;
     36  } else if (nodeType == "splitter") {
     37    const splitter = context.createChannelSplitter();
     38    source.connect(splitter);
     39    node = splitter;
     40  } else if (nodeType == "destination") {
     41    source.connect(context.destination);
     42    node = context.destination;
     43  }
     44  // Explicitly start offline context.
     45  if (contextType == "offline") {
     46    context.startRendering();
     47  }
     48 
     49  return node;
     50 }
     51 
     52 async function testRecord(source, mimeType) {
     53  const isOffline = source.context instanceof OfflineAudioContext;
     54  const recorder = new MediaRecorder(source, 0, {mimeType});
     55  is(recorder.mimeType, mimeType, "Mime type is set");
     56  const extendedMimeType = `${mimeType || "audio/ogg"}; codecs=opus`;
     57 
     58  recorder.onwarning = () => ok(false, "should not fire onwarning");
     59  recorder.onerror = () => ok(false, "should not fire onerror");
     60  if (!isOffline) {
     61    recorder.onstop = () => ok(false, "should not fire stop yet");
     62  }
     63 
     64  recorder.start(1000);
     65  is("recording", recorder.state, "state should become recording after calling start()");
     66  is(recorder.mimeType, mimeType, "Mime type is not changed by start()");
     67 
     68  await new Promise(r => recorder.onstart = r);
     69  is(recorder.mimeType, extendedMimeType, "Mime type is fully defined");
     70 
     71  const chunks = [];
     72  let {data} = await new Promise(r => recorder.ondataavailable = r);
     73  if (!isOffline) {
     74    is(recorder.state, "recording", "Expected to still be recording");
     75  }
     76  is(data.type, extendedMimeType, "Blob has fully defined mimetype");
     77  isnot(data.size, 0, "should get data and its length should be > 0");
     78  chunks.push(data);
     79 
     80  if (isOffline) {
     81    await new Promise(r => recorder.onstop = r);
     82    is(recorder.state, "inactive", "Offline context should end by itself");
     83  } else {
     84    is(recorder.state, "recording", "Expected to still be recording");
     85    recorder.stop();
     86    ({data} = await new Promise(r => recorder.ondataavailable = r));
     87    is(recorder.state, "inactive", "Expected to be inactive after last blob");
     88    isnot(data.size, 0, "should get data and its length should be > 0");
     89    chunks.push(data);
     90 
     91    await new Promise(r => recorder.onstop = r);
     92    is(recorder.state, "inactive", "state should remain inactive after stop event");
     93  }
     94  return new Blob(chunks, {type: chunks[0].type});
     95 }
     96 
     97 addLoadEvent(async () => {
     98  const src = setUpSource();
     99  let didThrow = false;
    100  try {
    101    new MediaRecorder(src);
    102  } catch (e) {
    103    didThrow = true;
    104  }
    105  ok(didThrow, "MediaRecorder(AudioNode) should be hidden behind a pref");
    106 
    107  await SpecialPowers.pushPrefEnv({set: [
    108      ["media.recorder.audio_node.enabled", true],
    109    ]});
    110 
    111  // Test with various context and source node types.
    112  for (const mimeType of [
    113    "audio/ogg",
    114    "audio/webm",
    115    "video/webm",
    116    "",
    117  ]) {
    118    for (const {context, node} of [
    119      {context: "", node: "source"},
    120      {context: "", node: "splitter"},
    121      {context: "offline", node: "destination"},
    122    ]) {
    123      info(`Testing recording ${context || "regular"} context and ${node} ` +
    124           `node with mimeType '${mimeType}'`);
    125      await testRecord(setUpSource(context, node), mimeType);
    126    }
    127  }
    128 
    129  SimpleTest.finish();
    130 });
    131 
    132 </script>
    133 </pre>
    134 </body>
    135 </html>