Fix failing mediasource-play.html and mediasource-config-change-mp4-v-bitrate.html...
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Sep 2016 21:09:15 +0000 (21:09 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Sep 2016 21:09:15 +0000 (21:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=161819

Reviewed by Eric Carlson.

Source/WebCore:

Fixes tests: imported/w3c/web-platform-tests/media-source/mediasource-play.html
             imported/w3c/web-platform-tests/media-source/mediasource-sourcebuffer-mode.html

The newest revision of the web-platform-test suite for Media Source tests new behavior
added to the MSE specification. Specifically, setting a MediaSource's duration will no
longer implicitly truncate the source's active SourceBuffer objects.

* Modules/mediasource/MediaSource.cpp:
(WebCore::MediaSource::setDuration): Return exception if issued by setDurationInternal.
(WebCore::MediaSource::setDurationInternal): Bring "duration change" algorithm up to spec.
* Modules/mediasource/MediaSource.h:
* Modules/mediasource/SampleMap.h:
(WebCore::PresentationOrderSampleMap::begin): Add const accessor.
(WebCore::PresentationOrderSampleMap::end): Ditto.
(WebCore::PresentationOrderSampleMap::rbegin): Ditto.
(WebCore::PresentationOrderSampleMap::rend): DItto.
(WebCore::DecodeOrderSampleMap::begin): Ditto.
(WebCore::DecodeOrderSampleMap::end): Ditto.
(WebCore::DecodeOrderSampleMap::rbegin): Ditto.
(WebCore::DecodeOrderSampleMap::rend): Ditto.
* Modules/mediasource/SourceBuffer.cpp:
(WebCore::SourceBuffer::highestPresentationTimestamp): Added convenience method.
(WebCore::SourceBuffer::removeCodedFrames): Drive-by fix; use .values() rather than
    pulling the value out of each HashMap iterator.
* Modules/mediasource/SourceBuffer.h:

LayoutTests:

* media/media-source/media-source-end-of-stream-readyState.html:
* media/media-source/media-source-end-of-stream-readyState-expected.txt:
* platform/mac/TestExpectations:

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

LayoutTests/ChangeLog
LayoutTests/media/media-source/media-source-end-of-stream-readyState-expected.txt
LayoutTests/media/media-source/media-source-end-of-stream-readyState.html
LayoutTests/platform/mac/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/Modules/mediasource/MediaSource.cpp
Source/WebCore/Modules/mediasource/MediaSource.h
Source/WebCore/Modules/mediasource/SampleMap.h
Source/WebCore/Modules/mediasource/SourceBuffer.cpp
Source/WebCore/Modules/mediasource/SourceBuffer.h

index 3cdedde..cd828c4 100644 (file)
@@ -1,3 +1,14 @@
+2016-09-12  Jer Noble  <jer.noble@apple.com>
+
+        Fix failing mediasource-play.html and mediasource-config-change-mp4-v-bitrate.html tests
+        https://bugs.webkit.org/show_bug.cgi?id=161819
+
+        Reviewed by Eric Carlson.
+
+        * media/media-source/media-source-end-of-stream-readyState.html:
+        * media/media-source/media-source-end-of-stream-readyState-expected.txt:
+        * platform/mac/TestExpectations:
+
 2016-09-12  Matt Baker  <mattbaker@apple.com>
 
         Web Inspector: Object.shallowEqual() should return false if object prototype chains differ
index d088d55..6909810 100644 (file)
@@ -8,6 +8,6 @@ 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)
+EXPECTED (sourceBuffer.updating == 'false') OK
 END OF TEST
 
index f026893..069aa0c 100644 (file)
         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);
+        testExpected('sourceBuffer.updating', false);
+        endTest();
     }
 
     </script>
index 6a5d2f7..dbb168c 100644 (file)
@@ -1047,8 +1047,10 @@ webkit.org/b/137505 media/track/track-forced-subtitles-in-band.html [ Failure Pa
 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/SourceBuffer-abort-removed.html [ Pass ]
 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/SourceBuffer-abort.html [ Pass ]
 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/mediasource-closed.html [ Pass ]
+[ Yosemite+ ] imported/w3c/web-platform-tests/media-source/mediasource-config-change-mp4-v-bitrate.html [ Pass ]
 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/mediasource-endofstream-invaliderror.html [ Pass ]
 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/mediasource-multiple-attach.html [ Pass ]
+[ Yosemite+ ] imported/w3c/web-platform-tests/media-source/mediasource-play.html [ Pass ]
 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/mediasource-sourcebufferlist.html [ Pass ]
 
 # Flaky Media Source tests
@@ -1060,7 +1062,6 @@ webkit.org/b/161725 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/m
 webkit.org/b/161725 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/mediasource-append-buffer.html [ Failure ]
 webkit.org/b/161725 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/mediasource-config-change-mp4-v-bitrate.html [ Failure ]
 webkit.org/b/161725 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/mediasource-is-type-supported.html [ Failure ]
-webkit.org/b/161725 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/mediasource-play.html [ Failure ]
 webkit.org/b/161725 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/mediasource-remove.html [ Failure ]
 webkit.org/b/161725 [ Yosemite+ ] imported/w3c/web-platform-tests/media-source/mediasource-sourcebuffer-mode.html [ Failure ]
 
index a60c8bf..59669f1 100644 (file)
@@ -1,3 +1,36 @@
+2016-09-12  Jer Noble  <jer.noble@apple.com>
+
+        Fix failing mediasource-play.html and mediasource-config-change-mp4-v-bitrate.html tests
+        https://bugs.webkit.org/show_bug.cgi?id=161819
+
+        Reviewed by Eric Carlson.
+
+        Fixes tests: imported/w3c/web-platform-tests/media-source/mediasource-play.html
+                     imported/w3c/web-platform-tests/media-source/mediasource-sourcebuffer-mode.html
+
+        The newest revision of the web-platform-test suite for Media Source tests new behavior
+        added to the MSE specification. Specifically, setting a MediaSource's duration will no
+        longer implicitly truncate the source's active SourceBuffer objects.
+
+        * Modules/mediasource/MediaSource.cpp:
+        (WebCore::MediaSource::setDuration): Return exception if issued by setDurationInternal.
+        (WebCore::MediaSource::setDurationInternal): Bring "duration change" algorithm up to spec.
+        * Modules/mediasource/MediaSource.h:
+        * Modules/mediasource/SampleMap.h:
+        (WebCore::PresentationOrderSampleMap::begin): Add const accessor.
+        (WebCore::PresentationOrderSampleMap::end): Ditto.
+        (WebCore::PresentationOrderSampleMap::rbegin): Ditto.
+        (WebCore::PresentationOrderSampleMap::rend): DItto.
+        (WebCore::DecodeOrderSampleMap::begin): Ditto.
+        (WebCore::DecodeOrderSampleMap::end): Ditto.
+        (WebCore::DecodeOrderSampleMap::rbegin): Ditto.
+        (WebCore::DecodeOrderSampleMap::rend): Ditto.
+        * Modules/mediasource/SourceBuffer.cpp:
+        (WebCore::SourceBuffer::highestPresentationTimestamp): Added convenience method.
+        (WebCore::SourceBuffer::removeCodedFrames): Drive-by fix; use .values() rather than
+            pulling the value out of each HashMap iterator.
+        * Modules/mediasource/SourceBuffer.h:
+
 2016-09-12  Chris Dumez  <cdumez@apple.com>
 
         Switch remaining users of Document::inPageCache() to pageCacheState()
index d07a67e..2ff80d4 100644 (file)
@@ -357,41 +357,49 @@ void MediaSource::setDuration(double duration, ExceptionCode& ec)
     }
 
     // 4. Run the duration change algorithm with new duration set to the value being assigned to this attribute.
-    setDurationInternal(MediaTime::createWithDouble(duration));
+    auto result = setDurationInternal(MediaTime::createWithDouble(duration));
+    if (result)
+        ec = result.value();
 }
 
-void MediaSource::setDurationInternal(const MediaTime& duration)
+Optional<ExceptionCode> MediaSource::setDurationInternal(const MediaTime& duration)
 {
-    // Duration Change Algorithm
-    // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#duration-change-algorithm
+    // 2.4.6 Duration Change
+    // https://rawgit.com/w3c/media-source/45627646344eea0170dd1cbc5a3d508ca751abb8/media-source-respec.html#duration-change-algorithm
 
-    // 1. If the current value of duration is equal to new duration, then return.
-    if (duration == m_duration)
-        return;
-
-    // 2. Set old duration to the current value of duration.
-    MediaTime oldDuration = m_duration;
-
-    // 3. Update duration to new duration.
-    m_duration = duration;
+    MediaTime newDuration = duration;
 
-    // 4. If the new duration is less than old duration, then call remove(new duration, old duration)
-    // on all objects in sourceBuffers.
-    if (oldDuration.isValid() && duration < oldDuration) {
-        for (auto& sourceBuffer : *m_sourceBuffers)
-            sourceBuffer->rangeRemoval(duration, oldDuration);
+    // 1. If the current value of duration is equal to new duration, then return.
+    if (newDuration == m_duration)
+        return { };
+
+    // 2. If new duration is less than the highest presentation timestamp of any buffered coded frames
+    // for all SourceBuffer objects in sourceBuffers, then throw an InvalidStateError exception and
+    // abort these steps.
+    // 3. Let highest end time be the largest track buffer ranges end time across all the track buffers
+    // across all SourceBuffer objects in sourceBuffers.
+    MediaTime highestPresentationTimestamp;
+    MediaTime highestEndTime;
+    for (auto& sourceBuffer : *m_sourceBuffers) {
+        highestPresentationTimestamp = std::max(highestPresentationTimestamp, sourceBuffer->highestPresentationTimestamp());
+        highestEndTime = std::max(highestEndTime, sourceBuffer->buffered()->ranges().maximumBufferedTime());
     }
+    if (highestPresentationTimestamp.isValid() && newDuration < highestPresentationTimestamp)
+        return INVALID_STATE_ERR;
 
-    // 5. If a user agent is unable to partially render audio frames or text cues that start before and end after the
-    // duration, then run the following steps:
-    // 5.1 Update new duration to the highest end time reported by the buffered attribute across all SourceBuffer objects
-    // in sourceBuffers.
-    // 5.2 Update duration to new duration.
-    // NOTE: Assume UA is able to partially render audio frames.
+    // 4. If new duration is less than highest end time, then
+    // 4.1. Update new duration to equal highest end time.
+    if (highestEndTime.isValid() && newDuration < highestEndTime)
+        newDuration = highestEndTime;
 
-    // 6. Update the media controller duration to new duration and run the HTMLMediaElement duration change algorithm.
+    // 5. Update duration to new 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());
     m_private->durationChanged();
+
+    return { };
 }
 
 void MediaSource::setReadyState(const AtomicString& state)
index 19ba1a4..6231360 100644 (file)
@@ -84,7 +84,7 @@ public:
     void completeSeek();
 
     void setDuration(double, ExceptionCode&);
-    void setDurationInternal(const MediaTime&);
+    Optional<ExceptionCode> setDurationInternal(const MediaTime&);
     MediaTime currentTime() const;
     const AtomicString& readyState() const { return m_readyState; }
     void setReadyState(const AtomicString&);
index 973afa9..d8acedc 100644 (file)
@@ -42,13 +42,19 @@ class PresentationOrderSampleMap {
 public:
     typedef std::map<MediaTime, RefPtr<MediaSample>> MapType;
     typedef MapType::iterator iterator;
+    typedef MapType::const_iterator const_iterator;
     typedef MapType::reverse_iterator reverse_iterator;
+    typedef MapType::const_reverse_iterator const_reverse_iterator;
     typedef std::pair<iterator, iterator> iterator_range;
 
     iterator begin() { return m_samples.begin(); }
+    const_iterator begin() const { return m_samples.begin(); }
     iterator end() { return m_samples.end(); }
+    const_iterator end() const { return m_samples.end(); }
     reverse_iterator rbegin() { return m_samples.rbegin(); }
+    const_reverse_iterator rbegin() const { return m_samples.rbegin(); }
     reverse_iterator rend() { return m_samples.rend(); }
+    const_reverse_iterator rend() const { return m_samples.rend(); }
 
     iterator findSampleWithPresentationTime(const MediaTime&);
     iterator findSampleContainingPresentationTime(const MediaTime&);
@@ -69,13 +75,19 @@ public:
     typedef std::pair<MediaTime, MediaTime> KeyType;
     typedef std::map<KeyType, RefPtr<MediaSample>> MapType;
     typedef MapType::iterator iterator;
+    typedef MapType::const_iterator const_iterator;
     typedef MapType::reverse_iterator reverse_iterator;
+    typedef MapType::const_reverse_iterator const_reverse_iterator;
     typedef std::pair<reverse_iterator, reverse_iterator> reverse_iterator_range;
 
     iterator begin() { return m_samples.begin(); }
+    const_iterator begin() const { return m_samples.begin(); }
     iterator end() { return m_samples.end(); }
+    const_iterator end() const { return m_samples.end(); }
     reverse_iterator rbegin() { return m_samples.rbegin(); }
+    const_reverse_iterator rbegin() const { return m_samples.rbegin(); }
     reverse_iterator rend() { return m_samples.rend(); }
+    const_reverse_iterator rend() const { return m_samples.rend(); }
 
     iterator findSampleWithDecodeKey(const KeyType&);
     reverse_iterator reverseFindSampleWithDecodeKey(const KeyType&);
index a14d0a8..b2a4efc 100644 (file)
@@ -395,6 +395,18 @@ void SourceBuffer::abortIfUpdating()
     scheduleEvent(eventNames().updateendEvent);
 }
 
+MediaTime SourceBuffer::highestPresentationTimestamp() const
+{
+    MediaTime highestTime;
+    for (auto& trackBuffer : m_trackBufferMap.values()) {
+        auto lastSampleIter = trackBuffer.samples.presentationOrder().rbegin();
+        if (lastSampleIter == trackBuffer.samples.presentationOrder().rend())
+            continue;
+        highestTime = std::max(highestTime, lastSampleIter->first);
+    }
+    return highestTime;
+}
+
 void SourceBuffer::removedFromMediaSource()
 {
     if (isRemoved())
@@ -741,9 +753,7 @@ void SourceBuffer::removeCodedFrames(const MediaTime& start, const MediaTime& en
 
     // 2. Let end be the end presentation timestamp for the removal range.
     // 3. For each track buffer in this source buffer, run the following steps:
-    for (auto& iter : m_trackBufferMap) {
-        TrackBuffer& trackBuffer = iter.value;
-
+    for (auto& trackBuffer : m_trackBufferMap.values()) {
         // 3.1. Let remove end timestamp be the current value of duration
         // 3.2 If this track buffer has a random access point timestamp that is greater than or equal to end, then update
         // remove end timestamp to that random access point timestamp.
index 6b5a38f..6cc0650 100644 (file)
@@ -124,6 +124,8 @@ public:
     bool isBufferedDirty() const { return m_bufferedDirty; }
     void setBufferedDirty(bool flag) { m_bufferedDirty = flag; }
 
+    MediaTime highestPresentationTimestamp() const;
+
     // ActiveDOMObject API.
     bool hasPendingActivity() const override;