Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: content/test/data/media/getusermedia-depth-capture.html

Issue 2476693002: WebGL & 16-bit video stream: upload to FLOAT texture. (Closed)
Patch Set: Rebase after crrev.com/2527343002 land. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 <html> 1 <html>
2 <head> 2 <head>
3 <script type="text/javascript" src="webrtc_test_utilities.js"></script> 3 <script type="text/javascript" src="webrtc_test_utilities.js"></script>
4 <script type="text/javascript" src="depth_stream_test_utilities.js"></script> 4 <script type="text/javascript" src="depth_stream_test_utilities.js"></script>
5 <script type="text/javascript"> 5 <script type="text/javascript">
6 6
7 function cubemapFaces(gl) {
8 return [gl.TEXTURE_CUBE_MAP_POSITIVE_X,
9 gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
10 gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
11 gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
12 gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
13 gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
14 }
15
7 $ = function(id) { 16 $ = function(id) {
8 return document.getElementById(id); 17 return document.getElementById(id);
9 }; 18 };
10 19
11 setAllEventsOccuredHandler(function() { 20 setAllEventsOccuredHandler(function() {
12 reportTestSuccess(); 21 reportTestSuccess();
13 }); 22 });
14 23
15 // testVideoToImageBitmap is a layout test that we run here because 24 // testVideoToImageBitmap and the tests below are layout tests that we
16 // it requires --use-fake-device-for-media-capture. 25 // run here because they require --use-fake-device-for-media-capture.
17 function getDepthStreamAndCallCreateImageBitmap() { 26 function getDepthStreamAndCallCreateImageBitmap() {
18 console.log('Calling getDepthStreamAndCallCreateImageBitmap'); 27 console.log('Calling getDepthStreamAndCallCreateImageBitmap');
19 getFake16bitStream().then(function(stream) { 28 getFake16bitStream().then(function(stream) {
20 detectVideoInLocalView1(stream, function() { 29 detectVideoInLocalView1(stream, function() {
21 testVideoToImageBitmap('local-view-1', function() { 30 testVideoToImageBitmap('local-view-1', function() {
22 stream.getVideoTracks()[0].stop(); 31 stream.getVideoTracks()[0].stop();
23 waitForVideoToStop('local-view-1'); 32 waitForVideoToStop('local-view-1');
24 }, failedCallback); 33 }, failedCallback);
25 }); 34 });
26 }, 35 },
27 failedCallback); 36 failedCallback);
28 } 37 }
29 38
39 function depthStreamToRGBAUint8Texture() {
40 console.log('Calling depthStreamToRGBAUint8Texture');
41 getFake16bitStream().then(function(stream) {
42 detectVideoInLocalView1(stream, function() {
43 testVideoToRGBA8Texture('local-view-1', function(skip_info) {
44 if (skip_info) {
45 console.log("SKIP depthStreamToRGBAUint8Texture: " +
46 skip_info);
47 }
48 stream.getVideoTracks()[0].stop();
49 waitForVideoToStop('local-view-1');
50 }, failedCallback);
51 });
52 },
53 failedCallback);
54 }
55
56 function depthStreamToRGBAFloatTexture() {
57 console.log('Calling depthStreamToRGBAFloatTexture');
58 getFake16bitStream().then(function(stream) {
59 detectVideoInLocalView1(stream, function() {
60 testVideoToRGBA32FTexture('local-view-1', function(skip_info) {
61 if (skip_info) {
62 console.log("SKIP depthStreamToRGBAFloatTexture: " +
63 skip_info);
64 }
65 stream.getVideoTracks()[0].stop();
66 waitForVideoToStop('local-view-1');
67 }, failedCallback);
68 });
69 },
70 failedCallback);
71 }
72
30 function failedCallback(error) { 73 function failedCallback(error) {
31 failTest('GetUserMedia call failed with error name ' + error.name); 74 failTest('GetUserMedia call failed with error name ' + error.name);
32 } 75 }
33 76
34 function attachMediaStream(stream, videoElement) { 77 function attachMediaStream(stream, videoElement) {
35 var localStreamUrl = URL.createObjectURL(stream); 78 var localStreamUrl = URL.createObjectURL(stream);
36 $(videoElement).src = localStreamUrl; 79 $(videoElement).src = localStreamUrl;
37 } 80 }
38 81
39 function detectVideoInLocalView1(stream, callback) { 82 function detectVideoInLocalView1(stream, callback) {
40 attachMediaStream(stream, 'local-view-1'); 83 attachMediaStream(stream, 'local-view-1');
41 detectVideoPlaying('local-view-1', callback); 84 detectVideoPlaying('local-view-1', callback);
42 } 85 }
86
87 function testVideoToImageBitmap(videoElementName, success, error) {
88 var bitmaps = {};
89 var video = $(videoElementName);
90 var canvas = document.createElement('canvas');
91 canvas.width = 96;
92 canvas.height = 96;
93 document.body.appendChild(canvas);
94 var p1 = createImageBitmap(video).then(function(imageBitmap) {
95 return runImageBitmapTest(imageBitmap, canvas, false); });
96 var p2 = createImageBitmap(video,
97 {imageOrientation: "none", premultiplyAlpha: "premultiply"}).then(
98 function(imageBitmap) {
99 return runImageBitmapTest(imageBitmap, canvas, false); });
100 var p3 = createImageBitmap(video,
101 {imageOrientation: "none", premultiplyAlpha: "default"}).then(
102 function(imageBitmap) {
103 return runImageBitmapTest(imageBitmap, canvas, false); });
104 var p4 = createImageBitmap(video,
105 {imageOrientation: "none", premultiplyAlpha: "none"}).then(
106 function(imageBitmap) {
107 return runImageBitmapTest(imageBitmap, canvas, false); });
108 var p5 = createImageBitmap(video,
109 {imageOrientation: "flipY", premultiplyAlpha: "premultiply"}).then(
110 function(imageBitmap) {
111 return runImageBitmapTest(imageBitmap, canvas, true); });
112 var p6 = createImageBitmap(video,
113 {imageOrientation: "flipY", premultiplyAlpha: "default"}).then(
114 function(imageBitmap) {
115 return runImageBitmapTest(imageBitmap, canvas, true); });
116 var p7 = createImageBitmap(video,
117 {imageOrientation: "flipY", premultiplyAlpha: "none"}).then(
118 function(imageBitmap) {
119 return runImageBitmapTest(imageBitmap, canvas, true); });
120 return Promise.all([p1, p2, p3, p4, p5, p6, p7]).then(success(), reason => {
121 return error({name: reason});
122 });
123 }
124
125 function runImageBitmapTest(bitmap, canvas, flip_y) {
126 var context = canvas.getContext('2d');
127 context.drawImage(bitmap, 0, 0);
128 var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
129 // Fake capture device 96x96 depth image is gradient. See also
130 // Draw16BitGradient in fake_video_capture_device.cc.
131 var color_step = 255.0 / (canvas.width + canvas.height);
132 return verifyPixels(imageData.data, canvas.width, canvas.height, flip_y,
133 color_step, 255, 2, "ImageBitmap");
134 }
135
136 function testVideoToRGBA32FTexture(videoElementName, success, error) {
137 var video = $(videoElementName);
138 var canvas = document.createElement('canvas');
139 canvas.width = 96;
140 canvas.height = 96;
141 var gl = canvas.getContext('webgl');
142 if(!gl)
143 return error({name:"WebGL is not available."});
144 if(!gl.getExtension("OES_texture_float"))
145 return error({name:"OES_texture_float extension is not available."});
146 return testVideoToTexture(gl, video, gl.RGBA, gl.RGBA, gl.FLOAT,
147 readAndVerifyRGBA32F, success, error);
148 }
149
150 function testVideoToRGBA8Texture(videoElementName, success, error) {
151 var video = $(videoElementName);
152 var canvas = document.createElement('canvas');
153 canvas.width = 96;
154 canvas.height = 96;
155 var gl = canvas.getContext('webgl');
156 if(!gl)
157 return error({name:"WebGL is not available."});
158 return testVideoToTexture(gl, video, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
159 readAndVerifyRGBA8, success, error);
160 }
161
162 function testVideoToTexture(gl, video, internalformat, format, type,
163 readAndVerifyFunction, success, error) {
164 // Create framebuffer that we will use for reading back the texture.
165 var fb = gl.createFramebuffer();
166 gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
167 var tests = [];
168 // Premultiply alpha is ignored but we just test both values.
169 var cases = [
170 {flip_y: false, premultiply_alpha: true},
171 {flip_y: true, premultiply_alpha: false}
172 ];
173 for (var i in cases) {
174 var flip_y = cases[i].flip_y;
175 var premultiply = cases[i].premultiply_alpha;
176 uploadVideoToTexture2D(gl, video, internalformat, format, type, flip_y,
177 premultiply);
178 tests.push(readAndVerifyFunction(gl, video.width, video.height, flip_y,
179 "TexImage_TEXTURE_2D"));
180 uploadVideoToSubTexture2D(gl, video, internalformat, format, type, flip_y,
181 premultiply);
182 tests.push(readAndVerifyFunction(gl, video.width, video.height, flip_y,
183 "TexSubImage_TEXTURE_2D"));
184
185 // cubemap texImage2D.
186 var tex = uploadVideoToTextureCubemap(gl, video, internalformat, format,
187 type, flip_y, premultiply);
188 for (var i = 0; i < cubemapFaces(gl).length; ++i) {
189 // Attach the texture to framebuffer for readback.
190 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
191 cubemapFaces(gl)[i], tex, 0);
192 tests.push(readAndVerifyFunction(gl, video.width, video.height,
193 flip_y,
194 "TexImage_" + cubemapFaces(gl)[i]));
195 }
196
197 // cubemap texSubImage2D.
198 tex = uploadVideoToSubTextureCubemap(gl, video, internalformat, format,
199 type, flip_y, premultiply);
200 for (var i = 0; i < cubemapFaces(gl).length; ++i) {
201 // Attach the texture to framebuffer for readback.
202 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
203 cubemapFaces(gl)[i], tex, 0);
204 tests.push(readAndVerifyFunction(gl, video.width, video.height,
205 flip_y,
206 "TexSubImage_" + cubemapFaces(gl)[i]));
207 }
208 }
209 return Promise.all(tests).then(success(), reason => {
210 return error({name: reason});
211 });
212 }
213
214 // Test setup helper method: create the texture and set texture parameters.
215 // For cubemap, target is gl.TEXTURE_CUBE_MAP. For gl.TEXTURE_2D, it is
216 // gl.TEXTURE_2D.
217 function createTexture(gl, target, video, flip_y, premultiply_alpha) {
218 var tex = gl.createTexture();
219 gl.bindTexture(target, tex);
220 gl.texParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
221 gl.texParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
222 gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
223 gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
224 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flip_y);
225 gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiply_alpha);
226 return tex;
227 }
228
229 function uploadVideoToTexture2D(gl, video, internalformat, format, type,
230 flip_y, premultiply_alpha) {
231 var tex = createTexture(gl, gl.TEXTURE_2D, video, flip_y,
232 premultiply_alpha);
233 // Attach the texture to framebuffer for readback.
234 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D,
235 tex, 0);
236 gl.texImage2D(gl.TEXTURE_2D, 0, internalformat, format, type, video);
237 return tex;
238 }
239
240 function uploadVideoToSubTexture2D(gl, video, internalformat, format, type,
241 flip_y, premultiply_alpha) {
242 var tex = createTexture(gl, gl.TEXTURE_2D, video, flip_y,
243 premultiply_alpha);
244 // Attach the texture to framebuffer for readback.
245 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D,
246 tex, 0);
247 gl.texImage2D(gl.TEXTURE_2D, 0, internalformat, video.width, video.height,
248 0, format, type, null);
249 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, format, type, video);
250 return tex;
251 }
252
253 function uploadVideoToTextureCubemap(gl, video, internalformat, format, type,
254 flip_y, premultiply_alpha) {
255 var tex = createTexture(gl, gl.TEXTURE_CUBE_MAP, video, flip_y,
256 premultiply_alpha);
257 for (var i = 0; i < cubemapFaces(gl).length; ++i) {
258 gl.texImage2D(cubemapFaces(gl)[i], 0, internalformat, format, type,
259 video);
260 }
261 return tex;
262 }
263
264 function uploadVideoToSubTextureCubemap(gl, video, internalformat, format,
265 type, flip_y, premultiply_alpha) {
266 var tex = createTexture(gl, gl.TEXTURE_CUBE_MAP, video, flip_y,
267 premultiply_alpha);
268 for (var i = 0; i < cubemapFaces(gl).length; ++i) {
269 gl.texImage2D(cubemapFaces(gl)[i], 0, internalformat, video.width,
270 video.height, 0, format, type, null);
271 gl.texSubImage2D(cubemapFaces(gl)[i], 0, 0, 0, format, type, video);
272 }
273 return tex;
274 }
275
276 function readAndVerifyRGBA8(gl, width, height, flip_y, test_name) {
277 var arr = new Uint8Array(width * height * 4);
278 gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, arr);
279 var color_step = 255.0 / (width + height);
280 return verifyPixels(arr, width, height, flip_y, color_step,
281 255 /*wrap_around*/, 2 /*tolerance*/, test_name);
282 }
283
284 function readAndVerifyRGBA32F(gl, width, height, flip_y, test_name) {
285 var arr = new Float32Array(width * height * 4);
286 gl.readPixels(0, 0, width, height, gl.RGBA, gl.FLOAT, arr);
287 var color_step = 1.0 / (width + height);
288 return verifyPixels(arr, width, height, flip_y, color_step,
289 1.0 /*wrap_around*/, 1.5/65535 /*tolerance*/,
290 test_name);
291 }
292
293 function onLoad() {
294 var query = /query=(.*)/.exec(window.location.href);
295 if (!query)
296 return;
297 if (query[1] == "RGBAUint8")
298 depthStreamToRGBAUint8Texture();
299 else if (query[1] == "RGBAFloat")
300 depthStreamToRGBAFloatTexture();
301 }
43 </script> 302 </script>
44 </head> 303 </head>
45 <body> 304 <body onload="onLoad()">
46 <table border="0"> 305 <table border="0">
47 <!-- Canvases are named after their corresponding video elements. -->
48 <tr> 306 <tr>
49 <td><video id="local-view-1" width="96" height="96" autoplay 307 <td><video id="local-view-1" width="96" height="96" autoplay
50 style="display:none"></video></td> 308 style="display:none"></video></td>
309 <!-- The canvas is used to detect when video starts and stops. -->
51 <td><canvas id="local-view-1-canvas" width="96" height="96" 310 <td><canvas id="local-view-1-canvas" width="96" height="96"
52 style="display:none"></canvas></td> 311 style="display:none"></canvas></td>
53 </tr> 312 </tr>
54 </table> 313 </table>
55 </body> 314 </body>
56 </html> 315 </html>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698