<!doctype html><!-- webkit-test-runner [ WebRTCRemoteVideoFrameEnabled=true ] -->
<html>
    <head>
        <meta charset="utf-8">
        <title>Testing basic video exchange from offerer to receiver</title>
        <script src="../resources/testharness.js"></script>
        <script src="../resources/testharnessreport.js"></script>
    </head>
    <body>
        <video id="video" autoplay=""></video>
        <canvas id="canvas" width="640" height="480"></canvas>
        <script src ="routines.js"></script>
        <script>
video = document.getElementById("video");
canvas = document.getElementById("canvas");

function grabFrameData(x, y, w, h)
{
    canvas.width = video.videoWidth;
    canvas.height = video.videoHeight;

    canvas.getContext('2d').drawImage(video, x, y, w, h, x, y, w, h);
    return canvas.getContext('2d').getImageData(x, y, w, h).data;
}

function testImage()
{
    const data = grabFrameData(10, 325, 250, 1);

    var index = 20;
    assert_true(data[index] < 100);
    assert_true(data[index + 1] < 100);
    assert_true(data[index + 2] < 100);

    index = 80;
    assert_true(data[index] > 200);
    assert_true(data[index + 1] > 200);
    assert_true(data[index + 2] > 200);

    index += 80;
    assert_true(data[index] > 200);
    assert_true(data[index + 1] > 200);
    assert_true(data[index + 2] < 100);
}

var pc1, pc2;
promise_test(async (test) => {
    if (window.testRunner)
        testRunner.setUserMediaPermission(true);

    const localStream = await navigator.mediaDevices.getUserMedia({video: {advanced: [{width:{min:640}}, {height:{min:480} } ]}});
    const localStream2 = new MediaStream([localStream.getVideoTracks()[0]]); 
    if (window.internals)
        assert_true(internals.pageMediaState().includes('HasActiveVideoCaptureDevice'), "Unexpected HasActiveVideoCaptureDevice");
    const stream = await new Promise((resolve, reject) => {
        createConnections((firstConnection) => {
            pc1 = firstConnection;
            const sender = firstConnection.addTrack(localStream.getVideoTracks()[0]);
            sender.setStreams(localStream, localStream2);
        }, (secondConnection) => {
            pc2 = secondConnection;
            secondConnection.ontrack = (trackEvent) => {
                assert_true(trackEvent.track instanceof MediaStreamTrack);
                assert_true(trackEvent.receiver instanceof RTCRtpReceiver);
                assert_true(Array.isArray(trackEvent.streams), "Array.isArray() should return true");
                assert_true(Object.isFrozen(trackEvent.streams), "Object.isFrozen() should return true");
                assert_equals(trackEvent.streams.length, 2);
                assert_equals(trackEvent.streams[0].id, localStream.id, "first stream id");
                assert_equals(trackEvent.streams[1].id, localStream2.id, "second stream id");
                assert_equals(trackEvent.track.id, localStream.getVideoTracks()[0].id);
                assert_equals(trackEvent.track, trackEvent.streams[0].getVideoTracks()[0]);
                resolve(trackEvent.streams[0]);
            };
        });
        setTimeout(() => reject("Test timed out"), 5000);
    });

    video.srcObject = stream;
    await video.play();

    testImage();

    let settings = stream.getVideoTracks()[0].getSettings();
    assert_equals(settings.width, 640, "remote track settings width");
    assert_equals(settings.height, 480, "remote track settings height");
    assert_equals(settings.aspectRatio, 640 / 480, "remote track settings aspectRatio");

    let counter = 0;
    while (++counter < 100 && settings.frameRate < 5) {
        await new Promise(resolve => setTimeout(resolve, 50));
        settings = stream.getVideoTracks()[0].getSettings();
    }
    assert_greater_than(settings.frameRate, 5 ,"remote track settings height");

}, "Basic video exchange");

function getCircleImageData()
{
    return grabFrameData(450, 100, 150, 100);
}

async function checkVideoIsUpdated(shouldBeUpdated, count, referenceData)
{
    if (count === undefined)
        count = 0;
    else if (count >= 20)
        return Promise.reject("checkVideoIsUpdated timed out :" + shouldBeUpdated + " " + count);

    if (referenceData === undefined)
        referenceData = getCircleImageData();

    await waitFor(200);
    const newData = getCircleImageData();

    if (shouldBeUpdated === (JSON.stringify(referenceData) !== JSON.stringify(newData)))
        return;

    await checkVideoIsUpdated(shouldBeUpdated, ++count, newData);
}

promise_test(async (test) => {
    const sender = pc1.getSenders()[0];
    let p = sender.getParameters();
    p.encodings[0].active = false;
    await sender.setParameters(p);

    assert_false(sender.getParameters().encodings[0].active, "encodings[0].active should be false");

    await checkVideoIsUpdated(false);
}, "Call setParameters to disable sending a given encoding");

promise_test(async (test) => {
    const sender = pc1.getSenders()[0];
    let p = sender.getParameters();
    p.encodings[0].active = true;
    await sender.setParameters(p);

    assert_true(sender.getParameters().encodings[0].active, "encodings[0].active should be true");

    await checkVideoIsUpdated(true);
}, "Call setParameters to reenable sending a given encoding");

promise_test(async (test) => {
    const sender = pc1.getSenders()[0];
    let p = sender.getParameters();
    p.encodings[0].scaleResolutionDownBy = 2;
    await sender.setParameters(p);

    assert_equals(sender.getParameters().encodings[0].scaleResolutionDownBy, 2, "encodings[0].scaleResolutionDownBy should be 2");
    assert_equals(video.videoWidth, 640);
    assert_equals(video.videoHeight, 480);

    let counter = 0;
    while (++counter < 50 && video.videoWidth == 640)
        await waitFor(200);

    assert_equals(video.videoWidth, 320);
    assert_equals(video.videoHeight, 240);
}, "Call setParameters to reduce size by two");
        </script>
    </body>
</html>
