OLD | NEW |
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> |
OLD | NEW |