Add Experimental Feature support for SourceBuffer.changeType()
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 16 Aug 2018 17:57:01 +0000 (17:57 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 16 Aug 2018 17:57:01 +0000 (17:57 +0000)
https://bugs.webkit.org/show_bug.cgi?id=188626
LayoutTests/imported/w3c:

Reviewed by Eric Carlson.

* resources/import-expectations.json:
* web-platform-tests/media-source/mediasource-changetype-expected.txt: Added.
* web-platform-tests/media-source/mediasource-changetype-play-expected.txt: Added.
* web-platform-tests/media-source/mediasource-changetype-play.html: Added.
* web-platform-tests/media-source/mediasource-changetype-util.js: Added.
(findSupportedChangeTypeTestTypes):
(appendBuffer):
(trimBuffered):
(trimDuration):
(runChangeTypeTest):
(mediaSourceChangeTypeTest):
* web-platform-tests/media-source/mediasource-changetype.html: Added.
* web-platform-tests/media-source/mp3/sound_5.mp3: Added.
* web-platform-tests/media-source/mp3/w3c-import.log: Added.
* web-platform-tests/media-source/w3c-import.log:
* web-platform-tests/media-source/webm/test-vp9.webm: Added.
* web-platform-tests/media-source/webm/w3c-import.log:

Source/WebCore:

Reviewed by Eric Carlson.

Tests: imported/w3c/web-platform-tests/media-source/mediasource-changetype-play.html
       imported/w3c/web-platform-tests/media-source/mediasource-changetype.html

The WICG is incubating a new proposal to allow clients to switch between streams
with different codecs within the same SourceBuffer. The proposal is being tracked
by <https://github.com/w3c/media-source/issues/155> and the proposed spec change
is available at <https://rawgit.com/wicg/media-source/codec-switching/index.html>.

Drive-by fix: One of the wpt tests uses a .mp3 file to test SourceBuffer switching.
The AVStreamDataParser does not necessarily emit every frame appended, and after a
new init segment is appended, it's possible that frames from the previous media
segment will be emitted. This causes an error condition to occur, due to an added
check in the spec for a new flag. When the SourceBuffer asks its private implementation
to reset the parser state, since there's no API on AVStreamDataParser to actually
reset the parser state, just set a flag to drop all emitted buffers until the next
initialization segment is parsed.

* Modules/mediasource/MediaSource.cpp:
(WebCore::MediaSource::contentTypeShouldGenerateTimestamps):
(WebCore::MediaSource::setDurationInternal):
(WebCore::MediaSource::addSourceBuffer):
* Modules/mediasource/MediaSource.h:
* Modules/mediasource/SourceBuffer.cpp:
(WebCore::SourceBuffer::changeType):
(WebCore::SourceBuffer::sourceBufferPrivateDidReceiveInitializationSegment):
(WebCore::SourceBuffer::validateInitializationSegment):
(WebCore::SourceBuffer::sourceBufferPrivateDidReceiveSample):
* Modules/mediasource/SourceBuffer.h:
* Modules/mediasource/SourceBuffer.idl:
* page/Settings.yaml:
* platform/graphics/SourceBufferPrivate.h:
(WebCore::SourceBufferPrivate::canSwitchToType):
* platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
* platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
(WebCore::SourceBufferPrivateAVFObjC::didParseStreamDataAsAsset):
(WebCore::SourceBufferPrivateAVFObjC::processCodedFrame):
(WebCore::SourceBufferPrivateAVFObjC::resetParserState):
(WebCore::SourceBufferPrivateAVFObjC::canSwitchToType):

Source/WebKit:

Reviewed by Eric Carlson.

* Shared/WebPreferences.yaml:
* UIProcess/API/C/WKPreferences.cpp:
(WKPreferencesSetSourceBufferChangeTypeEnabled):
(WKPreferencesGetSourceBufferChangeTypeEnabled):
* UIProcess/API/C/WKPreferencesRefPrivate.h:

Source/WebKitLegacy/mac:

<rdar://problem/43356021>

Reviewed by Eric Carlson.

Add a new WebPreference property mapping to the WebCore SourceBufferChangeTypeEnabled setting.

* WebView/WebPreferenceKeysPrivate.h:
* WebView/WebPreferences.mm:
(+[WebPreferences initialize]):
(-[WebPreferences sourceBufferChangeTypeEnabled]):
(-[WebPreferences setSourceBufferChangeTypeEnabled:]):
* WebView/WebPreferencesPrivate.h:
* WebView/WebView.mm:
(-[WebView _preferencesChanged:]):

Tools:

<rdar://problem/43356021>

Reviewed by Eric Carlson.

* DumpRenderTree/mac/DumpRenderTree.mm:
(enableExperimentalFeatures):
(resetWebPreferencesToConsistentValues):
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::resetPreferencesToConsistentValues):

LayoutTests:

Reviewed by Eric Carlson.

* platform/mac/imported/w3c/web-platform-tests/media-source/mediasource-changetype-play-expected.txt: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@234940 268f45cc-cd09-0410-ab3c-d52691b4dbfc

36 files changed:
LayoutTests/ChangeLog
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/resources/import-expectations.json
LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-play-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-play.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-util.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/media-source/mp3/sound_5.mp3 [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/media-source/mp3/w3c-import.log [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/media-source/w3c-import.log
LayoutTests/imported/w3c/web-platform-tests/media-source/webm/test-vp9.webm [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/media-source/webm/w3c-import.log
LayoutTests/platform/mac/imported/w3c/web-platform-tests/media-source/mediasource-changetype-play-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/mediasource/MediaSource.cpp
Source/WebCore/Modules/mediasource/MediaSource.h
Source/WebCore/Modules/mediasource/SourceBuffer.cpp
Source/WebCore/Modules/mediasource/SourceBuffer.h
Source/WebCore/Modules/mediasource/SourceBuffer.idl
Source/WebCore/page/Settings.yaml
Source/WebCore/platform/graphics/SourceBufferPrivate.h
Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h
Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm
Source/WebKit/ChangeLog
Source/WebKit/Shared/WebPreferences.yaml
Source/WebKit/UIProcess/API/C/WKPreferences.cpp
Source/WebKit/UIProcess/API/C/WKPreferencesRefPrivate.h
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h
Source/WebKitLegacy/mac/WebView/WebPreferences.mm
Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h
Source/WebKitLegacy/mac/WebView/WebView.mm
Tools/ChangeLog
Tools/DumpRenderTree/mac/DumpRenderTree.mm
Tools/WebKitTestRunner/TestController.cpp

index 1353882..106a934 100644 (file)
@@ -1,3 +1,12 @@
+2018-08-15  Jer Noble  <jer.noble@apple.com>
+
+        Add Experimental Feature support for SourceBuffer.changeType()
+        https://bugs.webkit.org/show_bug.cgi?id=188626
+
+        Reviewed by Eric Carlson.
+
+        * platform/mac/imported/w3c/web-platform-tests/media-source/mediasource-changetype-play-expected.txt: Added.
+
 2018-08-16  Per Arne Vollan  <pvollan@apple.com>
 
         [win-ews] No such file or directory: u'/cygdrive/C/cygwin/home/buildbot/WebKit/WebKitBuild/Release/bin32/layout-test-results/pywebsocket.ws.log-out.txt'
index baaad25..e75f8fa 100644 (file)
@@ -1,3 +1,28 @@
+2018-08-15  Jer Noble  <jer.noble@apple.com>
+
+        Add Experimental Feature support for SourceBuffer.changeType()
+        https://bugs.webkit.org/show_bug.cgi?id=188626
+
+        Reviewed by Eric Carlson.
+
+        * resources/import-expectations.json:
+        * web-platform-tests/media-source/mediasource-changetype-expected.txt: Added.
+        * web-platform-tests/media-source/mediasource-changetype-play-expected.txt: Added.
+        * web-platform-tests/media-source/mediasource-changetype-play.html: Added.
+        * web-platform-tests/media-source/mediasource-changetype-util.js: Added.
+        (findSupportedChangeTypeTestTypes):
+        (appendBuffer):
+        (trimBuffered):
+        (trimDuration):
+        (runChangeTypeTest):
+        (mediaSourceChangeTypeTest):
+        * web-platform-tests/media-source/mediasource-changetype.html: Added.
+        * web-platform-tests/media-source/mp3/sound_5.mp3: Added.
+        * web-platform-tests/media-source/mp3/w3c-import.log: Added.
+        * web-platform-tests/media-source/w3c-import.log:
+        * web-platform-tests/media-source/webm/test-vp9.webm: Added.
+        * web-platform-tests/media-source/webm/w3c-import.log:
+
 2018-08-14  Ryosuke Niwa  <rniwa@webkit.org>
 
         connectedCallback is invoked by the HTML parser after child nodes had been inserted
index 579f1c1..b00f834 100644 (file)
     "web-platform-tests/magnetometer": "skip", 
     "web-platform-tests/mathml": "import", 
     "web-platform-tests/media-capabilities": "skip", 
+    "web-platform-tests/media-source": "import", 
     "web-platform-tests/mediacapture-image": "skip", 
     "web-platform-tests/mediacapture-record": "skip", 
     "web-platform-tests/mediacapture-streams": "import", 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-expected.txt
new file mode 100644 (file)
index 0000000..3249f21
--- /dev/null
@@ -0,0 +1,10 @@
+
+PASS Test changeType with an empty type. 
+PASS Test changeType after SourceBuffer removed from mediaSource. 
+PASS Test changeType while update pending. 
+PASS Test changeType with null type. 
+PASS Test changeType with unsupported type. 
+PASS Test changeType transitioning readyState from 'ended' to 'open'. 
+PASS Test changeType sets mode to sequence for change to type that generates timestamps 
+PASS Test changeType retains previous mode when changing to type that doesn't generate timestamps 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-play-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-play-expected.txt
new file mode 100644 (file)
index 0000000..ae96bee
--- /dev/null
@@ -0,0 +1,8 @@
+
+PASS Check if browser supports enough test media types
+PASS Test audio-only changeType for audio/mp4; codecs="mp4a.40.2" <-> audio/mp4; codecs="mp4a.40.2" 
+PASS Test audio-only changeType for audio/mp4; codecs="mp4a.40.2" <-> audio/mpeg 
+PASS Test audio-only changeType for audio/mpeg <-> audio/mp4; codecs="mp4a.40.2" 
+PASS Test audio-only changeType for audio/mpeg <-> audio/mpeg 
+PASS Test video-only changeType for video/mp4; codecs="avc1.4D4001" <-> video/mp4; codecs="avc1.4D4001" 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-play.html b/LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-play.html
new file mode 100644 (file)
index 0000000..c452714
--- /dev/null
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- Copyright © 2018 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
+<html>
+    <head>
+        <title>Exercise changeType for supported test types.</title>
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="mediasource-util.js"></script>
+        <script src="mediasource-changetype-util.js"></script>
+    </head>
+    <body>
+        <div id="log"></div>
+        <script>
+
+function generateChangeTypeTests(audio_types, video_types)
+{
+    async_test(function(test) {
+        assert_true(audio_types.length > 1, "Browser doesn't support at least 2 types of audio test media" + audio_types);
+        assert_true(video_types.length > 1, "Browser doesn't support at least 2 types of video test media");
+        test.done();
+    }, "Check if browser supports enough test media types");
+
+    // Generate audio-only changeType tests
+    for (let audio1 of audio_types) {
+        for (let audio2 of audio_types) {
+            mediaSourceChangeTypeTest(audio1, audio2, "Test audio-only changeType for " + audio1.type + " <-> " + audio2.type);
+        }
+    }
+
+    // Generate video-only changeType tests
+    for (let video1 of video_types) {
+        for (let video2 of video_types) {
+            mediaSourceChangeTypeTest(video1, video2, "Test video-only changeType for " + video1.type + " <-> " + video2.type);
+        }
+    }
+}
+
+findSupportedChangeTypeTestTypes(generateChangeTypeTests);
+
+        </script>
+    </body>
+</html>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-util.js b/LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-util.js
new file mode 100644 (file)
index 0000000..4e24223
--- /dev/null
@@ -0,0 +1,156 @@
+// Copyright © 2018 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang).
+
+function findSupportedChangeTypeTestTypes(cb)
+{
+    var CHANGE_TYPE_MEDIA_LIST = [
+        {
+            type: 'video/webm; codecs="vp8"',
+            is_video: true,
+            url: 'webm/test-v-128k-320x240-24fps-8kfr.webm'
+        },
+        {
+            type: 'video/webm; codecs="vp9"',
+            is_video: true,
+            url: 'webm/test-vp9.webm'
+        },
+        {
+            type: 'video/mp4; codecs="avc1.4D4001"',
+            is_video: true,
+            url: 'mp4/test-v-128k-320x240-24fps-8kfr.mp4'
+        },
+        {
+            type: 'audio/webm; codecs="vorbis"',
+            is_video: false,
+            url: 'webm/test-a-128k-44100Hz-1ch.webm'
+        },
+        {
+            type: 'audio/mp4; codecs="mp4a.40.2"',
+            is_video: false,
+            url: 'mp4/test-a-128k-44100Hz-1ch.mp4'
+        },
+        {
+            type: 'audio/mpeg',
+            is_video: false,
+            url: 'mp3/sound_5.mp3'
+        }
+    ];
+
+    var audio_result = [];
+    var video_result = [];
+
+    for (var i = 0; i < CHANGE_TYPE_MEDIA_LIST.length; ++i) {
+        var media = CHANGE_TYPE_MEDIA_LIST[i];
+        if (window.MediaSource && MediaSource.isTypeSupported(media.type)) {
+            if (media.is_video === true) {
+                video_result.push(media);
+            } else {
+                audio_result.push(media);
+            }
+        }
+    }
+
+
+    cb(audio_result, video_result);
+}
+
+function appendBuffer(test, sourceBuffer, data)
+{
+    test.expectEvent(sourceBuffer, "update");
+    test.expectEvent(sourceBuffer, "updateend");
+    sourceBuffer.appendBuffer(data);
+}
+
+function trimBuffered(test, mediaElement, sourceBuffer, minimumPreviousDuration, newDuration)
+{
+    assert_less_than(newDuration, minimumPreviousDuration);
+    assert_less_than(minimumPreviousDuration, mediaElement.duration);
+    test.expectEvent(sourceBuffer, "update");
+    test.expectEvent(sourceBuffer, "updateend");
+    sourceBuffer.remove(newDuration, Infinity);
+}
+
+function trimDuration(test, mediaElement, mediaSource, newDuration)
+{
+    assert_less_than(newDuration, mediaElement.duration);
+    test.expectEvent(mediaElement, "durationchange");
+    mediaSource.duration = newDuration;
+}
+
+function runChangeTypeTest(test, mediaElement, mediaSource, typeA, dataA, typeB, dataB)
+{
+    var sourceBuffer = mediaSource.addSourceBuffer(typeA);
+
+    appendBuffer(test, sourceBuffer, dataA);
+
+    // changeType A->B and append B starting at 0.5 seconds.
+    test.waitForExpectedEvents(function()
+    {
+        sourceBuffer.changeType(typeB);
+        sourceBuffer.timestampOffset = 0.5;
+        appendBuffer(test, sourceBuffer, dataB);
+    });
+
+    // changeType B->B and append B starting at 1.0 seconds.
+    test.waitForExpectedEvents(function()
+    {
+        sourceBuffer.changeType(typeB);
+        sourceBuffer.timestampOffset = 1.0;
+        appendBuffer(test, sourceBuffer, dataB);
+    });
+
+    // changeType B->A and append A starting at 1.5 seconds.
+    test.waitForExpectedEvents(function()
+    {
+        sourceBuffer.changeType(typeA);
+        sourceBuffer.timestampOffset = 1.5;
+        appendBuffer(test, sourceBuffer, dataA);
+    });
+
+    // changeTypoe A->A and append A starting at 1.3 seconds.
+    test.waitForExpectedEvents(function()
+    {
+        sourceBuffer.changeType(typeA);
+        sourceBuffer.timestampOffset = 1.3;
+        appendBuffer(test, sourceBuffer, dataA);
+    });
+
+    // Trim duration to 2 seconds, then play through to end.
+    test.waitForExpectedEvents(function()
+    {
+        trimBuffered(test, mediaElement, sourceBuffer, 2.1, 2);
+    });
+
+    test.waitForExpectedEvents(function()
+    {
+        trimDuration(test, mediaElement, mediaSource, 2);
+    });
+
+    test.waitForExpectedEvents(function()
+    {
+        assert_equals(mediaElement.currentTime, 0);
+        test.expectEvent(mediaSource, "sourceended");
+        test.expectEvent(mediaElement, "play");
+        test.expectEvent(mediaElement, "ended");
+        mediaSource.endOfStream();
+        mediaElement.play();
+    });
+
+    test.waitForExpectedEvents(function() {
+        test.done();
+    });
+}
+
+function mediaSourceChangeTypeTest(metadataA, metadataB, description)
+{
+    mediasource_test(function(test, mediaElement, mediaSource)
+    {
+        mediaElement.pause();
+        mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'"));
+        MediaSourceUtil.loadBinaryData(test, metadataA.url, function(dataA) {
+            MediaSourceUtil.loadBinaryData(test, metadataB.url, function(dataB) {
+                runChangeTypeTest(test, mediaElement, mediaSource, metadataA.type, dataA, metadataB.type, dataB);
+            });
+        });
+    }, description);
+}
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype.html b/LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype.html
new file mode 100644 (file)
index 0000000..263dd82
--- /dev/null
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<!-- Copyright © 2018 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
+<html>
+    <head>
+        <meta  charset="utf-8">
+        <title>SourceBuffer.changeType() test cases.</title>
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="mediasource-util.js"></script>
+    </head>
+    <body>
+        <div id="log"></div>
+        <script>
+mediasource_test(function(test, mediaElement, mediaSource)
+{
+    var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+
+    assert_throws(new TypeError(), function()
+    {
+        sourceBuffer.changeType("");
+    }, "changeType");
+
+    test.done();
+}, "Test changeType with an empty type.");
+
+mediasource_test(function(test, mediaElement, mediaSource)
+{
+    var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+
+    mediaSource.removeSourceBuffer(sourceBuffer);
+
+    assert_throws("InvalidStateError", function()
+    {
+        sourceBuffer.changeType(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+    }, "changeType");
+
+    test.done();
+}, "Test changeType after SourceBuffer removed from mediaSource.");
+
+mediasource_test(function(test, mediaElement, mediaSource)
+{
+    var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+    sourceBuffer.appendBuffer(new Uint8Array(0));
+    assert_true(sourceBuffer.updating, "Updating flag set when a buffer is appended.");
+
+    assert_throws("InvalidStateError", function()
+    {
+        sourceBuffer.changeType(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+    }, "changeType");
+
+    test.done();
+}, "Test changeType while update pending.");
+
+mediasource_test(function(test, mediaElement, mediaSource)
+{
+    var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+
+    var unsupported_type = null;
+    assert_false(MediaSource.isTypeSupported(unsupported_type), "null MIME type is not expected to be supported.");
+
+    assert_throws("NotSupportedError", function()
+    {
+        sourceBuffer.changeType(unsupported_type);
+    }, "changeType");
+
+    test.done();
+}, "Test changeType with null type.");
+
+mediasource_test(function(test, mediaElement, mediaSource)
+{
+    var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+
+    var unsupported_type = 'invalidType';
+    assert_false(MediaSource.isTypeSupported(unsupported_type), unsupported_type + " is not expected to be supported.");
+
+    assert_throws("NotSupportedError", function()
+    {
+        sourceBuffer.changeType(unsupported_type);
+    }, "changeType");
+
+    test.done();
+}, "Test changeType with unsupported type.");
+
+mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+{
+    test.expectEvent(sourceBuffer, "updatestart");
+    test.expectEvent(sourceBuffer, "update");
+    test.expectEvent(sourceBuffer, "updateend");
+    sourceBuffer.appendBuffer(mediaData);
+
+    test.waitForExpectedEvents(function()
+    {
+        mediaSource.endOfStream();
+        assert_equals(mediaSource.readyState, "ended");
+
+        test.expectEvent(mediaSource, "sourceopen");
+        sourceBuffer.changeType(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+        assert_equals(mediaSource.readyState, "open");
+    });
+
+    test.waitForExpectedEvents(function()
+    {
+        test.done();
+    });
+}, "Test changeType transitioning readyState from 'ended' to 'open'.");
+
+mediasource_test(function(test, mediaElement, mediaSource) {
+    var sequenceType = "audio/aac";
+    if (!MediaSource.isTypeSupported(sequenceType)) {
+      sequenceType = "audio/mpeg";
+      assert_true(MediaSource.isTypeSupported(sequenceType),
+                  "No bytestream that generates timestamps is supported, aborting test");
+    }
+
+    assert_not_equals(MediaSourceUtil.AUDIO_ONLY_TYPE, sequenceType,
+                      "This test requires distinct audio-only types");
+
+    var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_ONLY_TYPE);
+    assert_equals(sourceBuffer.mode, "segments",
+                  "None of the audioOnlyTypes in the test util generate timestamps, but mode is incorrectly set");
+
+    sourceBuffer.changeType(sequenceType);
+    assert_equals(sourceBuffer.mode, "sequence",
+                  "Mode is not updated correctly for a bytestream that generates timestamps");
+
+    test.done();
+}, "Test changeType sets mode to sequence for change to type that generates timestamps");
+
+mediasource_test(function(test, mediaElement, mediaSource) {
+    var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_ONLY_TYPE);
+
+    assert_equals(sourceBuffer.mode, "segments",
+                  "None of the audioOnlyTypes in the test util generate timestamps, but mode is incorrectly set");
+    sourceBuffer.changeType(MediaSourceUtil.AUDIO_ONLY_TYPE);
+    assert_equals(sourceBuffer.mode, "segments",
+                  "Previous segments mode is not retained correctly for changeType to one that doesn't generate timestamps");
+
+    sourceBuffer.mode = "sequence";
+    assert_equals(sourceBuffer.mode, "sequence", "mode should be sequence now");
+    sourceBuffer.changeType(MediaSourceUtil.AUDIO_ONLY_TYPE);
+    assert_equals(sourceBuffer.mode, "sequence",
+                  "Previous sequence mode is not retained correctly for changeType to one that doesn't generate timestamps");
+
+    test.done();
+}, "Test changeType retains previous mode when changing to type that doesn't generate timestamps");
+
+        </script>
+    </body>
+</html>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/media-source/mp3/sound_5.mp3 b/LayoutTests/imported/w3c/web-platform-tests/media-source/mp3/sound_5.mp3
new file mode 100644 (file)
index 0000000..bd20291
Binary files /dev/null and b/LayoutTests/imported/w3c/web-platform-tests/media-source/mp3/sound_5.mp3 differ
diff --git a/LayoutTests/imported/w3c/web-platform-tests/media-source/mp3/w3c-import.log b/LayoutTests/imported/w3c/web-platform-tests/media-source/mp3/w3c-import.log
new file mode 100644 (file)
index 0000000..cd8b48a
--- /dev/null
@@ -0,0 +1,17 @@
+The tests in this directory were imported from the W3C repository.
+Do NOT modify these tests directly in WebKit.
+Instead, create a pull request on the WPT github:
+       https://github.com/web-platform-tests/wpt
+
+Then run the Tools/Scripts/import-w3c-tests in WebKit to reimport
+
+Do NOT modify or remove this file.
+
+------------------------------------------------------------------------
+Properties requiring vendor prefixes:
+None
+Property values requiring vendor prefixes:
+None
+------------------------------------------------------------------------
+List of files:
+/LayoutTests/imported/w3c/web-platform-tests/media-source/mp3/sound_5.mp3
index 92e0eaf..c1de6ed 100644 (file)
@@ -1,7 +1,7 @@
 The tests in this directory were imported from the W3C repository.
 Do NOT modify these tests directly in WebKit.
 Instead, create a pull request on the WPT github:
-       https://github.com/w3c/web-platform-tests
+       https://github.com/web-platform-tests/wpt
 
 Then run the Tools/Scripts/import-w3c-tests in WebKit to reimport
 
@@ -34,6 +34,9 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-attach-stops-delaying-load-event.html
 /LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-avtracks.html
 /LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-buffered.html
+/LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-play.html
+/LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype-util.js
+/LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-changetype.html
 /LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-closed.html
 /LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-config-change-mp4-a-bitrate.html
 /LayoutTests/imported/w3c/web-platform-tests/media-source/mediasource-config-change-mp4-av-audio-bitrate.html
diff --git a/LayoutTests/imported/w3c/web-platform-tests/media-source/webm/test-vp9.webm b/LayoutTests/imported/w3c/web-platform-tests/media-source/webm/test-vp9.webm
new file mode 100644 (file)
index 0000000..d63dfda
Binary files /dev/null and b/LayoutTests/imported/w3c/web-platform-tests/media-source/webm/test-vp9.webm differ
index 9c10900..54943fc 100644 (file)
@@ -1,7 +1,7 @@
 The tests in this directory were imported from the W3C repository.
 Do NOT modify these tests directly in WebKit.
 Instead, create a pull request on the WPT github:
-       https://github.com/w3c/web-platform-tests
+       https://github.com/web-platform-tests/wpt
 
 Then run the Tools/Scripts/import-w3c-tests in WebKit to reimport
 
@@ -35,4 +35,5 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/media-source/webm/test-v-256k-320x240-30fps-10kfr-manifest.json
 /LayoutTests/imported/w3c/web-platform-tests/media-source/webm/test-v-256k-320x240-30fps-10kfr.webm
 /LayoutTests/imported/w3c/web-platform-tests/media-source/webm/test-vp8-vorbis-webvtt.webm
+/LayoutTests/imported/w3c/web-platform-tests/media-source/webm/test-vp9.webm
 /LayoutTests/imported/w3c/web-platform-tests/media-source/webm/test.webm
diff --git a/LayoutTests/platform/mac/imported/w3c/web-platform-tests/media-source/mediasource-changetype-play-expected.txt b/LayoutTests/platform/mac/imported/w3c/web-platform-tests/media-source/mediasource-changetype-play-expected.txt
new file mode 100644 (file)
index 0000000..46062ce
--- /dev/null
@@ -0,0 +1,8 @@
+
+FAIL Check if browser supports enough test media types assert_true: Browser doesn't support at least 2 types of video test media expected true got false
+PASS Test audio-only changeType for audio/mp4; codecs="mp4a.40.2" <-> audio/mp4; codecs="mp4a.40.2" 
+PASS Test audio-only changeType for audio/mp4; codecs="mp4a.40.2" <-> audio/mpeg 
+PASS Test audio-only changeType for audio/mpeg <-> audio/mp4; codecs="mp4a.40.2" 
+PASS Test audio-only changeType for audio/mpeg <-> audio/mpeg 
+PASS Test video-only changeType for video/mp4; codecs="avc1.4D4001" <-> video/mp4; codecs="avc1.4D4001" 
+
index 71177c9..b9c9001 100644 (file)
@@ -1,3 +1,49 @@
+2018-08-15  Jer Noble  <jer.noble@apple.com>
+
+        Add Experimental Feature support for SourceBuffer.changeType()
+        https://bugs.webkit.org/show_bug.cgi?id=188626
+
+        Reviewed by Eric Carlson.
+
+        Tests: imported/w3c/web-platform-tests/media-source/mediasource-changetype-play.html
+               imported/w3c/web-platform-tests/media-source/mediasource-changetype.html
+
+        The WICG is incubating a new proposal to allow clients to switch between streams
+        with different codecs within the same SourceBuffer. The proposal is being tracked
+        by <https://github.com/w3c/media-source/issues/155> and the proposed spec change
+        is available at <https://rawgit.com/wicg/media-source/codec-switching/index.html>.
+
+        Drive-by fix: One of the wpt tests uses a .mp3 file to test SourceBuffer switching.
+        The AVStreamDataParser does not necessarily emit every frame appended, and after a
+        new init segment is appended, it's possible that frames from the previous media
+        segment will be emitted. This causes an error condition to occur, due to an added
+        check in the spec for a new flag. When the SourceBuffer asks its private implementation
+        to reset the parser state, since there's no API on AVStreamDataParser to actually
+        reset the parser state, just set a flag to drop all emitted buffers until the next
+        initialization segment is parsed.
+
+        * Modules/mediasource/MediaSource.cpp:
+        (WebCore::MediaSource::contentTypeShouldGenerateTimestamps):
+        (WebCore::MediaSource::setDurationInternal):
+        (WebCore::MediaSource::addSourceBuffer):
+        * Modules/mediasource/MediaSource.h:
+        * Modules/mediasource/SourceBuffer.cpp:
+        (WebCore::SourceBuffer::changeType):
+        (WebCore::SourceBuffer::sourceBufferPrivateDidReceiveInitializationSegment):
+        (WebCore::SourceBuffer::validateInitializationSegment):
+        (WebCore::SourceBuffer::sourceBufferPrivateDidReceiveSample):
+        * Modules/mediasource/SourceBuffer.h:
+        * Modules/mediasource/SourceBuffer.idl:
+        * page/Settings.yaml:
+        * platform/graphics/SourceBufferPrivate.h:
+        (WebCore::SourceBufferPrivate::canSwitchToType):
+        * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
+        * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
+        (WebCore::SourceBufferPrivateAVFObjC::didParseStreamDataAsAsset):
+        (WebCore::SourceBufferPrivateAVFObjC::processCodedFrame):
+        (WebCore::SourceBufferPrivateAVFObjC::resetParserState):
+        (WebCore::SourceBufferPrivateAVFObjC::canSwitchToType):
+
 2018-08-16  Christopher Reid  <chris.reid@sony.com>
 
         [Curl] Not all Cookie database files are deleted on corruption
index 9aee75d..bf84281 100644 (file)
@@ -344,6 +344,11 @@ const MediaTime& MediaSource::currentTimeFudgeFactor()
     return fudgeFactor;
 }
 
+bool MediaSource::contentTypeShouldGenerateTimestamps(const ContentType& contentType)
+{
+    return contentType.containerType() == "audio/aac" || contentType.containerType() == "audio/mpeg";
+}
+
 bool MediaSource::hasBufferedTime(const MediaTime& time)
 {
     if (time > duration())
@@ -524,7 +529,7 @@ ExceptionOr<void> MediaSource::setDurationInternal(const MediaTime& duration)
     m_duration = newDuration;
 
     // 6. Update the media duration to new duration and run the HTMLMediaElement duration change algorithm.
-    LOG(MediaSource, "MediaSource::setDurationInternal(%p) - duration(%g)", this, duration.toDouble());
+    LOG(MediaSource, "MediaSource::setDurationInternal(%p) - duration(%s)", this, duration.toString().utf8().data());
     m_private->durationChanged();
 
     return { };
@@ -662,7 +667,7 @@ ExceptionOr<Ref<SourceBuffer>> MediaSource::addSourceBuffer(const String& type)
     // column of the byte stream format registry [MSE-REGISTRY] entry that is associated with type.
     // NOTE: In the current byte stream format registry <http://www.w3.org/2013/12/byte-stream-format-registry/>
     // only the "MPEG Audio Byte Stream Format" has the "Generate Timestamps Flag" value set.
-    bool shouldGenerateTimestamps = contentType.containerType() == "audio/aac" || contentType.containerType() == "audio/mpeg";
+    bool shouldGenerateTimestamps = contentTypeShouldGenerateTimestamps(contentType);
     buffer->setShouldGenerateTimestamps(shouldGenerateTimestamps);
 
     // 7. If the generate timestamps flag equals true:
index bd5cd7c..eca269e 100644 (file)
@@ -103,6 +103,7 @@ public:
     bool hasPendingActivity() const final;
 
     static const MediaTime& currentTimeFudgeFactor();
+    static bool contentTypeShouldGenerateTimestamps(const ContentType&);
 
 private:
     explicit MediaSource(ScriptExecutionContext&);
index a5266ee..44443c7 100644 (file)
@@ -348,6 +348,58 @@ void SourceBuffer::rangeRemoval(const MediaTime& start, const MediaTime& end)
     m_removeTimer.startOneShot(0_s);
 }
 
+ExceptionOr<void> SourceBuffer::changeType(const String& type)
+{
+    // changeType() proposed API. See issue #155: <https://github.com/w3c/media-source/issues/155>
+    // https://rawgit.com/wicg/media-source/codec-switching/index.html#dom-sourcebuffer-changetype
+
+    // 1. If type is an empty string then throw a TypeError exception and abort these steps.
+    if (type.isEmpty())
+        return Exception { TypeError };
+
+    // 2. If this object has been removed from the sourceBuffers attribute of the parent media source,
+    // then throw an InvalidStateError exception and abort these steps.
+    // 3. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
+    if (isRemoved() || m_updating)
+        return Exception { InvalidStateError };
+
+    // 4. If type contains a MIME type that is not supported or contains a MIME type that is not supported with
+    // the types specified (currently or previously) of SourceBuffer objects in the sourceBuffers attribute of
+    // the parent media source, then throw a NotSupportedError exception and abort these steps.
+    ContentType contentType(type);
+    if (!m_private->canSwitchToType(contentType))
+        return Exception { NotSupportedError };
+
+    // 5. If the readyState attribute of the parent media source is in the "ended" state then run the following
+    // steps:
+    // 5.1. Set the readyState attribute of the parent media source to "open"
+    // 5.2. Queue a task to fire a simple event named sourceopen at the parent media source.
+    m_source->openIfInEndedState();
+
+    // 6. Run the reset parser state algorithm.
+    resetParserState();
+
+    // 7. Update the generate timestamps flag on this SourceBuffer object to the value in the "Generate Timestamps
+    // Flag" column of the byte stream format registry [MSE-REGISTRY] entry that is associated with type.
+    setShouldGenerateTimestamps(MediaSource::contentTypeShouldGenerateTimestamps(contentType));
+
+    // ↳ If the generate timestamps flag equals true:
+    // Set the mode attribute on this SourceBuffer object to "sequence", including running the associated steps
+    // for that attribute being set.
+    if (m_shouldGenerateTimestamps)
+        setMode(AppendMode::Sequence);
+
+    // ↳ Otherwise:
+    // Keep the previous value of the mode attribute on this SourceBuffer object, without running any associated
+    // steps for that attribute being set.
+    // NOTE: No-op.
+
+    // 9. Set pending initialization segment for changeType flag to true.
+    m_pendingInitializationSegmentForChangeType = true;
+
+    return { };
+}
+
 void SourceBuffer::abortIfUpdating()
 {
     // Section 3.2 abort() method step 4 substeps.
@@ -1010,8 +1062,10 @@ void SourceBuffer::sourceBufferPrivateDidReceiveInitializationSegment(const Init
         //   Run the duration change algorithm with new duration set to the duration in the initialization segment.
         // ↳ Otherwise:
         //   Run the duration change algorithm with new duration set to positive Infinity.
-        MediaTime newDuration = segment.duration.isValid() ? segment.duration : MediaTime::positiveInfiniteTime();
-        m_source->setDurationInternal(newDuration);
+        if (segment.duration.isValid() && !segment.duration.isIndefinite())
+            m_source->setDurationInternal(segment.duration);
+        else
+            m_source->setDurationInternal(MediaTime::positiveInfiniteTime());
     }
 
     // 2. If the initialization segment has no audio, video, or text tracks, then run the append error algorithm
@@ -1206,6 +1260,10 @@ void SourceBuffer::sourceBufferPrivateDidReceiveInitializationSegment(const Init
         m_receivedFirstInitializationSegment = true;
     }
 
+    // (Note: Issue #155 adds this step after step 5:)
+    // 6. Set  pending initialization segment for changeType flag  to false.
+    m_pendingInitializationSegmentForChangeType = false;
+
     // 6. If the HTMLMediaElement.readyState attribute is HAVE_NOTHING, then run the following steps:
     if (m_private->readyState() == MediaPlayer::HaveNothing) {
         // 6.1 If one or more objects in sourceBuffers have first initialization segment flag set to false, then abort these steps.
@@ -1240,9 +1298,14 @@ bool SourceBuffer::validateInitializationSegment(const InitializationSegment& se
         return false;
 
     //   * The codecs for each track, match what was specified in the first initialization segment.
-    for (auto& audioTrackInfo : segment.audioTracks) {
-        if (!m_audioCodecs.contains(audioTrackInfo.description->codec()))
-            return false;
+    // (Note: Issue #155 strikes out this check. For broad compatibility when this experimental feature
+    // is not enabled, only perform this check if the "pending initialization segment for changeType flag"
+    // is not set.)
+    if (!m_pendingInitializationSegmentForChangeType) {
+        for (auto& audioTrackInfo : segment.audioTracks) {
+            if (!m_audioCodecs.contains(audioTrackInfo.description->codec()))
+                return false;
+        }
     }
 
     for (auto& videoTrackInfo : segment.videoTracks) {
@@ -1328,12 +1391,14 @@ void SourceBuffer::sourceBufferPrivateDidReceiveSample(MediaSample& sample)
         return;
 
     // 3.5.1 Segment Parser Loop
-    // 6.1 If the first initialization segment received flag is false, then run the append error algorithm
+    // 6.1 If the first initialization segment received flag is false, (Note: Issue # 155 & changeType()
+    // algorithm) or the  pending initialization segment for changeType flag  is true, (End note)
+    // then run the append error algorithm
     //     with the decode error parameter set to true and abort this algorithm.
     // Note: current design makes SourceBuffer somehow ignorant of append state - it's more a thing
     //  of SourceBufferPrivate. That's why this check can't really be done in appendInternal.
     //  unless we force some kind of design with state machine switching.
-    if (!m_receivedFirstInitializationSegment) {
+    if (!m_receivedFirstInitializationSegment || m_pendingInitializationSegmentForChangeType) {
         appendError(true);
         return;
     }
index 9a30799..aae7a7d 100644 (file)
@@ -79,6 +79,7 @@ public:
     ExceptionOr<void> abort();
     ExceptionOr<void> remove(double start, double end);
     ExceptionOr<void> remove(const MediaTime&, const MediaTime&);
+    ExceptionOr<void> changeType(const String&);
 
     const TimeRanges& bufferedInternal() const { ASSERT(m_buffered); return *m_buffered; }
 
@@ -235,6 +236,7 @@ private:
     bool m_active { false };
     bool m_bufferFull { false };
     bool m_shouldGenerateTimestamps { false };
+    bool m_pendingInitializationSegmentForChangeType { false };
 };
 
 } // namespace WebCore
index 4d8f732..031cf84 100644 (file)
@@ -68,4 +68,6 @@
     attribute EventHandler onupdateend;
     attribute EventHandler onerror;
     attribute EventHandler onabort;
+
+    [EnabledBySetting=SourceBufferChangeType, MayThrowException] void changeType(DOMString type);
 };
index 8562c17..f71fbc5 100644 (file)
@@ -432,6 +432,10 @@ mediaSourceEnabled:
   initial: true
   conditional: MEDIA_SOURCE
 
+sourceBufferChangeTypeEnabled:
+  initial: false
+  conditional: MEDIA_SOURCE
+
 # FIXME: Rename to allowMultiElementImplicitFormSubmission once we upstream the iOS changes to WebView.mm.
 allowMultiElementImplicitSubmission:
   initial: false
index 35592eb..b267e55 100644 (file)
@@ -63,6 +63,8 @@ public:
     virtual void notifyClientWhenReadyForMoreSamples(const AtomicString&) { }
 
     virtual Vector<String> enqueuedSamplesForTrackID(const AtomicString&) { return { }; }
+
+    virtual bool canSwitchToType(const ContentType&) { return false; }
 };
 
 }
index 11f2fa9..019cf37 100644 (file)
@@ -144,6 +144,7 @@ private:
     bool isReadyForMoreSamples(const AtomicString& trackID) final;
     void setActive(bool) final;
     void notifyClientWhenReadyForMoreSamples(const AtomicString& trackID) final;
+    bool canSwitchToType(const ContentType&) final;
 
     void didBecomeReadyForMoreSamples(int trackID);
     void appendCompleted();
@@ -194,6 +195,7 @@ private:
     FloatSize m_currentSize;
     bool m_parsingSucceeded { true };
     bool m_parserStateWasReset { false };
+    bool m_discardSamplesUntilNextInitializationSegment { false };
     int m_enabledVideoTrackID { -1 };
     int m_protectedTrackID { -1 };
 };
index 01bb81b..dc93478 100644 (file)
@@ -538,6 +538,8 @@ void SourceBufferPrivateAVFObjC::didParseStreamDataAsAsset(AVAsset* asset)
     m_videoTracks.clear();
     m_audioTracks.clear();
 
+    m_discardSamplesUntilNextInitializationSegment = false;
+
     SourceBufferPrivateClient::InitializationSegment segment;
 
     if ([m_asset respondsToSelector:@selector(overallDurationHint)])
@@ -607,6 +609,9 @@ bool SourceBufferPrivateAVFObjC::processCodedFrame(int trackID, CMSampleBufferRe
         return false;
     }
 
+    if (m_discardSamplesUntilNextInitializationSegment)
+        return false;
+
     if (m_client) {
         Ref<MediaSample> mediaSample = MediaSampleAVFObjC::create(sampleBuffer, trackID);
         LOG(MediaSourceSamples, "SourceBufferPrivateAVFObjC::processCodedFrame(%p) - sample(%s)", this, toString(mediaSample.get()).utf8().data());
@@ -746,6 +751,7 @@ void SourceBufferPrivateAVFObjC::abort()
 void SourceBufferPrivateAVFObjC::resetParserState()
 {
     m_parserStateWasReset = true;
+    m_discardSamplesUntilNextInitializationSegment = true;
 }
 
 void SourceBufferPrivateAVFObjC::destroyParser()
@@ -1197,6 +1203,14 @@ void SourceBufferPrivateAVFObjC::notifyClientWhenReadyForMoreSamples(const Atomi
     }
 }
 
+bool SourceBufferPrivateAVFObjC::canSwitchToType(const ContentType& contentType)
+{
+    MediaEngineSupportParameters parameters;
+    parameters.isMediaSource = true;
+    parameters.type = contentType;
+    return MediaPlayerPrivateMediaSourceAVFObjC::supportsType(parameters) != MediaPlayer::IsNotSupported;
+}
+
 void SourceBufferPrivateAVFObjC::setVideoLayer(AVSampleBufferDisplayLayer* layer)
 {
     if (layer == m_displayLayer)
index 270d018..5f05419 100644 (file)
@@ -1,3 +1,16 @@
+2018-08-15  Jer Noble  <jer.noble@apple.com>
+
+        Add Experimental Feature support for SourceBuffer.changeType()
+        https://bugs.webkit.org/show_bug.cgi?id=188626
+
+        Reviewed by Eric Carlson.
+
+        * Shared/WebPreferences.yaml:
+        * UIProcess/API/C/WKPreferences.cpp:
+        (WKPreferencesSetSourceBufferChangeTypeEnabled):
+        (WKPreferencesGetSourceBufferChangeTypeEnabled):
+        * UIProcess/API/C/WKPreferencesRefPrivate.h:
+
 2018-08-16  Alex Christensen  <achristensen@webkit.org>
 
         Transition more WKWebViewConfiguration ivars to API::PageConfiguration values
index cd2bfd5..260221c 100644 (file)
@@ -1309,3 +1309,10 @@ ProcessSwapOnNavigationEnabled:
   category: experimental
   webcoreBinding: none
 
+SourceBufferChangeTypeEnabled:
+  type: bool
+  defaultValue: DEFAULT_EXPERIMENTAL_FEATURES_ENABLED
+  humanReadableName: "Media Source Codec Switching Support"
+  humanReadableDescription: "Enable Media Source Codec Switching through changeType()"
+  category: experimental
+  condition: ENABLE(MEDIA_SOURCE)
index 8a5d651..cf39550 100644 (file)
@@ -1468,6 +1468,16 @@ bool WKPreferencesGetMediaSourceEnabled(WKPreferencesRef preferencesRef)
     return toImpl(preferencesRef)->mediaSourceEnabled();
 }
 
+void WKPreferencesSetSourceBufferChangeTypeEnabled(WKPreferencesRef preferencesRef, bool enabled)
+{
+    toImpl(preferencesRef)->setSourceBufferChangeTypeEnabled(enabled);
+}
+
+bool WKPreferencesGetSourceBufferChangeTypeEnabled(WKPreferencesRef preferencesRef)
+{
+    return toImpl(preferencesRef)->sourceBufferChangeTypeEnabled();
+}
+
 void WKPreferencesSetViewGestureDebuggingEnabled(WKPreferencesRef preferencesRef, bool enabled)
 {
     toImpl(preferencesRef)->setViewGestureDebuggingEnabled(enabled);
index df1619e..7cd4825 100644 (file)
@@ -377,6 +377,10 @@ WK_EXPORT bool WKPreferencesUseLegacyTextAlignPositionedElementBehavior(WKPrefer
 WK_EXPORT void WKPreferencesSetMediaSourceEnabled(WKPreferencesRef preferencesRef, bool enabled);
 WK_EXPORT bool WKPreferencesGetMediaSourceEnabled(WKPreferencesRef preferencesRef);
 
+// Defaults to false;
+WK_EXPORT void WKPreferencesSetSourceBufferChangeTypeEnabled(WKPreferencesRef preferencesRef, bool enabled);
+WK_EXPORT bool WKPreferencesGetSourceBufferChangeTypeEnabled(WKPreferencesRef preferencesRef);
+
 // Default to false.
 WK_EXPORT void WKPreferencesSetViewGestureDebuggingEnabled(WKPreferencesRef preferencesRef, bool enabled);
 WK_EXPORT bool WKPreferencesGetViewGestureDebuggingEnabled(WKPreferencesRef preferencesRef);
index 28e410e..2739595 100644 (file)
@@ -1,3 +1,22 @@
+2018-08-16  Jer Noble  <jer.noble@apple.com>
+
+        Add Experimental Feature support for SourceBuffer.changeType()
+        https://bugs.webkit.org/show_bug.cgi?id=188626
+        <rdar://problem/43356021>
+
+        Reviewed by Eric Carlson.
+
+        Add a new WebPreference property mapping to the WebCore SourceBufferChangeTypeEnabled setting.
+
+        * WebView/WebPreferenceKeysPrivate.h:
+        * WebView/WebPreferences.mm:
+        (+[WebPreferences initialize]):
+        (-[WebPreferences sourceBufferChangeTypeEnabled]):
+        (-[WebPreferences setSourceBufferChangeTypeEnabled:]):
+        * WebView/WebPreferencesPrivate.h:
+        * WebView/WebView.mm:
+        (-[WebView _preferencesChanged:]):
+
 2018-08-16  Aditya Keerthi  <akeerthi@apple.com>
 
         Support drag-and-drop for input[type=color]
index 9b18a7f..fc7bf74 100644 (file)
 #define WebKitLowPowerVideoAudioBufferSizeEnabledPreferenceKey @"WebKitLowPowerVideoAudioBufferSizeEnabled"
 #define WebKitUseLegacyTextAlignPositionedElementBehaviorPreferenceKey @"WebKitUseLegacyTextAlignPositionedElementBehavior"
 #define WebKitMediaSourceEnabledPreferenceKey @"WebKitMediaSourceEnabled"
+#define WebKitSourceBufferChangeTypeEnabledPreferenceKey @"WebKitSourceBufferChangeTypeEnabled"
 #define WebKitShouldConvertPositionStyleOnCopyPreferenceKey @"WebKitShouldConvertPositionStyleOnCopy"
 #define WebKitImageControlsEnabledPreferenceKey @"WebKitImageControlsEnabled"
 #define WebKitGamepadsEnabledPreferenceKey @"WebKitGamepadsEnabled"
index 4afda34..3a98607 100644 (file)
@@ -605,6 +605,7 @@ public:
         [NSNumber numberWithBool:NO], WebKitUseLegacyTextAlignPositionedElementBehaviorPreferenceKey,
 #if ENABLE(MEDIA_SOURCE)
         [NSNumber numberWithBool:YES], WebKitMediaSourceEnabledPreferenceKey,
+        @NO, WebKitSourceBufferChangeTypeEnabledPreferenceKey,
 #endif
 #if ENABLE(SERVICE_CONTROLS)
         [NSNumber numberWithBool:NO], WebKitImageControlsEnabledPreferenceKey,
@@ -2742,6 +2743,16 @@ static NSString *classIBCreatorID = nil;
     [self _setBoolValue:enabled forKey:WebKitMediaSourceEnabledPreferenceKey];
 }
 
+- (BOOL)sourceBufferChangeTypeEnabled
+{
+    return [self _boolValueForKey:WebKitSourceBufferChangeTypeEnabledPreferenceKey];
+}
+
+- (void)setSourceBufferChangeTypeEnabled:(BOOL)enabled
+{
+    [self _setBoolValue:enabled forKey:WebKitSourceBufferChangeTypeEnabledPreferenceKey];
+}
+
 - (BOOL)imageControlsEnabled
 {
     return [self _boolValueForKey:WebKitImageControlsEnabledPreferenceKey];
index 6bf0d48..2f1ddc4 100644 (file)
@@ -614,6 +614,7 @@ extern NSString *WebPreferencesCacheModelChangedInternalNotification WEBKIT_DEPR
 @property (nonatomic) BOOL ariaReflectionEnabled;
 @property (nonatomic) BOOL mediaCapabilitiesEnabled;
 @property (nonatomic) BOOL allowCrossOriginSubresourcesToAskForCredentials;
+@property (nonatomic) BOOL sourceBufferChangeTypeEnabled;
 
 #if TARGET_OS_IPHONE
 @property (nonatomic) BOOL quickLookDocumentSavingEnabled;
index d4d1e6e..7923346 100644 (file)
@@ -3021,6 +3021,7 @@ static bool needsSelfRetainWhileLoadingQuirk()
 
 #if ENABLE(MEDIA_SOURCE)
     settings.setMediaSourceEnabled([preferences mediaSourceEnabled]);
+    settings.setSourceBufferChangeTypeEnabled([preferences sourceBufferChangeTypeEnabled]);
 #endif
 
 #if ENABLE(SERVICE_CONTROLS)
index 7bbf463..f5e45bc 100644 (file)
@@ -1,3 +1,17 @@
+2018-08-16  Jer Noble  <jer.noble@apple.com>
+
+        Add Experimental Feature support for SourceBuffer.changeType()
+        https://bugs.webkit.org/show_bug.cgi?id=188626
+        <rdar://problem/43356021>
+
+        Reviewed by Eric Carlson.
+
+        * DumpRenderTree/mac/DumpRenderTree.mm:
+        (enableExperimentalFeatures):
+        (resetWebPreferencesToConsistentValues):
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::resetPreferencesToConsistentValues):
+
 2018-08-16  Aditya Keerthi  <akeerthi@apple.com>
 
         Support drag-and-drop for input[type=color]
index 5d52905..43069cc 100644 (file)
@@ -868,6 +868,7 @@ static void enableExperimentalFeatures(WebPreferences* preferences)
     [preferences setCrossOriginWindowPolicySupportEnabled:YES];
     [preferences setServerTimingEnabled:YES];
     [preferences setIntersectionObserverEnabled:YES];
+    preferences.sourceBufferChangeTypeEnabled = YES;
 }
 
 // Called before each test.
@@ -960,6 +961,7 @@ static void resetWebPreferencesToConsistentValues()
 
     [preferences setWebAudioEnabled:YES];
     [preferences setMediaSourceEnabled:YES];
+    [preferences setSourceBufferChangeTypeEnabled:YES];
 
     [preferences setShadowDOMEnabled:YES];
     [preferences setCustomElementsEnabled:YES];
index f3dc811..e3a62ea 100644 (file)
@@ -740,8 +740,9 @@ void TestController::resetPreferencesToConsistentValues(const TestOptions& optio
     WKPreferencesSetSansSerifFontFamily(preferences, sansSerifFontFamily);
     WKPreferencesSetSerifFontFamily(preferences, serifFontFamily);
     WKPreferencesSetAsynchronousSpellCheckingEnabled(preferences, false);
-#if ENABLE(WEB_AUDIO)
+#if ENABLE(MEDIA_SOURCE)
     WKPreferencesSetMediaSourceEnabled(preferences, true);
+    WKPreferencesSetSourceBufferChangeTypeEnabled(preferences, true);
 #endif
 
     WKPreferencesSetHiddenPageDOMTimerThrottlingEnabled(preferences, false);