Bug 1935611 - Fix libyuv/libpng link failed for loongarch64. r=glandium,tnikkel,ng
[gecko.git] / dom / canvas / test / test_capture_throttled.html
blob41cd93a6b96406cc8c1c1b0b1d3bb39450c36128
1 <!DOCTYPE HTML>
2 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
4 <title>Canvas2D test: CaptureStream() with throttled rAF</title>
6 <script src="/tests/SimpleTest/SimpleTest.js"></script>
7 <script src="captureStream_common.js"></script>
8 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
9 <body>
10 <script>
11 SimpleTest.waitForExplicitFinish();
12 SimpleTest.requestFlakyTimeout("Ensuring nothing happens until timing out with good margin");
14 // CaptureStreamTestHelper holding utility test functions.
15 const h = new CaptureStreamTestHelper2D();
17 async function measureRequestAnimationFrameRate() {
18 const frameRate = await new Promise(resolve => {
19 let start;
20 let count;
21 const tick = time => {
22 if (!start) {
23 start = time;
24 count = 0;
25 } else {
26 count += 1;
28 if (time - start > 1000) {
29 // One second has passed, break.
30 resolve(count / ((time - start) / 1000));
31 return;
33 window.requestAnimationFrame(tick);
35 window.requestAnimationFrame(tick);
36 });
37 return frameRate;
40 async function measureSetTimeoutRate() {
41 const start = performance.now();
42 const COUNT = 5;
43 for(let i = 0; i < COUNT; ++i) {
44 await new Promise(resolve => setTimeout(resolve, 0));
46 return COUNT / ((performance.now() - start) / 1000);
49 async function measureCanvasCaptureFrameRate(captureRate) {
50 // Canvas element captured by streams.
51 const c = h.createAndAppendElement('canvas', 'c');
53 // Since we are in a background tab, the video element won't get composited,
54 // so we cannot look for a frame count there. Instead we use RTCPeerConnection
55 // and RTCOutboundRtpStreamStats.framesEncoded.
56 const pc1 = new RTCPeerConnection();
57 const pc2 = new RTCPeerConnection();
59 // Add the canvas.captureStream track.
60 const ctx = c.getContext('2d');
61 const [track] = c.captureStream(captureRate).getTracks();
62 const sender = pc1.addTrack(track);
64 // Ice candidates signaling
65 for (const [local, remote] of [[pc1, pc2], [pc2, pc1]]) {
66 local.addEventListener("icecandidate", ({candidate}) => {
67 if (!candidate || remote.signalingState == "closed") {
68 return;
70 remote.addIceCandidate(candidate);
71 });
74 // Offer/Answer exchange
75 await pc1.setLocalDescription(await pc1.createOffer());
76 await pc2.setRemoteDescription(pc1.localDescription);
77 await pc2.setLocalDescription(await pc2.createAnswer());
78 await pc1.setRemoteDescription(pc2.localDescription);
80 // Wait for connection
81 while ([pc1, pc2].some(pc => pc.iceConnectionState == "new" ||
82 pc.iceConnectionState == "checking")) {
83 await Promise.any(
84 [pc1, pc2].map(p => new Promise(r => p.oniceconnectionstatechange = r)));
86 for (const [pc, name] of [[pc1, "pc1"], [pc2, "pc2"]]) {
87 ok(["connected", "completed"].includes(pc.iceConnectionState),
88 `${name} connection established (${pc.iceConnectionState})`);
91 // Draw to the canvas
92 const intervalMillis = 1000 / 60;
93 const getFrameCount = async () => {
94 const stats = await sender.getStats();
95 const outbound =
96 [...stats.values()].find(({type}) => type == "outbound-rtp");
97 return outbound?.framesEncoded ?? 0;
99 // Wait for frame count change to ensure sender is working.
100 while (await getFrameCount() == 0) {
101 h.drawColor(c, h.green);
102 await new Promise(resolve => setTimeout(resolve, intervalMillis));
104 const startFrameCount = await getFrameCount();
105 const start = performance.now();
106 let end = start;
107 while(end - start <= 1000) {
108 h.drawColor(c, h.green);
109 await new Promise(resolve => setTimeout(resolve, intervalMillis));
110 end = performance.now();
112 const framerate = (await getFrameCount() - startFrameCount) / ((end - start) / 1000);
113 pc1.close();
114 pc2.close();
115 return framerate;
118 (async () => {
119 // Disable background timer throttling so we can use setTimeout to draw to the
120 // canvas while the refresh driver is throttled.
121 await SpecialPowers.pushPrefEnv({
122 set: [
123 ["dom.timeout.enable_budget_timer_throttling", false],
124 ["dom.min_background_timeout_value", 0],
125 ["dom.min_background_timeout_value_without_budget_throttling", 0],
126 ["browser.link.open_newwindow", 3], // window.open in new tab
129 // Throttle the canvas' refresh driver by opening a new foreground tab
130 const foregroundTab = window.open("about:blank");
132 // Let the throttling take effect
133 await new Promise(r => setTimeout(r, 500));
135 const rAFRate = await measureRequestAnimationFrameRate();
136 ok(rAFRate < 5, `rAF framerate is at ${rAFRate} fps`);
138 const setTimeoutRate = await measureSetTimeoutRate();
139 ok(setTimeoutRate > 30, `setTimeout rate is at ${setTimeoutRate} tps`);
141 const autoRate = await measureCanvasCaptureFrameRate();
142 ok(autoRate > 5, `captureStream() framerate is at ${autoRate} fps`);
144 const cappedRate = await measureCanvasCaptureFrameRate(10);
145 ok(cappedRate > 5, `captureStream(10) framerate is at ${cappedRate} fps`);
147 foregroundTab.close();
148 SimpleTest.finish();
149 })();
150 </script>