diff options
Diffstat (limited to '')
-rw-r--r-- | dom/media/test/test_mediarecorder_record_changing_video_resolution.html | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/dom/media/test/test_mediarecorder_record_changing_video_resolution.html b/dom/media/test/test_mediarecorder_record_changing_video_resolution.html new file mode 100644 index 0000000000..d6354ee5a1 --- /dev/null +++ b/dom/media/test/test_mediarecorder_record_changing_video_resolution.html @@ -0,0 +1,174 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test MediaRecorder Recording canvas stream that dynamically changes resolution</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<pre id="test"> +<div id="content"> +</div> +<script class="testbody" type="text/javascript"> + +function startTest() { + 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; + + 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. + let stream = canvas.captureStream(); + + // Check values for events + let numDataAvailabledRaised = 0; + let numResizeRaised = 0; + // Recorded data that will be playback. + let blob; + + // Media recorder for VP8 and canvas 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(); + }; + + // When recorder is stopped get recorded data. + mediaRecorder.ondataavailable = ev => { + info("Got 'dataavailable' event"); + ++numDataAvailabledRaised; + is(blob, undefined, "Should only get one dataavailable event"); + // Save recorded data for playback + blob = ev.data; + }; + + mediaRecorder.onstart = () => { + info('onstart fired successfully'); + }; + + 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"); + + 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(); + }; + + // 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"); + } 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(); + // This shouldn't be needed, however video.ended may not be set after + // seeking to the final frame. This can result in seekToNextFrame being + // called again by seekThroughFrames and onended being invoked again, + // resulting in multiple finish() calls. + // FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=1386489 + video.onended = null; + }; + + document.getElementById("content").appendChild(video); + + function seekThroughFrames() { + info("Seeking to next frame"); + video.seekToNextFrame() + .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 + 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) { + 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 ], + ["media.video-queue.send-to-compositor-size", 1] + ] + }, startTest); + +</script> +</pre> +</body> +</html> |