Title: [179044] trunk
Revision
179044
Author
[email protected]
Date
2015-01-23 16:52:42 -0800 (Fri, 23 Jan 2015)

Log Message

[MSE] Implement Range Removal algorithm.
https://bugs.webkit.org/show_bug.cgi?id=140622.

Patch by Bartlomiej Gajda <[email protected]> on 2015-01-23
Reviewed by Jer Noble.

Source/WebCore:

This extract Range Removal algorithm (Editor's Draft version, bug:26316) from remove(),
to separate function to deal with old FIXME since bug in spec was resolved.
This should both guarantee good order of events, and prevent from switching to 'open' state
during end of stream.

Test: media/media-source/media-source-end-of-stream-readyState.html

* Modules/mediasource/MediaSource.cpp:
(WebCore::MediaSource::setDurationInternal): update to use rangeRemoval(), not remove()
(WebCore::MediaSource::streamEndedWithError): remove FIXME, brigning back correct order of events.
* Modules/mediasource/SourceBuffer.cpp:
(WebCore::SourceBuffer::remove): comments up to spec, extract rangeRemoval algorithm.
(WebCore::SourceBuffer::rangeRemoval):
(WebCore::SourceBuffer::removeTimerFired): comments up to spec.
* Modules/mediasource/SourceBuffer.h:

LayoutTests:

Added short test to check whether endOfStream incorrectly switches back
to 'open' state.

* media/media-source/media-source-end-of-stream-readyState.html: Added.
* media/media-source/media-source-end-of-stream-readyState-expected.txt: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (179043 => 179044)


--- trunk/LayoutTests/ChangeLog	2015-01-24 00:49:02 UTC (rev 179043)
+++ trunk/LayoutTests/ChangeLog	2015-01-24 00:52:42 UTC (rev 179044)
@@ -1,3 +1,16 @@
+2015-01-23  Bartlomiej Gajda  <[email protected]>
+
+        [MSE] Implement Range Removal algorithm.
+        https://bugs.webkit.org/show_bug.cgi?id=140622.
+
+        Reviewed by Jer Noble.
+
+        Added short test to check whether endOfStream incorrectly switches back
+        to 'open' state.
+
+        * media/media-source/media-source-end-of-stream-readyState.html: Added.
+        * media/media-source/media-source-end-of-stream-readyState-expected.txt: Added.
+
 2015-01-23  Brent Fulgham  <[email protected]>
 
         [Win] Test gardening. Mark a few failures after filing bugs.

Added: trunk/LayoutTests/media/media-source/media-source-end-of-stream-readyState-expected.txt (0 => 179044)


--- trunk/LayoutTests/media/media-source/media-source-end-of-stream-readyState-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-end-of-stream-readyState-expected.txt	2015-01-24 00:52:42 UTC (rev 179044)
@@ -0,0 +1,13 @@
+
+RUN(video.src = ""
+EVENT(sourceopen)
+RUN(sourceBuffer = source.addSourceBuffer("video/mock; codecs=mock"))
+RUN(sourceBuffer.appendBuffer(mediaSegment))
+EVENT(updateend)
+EXPECTED (source.duration.toFixed(3) == '10') OK
+EXPECTED (sourceBuffer.buffered.end(0).toFixed(3) == '5') OK
+RUN(source.endOfStream())
+EXPECTED (source.duration.toFixed(3) == '5') OK
+EVENT(updateend)
+END OF TEST
+

Added: trunk/LayoutTests/media/media-source/media-source-end-of-stream-readyState.html (0 => 179044)


--- trunk/LayoutTests/media/media-source/media-source-end-of-stream-readyState.html	                        (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-end-of-stream-readyState.html	2015-01-24 00:52:42 UTC (rev 179044)
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>mock-media-source</title>
+    <script src=""
+    <script src=""
+    <script>
+    var source;
+    var sourceBuffer;
+    var mediaSegment;
+
+    if (window.internals)
+        internals.initializeMockMediaSource();
+
+    function runTest() {
+        findMediaElement();
+
+        source = new MediaSource();
+        waitForEventOn(source, 'sourceopen', sourceOpen, false, true);
+        run('video.src = ""
+    }
+
+    function sourceOpen() {
+        run('sourceBuffer = source.addSourceBuffer("video/mock; codecs=mock")');
+        waitForEventOn(sourceBuffer, 'updateend', updateEnd1, false, true);
+        mediaSegment = concatenateSamples([
+            makeAInit(10, [makeATrack(1, 'mock', TRACK_KIND.VIDEO)]),
+            makeASample(0, 0, 5, 1, SAMPLE_FLAG.SYNC, 0),
+        ]);
+        run('sourceBuffer.appendBuffer(mediaSegment)');
+
+    }
+
+    function updateEnd1() {
+        testExpected('source.duration.toFixed(3)', 10);
+        testExpected('sourceBuffer.buffered.end(0).toFixed(3)', 5);
+
+        waitForEventOn(source, 'sourceopen', function() { failTest("Should not transit to 'open' state during endOfStream().") }, false, true);
+        waitForEventOn(sourceBuffer, 'updateend', endTest, false, true);
+        run('source.endOfStream()');
+        testExpected('source.duration.toFixed(3)', 5);
+    }
+
+    </script>
+</head>
+<body _onload_="runTest()">
+    <video></video>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (179043 => 179044)


--- trunk/Source/WebCore/ChangeLog	2015-01-24 00:49:02 UTC (rev 179043)
+++ trunk/Source/WebCore/ChangeLog	2015-01-24 00:52:42 UTC (rev 179044)
@@ -1,3 +1,26 @@
+2015-01-23  Bartlomiej Gajda  <[email protected]>
+
+        [MSE] Implement Range Removal algorithm.
+        https://bugs.webkit.org/show_bug.cgi?id=140622.
+
+        Reviewed by Jer Noble.
+
+        This extract Range Removal algorithm (Editor's Draft version, bug:26316) from remove(),
+        to separate function to deal with old FIXME since bug in spec was resolved.
+        This should both guarantee good order of events, and prevent from switching to 'open' state
+        during end of stream.
+
+        Test: media/media-source/media-source-end-of-stream-readyState.html
+
+        * Modules/mediasource/MediaSource.cpp:
+        (WebCore::MediaSource::setDurationInternal): update to use rangeRemoval(), not remove()
+        (WebCore::MediaSource::streamEndedWithError): remove FIXME, brigning back correct order of events.
+        * Modules/mediasource/SourceBuffer.cpp:
+        (WebCore::SourceBuffer::remove): comments up to spec, extract rangeRemoval algorithm.
+        (WebCore::SourceBuffer::rangeRemoval):
+        (WebCore::SourceBuffer::removeTimerFired): comments up to spec.
+        * Modules/mediasource/SourceBuffer.h:
+
 2015-01-23  Enrica Casucci  <[email protected]>
 
         Hit test returns incorrect results when performed in paginated content over the page gaps.

Modified: trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp (179043 => 179044)


--- trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp	2015-01-24 00:49:02 UTC (rev 179043)
+++ trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp	2015-01-24 00:52:42 UTC (rev 179044)
@@ -371,7 +371,7 @@
     // on all objects in sourceBuffers.
     if (oldDuration.isValid() && duration < oldDuration) {
         for (auto& sourceBuffer : *m_sourceBuffers)
-            sourceBuffer->remove(duration, oldDuration, IGNORE_EXCEPTION);
+            sourceBuffer->rangeRemoval(duration, oldDuration);
     }
 
     // 5. If a user agent is unable to partially render audio frames or text cues that start before and end after the
@@ -447,6 +447,10 @@
 
     // 2.4.7 https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#end-of-stream-algorithm
 
+    // 1. Change the readyState attribute value to "ended".
+    // 2. Queue a task to fire a simple event named sourceended at the MediaSource.
+    setReadyState(endedKeyword());
+
     // 3.
     if (error.isEmpty()) {
         // ↳ If error is not set, is null, or is an empty string
@@ -463,13 +467,6 @@
         m_private->markEndOfStream(MediaSourcePrivate::EosNoError);
     }
 
-    // NOTE: Do steps 1 & 2 after step 3 (with an empty error) to avoid the MediaSource's readyState being re-opened by a
-    // remove() operation resulting from a duration change.
-    // FIXME: Re-number or update this section once <https://www.w3.org/Bugs/Public/show_bug.cgi?id=26316> is resolved.
-    // 1. Change the readyState attribute value to "ended".
-    // 2. Queue a task to fire a simple event named sourceended at the MediaSource.
-    setReadyState(endedKeyword());
-
     if (error == network) {
         // ↳ If error is set to "network"
         ASSERT(m_mediaElement);

Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp (179043 => 179044)


--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp	2015-01-24 00:49:02 UTC (rev 179043)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp	2015-01-24 00:52:42 UTC (rev 179044)
@@ -360,33 +360,49 @@
     LOG(MediaSource, "SourceBuffer::remove(%p) - start(%lf), end(%lf)", this, start.toDouble(), end.toDouble());
 
     // Section 3.2 remove() method steps.
-    // 1. If start is negative or greater than duration, then throw an InvalidAccessError exception and abort these steps.
-    // 2. If end is less than or equal to start, then throw an InvalidAccessError exception and abort these steps.
-    if (start < MediaTime::zeroTime() || (m_source && (!m_source->duration().isValid() || start > m_source->duration())) || end <= start) {
+    // 1. If duration equals NaN, then throw an InvalidAccessError exception and abort these steps.
+    // 2. If start is negative or greater than duration, then throw an InvalidAccessError exception and abort these steps.
+    // 3. If end is less than or equal to start, then throw an InvalidAccessError exception and abort these steps.
+
+    // FIXME: reorder/revisit this section once <https://www.w3.org/Bugs/Public/show_bug.cgi?id=27857> got resolved
+    // as it seems wrong to check mediaSource duration before checking isRemoved().
+    if ((m_source && m_source->duration().isInvalid())
+        || start < MediaTime::zeroTime() || (m_source && start > m_source->duration())
+        || end <= start) {
         ec = INVALID_ACCESS_ERR;
         return;
     }
 
-    // 3. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
+    // 4. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
     //    InvalidStateError exception and abort these steps.
-    // 4. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
+    // 5. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
     if (isRemoved() || m_updating) {
         ec = INVALID_STATE_ERR;
         return;
     }
 
-    // 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 .
+    // 6. If the readyState attribute of the parent media source is in the "ended" state then run the following steps:
+    // 6.1. Set the readyState attribute of the parent media source to "open"
+    // 6.2. Queue a task to fire a simple event named sourceopen at the parent media source .
     m_source->openIfInEndedState();
 
-    // 6. Set the updating attribute to true.
+    // 7. Run the range removal algorithm with start and end as the start and end of the removal range.
+    rangeRemoval(start, end);
+}
+
+void SourceBuffer::rangeRemoval(const MediaTime& start, const MediaTime& end)
+{
+    // 3.5.7 Range Removal
+    // https://rawgit.com/w3c/media-source/7bbe4aa33c61ec025bc7acbd80354110f6a000f9/media-source.html#sourcebuffer-range-removal
+    // 1. Let start equal the starting presentation timestamp for the removal range.
+    // 2. Let end equal the end presentation timestamp for the removal range.
+    // 3. Set the updating attribute to true.
     m_updating = true;
 
-    // 7. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
+    // 4. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
     scheduleEvent(eventNames().updatestartEvent);
 
-    // 8. Return control to the caller and run the rest of the steps asynchronously.
+    // 5. Return control to the caller and run the rest of the steps asynchronously.
     m_pendingRemoveStart = start;
     m_pendingRemoveEnd = end;
     m_removeTimer.startOneShot(0);
@@ -789,21 +805,21 @@
     ASSERT(m_pendingRemoveStart.isValid());
     ASSERT(m_pendingRemoveStart < m_pendingRemoveEnd);
 
-    // Section 3.2 remove() method steps
-    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-remove-void-double-start-double-end
+    // Section 3.5.7 Range Removal
+    // http://w3c.github.io/media-source/#sourcebuffer-range-removal
 
-    // 9. Run the coded frame removal algorithm with start and end as the start and end of the removal range.
+    // 6. Run the coded frame removal algorithm with start and end as the start and end of the removal range.
     removeCodedFrames(m_pendingRemoveStart, m_pendingRemoveEnd);
 
-    // 10. Set the updating attribute to false.
+    // 7. Set the updating attribute to false.
     m_updating = false;
     m_pendingRemoveStart = MediaTime::invalidTime();
     m_pendingRemoveEnd = MediaTime::invalidTime();
 
-    // 11. Queue a task to fire a simple event named update at this SourceBuffer object.
+    // 8. Queue a task to fire a simple event named update at this SourceBuffer object.
     scheduleEvent(eventNames().updateEvent);
 
-    // 12. Queue a task to fire a simple event named updateend at this SourceBuffer object.
+    // 9. Queue a task to fire a simple event named updateend at this SourceBuffer object.
     scheduleEvent(eventNames().updateendEvent);
 }
 

Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h (179043 => 179044)


--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h	2015-01-24 00:49:02 UTC (rev 179043)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h	2015-01-24 00:52:42 UTC (rev 179044)
@@ -126,6 +126,7 @@
     bool shouldGenerateTimestamps() const { return m_shouldGenerateTimestamps; }
     void setShouldGenerateTimestamps(bool flag) { m_shouldGenerateTimestamps = flag; }
 
+    void rangeRemoval(const MediaTime&, const MediaTime&);
 protected:
     // EventTarget interface
     virtual void refEventTarget() override { ref(); }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to