Home | History | Annotate | Download | only in mediasource
      1 /*
      2  * Copyright (C) 2012 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "modules/mediasource/WebKitMediaSource.h"
     33 
     34 #include "bindings/v8/ExceptionState.h"
     35 #include "bindings/v8/ExceptionStatePlaceholder.h"
     36 #include "core/dom/ExceptionCode.h"
     37 #include "core/html/TimeRanges.h"
     38 #include "modules/mediasource/MediaSourceRegistry.h"
     39 #include "platform/ContentType.h"
     40 #include "platform/MIMETypeRegistry.h"
     41 #include "public/platform/WebSourceBuffer.h"
     42 #include "wtf/Uint8Array.h"
     43 
     44 using blink::WebSourceBuffer;
     45 
     46 namespace WebCore {
     47 
     48 PassRefPtr<WebKitMediaSource> WebKitMediaSource::create(ExecutionContext* context)
     49 {
     50     RefPtr<WebKitMediaSource> mediaSource(adoptRef(new WebKitMediaSource(context)));
     51     mediaSource->suspendIfNeeded();
     52     return mediaSource.release();
     53 }
     54 
     55 WebKitMediaSource::WebKitMediaSource(ExecutionContext* context)
     56     : MediaSourceBase(context)
     57 {
     58     ScriptWrappable::init(this);
     59     m_sourceBuffers = WebKitSourceBufferList::create(executionContext(), asyncEventQueue());
     60     m_activeSourceBuffers = WebKitSourceBufferList::create(executionContext(), asyncEventQueue());
     61 }
     62 
     63 WebKitSourceBufferList* WebKitMediaSource::sourceBuffers()
     64 {
     65     return m_sourceBuffers.get();
     66 }
     67 
     68 WebKitSourceBufferList* WebKitMediaSource::activeSourceBuffers()
     69 {
     70     // FIXME(91649): support track selection
     71     return m_activeSourceBuffers.get();
     72 }
     73 
     74 WebKitSourceBuffer* WebKitMediaSource::addSourceBuffer(const String& type, ExceptionState& exceptionState)
     75 {
     76     // 3.1 http://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#dom-addsourcebuffer
     77     // 1. If type is null or an empty then throw an InvalidAccessError exception and
     78     // abort these steps.
     79     if (type.isNull() || type.isEmpty()) {
     80         exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
     81         return 0;
     82     }
     83 
     84     // 2. If type contains a MIME type that is not supported ..., then throw a
     85     // NotSupportedError exception and abort these steps.
     86     if (!isTypeSupported(type)) {
     87         exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError);
     88         return 0;
     89     }
     90 
     91     // 4. If the readyState attribute is not in the "open" state then throw an
     92     // InvalidStateError exception and abort these steps.
     93     if (!isOpen()) {
     94         exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
     95         return 0;
     96     }
     97 
     98     // 5. Create a new SourceBuffer object and associated resources.
     99     ContentType contentType(type);
    100     Vector<String> codecs = contentType.codecs();
    101     OwnPtr<WebSourceBuffer> webSourceBuffer = createWebSourceBuffer(contentType.type(), codecs, exceptionState);
    102     if (!webSourceBuffer)
    103         return 0;
    104 
    105     RefPtr<WebKitSourceBuffer> buffer = WebKitSourceBuffer::create(webSourceBuffer.release(), this);
    106     // 6. Add the new object to sourceBuffers and fire a addsourcebuffer on that object.
    107     m_sourceBuffers->add(buffer);
    108     m_activeSourceBuffers->add(buffer);
    109     // 7. Return the new object to the caller.
    110     return buffer.get();
    111 }
    112 
    113 void WebKitMediaSource::removeSourceBuffer(WebKitSourceBuffer* buffer, ExceptionState& exceptionState)
    114 {
    115     // 3.1 http://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#dom-removesourcebuffer
    116     // 1. If sourceBuffer is null then throw an InvalidAccessError exception and
    117     // abort these steps.
    118     if (!buffer) {
    119         exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
    120         return;
    121     }
    122 
    123     // 2. If sourceBuffers is empty then throw an InvalidStateError exception and
    124     // abort these steps.
    125     if (isClosed() || !m_sourceBuffers->length()) {
    126         exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
    127         return;
    128     }
    129 
    130     // 3. If sourceBuffer specifies an object that is not in sourceBuffers then
    131     // throw a NotFoundError exception and abort these steps.
    132     // 6. Remove sourceBuffer from sourceBuffers and fire a removesourcebuffer event
    133     // on that object.
    134     if (!m_sourceBuffers->remove(buffer)) {
    135         exceptionState.throwUninformativeAndGenericDOMException(NotFoundError);
    136         return;
    137     }
    138 
    139     // 7. Destroy all resources for sourceBuffer.
    140     m_activeSourceBuffers->remove(buffer);
    141 
    142     // 4. Remove track information from audioTracks, videoTracks, and textTracks for all tracks
    143     // associated with sourceBuffer and fire a simple event named change on the modified lists.
    144     // FIXME(91649): support track selection
    145 
    146     // 5. If sourceBuffer is in activeSourceBuffers, then remove it from that list and fire a
    147     // removesourcebuffer event on that object.
    148     // FIXME(91649): support track selection
    149 }
    150 
    151 void WebKitMediaSource::onReadyStateChange(const AtomicString& oldState, const AtomicString& newState)
    152 {
    153     if (isClosed()) {
    154         m_sourceBuffers->clear();
    155         m_activeSourceBuffers->clear();
    156         scheduleEvent(EventTypeNames::webkitsourceclose);
    157         return;
    158     }
    159 
    160     if (oldState == openKeyword() && newState == endedKeyword()) {
    161         scheduleEvent(EventTypeNames::webkitsourceended);
    162         return;
    163     }
    164 
    165     if (isOpen()) {
    166         scheduleEvent(EventTypeNames::webkitsourceopen);
    167         return;
    168     }
    169 }
    170 
    171 Vector<RefPtr<TimeRanges> > WebKitMediaSource::activeRanges() const
    172 {
    173     Vector<RefPtr<TimeRanges> > activeRanges(m_activeSourceBuffers->length());
    174     for (size_t i = 0; i < m_activeSourceBuffers->length(); ++i)
    175         activeRanges[i] = m_activeSourceBuffers->item(i)->buffered(ASSERT_NO_EXCEPTION);
    176 
    177     return activeRanges;
    178 }
    179 
    180 bool WebKitMediaSource::isTypeSupported(const String& type)
    181 {
    182     // Section 2.1 isTypeSupported() method steps.
    183     // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-MediaSource-isTypeSupported-boolean-DOMString-type
    184     // 1. If type is an empty string, then return false.
    185     if (type.isNull() || type.isEmpty())
    186         return false;
    187 
    188     ContentType contentType(type);
    189     String codecs = contentType.parameter("codecs");
    190 
    191     // 2. If type does not contain a valid MIME type string, then return false.
    192     if (contentType.type().isEmpty())
    193         return false;
    194 
    195     // 3. If type contains a media type or media subtype that the MediaSource does not support, then return false.
    196     // 4. If type contains at a codec that the MediaSource does not support, then return false.
    197     // 5. If the MediaSource does not support the specified combination of media type, media subtype, and codecs then return false.
    198     // 6. Return true.
    199     return MIMETypeRegistry::isSupportedMediaSourceMIMEType(contentType.type(), codecs);
    200 }
    201 
    202 const AtomicString& WebKitMediaSource::interfaceName() const
    203 {
    204     return EventTargetNames::WebKitMediaSource;
    205 }
    206 
    207 } // namespace WebCore
    208