<!DOCTYPE HTML>
<html>
<head>
  <title>MSE: basic functionality</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="text/javascript" src="mediasource.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">

SimpleTest.waitForExplicitFinish();

runWithMSE(async (ms, v) => {
  SimpleTest.doesThrow(() => new SourceBuffer, "new SourceBuffer should fail");
  SimpleTest.doesThrow(() => new SourceBufferList, "new SourceBufferList direct should fail");

  ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
  is(ms.readyState, "closed", "New MediaSource must be in closed state");

  // Wrapper creation, tests for leaks.
  SpecialPowers.wrap(ms);

  // Set an expando to force wrapper creation, tests for leaks.
  ms.foo = null;

  ok(URL.createObjectURL(ms), "Create an objectURL from the MediaSource");

  let loadedmetadataCount = 0;
  let updatestartCount = 0;
  let updateendCount = 0;
  let updateCount = 0;

  await once(ms, "sourceopen");
  ok(true, "Receive a sourceopen event");
  is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
  const sb = ms.addSourceBuffer("video/mp4");
  ok(sb, "Create a SourceBuffer");
  is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
  is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
  is(ms.activeSourceBuffers.length, 0, "MediaSource.activeSourceBuffers is expected length");

  sb.appendBuffer(new Uint8Array(await fetchWithXHR("bipbop/bipbop2s.mp4")));
  is(sb.updating, true, "SourceBuffer.updating is expected value after appendBuffer");

  sb.addEventListener("update", () => {
    is(sb.updating, false, "SourceBuffer.updating is expected value in update event");
    updateCount++;
    /* Ensure that we endOfStream on the first update event only as endOfStream can
       raise more if the duration of the last buffered range and the intial duration
       differ. See bug 1065207 */
    if (updateCount == 1) {
      ms.endOfStream();
    }
  });

  sb.addEventListener("updatestart", () => updatestartCount++);

  sb.addEventListener("updateend", () => {
    is(ms.activeSourceBuffers[0], sb, "SourceBuffer in active list matches our SourceBuffer");
    is(sb.updating, false, "SourceBuffer.updating is expected value in updateend event");
    updateendCount++;
    v.play();
  });

  ms.addEventListener("sourceended", () => {
    ok(true, "Receive a sourceended event");
    is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
  });

  v.addEventListener("loadedmetadata", () => loadedmetadataCount++);

  await once(v, "ended");
  // The bipbop video doesn't start at 0. The old MSE code adjust the
  // timestamps and ignore the audio track. The new one doesn't.
  isfuzzy(v.duration, 1.696, 0.166, "Video has correct duration");
  isfuzzy(v.currentTime, 1.696, 0.166, "Video has correct duration");
  // XXX: 2 update events can be received dueto duration differences, see bug 1065207.
  ok(updateCount == 1 || updateCount == 2, "update event received");
  ok(updateendCount == 1 || updateendCount == 2, "updateend event received");
  ok(updatestartCount == 1 || updatestartCount == 2, "updatestart event received");
  is(loadedmetadataCount, 1, "loadedmetadata event received");
  SimpleTest.finish();
});

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