diff options
Diffstat (limited to 'dom/media/test/test_mediarecorder_record_addtracked_stream.html')
-rw-r--r-- | dom/media/test/test_mediarecorder_record_addtracked_stream.html | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/dom/media/test/test_mediarecorder_record_addtracked_stream.html b/dom/media/test/test_mediarecorder_record_addtracked_stream.html new file mode 100644 index 0000000000..639531f7f2 --- /dev/null +++ b/dom/media/test/test_mediarecorder_record_addtracked_stream.html @@ -0,0 +1,182 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test MediaRecorder recording a constructed MediaStream</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/dom/canvas/test/captureStream_common.js"></script> + <script src="/tests/dom/media/webrtc/tests/mochitests/head.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<pre id="test"> +<div id="content"> +</div> +<script> +SimpleTest.waitForExplicitFinish(); +runTestWhenReady(async () => { + const canvas = document.createElement("canvas"); + canvas.width = canvas.height = 100; + document.getElementById("content").appendChild(canvas); + + const helper = new CaptureStreamTestHelper2D(100, 100); + helper.drawColor(canvas, helper.red); + + const audioCtx = new AudioContext(); + const osc = audioCtx.createOscillator(); + osc.frequency.value = 1000; + osc.start(); + const dest = audioCtx.createMediaStreamDestination(); + osc.connect(dest); + + const stream = dest.stream; + + // Timeouts are experienced intermittently in Linux due to no sound in the + // destination. As a workaround wait for the source sound to arrive. + const sourceAnalyser = new AudioStreamAnalyser(audioCtx, stream); + const sourceAudioReady = sourceAnalyser.waitForAnalysisSuccess(array => { + const freq = osc.frequency.value; + const lowerFreq = freq / 2; + const upperFreq = freq + 1000; + const lowerAmp = array[sourceAnalyser.binIndexForFrequency(lowerFreq)]; + const freqAmp = array[sourceAnalyser.binIndexForFrequency(freq)]; + const upperAmp = array[sourceAnalyser.binIndexForFrequency(upperFreq)]; + info("Analysing source audio. " + + lowerFreq + ": " + lowerAmp + ", " + + freq + ": " + freqAmp + ", " + + upperFreq + ": " + upperAmp); + return lowerAmp < 50 && freqAmp > 200 && upperAmp < 50; + }); + await sourceAudioReady; + info("Source Audio content ok"); + + canvas.captureStream(0).getVideoTracks().forEach(t => stream.addTrack(t)); + + const blobs = []; + + let mediaRecorder = new MediaRecorder(stream); + is(mediaRecorder.stream, stream, + "Media recorder stream = constructed stream at the start of recording"); + + + mediaRecorder.ondataavailable = evt => { + info("ondataavailable fired"); + + is(mediaRecorder.state, "inactive", "Blob received after stopping"); + is(blobs.length, 0, "This is the first and only blob"); + ok(evt instanceof BlobEvent, + "Events fired from ondataavailable should be BlobEvent"); + is(evt.type, "dataavailable", + "Event type should dataavailable"); + ok(evt.data.size >= 0, + "Blob data size received is greater than or equal to zero"); + + blobs.push(evt.data); + }; + + const stopped = haveEvent(mediaRecorder, "stop", wait(5000, new Error("Timeout"))); + const stoppedNoErrors = Promise.all([ + stopped, + haveNoEvent(mediaRecorder, "warning", stopped), + haveNoEvent(mediaRecorder, "error", stopped) + ]); + + mediaRecorder.start(); + is(mediaRecorder.state, "recording", "Media recorder should be recording"); + + await haveEvent(mediaRecorder, "start", wait(5000, new Error("Timeout"))); + info("onstart fired"); + + // The recording can be too short to cause any checks with + // waitForAnalysisSuccess(). Waiting a bit here solves this. + await wait(500); + + is(mediaRecorder.state, "recording", + "Media recorder is recording before being stopped"); + mediaRecorder.stop(); + is(mediaRecorder.state, "inactive", + "Media recorder is inactive after being stopped"); + is(mediaRecorder.stream, stream, + "Media recorder stream = constructed stream post recording"); + + await stoppedNoErrors; + info("Got 'stop' event"); + + ok(blobs.length == 1, "Should have gotten one data blob"); + + // Clean up recording sources + osc.stop(); + stream.getTracks().forEach(t => t.stop()); + + // Sanity check the recording + const video = document.createElement("video"); + document.getElementById("content").appendChild(video); + video.id = "recorded-video"; + + const blob = new Blob(blobs); + ok(blob.size > 0, "Recorded blob should contain data"); + + video.src = URL.createObjectURL(blob); + video.preload = "metadata"; + + info("Waiting for metadata to be preloaded"); + + await haveEvent(video, "loadedmetadata", wait(5000, new Error("Timeout"))); + info("Playback of recording loaded metadata"); + + const recordingStream = video.mozCaptureStream(); + is(recordingStream.getVideoTracks().length, 1, + "Recording should have one video track"); + is(recordingStream.getAudioTracks().length, 1, + "Recording should have one audio track"); + + const ended = haveEvent(video, "ended", wait(5000, new Error("Timeout"))); + const endedNoError = Promise.all([ + ended, + haveNoEvent(video, "error", ended), + ]); + + const analyser = new AudioStreamAnalyser(audioCtx, recordingStream); + const audioReady = analyser.waitForAnalysisSuccess(array => { + const freq = osc.frequency.value; + const lowerFreq = freq / 2; + const upperFreq = freq + 1000; + const lowerAmp = array[analyser.binIndexForFrequency(lowerFreq)]; + const freqAmp = array[analyser.binIndexForFrequency(freq)]; + const upperAmp = array[analyser.binIndexForFrequency(upperFreq)]; + info("Analysing audio. " + + lowerFreq + ": " + lowerAmp + ", " + + freq + ": " + freqAmp + ", " + + upperFreq + ": " + upperAmp); + return lowerAmp < 50 && freqAmp > 200 && upperAmp < 50; + }, endedNoError.then(() => new Error("Audio check failed"))); + + const videoReady = helper.pixelMustBecome( + video, helper.red, { + threshold: 128, + infoString: "Should become red", + cancelPromise: endedNoError.then(() => new Error("Video check failed")), + }); + + video.play(); + + try { + await endedNoError; + } finally { + analyser.disconnect(); + let url = video.src; + video.src = ""; + URL.revokeObjectURL(url); + } + + info("Playback of recording ended without error"); + + await audioReady; + info("Audio content ok"); + + await videoReady; + info("Video content ok"); +}); +</script> +</pre> +</body> +</html> |