OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
13 * distribution. | 13 * distribution. |
14 * * Neither the name of Google Inc. nor the names of its | 14 * * Neither the name of Google Inc. nor the names of its |
15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
17 * | 17 * |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | 30 |
31 #include "config.h" | 31 #include "config.h" |
32 #include "modules/mediasource/WebKitMediaSource.h" | 32 #include "modules/mediasource/MediaSource.h" |
33 | 33 |
| 34 #include "core/dom/GenericEventQueue.h" |
34 #include "core/html/TimeRanges.h" | 35 #include "core/html/TimeRanges.h" |
35 #include "core/platform/ContentType.h" | 36 #include "core/platform/ContentType.h" |
| 37 #include "core/platform/Logging.h" |
36 #include "core/platform/MIMETypeRegistry.h" | 38 #include "core/platform/MIMETypeRegistry.h" |
37 #include "core/platform/graphics/SourceBufferPrivate.h" | 39 #include "core/platform/graphics/SourceBufferPrivate.h" |
38 #include "modules/mediasource/MediaSourceRegistry.h" | 40 #include "modules/mediasource/MediaSourceRegistry.h" |
39 #include "wtf/Uint8Array.h" | 41 #include "wtf/Uint8Array.h" |
40 | 42 |
41 namespace WebCore { | 43 namespace WebCore { |
42 | 44 |
43 PassRefPtr<WebKitMediaSource> WebKitMediaSource::create(ScriptExecutionContext*
context) | 45 PassRefPtr<MediaSource> MediaSource::create(ScriptExecutionContext* context) |
44 { | 46 { |
45 RefPtr<WebKitMediaSource> mediaSource(adoptRef(new WebKitMediaSource(context
))); | 47 RefPtr<MediaSource> mediaSource(adoptRef(new MediaSource(context))); |
46 mediaSource->suspendIfNeeded(); | 48 mediaSource->suspendIfNeeded(); |
47 return mediaSource.release(); | 49 return mediaSource.release(); |
48 } | 50 } |
49 | 51 |
50 WebKitMediaSource::WebKitMediaSource(ScriptExecutionContext* context) | 52 MediaSource::MediaSource(ScriptExecutionContext* context) |
51 : MediaSourceBase(context) | 53 : MediaSourceBase(context) |
52 { | 54 { |
| 55 LOG(Media, "MediaSource::MediaSource %p", this); |
53 ScriptWrappable::init(this); | 56 ScriptWrappable::init(this); |
54 m_sourceBuffers = WebKitSourceBufferList::create(scriptExecutionContext(), a
syncEventQueue()); | 57 m_sourceBuffers = SourceBufferList::create(scriptExecutionContext(), asyncEv
entQueue()); |
55 m_activeSourceBuffers = WebKitSourceBufferList::create(scriptExecutionContex
t(), asyncEventQueue()); | 58 m_activeSourceBuffers = SourceBufferList::create(scriptExecutionContext(), a
syncEventQueue()); |
56 } | 59 } |
57 | 60 |
58 WebKitSourceBufferList* WebKitMediaSource::sourceBuffers() | 61 MediaSource::~MediaSource() |
59 { | 62 { |
60 return m_sourceBuffers.get(); | 63 LOG(Media, "MediaSource::~MediaSource %p", this); |
| 64 ASSERT(isClosed()); |
61 } | 65 } |
62 | 66 |
63 WebKitSourceBufferList* WebKitMediaSource::activeSourceBuffers() | 67 SourceBuffer* MediaSource::addSourceBuffer(const String& type, ExceptionCode& ec
) |
64 { | 68 { |
65 // FIXME(91649): support track selection | 69 LOG(Media, "MediaSource::addSourceBuffer(%s) %p", type.ascii().data(), this)
; |
66 return m_activeSourceBuffers.get(); | |
67 } | |
68 | 70 |
69 WebKitSourceBuffer* WebKitMediaSource::addSourceBuffer(const String& type, Excep
tionCode& ec) | 71 // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media
-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type |
70 { | |
71 // 3.1 http://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-sour
ce.html#dom-addsourcebuffer | |
72 // 1. If type is null or an empty then throw an INVALID_ACCESS_ERR exception
and | 72 // 1. If type is null or an empty then throw an INVALID_ACCESS_ERR exception
and |
73 // abort these steps. | 73 // abort these steps. |
74 if (type.isNull() || type.isEmpty()) { | 74 if (type.isNull() || type.isEmpty()) { |
75 ec = INVALID_ACCESS_ERR; | 75 ec = INVALID_ACCESS_ERR; |
76 return 0; | 76 return 0; |
77 } | 77 } |
78 | 78 |
79 // 2. If type contains a MIME type that is not supported ..., then throw a | 79 // 2. If type contains a MIME type that is not supported ..., then throw a |
80 // NOT_SUPPORTED_ERR exception and abort these steps. | 80 // NOT_SUPPORTED_ERR exception and abort these steps. |
81 if (!isTypeSupported(type)) { | 81 if (!isTypeSupported(type)) { |
82 ec = NOT_SUPPORTED_ERR; | 82 ec = NOT_SUPPORTED_ERR; |
83 return 0; | 83 return 0; |
84 } | 84 } |
85 | 85 |
86 // 4. If the readyState attribute is not in the "open" state then throw an | 86 // 4. If the readyState attribute is not in the "open" state then throw an |
87 // INVALID_STATE_ERR exception and abort these steps. | 87 // INVALID_STATE_ERR exception and abort these steps. |
88 if (!isOpen()) { | 88 if (!isOpen()) { |
89 ec = INVALID_STATE_ERR; | 89 ec = INVALID_STATE_ERR; |
90 return 0; | 90 return 0; |
91 } | 91 } |
92 | 92 |
93 // 5. Create a new SourceBuffer object and associated resources. | 93 // 5. Create a new SourceBuffer object and associated resources. |
94 ContentType contentType(type); | 94 ContentType contentType(type); |
95 Vector<String> codecs = contentType.codecs(); | 95 Vector<String> codecs = contentType.codecs(); |
96 OwnPtr<SourceBufferPrivate> sourceBufferPrivate = createSourceBufferPrivate(
contentType.type(), codecs, ec); | 96 OwnPtr<SourceBufferPrivate> sourceBufferPrivate = createSourceBufferPrivate(
contentType.type(), codecs, ec); |
97 if (!sourceBufferPrivate) | 97 |
| 98 if (!sourceBufferPrivate) { |
| 99 ASSERT(ec == NOT_SUPPORTED_ERR || ec == QUOTA_EXCEEDED_ERR); |
| 100 // 2. If type contains a MIME type that is not supported ..., then throw
a NOT_SUPPORTED_ERR exception and abort these steps. |
| 101 // 3. If the user agent can't handle any more SourceBuffer objects then
throw a QUOTA_EXCEEDED_ERR exception and abort these steps |
98 return 0; | 102 return 0; |
| 103 } |
99 | 104 |
100 RefPtr<WebKitSourceBuffer> buffer = WebKitSourceBuffer::create(sourceBufferP
rivate.release(), this); | 105 RefPtr<SourceBuffer> buffer = SourceBuffer::create(sourceBufferPrivate.relea
se(), this, asyncEventQueue()); |
101 // 6. Add the new object to sourceBuffers and fire a addsourcebuffer on that
object. | 106 // 6. Add the new object to sourceBuffers and fire a addsourcebuffer on that
object. |
102 m_sourceBuffers->add(buffer); | 107 m_sourceBuffers->add(buffer); |
103 m_activeSourceBuffers->add(buffer); | 108 m_activeSourceBuffers->add(buffer); |
104 // 7. Return the new object to the caller. | 109 // 7. Return the new object to the caller. |
105 return buffer.get(); | 110 return buffer.get(); |
106 } | 111 } |
107 | 112 |
108 void WebKitMediaSource::removeSourceBuffer(WebKitSourceBuffer* buffer, Exception
Code& ec) | 113 void MediaSource::removeSourceBuffer(SourceBuffer* buffer, ExceptionCode& ec) |
109 { | 114 { |
110 // 3.1 http://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-sour
ce.html#dom-removesourcebuffer | 115 LOG(Media, "MediaSource::removeSourceBuffer() %p", this); |
| 116 RefPtr<SourceBuffer> protect(buffer); |
| 117 |
| 118 // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media
-source.html#widl-MediaSource-removeSourceBuffer-void-SourceBuffer-sourceBuffer |
111 // 1. If sourceBuffer is null then throw an INVALID_ACCESS_ERR exception and | 119 // 1. If sourceBuffer is null then throw an INVALID_ACCESS_ERR exception and |
112 // abort these steps. | 120 // abort these steps. |
113 if (!buffer) { | 121 if (!buffer) { |
114 ec = INVALID_ACCESS_ERR; | 122 ec = INVALID_ACCESS_ERR; |
115 return; | 123 return; |
116 } | 124 } |
117 | 125 |
118 // 2. If sourceBuffers is empty then throw an INVALID_STATE_ERR exception an
d | 126 // 2. If sourceBuffer specifies an object that is not in sourceBuffers then |
119 // abort these steps. | |
120 if (isClosed() || !m_sourceBuffers->length()) { | |
121 ec = INVALID_STATE_ERR; | |
122 return; | |
123 } | |
124 | |
125 // 3. If sourceBuffer specifies an object that is not in sourceBuffers then | |
126 // throw a NOT_FOUND_ERR exception and abort these steps. | 127 // throw a NOT_FOUND_ERR exception and abort these steps. |
127 // 6. Remove sourceBuffer from sourceBuffers and fire a removesourcebuffer e
vent | 128 if (!m_sourceBuffers->length() || !m_sourceBuffers->contains(buffer)) { |
128 // on that object. | |
129 if (!m_sourceBuffers->remove(buffer)) { | |
130 ec = NOT_FOUND_ERR; | 129 ec = NOT_FOUND_ERR; |
131 return; | 130 return; |
132 } | 131 } |
133 | 132 |
134 // 7. Destroy all resources for sourceBuffer. | 133 // 3. If the sourceBuffer.updating attribute equals true, then run the follo
wing steps: ... |
| 134 buffer->abortIfUpdating(); |
| 135 |
| 136 // Steps 4-9 are related to updating audioTracks, videoTracks, and textTrack
s which aren't implmented yet. |
| 137 // FIXME(91649): support track selection |
| 138 |
| 139 // 10. If sourceBuffer is in activeSourceBuffers, then remove sourceBuffer f
rom activeSourceBuffers ... |
135 m_activeSourceBuffers->remove(buffer); | 140 m_activeSourceBuffers->remove(buffer); |
136 | 141 |
137 // 4. Remove track information from audioTracks, videoTracks, and textTracks
for all tracks | 142 // 11. Remove sourceBuffer from sourceBuffers and fire a removesourcebuffer
event |
138 // associated with sourceBuffer and fire a simple event named change on the
modified lists. | 143 // on that object. |
139 // FIXME(91649): support track selection | 144 m_sourceBuffers->remove(buffer); |
140 | 145 |
141 // 5. If sourceBuffer is in activeSourceBuffers, then remove it from that li
st and fire a | 146 // 12. Destroy all resources for sourceBuffer. |
142 // removesourcebuffer event on that object. | 147 buffer->removedFromMediaSource(); |
143 // FIXME(91649): support track selection | |
144 } | 148 } |
145 | 149 |
146 void WebKitMediaSource::setReadyState(const AtomicString& state) | 150 void MediaSource::setReadyState(const AtomicString& state) |
147 { | 151 { |
148 ASSERT(state == openKeyword() || state == closedKeyword() || state == endedK
eyword()); | 152 ASSERT(state == openKeyword() || state == closedKeyword() || state == endedK
eyword()); |
149 String oldState = readyState(); | 153 AtomicString oldState = readyState(); |
150 if (oldState == state) | 154 if (oldState == state) |
151 return; | 155 return; |
152 | 156 |
| 157 LOG(Media, "MediaSource::setReadyState() %p : %s -> %s", this, oldState.stri
ng().ascii().data(), state.string().ascii().data()); |
| 158 |
153 MediaSourceBase::setReadyState(state); | 159 MediaSourceBase::setReadyState(state); |
154 | 160 |
155 if (isClosed()) { | 161 if (isOpen()) { |
156 m_sourceBuffers->clear(); | 162 scheduleEvent(eventNames().sourceopenEvent); |
157 m_activeSourceBuffers->clear(); | |
158 scheduleEvent(eventNames().webkitsourcecloseEvent); | |
159 return; | 163 return; |
160 } | 164 } |
161 | 165 |
162 if (oldState == openKeyword() && state == endedKeyword()) { | 166 if (oldState == openKeyword() && state == endedKeyword()) { |
163 scheduleEvent(eventNames().webkitsourceendedEvent); | 167 scheduleEvent(eventNames().sourceendedEvent); |
164 return; | 168 return; |
165 } | 169 } |
166 | 170 |
167 if (isOpen()) { | 171 ASSERT(isClosed()); |
168 scheduleEvent(eventNames().webkitsourceopenEvent); | 172 |
169 return; | 173 m_activeSourceBuffers->clear(); |
170 } | 174 |
| 175 // Clear SourceBuffer references to this object. |
| 176 for (unsigned long i = 0; i < m_sourceBuffers->length(); ++i) |
| 177 m_sourceBuffers->item(i)->removedFromMediaSource(); |
| 178 m_sourceBuffers->clear(); |
| 179 |
| 180 scheduleEvent(eventNames().sourcecloseEvent); |
171 } | 181 } |
172 | 182 |
173 bool WebKitMediaSource::isTypeSupported(const String& type) | 183 bool MediaSource::isTypeSupported(const String& type) |
174 { | 184 { |
175 // Section 2.1 isTypeSupported() method steps. | 185 LOG(Media, "MediaSource::isTypeSupported(%s)", type.ascii().data()); |
| 186 |
| 187 // Section 2.2 isTypeSupported() method steps. |
176 // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.
html#widl-MediaSource-isTypeSupported-boolean-DOMString-type | 188 // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.
html#widl-MediaSource-isTypeSupported-boolean-DOMString-type |
177 // 1. If type is an empty string, then return false. | 189 // 1. If type is an empty string, then return false. |
178 if (type.isNull() || type.isEmpty()) | 190 if (type.isNull() || type.isEmpty()) |
179 return false; | 191 return false; |
180 | 192 |
181 ContentType contentType(type); | 193 ContentType contentType(type); |
182 String codecs = contentType.parameter("codecs"); | 194 String codecs = contentType.parameter("codecs"); |
183 | 195 |
184 // 2. If type does not contain a valid MIME type string, then return false. | 196 // 2. If type does not contain a valid MIME type string, then return false. |
185 if (contentType.type().isEmpty() || codecs.isEmpty()) | 197 if (contentType.type().isEmpty() || codecs.isEmpty()) |
186 return false; | 198 return false; |
187 | 199 |
188 // 3. If type contains a media type or media subtype that the MediaSource do
es not support, then return false. | 200 // 3. If type contains a media type or media subtype that the MediaSource do
es not support, then return false. |
189 // 4. If type contains at a codec that the MediaSource does not support, the
n return false. | 201 // 4. If type contains at a codec that the MediaSource does not support, the
n return false. |
190 // 5. If the MediaSource does not support the specified combination of media
type, media subtype, and codecs then return false. | 202 // 5. If the MediaSource does not support the specified combination of media
type, media subtype, and codecs then return false. |
191 // 6. Return true. | 203 // 6. Return true. |
192 return MIMETypeRegistry::isSupportedMediaSourceMIMEType(contentType.type(),
codecs); | 204 return MIMETypeRegistry::isSupportedMediaSourceMIMEType(contentType.type(),
codecs); |
193 } | 205 } |
194 | 206 |
195 const AtomicString& WebKitMediaSource::interfaceName() const | 207 const AtomicString& MediaSource::interfaceName() const |
196 { | 208 { |
197 return eventNames().interfaceForWebKitMediaSource; | 209 return eventNames().interfaceForMediaSource; |
198 } | 210 } |
199 | 211 |
200 void WebKitMediaSource::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) co
nst | 212 void MediaSource::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const |
201 { | 213 { |
202 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); | 214 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); |
203 ScriptWrappable::reportMemoryUsage(memoryObjectInfo); | 215 ScriptWrappable::reportMemoryUsage(memoryObjectInfo); |
204 MediaSourceBase::reportMemoryUsage(memoryObjectInfo); | 216 MediaSourceBase::reportMemoryUsage(memoryObjectInfo); |
205 info.addMember(m_sourceBuffers, "sourceBuffers"); | 217 info.addMember(m_sourceBuffers, "sourceBuffers"); |
206 info.addMember(m_activeSourceBuffers, "activeSourceBuffers"); | 218 info.addMember(m_activeSourceBuffers, "activeSourceBuffers"); |
207 } | 219 } |
208 | 220 |
209 } // namespace WebCore | 221 } // namespace WebCore |
OLD | NEW |