summaryrefslogtreecommitdiffstats
path: root/dom/media/test/test_streams_element_capture.html
blob: 8695dbf63b9494a55fc91b0d2ee299fbd9945e2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<!DOCTYPE HTML>
<html>
<head>
  <title>Test that a MediaStream captured from one element plays back in another</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
  <script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
const manager = new MediaTestManager();

function checkDrawImage(vout, msg) {
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  ctx.drawImage(vout, 0, 0);
  const imgData = ctx.getImageData(0, 0, 1, 1);
  is(imgData.data[3], 255, msg);
}

function maybeTodoGreaterThanOrEqual(a, b, msg) {
  const isExpected = a >= b;
  (isExpected ? ok : todo)(
    isExpected,
    `Got ${a}, expected at least ${b}; ${msg}`
  );
}

async function startTest(test, token) {
  manager.started(token);
  const v = document.createElement('video');
  const vout = document.createElement('video');

  v.token = token;
  v.id = "MediaDecoder";
  vout.id = "MediaStream";

  document.body.appendChild(vout);

  // Log events for debugging.
  const events = ["suspend", "play", "canplay", "canplaythrough", "loadstart", "loadedmetadata",
                "loadeddata", "playing", "ended", "error", "stalled", "emptied", "abort",
                "waiting", "pause"];
  function logEvent(e) {
    Log(token, `${e.target.id} got ${e.type}`);
  }
  for (const e of events) {
    v.addEventListener(e, logEvent);
    vout.addEventListener(e, logEvent);
  };

  v.src = test.name;
  v.preload = 'metadata';
  await new Promise(r => v.onloadedmetadata = r);

  const stream = v.mozCaptureStreamUntilEnded();
  vout.srcObject = stream;
  is(vout.srcObject, stream,
    `${token} set output element .srcObject correctly`);

  isnot(stream.getTracks().length, 0, `${token} results in some tracks`);
  const hadVideoTracks = stream.getVideoTracks().length >= 1;
  // Wait for the resource fetch algorithm to have run, so that the media
  // element is hooked up to the MediaStream and ready to go. If we don't do
  // this, we're not guaranteed to render the very first video frame, which
  // can make this test fail the drawImage test when a video resource only
  // contains one frame.
  await new Promise(r => vout.onloadstart = r);
  v.play();
  vout.play();

  await Promise.race([
    Promise.all([
      new Promise(r => vout.onended = r),
      new Promise(r => v.onended = r),
    ]),
    new Promise((res, rej) => vout.onerror = () => rej(new Error(vout.error.message))),
    new Promise((res, rej) => v.onerror = () => rej(new Error(v.error.message))),
  ]);

  let duration = test.duration;
  if (typeof(test.contentDuration) == "number") {
    duration = test.contentDuration;
  }
  if (duration) {
    // Unexpected results are tracked in bug 1839502
    maybeTodoGreaterThanOrEqual(vout.currentTime, duration,
      `${token} current time at end`);
  }
  is(vout.readyState, vout.HAVE_CURRENT_DATA,
    `${token} checking readyState`);
  ok(vout.ended, `${token} checking playback has ended`);
  if (hadVideoTracks) {
    ok(test.type.match(/^video/), `${token} is a video resource`);
    checkDrawImage(vout, `${token} checking video frame pixel has been drawn`);
  }
  vout.remove();
  removeNodeAndSource(v);
}

(async () => {
  SimpleTest.requestCompleteLog();
  SimpleTest.waitForExplicitFinish();
  await SpecialPowers.pushPrefEnv(
    { "set": [
      ["privacy.reduceTimerPrecision", false],
    ]});
  let tests = gPlayTests;
  // Filter out bug1377278.webm due to bug 1541401.
  tests = tests.filter(t => !t.name.includes("1377278"));
  // bug 1372457, bug 1526207 for drawImage -- restrict to codecs that can be
  // decoded in software.
  if (navigator.userAgent.includes("Android")) {
    tests = tests.filter(t => !t.name.includes("mp4"));
  }

  manager.runTests(tests, async (test, token) => {
    try {
      await startTest(test, token);
    } catch(e) {
      ok(false, `Caught exception for ${token}: ${e}`);
    }
    manager.finished(token);
  });
})();
</script>
</pre>
</body>
</html>