<!DOCTYPE html>
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
<html>
    <head>
        <title>Checks MediaSource.activeSourceBuffers and changes to selected/enabled track state</title>
        <script src="/resources/testharness.js"></script>
        <script src="/resources/testharnessreport.js"></script>
        <script src="mediasource-util.js"></script>
    </head>
    <body>
        <div id="log"></div>
        <script>
          // Audio / Video files supported by the user agent under test
          var subType = MediaSourceUtil.getSubType(MediaSourceUtil.AUDIO_ONLY_TYPE);
          var manifestFilenameAudio = subType + "/test-a-128k-44100Hz-1ch-manifest.json";
          var manifestFilenameVideo = subType + "/test-v-128k-320x240-30fps-10kfr-manifest.json";
          var manifestFilenameAV = subType + "/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr-manifest.json";

          mediasource_test(function(test, mediaElement, mediaSource)
          {
              mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'"));
              MediaSourceUtil.fetchManifestAndData(test, manifestFilenameAudio, function (typeAudio, dataAudio)
              {
                  var sourceBuffer = mediaSource.addSourceBuffer(typeAudio);
                  assert_equals(mediaSource.sourceBuffers.length, 1,
                    "sourceBuffers list contains one SourceBuffer");
                  assert_equals(mediaSource.activeSourceBuffers.length, 0,
                    "activeSourceBuffers is empty to start with");

                  test.expectEvent(mediaSource.activeSourceBuffers, "addsourcebuffer");
                  test.expectEvent(mediaElement, "loadedmetadata");
                  sourceBuffer.appendBuffer(dataAudio);

                  test.waitForExpectedEvents(function()
                  {
                      assert_equals(mediaSource.activeSourceBuffers.length, 1,
                        "activeSourceBuffers updated when media element is loaded");
                      assert_equals(mediaSource.activeSourceBuffers[0], sourceBuffer,
                        "activeSourceBuffers contains sourceBuffer when media element is loaded");
                      test.done();
                  });
              });
          }, "SourceBuffer added to activeSourceBuffers list when its only audio track gets loaded (and thus becomes enabled).");


          mediasource_test(function(test, mediaElement, mediaSource)
          {
              mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'"));
              MediaSourceUtil.fetchManifestAndData(test, manifestFilenameVideo, function (typeVideo, dataVideo)
              {
                  var sourceBuffer = mediaSource.addSourceBuffer(typeVideo);
                  assert_equals(mediaSource.sourceBuffers.length, 1,
                    "sourceBuffers list contains one SourceBuffer");
                  assert_equals(mediaSource.activeSourceBuffers.length, 0,
                    "activeSourceBuffers is empty to start with");

                  test.expectEvent(mediaSource.activeSourceBuffers, "addsourcebuffer");
                  test.expectEvent(mediaElement, "loadedmetadata");
                  sourceBuffer.appendBuffer(dataVideo);

                  test.waitForExpectedEvents(function()
                  {
                      assert_equals(mediaSource.activeSourceBuffers.length, 1,
                        "activeSourceBuffers updated when media element is loaded");
                      assert_equals(mediaSource.activeSourceBuffers[0], sourceBuffer,
                        "activeSourceBuffers contains sourceBuffer when media element is loaded");
                      test.done();
                  });
              });
          }, "SourceBuffer added to activeSourceBuffers list when its only video track gets loaded (and thus becomes selected).");

          function mediaSourceActiveSourceBufferOrderTest(addAudioFirst, appendAudioFirst)
          {
              mediasource_test(function(test, mediaElement, mediaSource)
              {
                  mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'"));
                  MediaSourceUtil.fetchManifestAndData(test, manifestFilenameAudio, function (typeAudio, dataAudio)
                  {
                      MediaSourceUtil.fetchManifestAndData(test, manifestFilenameVideo, function (typeVideo, dataVideo)
                      {
                          var sourceBufferAudio, sourceBufferVideo, expectedFirstSB, expectedSecondSB;
                          if (addAudioFirst) {
                              expectedFirstSB = sourceBufferAudio = mediaSource.addSourceBuffer(typeAudio);
                              expectedSecondSB = sourceBufferVideo = mediaSource.addSourceBuffer(typeVideo);
                          } else {
                              expectedFirstSB = sourceBufferVideo = mediaSource.addSourceBuffer(typeVideo);
                              expectedSecondSB = sourceBufferAudio = mediaSource.addSourceBuffer(typeAudio);
                          }

                          assert_equals(mediaSource.activeSourceBuffers.length, 0,
                            "activeSourceBuffers is empty to start with");
                          assert_equals(mediaSource.sourceBuffers.length, 2,
                            "sourceBuffers list contains both SourceBuffers");
                          assert_equals(mediaSource.sourceBuffers[0], expectedFirstSB,
                            "first SourceBuffer matches expectation");
                          assert_equals(mediaSource.sourceBuffers[1], expectedSecondSB,
                            "second SourceBuffer matches expectation");
                          test.expectEvent(mediaSource.activeSourceBuffers, "addsourcebuffer");
                          test.expectEvent(mediaSource.activeSourceBuffers, "addsourcebuffer");
                          test.expectEvent(mediaElement, "loadedmetadata");
                          if (appendAudioFirst) {
                              sourceBufferAudio.appendBuffer(dataAudio);
                              sourceBufferVideo.appendBuffer(dataVideo);
                          } else {
                              sourceBufferVideo.appendBuffer(dataVideo);
                              sourceBufferAudio.appendBuffer(dataAudio);
                          }

                          test.waitForExpectedEvents(function()
                          {
                              assert_equals(mediaSource.activeSourceBuffers.length, 2,
                                "activeSourceBuffers list updated when tracks are loaded");
                              assert_equals(mediaSource.activeSourceBuffers[0], mediaSource.sourceBuffers[0],
                                "first active SourceBuffer matches first SourceBuffer");
                              assert_equals(mediaSource.activeSourceBuffers[1], mediaSource.sourceBuffers[1],
                                "second active SourceBuffer matches second SourceBuffer");
                              test.done();
                          });
                      });
                  });
              },
              "Active SourceBuffers must appear in the same order as they appear in the sourceBuffers attribute: " +
                (addAudioFirst ? "audio is first sourceBuffer" : "video is first sourceBuffer") + ", " +
                (appendAudioFirst ? "audio media appended first" : "video media appended first"));
          }

          mediaSourceActiveSourceBufferOrderTest(true, true);
          mediaSourceActiveSourceBufferOrderTest(true, false);
          mediaSourceActiveSourceBufferOrderTest(false, true);
          mediaSourceActiveSourceBufferOrderTest(false, false);

          mediasource_test(function(test, mediaElement, mediaSource)
          {
              mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'"));
              MediaSourceUtil.fetchManifestAndData(test, manifestFilenameAudio, function (typeAudio, dataAudio)
              {
                  MediaSourceUtil.fetchManifestAndData(test, manifestFilenameVideo, function (typeVideo, dataVideo)
                  {
                      var sourceBufferAudio = mediaSource.addSourceBuffer(typeAudio);
                      var sourceBufferVideo = mediaSource.addSourceBuffer(typeVideo);

                      test.expectEvent(sourceBufferAudio.audioTracks, "addtrack");
                      test.expectEvent(sourceBufferVideo.videoTracks, "addtrack");
                      sourceBufferAudio.appendBuffer(dataAudio);
                      sourceBufferVideo.appendBuffer(dataVideo);

                      test.waitForExpectedEvents(function()
                      {
                          assert_equals(mediaSource.activeSourceBuffers.length, 2,
                            "activeSourceBuffers list updated when tracks are loaded");
                          assert_equals(sourceBufferAudio.audioTracks.length, 1,
                            "audio track list contains loaded audio track");
                          assert_equals(sourceBufferVideo.videoTracks.length, 1,
                            "video track list contains loaded video track");

                          test.expectEvent(mediaSource.activeSourceBuffers, "removesourcebuffer");
                          sourceBufferAudio.audioTracks[0].enabled = false;
                      });

                      test.waitForExpectedEvents(function()
                      {
                          assert_equals(mediaSource.activeSourceBuffers.length, 1,
                            "audio source buffer no longer in the activeSourceBuffers list");
                          assert_equals(mediaSource.activeSourceBuffers[0], sourceBufferVideo,
                            "activeSourceBuffers list only contains the video SourceBuffer");

                          test.expectEvent(mediaSource.activeSourceBuffers, "addsourcebuffer");
                          test.expectEvent(mediaSource.activeSourceBuffers, "removesourcebuffer");
                          sourceBufferAudio.audioTracks[0].enabled = true;
                          sourceBufferVideo.videoTracks[0].selected = false;
                      });

                      test.waitForExpectedEvents(function()
                      {
                          assert_equals(mediaSource.activeSourceBuffers.length, 1,
                            "video source buffer no longer in the activeSourceBuffers list");
                          assert_equals(mediaSource.activeSourceBuffers[0], sourceBufferAudio,
                            "activeSourceBuffers list only contains the audio SourceBuffer");
                          test.done();
                      });
                  });
              });
          }, "Active SourceBuffers list reflects changes to selected audio/video tracks associated with separate SourceBuffers.");


          mediasource_test(function(test, mediaElement, mediaSource)
          {
              mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'"));
              MediaSourceUtil.fetchManifestAndData(test, manifestFilenameAV, function (typeAV, dataAV)
              {
                  var sourceBuffer = mediaSource.addSourceBuffer(typeAV);

                  test.expectEvent(sourceBuffer.audioTracks, "addtrack");
                  test.expectEvent(sourceBuffer.videoTracks, "addtrack");
                  sourceBuffer.appendBuffer(dataAV);

                  test.waitForExpectedEvents(function()
                  {
                      assert_equals(mediaSource.activeSourceBuffers.length, 1,
                        "activeSourceBuffers list updated when tracks are loaded");
                      assert_equals(sourceBuffer.audioTracks.length, 1,
                        "audio track list contains loaded audio track");
                      assert_equals(sourceBuffer.videoTracks.length, 1,
                        "video track list contains loaded video track");

                      mediaSource.activeSourceBuffers.addEventListener("removesourcebuffer", test.unreached_func(
                        "Unexpected removal from activeSourceBuffers list"));
                      mediaSource.activeSourceBuffers.addEventListener("addsourcebuffer", test.unreached_func(
                        "Unexpected insertion in activeSourceBuffers list"));

                      // Changes should only trigger events at the
                      // AudioTrack/VideoTrack instance
                      test.expectEvent(sourceBuffer.audioTracks, "change");
                      sourceBuffer.audioTracks[0].enabled = false;
                  });

                  test.waitForExpectedEvents(function()
                  {
                      assert_equals(mediaSource.activeSourceBuffers.length, 1,
                        "activeSourceBuffers list unchanged");

                      test.expectEvent(sourceBuffer.videoTracks, "change");
                      sourceBuffer.audioTracks[0].enabled = true;
                      sourceBuffer.videoTracks[0].selected = false;
                  });

                  test.waitForExpectedEvents(function()
                  {
                      assert_equals(mediaSource.activeSourceBuffers.length, 1,
                        "activeSourceBuffers list unchanged");
                      test.done();
                  });
              });
          }, "Active SourceBuffers list ignores changes to selected audio/video tracks " +
            "that do not affect the activation of the SourceBuffer.");
        </script>
    </body>
</html>
