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/MediaSource.h"
33521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
34197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionMessages.h"
35197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionState.h"
36197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionStatePlaceholder.h"
377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "core/dom/ExceptionCode.h"
385d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/events/Event.h"
3906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/GenericEventQueue.h"
40f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "core/html/HTMLMediaElement.h"
41521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "core/html/TimeRanges.h"
4251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "modules/mediasource/MediaSourceRegistry.h"
431e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/ContentType.h"
441e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/Logging.h"
4551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/MIMETypeRegistry.h"
4676c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)#include "platform/RuntimeEnabledFeatures.h"
47f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "platform/TraceEvent.h"
48f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "public/platform/WebMediaSource.h"
4951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "public/platform/WebSourceBuffer.h"
50521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/Uint8Array.h"
510019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch#include "wtf/text/CString.h"
52521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
53f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)using blink::WebMediaSource;
5451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)using blink::WebSourceBuffer;
5551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
56c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
57521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
58f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)static bool throwExceptionIfClosedOrUpdating(bool isOpen, bool isUpdating, ExceptionState& exceptionState)
59f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
60f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (!isOpen) {
61f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "The MediaSource's readyState is not 'open'.");
62f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return true;
63f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    }
64f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (isUpdating) {
65f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "The 'updating' attribute is true on one or more of this MediaSource's SourceBuffers.");
66f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return true;
67f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    }
68f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
69f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return false;
70f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
71f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
72f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)const AtomicString& MediaSource::openKeyword()
73f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
74f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, open, ("open", AtomicString::ConstructFromLiteral));
75f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return open;
76f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
77f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
78f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)const AtomicString& MediaSource::closedKeyword()
79f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
80f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, closed, ("closed", AtomicString::ConstructFromLiteral));
81f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return closed;
82f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
83f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
84f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)const AtomicString& MediaSource::endedKeyword()
85f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
86f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, ended, ("ended", AtomicString::ConstructFromLiteral));
87f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return ended;
88f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
89f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
90197021e6b966cfb06891637935ef33fff06433d1Ben MurdochMediaSource* MediaSource::create(ExecutionContext* context)
91521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
92197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    MediaSource* mediaSource(adoptRefCountedGarbageCollectedWillBeNoop(new MediaSource(context)));
93521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    mediaSource->suspendIfNeeded();
94197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return mediaSource;
95521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
96521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
971e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)MediaSource::MediaSource(ExecutionContext* context)
98f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    : ActiveDOMObject(context)
99f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    , m_readyState(closedKeyword())
100f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    , m_asyncEventQueue(GenericEventQueue::create(this))
101197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    , m_attachedElement(nullptr)
102f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    , m_sourceBuffers(SourceBufferList::create(executionContext(), m_asyncEventQueue.get()))
103f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    , m_activeSourceBuffers(SourceBufferList::create(executionContext(), m_asyncEventQueue.get()))
104197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    , m_isAddedToRegistry(false)
105521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
106a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(Media, "MediaSource::MediaSource %p", this);
107521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
108521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
109521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)MediaSource::~MediaSource()
110521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
111a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(Media, "MediaSource::~MediaSource %p", this);
112197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if !ENABLE(OILPAN)
113521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    ASSERT(isClosed());
114197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
115521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
116521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
11751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)SourceBuffer* MediaSource::addSourceBuffer(const String& type, ExceptionState& exceptionState)
118521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
119a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(Media, "MediaSource::addSourceBuffer(%s) %p", type.ascii().data(), this);
120521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
121521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type
122323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 1. If type is an empty string then throw an InvalidAccessError exception
123323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // and abort these steps.
124323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (type.isEmpty()) {
125d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidAccessError, "The type provided is empty.");
126521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return 0;
127521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
128521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
129521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 2. If type contains a MIME type that is not supported ..., then throw a
130e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // NotSupportedError exception and abort these steps.
131521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    if (!isTypeSupported(type)) {
132d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(NotSupportedError, "The type provided ('" + type + "') is unsupported.");
133521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return 0;
134521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
135521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
136521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 4. If the readyState attribute is not in the "open" state then throw an
137e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // InvalidStateError exception and abort these steps.
138521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    if (!isOpen()) {
139d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(InvalidStateError, "The MediaSource's readyState is not 'open'.");
140521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return 0;
141521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
142521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
143521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 5. Create a new SourceBuffer object and associated resources.
144521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    ContentType contentType(type);
145521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    Vector<String> codecs = contentType.codecs();
14651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    OwnPtr<WebSourceBuffer> webSourceBuffer = createWebSourceBuffer(contentType.type(), codecs, exceptionState);
147521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
14851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (!webSourceBuffer) {
14951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        ASSERT(exceptionState.code() == NotSupportedError || exceptionState.code() == QuotaExceededError);
150e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // 2. If type contains a MIME type that is not supported ..., then throw a NotSupportedError exception and abort these steps.
151e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // 3. If the user agent can't handle any more SourceBuffer objects then throw a QuotaExceededError exception and abort these steps
152521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return 0;
153521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
154521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
155197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    SourceBuffer* buffer = SourceBuffer::create(webSourceBuffer.release(), this, m_asyncEventQueue.get());
156521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 6. Add the new object to sourceBuffers and fire a addsourcebuffer on that object.
157521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_sourceBuffers->add(buffer);
1587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
159521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 7. Return the new object to the caller.
160197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return buffer;
161521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
162521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
16351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void MediaSource::removeSourceBuffer(SourceBuffer* buffer, ExceptionState& exceptionState)
164521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
165a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(Media, "MediaSource::removeSourceBuffer() %p", this);
166521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
167521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-removeSourceBuffer-void-SourceBuffer-sourceBuffer
168521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
169323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 1. If sourceBuffer specifies an object that is not in sourceBuffers then
170e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // throw a NotFoundError exception and abort these steps.
171521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    if (!m_sourceBuffers->length() || !m_sourceBuffers->contains(buffer)) {
172d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        exceptionState.throwDOMException(NotFoundError, "The SourceBuffer provided is not contained in this MediaSource.");
173521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return;
174521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
175521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
176323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 2. If the sourceBuffer.updating attribute equals true, then run the following steps: ...
177521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    buffer->abortIfUpdating();
178521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
179323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // Steps 3-8 are related to updating audioTracks, videoTracks, and textTracks which aren't implmented yet.
180521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // FIXME(91649): support track selection
181521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
182323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 9. If sourceBuffer is in activeSourceBuffers, then remove sourceBuffer from activeSourceBuffers ...
183521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_activeSourceBuffers->remove(buffer);
184521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
185323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 10. Remove sourceBuffer from sourceBuffers and fire a removesourcebuffer event
186521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // on that object.
187521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_sourceBuffers->remove(buffer);
188521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
189323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // 11. Destroy all resources for sourceBuffer.
190521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    buffer->removedFromMediaSource();
191521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
192521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
193e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochvoid MediaSource::onReadyStateChange(const AtomicString& oldState, const AtomicString& newState)
194521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
195521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    if (isOpen()) {
1961e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        scheduleEvent(EventTypeNames::sourceopen);
197521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return;
198521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
199521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
200e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (oldState == openKeyword() && newState == endedKeyword()) {
2011e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        scheduleEvent(EventTypeNames::sourceended);
202521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return;
203521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
204521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
205521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    ASSERT(isClosed());
206521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
207521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_activeSourceBuffers->clear();
208521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
209521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // Clear SourceBuffer references to this object.
210521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    for (unsigned long i = 0; i < m_sourceBuffers->length(); ++i)
211521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        m_sourceBuffers->item(i)->removedFromMediaSource();
212521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_sourceBuffers->clear();
213521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
2141e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    scheduleEvent(EventTypeNames::sourceclose);
215521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
216521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
21709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool MediaSource::isUpdating() const
21809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
21909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Return true if any member of |m_sourceBuffers| is updating.
22009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    for (unsigned long i = 0; i < m_sourceBuffers->length(); ++i) {
22109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (m_sourceBuffers->item(i)->updating())
22209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return true;
22309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
22409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
22509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return false;
22609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
22709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
228521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)bool MediaSource::isTypeSupported(const String& type)
229521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
230a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    WTF_LOG(Media, "MediaSource::isTypeSupported(%s)", type.ascii().data());
231521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
232521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // Section 2.2 isTypeSupported() method steps.
233521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-MediaSource-isTypeSupported-boolean-DOMString-type
234521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 1. If type is an empty string, then return false.
235521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    if (type.isNull() || type.isEmpty())
236521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return false;
237521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
238521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    ContentType contentType(type);
239521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    String codecs = contentType.parameter("codecs");
240521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
241521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 2. If type does not contain a valid MIME type string, then return false.
242c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    if (contentType.type().isEmpty())
243521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return false;
244521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
245e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // Note: MediaSource.isTypeSupported() returning true implies that HTMLMediaElement.canPlayType() will return "maybe" or "probably"
246e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    // since it does not make sense for a MediaSource to support a type the HTMLMediaElement knows it cannot play.
247e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    if (HTMLMediaElement::supportsType(contentType, String()) == WebMimeRegistry::IsNotSupported)
248e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        return false;
249e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
250521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 3. If type contains a media type or media subtype that the MediaSource does not support, then return false.
251521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 4. If type contains at a codec that the MediaSource does not support, then return false.
252521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 5. If the MediaSource does not support the specified combination of media type, media subtype, and codecs then return false.
253521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    // 6. Return true.
254521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    return MIMETypeRegistry::isSupportedMediaSourceMIMEType(contentType.type(), codecs);
255521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
256521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
257521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)const AtomicString& MediaSource::interfaceName() const
258521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
2591e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    return EventTargetNames::MediaSource;
260521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
261521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
262f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)ExecutionContext* MediaSource::executionContext() const
263f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
264f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return ActiveDOMObject::executionContext();
265f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
266f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
267197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid MediaSource::clearWeakMembers(Visitor* visitor)
268197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
269197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(OILPAN)
270197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // Oilpan: If the MediaSource survived, but its attached media
271197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // element did not, signal the element that it can safely
272197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // notify its MediaSource during finalization by calling close().
273197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (m_attachedElement && !visitor->isAlive(m_attachedElement)) {
274197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        m_attachedElement->setCloseMediaSourceWhenFinalizing();
275197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        m_attachedElement.clear();
276197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
277197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
278197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
279197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
28009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MediaSource::trace(Visitor* visitor)
28109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
282197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(OILPAN)
2835d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    visitor->trace(m_asyncEventQueue);
284197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
28509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    visitor->trace(m_sourceBuffers);
28609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    visitor->trace(m_activeSourceBuffers);
287197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    visitor->registerWeakMembers<MediaSource, &MediaSource::clearWeakMembers>(this);
288f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    EventTargetWithInlineData::trace(visitor);
289f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
290f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
291f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void MediaSource::setWebMediaSourceAndOpen(PassOwnPtr<WebMediaSource> webMediaSource)
292f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
293f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    TRACE_EVENT_ASYNC_END0("media", "MediaSource::attachToElement", this);
294f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(webMediaSource);
295f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(!m_webMediaSource);
296f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(m_attachedElement);
297f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    m_webMediaSource = webMediaSource;
298f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    setReadyState(openKeyword());
299f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
300f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
301f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void MediaSource::addedToRegistry()
302f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
303197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ASSERT(!m_isAddedToRegistry);
304197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    m_isAddedToRegistry = true;
305f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
306f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
307f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void MediaSource::removedFromRegistry()
308f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
309197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ASSERT(m_isAddedToRegistry);
310197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    m_isAddedToRegistry = false;
311f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
312f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
313f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)double MediaSource::duration() const
314f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
315f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return isClosed() ? std::numeric_limits<float>::quiet_NaN() : m_webMediaSource->duration();
316f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
317f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
318197021e6b966cfb06891637935ef33fff06433d1Ben MurdochPassRefPtrWillBeRawPtr<TimeRanges> MediaSource::buffered() const
319f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
320f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // Implements MediaSource algorithm for HTMLMediaElement.buffered.
321f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#htmlmediaelement-extensions
322197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    WillBeHeapVector<RefPtrWillBeMember<TimeRanges> > ranges(m_activeSourceBuffers->length());
323f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    for (size_t i = 0; i < m_activeSourceBuffers->length(); ++i)
324f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        ranges[i] = m_activeSourceBuffers->item(i)->buffered(ASSERT_NO_EXCEPTION);
325f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
326f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 1. If activeSourceBuffers.length equals 0 then return an empty TimeRanges object and abort these steps.
327f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (ranges.isEmpty())
328f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return TimeRanges::create();
329f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
330f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 2. Let active ranges be the ranges returned by buffered for each SourceBuffer object in activeSourceBuffers.
331f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 3. Let highest end time be the largest range end time in the active ranges.
332f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    double highestEndTime = -1;
333f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    for (size_t i = 0; i < ranges.size(); ++i) {
334f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        unsigned length = ranges[i]->length();
335f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (length)
336f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            highestEndTime = std::max(highestEndTime, ranges[i]->end(length - 1, ASSERT_NO_EXCEPTION));
337f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    }
338f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
339f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // Return an empty range if all ranges are empty.
340f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (highestEndTime < 0)
341f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return TimeRanges::create();
342f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
343f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 4. Let intersection ranges equal a TimeRange object containing a single range from 0 to highest end time.
344197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    RefPtrWillBeRawPtr<TimeRanges> intersectionRanges = TimeRanges::create(0, highestEndTime);
345f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
346f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 5. For each SourceBuffer object in activeSourceBuffers run the following steps:
347f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    bool ended = readyState() == endedKeyword();
348f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    for (size_t i = 0; i < ranges.size(); ++i) {
349f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // 5.1 Let source ranges equal the ranges returned by the buffered attribute on the current SourceBuffer.
350f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        TimeRanges* sourceRanges = ranges[i].get();
351f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
352f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // 5.2 If readyState is "ended", then set the end time on the last range in source ranges to highest end time.
353f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (ended && sourceRanges->length())
354f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            sourceRanges->add(sourceRanges->start(sourceRanges->length() - 1, ASSERT_NO_EXCEPTION), highestEndTime);
355f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
356f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // 5.3 Let new intersection ranges equal the the intersection between the intersection ranges and the source ranges.
357f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // 5.4 Replace the ranges in intersection ranges with the new intersection ranges.
358f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        intersectionRanges->intersectWith(sourceRanges);
359f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    }
360f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
361f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return intersectionRanges.release();
362f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
363f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
364f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void MediaSource::setDuration(double duration, ExceptionState& exceptionState)
365f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
366f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 2.1 http://www.w3.org/TR/media-source/#widl-MediaSource-duration
367f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 1. If the value being set is negative or NaN then throw an InvalidAccessError
368f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // exception and abort these steps.
369f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (std::isnan(duration)) {
370f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::notAFiniteNumber(duration, "duration"));
371f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return;
372f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    }
373f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (duration < 0.0) {
374f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::indexExceedsMinimumBound("duration", duration, 0.0));
375f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return;
376f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    }
377f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
378f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 2. If the readyState attribute is not "open" then throw an InvalidStateError
379f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // exception and abort these steps.
380f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 3. If the updating attribute equals true on any SourceBuffer in sourceBuffers,
381f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // then throw an InvalidStateError exception and abort these steps.
382f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (throwExceptionIfClosedOrUpdating(isOpen(), isUpdating(), exceptionState))
383f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return;
384f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
385f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 4. Run the duration change algorithm with new duration set to the value being
386f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // assigned to this attribute.
3875d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    durationChangeAlgorithm(duration);
3885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
3895d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
3905d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)void MediaSource::durationChangeAlgorithm(double newDuration)
3915d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles){
3925d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // Section 2.6.4 Duration change
3935d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#duration-change-algorithm
3945d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // 1. If the current value of duration is equal to new duration, then return.
3955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (newDuration == duration())
3965d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return;
3975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
3985d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // 2. Set old duration to the current value of duration.
3995d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    double oldDuration = duration();
4005d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
4015d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    bool requestSeek = m_attachedElement->currentTime() > newDuration;
4025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
4035d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // 3. Update duration to new duration.
4045d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    m_webMediaSource->setDuration(newDuration);
4055d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
4065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // 4. If the new duration is less than old duration, then call remove(new duration, old duration) on all all objects in sourceBuffers.
4075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (newDuration < oldDuration) {
4085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        for (size_t i = 0; i < m_sourceBuffers->length(); ++i)
4095d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            m_sourceBuffers->item(i)->remove(newDuration, oldDuration, ASSERT_NO_EXCEPTION);
4105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
4115d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
4125d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // 5. If a user agent is unable to partially render audio frames or text cues that start before and end after the duration, then run the following steps:
4135d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // NOTE: Currently we assume that the media engine is able to render partial frames/cues. If a media
4145d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // engine gets added that doesn't support this, then we'll need to add logic to handle the substeps.
4155d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
4165d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // 6. Update the media controller duration to new duration and run the HTMLMediaElement duration change algorithm.
4175d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    m_attachedElement->durationChanged(newDuration, requestSeek);
418f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
419f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
420f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void MediaSource::setReadyState(const AtomicString& state)
421f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
422f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(state == openKeyword() || state == closedKeyword() || state == endedKeyword());
423f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
424f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    AtomicString oldState = readyState();
425f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    WTF_LOG(Media, "MediaSource::setReadyState() %p : %s -> %s", this, oldState.ascii().data(), state.ascii().data());
426f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
427f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (state == closedKeyword()) {
428f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        m_webMediaSource.clear();
429197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        m_attachedElement.clear();
430f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    }
431f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
432f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (oldState == state)
433f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return;
434f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
435f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    m_readyState = state;
436f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
437f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    onReadyStateChange(oldState, state);
438f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
439f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
440f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void MediaSource::endOfStream(const AtomicString& error, ExceptionState& exceptionState)
441f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
442f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, network, ("network", AtomicString::ConstructFromLiteral));
443f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, decode, ("decode", AtomicString::ConstructFromLiteral));
444f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
445f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (error == network) {
446e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        endOfStreamInternal(WebMediaSource::EndOfStreamStatusNetworkError, exceptionState);
447f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    } else if (error == decode) {
448e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        endOfStreamInternal(WebMediaSource::EndOfStreamStatusDecodeError, exceptionState);
449f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    } else {
450f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        ASSERT_NOT_REACHED(); // IDL enforcement should prevent this case.
451f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    }
452f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
453f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
454f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void MediaSource::endOfStream(ExceptionState& exceptionState)
455f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
456e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    endOfStreamInternal(WebMediaSource::EndOfStreamStatusNoError, exceptionState);
457f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
458f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
459e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void MediaSource::endOfStreamInternal(const WebMediaSource::EndOfStreamStatus eosStatus, ExceptionState& exceptionState)
460f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
461f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 2.2 http://www.w3.org/TR/media-source/#widl-MediaSource-endOfStream-void-EndOfStreamError-error
462f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 1. If the readyState attribute is not in the "open" state then throw an
463f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // InvalidStateError exception and abort these steps.
464f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 2. If the updating attribute equals true on any SourceBuffer in sourceBuffers, then throw an
465f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // InvalidStateError exception and abort these steps.
466f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (throwExceptionIfClosedOrUpdating(isOpen(), isUpdating(), exceptionState))
467f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return;
468f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
469f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // 3. Run the end of stream algorithm with the error parameter set to error.
470f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    //   1. Change the readyState attribute value to "ended".
471f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    //   2. Queue a task to fire a simple event named sourceended at the MediaSource.
472f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    setReadyState(endedKeyword());
473f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
474f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    //   3. Do various steps based on |eosStatus|.
475f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    m_webMediaSource->markEndOfStream(eosStatus);
476f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
477f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
478f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)bool MediaSource::isOpen() const
479f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
480f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return readyState() == openKeyword();
481f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
482f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
4837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid MediaSource::setSourceBufferActive(SourceBuffer* sourceBuffer)
4847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
4857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(!m_activeSourceBuffers->contains(sourceBuffer));
4867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
4877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-MediaSource-activeSourceBuffers
4887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // SourceBuffer objects in SourceBuffer.activeSourceBuffers must appear in
4897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // the same order as they appear in SourceBuffer.sourceBuffers.
4907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // SourceBuffer transitions to active are not guaranteed to occur in the
4917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // same order as buffers in |m_sourceBuffers|, so this method needs to
4927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // insert |sourceBuffer| into |m_activeSourceBuffers|.
4937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    size_t indexInSourceBuffers = m_sourceBuffers->find(sourceBuffer);
4947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(indexInSourceBuffers != kNotFound);
4957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
4967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    size_t insertPosition = 0;
4977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    while (insertPosition < m_activeSourceBuffers->length()
4987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        && m_sourceBuffers->find(m_activeSourceBuffers->item(insertPosition)) < indexInSourceBuffers) {
4997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        ++insertPosition;
5007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
5017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
5027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_activeSourceBuffers->insert(insertPosition, sourceBuffer);
5037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
5047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
505f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)bool MediaSource::isClosed() const
506f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
507f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return readyState() == closedKeyword();
508f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
509f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
510f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void MediaSource::close()
511f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
512f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    setReadyState(closedKeyword());
513f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
514f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
515f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)bool MediaSource::attachToElement(HTMLMediaElement* element)
516f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
517f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (m_attachedElement)
518f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return false;
519f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
520f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(isClosed());
521f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
522f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSource::attachToElement", this);
523f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    m_attachedElement = element;
524f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return true;
525f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
526f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
527f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void MediaSource::openIfInEndedState()
528f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
529f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (m_readyState != endedKeyword())
530f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return;
531f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
532f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    setReadyState(openKeyword());
533f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    m_webMediaSource->unmarkEndOfStream();
534f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
535f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
536f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)bool MediaSource::hasPendingActivity() const
537f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
538f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return m_attachedElement || m_webMediaSource
539f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        || m_asyncEventQueue->hasPendingEvents()
540197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        || m_isAddedToRegistry;
541f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
542f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
543f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void MediaSource::stop()
544f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
545f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    m_asyncEventQueue->close();
546f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (!isClosed())
547f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        setReadyState(closedKeyword());
548f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    m_webMediaSource.clear();
549f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
550f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
551f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)PassOwnPtr<WebSourceBuffer> MediaSource::createWebSourceBuffer(const String& type, const Vector<String>& codecs, ExceptionState& exceptionState)
552f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
553f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    WebSourceBuffer* webSourceBuffer = 0;
554f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
5555d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    switch (m_webMediaSource->addSourceBuffer(type, codecs, &webSourceBuffer)) {
556f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    case WebMediaSource::AddStatusOk:
557f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return adoptPtr(webSourceBuffer);
558f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    case WebMediaSource::AddStatusNotSupported:
559f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        ASSERT(!webSourceBuffer);
560f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type
561f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // Step 2: If type contains a MIME type ... that is not supported with the types
562f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // specified for the other SourceBuffer objects in sourceBuffers, then throw
563f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // a NotSupportedError exception and abort these steps.
564f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        exceptionState.throwDOMException(NotSupportedError, "The type provided ('" + type + "') is not supported.");
565f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return nullptr;
566f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    case WebMediaSource::AddStatusReachedIdLimit:
567f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        ASSERT(!webSourceBuffer);
568f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type
569f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // Step 3: If the user agent can't handle any more SourceBuffer objects then throw
570f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // a QuotaExceededError exception and abort these steps.
571f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        exceptionState.throwDOMException(QuotaExceededError, "This MediaSource has reached the limit of SourceBuffer objects it can handle. No additional SourceBuffer objects may be added.");
572f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return nullptr;
573f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    }
574f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
575f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT_NOT_REACHED();
576f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return nullptr;
577f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
578f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
579f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void MediaSource::scheduleEvent(const AtomicString& eventName)
580f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
581f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(m_asyncEventQueue);
582f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
583f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    RefPtrWillBeRawPtr<Event> event = Event::create(eventName);
584f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    event->setTarget(this);
585f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
586f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    m_asyncEventQueue->enqueueEvent(event.release());
587f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
588f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
589f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)URLRegistry& MediaSource::registry() const
590f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
591f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return MediaSourceRegistry::registry();
59209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
59309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
594c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
595