request-video-frame-callback.html (5083B)
1 <!DOCTYPE html> 2 <html> 3 <title>Test the basics of the video.requestVideoFrameCallback() API.</title> 4 <body></body> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="/common/media.js"></script> 8 <script> 9 var testVideo = { 10 url: getVideoURI('/media/movie_5'), 11 height: 240, 12 width: 320, 13 } 14 15 var altTestVideo = { 16 url: getVideoURI('/media/counting'), 17 height: 240, 18 width: 320, 19 } 20 21 promise_test(async function(t) { 22 let done; 23 const promise = new Promise(resolve => done = resolve); 24 25 let video = document.createElement('video'); 26 video.muted = true; 27 document.body.appendChild(video); 28 29 let id = video.requestVideoFrameCallback( 30 t.step_func((time, metadata) => { 31 assert_true(time > 0); 32 assert_equals(metadata.height, testVideo.height); 33 assert_equals(metadata.width, testVideo.width); 34 done(); 35 }) 36 ); 37 38 assert_true(id > 0); 39 40 video.src = testVideo.url; 41 await video.play(); 42 43 return promise; 44 }, 'Test we can register a video.rVFC callback.'); 45 46 promise_test(async function(t) { 47 let done; 48 const promise = new Promise(resolve => done = resolve); 49 50 let video = document.createElement('video'); 51 video.muted = true; 52 document.body.appendChild(video); 53 54 video.requestVideoFrameCallback( 55 t.step_func(video_now => { 56 // Queue a call to window.rAF, and make sure it is executed within the 57 // same turn of the event loop (with the same 'time' parameter). 58 window.requestAnimationFrame( t.step_func( window_now => { 59 assert_equals(video_now, window_now); 60 done(); 61 })); 62 }) 63 ); 64 65 video.src = testVideo.url; 66 await video.play(); 67 68 return promise; 69 }, 'Test video.rVFC callbacks run before window.rAF callbacks.'); 70 71 72 promise_test(async function(t) { 73 let done; 74 const promise = new Promise(resolve => done = resolve); 75 76 let video = document.createElement('video'); 77 video.muted = true; 78 document.body.appendChild(video); 79 80 let id = video.requestVideoFrameCallback( 81 t.step_func(_ => { 82 assert_unreached("Cancelled callbacks shouldn't be executed") 83 }) 84 ); 85 86 video.cancelVideoFrameCallback(id); 87 88 video.requestVideoFrameCallback( 89 t.step_func(_ => { 90 // At this point, the other callback shouldn't have fired, but 91 // give it some more time and really make sure it doesn't, by going 92 // throught the event loop once more. 93 t.step_timeout(() => { done(); }, 0); 94 }) 95 ); 96 97 video.src = testVideo.url; 98 await video.play(); 99 100 return promise; 101 }, 'Test we can cancel a video.rVFC request.'); 102 103 test(function(t) { 104 let video = document.createElement('video'); 105 video.muted = true; 106 document.body.appendChild(video); 107 108 // requestVideoFrameCallback() expects 1 function as a parameter. 109 assert_throws_js(TypeError, _ => { video.requestVideoFrameCallback() } ); 110 assert_throws_js(TypeError, _ => { video.requestVideoFrameCallback(0) }); 111 assert_throws_js(TypeError, _ => { video.requestVideoFrameCallback("foo") }); 112 113 // cancelVideoFrameCallback() expects 1 number as a parameter 114 assert_throws_js(TypeError, _ => { video.cancelVideoFrameCallback() } ); 115 116 // Invalid calls are just no-ops 117 video.cancelVideoFrameCallback(_ => {}); 118 video.cancelVideoFrameCallback(NaN); 119 video.cancelVideoFrameCallback("foo"); 120 video.cancelVideoFrameCallback(12345); 121 video.cancelVideoFrameCallback(-1); 122 123 }, 'Test invalid calls to the video.rVFC API.'); 124 125 promise_test(async function(t) { 126 let video = document.createElement('video'); 127 video.muted = true; 128 video.autoplay = true; 129 document.body.appendChild(video); 130 131 let first_width = 0; 132 let first_height = 0; 133 134 video.src = testVideo.url; 135 136 await video.play(); 137 138 // Switch to and from a second video, and make sure we get rVFC calls at 139 // each step. 140 return new Promise((resolve, reject) => { 141 let onReturnToOriginalVideo = t.step_func((now, metadata) => { 142 assert_equals(first_width, metadata.width); 143 assert_equals(first_height, metadata.height); 144 145 resolve(); 146 }); 147 148 let onAltVideoFirstFrame = t.step_func((now, metadata) => { 149 // The videos have different sizes, and shouldn't match. 150 assert_not_equals(first_width, metadata.width); 151 assert_not_equals(first_height, metadata.height); 152 153 // Swith back to the original video. 154 video.requestVideoFrameCallback(onReturnToOriginalVideo); 155 video.src = testVideo.url; 156 }); 157 158 let onFirstFrame = t.step_func((now, metadata) => { 159 first_width = metadata.width; 160 first_height = metadata.height; 161 162 // Callbacks should persist after changing the source to the alt video. 163 video.requestVideoFrameCallback(onAltVideoFirstFrame); 164 video.src = altTestVideo.url; 165 }) 166 167 video.requestVideoFrameCallback(onFirstFrame); 168 }); 169 }, 'Test video.rVFC does not stop when switching sources.'); 170 171 </script> 172 </html>