Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / mediasource / SourceBuffer.cpp
index 3552d4d..26b12a1 100644 (file)
 #include "core/fileapi/FileReaderLoader.h"
 #include "core/fileapi/Stream.h"
 #include "core/html/TimeRanges.h"
-#include "core/platform/graphics/SourceBufferPrivate.h"
 #include "modules/mediasource/MediaSource.h"
 #include "platform/Logging.h"
 #include "platform/TraceEvent.h"
+#include "public/platform/WebSourceBuffer.h"
 #include "wtf/ArrayBuffer.h"
 #include "wtf/ArrayBufferView.h"
 #include "wtf/MathExtras.h"
 
 #include <limits>
 
+using blink::WebSourceBuffer;
+
 namespace WebCore {
 
-PassRefPtr<SourceBuffer> SourceBuffer::create(PassOwnPtr<SourceBufferPrivate> sourceBufferPrivate, MediaSource* source, GenericEventQueue* asyncEventQueue)
+DEFINE_GC_INFO(SourceBuffer);
+
+PassRefPtrWillBeRawPtr<SourceBuffer> SourceBuffer::create(PassOwnPtr<WebSourceBuffer> webSourceBuffer, MediaSource* source, GenericEventQueue* asyncEventQueue)
 {
-    RefPtr<SourceBuffer> sourceBuffer(adoptRef(new SourceBuffer(sourceBufferPrivate, source, asyncEventQueue)));
+    RefPtrWillBeRawPtr<SourceBuffer> sourceBuffer(adoptRefCountedWillBeRefCountedGarbageCollected(new SourceBuffer(webSourceBuffer, source, asyncEventQueue)));
     sourceBuffer->suspendIfNeeded();
     return sourceBuffer.release();
 }
 
-SourceBuffer::SourceBuffer(PassOwnPtr<SourceBufferPrivate> sourceBufferPrivate, MediaSource* source, GenericEventQueue* asyncEventQueue)
+SourceBuffer::SourceBuffer(PassOwnPtr<WebSourceBuffer> webSourceBuffer, MediaSource* source, GenericEventQueue* asyncEventQueue)
     : ActiveDOMObject(source->executionContext())
-    , m_private(sourceBufferPrivate)
+    , m_webSourceBuffer(webSourceBuffer)
     , m_source(source)
     , m_asyncEventQueue(asyncEventQueue)
+    , m_mode(segmentsKeyword())
     , m_updating(false)
     , m_timestampOffset(0)
     , m_appendWindowStart(0)
@@ -75,7 +80,7 @@ SourceBuffer::SourceBuffer(PassOwnPtr<SourceBufferPrivate> sourceBufferPrivate,
     , m_streamMaxSize(0)
     , m_appendStreamAsyncPartRunner(this, &SourceBuffer::appendStreamAsyncPart)
 {
-    ASSERT(m_private);
+    ASSERT(m_webSourceBuffer);
     ASSERT(m_source);
     ScriptWrappable::init(this);
 }
@@ -87,18 +92,65 @@ SourceBuffer::~SourceBuffer()
     ASSERT(!m_stream);
 }
 
-PassRefPtr<TimeRanges> SourceBuffer::buffered(ExceptionState& es) const
+const AtomicString& SourceBuffer::segmentsKeyword()
+{
+    DEFINE_STATIC_LOCAL(const AtomicString, segments, ("segments", AtomicString::ConstructFromLiteral));
+    return segments;
+}
+
+const AtomicString& SourceBuffer::sequenceKeyword()
+{
+    DEFINE_STATIC_LOCAL(const AtomicString, sequence, ("sequence", AtomicString::ConstructFromLiteral));
+    return sequence;
+}
+
+void SourceBuffer::setMode(const AtomicString& newMode, ExceptionState& exceptionState)
+{
+    // Section 3.1 On setting mode attribute steps.
+    // 1. Let new mode equal the new value being assigned to this attribute.
+    // 2. If new mode does not equal "segments" or "sequence", then throw an INVALID_ACCESS_ERR exception and abort
+    //    these steps.
+    //    Step 2 is unnecessary: IDL enforcement prevents this case and should just return immediately to script
+    //    without calling this method in this case.
+    // 3. 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.
+    // 4. If the updating attribute equals true, then throw an INVALID_STATE_ERR exception and abort these steps.
+    if (isRemoved() || m_updating) {
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
+        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.
+    m_source->openIfInEndedState();
+
+    // 6. If the append state equals PARSING_MEDIA_SEGMENT, then throw an INVALID_STATE_ERR and abort these steps.
+    // 7. If the new mode equals "sequence", then set the group start timestamp to the highest presentation end timestamp.
+    WebSourceBuffer::AppendMode appendMode = WebSourceBuffer::AppendModeSegments;
+    if (newMode == sequenceKeyword())
+        appendMode = WebSourceBuffer::AppendModeSequence;
+    if (!m_webSourceBuffer->setMode(appendMode)) {
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
+        return;
+    }
+
+    // 8. Update the attribute to new mode.
+    m_mode = newMode;
+}
+
+PassRefPtr<TimeRanges> SourceBuffer::buffered(ExceptionState& exceptionState) const
 {
     // Section 3.1 buffered attribute steps.
     // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
     //    InvalidStateError exception and abort these steps.
     if (isRemoved()) {
-        es.throwUninformativeAndGenericDOMException(InvalidStateError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
         return 0;
     }
 
     // 2. Return a new static normalized TimeRanges object for the media segments buffered.
-    return m_private->buffered();
+    return TimeRanges::create(m_webSourceBuffer->buffered());
 }
 
 double SourceBuffer::timestampOffset() const
@@ -106,7 +158,7 @@ double SourceBuffer::timestampOffset() const
     return m_timestampOffset;
 }
 
-void SourceBuffer::setTimestampOffset(double offset, ExceptionState& es)
+void SourceBuffer::setTimestampOffset(double offset, ExceptionState& exceptionState)
 {
     // Section 3.1 timestampOffset attribute setter steps.
     // 1. Let new timestamp offset equal the new value being assigned to this attribute.
@@ -114,7 +166,7 @@ void SourceBuffer::setTimestampOffset(double offset, ExceptionState& es)
     //    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) {
-        es.throwUninformativeAndGenericDOMException(InvalidStateError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
         return;
     }
 
@@ -123,12 +175,10 @@ void SourceBuffer::setTimestampOffset(double offset, ExceptionState& es)
     // 4.2 Queue a task to fire a simple event named sourceopen at the parent media source.
     m_source->openIfInEndedState();
 
-    // 5. If this object is waiting for the end of a media segment to be appended, then throw an InvalidStateError
-    // and abort these steps.
-    //
-    // FIXME: Add step 6 text when mode attribute is implemented.
-    if (!m_private->setTimestampOffset(offset)) {
-        es.throwUninformativeAndGenericDOMException(InvalidStateError);
+    // 5. If the append state equals PARSING_MEDIA_SEGMENT, then throw an INVALID_STATE_ERR and abort these steps.
+    // 6. If the mode attribute equals "sequence", then set the group start timestamp to new timestamp offset.
+    if (!m_webSourceBuffer->setTimestampOffset(offset)) {
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
         return;
     }
 
@@ -141,13 +191,13 @@ double SourceBuffer::appendWindowStart() const
     return m_appendWindowStart;
 }
 
-void SourceBuffer::setAppendWindowStart(double start, ExceptionState& es)
+void SourceBuffer::setAppendWindowStart(double start, ExceptionState& exceptionState)
 {
     // Enforce throwing an exception on restricted double values.
     if (std::isnan(start)
         || start == std::numeric_limits<double>::infinity()
         || start == -std::numeric_limits<double>::infinity()) {
-        es.throwUninformativeAndGenericDOMException(TypeMismatchError);
+        exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError);
         return;
     }
 
@@ -156,18 +206,18 @@ void SourceBuffer::setAppendWindowStart(double start, ExceptionState& es)
     //    InvalidStateError exception and abort these steps.
     // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
     if (isRemoved() || m_updating) {
-        es.throwUninformativeAndGenericDOMException(InvalidStateError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
         return;
     }
 
     // 3. If the new value is less than 0 or greater than or equal to appendWindowEnd then throw an InvalidAccessError
     //    exception and abort these steps.
     if (start < 0 || start >= m_appendWindowEnd) {
-        es.throwUninformativeAndGenericDOMException(InvalidAccessError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
         return;
     }
 
-    m_private->setAppendWindowStart(start);
+    m_webSourceBuffer->setAppendWindowStart(start);
 
     // 4. Update the attribute to the new value.
     m_appendWindowStart = start;
@@ -178,14 +228,14 @@ double SourceBuffer::appendWindowEnd() const
     return m_appendWindowEnd;
 }
 
-void SourceBuffer::setAppendWindowEnd(double end, ExceptionState& es)
+void SourceBuffer::setAppendWindowEnd(double end, ExceptionState& exceptionState)
 {
     // Section 3.1 appendWindowEnd attribute setter steps.
     // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
     //    InvalidStateError exception and abort these steps.
     // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
     if (isRemoved() || m_updating) {
-        es.throwUninformativeAndGenericDOMException(InvalidStateError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
         return;
     }
 
@@ -193,57 +243,57 @@ void SourceBuffer::setAppendWindowEnd(double end, ExceptionState& es)
     // 4. If the new value is less than or equal to appendWindowStart then throw an InvalidAccessError
     //    exception and abort these steps.
     if (std::isnan(end) || end <= m_appendWindowStart) {
-        es.throwUninformativeAndGenericDOMException(InvalidAccessError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
         return;
     }
 
-    m_private->setAppendWindowEnd(end);
+    m_webSourceBuffer->setAppendWindowEnd(end);
 
     // 5. Update the attribute to the new value.
     m_appendWindowEnd = end;
 }
 
-void SourceBuffer::appendBuffer(PassRefPtr<ArrayBuffer> data, ExceptionState& es)
+void SourceBuffer::appendBuffer(PassRefPtr<ArrayBuffer> data, ExceptionState& exceptionState)
 {
     // Section 3.2 appendBuffer()
     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
     // 1. If data is null then throw an InvalidAccessError exception and abort these steps.
     if (!data) {
-        es.throwUninformativeAndGenericDOMException(InvalidAccessError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
         return;
     }
 
-    appendBufferInternal(static_cast<const unsigned char*>(data->data()), data->byteLength(), es);
+    appendBufferInternal(static_cast<const unsigned char*>(data->data()), data->byteLength(), exceptionState);
 }
 
-void SourceBuffer::appendBuffer(PassRefPtr<ArrayBufferView> data, ExceptionState& es)
+void SourceBuffer::appendBuffer(PassRefPtr<ArrayBufferView> data, ExceptionState& exceptionState)
 {
     // Section 3.2 appendBuffer()
     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
     // 1. If data is null then throw an InvalidAccessError exception and abort these steps.
     if (!data) {
-        es.throwUninformativeAndGenericDOMException(InvalidAccessError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
         return;
     }
 
-    appendBufferInternal(static_cast<const unsigned char*>(data->baseAddress()), data->byteLength(), es);
+    appendBufferInternal(static_cast<const unsigned char*>(data->baseAddress()), data->byteLength(), exceptionState);
 }
 
-void SourceBuffer::appendStream(PassRefPtr<Stream> stream, ExceptionState& es)
+void SourceBuffer::appendStream(PassRefPtr<Stream> stream, ExceptionState& exceptionState)
 {
     m_streamMaxSizeValid = false;
-    appendStreamInternal(stream, es);
+    appendStreamInternal(stream, exceptionState);
 }
 
-void SourceBuffer::appendStream(PassRefPtr<Stream> stream, unsigned long long maxSize, ExceptionState& es)
+void SourceBuffer::appendStream(PassRefPtr<Stream> stream, unsigned long long maxSize, ExceptionState& exceptionState)
 {
     m_streamMaxSizeValid = maxSize > 0;
     if (m_streamMaxSizeValid)
         m_streamMaxSize = maxSize;
-    appendStreamInternal(stream, es);
+    appendStreamInternal(stream, exceptionState);
 }
 
-void SourceBuffer::abort(ExceptionState& es)
+void SourceBuffer::abort(ExceptionState& exceptionState)
 {
     // Section 3.2 abort() method steps.
     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-abort-void
@@ -252,7 +302,7 @@ void SourceBuffer::abort(ExceptionState& es)
     // 2. If the readyState attribute of the parent media source is not in the "open" state
     //    then throw an InvalidStateError exception and abort these steps.
     if (isRemoved() || !m_source->isOpen()) {
-        es.throwUninformativeAndGenericDOMException(InvalidStateError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
         return;
     }
 
@@ -260,22 +310,22 @@ void SourceBuffer::abort(ExceptionState& es)
     abortIfUpdating();
 
     // 4. Run the reset parser state algorithm.
-    m_private->abort();
+    m_webSourceBuffer->abort();
 
     // 5. Set appendWindowStart to 0.
-    setAppendWindowStart(0, es);
+    setAppendWindowStart(0, exceptionState);
 
     // 6. Set appendWindowEnd to positive Infinity.
-    setAppendWindowEnd(std::numeric_limits<double>::infinity(), es);
+    setAppendWindowEnd(std::numeric_limits<double>::infinity(), exceptionState);
 }
 
-void SourceBuffer::remove(double start, double end, ExceptionState& es)
+void SourceBuffer::remove(double start, double end, ExceptionState& exceptionState)
 {
     // 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 < 0 || (m_source && (std::isnan(m_source->duration()) || start > m_source->duration())) || end <= start) {
-        es.throwUninformativeAndGenericDOMException(InvalidAccessError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
         return;
     }
 
@@ -283,7 +333,7 @@ void SourceBuffer::remove(double start, double end, ExceptionState& es)
     //    InvalidStateError exception and abort these steps.
     // 4. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
     if (isRemoved() || m_updating) {
-        es.throwUninformativeAndGenericDOMException(InvalidStateError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
         return;
     }
 
@@ -355,7 +405,8 @@ void SourceBuffer::removedFromMediaSource()
 
     abortIfUpdating();
 
-    m_private->removedFromMediaSource();
+    m_webSourceBuffer->removedFromMediaSource();
+    m_webSourceBuffer.clear();
     m_source = 0;
     m_asyncEventQueue = 0;
 }
@@ -411,7 +462,7 @@ void SourceBuffer::scheduleEvent(const AtomicString& eventName)
     m_asyncEventQueue->enqueueEvent(event.release());
 }
 
-void SourceBuffer::appendBufferInternal(const unsigned char* data, unsigned size, ExceptionState& es)
+void SourceBuffer::appendBufferInternal(const unsigned char* data, unsigned size, ExceptionState& exceptionState)
 {
     // Section 3.2 appendBuffer()
     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
@@ -420,7 +471,7 @@ void SourceBuffer::appendBufferInternal(const unsigned char* data, unsigned size
     // 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) {
-        es.throwUninformativeAndGenericDOMException(InvalidStateError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
         return;
     }
 
@@ -443,14 +494,14 @@ void SourceBuffer::appendBufferInternal(const unsigned char* data, unsigned size
     // 10. Asynchronously run the buffer append algorithm.
     m_appendBufferAsyncPartRunner.runAsync();
 
-    TRACE_EVENT_ASYNC_STEP0("media", "SourceBuffer::appendBuffer", this, "waiting");
+    TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this, "waiting");
 }
 
 void SourceBuffer::appendBufferAsyncPart()
 {
     ASSERT(m_updating);
 
-    TRACE_EVENT_ASYNC_STEP0("media", "SourceBuffer::appendBuffer", this, "appending");
+    TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this, "appending");
 
     // Section 3.5.4 Buffer Append Algorithm
     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-buffer-append
@@ -460,11 +511,11 @@ void SourceBuffer::appendBufferAsyncPart()
     size_t appendSize = m_pendingAppendData.size();
     if (!appendSize) {
         // Resize buffer for 0 byte appends so we always have a valid pointer.
-        // We need to convey all appends, even 0 byte ones to |m_private| so
-        // that it can clear its end of stream state if necessary.
+        // We need to convey all appends, even 0 byte ones to |m_webSourceBuffer|
+        // so that it can clear its end of stream state if necessary.
         m_pendingAppendData.resize(1);
     }
-    m_private->append(m_pendingAppendData.data(), appendSize);
+    m_webSourceBuffer->append(m_pendingAppendData.data(), appendSize);
 
     // 3. Set the updating attribute to false.
     m_updating = false;
@@ -488,7 +539,7 @@ void SourceBuffer::removeAsyncPart()
     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-remove-void-double-start-double-end
 
     // 9. Run the coded frame removal algorithm with start and end as the start and end of the removal range.
-    m_private->remove(m_pendingRemoveStart, m_pendingRemoveEnd);
+    m_webSourceBuffer->remove(m_pendingRemoveStart, m_pendingRemoveEnd);
 
     // 10. Set the updating attribute to false.
     m_updating = false;
@@ -502,13 +553,13 @@ void SourceBuffer::removeAsyncPart()
     scheduleEvent(EventTypeNames::updateend);
 }
 
-void SourceBuffer::appendStreamInternal(PassRefPtr<Stream> stream, ExceptionState& es)
+void SourceBuffer::appendStreamInternal(PassRefPtr<Stream> stream, ExceptionState& exceptionState)
 {
     // Section 3.2 appendStream()
     // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendStream-void-Stream-stream-unsigned-long-long-maxSize
     // 1. If stream is null then throw an InvalidAccessError exception and abort these steps.
     if (!stream || stream->isNeutered()) {
-        es.throwUninformativeAndGenericDOMException(InvalidAccessError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
         return;
     }
 
@@ -518,7 +569,7 @@ void SourceBuffer::appendStreamInternal(PassRefPtr<Stream> stream, ExceptionStat
     //  1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an InvalidStateError exception and abort these steps.
     //  2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
     if (isRemoved() || m_updating) {
-        es.throwUninformativeAndGenericDOMException(InvalidStateError);
+        exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
         return;
     }
 
@@ -527,7 +578,7 @@ void SourceBuffer::appendStreamInternal(PassRefPtr<Stream> stream, ExceptionStat
     //  3. If the readyState attribute of the parent media source is in the "ended" state then run the following steps: ...
     m_source->openIfInEndedState();
 
-    //  Steps 4-5 of the prepare append algorithm are handled by m_private.
+    // Steps 4-5 of the prepare append algorithm are handled by m_webSourceBuffer.
 
     // 3. Set the updating attribute to true.
     m_updating = true;
@@ -590,7 +641,7 @@ void SourceBuffer::appendStreamDone(bool success)
     }
 
     // Section 3.5.6 Stream Append Loop
-    // Steps 1-11 are handled by appendStreamAsyncPart(), |m_loader|, and |m_private|.
+    // Steps 1-11 are handled by appendStreamAsyncPart(), |m_loader|, and |m_webSourceBuffer|.
     // 12. Loop Done: Set the updating attribute to false.
     m_updating = false;
 
@@ -612,28 +663,33 @@ void SourceBuffer::clearAppendStreamState()
 
 void SourceBuffer::didStartLoading()
 {
-    LOG(Media, "SourceBuffer::didStartLoading() %p", this);
+    WTF_LOG(Media, "SourceBuffer::didStartLoading() %p", this);
 }
 
 void SourceBuffer::didReceiveDataForClient(const char* data, unsigned dataLength)
 {
-    LOG(Media, "SourceBuffer::didReceiveDataForClient(%d) %p", dataLength, this);
+    WTF_LOG(Media, "SourceBuffer::didReceiveDataForClient(%d) %p", dataLength, this);
     ASSERT(m_updating);
     ASSERT(m_loader);
 
-    m_private->append(reinterpret_cast<const unsigned char*>(data), dataLength);
+    m_webSourceBuffer->append(reinterpret_cast<const unsigned char*>(data), dataLength);
 }
 
 void SourceBuffer::didFinishLoading()
 {
-    LOG(Media, "SourceBuffer::didFinishLoading() %p", this);
+    WTF_LOG(Media, "SourceBuffer::didFinishLoading() %p", this);
     appendStreamDone(true);
 }
 
 void SourceBuffer::didFail(FileError::ErrorCode errorCode)
 {
-    LOG(Media, "SourceBuffer::didFail(%d) %p", errorCode, this);
+    WTF_LOG(Media, "SourceBuffer::didFail(%d) %p", errorCode, this);
     appendStreamDone(false);
 }
 
+void SourceBuffer::trace(Visitor* visitor)
+{
+    visitor->trace(m_source);
+}
+
 } // namespace WebCore