1521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)/*
2521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved.
3521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) *
4521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
5521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * modification, are permitted provided that the following conditions are
6521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * met:
7521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) *
8521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
9521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
10521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
11521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
12521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * in the documentation and/or other materials provided with the
13521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * distribution.
14521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
15521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
16521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * this software without specific prior written permission.
17521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) *
18521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) */
30521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
31521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "config.h"
32521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "modules/mediasource/SourceBuffer.h"
33521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
34197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionMessages.h"
35197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionState.h"
367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "core/dom/ExceptionCode.h"
371e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "core/dom/ExecutionContext.h"
38197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/events/Event.h"
3906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/GenericEventQueue.h"
4006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/fileapi/FileReaderLoader.h"
41521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "core/html/TimeRanges.h"
42197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/streams/Stream.h"
43521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "modules/mediasource/MediaSource.h"
441e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/Logging.h"
451e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/TraceEvent.h"
4651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "public/platform/WebSourceBuffer.h"
47521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/ArrayBuffer.h"
48521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/ArrayBufferView.h"
493c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "wtf/MathExtras.h"
503c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
513c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include <limits>
52521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
5351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)using blink::WebSourceBuffer;
5451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
55c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
56521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
57d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)namespace {
58d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
59d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static bool throwExceptionIfRemovedOrUpdating(bool isRemoved, bool isUpdating, ExceptionState& exceptionState)
60d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
61d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (isRemoved) {
62d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "This SourceBuffer has been removed from the parent media source.");
63d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return true;
64d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
65d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (isUpdating) {
66d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "This SourceBuffer is still processing an 'appendBuffer', 'appendStream', or 'remove' operation.");
67d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return true;
68d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
69d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
70d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return false;
71d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
72d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
73d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} // namespace
7409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
75197021e6b966cfb06891637935ef33fff06433d1Ben MurdochSourceBuffer* SourceBuffer::create(PassOwnPtr<WebSourceBuffer> webSourceBuffer, MediaSource* source, GenericEventQueue* asyncEventQueue)
76521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
77197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    SourceBuffer* sourceBuffer(adoptRefCountedGarbageCollectedWillBeNoop(new SourceBuffer(webSourceBuffer, source, asyncEventQueue)));
78521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    sourceBuffer->suspendIfNeeded();
79197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return sourceBuffer;
80521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
81521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
8251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)SourceBuffer::SourceBuffer(PassOwnPtr<WebSourceBuffer> webSourceBuffer, MediaSource* source, GenericEventQueue* asyncEventQueue)
831e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    : ActiveDOMObject(source->executionContext())
8451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    , m_webSourceBuffer(webSourceBuffer)
85521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    , m_source(source)
86521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    , m_asyncEventQueue(asyncEventQueue)
8709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , m_mode(segmentsKeyword())
88521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    , m_updating(false)
89521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    , m_timestampOffset(0)
903c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    , m_appendWindowStart(0)
913c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    , m_appendWindowEnd(std::numeric_limits<double>::infinity())
927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    , m_firstInitializationSegmentReceived(false)
93323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    , m_pendingAppendDataOffset(0)
94f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    , m_appendBufferAsyncPartRunner(this, &SourceBuffer::appendBufferAsyncPart)
9523e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    , m_pendingRemoveStart(-1)
9623e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    , m_pendingRemoveEnd(-1)
97f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    , m_removeAsyncPartRunner(this, &SourceBuffer::removeAsyncPart)
9806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    , m_streamMaxSizeValid(false)
9906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    , m_streamMaxSize(0)
100f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    , m_appendStreamAsyncPartRunner(this, &SourceBuffer::appendStreamAsyncPart)
101521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
10251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    ASSERT(m_webSourceBuffer);
103521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    ASSERT(m_source);
1047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_webSourceBuffer->setClient(this);
105521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
106521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
107521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)SourceBuffer::~SourceBuffer()
108521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
109197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // Oilpan: a SourceBuffer might be finalized without having been
110197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // explicitly removed first, hence the asserts below will not
111197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // hold.
112197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if !ENABLE(OILPAN)
113521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    ASSERT(isRemoved());
11406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    ASSERT(!m_loader);
11506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    ASSERT(!m_stream);
1167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(!m_webSourceBuffer);
117197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
118521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
119521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
12009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const AtomicString& SourceBuffer::segmentsKeyword()
12109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
12209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, segments, ("segments", AtomicString::ConstructFromLiteral));
12309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return segments;
12409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
12509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
12609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const AtomicString& SourceBuffer::sequenceKeyword()
12709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
12809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, sequence, ("sequence", AtomicString::ConstructFromLiteral));
12909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return sequence;
13009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
13109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
13209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SourceBuffer::setMode(const AtomicString& newMode, ExceptionState& exceptionState)
13309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
13409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Section 3.1 On setting mode attribute steps.
13509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // 1. Let new mode equal the new value being assigned to this attribute.
136323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 2. If this object has been removed from the sourceBuffers attribute of the parent media source, then throw
13709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    //    an INVALID_STATE_ERR exception and abort these steps.
138323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 3. If the updating attribute equals true, then throw an INVALID_STATE_ERR exception and abort these steps.
139d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState))
14009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return;
14109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
142323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 4. If the readyState attribute of the parent media source is in the "ended" state then run the following steps:
143323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 4.1 Set the readyState attribute of the parent media source to "open"
144323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 4.2 Queue a task to fire a simple event named sourceopen at the parent media source.
14509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_source->openIfInEndedState();
14609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
147323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 5. If the append state equals PARSING_MEDIA_SEGMENT, then throw an INVALID_STATE_ERR and abort these steps.
148323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 6. If the new mode equals "sequence", then set the group start timestamp to the highest presentation end timestamp.
14909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    WebSourceBuffer::AppendMode appendMode = WebSourceBuffer::AppendModeSegments;
15009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (newMode == sequenceKeyword())
15109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        appendMode = WebSourceBuffer::AppendModeSequence;
15209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!m_webSourceBuffer->setMode(appendMode)) {
153d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "The mode may not be set while the SourceBuffer's append state is 'PARSING_MEDIA_SEGMENT'.");
15409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return;
15509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
15609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
157323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 7. Update the attribute to new mode.
15809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_mode = newMode;
15909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
16009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
161197021e6b966cfb06891637935ef33fff06433d1Ben MurdochPassRefPtrWillBeRawPtr<TimeRanges> SourceBuffer::buffered(ExceptionState& exceptionState) const
162521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
163521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // Section 3.1 buffered attribute steps.
164521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
165e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    //    InvalidStateError exception and abort these steps.
166521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    if (isRemoved()) {
167d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "This SourceBuffer has been removed from the parent media source.");
168d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return nullptr;
169521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
170521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
171521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 2. Return a new static normalized TimeRanges object for the media segments buffered.
17251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return TimeRanges::create(m_webSourceBuffer->buffered());
173521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
174521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
175521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)double SourceBuffer::timestampOffset() const
176521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
177521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    return m_timestampOffset;
178521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
179521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
18051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void SourceBuffer::setTimestampOffset(double offset, ExceptionState& exceptionState)
181521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
182521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // Section 3.1 timestampOffset attribute setter steps.
183323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-SourceBuffer-timestampOffset
18423e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    // 1. Let new timestamp offset equal the new value being assigned to this attribute.
18523e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    // 2. If this object has been removed from the sourceBuffers attribute of the parent media source, then throw an
186e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    //    InvalidStateError exception and abort these steps.
18723e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    // 3. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
188d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState))
1891fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch        return;
1901fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch
191521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 4. If the readyState attribute of the parent media source is in the "ended" state then run the following steps:
192521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 4.1 Set the readyState attribute of the parent media source to "open"
193521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 4.2 Queue a task to fire a simple event named sourceopen at the parent media source.
194521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_source->openIfInEndedState();
195521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
19609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // 5. If the append state equals PARSING_MEDIA_SEGMENT, then throw an INVALID_STATE_ERR and abort these steps.
19709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // 6. If the mode attribute equals "sequence", then set the group start timestamp to new timestamp offset.
19851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (!m_webSourceBuffer->setTimestampOffset(offset)) {
199d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "The timestamp offset may not be set while the SourceBuffer's append state is 'PARSING_MEDIA_SEGMENT'.");
200521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return;
201521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
202521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
20323e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    // 7. Update the attribute to new timestamp offset.
204521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_timestampOffset = offset;
205521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
206521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
2073c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdochdouble SourceBuffer::appendWindowStart() const
2083c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
2093c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    return m_appendWindowStart;
2103c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
2113c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
21251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void SourceBuffer::setAppendWindowStart(double start, ExceptionState& exceptionState)
2133c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
2143c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // Section 3.1 appendWindowStart attribute setter steps.
215323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-SourceBuffer-appendWindowStart
2163c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
2173c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    //    InvalidStateError exception and abort these steps.
2183c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
219d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState))
2203c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        return;
2213c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2223c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // 3. If the new value is less than 0 or greater than or equal to appendWindowEnd then throw an InvalidAccessError
2233c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    //    exception and abort these steps.
2243c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (start < 0 || start >= m_appendWindowEnd) {
225d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::indexOutsideRange("value", start, 0.0, ExceptionMessages::ExclusiveBound, m_appendWindowEnd, ExceptionMessages::InclusiveBound));
2263c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        return;
2273c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    }
2283c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
22951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    m_webSourceBuffer->setAppendWindowStart(start);
2303c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2313c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // 4. Update the attribute to the new value.
2323c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    m_appendWindowStart = start;
2333c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
2343c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2353c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdochdouble SourceBuffer::appendWindowEnd() const
2363c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
2373c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    return m_appendWindowEnd;
2383c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
2393c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
24051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void SourceBuffer::setAppendWindowEnd(double end, ExceptionState& exceptionState)
2413c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
2423c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // Section 3.1 appendWindowEnd attribute setter steps.
243323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-SourceBuffer-appendWindowEnd
2443c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // 1. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
2453c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    //    InvalidStateError exception and abort these steps.
2463c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // 2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
247d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState))
2483c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        return;
2493c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2503c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // 3. If the new value equals NaN, then throw an InvalidAccessError and abort these steps.
251d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (std::isnan(end)) {
252d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::notAFiniteNumber(end));
253d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
254d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
255323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 4. If the new value is less than or equal to appendWindowStart then throw an InvalidAccessError
256323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    //    exception and abort these steps.
257d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (end <= m_appendWindowStart) {
258f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::indexExceedsMinimumBound("value", end, m_appendWindowStart));
2593c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        return;
2603c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    }
2613c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
26251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    m_webSourceBuffer->setAppendWindowEnd(end);
2633c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2643c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // 5. Update the attribute to the new value.
2653c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    m_appendWindowEnd = end;
2663c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
2673c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
26851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void SourceBuffer::appendBuffer(PassRefPtr<ArrayBuffer> data, ExceptionState& exceptionState)
269521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
270521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // Section 3.2 appendBuffer()
271521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
27251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    appendBufferInternal(static_cast<const unsigned char*>(data->data()), data->byteLength(), exceptionState);
273521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
274521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
27551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void SourceBuffer::appendBuffer(PassRefPtr<ArrayBufferView> data, ExceptionState& exceptionState)
276521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
277521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // Section 3.2 appendBuffer()
278521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
27951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    appendBufferInternal(static_cast<const unsigned char*>(data->baseAddress()), data->byteLength(), exceptionState);
28006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)}
28106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
282d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void SourceBuffer::appendStream(PassRefPtrWillBeRawPtr<Stream> stream, ExceptionState& exceptionState)
28306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){
28406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    m_streamMaxSizeValid = false;
28551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    appendStreamInternal(stream, exceptionState);
28606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)}
28706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
288d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void SourceBuffer::appendStream(PassRefPtrWillBeRawPtr<Stream> stream, unsigned long long maxSize, ExceptionState& exceptionState)
28906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){
29006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    m_streamMaxSizeValid = maxSize > 0;
29106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    if (m_streamMaxSizeValid)
29206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        m_streamMaxSize = maxSize;
29351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    appendStreamInternal(stream, exceptionState);
294521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
295521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
29651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void SourceBuffer::abort(ExceptionState& exceptionState)
297521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
298521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // Section 3.2 abort() method steps.
299521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-abort-void
300521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 1. If this object has been removed from the sourceBuffers attribute of the parent media source
301e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    //    then throw an InvalidStateError exception and abort these steps.
302521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 2. If the readyState attribute of the parent media source is not in the "open" state
303e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    //    then throw an InvalidStateError exception and abort these steps.
304d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (isRemoved()) {
305d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "This SourceBuffer has been removed from the parent media source.");
306d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
307d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
308d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!m_source->isOpen()) {
309d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "The parent media source's readyState is not 'open'.");
310521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return;
311521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
312521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
313521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 3. If the sourceBuffer.updating attribute equals true, then run the following steps: ...
314521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    abortIfUpdating();
315521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
316521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 4. Run the reset parser state algorithm.
31751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    m_webSourceBuffer->abort();
318521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3193c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // 5. Set appendWindowStart to 0.
32051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    setAppendWindowStart(0, exceptionState);
3213c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
3223c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // 6. Set appendWindowEnd to positive Infinity.
32351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    setAppendWindowEnd(std::numeric_limits<double>::infinity(), exceptionState);
324521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
325521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
32651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void SourceBuffer::remove(double start, double end, ExceptionState& exceptionState)
32723e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch{
32823e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    // Section 3.2 remove() method steps.
329e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // 1. If duration equals NaN, then throw an InvalidAccessError exception and abort these steps.
330e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // 2. If start is negative or greater than duration, then throw an InvalidAccessError exception and abort these steps.
331d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
332d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (start < 0 || (m_source && (std::isnan(m_source->duration()) || start > m_source->duration()))) {
333d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::indexOutsideRange("start", start, 0.0, ExceptionMessages::ExclusiveBound, !m_source || std::isnan(m_source->duration()) ? 0 : m_source->duration(), ExceptionMessages::ExclusiveBound));
334d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
335d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
336e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
337e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // 3. If end is less than or equal to start or end equals NaN, then throw an InvalidAccessError exception and abort these steps.
338e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    if (end <= start || std::isnan(end)) {
339d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidAccessError, "The end value provided (" + String::number(end) + ") must be greater than the start value provided (" + String::number(start) + ").");
34023e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch        return;
34123e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    }
34223e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch
343e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // 4. If this object has been removed from the sourceBuffers attribute of the parent media source then throw an
34423e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    //    InvalidStateError exception and abort these steps.
345e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // 5. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
346d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState))
34723e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch        return;
34823e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch
3491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::remove", this);
3501e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
351e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // 6. If the readyState attribute of the parent media source is in the "ended" state then run the following steps:
352e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // 6.1. Set the readyState attribute of the parent media source to "open"
353e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // 6.2. Queue a task to fire a simple event named sourceopen at the parent media source .
35423e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    m_source->openIfInEndedState();
35523e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch
356e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // 7. Run the range removal algorithm with start and end as the start and end of the removal range.
357e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // 7.3. Set the updating attribute to true.
35823e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    m_updating = true;
35923e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch
360e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // 7.4. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
3611e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    scheduleEvent(EventTypeNames::updatestart);
36223e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch
363e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // 7.5. Return control to the caller and run the rest of the steps asynchronously.
36423e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    m_pendingRemoveStart = start;
36523e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    m_pendingRemoveEnd = end;
366f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_removeAsyncPartRunner.runAsync();
36723e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch}
368521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
369521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void SourceBuffer::abortIfUpdating()
370521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
371521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // Section 3.2 abort() method step 3 substeps.
372521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-abort-void
373521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
374521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    if (!m_updating)
375521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return;
376521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3771e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    const char* traceEventName = 0;
3781e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    if (!m_pendingAppendData.isEmpty()) {
3791e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        traceEventName = "SourceBuffer::appendBuffer";
3801e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    } else if (m_stream) {
3811e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        traceEventName = "SourceBuffer::appendStream";
3821e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    } else if (m_pendingRemoveStart != -1) {
3831e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        traceEventName = "SourceBuffer::remove";
3841e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    } else {
3851e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        ASSERT_NOT_REACHED();
3861e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    }
3871e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
388521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 3.1. Abort the buffer append and stream append loop algorithms if they are running.
389f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_appendBufferAsyncPartRunner.stop();
390521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_pendingAppendData.clear();
391323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    m_pendingAppendDataOffset = 0;
392521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
393f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_removeAsyncPartRunner.stop();
39423e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    m_pendingRemoveStart = -1;
39523e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    m_pendingRemoveEnd = -1;
39623e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch
397f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_appendStreamAsyncPartRunner.stop();
39806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    clearAppendStreamState();
39906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
400521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 3.2. Set the updating attribute to false.
401521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_updating = false;
402521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
403521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 3.3. Queue a task to fire a simple event named abort at this SourceBuffer object.
4041e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    scheduleEvent(EventTypeNames::abort);
405521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
406521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 3.4. Queue a task to fire a simple event named updateend at this SourceBuffer object.
4071e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    scheduleEvent(EventTypeNames::updateend);
4081e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
4091e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    TRACE_EVENT_ASYNC_END0("media", traceEventName, this);
410521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
411521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
412521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void SourceBuffer::removedFromMediaSource()
413521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
414521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    if (isRemoved())
415521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return;
416521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
41723e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    abortIfUpdating();
41823e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch
41951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    m_webSourceBuffer->removedFromMediaSource();
42051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    m_webSourceBuffer.clear();
421d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_source = nullptr;
422521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_asyncEventQueue = 0;
423521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
424521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
4257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid SourceBuffer::initializationSegmentReceived()
4267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
4277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(m_source);
4287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(m_updating);
4297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
4307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#sourcebuffer-init-segment-received
4317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // FIXME: Make steps 1-7 synchronous with this call.
4327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // FIXME: Augment the interface to this method to implement compliant steps 4-7 here.
4337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Step 3 (if the first initialization segment received flag is true) is
4347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // implemented by caller.
4357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
4367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!m_firstInitializationSegmentReceived) {
4377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // 5. If active track flag equals true, then run the following steps:
4387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // 5.1. Add this SourceBuffer to activeSourceBuffers.
4397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // 5.2. Queue a task to fire a simple event named addsourcebuffer at
4407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // activesourcebuffers.
4417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_source->setSourceBufferActive(this);
4427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
4437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // 6. Set first initialization segment received flag to true.
4447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_firstInitializationSegmentReceived = true;
4457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
4467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
4477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
448521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)bool SourceBuffer::hasPendingActivity() const
449521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
450521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    return m_source;
451521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
452521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
453f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)void SourceBuffer::suspend()
454f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){
455f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_appendBufferAsyncPartRunner.suspend();
456f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_removeAsyncPartRunner.suspend();
457f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_appendStreamAsyncPartRunner.suspend();
458f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)}
459f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
460f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)void SourceBuffer::resume()
461f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){
462f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_appendBufferAsyncPartRunner.resume();
463f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_removeAsyncPartRunner.resume();
464f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_appendStreamAsyncPartRunner.resume();
465f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)}
466f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
467521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void SourceBuffer::stop()
468521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
469f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_appendBufferAsyncPartRunner.stop();
470f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_removeAsyncPartRunner.stop();
471f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_appendStreamAsyncPartRunner.stop();
472521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
473521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
4741e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)ExecutionContext* SourceBuffer::executionContext() const
475521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
4761e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return ActiveDOMObject::executionContext();
477521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
478521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
479521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)const AtomicString& SourceBuffer::interfaceName() const
480521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
4811e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return EventTargetNames::SourceBuffer;
482521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
483521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
484521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)bool SourceBuffer::isRemoved() const
485521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
486521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    return !m_source;
487521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
488521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
489521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void SourceBuffer::scheduleEvent(const AtomicString& eventName)
490521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
491521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    ASSERT(m_asyncEventQueue);
492521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
493a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    RefPtrWillBeRawPtr<Event> event = Event::create(eventName);
494521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    event->setTarget(this);
495521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
496521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_asyncEventQueue->enqueueEvent(event.release());
497521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
498521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
49951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void SourceBuffer::appendBufferInternal(const unsigned char* data, unsigned size, ExceptionState& exceptionState)
500521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
501521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // Section 3.2 appendBuffer()
502521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-appendBuffer-void-ArrayBufferView-data
503521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
504323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 1. Run the prepare append algorithm.
505323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-prepare-append
506323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    //  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.
507323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    //  2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
508d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState))
509521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return;
510521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
511323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    TRACE_EVENT_ASYNC_BEGIN1("media", "SourceBuffer::appendBuffer", this, "size", size);
5121e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
513323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    //  3. If the readyState attribute of the parent media source is in the "ended" state then run the following steps: ...
514521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_source->openIfInEndedState();
515521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
516323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    //  Steps 4-5 - end "prepare append" algorithm.
517521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
518323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 2. Add data to the end of the input buffer.
519323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    ASSERT(data || size == 0);
520323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (data)
521323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        m_pendingAppendData.append(data, size);
522323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    m_pendingAppendDataOffset = 0;
523521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
524323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 3. Set the updating attribute to true.
525521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_updating = true;
526521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
527323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 4. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
5281e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    scheduleEvent(EventTypeNames::updatestart);
529521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
530323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 5. Asynchronously run the buffer append algorithm.
531f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_appendBufferAsyncPartRunner.runAsync();
5321e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
533323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this, "initialDelay");
534521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
535521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
536f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)void SourceBuffer::appendBufferAsyncPart()
537521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
538521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    ASSERT(m_updating);
539521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
540521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // Section 3.5.4 Buffer Append Algorithm
541521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-buffer-append
542521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
543521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 1. Run the segment parser loop algorithm.
544521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // Step 2 doesn't apply since we run Step 1 synchronously here.
545323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    ASSERT(m_pendingAppendData.size() >= m_pendingAppendDataOffset);
546323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    size_t appendSize = m_pendingAppendData.size() - m_pendingAppendDataOffset;
547323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
548323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // Impose an arbitrary max size for a single append() call so that an append
549323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // doesn't block the renderer event loop very long. This value was selected
550323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // by looking at YouTube SourceBuffer usage across a variety of bitrates.
551323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // This value allows relatively large appends while keeping append() call
552323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // duration in the  ~5-15ms range.
553323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    const size_t MaxAppendSize = 128 * 1024;
554323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (appendSize > MaxAppendSize)
555323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        appendSize = MaxAppendSize;
556323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
557323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    TRACE_EVENT_ASYNC_STEP_INTO1("media", "SourceBuffer::appendBuffer", this, "appending", "appendSize", static_cast<unsigned>(appendSize));
558323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
559323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // |zero| is used for 0 byte appends so we always have a valid pointer.
560323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // We need to convey all appends, even 0 byte ones to |m_webSourceBuffer|
561323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // so that it can clear its end of stream state if necessary.
562323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    unsigned char zero = 0;
563323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    unsigned char* appendData = &zero;
564323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (appendSize)
565323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        appendData = m_pendingAppendData.data() + m_pendingAppendDataOffset;
566323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
567323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    m_webSourceBuffer->append(appendData, appendSize, &m_timestampOffset);
568323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
569323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    m_pendingAppendDataOffset += appendSize;
570323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
571323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (m_pendingAppendDataOffset < m_pendingAppendData.size()) {
572323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        m_appendBufferAsyncPartRunner.runAsync();
573323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        TRACE_EVENT_ASYNC_STEP_INTO0("media", "SourceBuffer::appendBuffer", this, "nextPieceDelay");
574323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        return;
575591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
576521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
577521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 3. Set the updating attribute to false.
578521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_updating = false;
579521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_pendingAppendData.clear();
580323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    m_pendingAppendDataOffset = 0;
581521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
582521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 4. Queue a task to fire a simple event named update at this SourceBuffer object.
5831e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    scheduleEvent(EventTypeNames::update);
584521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
585521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 5. Queue a task to fire a simple event named updateend at this SourceBuffer object.
5861e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    scheduleEvent(EventTypeNames::updateend);
5871e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendBuffer", this);
588521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
589521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
590f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)void SourceBuffer::removeAsyncPart()
59123e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch{
59223e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    ASSERT(m_updating);
59323e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    ASSERT(m_pendingRemoveStart >= 0);
59423e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    ASSERT(m_pendingRemoveStart < m_pendingRemoveEnd);
59523e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch
59623e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    // Section 3.2 remove() method steps
59723e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-SourceBuffer-remove-void-double-start-double-end
59823e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch
59923e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    // 9. Run the coded frame removal algorithm with start and end as the start and end of the removal range.
60051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    m_webSourceBuffer->remove(m_pendingRemoveStart, m_pendingRemoveEnd);
60123e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch
60223e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    // 10. Set the updating attribute to false.
60323e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    m_updating = false;
60423e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    m_pendingRemoveStart = -1;
60523e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    m_pendingRemoveEnd = -1;
60623e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch
60723e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    // 11. Queue a task to fire a simple event named update at this SourceBuffer object.
6081e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    scheduleEvent(EventTypeNames::update);
60923e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch
61023e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch    // 12. Queue a task to fire a simple event named updateend at this SourceBuffer object.
6111e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    scheduleEvent(EventTypeNames::updateend);
61223e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch}
61323e46e0f045bc1935a09565578b448d36cfc5b8cBen Murdoch
614d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void SourceBuffer::appendStreamInternal(PassRefPtrWillBeRawPtr<Stream> stream, ExceptionState& exceptionState)
61506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){
61606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    // Section 3.2 appendStream()
61706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    // 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
618323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // (0. If the stream has been neutered, then throw an InvalidAccessError exception and abort these steps.)
619323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (stream->isNeutered()) {
620323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        exceptionState.throwDOMException(InvalidAccessError, "The stream provided has been neutered.");
62106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return;
62206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    }
62306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
624323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 1. Run the prepare append algorithm.
62506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    //  Section 3.5.4 Prepare Append Algorithm.
62606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    //  https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-prepare-append
62706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    //  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.
62806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    //  2. If the updating attribute equals true, then throw an InvalidStateError exception and abort these steps.
629d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (throwExceptionIfRemovedOrUpdating(isRemoved(), m_updating, exceptionState))
63006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return;
63106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
6321e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    TRACE_EVENT_ASYNC_BEGIN0("media", "SourceBuffer::appendStream", this);
6331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
63406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    //  3. If the readyState attribute of the parent media source is in the "ended" state then run the following steps: ...
63506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    m_source->openIfInEndedState();
63606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
63751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // Steps 4-5 of the prepare append algorithm are handled by m_webSourceBuffer.
63806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
639323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 2. Set the updating attribute to true.
64006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    m_updating = true;
64106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
642323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 3. Queue a task to fire a simple event named updatestart at this SourceBuffer object.
6431e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    scheduleEvent(EventTypeNames::updatestart);
64406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
645323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 4. Asynchronously run the stream append loop algorithm with stream and maxSize.
64606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
64706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    stream->neuter();
64806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    m_loader = adoptPtr(new FileReaderLoader(FileReaderLoader::ReadByClient, this));
64906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    m_stream = stream;
650f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    m_appendStreamAsyncPartRunner.runAsync();
65106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)}
65206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
653f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)void SourceBuffer::appendStreamAsyncPart()
65406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){
65506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    ASSERT(m_updating);
65606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    ASSERT(m_loader);
65706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    ASSERT(m_stream);
65806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
65906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    // Section 3.5.6 Stream Append Loop
66006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-stream-append-loop
66106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
66206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    // 1. If maxSize is set, then let bytesLeft equal maxSize.
66306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    // 2. Loop Top: If maxSize is set and bytesLeft equals 0, then jump to the loop done step below.
66406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    if (m_streamMaxSizeValid && !m_streamMaxSize) {
66506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        appendStreamDone(true);
66606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return;
66706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    }
66806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
66906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    // Steps 3-11 are handled by m_loader.
67006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    // Note: Passing 0 here signals that maxSize was not set. (i.e. Read all the data in the stream).
6711e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    m_loader->start(executionContext(), *m_stream, m_streamMaxSizeValid ? m_streamMaxSize : 0);
67206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)}
67306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
67406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)void SourceBuffer::appendStreamDone(bool success)
67506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){
67606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    ASSERT(m_updating);
67706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    ASSERT(m_loader);
67806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    ASSERT(m_stream);
67906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
68006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    clearAppendStreamState();
68106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
68206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    if (!success) {
68306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        // Section 3.5.3 Append Error Algorithm
68406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#sourcebuffer-append-error
68506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        //
68606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        // 1. Run the reset parser state algorithm. (Handled by caller)
68706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        // 2. Set the updating attribute to false.
68806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        m_updating = false;
68906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
69006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        // 3. Queue a task to fire a simple event named error at this SourceBuffer object.
6911e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        scheduleEvent(EventTypeNames::error);
69206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
69306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        // 4. Queue a task to fire a simple event named updateend at this SourceBuffer object.
6941e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        scheduleEvent(EventTypeNames::updateend);
6951e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this);
69606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return;
69706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    }
69806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
69906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    // Section 3.5.6 Stream Append Loop
70051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // Steps 1-11 are handled by appendStreamAsyncPart(), |m_loader|, and |m_webSourceBuffer|.
70106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    // 12. Loop Done: Set the updating attribute to false.
70206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    m_updating = false;
70306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
70406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    // 13. Queue a task to fire a simple event named update at this SourceBuffer object.
7051e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    scheduleEvent(EventTypeNames::update);
70606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
70706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    // 14. Queue a task to fire a simple event named updateend at this SourceBuffer object.
7081e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    scheduleEvent(EventTypeNames::updateend);
7091e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::appendStream", this);
71006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)}
71106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
71206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)void SourceBuffer::clearAppendStreamState()
71306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){
71406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    m_streamMaxSizeValid = false;
71506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    m_streamMaxSize = 0;
71606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    m_loader.clear();
717d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_stream = nullptr;
71806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)}
71906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
72006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)void SourceBuffer::didStartLoading()
72106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){
722a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(Media, "SourceBuffer::didStartLoading() %p", this);
72306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)}
72406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
72506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)void SourceBuffer::didReceiveDataForClient(const char* data, unsigned dataLength)
72606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){
727a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(Media, "SourceBuffer::didReceiveDataForClient(%d) %p", dataLength, this);
72806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    ASSERT(m_updating);
72906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    ASSERT(m_loader);
730d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_webSourceBuffer->append(reinterpret_cast<const unsigned char*>(data), dataLength, &m_timestampOffset);
73106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)}
73206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
73306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)void SourceBuffer::didFinishLoading()
73406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){
735a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(Media, "SourceBuffer::didFinishLoading() %p", this);
73606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    appendStreamDone(true);
73706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)}
73806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
73906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)void SourceBuffer::didFail(FileError::ErrorCode errorCode)
74006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){
741a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(Media, "SourceBuffer::didFail(%d) %p", errorCode, this);
74206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    appendStreamDone(false);
74306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)}
74406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
74509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SourceBuffer::trace(Visitor* visitor)
74609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
74709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    visitor->trace(m_source);
748d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    visitor->trace(m_stream);
749d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    EventTargetWithInlineData::trace(visitor);
75009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
75109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
752c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
753