Diff
Modified: trunk/LayoutTests/ChangeLog (237641 => 237642)
--- trunk/LayoutTests/ChangeLog 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/LayoutTests/ChangeLog 2018-10-31 17:19:27 UTC (rev 237642)
@@ -1,3 +1,18 @@
+2018-10-31 YUHAN WU <yuhan...@apple.com>
+
+ MediaRecorder should fire dataavailable event when all tracks are ended and stop() is called
+ https://bugs.webkit.org/show_bug.cgi?id=190778
+
+ Reviewed by Youenn Fablet.
+
+ These tests are used to check if MediaRecorder can generate both video and audio buffers through mock source.
+
+ * http/wpt/mediarecorder/MediaRecorder-dataavailable-expected.txt: Added.
+ * http/wpt/mediarecorder/MediaRecorder-dataavailable.html: Added.
+ * http/wpt/mediarecorder/MediaRecorder-mock-dataavailable-expected.txt: Added.
+ * http/wpt/mediarecorder/MediaRecorder-mock-dataavailable.html: Added.
+ * platform/win/TestExpectations:
+
2018-10-31 Chris Dumez <cdu...@apple.com>
[PSON] When process-swapping for a POST request the HTTP body gets dropped
Added: trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-dataavailable-expected.txt (0 => 237642)
--- trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-dataavailable-expected.txt (rev 0)
+++ trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-dataavailable-expected.txt 2018-10-31 17:19:27 UTC (rev 237642)
@@ -0,0 +1,5 @@
+
+PASS MediaRecorder will fire a dataavailable event with a blob data for a video-only stream when stop() is called
+PASS MediaRecorder will fire a dataavailable event with a blob data for a audio-only stream when stop() is called
+PASS MediaRecorder will fire a dataavailable event with a blob data for a video-audio stream when stop() is called
+
Added: trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-dataavailable.html (0 => 237642)
--- trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-dataavailable.html (rev 0)
+++ trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-dataavailable.html 2018-10-31 17:19:27 UTC (rev 237642)
@@ -0,0 +1,101 @@
+<!doctype html>
+<html>
+<head>
+ <title>MediaRecorder Dataavailable</title>
+ <link rel="help" href=""
+ <script src=""
+ <script src=""
+</head>
+<body>
+<canvas id="canvas" width="200" height="200">
+</canvas>
+<script>
+ var context;
+
+ 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);
+
+ recorder._ondataavailable_ = t.step_func(blobEvent => {
+ dataAvailableAssertions(blobEvent);
+ t.done();
+ });
+ recorder.start();
+ assert_equals(recorder.state, 'recording', 'MediaRecorder has been started successfully');
+ drawSomethingOnCanvas();
+ setTimeout(() => {
+ recorder.stop();
+ }, 500)
+ }, '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();
+ }, 500);
+ }, '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();
+ }, 500);
+ }, 'MediaRecorder will fire a dataavailable event with a blob data for a video-audio stream when stop() is called');
+
+</script>
+</body>
+</html>
\ No newline at end of file
Added: trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-mock-dataavailable-expected.txt (0 => 237642)
--- trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-mock-dataavailable-expected.txt (rev 0)
+++ trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-mock-dataavailable-expected.txt 2018-10-31 17:19:27 UTC (rev 237642)
@@ -0,0 +1,5 @@
+
+PASS MediaRecorder will fire a dataavailable event which only contains video buffers for a video-only stream when stop() is called
+PASS MediaRecorder will fire a dataavailable event which only contains audio buffers for a audio-only stream when stop() is called
+PASS MediaRecorder will fire a dataavailable event which only contains both video and audio buffers when stop() is called
+
Added: trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-mock-dataavailable.html (0 => 237642)
--- trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-mock-dataavailable.html (rev 0)
+++ trunk/LayoutTests/http/wpt/mediarecorder/MediaRecorder-mock-dataavailable.html 2018-10-31 17:19:27 UTC (rev 237642)
@@ -0,0 +1,106 @@
+<!doctype html>
+<html>
+<head>
+ <title>MediaRecorder Dataavailable</title>
+ <link rel="help" href=""
+ <script src=""
+ <script src=""
+</head>
+<body>
+<canvas id="canvas" width="200" height="200">
+</canvas>
+<script>
+ var context;
+ const reader = new FileReader();
+
+ 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);
+ }
+
+ async_test(t => {
+ const video = createVideoStream();
+ const recorder = new MediaRecorder(video);
+
+ recorder._ondataavailable_ = t.step_func(blobEvent => {
+ reader.readAsText(blobEvent.data);
+ reader._onloadend_ = t.step_func(() => {
+ assert_not_equals(reader.result.indexOf('Video'), -1, 'MediaRecorder successfully captured video buffers');
+ assert_equals(reader.result.indexOf('Audio'), -1, 'MediaRecorder does not capture audio buffers for a video-only stream');
+ t.done();
+ });
+ });
+ recorder.start();
+ assert_equals(recorder.state, 'recording', 'MediaRecorder has been started successfully');
+ drawSomethingOnCanvas();
+ setTimeout(() => {
+ recorder.stop();
+ }, 500);
+ }, 'MediaRecorder will fire a dataavailable event which only contains video buffers 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 => {
+ reader.readAsText(blobEvent.data);
+ reader._onloadend_ = t.step_func(() => {
+ assert_not_equals(reader.result.indexOf('Audio'), -1, 'MediaRecorder successfully captured video buffers');
+ assert_equals(reader.result.indexOf('Video'), -1, 'MediaRecorder does not capture audio buffers for a video-only stream');
+ t.done();
+ });
+ });
+ recorder.start();
+ osc.start();
+ assert_equals(recorder.state, 'recording', 'MediaRecorder has been started successfully');
+ setTimeout(() => {
+ recorder.stop();
+ osc.stop();
+ }, 500);
+ }, 'MediaRecorder will fire a dataavailable event which only contains audio buffers 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 => {
+ reader.readAsText(blobEvent.data);
+ reader._onloadend_ = t.step_func(() => {
+ assert_not_equals(reader.result.indexOf('Audio'), -1, 'MediaRecorder successfully captured video buffers');
+ assert_not_equals(reader.result.indexOf('Video'), -1, 'MediaRecorder does not capture audio buffers for a video-only stream');
+ t.done();
+ });
+ });
+ recorder.start();
+ osc.start();
+ drawSomethingOnCanvas();
+ assert_equals(recorder.state, 'recording', 'MediaRecorder has been started successfully');
+ setTimeout(() => {
+ recorder.stop();
+ osc.stop();
+ }, 500);
+ }, 'MediaRecorder will fire a dataavailable event which only contains both video and audio buffers when stop() is called');
+
+</script>
+</body>
+</html>
\ No newline at end of file
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (237641 => 237642)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2018-10-31 17:19:27 UTC (rev 237642)
@@ -1,3 +1,17 @@
+2018-10-31 YUHAN WU <yuhan...@apple.com>
+
+ MediaRecorder should fire dataavailable event when all tracks are ended and stop() is called
+ https://bugs.webkit.org/show_bug.cgi?id=190778
+
+ Reviewed by Youenn Fablet.
+
+ * web-platform-tests/mediacapture-record/BlobEvent-constructor-expected.txt:
+ * web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution-expected.txt: Added.
+ * web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution.html: Added.
+ * web-platform-tests/mediacapture-record/MediaRecorder-stop-expected.txt:
+ * web-platform-tests/mediacapture-record/MediaRecorder-stop.html:
+ * web-platform-tests/mediacapture-record/support/MediaRecorder-iframe.html: Added.
+
2018-10-30 Chris Dumez <cdu...@apple.com>
Resync XHR Web Platform Tests from upstream
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/BlobEvent-constructor-expected.txt (237641 => 237642)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/BlobEvent-constructor-expected.txt 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/BlobEvent-constructor-expected.txt 2018-10-31 17:19:27 UTC (rev 237642)
@@ -1,5 +1,5 @@
PASS The BlobEventInit dictionary is required
PASS The BlobEventInit dictionary's data member is required.
-FAIL The BlobEvent instance's data attribute is set. assert_equals: expected (object) object "[object Blob]" but got (undefined) undefined
+PASS The BlobEvent instance's data attribute is set.
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution-expected.txt (0 => 237642)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution-expected.txt 2018-10-31 17:19:27 UTC (rev 237642)
@@ -0,0 +1,4 @@
+
+PASS MediaRecorder will not fire the stop event when stop() is called and the script execution context is going away
+PASS MediaRecorder will not fire the stop event when all tracks are ended and the script execution context is going away
+
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution.html (0 => 237642)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution.html (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution.html 2018-10-31 17:19:27 UTC (rev 237642)
@@ -0,0 +1,47 @@
+<!doctype html>
+<meta charset="utf-8">
+<html>
+<title>MediaRecorder destroy script execution context</title>
+<script src=""
+<script src=""
+<body>
+<iframe src="" id="subFrame-stop" name="subFrameStop"></iframe>
+<iframe src="" id="subFrame-allTrackEnded" name="subFrameAllTrackEnded"></iframe>
+<script>
+ var iframeForCallingStop = document.getElementById('subFrame-stop');
+ var iframeForAllTrackEnded = document.getElementById('subFrame-allTrackEnded');
+
+ var testForCallingStop = async_test('MediaRecorder will not fire the stop event when stop() is called and the script execution context is going away');
+ var testForAllTrackEnded = async_test('MediaRecorder will not fire the stop event when all tracks are ended and the script execution context is going away');
+
+ iframeForCallingStop._onload_ = function(e) {
+ subFrameStop.window.prepareForTest();
+ const recorder = subFrameStop.window.recorder;
+ recorder._ondataavailable_ = testForCallingStop.step_func(blobEvent => {
+ iframeForCallingStop.remove();
+ testForCallingStop.step_timeout(testForCallingStop.step_func_done(), 0);
+ });
+ recorder._onstop_ = testForCallingStop.unreached_func('Unexpected stop event');
+ recorder.start();
+ assert_equals(recorder.state, 'recording', 'MediaRecorder has been started successfully');
+ subFrameStop.window.drawSomethingOnCanvas();
+ recorder.stop();
+ };
+
+ iframeForAllTrackEnded._onload_ = function(e) {
+ subFrameAllTrackEnded.window.prepareForTest();
+ const recorder = subFrameAllTrackEnded.window.recorder;
+ recorder._ondataavailable_ = testForAllTrackEnded.step_func(blobEvent => {
+ iframeForAllTrackEnded.remove();
+ testForAllTrackEnded.step_timeout(testForAllTrackEnded.step_func_done(), 0);
+ });
+ recorder._onstop_ = testForAllTrackEnded.unreached_func('Unexpected stop event');
+ recorder.start();
+ assert_equals(recorder.state, 'recording', 'MediaRecorder has been started successfully');
+ subFrameAllTrackEnded.window.drawSomethingOnCanvas();
+ subFrameAllTrackEnded.window.video.getVideoTracks()[0].stop();
+ };
+
+</script>
+</body>
+</html>
\ No newline at end of file
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-stop-expected.txt (237641 => 237642)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-stop-expected.txt 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-stop-expected.txt 2018-10-31 17:19:27 UTC (rev 237642)
@@ -1,3 +1,4 @@
PASS MediaRecorder will stop recording and fire a stop event when all tracks are ended
+PASS MediaRecorder will stop recording and fire a stop event when stop() is called
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-stop.html (237641 => 237642)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-stop.html 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-stop.html 2018-10-31 17:19:27 UTC (rev 237642)
@@ -29,7 +29,22 @@
recorder.start();
assert_equals(recorder.state, "recording", "MediaRecorder has been started successfully");
video.getVideoTracks()[0].stop();
- }, "MediaRecorder will stop recording and fire a stop event when all tracks are ended", { timeout: 10000 });
+ }, "MediaRecorder will stop recording and fire a stop event when all tracks are ended");
+
+ async_test(t => {
+ let video = createVideoStream();
+ let recorder = new MediaRecorder(video);
+ recorder._onstop_ = t.step_func(errorEvent => {
+ assert_equals(errorEvent.type, 'stop', 'the error type should be stop');
+ assert_true(errorEvent.isTrusted, 'isTrusted should be true when the event is created by C++');
+ assert_equals(recorder.state, "inactive", "MediaRecorder has been stopped when stop() is called");
+ t.done();
+ });
+ recorder.start();
+ assert_equals(recorder.state, "recording", "MediaRecorder has been started successfully");
+ recorder.stop();
+ assert_equals(recorder.state, "recording", "State should remain the same until stop event is fired");
+ }, "MediaRecorder will stop recording and fire a stop event when stop() is called");
</script>
</body>
</html>
\ No newline at end of file
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/support/MediaRecorder-iframe.html (0 => 237642)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/support/MediaRecorder-iframe.html (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/mediacapture-record/support/MediaRecorder-iframe.html 2018-10-31 17:19:27 UTC (rev 237642)
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Start a MediaRecorder</title>
+<html>
+<body>
+<canvas id="canvas" width="200px" height="200px"></canvas>
+<script>
+ var context;
+ var recorder;
+ var video;
+
+ 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 prepareForTest() {
+ video = createVideoStream();
+ recorder = new MediaRecorder(video);
+ }
+</script>
+</body>
+</html>
\ No newline at end of file
Modified: trunk/LayoutTests/platform/win/TestExpectations (237641 => 237642)
--- trunk/LayoutTests/platform/win/TestExpectations 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/LayoutTests/platform/win/TestExpectations 2018-10-31 17:19:27 UTC (rev 237642)
@@ -4222,9 +4222,9 @@
webkit.org/b/190032 legacy-animation-engine/animations/stacking-context-unchanged-while-running.html [ Pass ImageOnlyFailure ]
# MediaRecorder is not enabled on Windows
-imported/w3c/web-platform-tests/mediacapture-record/BlobEvent-constructor.html [ Skip ]
-imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-constructor.html [ Skip ]
+imported/w3c/web-platform-tests/mediacapture-record [ Skip ]
fast/mediacapturefromelement/CanvasCaptureMediaStream-imagebitmaprenderingcontext.html [ Skip ]
+http/wpt/mediarecorder [ Skip ]
webkit.org/b/190472 fast/forms/fieldset/fieldset-elements-htmlcollection.html [ Failure ]
Modified: trunk/Source/WebCore/CMakeLists.txt (237641 => 237642)
--- trunk/Source/WebCore/CMakeLists.txt 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/Source/WebCore/CMakeLists.txt 2018-10-31 17:19:27 UTC (rev 237642)
@@ -113,6 +113,7 @@
"${WEBCORE_DIR}/platform/graphics/iso"
"${WEBCORE_DIR}/platform/graphics/opentype"
"${WEBCORE_DIR}/platform/graphics/transforms"
+ "${WEBCORE_DIR}/platform/mediarecorder"
"${WEBCORE_DIR}/platform/mediastream"
"${WEBCORE_DIR}/platform/mediastream/libwebrtc"
"${WEBCORE_DIR}/platform/mock"
Modified: trunk/Source/WebCore/ChangeLog (237641 => 237642)
--- trunk/Source/WebCore/ChangeLog 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/Source/WebCore/ChangeLog 2018-10-31 17:19:27 UTC (rev 237642)
@@ -1,3 +1,52 @@
+2018-10-31 YUHAN WU <yuhan...@apple.com>
+
+ MediaRecorder should fire dataavailable event when all tracks are ended and stop() is called
+ https://bugs.webkit.org/show_bug.cgi?id=190778
+
+ Reviewed by Youenn Fablet.
+
+ Implement _javascript_ dispatch event dataavailable and _javascript_ exposed method stop().
+ Implement a mock string as the output buffer of MediaRecorder.
+ Remove the declaration of timecode in BlobEvent since it has not been implemented in MediaRecorder and MediaRecorderPrivate.
+
+ Tests: http/wpt/mediarecorder/MediaRecorder-dataavailable.html
+ http/wpt/mediarecorder/MediaRecorder-mock-dataavailable.html
+ imported/w3c/web-platform-tests/mediacapture-record/MediaRecorder-destroy-script-execution.html
+ imported/w3c/web-platform-tests/mediacapture-record/support/MediaRecorder-iframe.html
+
+ * CMakeLists.txt:
+ * Modules/mediarecorder/BlobEvent.cpp: Added.
+ (WebCore::BlobEvent::create):
+ (WebCore::BlobEvent::BlobEvent):
+ (WebCore::BlobEvent::eventInterface const):
+ * Modules/mediarecorder/BlobEvent.h:
+ * Modules/mediarecorder/BlobEvent.idl:
+ * Modules/mediarecorder/MediaRecorder.cpp:
+ (WebCore::MediaRecorder::MediaRecorder):
+ (WebCore::MediaRecorder::~MediaRecorder):
+ (WebCore::MediaRecorder::stop):
+ (WebCore::MediaRecorder::startRecording):
+ (WebCore::MediaRecorder::stopRecording):
+ (WebCore::MediaRecorder::stopRecordingInternal):
+ (WebCore::MediaRecorder::didAddOrRemoveTrack):
+ (WebCore::MediaRecorder::trackEnded):
+ (WebCore::MediaRecorder::sampleBufferUpdated):
+ (WebCore::MediaRecorder::audioSamplesAvailable):
+ (WebCore::MediaRecorder::scheduleDeferredTask):
+ * Modules/mediarecorder/MediaRecorder.h:
+ * Modules/mediarecorder/MediaRecorder.idl:
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * dom/EventNames.h:
+ * dom/EventNames.in:
+ * platform/mediarecorder/MediaRecorderPrivate.h: Added.
+ * platform/mediarecorder/MediaRecorderPrivateMock.cpp: Added.
+ (WebCore::MediaRecorderPrivateMock::sampleBufferUpdated):
+ (WebCore::MediaRecorderPrivateMock::audioSamplesAvailable):
+ (WebCore::MediaRecorderPrivateMock::generateMockString):
+ (WebCore::MediaRecorderPrivateMock::fetchData):
+ * platform/mediarecorder/MediaRecorderPrivateMock.h: Added.
+
2018-10-31 Claudio Saavedra <csaave...@igalia.com>
[GTK][WPE] Remaining topPrivatelyControlledDomain() fixes
Copied: trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.cpp (from rev 237641, trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.h) (0 => 237642)
--- trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.cpp (rev 0)
+++ trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.cpp 2018-10-31 17:19:27 UTC (rev 237642)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+#include "BlobEvent.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "Blob.h"
+
+namespace WebCore {
+
+Ref<BlobEvent> BlobEvent::create(const AtomicString& type, Init&& init, IsTrusted isTrusted)
+{
+ return adoptRef(*new BlobEvent(type, WTFMove(init), isTrusted));
+}
+
+Ref<BlobEvent> BlobEvent::create(const AtomicString& type, CanBubble canBubble, IsCancelable isCancelable, Ref<Blob>&& data)
+{
+ return adoptRef(*new BlobEvent(type, canBubble, isCancelable, WTFMove(data)));
+}
+
+BlobEvent::BlobEvent(const AtomicString& type, Init&& init, IsTrusted isTrusted)
+ : Event(type, init, isTrusted)
+ , m_blob(init.data.releaseNonNull())
+{
+}
+
+BlobEvent::BlobEvent(const AtomicString& type, CanBubble canBubble, IsCancelable isCancelable, Ref<Blob>&& data)
+ : Event(type, canBubble, isCancelable)
+ , m_blob(WTFMove(data))
+{
+}
+
+EventInterface BlobEvent::eventInterface() const
+{
+ return BlobEventInterfaceType;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
Modified: trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.h (237641 => 237642)
--- trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.h 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.h 2018-10-31 17:19:27 UTC (rev 237642)
@@ -39,16 +39,19 @@
double timecode;
};
- static Ref<BlobEvent> create(const AtomicString& type, Init&& init, IsTrusted isTrusted = IsTrusted::No)
- {
- return adoptRef(*new BlobEvent(type, WTFMove(init), isTrusted));
- }
+ static Ref<BlobEvent> create(const AtomicString&, Init&&, IsTrusted = IsTrusted::No);
+ static Ref<BlobEvent> create(const AtomicString&, CanBubble, IsCancelable, Ref<Blob>&&);
+ Blob& data() const { return m_blob.get(); }
+
private:
- BlobEvent(const AtomicString& type, Init&& init, IsTrusted isTrusted)
- : Event(type, WTFMove(init), isTrusted)
- {
- }
+ BlobEvent(const AtomicString&, Init&&, IsTrusted);
+ BlobEvent(const AtomicString&, CanBubble, IsCancelable, Ref<Blob>&&);
+
+ // Event
+ EventInterface eventInterface() const final;
+
+ Ref<Blob> m_blob;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.idl (237641 => 237642)
--- trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.idl 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.idl 2018-10-31 17:19:27 UTC (rev 237642)
@@ -31,7 +31,7 @@
Exposed=Window
] interface BlobEvent : Event {
// FIXME: Implement these:
- // [SameObject] readonly attribute Blob data;
+ [SameObject] readonly attribute Blob data;
// readonly attribute DOMHighResTimeStamp timecode;
};
Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp (237641 => 237642)
--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp 2018-10-31 17:19:27 UTC (rev 237642)
@@ -28,9 +28,12 @@
#if ENABLE(MEDIA_STREAM)
+#include "Blob.h"
+#include "BlobEvent.h"
#include "Document.h"
#include "EventNames.h"
#include "MediaRecorderErrorEvent.h"
+#include "MediaRecorderPrivateMock.h"
namespace WebCore {
@@ -45,11 +48,10 @@
: ActiveDOMObject(&document)
, m_options(WTFMove(option))
, m_stream(WTFMove(stream))
+ , m_private(makeUniqueRef<MediaRecorderPrivateMock>()) // FIXME: we will need to decide which MediaRecorderPrivate instance to create based on the mock enabled feature flag
{
- m_tracks = WTF::map(m_stream->getTracks(), [this] (const auto& track) -> Ref<MediaStreamTrackPrivate> {
- auto& privateTrack = track->privateTrack();
- privateTrack.addObserver(*this);
- return privateTrack;
+ m_tracks = WTF::map(m_stream->getTracks(), [] (auto&& track) -> Ref<MediaStreamTrackPrivate> {
+ return track->privateTrack();
});
m_stream->addObserver(this);
}
@@ -57,13 +59,13 @@
MediaRecorder::~MediaRecorder()
{
m_stream->removeObserver(this);
- for (auto& track : m_tracks)
- track->removeObserver(*this);
+ stopRecordingInternal();
}
void MediaRecorder::stop()
{
m_isActive = false;
+ stopRecordingInternal();
}
const char* MediaRecorder::activeDOMObjectName() const
@@ -76,16 +78,49 @@
return false; // FIXME: We should do better here as this prevents entering PageCache.
}
-ExceptionOr<void> MediaRecorder::start(std::optional<int> timeslice)
+ExceptionOr<void> MediaRecorder::startRecording(std::optional<int> timeslice)
{
UNUSED_PARAM(timeslice);
if (state() != RecordingState::Inactive)
return Exception { InvalidStateError, "The MediaRecorder's state must be inactive in order to start recording"_s };
+ for (auto& track : m_tracks)
+ track->addObserver(*this);
+
m_state = RecordingState::Recording;
return { };
}
+ExceptionOr<void> MediaRecorder::stopRecording()
+{
+ if (state() == RecordingState::Inactive)
+ return Exception { InvalidStateError, "The MediaRecorder's state cannot be inactive"_s };
+
+ scheduleDeferredTask([this] {
+ if (!m_isActive || state() == RecordingState::Inactive)
+ return;
+
+ stopRecordingInternal();
+ ASSERT(m_state == RecordingState::Inactive);
+ dispatchEvent(BlobEvent::create(eventNames().dataavailableEvent, Event::CanBubble::No, Event::IsCancelable::No, m_private->fetchData()));
+ if (!m_isActive)
+ return;
+ dispatchEvent(Event::create(eventNames().stopEvent, Event::CanBubble::No, Event::IsCancelable::No));
+ });
+ return { };
+}
+
+void MediaRecorder::stopRecordingInternal()
+{
+ if (state() != RecordingState::Recording)
+ return;
+
+ for (auto& track : m_tracks)
+ track->removeObserver(*this);
+
+ m_state = RecordingState::Inactive;
+}
+
void MediaRecorder::didAddOrRemoveTrack()
{
scheduleDeferredTask([this] {
@@ -103,15 +138,20 @@
});
if (position != notFound)
return;
- scheduleDeferredTask([this] {
- if (!m_isActive || state() == RecordingState::Inactive)
- return;
- // FIXME: Add a dataavailable event
- auto event = Event::create(eventNames().stopEvent, Event::CanBubble::No, Event::IsCancelable::No);
- setNewRecordingState(RecordingState::Inactive, WTFMove(event));
- });
+
+ stopRecording();
}
+void MediaRecorder::sampleBufferUpdated(MediaStreamTrackPrivate& track, MediaSample& mediaSample)
+{
+ m_private->sampleBufferUpdated(track, mediaSample);
+}
+
+void MediaRecorder::audioSamplesAvailable(MediaStreamTrackPrivate& track, const MediaTime& mediaTime, const PlatformAudioData& audioData, const AudioStreamDescription& description, size_t sampleCount)
+{
+ m_private->audioSamplesAvailable(track, mediaTime, audioData, description, sampleCount);
+}
+
void MediaRecorder::setNewRecordingState(RecordingState newState, Ref<Event>&& event)
{
m_state = newState;
@@ -124,10 +164,7 @@
auto* scriptExecutionContext = this->scriptExecutionContext();
if (!scriptExecutionContext)
return;
- scriptExecutionContext->postTask([weakThis = makeWeakPtr(*this), function = WTFMove(function)] (auto&) {
- if (!weakThis)
- return;
-
+ scriptExecutionContext->postTask([protectedThis = makeRef(*this), function = WTFMove(function)] (auto&) {
function();
});
}
Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h (237641 => 237642)
--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.h 2018-10-31 17:19:27 UTC (rev 237642)
@@ -25,14 +25,17 @@
#pragma once
#if ENABLE(MEDIA_STREAM)
+
#include "ActiveDOMObject.h"
#include "EventTarget.h"
#include "MediaStream.h"
#include "MediaStreamTrackPrivate.h"
+#include <wtf/UniqueRef.h>
namespace WebCore {
class Document;
+class MediaRecorderPrivate;
class MediaRecorder final
: public ActiveDOMObject
@@ -60,7 +63,8 @@
using RefCounted::ref;
using RefCounted::deref;
- ExceptionOr<void> start(std::optional<int>);
+ ExceptionOr<void> startRecording(std::optional<int>);
+ ExceptionOr<void> stopRecording();
private:
MediaRecorder(Document&, Ref<MediaStream>&&, Options&& = { });
@@ -76,6 +80,8 @@
const char* activeDOMObjectName() const final;
bool canSuspendForDocumentSuspension() const final;
+ void stopRecordingInternal();
+
// MediaStream::Observer
void didAddOrRemoveTrack() final;
@@ -84,6 +90,8 @@
void trackMutedChanged(MediaStreamTrackPrivate&) final { };
void trackSettingsChanged(MediaStreamTrackPrivate&) final { };
void trackEnabledChanged(MediaStreamTrackPrivate&) final { };
+ void sampleBufferUpdated(MediaStreamTrackPrivate&, MediaSample&) final;
+ void audioSamplesAvailable(MediaStreamTrackPrivate&, const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
void scheduleDeferredTask(Function<void()>&&);
void setNewRecordingState(RecordingState, Ref<Event>&&);
@@ -90,6 +98,7 @@
Options m_options;
Ref<MediaStream> m_stream;
+ UniqueRef<MediaRecorderPrivate> m_private;
RecordingState m_state { RecordingState::Inactive };
Vector<Ref<MediaStreamTrackPrivate>> m_tracks;
Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.idl (237641 => 237642)
--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.idl 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.idl 2018-10-31 17:19:27 UTC (rev 237642)
@@ -38,7 +38,7 @@
// readonly attribute DOMString mimeType;
// attribute EventHandler onstart;
attribute EventHandler onstop;
- // attribute EventHandler ondataavailable;
+ attribute EventHandler ondataavailable;
// attribute EventHandler onpause;
// attribute EventHandler onresume;
attribute EventHandler onerror;
@@ -45,8 +45,8 @@
// readonly attribute unsigned long videoBitsPerSecond;
// readonly attribute unsigned long audioBitsPerSecond;
- [MayThrowException] void start(optional long timeslice);
- // void stop();
+ [MayThrowException, ImplementedAs=startRecording] void start(optional long timeslice);
+ [ImplementedAs=stopRecording] void stop();
// void pause();
// void resume();
// void requestData();
Modified: trunk/Source/WebCore/Sources.txt (237641 => 237642)
--- trunk/Source/WebCore/Sources.txt 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/Source/WebCore/Sources.txt 2018-10-31 17:19:27 UTC (rev 237642)
@@ -140,6 +140,7 @@
Modules/mediacontrols/MediaControlsHost.cpp
+Modules/mediarecorder/BlobEvent.cpp
Modules/mediarecorder/MediaRecorder.cpp
Modules/mediarecorder/MediaRecorderErrorEvent.cpp
@@ -1767,6 +1768,8 @@
platform/mediacapabilities/MediaEngineConfigurationFactory.cpp
+platform/mediarecorder/MediaRecorderPrivateMock.cpp
+
platform/mediastream/CaptureDeviceManager.cpp
platform/mediastream/MediaConstraints.cpp
platform/mediastream/MediaEndpointConfiguration.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (237641 => 237642)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-10-31 17:19:27 UTC (rev 237642)
@@ -1360,6 +1360,7 @@
4BDA40012151B6F500FD6604 /* CSSRegisteredCustomProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BDA3FFB2151B6F400FD6604 /* CSSRegisteredCustomProperty.h */; settings = {ATTRIBUTES = (Private, ); }; };
4D3B00AB215D69A70076B983 /* MediaRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D3B00A9215D69A70076B983 /* MediaRecorder.h */; };
4D3B00AF215D6A690076B983 /* BlobEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D3B00AD215D6A690076B983 /* BlobEvent.h */; };
+ 4D3B5016217E58B700665DB1 /* MediaRecorderPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D3B5014217E58B700665DB1 /* MediaRecorderPrivate.h */; };
4DB7130D216ECB4D0096A4DD /* MediaRecorderErrorEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DB7130C216EC2BD0096A4DD /* MediaRecorderErrorEvent.h */; };
4E1959220A39DABA00220FE5 /* MediaFeatureNames.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E1959200A39DABA00220FE5 /* MediaFeatureNames.h */; settings = {ATTRIBUTES = (Private, ); }; };
4E19592A0A39DACC00220FE5 /* MediaQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E1959240A39DACC00220FE5 /* MediaQuery.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -7920,6 +7921,10 @@
4D3B00A8215D69A60076B983 /* MediaRecorder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaRecorder.cpp; sourceTree = "<group>"; };
4D3B00A9215D69A70076B983 /* MediaRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaRecorder.h; sourceTree = "<group>"; };
4D3B00AD215D6A690076B983 /* BlobEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlobEvent.h; sourceTree = "<group>"; };
+ 4D3B5014217E58B700665DB1 /* MediaRecorderPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MediaRecorderPrivate.h; sourceTree = "<group>"; };
+ 4D7EB3F4217C6AE600D64888 /* BlobEvent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BlobEvent.cpp; sourceTree = "<group>"; };
+ 4D9F6B642182532B0092A9C5 /* MediaRecorderPrivateMock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MediaRecorderPrivateMock.h; sourceTree = "<group>"; };
+ 4D9F6B652182532B0092A9C5 /* MediaRecorderPrivateMock.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MediaRecorderPrivateMock.cpp; sourceTree = "<group>"; };
4DB7130A216EC2BC0096A4DD /* MediaRecorderErrorEvent.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MediaRecorderErrorEvent.idl; sourceTree = "<group>"; };
4DB7130C216EC2BD0096A4DD /* MediaRecorderErrorEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaRecorderErrorEvent.h; sourceTree = "<group>"; };
4DB7130E216EEBAE0096A4DD /* MediaRecorderErrorEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaRecorderErrorEvent.cpp; sourceTree = "<group>"; };
@@ -18037,6 +18042,7 @@
4D3B00A0215D5C0F0076B983 /* mediarecorder */ = {
isa = PBXGroup;
children = (
+ 4D7EB3F4217C6AE600D64888 /* BlobEvent.cpp */,
4D3B00AD215D6A690076B983 /* BlobEvent.h */,
4D3B00A6215D645B0076B983 /* BlobEvent.idl */,
4D3B00A8215D69A60076B983 /* MediaRecorder.cpp */,
@@ -18049,6 +18055,16 @@
path = mediarecorder;
sourceTree = "<group>";
};
+ 4D3B5012217E58A300665DB1 /* mediarecorder */ = {
+ isa = PBXGroup;
+ children = (
+ 4D3B5014217E58B700665DB1 /* MediaRecorderPrivate.h */,
+ 4D9F6B652182532B0092A9C5 /* MediaRecorderPrivateMock.cpp */,
+ 4D9F6B642182532B0092A9C5 /* MediaRecorderPrivateMock.h */,
+ );
+ path = mediarecorder;
+ sourceTree = "<group>";
+ };
510310421BA8C64C003329C0 /* client */ = {
isa = PBXGroup;
children = (
@@ -24831,6 +24847,7 @@
A59E3C1B11580F340072928E /* ios */,
6582A14809999D6C00BEEB6D /* mac */,
9AC6F02021148F1E00CBDA06 /* mediacapabilities */,
+ 4D3B5012217E58A300665DB1 /* mediarecorder */,
C96F5EBF1B5872260091EA9D /* mediasession */,
07221B9217CF0AD400848E51 /* mediastream */,
59C77F101054591C00506104 /* mock */,
@@ -29945,6 +29962,7 @@
4471710E205AF945000A116E /* MediaQueryParserContext.h in Headers */,
4D3B00AB215D69A70076B983 /* MediaRecorder.h in Headers */,
4DB7130D216ECB4D0096A4DD /* MediaRecorderErrorEvent.h in Headers */,
+ 4D3B5016217E58B700665DB1 /* MediaRecorderPrivate.h in Headers */,
C90843D01B18E47D00B68564 /* MediaRemoteControls.h in Headers */,
CD8ACA8F1D23971900ECC59E /* MediaRemoteSoftLink.h in Headers */,
CEEFCD7A19DB31F7003876D7 /* MediaResourceLoader.h in Headers */,
Modified: trunk/Source/WebCore/dom/EventNames.h (237641 => 237642)
--- trunk/Source/WebCore/dom/EventNames.h 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/Source/WebCore/dom/EventNames.h 2018-10-31 17:19:27 UTC (rev 237642)
@@ -101,6 +101,7 @@
macro(copy) \
macro(cuechange) \
macro(cut) \
+ macro(dataavailable) \
macro(datachannel) \
macro(dblclick) \
macro(devicechange) \
Modified: trunk/Source/WebCore/dom/EventNames.in (237641 => 237642)
--- trunk/Source/WebCore/dom/EventNames.in 2018-10-31 16:39:06 UTC (rev 237641)
+++ trunk/Source/WebCore/dom/EventNames.in 2018-10-31 17:19:27 UTC (rev 237642)
@@ -47,6 +47,7 @@
ApplePayShippingMethodSelectedEvent conditional=APPLE_PAY
ApplePayValidateMerchantEvent conditional=APPLE_PAY
AudioProcessingEvent conditional=WEB_AUDIO
+BlobEvent conditional=MEDIA_STREAM
OfflineAudioCompletionEvent conditional=WEB_AUDIO
MediaRecorderErrorEvent conditional=MEDIA_STREAM
MediaStreamTrackEvent conditional=MEDIA_STREAM
Copied: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h (from rev 237641, trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.h) (0 => 237642)
--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h (rev 0)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h 2018-10-31 17:19:27 UTC (rev 237642)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(MEDIA_STREAM)
+
+namespace WTF {
+class MediaTime;
+}
+
+namespace WebCore {
+
+class AudioStreamDescription;
+class Blob;
+class PlatformAudioData;
+class MediaSample;
+class MediaStreamTrackPrivate;
+
+class MediaRecorderPrivate {
+public:
+ virtual void sampleBufferUpdated(MediaStreamTrackPrivate&, MediaSample&) = 0;
+ virtual void audioSamplesAvailable(MediaStreamTrackPrivate&, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) = 0;
+
+ virtual Ref<Blob> fetchData() = 0;
+ virtual ~MediaRecorderPrivate() = default;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
Copied: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.cpp (from rev 237641, trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.h) (0 => 237642)
--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.cpp (rev 0)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.cpp 2018-10-31 17:19:27 UTC (rev 237642)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+#include "MediaRecorderPrivateMock.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "Blob.h"
+#include "MediaStreamTrackPrivate.h"
+
+namespace WebCore {
+
+void MediaRecorderPrivateMock::sampleBufferUpdated(MediaStreamTrackPrivate& track, MediaSample&)
+{
+ generateMockString(track);
+}
+
+void MediaRecorderPrivateMock::audioSamplesAvailable(MediaStreamTrackPrivate& track, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t)
+{
+ generateMockString(track);
+}
+
+void MediaRecorderPrivateMock::generateMockString(MediaStreamTrackPrivate& track)
+{
+ auto locker = holdLock(m_bufferLock);
+ if (track.type() == RealtimeMediaSource::Type::Audio)
+ m_buffer.append("Audio Track ID: ");
+ else
+ m_buffer.append("Video Track ID: ");
+ m_buffer.append(track.id());
+ m_buffer.append(" Counter: ");
+ m_buffer.appendNumber(++m_counter);
+ m_buffer.append("\r\n---------\r\n");
+}
+
+Ref<Blob> MediaRecorderPrivateMock::fetchData()
+{
+ auto locker = holdLock(m_bufferLock);
+ Vector<uint8_t> value(m_buffer.length());
+ memcpy(value.data(), m_buffer.characters8(), m_buffer.length());
+ m_buffer.clear();
+ return Blob::create(WTFMove(value), "text/plain");
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
Copied: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.h (from rev 237641, trunk/Source/WebCore/Modules/mediarecorder/BlobEvent.h) (0 => 237642)
--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.h (rev 0)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.h 2018-10-31 17:19:27 UTC (rev 237642)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "MediaRecorderPrivate.h"
+#include <wtf/Lock.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+class Blob;
+class MediaStreamTrackPrivate;
+
+class MediaRecorderPrivateMock final : public MediaRecorderPrivate {
+private:
+ void sampleBufferUpdated(MediaStreamTrackPrivate&, MediaSample&) final;
+ void audioSamplesAvailable(MediaStreamTrackPrivate&, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final;
+ Ref<Blob> fetchData() final;
+
+ void generateMockString(MediaStreamTrackPrivate&);
+
+ mutable Lock m_bufferLock;
+ StringBuilder m_buffer;
+ unsigned m_counter { 0 };
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)