Diff
Modified: trunk/LayoutTests/ChangeLog (158927 => 158928)
--- trunk/LayoutTests/ChangeLog 2013-11-08 18:28:06 UTC (rev 158927)
+++ trunk/LayoutTests/ChangeLog 2013-11-08 18:30:29 UTC (rev 158928)
@@ -1,3 +1,14 @@
+2013-10-30 Jer Noble <[email protected]>
+
+ [MSE] Bring SourceBuffer.append up to the most recent spec.
+ https://bugs.webkit.org/show_bug.cgi?id=123377
+
+ Reviewed by Eric Carlson.
+
+ * media/media-source/media-source-append-failed-expected.txt: Added.
+ * media/media-source/media-source-append-failed.html: Added.
+ * media/media-source/mock-media-source.js:
+
2013-11-08 Michał Pakuła vel Rutka <[email protected]>
Unreviewed EFL gardening
Added: trunk/LayoutTests/media/media-source/media-source-append-failed-expected.txt (0 => 158928)
--- trunk/LayoutTests/media/media-source/media-source-append-failed-expected.txt (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-append-failed-expected.txt 2013-11-08 18:30:29 UTC (rev 158928)
@@ -0,0 +1,9 @@
+
+RUN(video.src = ""
+EVENT(sourceopen)
+RUN(sourceBuffer = source.addSourceBuffer("video/mock; codecs=mock"))
+RUN(sourceBuffer.appendBuffer(initSegment))
+EVENT(updatestart)
+EVENT(sourceended)
+END OF TEST
+
Added: trunk/LayoutTests/media/media-source/media-source-append-failed.html (0 => 158928)
--- trunk/LayoutTests/media/media-source/media-source-append-failed.html (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-append-failed.html 2013-11-08 18:30:29 UTC (rev 158928)
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>mock-media-source</title>
+ <script src=""
+ <script src=""
+ <script>
+ var source;
+ var sourceBuffer;
+ var initSegment;
+
+ if (window.internals)
+ internals.initializeMockMediaSource();
+
+ function runTest() {
+ findMediaElement();
+
+ source = new MediaSource();
+ waitForEventOn(source, 'sourceopen', sourceOpen);
+ run('video.src = ""
+ }
+
+ function sourceOpen() {
+ run('sourceBuffer = source.addSourceBuffer("video/mock; codecs=mock")');
+
+ waitForEventOn(sourceBuffer, 'updatestart');
+ waitForEventOn(sourceBuffer, 'update');
+ waitForEventOn(sourceBuffer, 'updateend');
+ waitForEventOn(source, 'sourceended', endTest);
+ initSegment = makeAnInvalidBox();
+ run('sourceBuffer.appendBuffer(initSegment)');
+ }
+
+ </script>
+</head>
+<body _onload_="runTest()">
+ <video></video>
+</body>
+</html>
Modified: trunk/LayoutTests/media/media-source/mock-media-source.js (158927 => 158928)
--- trunk/LayoutTests/media/media-source/mock-media-source.js 2013-11-08 18:28:06 UTC (rev 158927)
+++ trunk/LayoutTests/media/media-source/mock-media-source.js 2013-11-08 18:30:29 UTC (rev 158928)
@@ -69,4 +69,15 @@
return buffer;
}
+function makeAnInvalidBox() {
+ var byteLength = 12;
+ var buffer = new ArrayBuffer(byteLength);
+ var array = new Uint8Array(buffer);
+ array.set(stringToArray('invl'));
+ var view = new DataView(buffer);
+ view.setUint32(8, 0xFFFF, true);
+
+ return buffer;
+}
+
Modified: trunk/Source/WebCore/ChangeLog (158927 => 158928)
--- trunk/Source/WebCore/ChangeLog 2013-11-08 18:28:06 UTC (rev 158927)
+++ trunk/Source/WebCore/ChangeLog 2013-11-08 18:30:29 UTC (rev 158928)
@@ -1,3 +1,24 @@
+2013-10-30 Jer Noble <[email protected]>
+
+ [MSE] Bring SourceBuffer.append up to the most recent spec.
+ https://bugs.webkit.org/show_bug.cgi?id=123377
+
+ Reviewed by Eric Carlson.
+
+ Test: media/media-source/media-source-append-failed.html
+
+ Bring the MediaSource append() implementation up to the current spec.
+
+ * Modules/mediasource/SourceBuffer.cpp:
+ (WebCore::SourceBuffer::appendBufferInternal):
+ (WebCore::SourceBuffer::appendBufferTimerFired):
+ * platform/graphics/SourceBufferPrivate.h:
+ * platform/mock/mediasource/MockSourceBufferPrivate.cpp:
+ (WebCore::MockSourceBufferPrivate::append):
+ (WebCore::MockSourceBufferPrivate::evictCodedFrames):
+ (WebCore::MockSourceBufferPrivate::isFull):
+ * platform/mock/mediasource/MockSourceBufferPrivate.h:
+
2013-11-07 Jer Noble <[email protected]>
[Mac] Crash at com.apple.WebCore: WebCore::MediaPlayerPrivateAVFoundationObjC::tracksDidChange + 26
Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp (158927 => 158928)
--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp 2013-11-08 18:28:06 UTC (rev 158927)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp 2013-11-08 18:30:29 UTC (rev 158928)
@@ -35,6 +35,7 @@
#include "AudioTrackList.h"
#include "Event.h"
+#include "ExceptionCodePlaceholder.h"
#include "GenericEventQueue.h"
#include "HTMLMediaElement.h"
#include "InbandTextTrack.h"
@@ -272,28 +273,42 @@
// https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
// Step 1 is enforced by the caller.
- // 2. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an INVALID_STATE_ERR exception and abort these steps.
- // 3. If the updating attribute equals true, then throw an INVALID_STATE_ERR exception and abort these steps.
+ // 2. Run the prepare append algorithm.
+ // Section 3.5.4 Prepare AppendAlgorithm
+
+ // 1. If the SourceBuffer has been removed from the sourceBuffers attribute of the parent media source
+ // then throw an INVALID_STATE_ERR exception and abort these steps.
+ // 2. If the updating attribute equals true, then throw an INVALID_STATE_ERR exception and abort these steps.
if (isRemoved() || m_updating) {
ec = INVALID_STATE_ERR;
return;
}
- // 4. If the readyState attribute of the parent media source is in the "ended" state then run the following steps: ...
+ // 3. If the readyState attribute of the parent media source is in the "ended" state then run the following steps:
+ // 3.1. Set the readyState attribute of the parent media source to "open"
+ // 3.2. Queue a task to fire a simple event named sourceopen at the parent media source .
m_source->openIfInEndedState();
- // Steps 5-6
+ // 4. Run the coded frame eviction algorithm.
+ m_private->evictCodedFrames();
- // 7. Add data to the end of the input buffer.
+ // 5. If the buffer full flag equals true, then throw a QUOTA_EXCEEDED_ERR exception and abort these step.
+ if (m_private->isFull()) {
+ ec = QUOTA_EXCEEDED_ERR;
+ return;
+ }
+
+ // NOTE: Return to 3.2 appendBuffer()
+ // 3. Add data to the end of the input buffer.
m_pendingAppendData.append(data, size);
- // 8. Set the updating attribute to true.
+ // 4. Set the updating attribute to true.
m_updating = true;
- // 9. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
+ // 5. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
scheduleEvent(eventNames().updatestartEvent);
- // 10. Asynchronously run the buffer append algorithm.
+ // 6. Asynchronously run the buffer append algorithm.
m_appendBufferTimer.startOneShot(0);
}
@@ -301,11 +316,10 @@
{
ASSERT(m_updating);
- // Section 3.5.4 Buffer Append Algorithm
+ // Section 3.5.5 Buffer Append Algorithm
// https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-buffer-append
// 1. Run the segment parser loop algorithm.
- // Step 2 doesn't apply since we run Step 1 synchronously here.
size_t appendSize = m_pendingAppendData.size();
if (!appendSize) {
// Resize buffer for 0 byte appends so we always have a valid pointer.
@@ -313,11 +327,40 @@
// that it can clear its end of stream state if necessary.
m_pendingAppendData.resize(1);
}
- m_private->append(m_pendingAppendData.data(), appendSize);
+ // Section 3.5.1 Segment Parser Loop
+ // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#sourcebuffer-segment-parser-loop
+ // When the segment parser loop algorithm is invoked, run the following steps:
+
+ SourceBufferPrivate::AppendResult result = SourceBufferPrivate::AppendSucceeded;
+ do {
+ // 1. Loop Top: If the input buffer is empty, then jump to the need more data step below.
+ if (!m_pendingAppendData.size())
+ break;
+
+ result = m_private->append(m_pendingAppendData.data(), appendSize);
+ m_pendingAppendData.clear();
+
+ // 2. If the input buffer contains bytes that violate the SourceBuffer byte stream format specification,
+ // then run the end of stream algorithm with the error parameter set to "decode" and abort this algorithm.
+ if (result == SourceBufferPrivate::ParsingFailed) {
+ m_source->endOfStream(decodeError(), IgnorableExceptionCode());
+ break;
+ }
+
+ // NOTE: Steps 3 - 6 enforced by sourceBufferPrivateDidReceiveInitializationSegment() and
+ // sourceBufferPrivateDidReceiveSample below.
+
+ // 7. Need more data: Return control to the calling algorithm.
+ } while (0);
+
+ // NOTE: return to Section 3.5.5
+ // 2.If the segment parser loop algorithm in the previous step was aborted, then abort this algorithm.
+ if (result != SourceBufferPrivate::AppendSucceeded)
+ return;
+
// 3. Set the updating attribute to false.
m_updating = false;
- m_pendingAppendData.clear();
// 4. Queue a task to fire a simple event named update at this SourceBuffer object.
scheduleEvent(eventNames().updateEvent);
@@ -389,8 +432,6 @@
void SourceBuffer::sourceBufferPrivateDidReceiveInitializationSegment(SourceBufferPrivate*, const InitializationSegment& segment)
{
- m_appendState = ParsingInitSegment;
-
// 3.5.7 Initialization Segment Received
// https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-init-segment-received
// 1. Update the duration attribute if it currently equals NaN:
Modified: trunk/Source/WebCore/platform/graphics/SourceBufferPrivate.h (158927 => 158928)
--- trunk/Source/WebCore/platform/graphics/SourceBufferPrivate.h 2013-11-08 18:28:06 UTC (rev 158927)
+++ trunk/Source/WebCore/platform/graphics/SourceBufferPrivate.h 2013-11-08 18:30:29 UTC (rev 158928)
@@ -46,12 +46,20 @@
virtual ~SourceBufferPrivate() { }
virtual void setClient(SourceBufferPrivateClient*) = 0;
- virtual void append(const unsigned char* data, unsigned length) = 0;
+
+ enum AppendResult {
+ AppendSucceeded,
+ ReadStreamFailed,
+ ParsingFailed,
+ };
+ virtual AppendResult append(const unsigned char* data, unsigned length) = 0;
virtual void abort() = 0;
virtual void removedFromMediaSource() = 0;
virtual MediaPlayer::ReadyState readyState() const = 0;
virtual void setReadyState(MediaPlayer::ReadyState) = 0;
+ virtual void evictCodedFrames() = 0;
+ virtual bool isFull() = 0;
};
}
Modified: trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp (158927 => 158928)
--- trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp 2013-11-08 18:28:06 UTC (rev 158927)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp 2013-11-08 18:30:29 UTC (rev 158928)
@@ -106,11 +106,12 @@
m_client = client;
}
-void MockSourceBufferPrivate::append(const unsigned char* data, unsigned length)
+SourceBufferPrivate::AppendResult MockSourceBufferPrivate::append(const unsigned char* data, unsigned length)
{
m_inputBuffer.append(data, length);
+ AppendResult result = AppendSucceeded;
- while (m_inputBuffer.size()) {
+ while (m_inputBuffer.size() && result == AppendSucceeded) {
RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_inputBuffer.data(), m_inputBuffer.size());
size_t boxLength = MockBox::peekLength(buffer.get());
if (boxLength > buffer->byteLength())
@@ -120,15 +121,16 @@
if (type == MockInitializationBox::type()) {
MockInitializationBox initBox = MockInitializationBox(buffer.get());
didReceiveInitializationSegment(initBox);
- }
-
- if (type == MockSampleBox::type()) {
+ } else if (type == MockSampleBox::type()) {
MockSampleBox sampleBox = MockSampleBox(buffer.get());
didReceiveSample(sampleBox);
- }
+ } else
+ result = ParsingFailed;
m_inputBuffer.remove(0, boxLength);
}
+
+ return result;
}
void MockSourceBufferPrivate::didReceiveInitializationSegment(const MockInitializationBox& initBox)
@@ -190,6 +192,16 @@
m_parent->player()->setReadyState(readyState);
}
+void MockSourceBufferPrivate::evictCodedFrames()
+{
+ // No-op.
+}
+
+bool MockSourceBufferPrivate::isFull()
+{
+ return false;
+}
+
bool MockSourceBufferPrivate::hasVideo() const
{
if (!m_client)
Modified: trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h (158927 => 158928)
--- trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h 2013-11-08 18:28:06 UTC (rev 158927)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h 2013-11-08 18:30:29 UTC (rev 158928)
@@ -58,11 +58,13 @@
// SourceBufferPrivate overrides
virtual void setClient(SourceBufferPrivateClient*) OVERRIDE;
- virtual void append(const unsigned char* data, unsigned length) OVERRIDE;
+ virtual AppendResult append(const unsigned char* data, unsigned length) OVERRIDE;
virtual void abort() OVERRIDE;
virtual void removedFromMediaSource() OVERRIDE;
virtual MediaPlayer::ReadyState readyState() const OVERRIDE;
virtual void setReadyState(MediaPlayer::ReadyState) OVERRIDE;
+ virtual void evictCodedFrames() OVERRIDE;
+ virtual bool isFull() OVERRIDE;
void didReceiveInitializationSegment(const MockInitializationBox&);
void didReceiveSample(const MockSampleBox&);