| <!doctype html> |
| <html> |
| <head> |
| <title>MediaRecorder Dataavailable</title> |
| <link rel="help" href="https://w3c.github.io/mediacapture-record/MediaRecorder.html#mediarecorder"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| </head> |
| <body> |
| <canvas id="canvas" width="200" height="200"> |
| </canvas> |
| <script> |
| var context; |
| |
| if (window.internals) |
| internals.setCustomPrivateRecorderCreator(); |
| |
| function createVideoStream() { |
| const canvas = document.getElementById("canvas"); |
| context = canvas.getContext('2d'); |
| return canvas.captureStream(); |
| } |
| |
| function drawSomethingOnCanvas() { |
| context.fillStyle = "red"; |
| context.fillRect(0, 0, 10, 10); |
| } |
| |
| function dataAvailableAssertions(blobEvent) { |
| assert_true(blobEvent instanceof BlobEvent, 'the type of event should be BlobEvent'); |
| assert_equals(blobEvent.type, 'dataavailable', 'the event type should be dataavailable'); |
| assert_true(blobEvent.isTrusted, 'isTrusted should be true when the event is created by C++'); |
| assert_true(blobEvent.data instanceof Blob, 'the type of data should be Blob'); |
| assert_true(blobEvent.data.size > 0, 'the blob should contain some buffers'); |
| } |
| |
| async_test(t => { |
| const video = createVideoStream(); |
| const recorder = new MediaRecorder(video); |
| let state = 0; |
| |
| assert_equals(recorder.stream, video); |
| |
| recorder.ondataavailable = t.step_func(blobEvent => { |
| if (!state) { |
| assert_true(blobEvent instanceof BlobEvent, 'the type of event should be BlobEvent'); |
| assert_equals(blobEvent.type, 'dataavailable', 'the event type should be dataavailable'); |
| assert_true(blobEvent.isTrusted, 'isTrusted should be true when the event is created by C++'); |
| assert_true(blobEvent.data instanceof Blob, 'the type of data should be Blob'); |
| |
| state = 1; |
| setTimeout(() => { |
| // Stopping the recorder will trigger another dataavailable event. |
| recorder.stop(); |
| }, 1000); |
| return; |
| } |
| dataAvailableAssertions(blobEvent); |
| t.done(); |
| }); |
| recorder.start(); |
| assert_equals(recorder.state, 'recording', 'MediaRecorder has been started successfully'); |
| drawSomethingOnCanvas(); |
| |
| recorder.requestData(); |
| }, 'MediaRecorder will fire a dataavailable event with a blob data for a video-only stream when stop() is called'); |
| |
| async_test(t => { |
| const ac = new AudioContext(); |
| const osc = ac.createOscillator(); |
| const dest = ac.createMediaStreamDestination(); |
| const audio = dest.stream; |
| osc.connect(dest); |
| const recorder = new MediaRecorder(audio); |
| |
| recorder.ondataavailable = t.step_func(blobEvent => { |
| dataAvailableAssertions(blobEvent); |
| t.done(); |
| }); |
| recorder.start(); |
| osc.start(); |
| assert_equals(recorder.state, 'recording', 'MediaRecorder has been started successfully'); |
| setTimeout(() => { |
| recorder.stop(); |
| osc.stop(); |
| }, 1000); |
| }, 'MediaRecorder will fire a dataavailable event with a blob data for a audio-only stream when stop() is called'); |
| |
| async_test(t => { |
| const ac = new AudioContext(); |
| const osc = ac.createOscillator(); |
| const dest = ac.createMediaStreamDestination(); |
| const audio = dest.stream; |
| osc.connect(dest); |
| |
| const video = createVideoStream(); |
| assert_equals(video.getAudioTracks().length, 0, "video mediastream starts with no audio track"); |
| assert_equals(audio.getAudioTracks().length, 1, "audio mediastream starts with one audio track"); |
| video.addTrack(audio.getAudioTracks()[0]); |
| assert_equals(video.getAudioTracks().length, 1, "video mediastream starts with one audio track"); |
| const recorder = new MediaRecorder(video); |
| |
| recorder.ondataavailable = t.step_func(blobEvent => { |
| dataAvailableAssertions(blobEvent); |
| t.done(); |
| }); |
| recorder.start(); |
| osc.start(); |
| drawSomethingOnCanvas(); |
| assert_equals(recorder.state, 'recording', 'MediaRecorder has been started successfully'); |
| setTimeout(() => { |
| recorder.stop(); |
| osc.stop(); |
| }, 1000); |
| }, 'MediaRecorder will fire a dataavailable event with a blob data for a video-audio stream when stop() is called'); |
| |
| promise_test(async t => { |
| const stream = await navigator.mediaDevices.getUserMedia({ audio : true }); |
| const recorder = new MediaRecorder(stream); |
| |
| let count = 0; |
| const dataPromise = new Promise(resolve => recorder.ondataavailable = () => { |
| if (++count === 5) |
| resolve(); |
| }); |
| const startPromise = new Promise(resolve => recorder.onstart = resolve); |
| recorder.start(); |
| await startPromise; |
| |
| recorder.requestData(); |
| recorder.requestData(); |
| recorder.requestData(); |
| |
| await new Promise(resolve => setTimeout(resolve, 0)); |
| |
| recorder.requestData(); |
| recorder.stop(); |
| |
| return dataPromise; |
| }, 'Make sure to handle well the case of fetching data quickly and stopping the recorder while fetching data is ongoing'); |
| |
| </script> |
| </body> |
| </html> |