Backed out changeset b462e7b742d8 (bug 1908261) for causing multiple reftest failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / conformance / extensions / webgl-webcodecs-video-frame.html
blobf0e413e2f6f474ccb6bea2e03b885130e0dff57b
1 <!--
2 Copyright (c) 2021 The Khronos Group Inc.
3 Use of this source code is governed by an MIT-style license that can be
4 found in the LICENSE.txt file.
5 -->
7 <!DOCTYPE html>
8 <html>
10 <head>
11 <meta charset="UTF-8">
12 <link rel="stylesheet" href="../../resources/js-test-style.css" />
13 <script src="../../js/js-test-pre.js"></script>
14 <script src="../../js/webgl-test-utils.js"></script>
15 <script src="../../js/tests/out-of-bounds-test.js"></script>
16 <script src="../../../../extensions/proposals/WEBGL_webcodecs_video_frame/webgl_webcodecs_video_frame.js"></script>
17 <style>
18 canvas {
19 padding: 10px;
20 background: gold;
23 button {
24 background-color: #555555;
25 border: none;
26 color: white;
27 padding: 15px 32px;
28 width: 150px;
29 text-align: center;
30 display: block;
31 font-size: 16px;
33 </style>
34 </head>
36 <body>
37 <canvas id="src" width="640" height="480"></canvas>
38 <canvas id="dst" width="640" height="480"></canvas>
39 <p id="info"></p>
40 <div id="description"></div>
41 <div id="console"></div>
42 <script>
43 "use strict";
44 description("Test of importing Videoframe from Webcodecs to Webgl");
46 const kIsRunningTest = true;
47 const kMaxFrame = 10;
48 const kTestPixel = [255, 128, 0, 255];
49 // Sum of pixel difference of R/G/B channel. Use to decide whether a
50 // pixel is matched with another.
51 const codec_string = "vp09.00.51.08.00";
53 let wtu = WebGLTestUtils;
54 let cnv = document.getElementById("src");
55 let src_width = cnv.width;
56 let src_height = cnv.height;
57 let src_color = "rgba(" + kTestPixel[0].toString() + "," + kTestPixel[1].toString() + ","
58 + kTestPixel[2].toString() + "," + kTestPixel[3].toString() + ")";
59 let frame_counter = 0;
60 let pixelCompareTolerance = 5;
62 function getQueryVariable(variable) {
63 var query = window.location.search.substring(1);
64 var vars = query.split("&");
65 for (var i = 0; i < vars.length; i++) {
66 var pair = vars[i].split("=");
67 if (pair[0] == variable) { return pair[1]; }
69 return false;
72 let th = parseInt(getQueryVariable('threshold'));
73 if (!isNaN(th))
74 pixelCompareTolerance = th;
76 async function startDrawing() {
77 let cnv = document.getElementById("src");
78 var ctx = cnv.getContext('2d', { alpha: false });
80 ctx.fillStyle = src_color;
81 let drawOneFrame = function (time) {
82 ctx.fillStyle = src_color;
83 ctx.fillRect(0, 0, src_width, src_height);
84 window.requestAnimationFrame(drawOneFrame);
86 window.requestAnimationFrame(drawOneFrame);
89 function captureAndEncode(processChunk) {
90 let cnv = document.getElementById("src");
91 let fps = 60;
92 let pending_outputs = 0;
93 let stream = cnv.captureStream(fps);
94 let processor = new MediaStreamTrackProcessor(stream.getVideoTracks()[0]);
96 const init = {
97 output: (chunk) => {
98 testPassed("Encode frame successfully.");
99 pending_outputs--;
100 processChunk(chunk);
102 error: (e) => {
103 testFailed("Failed to encode frame.");
104 finishTest();
105 vtr.stop();
109 const config = {
110 codec: codec_string,
111 width: cnv.width,
112 height: cnv.height,
113 bitrate: 10e6,
114 framerate: fps,
117 let encoder = new VideoEncoder(init);
118 encoder.configure(config);
120 const frame_reader = processor.readable.getReader();
121 frame_reader.read().then(function processFrame({done, value}) {
122 if (done)
123 return;
125 if (pending_outputs > 30) {
126 console.log("drop this frame");
127 // Too many frames in flight, encoder is overwhelmed
128 // let's drop this frame.
129 value.close();
130 frame_reader.read().then(processFrame);
131 return;
134 if(frame_counter == kMaxFrame) {
135 frame_reader.releaseLock();
136 processor.readable.cancel();
137 value.close();
138 return;
141 frame_counter++;
142 pending_outputs++;
143 const insert_keyframe = (frame_counter % 150) == 0;
144 encoder.encode(value, { keyFrame: insert_keyframe });
146 frame_reader.read().then(processFrame);
150 function startDecodingAndRendering(cnv, handleFrame) {
151 const init = {
152 output: handleFrame,
153 error: (e) => {
154 testFailed("Failed to decode frame.");
155 finishTest();
159 const config = {
160 codec: codec_string,
161 codedWidth: cnv.width,
162 codedHeight: cnv.height,
163 acceleration: "deny",
167 let decoder = new VideoDecoder(init);
168 decoder.configure(config);
169 return decoder;
172 function isFramePixelMatched(gl, th_per_pixel = pixelCompareTolerance) {
173 WebGLTestUtils.checkCanvasRect(gl, 0, 0, src_width, src_width, kTestPixel, "should be orange", pixelCompareTolerance)
176 function main() {
177 if (!("VideoEncoder" in window)) {
178 testPassed("WebCodecs API is not supported.");
179 finishTest();
180 return;
182 let cnv = document.getElementById("dst");
184 let webgl_webcodecs_test_context = {
185 maxFrameTested: kMaxFrame,
186 displayed_frame: 0,
187 isFramePixelMatched: isFramePixelMatched,
188 testFailed: testFailed,
189 testPassed: testPassed,
190 finishTest: finishTest
192 setTestMode(webgl_webcodecs_test_context);
193 let handleFrame = requestWebGLVideoFrameHandler(cnv);
194 if (handleFrame === null) {
195 finishTest();
196 return;
199 startDrawing();
200 let decoder = startDecodingAndRendering(cnv, handleFrame);
201 captureAndEncode((chunk) => {
202 decoder.decode(chunk);
206 document.body.onload = main;
207 </script>
209 </body>
211 </html>