<!DOCTYPE html>
<!-- Copyright © 2019 Igalia. -->
<html>
<head>
    <title>Frame checking test for simple MSE playback.</title>
    <meta name="timeout" content="long">
    <meta name="charset" content="UTF-8">
    <link rel="author" title="Alicia Boya García" href="mailto:aboya@igalia.com">
    <script src="/resources/testharness.js"></script>
    <script src="/resources/testharnessreport.js"></script>
    <script src="mediasource-util.js"></script>
</head>
<body>
<div id="log"></div>
<canvas id="test-canvas"></canvas>
<script>
    function waitForEventPromise(element, event) {
        return new Promise(resolve => {
            function handler(ev) {
                element.removeEventListener(event, handler);
                resolve(ev);
            }
            element.addEventListener(event, handler);
        });
    }

    function appendBufferPromise(sourceBuffer, data) {
        sourceBuffer.appendBuffer(data);
        return waitForEventPromise(sourceBuffer, "update");
    }

    function readPixel(imageData, x, y) {
        return {
            r: imageData.data[4 * (y * imageData.width + x)],
            g: imageData.data[1 + 4 * (y * imageData.width + x)],
            b: imageData.data[2 + 4 * (y * imageData.width + x)],
            a: imageData.data[3 + 4 * (y * imageData.width + x)],
        };
    }

    function isPixelLit(pixel) {
        const threshold = 200; // out of 255
        return pixel.r >= threshold && pixel.g >= threshold && pixel.b >= threshold;
    }

    // The test video has a few gray boxes. Each box interval (1 second) a new box is lit white and a different note
    // is played. This test makes sure the right number of lit boxes and the right note are played at the right time.
    const totalBoxes = 7;
    const boxInterval = 1; // seconds

    const videoWidth = 320;
    const videoHeight = 240;
    const boxesY = 210;
    const boxSide = 20;
    const boxMargin = 20;
    const allBoxesWidth = totalBoxes * boxSide + (totalBoxes - 1) * boxMargin;
    const boxesX = new Array(totalBoxes).fill(undefined)
        .map((_, i) => (videoWidth - allBoxesWidth) / 2 + boxSide / 2 + i * (boxSide + boxMargin));

    // Sound starts playing A4 (440 Hz) and goes one chromatic note up with every box lit.
    // By comparing the player position to both the amount of boxes lit and the note played we can detect A/V
    // synchronization issues automatically.
    const noteFrequencies = new Array(1 + totalBoxes).fill(undefined)
        .map((_, i) => 440 * Math.pow(Math.pow(2, 1 / 12), i));

    // We also check the first second [0, 1) where no boxes are lit, therefore we start counting at -1 to do the check
    // for zero lit boxes.
    let boxesLitSoFar = -1;

    mediasource_test(async function (test, mediaElement, mediaSource) {
        const canvas = document.getElementById("test-canvas");
        const canvasCtx = canvas.getContext("2d");
        canvas.width = videoWidth;
        canvas.height = videoHeight;

        const videoData = await (await fetch("mp4/test-boxes-video.mp4")).arrayBuffer();
        const audioData = (await (await fetch("mp4/test-boxes-audio.mp4")).arrayBuffer());

        const videoSb = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.4d401f"');
        const audioSb = mediaSource.addSourceBuffer('audio/mp4; codecs="mp4a.40.2"');

        mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'"));
        mediaElement.addEventListener('ended', onEnded);
        mediaElement.addEventListener('timeupdate', onTimeUpdate);

        await appendBufferPromise(videoSb, videoData);
        await appendBufferPromise(audioSb, audioData);
        mediaSource.endOfStream();
        mediaElement.play();

        const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
        const source = audioCtx.createMediaElementSource(mediaElement);
        const analyser = audioCtx.createAnalyser();
        analyser.fftSize = 8192;
        source.connect(analyser);
        analyser.connect(audioCtx.destination);

        const freqDomainArray = new Float32Array(analyser.frequencyBinCount);

        function checkNoteBeingPlayed() {
            const expectedNoteFrequency = noteFrequencies[boxesLitSoFar];

            analyser.getFloatFrequencyData(freqDomainArray);
            const maxBin = freqDomainArray.reduce((prev, curValue, i) =>
                curValue > prev.value ? {index: i, value: curValue} : prev,
                {index: -1, value: -Infinity});
            const binFrequencyWidth = audioCtx.sampleRate / analyser.fftSize;
            const binFreq = maxBin.index * binFrequencyWidth;

            assert_true(Math.abs(expectedNoteFrequency - binFreq) <= binFrequencyWidth,
                `The note being played matches the expected one (boxes lit: ${boxesLitSoFar}, ${expectedNoteFrequency.toFixed(1)} Hz)` +
                `, found ~${binFreq.toFixed(1)} Hz`);
        }

        function countLitBoxesInCurrentVideoFrame() {
            canvasCtx.drawImage(mediaElement, 0, 0);
            const imageData = canvasCtx.getImageData(0, 0, videoWidth, videoHeight);
            const lights = boxesX.map(boxX => isPixelLit(readPixel(imageData, boxX, boxesY)));
            let litBoxes = 0;
            for (let i = 0; i < lights.length; i++) {
                if (lights[i])
                    litBoxes++;
            }
            for (let i = litBoxes; i < lights.length; i++) {
                assert_false(lights[i], 'After the first non-lit box, all boxes must non-lit');
            }
            return litBoxes;
        }

        function onTimeUpdate() {
            const graceTime = 0.5;
            if (mediaElement.currentTime >= (1 + boxesLitSoFar) * boxInterval + graceTime && boxesLitSoFar < totalBoxes) {
                assert_equals(countLitBoxesInCurrentVideoFrame(), boxesLitSoFar + 1, "Num of lit boxes:");
                boxesLitSoFar++;
                checkNoteBeingPlayed();
            }
        }

        function onEnded() {
            assert_equals(boxesLitSoFar, totalBoxes, "Boxes lit at video ended event");
            test.done();
        }
    }, "Test the expected frames are played at the expected times");
</script>
</body>
</html>
