<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>A recorded muted audio track should produce silence</title>
    <script src="/resources/testharness.js"></script>
    <script src="/resources/testharnessreport.js"></script>
</head>
<body>
    <video id="video1" controls></video>
    <video id="video2" controls></video>
    <video id="video3" controls></video>
    <canvas id="canvas3" width="320" height="240"></canvas>
    <script>
function setupAudioContext(context, streamOrVideo)
{
    var sourceNode = streamOrVideo instanceof MediaStream ? context.createMediaStreamSource(streamOrVideo) : context.createMediaElementSource(streamOrVideo);

    var analyser = context.createAnalyser();
    var gain = context.createGain();

    analyser.fftSize = 2048;
    analyser.smoothingTimeConstant = 0;
    analyser.minDecibels = -100;
    analyser.maxDecibels = 0;
    gain.gain.value = 0;

    sourceNode.connect(analyser);
    analyser.connect(gain);
    gain.connect(context.destination);

    return analyser;
}

function analyseAudio(analyser, duration, context)
{
    return new Promise((resolve, reject) => {
       var results = { heardHum: false, heardBip: false, heardBop: false, heardNoise: false };

       function analyse() {
           var freqDomain = new Uint8Array(analyser.frequencyBinCount);
           analyser.getByteFrequencyData(freqDomain);

           var hasFrequency = expectedFrequency => {
                var bin = Math.floor(expectedFrequency * analyser.fftSize / context.sampleRate);
                return bin < freqDomain.length && freqDomain[bin] >= 150;
           };

           if (!results.heardHum)
                results.heardHum = hasFrequency(150);

           if (!results.heardBip)
               results.heardBip = hasFrequency(1500);

           if (!results.heardBop)
                results.heardBop = hasFrequency(500);

           if (!results.heardNoise)
                results.heardNoise = hasFrequency(3000);

           if (results.heardHum && results.heardBip && results.heardBop && results.heardNoise)
                done();
        };

       function done() {
            clearTimeout(timeout);
            clearInterval(interval);

            resolve(results);
       }

        var timeout = setTimeout(done, 3 * duration);
        var interval = setInterval(analyse, duration / 30);
        analyse();
    });
}

function waitFor(duration)
{
    return new Promise((resolve) => setTimeout(resolve, duration));
}

async function doHumAnalysis(streamOrVideo, expected)
{
    let context = new AudioContext();
    let analyser = setupAudioContext(context, streamOrVideo);
    for (var cptr = 0; cptr < 20; cptr++) {
        const results = await analyseAudio(analyser, 200, context);
        if (results.heardHum === expected) {
            await context.close();
            return true;
        }
        await waitFor(50);
    }
    await context.close();
    return false;
}

function isVideoBlack(canvas, video, startX, startY, grabbedWidth, grabbedHeight)
{
    canvas.width = video.videoWidth;
    canvas.height = video.videoHeight;
    if (!grabbedHeight) {
        startX = 10;
        startY = 10;
        grabbedWidth = canvas.width - 20;
        grabbedHeight = canvas.height - 20;
    }

    canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);

    imageData = canvas.getContext('2d').getImageData(startX, startY, grabbedWidth, grabbedHeight);
    data = imageData.data;
    for (var cptr = 0; cptr < grabbedWidth * grabbedHeight; ++cptr) {
        // Approximatively black pixels.
        if (data[4 * cptr] > 30 || data[4 * cptr + 1] > 30 || data[4 * cptr + 2] > 30)
            return false;
    }
    return true;
}

async function checkVideoBlack(expected, canvas, video, errorMessage, counter)
{
    if (isVideoBlack(canvas, video) === expected)
        return Promise.resolve();

    if (counter === undefined)
        counter = 0;
    if (counter > 100) {
        if (!errorMessage)
            errorMessage = "checkVideoBlack timed out expecting " + expected;
        return Promise.reject(errorMessage);
    }

    await waitFor(50);
    return checkVideoBlack(expected, canvas, video, errorMessage, ++counter);
}

promise_test(async (test) => {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false });

    const localTrack = stream.getAudioTracks()[0];
    localTrack.enabled = false;
    setTimeout(() => localTrack.enabled = false, 0);
    const recorder = new MediaRecorder(stream);
    const dataPromise = new Promise(resolve => recorder.ondataavailable = (e) => resolve(e.data));

    recorder.start();
    await waitFor(1000);
    recorder.stop();
    const blob = await dataPromise;

    const url = URL.createObjectURL(blob);
    video1.src = url;
    await video1.play();

    assert_greater_than(video1.duration, 0.5);

    const results = await doHumAnalysis(video1, false); 
    assert_true(results, "Should not hear hum");

    URL.revokeObjectURL(url);
}, "Recording a muted audio track should produce silence");

promise_test(async (test) => {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });

    const localTrack = stream.getAudioTracks()[0];
    setTimeout(() => localTrack.enabled = false, 50);
    const recorder = new MediaRecorder(stream);
    const dataPromise = new Promise(resolve => recorder.ondataavailable = (e) => resolve(e.data));

    recorder.start();
    await waitFor(1000);
    recorder.stop();
    const blob = await dataPromise;

    const url = URL.createObjectURL(blob);
    video2.src = url;
    await video2.play();

    assert_greater_than(video2.duration, 0.5);

    const results = await doHumAnalysis(video2, false); 
    assert_true(results, "Should not hear hum");

    URL.revokeObjectURL(url);
}, "Muting an audio track should record silence");

promise_test(async (test) => {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });

    const localTrack = stream.getVideoTracks()[0];
    setTimeout(() => localTrack.enabled = false, 50);
    const recorder = new MediaRecorder(stream);
    const dataPromise = new Promise(resolve => recorder.ondataavailable = (e) => resolve(e.data));

    recorder.start();
    await waitFor(1000);
    recorder.stop();
    const blob = await dataPromise;

    const url = URL.createObjectURL(blob);
    video3.src = url;
    await video3.play();

    assert_greater_than(video3.duration, 0.5);

    const result = await checkVideoBlack(true, canvas3, video3, "muted video should produce black frames");

    URL.revokeObjectURL(url);
}, "Muting a video track should produce black frames");

    </script>
</body>
</html>
