<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Clone a video track.</title>
    <script src="../../resources/gc.js"></script>
    <script src="../../resources/testharness.js"></script>
    <script src="../../resources/testharnessreport.js"></script>
</head>
<body>
    <video id='video1' autoplay playsinline></video>
    <br>
    <video id='video2' autoplay playsinline></video>
    <br>
    <video id='video3' autoplay playsinline></video>
    <script>
    promise_test(async (t) => {
        let constraints = { video: { width: 160 } };
        const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 160 } });
        assert_equals(stream.getVideoTracks()[0].getConstraints().width, 160);

        const streamClone = stream.clone();

        video1.srcObject = stream;
        video2.srcObject = streamClone;

        const videoTrack = stream.getVideoTracks()[0];
        const videoTrackClone = streamClone.getVideoTracks()[0];

        assert_equals(videoTrack.enabled, videoTrackClone.enabled);
        videoTrack.enabled = false;
        assert_true(videoTrackClone.enabled);
        videoTrack.enabled = true;

        await videoTrackClone.applyConstraints({width: 640});
        test(() => {
            assert_equals(videoTrackClone.getSettings().width, 640);
            assert_equals(videoTrack.getSettings().width, 160);
        }, "Check cloned track settings after applying width constraints");

        const videoTrackClone2 = videoTrackClone.clone();
        await videoTrackClone.applyConstraints({width: 1280});
        video3.srcObject = new MediaStream([videoTrackClone2]);
        test(() => {
            assert_equals(videoTrackClone.getSettings().width, 1280);
            assert_equals(videoTrackClone2.getSettings().width, 640);
        }, "Check cloned track settings after applying width constraint to original track");
    }, "Setup for width test");

    promise_test(async (t) => {
        const stream = await navigator.mediaDevices.getUserMedia({ video: { height: 100 } });
        const streamClone = stream.clone();

        video1.srcObject = stream;
        video2.srcObject = streamClone;

        const videoTrack = stream.getVideoTracks()[0];
        const videoTrackClone = streamClone.getVideoTracks()[0];

        assert_equals(videoTrack.enabled, videoTrackClone.enabled);
        videoTrack.enabled = false;
        assert_true(videoTrackClone.enabled);
        videoTrack.enabled = true;

        await videoTrackClone.applyConstraints({height: 200});
        test(() => {
            assert_equals(videoTrackClone.getSettings().height, 200);
            assert_equals(videoTrack.getSettings().height, 100);
        }, "Check cloned track settings after applying height constraints");

        const videoTrackClone2 = videoTrackClone.clone();
        await videoTrackClone.applyConstraints({height: 400});
        video3.srcObject = new MediaStream([videoTrackClone2]);
        test(() => {
            assert_equals(videoTrackClone.getSettings().height, 400);
            assert_equals(videoTrackClone2.getSettings().height, 200);
        }, "Check cloned track settings after applying height constraints to original track");
    }, "Setup for height test");

    promise_test(async (t) => {
        const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 100, height: 100 } });
        const streamClone = stream.clone();

        video1.srcObject = stream;
        video2.srcObject = streamClone;

        const videoTrack = stream.getVideoTracks()[0];
        const videoTrackClone = streamClone.getVideoTracks()[0];

        assert_equals(videoTrack.enabled, videoTrackClone.enabled);
        videoTrack.enabled = false;
        assert_true(videoTrackClone.enabled);
        videoTrack.enabled = true;

        await videoTrackClone.applyConstraints({width: 100, height: 200});
        test(() => {
            assert_equals(videoTrackClone.getSettings().width, 100);
            assert_equals(videoTrackClone.getSettings().height, 200);
            assert_equals(videoTrack.getSettings().height, 100);
            assert_equals(videoTrack.getSettings().width, 100);
        }, "Check cloned track settings after applying width+height constraints");

        const videoTrackClone2 = videoTrackClone.clone();
        await videoTrackClone.applyConstraints({width: 400, height: 200});
        video3.srcObject = new MediaStream([videoTrackClone2]);
        test(() => {
            assert_equals(videoTrackClone.getSettings().width, 400);
            assert_equals(videoTrackClone.getSettings().height, 200);
            assert_equals(videoTrackClone2.getSettings().width, 100);
            assert_equals(videoTrackClone2.getSettings().height, 200);
        }, "Check cloned track settings after applying width+height constraints to original track");
    }, "Setup for width+height test");

    promise_test(async (t) => {
        const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 100, height: 100 } });
        const streamClone = stream.clone();

        video1.srcObject = streamClone;
        stream.getVideoTracks()[0].stop();

        await video1.play();
        assert_equals(video1.videoWidth, 100);
    }, "Stopping a track should not stop its clone");

    promise_test(async (t) => {
        const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 100, height: 100 } });
        const streamClone = stream.clone();

        video1.srcObject = stream;
        streamClone.getVideoTracks()[0].stop();

        await video1.play();
        assert_equals(video1.videoWidth, 100);
    }, "Stopping a cloned track should not stop the original track");

    promise_test(async (t) => {
        const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 100, height: 100 } });
        stream.clone().getVideoTracks()[0].stop();
        gc();

        video1.srcObject = stream;

        await video1.play();
        assert_equals(video1.videoWidth, 100);
    }, "Collecting a cloned track should not stop the original track");
    </script>
</body>
</html>
