15267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)/*
25267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved.
35267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) *
45267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * modification, are permitted provided that the following conditions are
65267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * met:
75267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) *
85267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * in the documentation and/or other materials provided with the
135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * distribution.
145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * contributors may be used to endorse or promote products derived from
165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * this software without specific prior written permission.
175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) *
185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) */
305267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
315267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "config.h"
325267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "modules/mediasource/MediaSourceBase.h"
335267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "bindings/v8/ExceptionState.h"
357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "bindings/v8/ExceptionStatePlaceholder.h"
365267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "core/dom/Event.h"
375267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "core/dom/ExceptionCode.h"
385267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "core/dom/GenericEventQueue.h"
39e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "core/platform/Logging.h"
405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "core/platform/graphics/SourceBufferPrivate.h"
415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "modules/mediasource/MediaSourceRegistry.h"
425267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "wtf/text/WTFString.h"
435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)namespace WebCore {
455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
465267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)MediaSourceBase::MediaSourceBase(ScriptExecutionContext* context)
475267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    : ActiveDOMObject(context)
485267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    , m_readyState(closedKeyword())
495267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    , m_asyncEventQueue(GenericEventQueue::create(this))
50e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    , m_attachedElement(0)
515267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
525267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
535267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
545267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)MediaSourceBase::~MediaSourceBase()
555267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
565267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
575267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
585267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)const AtomicString& MediaSourceBase::openKeyword()
595267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, open, ("open", AtomicString::ConstructFromLiteral));
615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return open;
625267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
645267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)const AtomicString& MediaSourceBase::closedKeyword()
655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
665267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, closed, ("closed", AtomicString::ConstructFromLiteral));
675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return closed;
685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
705267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)const AtomicString& MediaSourceBase::endedKeyword()
715267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
725267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, ended, ("ended", AtomicString::ConstructFromLiteral));
735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return ended;
745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
765267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void MediaSourceBase::setPrivateAndOpen(PassOwnPtr<MediaSourcePrivate> mediaSourcePrivate)
775267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
785267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    ASSERT(mediaSourcePrivate);
795267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    ASSERT(!m_private);
80e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    ASSERT(m_attachedElement);
815267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    m_private = mediaSourcePrivate;
825267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    setReadyState(openKeyword());
835267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
845267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
855267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void MediaSourceBase::addedToRegistry()
865267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
875267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    setPendingActivity(this);
885267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
895267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
905267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void MediaSourceBase::removedFromRegistry()
915267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    unsetPendingActivity(this);
935267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
945267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
955267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)double MediaSourceBase::duration() const
965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
975267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return isClosed() ? std::numeric_limits<float>::quiet_NaN() : m_private->duration();
985267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
995267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
100e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben MurdochPassRefPtr<TimeRanges> MediaSourceBase::buffered() const
101e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch{
102e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // Implements MediaSource algorithm for HTMLMediaElement.buffered.
103e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#htmlmediaelement-extensions
104e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    Vector<RefPtr<TimeRanges> > ranges = activeRanges();
105e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
106e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // 1. If activeSourceBuffers.length equals 0 then return an empty TimeRanges object and abort these steps.
107e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (ranges.isEmpty())
108e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return TimeRanges::create();
109e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
110e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // 2. Let active ranges be the ranges returned by buffered for each SourceBuffer object in activeSourceBuffers.
111e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // 3. Let highest end time be the largest range end time in the active ranges.
112e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    double highestEndTime = -1;
113e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    for (size_t i = 0; i < ranges.size(); ++i) {
114e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        unsigned length = ranges[i]->length();
115e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (length)
1161fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch            highestEndTime = std::max(highestEndTime, ranges[i]->end(length - 1, ASSERT_NO_EXCEPTION));
117e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
118e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
119e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // Return an empty range if all ranges are empty.
120e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (highestEndTime < 0)
121e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return TimeRanges::create();
122e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
123e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // 4. Let intersection ranges equal a TimeRange object containing a single range from 0 to highest end time.
124e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    RefPtr<TimeRanges> intersectionRanges = TimeRanges::create(0, highestEndTime);
125e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
126e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // 5. For each SourceBuffer object in activeSourceBuffers run the following steps:
127e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    bool ended = readyState() == endedKeyword();
128e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    for (size_t i = 0; i < ranges.size(); ++i) {
129e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // 5.1 Let source ranges equal the ranges returned by the buffered attribute on the current SourceBuffer.
130e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        TimeRanges* sourceRanges = ranges[i].get();
131e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
132e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // 5.2 If readyState is "ended", then set the end time on the last range in source ranges to highest end time.
133e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (ended && sourceRanges->length())
1341fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch            sourceRanges->add(sourceRanges->start(sourceRanges->length() - 1, ASSERT_NO_EXCEPTION), highestEndTime);
135e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
136e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // 5.3 Let new intersection ranges equal the the intersection between the intersection ranges and the source ranges.
137e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // 5.4 Replace the ranges in intersection ranges with the new intersection ranges.
138e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        intersectionRanges->intersectWith(sourceRanges);
139e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
140e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
141e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return intersectionRanges.release();
142e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
143e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochvoid MediaSourceBase::setDuration(double duration, ExceptionState& es)
1455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
1465267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (duration < 0.0 || std::isnan(duration)) {
1477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        es.throwDOMException(InvalidAccessError);
1485267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return;
1495267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
1505267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (!isOpen()) {
1517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        es.throwDOMException(InvalidStateError);
1525267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return;
1535267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
154e6d4491e48613634a83c1957c72759da80987961Ben Murdoch
155e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    // Synchronously process duration change algorithm to enforce any required
156e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    // seek is started prior to returning.
157e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    m_attachedElement->durationChanged(duration);
1585267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    m_private->setDuration(duration);
1595267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
1605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
162e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochvoid MediaSourceBase::setReadyState(const AtomicString& state)
1635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
164e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    ASSERT(state == openKeyword() || state == closedKeyword() || state == endedKeyword());
165e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
166e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    AtomicString oldState = readyState();
167e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    LOG(Media, "MediaSourceBase::setReadyState() %p : %s -> %s", this, oldState.string().ascii().data(), state.string().ascii().data());
1685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
169e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (state == closedKeyword()) {
1705267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        m_private.clear();
171e6d4491e48613634a83c1957c72759da80987961Ben Murdoch        m_attachedElement = 0;
172e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
173e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
174e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (oldState == state)
175e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return;
176e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
177e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    m_readyState = state;
178e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
179e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    onReadyStateChange(oldState, state);
1805267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
1815267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochvoid MediaSourceBase::endOfStream(const AtomicString& error, ExceptionState& es)
1835267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
1845267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, network, ("network", AtomicString::ConstructFromLiteral));
1855267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, decode, ("decode", AtomicString::ConstructFromLiteral));
1865267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1875267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    // 3.1 http://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#dom-endofstream
1885267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    // 1. If the readyState attribute is not in the "open" state then throw an
189e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // InvalidStateError exception and abort these steps.
1905267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (!isOpen()) {
1917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        es.throwDOMException(InvalidStateError);
1925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return;
1935267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
1945267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1955267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    MediaSourcePrivate::EndOfStreamStatus eosStatus = MediaSourcePrivate::EosNoError;
1965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1975267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (error.isNull() || error.isEmpty()) {
1985267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        eosStatus = MediaSourcePrivate::EosNoError;
1995267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    } else if (error == network) {
2005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        eosStatus = MediaSourcePrivate::EosNetworkError;
2015267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    } else if (error == decode) {
2025267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        eosStatus = MediaSourcePrivate::EosDecodeError;
2035267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    } else {
2047757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        es.throwDOMException(InvalidAccessError);
2055267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return;
2065267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
2075267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2085267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    // 2. Change the readyState attribute value to "ended".
2095267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    setReadyState(endedKeyword());
210e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    m_private->markEndOfStream(eosStatus);
2115267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
2125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)bool MediaSourceBase::isOpen() const
2145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
2155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return readyState() == openKeyword();
2165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
2175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)bool MediaSourceBase::isClosed() const
2195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
2205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return readyState() == closedKeyword();
2215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
2225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void MediaSourceBase::close()
2245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
2255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    setReadyState(closedKeyword());
2265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
2275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
228e6d4491e48613634a83c1957c72759da80987961Ben Murdochbool MediaSourceBase::attachToElement(HTMLMediaElement* element)
229e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch{
230e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    if (m_attachedElement)
231e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return false;
232e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
233e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    ASSERT(isClosed());
234e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
235e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    m_attachedElement = element;
236e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return true;
237e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
238e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
2395267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void MediaSourceBase::openIfInEndedState()
2405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
2415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (m_readyState != endedKeyword())
2425267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return;
2435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    setReadyState(openKeyword());
245e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    m_private->unmarkEndOfStream();
2465267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
2475267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2485267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)bool MediaSourceBase::hasPendingActivity() const
2495267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
2505267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return m_private || m_asyncEventQueue->hasPendingEvents()
2515267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        || ActiveDOMObject::hasPendingActivity();
2525267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
2535267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2545267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void MediaSourceBase::stop()
2555267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
256521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    m_asyncEventQueue->close();
257521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    if (!isClosed())
258521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        setReadyState(closedKeyword());
2595267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    m_private.clear();
2605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
2615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochPassOwnPtr<SourceBufferPrivate> MediaSourceBase::createSourceBufferPrivate(const String& type, const MediaSourcePrivate::CodecsArray& codecs, ExceptionState& es)
2635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
2645267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    OwnPtr<SourceBufferPrivate> sourceBufferPrivate;
2655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    switch (m_private->addSourceBuffer(type, codecs, &sourceBufferPrivate)) {
2665267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    case MediaSourcePrivate::Ok: {
2675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return sourceBufferPrivate.release();
2685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
2695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    case MediaSourcePrivate::NotSupported:
2705267f701546148b83dfbe1d151cb184385bb5c22Torne (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
2715267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        // Step 2: If type contains a MIME type ... that is not supported with the types
2725267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        // specified for the other SourceBuffer objects in sourceBuffers, then throw
273e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // a NotSupportedError exception and abort these steps.
2747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        es.throwDOMException(NotSupportedError);
2755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return nullptr;
2765267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    case MediaSourcePrivate::ReachedIdLimit:
2775267f701546148b83dfbe1d151cb184385bb5c22Torne (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
2785267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        // Step 3: If the user agent can't handle any more SourceBuffer objects then throw
279e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // a QuotaExceededError exception and abort these steps.
2807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        es.throwDOMException(QuotaExceededError);
2815267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return nullptr;
2825267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
2835267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2845267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    ASSERT_NOT_REACHED();
2855267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return nullptr;
2865267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
2875267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2885267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void MediaSourceBase::scheduleEvent(const AtomicString& eventName)
2895267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
2905267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    ASSERT(m_asyncEventQueue);
2915267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    RefPtr<Event> event = Event::create(eventName, false, false);
2935267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    event->setTarget(this);
2945267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2955267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    m_asyncEventQueue->enqueueEvent(event.release());
2965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
2975267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2985267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)ScriptExecutionContext* MediaSourceBase::scriptExecutionContext() const
2995267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
3005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return ActiveDOMObject::scriptExecutionContext();
3015267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
3025267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
3035267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)EventTargetData* MediaSourceBase::eventTargetData()
3045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
3055267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return &m_eventTargetData;
3065267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
3075267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
3085267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)EventTargetData* MediaSourceBase::ensureEventTargetData()
3095267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
3105267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return &m_eventTargetData;
3115267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
3125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
3135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)URLRegistry& MediaSourceBase::registry() const
3145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
3155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return MediaSourceRegistry::registry();
3165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
3175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
3185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
319