Bug 1356212 - Stabilize test_mr_record_changing_video_resolution.html. r?achronop, r?SingingTree draft
authorAndreas Pehrson <pehrsons@gmail.com>
Thu, 18 May 2017 15:31:32 +0200
changeset 583657 0f0a2a28ec7a1fbda2b60b5e2d72f2e271e9f576
parent 578175 3e166b6838931b3933ca274331f9e0e115af5cc0
child 630155 85e5acbe0ad12ccaa2f2de1a7088701bb6457af5
push id60497
push userbmo:pehrson@telenordigital.com
push dateWed, 24 May 2017 11:45:59 +0000
reviewersachronop, SingingTree
bugs1356212
milestone55.0a1
Bug 1356212 - Stabilize test_mr_record_changing_video_resolution.html. r?achronop, r?SingingTree I noted locally that it could sometimes take this test >1s between draws to the canvas that gets fed to the MediaRecorder. Perhaps due to GC. When that happens, the encoder gets fed an extra frame, and so our assumption on nr of frames when playing back the recording is moot. With this patch we will seek through all frames until reaching the end of the recorded media, observing the resize events as it goes. MozReview-Commit-ID: 2Sy5Cdke688
dom/media/test/test_mediarecorder_record_changing_video_resolution.html
--- a/dom/media/test/test_mediarecorder_record_changing_video_resolution.html
+++ b/dom/media/test/test_mediarecorder_record_changing_video_resolution.html
@@ -7,42 +7,40 @@
 </head>
 <body>
 <pre id="test">
 <div id="content">
 </div>
 <script class="testbody" type="text/javascript">
 
 function startTest() {
-  var content = document.getElementById("content");
-
-  var canvas = document.createElement("canvas");
+  let canvas = document.createElement("canvas");
   const resolution_change = [
     {width: 100, height: 100, color: "red"},
     {width: 150, height: 150, color: "blue"},
     {width: 100, height: 100, color: "red"},
   ];
   canvas.width = resolution_change[0].width;
   canvas.height = resolution_change[0].height;
 
-  var ctx = canvas.getContext("2d");
+  let ctx = canvas.getContext("2d");
   ctx.fillStyle = resolution_change[0].color;
   ctx.fillRect(0, 0, canvas.width, canvas.height);
 
   // The recorded stream coming from canvas.
-  var stream = canvas.captureStream();
+  let stream = canvas.captureStream();
 
   // Check values for events
-  var numDataAvailabledRaised = 0;
-  var numResizeRaised = 0;
+  let numDataAvailabledRaised = 0;
+  let numResizeRaised = 0;
   // Recorded data that will be playback.
-  var blob;
+  let blob;
 
   // Media recorder for VP8 and canvas stream.
-  var mediaRecorder = new MediaRecorder(stream);
+  let mediaRecorder = new MediaRecorder(stream);
   is(mediaRecorder.stream, stream,
      "Media recorder stream = canvas stream at the start of recording");
 
   // Not expected events.
   mediaRecorder.onwarning = () => ok(false, "MediaRecorder: onwarning unexpectedly fired");
   mediaRecorder.onerror = err => {
     ok(false, "MediaRecorder: onerror unexpectedly fired. Code " + err.name);
     SimpleTest.finish();
@@ -62,97 +60,101 @@ function startTest() {
   };
 
   mediaRecorder.onstop = () => {
     info("Got 'stop' event");
     is(numDataAvailabledRaised, 1, "Should have gotten 1 dataavailable event");
     // Playback stream and verify resolution changes.
     ok(blob, "Should have gotten a data blob");
 
-    var video = document.createElement("video");
+    let video = document.createElement("video");
     video.id = "recorded-video";
     video.src = URL.createObjectURL(blob);
     video.preload = "metadata";
 
     video.onerror = err => {
       ok(false, "Should be able to play the recording. Got error. code=" + video.error.code);
       SimpleTest.finish();
     };
 
-    video.onloadedmetadata = function(){
-      info("onloadedmetadata");
-      video.seekToNextFrame()
-      .then(()=>video.seekToNextFrame())
-      .catch((reason)=>{
-        info("seekToNextFrame rejected: " + reason)
-        callSeekToNextFrame();
-      });
-    }
-
-    // Check that resize is correct for playback stream.
+    // Check that the encoded frames have the correct sizes.
     video.onresize = function() {
       if (numResizeRaised < resolution_change.length) {
         is(video.videoWidth, resolution_change[numResizeRaised].width,
           "onresize width should be as expected");
         is(video.videoHeight, resolution_change[numResizeRaised].height,
           "onresize height should be as expected");
-        if (numResizeRaised > 0) {
-          callSeekToNextFrame();
-        }
       } else {
         ok(false, "Got more resize events than expected");
       }
       ++numResizeRaised;
     };
 
+    video.onloadedmetadata = function() {
+      info("loadedmetadata");
+      seekThroughFrames();
+    };
+
     video.onended = function() {
       is(numResizeRaised, resolution_change.length, "Expected number of resize events");
       SimpleTest.finish();
     };
 
     document.getElementById("content").appendChild(video);
 
-    function callSeekToNextFrame() {
+    function seekThroughFrames() {
+      info("Seeking to next frame");
       video.seekToNextFrame()
-      .then()
-      .catch((reason)=>{
-        info("seekToNextFrame rejected: " + reason)
-        callSeekToNextFrame();
-      });
-    };
+        .then(() => {
+          info("Seeking to next frame finished. width=" + video.videoWidth
+               + ", height=" + video.videoHeight);
+
+          if (video.ended) {
+            return;
+          }
+
+          // After seeking finished we queue the next seek task on the event
+          // loop so it gets in the same queue as the "resize" events.
+          setTimeout(seekThroughFrames, 0);
+        })
+        .catch(error => {
+          ok(false, "seekToNextFrame rejected: " + error);
+        });
+    }
   };
 
   // Start here by stream recorder.
   mediaRecorder.start();
   is(mediaRecorder.state, "recording", "Media recorder should be recording");
   requestAnimationFrame(draw);
 
   // Change resolution in every frame
   // Stop recorder on last frame
-  var countFrames=0;
-  var previous_time = performance.now();
+  let countFrames = 0;
+  let previous_time = performance.now();
   function draw(timestamp) {
     if (timestamp - previous_time < 100) {
       requestAnimationFrame(draw);
       return;
     }
     previous_time = timestamp;
 
-    if (countFrames < resolution_change.length) {
-      canvas.width = resolution_change[countFrames].width;
-      canvas.height = resolution_change[countFrames].height;
-      ctx.fillStyle = resolution_change[countFrames].color;
-      // Resize and draw canvas
-      ctx.fillRect(0, 0, canvas.width, canvas.height);
-      // Register draw to be called on next rendering
-      requestAnimationFrame(draw);
-      countFrames++;
-    } else {
+    if (countFrames == resolution_change.length) {
       mediaRecorder.stop();
+      return;
     }
+
+    canvas.width = resolution_change[countFrames].width;
+    canvas.height = resolution_change[countFrames].height;
+    ctx.fillStyle = resolution_change[countFrames].color;
+    // Resize and draw canvas
+    ctx.fillRect(0, 0, canvas.width, canvas.height);
+    // Register draw to be called on next rendering
+    requestAnimationFrame(draw);
+    countFrames++;
   }
 }
 
 SimpleTest.waitForExplicitFinish();
 SpecialPowers.pushPrefEnv(
   {
     "set": [
       ["media.seekToNextFrame.enabled", true ],