Update MediaSource to allow append() calls in "ended" state.
authoracolwell@chromium.org <acolwell@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Dec 2012 18:23:46 +0000 (18:23 +0000)
committeracolwell@chromium.org <acolwell@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Dec 2012 18:23:46 +0000 (18:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=104581

Reviewed by Eric Carlson.

Source/WebCore:

Updated append and setTimestampOffset to allow appending in the "ended" readyState. An append() call
in the "ended" state now triggers a transition to the "open" state and allows the append to succeed.

Tests: http/tests/media/media-source/video-media-source-append-in-ended-state.html
       http/tests/media/media-source/video-media-source-append-with-offset-in-ended-state.html
       http/tests/media/media-source/video-media-source-zero-byte-append-in-ended-state.html

* Modules/mediasource/MediaSource.cpp:
(WebCore::MediaSource::append):
(WebCore::MediaSource::setTimestampOffset):

LayoutTests:

- Removed old test case that verified appending in "ended" state failed.
- Added 3 new test cases that verify append behavior in the "ended" state.

* http/tests/media/media-source/video-media-source-add-and-remove-buffers-expected.txt:
* http/tests/media/media-source/video-media-source-add-and-remove-buffers.html:
* http/tests/media/media-source/video-media-source-append-in-ended-state-expected.txt: Added.
* http/tests/media/media-source/video-media-source-append-in-ended-state.html: Added.
* http/tests/media/media-source/video-media-source-append-with-offset-in-ended-state-expected.txt: Added.
* http/tests/media/media-source/video-media-source-append-with-offset-in-ended-state.html: Added.
* http/tests/media/media-source/video-media-source-zero-byte-append-in-ended-state-expected.txt: Added.
* http/tests/media/media-source/video-media-source-zero-byte-append-in-ended-state.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/http/tests/media/media-source/video-media-source-add-and-remove-buffers-expected.txt
LayoutTests/http/tests/media/media-source/video-media-source-add-and-remove-buffers.html
LayoutTests/http/tests/media/media-source/video-media-source-append-in-ended-state-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/media/media-source/video-media-source-append-in-ended-state.html [new file with mode: 0644]
LayoutTests/http/tests/media/media-source/video-media-source-append-with-offset-in-ended-state-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/media/media-source/video-media-source-append-with-offset-in-ended-state.html [new file with mode: 0644]
LayoutTests/http/tests/media/media-source/video-media-source-zero-byte-append-in-ended-state-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/media/media-source/video-media-source-zero-byte-append-in-ended-state.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/mediasource/MediaSource.cpp

index 362bc2d..7cbf88d 100644 (file)
@@ -1,3 +1,22 @@
+2012-12-11  Aaron Colwell  <acolwell@chromium.org>
+
+        Update MediaSource to allow append() calls in "ended" state.
+        https://bugs.webkit.org/show_bug.cgi?id=104581
+
+        Reviewed by Eric Carlson.
+
+        - Removed old test case that verified appending in "ended" state failed.
+        - Added 3 new test cases that verify append behavior in the "ended" state.
+
+        * http/tests/media/media-source/video-media-source-add-and-remove-buffers-expected.txt:
+        * http/tests/media/media-source/video-media-source-add-and-remove-buffers.html:
+        * http/tests/media/media-source/video-media-source-append-in-ended-state-expected.txt: Added.
+        * http/tests/media/media-source/video-media-source-append-in-ended-state.html: Added.
+        * http/tests/media/media-source/video-media-source-append-with-offset-in-ended-state-expected.txt: Added.
+        * http/tests/media/media-source/video-media-source-append-with-offset-in-ended-state.html: Added.
+        * http/tests/media/media-source/video-media-source-zero-byte-append-in-ended-state-expected.txt: Added.
+        * http/tests/media/media-source/video-media-source-zero-byte-append-in-ended-state.html: Added.
+
 2012-12-11  Robert Hogan  <robert@webkit.org>
 
         REGRESSION(r121789): Text not wrapping in presence of floating objects
index 58b7556..77ea313 100644 (file)
@@ -38,8 +38,6 @@ EVENT(webkitsourceopen)
 Test a successful append.
 Test append with a null buffer.
 Got expected exception Error: InvalidAccessError: DOM Exception 15
-Test append after ended.
-Got expected exception Error: InvalidStateError: DOM Exception 11
 Test append after buffer has been removed.
 Got expected exception Error: InvalidStateError: DOM Exception 11
 END OF TEST
index 3d7224c..e3b392a 100644 (file)
                 consoleWrite("Test append with a null buffer.");
                 expectExceptionOnAppend(null, DOMException.INVALID_ACCESS_ERR);
 
-                consoleWrite("Test append after ended.");
-                mediaSource.endOfStream();
-                expectExceptionOnAppend(initSegment, DOMException.INVALID_STATE_ERR);
-
                 consoleWrite("Test append after buffer has been removed.");
                 mediaSource.removeSourceBuffer(segmentHelper.sourceBuffer);
                 expectExceptionOnAppend(initSegment, DOMException.INVALID_STATE_ERR);
diff --git a/LayoutTests/http/tests/media/media-source/video-media-source-append-in-ended-state-expected.txt b/LayoutTests/http/tests/media/media-source/video-media-source-append-in-ended-state-expected.txt
new file mode 100644 (file)
index 0000000..cd855f7
--- /dev/null
@@ -0,0 +1,9 @@
+Tests calling append() after the MediaSource has transitioned to the "ended" state.
+
+Appending initialization segment.
+EVENT(loadedmetadata)
+Appending first media segment.
+Calling endOfStream().
+Appending second media segment.
+END OF TEST
+
diff --git a/LayoutTests/http/tests/media/media-source/video-media-source-append-in-ended-state.html b/LayoutTests/http/tests/media/media-source/video-media-source-append-in-ended-state.html
new file mode 100644 (file)
index 0000000..5d18753
--- /dev/null
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <script src="/media-resources/video-test.js"></script>
+        <script src="/media/resources/media-source/webm/segment-info.js"></script>
+        <script src="media-source.js"></script>
+        <script>
+            var segmentHelper = new MediaSourceTest.SegmentHelper(WebMSegmentInfo.testWebM);
+
+            function onSourceOpen(event)
+            {
+                event.target.removeEventListener('webkitsourceopen', onSourceOpen);
+
+                segmentHelper.addSourceBuffer();
+
+                consoleWrite("Appending initialization segment.");
+                segmentHelper.appendInitSegment();
+
+                waitForEventOnce('loadedmetadata', function()
+                {
+                    try
+                    {
+                        consoleWrite("Appending first media segment.");
+                        segmentHelper.appendMediaSegment(0);
+
+                        consoleWrite("Calling endOfStream().");
+                        mediaSource.endOfStream();
+
+                        MediaSourceTest.expectSourceState(mediaSource, "ended");
+
+                        MediaSourceTest.expectBufferedRange(mediaSource.sourceBuffers[0], [[0, 0.399]]);
+
+                        consoleWrite("Appending second media segment.");
+                        segmentHelper.sourceBuffer.append(segmentHelper.mediaSegments[1]);
+
+                        MediaSourceTest.expectBufferedRange(mediaSource.sourceBuffers[0], [[0, 0.780]]);
+
+                        MediaSourceTest.expectSourceState(mediaSource, "open");
+                    }
+                    catch (e)
+                    {
+                        failTest("Unexpected exception: " + e);
+                    }
+
+                    endTest();
+                });
+            }
+
+            function onLoad()
+            {
+                findMediaElement();
+
+                waitForEventAndFail('error');
+
+                segmentHelper.init(video, function(success)
+                {
+                    if (!success) {
+                        failTest("Failed to load segment data");
+                        return;
+                    }
+
+                    mediaSource.addEventListener('webkitsourceopen', onSourceOpen);
+                    MediaSourceTest.setSrcToMediaSourceTestURL(video);
+                });
+            }
+        </script>
+    </head>
+    <body onload="onLoad()">
+        <video> </video>
+        <p>Tests calling append() after the MediaSource has transitioned to the "ended" state.</p>
+    </body>
+</html>
diff --git a/LayoutTests/http/tests/media/media-source/video-media-source-append-with-offset-in-ended-state-expected.txt b/LayoutTests/http/tests/media/media-source/video-media-source-append-with-offset-in-ended-state-expected.txt
new file mode 100644 (file)
index 0000000..0512b68
--- /dev/null
@@ -0,0 +1,10 @@
+Tests setting a timestampOffset and calling append() after the MediaSource has transitioned to the "ended" state.
+
+Appending initialization segment.
+EVENT(loadedmetadata)
+Appending first media segment.
+Calling endOfStream().
+Setting timestampOffset to 1.
+Appending second media segment.
+END OF TEST
+
diff --git a/LayoutTests/http/tests/media/media-source/video-media-source-append-with-offset-in-ended-state.html b/LayoutTests/http/tests/media/media-source/video-media-source-append-with-offset-in-ended-state.html
new file mode 100644 (file)
index 0000000..8d4743e
--- /dev/null
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <script src="/media-resources/video-test.js"></script>
+        <script src="/media/resources/media-source/webm/segment-info.js"></script>
+        <script src="media-source.js"></script>
+        <script>
+            var segmentHelper = new MediaSourceTest.SegmentHelper(WebMSegmentInfo.testWebM);
+
+            function onSourceOpen(event)
+            {
+                event.target.removeEventListener('webkitsourceopen', onSourceOpen);
+
+                segmentHelper.addSourceBuffer();
+                consoleWrite("Appending initialization segment.");
+                segmentHelper.appendInitSegment();
+
+                waitForEventOnce('loadedmetadata', function()
+                {
+                    try
+                    {
+                        consoleWrite("Appending first media segment.");
+                        segmentHelper.appendMediaSegment(0);
+
+                       MediaSourceTest.expectBufferedRange(mediaSource.sourceBuffers[0], [[0, 0.385]]);
+
+                       consoleWrite("Calling endOfStream().");
+                       mediaSource.endOfStream();
+
+                       MediaSourceTest.expectSourceState(mediaSource, "ended");
+
+                       consoleWrite("Setting timestampOffset to 1.");
+                       mediaSource.sourceBuffers[0].timestampOffset = 1;
+
+                       consoleWrite("Appending second media segment.");
+                       segmentHelper.sourceBuffer.append(segmentHelper.mediaSegments[1]);
+
+                       MediaSourceTest.expectBufferedRange(mediaSource.sourceBuffers[0], [[0, 0.385], [1.385, 1.780]]);
+
+                       MediaSourceTest.expectSourceState(mediaSource, "open");
+                   }
+                   catch (e)
+                   {
+                       failTest("Unexpected exception: " + e);
+                   }
+
+                   endTest();
+                });
+            }
+
+            function onLoad()
+            {
+                findMediaElement();
+
+                waitForEventAndFail('error');
+
+                segmentHelper.init(video, function(success)
+                {
+                    if (!success) {
+                        failTest("Failed to load segment data");
+                        return;
+                    }
+
+                    mediaSource.addEventListener('webkitsourceopen', onSourceOpen);
+                    MediaSourceTest.setSrcToMediaSourceTestURL(video);
+                });
+            }
+        </script>
+    </head>
+    <body onload="onLoad()">
+        <video> </video>
+        <p>Tests setting a timestampOffset and calling append() after the MediaSource has transitioned to the "ended" state.</p>
+    </body>
+</html>
diff --git a/LayoutTests/http/tests/media/media-source/video-media-source-zero-byte-append-in-ended-state-expected.txt b/LayoutTests/http/tests/media/media-source/video-media-source-zero-byte-append-in-ended-state-expected.txt
new file mode 100644 (file)
index 0000000..699759b
--- /dev/null
@@ -0,0 +1,9 @@
+Tests calling append() with an empty Uint8Array after the MediaSource has transitioned to the "ended" state.
+
+Appending initialization segment.
+EVENT(loadedmetadata)
+Appending first media segment.
+Calling endOfStream().
+Appending zero length Uint8Array.
+END OF TEST
+
diff --git a/LayoutTests/http/tests/media/media-source/video-media-source-zero-byte-append-in-ended-state.html b/LayoutTests/http/tests/media/media-source/video-media-source-zero-byte-append-in-ended-state.html
new file mode 100644 (file)
index 0000000..8cf2efd
--- /dev/null
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <script src="/media-resources/video-test.js"></script>
+        <script src="/media/resources/media-source/webm/segment-info.js"></script>
+        <script src="media-source.js"></script>
+        <script>
+            var segmentHelper = new MediaSourceTest.SegmentHelper(WebMSegmentInfo.testWebM);
+
+            function onSourceOpen(event)
+            {
+                event.target.removeEventListener('webkitsourceopen', onSourceOpen);
+
+                segmentHelper.addSourceBuffer();
+
+                consoleWrite("Appending initialization segment.");
+                segmentHelper.appendInitSegment();
+
+                waitForEventOnce('loadedmetadata', function()
+                {
+                    try
+                    {
+                        consoleWrite("Appending first media segment.");
+                        segmentHelper.appendMediaSegment(0);
+
+                        consoleWrite("Calling endOfStream().");
+                        mediaSource.endOfStream();
+
+                        MediaSourceTest.expectSourceState(mediaSource, "ended");
+
+                        MediaSourceTest.expectBufferedRange(mediaSource.sourceBuffers[0], [[0, 0.399]]);
+
+                        consoleWrite("Appending zero length Uint8Array.");
+                        segmentHelper.sourceBuffer.append(new Uint8Array(0));
+
+                        MediaSourceTest.expectSourceState(mediaSource, "open");
+                    }
+                    catch (e)
+                    {
+                        failTest("Unexpected exception: " + e);
+                    }
+
+                    endTest();
+                });
+            }
+
+            function onLoad()
+            {
+                findMediaElement();
+
+                waitForEventAndFail('error');
+
+                segmentHelper.init(video, function(success)
+                {
+                    if (!success) {
+                        failTest("Failed to load segment data");
+                        return;
+                    }
+
+                    mediaSource.addEventListener('webkitsourceopen', onSourceOpen);
+                    MediaSourceTest.setSrcToMediaSourceTestURL(video);
+                });
+            }
+        </script>
+    </head>
+    <body onload="onLoad()">
+        <video> </video>
+        <p>Tests calling append() with an empty Uint8Array after the MediaSource has transitioned to the "ended" state.</p>
+    </body>
+</html>
index 844671b..a734897 100644 (file)
@@ -1,3 +1,21 @@
+2012-12-11  Aaron Colwell  <acolwell@chromium.org>
+
+        Update MediaSource to allow append() calls in "ended" state.
+        https://bugs.webkit.org/show_bug.cgi?id=104581
+
+        Reviewed by Eric Carlson.
+
+        Updated append and setTimestampOffset to allow appending in the "ended" readyState. An append() call
+        in the "ended" state now triggers a transition to the "open" state and allows the append to succeed.
+
+        Tests: http/tests/media/media-source/video-media-source-append-in-ended-state.html
+               http/tests/media/media-source/video-media-source-append-with-offset-in-ended-state.html
+               http/tests/media/media-source/video-media-source-zero-byte-append-in-ended-state.html
+
+        * Modules/mediasource/MediaSource.cpp:
+        (WebCore::MediaSource::append):
+        (WebCore::MediaSource::setTimestampOffset):
+
 2012-12-11  Robert Hogan  <robert@webkit.org>
 
         REGRESSION(r121789): Text not wrapping in presence of floating objects
index a915c27..e8ea781 100644 (file)
@@ -281,13 +281,13 @@ void MediaSource::append(const String& id, PassRefPtr<Uint8Array> data, Exceptio
         return;
     }
 
-    if (!m_player || m_readyState != openKeyword()) {
+    if (!m_player || m_readyState == closedKeyword()) {
         ec = INVALID_STATE_ERR;
         return;
     }
 
-    if (!data->length())
-        return;
+    if (m_readyState == endedKeyword())
+        setReadyState(openKeyword());
 
     if (!m_player->sourceAppend(id, data->data(), data->length())) {
         ec = SYNTAX_ERR;
@@ -308,7 +308,7 @@ void MediaSource::abort(const String& id, ExceptionCode& ec)
 
 bool MediaSource::setTimestampOffset(const String& id, double offset, ExceptionCode& ec)
 {
-    if (!m_player || m_readyState != openKeyword()) {
+    if (!m_player || m_readyState == closedKeyword()) {
         ec = INVALID_STATE_ERR;
         return false;
     }