Chromium Code Reviews| 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(id) { | 7 $ = function(id) { |
| 8 return document.getElementById(id); | 8 return document.getElementById(id); |
| 9 }; | 9 }; |
| 10 | 10 |
| 11 setAllEventsOccuredHandler(function() { | 11 setAllEventsOccuredHandler(function() { |
| 12 reportTestSuccess(); | 12 reportTestSuccess(); |
| 13 }); | 13 }); |
| 14 | 14 |
| 15 // testVideoToImageBitmap is a layout test that we run here because | 15 // testVideoToImageBitmap is a layout test that we run here because |
| 16 // it requires --use-fake-device-for-media-capture. | 16 // it requires --use-fake-device-for-media-capture. |
| 17 function getDepthStreamAndCallCreateImageBitmap() { | 17 function getDepthStreamAndCallCreateImageBitmap() { |
| 18 console.log('Calling getDepthStreamAndCallCreateImageBitmap'); | 18 console.log('Calling getDepthStreamAndCallCreateImageBitmap'); |
| 19 getFake16bitStream().then(function(stream) { | 19 getFake16bitStream().then(function(stream) { |
| 20 detectVideoInLocalView1(stream, function() { | 20 detectVideoInLocalView1(stream, function() { |
| 21 testVideoToImageBitmap('local-view-1', function() { | 21 testVideoToImageBitmap('local-view-1', function() { |
| 22 stream.getVideoTracks()[0].stop(); | 22 stream.getVideoTracks()[0].stop(); |
| 23 waitForVideoToStop('local-view-1'); | 23 waitForVideoToStop('local-view-1'); |
| 24 }, failedCallback); | 24 }, failedCallback); |
| 25 }); | 25 }); |
| 26 }, | 26 }, |
| 27 failedCallback); | 27 failedCallback); |
| 28 } | 28 } |
| 29 | |
| 30 // testVideoToWebGLTexture is a layout test that we run here because it | |
| 31 // requires --use-fake-device-for-media-capture. | |
| 32 function getDepthStreamAndCallGLTexImage2D() { | |
| 33 console.log('Calling getDepthStreamAndCallGLTexImage2D'); | |
| 34 getFake16bitStream().then(function(stream) { | |
| 35 detectVideoInLocalView1(stream, function() { | |
| 36 testVideoToWebGLTexture('local-view-1', function(skip_info) { | |
| 37 if (skip_info) { | |
| 38 console.log("SKIP getDepthStreamAndCallGLTexImage2D: " + | |
| 39 skip_info); | |
| 40 } | |
| 41 stream.getVideoTracks()[0].stop(); | |
| 42 waitForVideoToStop('local-view-1'); | |
| 43 }, failedCallback); | |
| 44 }); | |
| 45 }, | |
| 46 failedCallback); | |
| 47 } | |
| 29 | 48 |
| 30 function failedCallback(error) { | 49 function failedCallback(error) { |
| 31 failTest('GetUserMedia call failed with error name ' + error.name); | 50 failTest('GetUserMedia call failed with error name ' + error.name); |
| 32 } | 51 } |
| 33 | 52 |
| 34 function attachMediaStream(stream, videoElement) { | 53 function attachMediaStream(stream, videoElement) { |
| 35 var localStreamUrl = URL.createObjectURL(stream); | 54 var localStreamUrl = URL.createObjectURL(stream); |
| 36 $(videoElement).src = localStreamUrl; | 55 $(videoElement).src = localStreamUrl; |
| 37 } | 56 } |
| 38 | 57 |
| 39 function detectVideoInLocalView1(stream, callback) { | 58 function detectVideoInLocalView1(stream, callback) { |
| 40 attachMediaStream(stream, 'local-view-1'); | 59 attachMediaStream(stream, 'local-view-1'); |
| 41 detectVideoPlaying('local-view-1', callback); | 60 detectVideoPlaying('local-view-1', callback); |
| 42 } | 61 } |
| 62 | |
| 63 function testVideoToImageBitmap(videoElementName, success, error) | |
| 64 { | |
|
phoglund_chromium
2016/11/07 09:20:00
Nit: pull up braces to previous line (apply throug
aleksandar.stojiljkovic
2016/11/16 20:01:24
Done.
| |
| 65 var bitmaps = {}; | |
| 66 var video = $(videoElementName); | |
| 67 var canvas = document.createElement('canvas'); | |
| 68 canvas.width = 96; | |
| 69 canvas.height = 96; | |
| 70 document.body.appendChild(canvas); | |
| 71 var p1 = createImageBitmap(video).then(function(imageBitmap) { | |
| 72 return runImageBitmapTest(imageBitmap, canvas, false); }); | |
| 73 var p2 = createImageBitmap(video, | |
| 74 {imageOrientation: "none", premultiplyAlpha: "premultiply"}).then( | |
| 75 function(imageBitmap) { | |
| 76 return runImageBitmapTest(imageBitmap, canvas, false); }); | |
| 77 var p3 = createImageBitmap(video, | |
| 78 {imageOrientation: "none", premultiplyAlpha: "default"}).then( | |
| 79 function(imageBitmap) { | |
| 80 return runImageBitmapTest(imageBitmap, canvas, false); }); | |
| 81 var p4 = createImageBitmap(video, | |
| 82 {imageOrientation: "none", premultiplyAlpha: "none"}).then( | |
| 83 function(imageBitmap) { | |
| 84 return runImageBitmapTest(imageBitmap, canvas, false); }); | |
| 85 var p5 = createImageBitmap(video, | |
| 86 {imageOrientation: "flipY", premultiplyAlpha: "premultiply"}).then( | |
| 87 function(imageBitmap) { | |
| 88 return runImageBitmapTest(imageBitmap, canvas, true); }); | |
| 89 var p6 = createImageBitmap(video, | |
| 90 {imageOrientation: "flipY", premultiplyAlpha: "default"}).then( | |
| 91 function(imageBitmap) { | |
| 92 return runImageBitmapTest(imageBitmap, canvas, true); }); | |
| 93 var p7 = createImageBitmap(video, | |
| 94 {imageOrientation: "flipY", premultiplyAlpha: "none"}).then( | |
| 95 function(imageBitmap) { | |
| 96 return runImageBitmapTest(imageBitmap, canvas, true); }); | |
| 97 return Promise.all([p1, p2, p3, p4, p5, p6, p7]).then(success(), reason => { | |
| 98 return error({name: reason}); | |
| 99 }); | |
| 100 } | |
| 101 | |
| 102 function runImageBitmapTest(bitmap, canvas, flip_y) { | |
| 103 var context = canvas.getContext('2d'); | |
| 104 context.drawImage(bitmap,0,0); | |
| 105 var imageData = context.getImageData(0, 0, canvas.width, canvas.height); | |
| 106 // Fake capture device 96x96 depth image is gradient. See also | |
| 107 // Draw16BitGradient in fake_video_capture_device.cc. | |
| 108 var color_step = 255.0 / (canvas.width + canvas.height); | |
| 109 return verifyPixels(imageData.data, canvas.width, canvas.height, flip_y, | |
| 110 color_step, 255, 2); | |
| 111 } | |
| 112 | |
| 113 function testVideoToWebGLTexture(videoElementName, success, error) | |
|
phoglund_chromium
2016/11/07 09:20:00
Will you get clear test errors when any of the sub
aleksandar.stojiljkovic
2016/11/16 20:01:24
Done.
The only reason to couple unsigned byte and
| |
| 114 { | |
| 115 var video = $(videoElementName); | |
| 116 var canvas = document.createElement('canvas'); | |
| 117 canvas.width = 96; | |
| 118 canvas.height = 96; | |
| 119 video.width = 96; | |
| 120 video.height = 96; | |
| 121 var gl = canvas.getContext('webgl'); | |
| 122 if(!gl) | |
| 123 return error({name:"WebGL is not available."}); | |
| 124 if(!gl.getExtension("OES_texture_float")) | |
| 125 return error({name:"OES_texture_float extension is not available."}); | |
| 126 var p1 = testVideoToTexture2D(gl, gl.UNSIGNED_BYTE, video); | |
| 127 var p2 = testVideoToTextureCubemap(gl, gl.UNSIGNED_BYTE, video); | |
| 128 var p3 = testVideoToTexture2D(gl, gl.FLOAT, video); | |
| 129 var p4 = testVideoToTextureCubemap(gl, gl.FLOAT, video); | |
| 130 return Promise.all([p1, p2, p3, p4]).then(success(), reason => { | |
| 131 return error({name: reason}); | |
| 132 }); | |
| 133 } | |
| 134 | |
| 135 function testVideoToTexture2D(gl, type, video) | |
| 136 { | |
| 137 // Premultiply alpha is ignored, so we test it in one iteration only. | |
| 138 var p1 = runWebGLTextureTest(gl, gl.TEXTURE_2D, gl.TEXTURE_2D, type, video, | |
| 139 false/*sub_image*/, false/*flip_y*/, true/*premultiply_alpha*/); | |
| 140 var p2 = runWebGLTextureTest(gl, gl.TEXTURE_2D, gl.TEXTURE_2D, type, video, | |
| 141 false/*sub_image*/, true/*flip_y*/, false/*premultiply_alpha*/); | |
| 142 var p3 = runWebGLTextureTest(gl, gl.TEXTURE_2D, gl.TEXTURE_2D, type, video, | |
| 143 true/*sub_image*/, false/*flip_y*/, false/*premultiply_alpha*/); | |
| 144 var p4 = runWebGLTextureTest(gl, gl.TEXTURE_2D, gl.TEXTURE_2D, type, video, | |
| 145 true/*sub_image*/, true/*flip_y*/, false/*premultiply_alpha*/); | |
| 146 return Promise.all([p1, p2, p3, p4]).then(Promise.resolve(), reason => { | |
| 147 return Promise.reject(reason); | |
| 148 }); | |
| 149 } | |
| 150 | |
| 151 function testVideoToTextureCubemap(gl, type, video) | |
| 152 { | |
| 153 var p1 = runWebGLTextureTest(gl, gl.TEXTURE_CUBE_MAP, | |
| 154 gl.TEXTURE_CUBE_MAP_POSITIVE_X, type, video, false/*sub_image*/, | |
| 155 false/*flip_y*/, true/*premultiply_alpha*/); | |
| 156 var p2 = runWebGLTextureTest(gl, gl.TEXTURE_CUBE_MAP, | |
| 157 gl.TEXTURE_CUBE_MAP_POSITIVE_Y, type, video, true/*sub_image*/, | |
| 158 false/*flip_y*/, true/*premultiply_alpha*/); | |
| 159 var p3 = runWebGLTextureTest(gl, gl.TEXTURE_CUBE_MAP, | |
| 160 gl.TEXTURE_CUBE_MAP_POSITIVE_Z, type, video, false/*sub_image*/, | |
| 161 true/*flip_y*/, true/*premultiply_alpha*/); | |
| 162 var p4 = runWebGLTextureTest(gl, gl.TEXTURE_CUBE_MAP, | |
| 163 gl.TEXTURE_CUBE_MAP_NEGATIVE_X, type, video, true/*sub_image*/, | |
| 164 true/*flip_y*/, true/*premultiply_alpha*/); | |
| 165 var p5 = runWebGLTextureTest(gl, gl.TEXTURE_CUBE_MAP, | |
| 166 gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, type, video, false/*sub_image*/, | |
| 167 false/*flip_y*/, false/*premultiply_alpha*/); | |
| 168 var p6 = runWebGLTextureTest(gl, gl.TEXTURE_CUBE_MAP, | |
| 169 gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, type, video, true/*sub_image*/, | |
| 170 true/*flip_y*/, false/*premultiply_alpha*/); | |
| 171 return Promise.all([p1, p2, p3, p4, p5, p6]).then(Promise.resolve(), | |
| 172 reason => { | |
| 173 return Promise.reject(reason); | |
| 174 }); | |
| 175 } | |
| 176 | |
| 177 //For cubemap, binding_target is gl.TEXTURE_CUBE_MAP and target is a face id. | |
|
phoglund_chromium
2016/11/07 09:20:00
Nit: Space between // and For; this and next line
aleksandar.stojiljkovic
2016/11/16 20:01:24
Done.
| |
| 178 //For gl.TEXTURE_2D, binding_target=target=gl.TEXTURE_2D. | |
| 179 function runWebGLTextureTest(gl, binding_target, target, type, video, | |
| 180 use_sub_image_2d, flip_y, premultiply_alpha) { | |
| 181 var tex = gl.createTexture(); | |
|
phoglund_chromium
2016/11/07 09:20:00
Nit: indent 2 here, not 1
aleksandar.stojiljkovic
2016/11/16 20:01:24
Done.
| |
| 182 gl.bindTexture(binding_target, tex); | |
| 183 gl.texParameteri(binding_target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); | |
| 184 gl.texParameteri(binding_target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); | |
| 185 gl.texParameteri(binding_target, gl.TEXTURE_MAG_FILTER, gl.LINEAR); | |
| 186 gl.texParameteri(binding_target, gl.TEXTURE_MIN_FILTER, gl.LINEAR); | |
| 187 | |
| 188 // Create framebuffer that we will use for reading back the texture. | |
| 189 var fb = gl.createFramebuffer(); | |
| 190 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); | |
| 191 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, | |
| 192 target, tex, 0); | |
| 193 | |
| 194 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flip_y); | |
| 195 gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiply_alpha); | |
| 196 | |
| 197 var targets = (binding_target == gl.TEXTURE_CUBE_MAP) ? | |
| 198 [gl.TEXTURE_CUBE_MAP_POSITIVE_X, | |
| 199 gl.TEXTURE_CUBE_MAP_NEGATIVE_X, | |
| 200 gl.TEXTURE_CUBE_MAP_POSITIVE_Y, | |
| 201 gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, | |
| 202 gl.TEXTURE_CUBE_MAP_POSITIVE_Z, | |
| 203 gl.TEXTURE_CUBE_MAP_NEGATIVE_Z] : [target]; | |
| 204 | |
| 205 // Upload the video frame into the texture. | |
| 206 for (var i = 0; i < targets.length; ++i) { | |
| 207 if (use_sub_image_2d) { | |
|
phoglund_chromium
2016/11/07 09:20:00
I don't like this kind of complexity in tests; the
aleksandar.stojiljkovic
2016/11/16 20:01:24
Done. Rewritten, no branching.
| |
| 208 gl.texImage2D(targets[i], 0, gl.RGBA, video.width, video.height, 0, | |
| 209 gl.RGBA, type, null); | |
| 210 gl.texSubImage2D(targets[i], 0, 0, 0, gl.RGBA, type, video); | |
| 211 } else { | |
| 212 gl.texImage2D(targets[i], 0, gl.RGBA, gl.RGBA, type, video); | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 var arr = (type == gl.FLOAT) ? | |
| 217 new Float32Array(video.width * video.height * 4) : | |
| 218 new Uint8Array(video.width * video.height * 4); | |
| 219 // Read the texture attached to framebuffer. | |
| 220 gl.readPixels(0, 0, video.width, video.height, gl.RGBA, type, arr); | |
| 221 gl.bindFramebuffer(gl.FRAMEBUFFER, null); | |
| 222 gl.deleteTexture(tex); | |
| 223 gl.deleteFramebuffer(fb); | |
| 224 | |
| 225 if(type == gl.FLOAT) { | |
| 226 var color_step = 1.0 / (video.width + video.height); | |
| 227 return verifyPixels(arr, video.width, video.height, flip_y, color_step, | |
| 228 1.0 /*wrap_around*/, 1.5/65535 /*tolerance*/); | |
| 229 } else { | |
| 230 var color_step = 255.0 / (video.width + video.height); | |
| 231 return verifyPixels(arr, video.width, video.height, flip_y, color_step, | |
| 232 255 /*wrap_around*/, 2 /*tolerance*/); | |
| 233 } | |
| 234 } | |
| 43 </script> | 235 </script> |
| 44 </head> | 236 </head> |
| 45 <body> | 237 <body> |
| 46 <table border="0"> | 238 <table border="0"> |
| 47 <!-- Canvases are named after their corresponding video elements. --> | |
| 48 <tr> | 239 <tr> |
| 49 <td><video id="local-view-1" width="96" height="96" autoplay | 240 <td><video id="local-view-1" width="96" height="96" autoplay |
| 50 style="display:none"></video></td> | 241 style="display:none"></video></td> |
| 242 <!-- The canvas is used to detect when video starts and stops. --> | |
| 51 <td><canvas id="local-view-1-canvas" width="96" height="96" | 243 <td><canvas id="local-view-1-canvas" width="96" height="96" |
| 52 style="display:none"></canvas></td> | 244 style="display:none"></canvas></td> |
| 53 </tr> | 245 </tr> |
| 54 </table> | 246 </table> |
| 55 </body> | 247 </body> |
| 56 </html> | 248 </html> |
| OLD | NEW |