OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights
reserved. | 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple 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 | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 #include "core/frame/UseCounter.h" | 45 #include "core/frame/UseCounter.h" |
46 #include "core/frame/csp/ContentSecurityPolicy.h" | 46 #include "core/frame/csp/ContentSecurityPolicy.h" |
47 #include "core/html/HTMLMediaSource.h" | 47 #include "core/html/HTMLMediaSource.h" |
48 #include "core/html/HTMLSourceElement.h" | 48 #include "core/html/HTMLSourceElement.h" |
49 #include "core/html/HTMLTrackElement.h" | 49 #include "core/html/HTMLTrackElement.h" |
50 #include "core/html/MediaController.h" | 50 #include "core/html/MediaController.h" |
51 #include "core/html/MediaError.h" | 51 #include "core/html/MediaError.h" |
52 #include "core/html/MediaFragmentURIParser.h" | 52 #include "core/html/MediaFragmentURIParser.h" |
53 #include "core/html/TimeRanges.h" | 53 #include "core/html/TimeRanges.h" |
54 #include "core/html/shadow/MediaControls.h" | 54 #include "core/html/shadow/MediaControls.h" |
| 55 #include "core/html/track/AudioTrack.h" |
| 56 #include "core/html/track/AudioTrackList.h" |
55 #include "core/html/track/InbandTextTrack.h" | 57 #include "core/html/track/InbandTextTrack.h" |
56 #include "core/html/track/TextTrackCueList.h" | 58 #include "core/html/track/TextTrackCueList.h" |
57 #include "core/html/track/TextTrackList.h" | 59 #include "core/html/track/TextTrackList.h" |
| 60 #include "core/html/track/VideoTrack.h" |
| 61 #include "core/html/track/VideoTrackList.h" |
58 #include "core/loader/FrameLoader.h" | 62 #include "core/loader/FrameLoader.h" |
59 #include "core/rendering/RenderVideo.h" | 63 #include "core/rendering/RenderVideo.h" |
60 #include "core/rendering/RenderView.h" | 64 #include "core/rendering/RenderView.h" |
61 #include "core/rendering/compositing/RenderLayerCompositor.h" | 65 #include "core/rendering/compositing/RenderLayerCompositor.h" |
62 #include "platform/ContentType.h" | 66 #include "platform/ContentType.h" |
63 #include "platform/Language.h" | 67 #include "platform/Language.h" |
64 #include "platform/Logging.h" | 68 #include "platform/Logging.h" |
65 #include "platform/MIMETypeFromURL.h" | 69 #include "platform/MIMETypeFromURL.h" |
66 #include "platform/MIMETypeRegistry.h" | 70 #include "platform/MIMETypeRegistry.h" |
67 #include "platform/NotImplemented.h" | 71 #include "platform/NotImplemented.h" |
(...skipping 10 matching lines...) Expand all Loading... |
78 #include "wtf/text/CString.h" | 82 #include "wtf/text/CString.h" |
79 | 83 |
80 #if ENABLE(WEB_AUDIO) | 84 #if ENABLE(WEB_AUDIO) |
81 #include "platform/audio/AudioSourceProvider.h" | 85 #include "platform/audio/AudioSourceProvider.h" |
82 #include "modules/webaudio/MediaElementAudioSourceNode.h" | 86 #include "modules/webaudio/MediaElementAudioSourceNode.h" |
83 #endif | 87 #endif |
84 | 88 |
85 using namespace std; | 89 using namespace std; |
86 using blink::WebInbandTextTrack; | 90 using blink::WebInbandTextTrack; |
87 using blink::WebMimeRegistry; | 91 using blink::WebMimeRegistry; |
| 92 using blink::WebMediaPlayerClient; |
88 | 93 |
89 namespace WebCore { | 94 namespace WebCore { |
90 | 95 |
91 #if !LOG_DISABLED | 96 #if !LOG_DISABLED |
92 static String urlForLoggingMedia(const KURL& url) | 97 static String urlForLoggingMedia(const KURL& url) |
93 { | 98 { |
94 static const unsigned maximumURLLengthForLogging = 128; | 99 static const unsigned maximumURLLengthForLogging = 128; |
95 | 100 |
96 if (url.string().length() < maximumURLLengthForLogging) | 101 if (url.string().length() < maximumURLLengthForLogging) |
97 return url.string(); | 102 return url.string(); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 ~TrackDisplayUpdateScope() | 161 ~TrackDisplayUpdateScope() |
157 { | 162 { |
158 ASSERT(m_mediaElement); | 163 ASSERT(m_mediaElement); |
159 m_mediaElement->endIgnoringTrackDisplayUpdateRequests(); | 164 m_mediaElement->endIgnoringTrackDisplayUpdateRequests(); |
160 } | 165 } |
161 | 166 |
162 private: | 167 private: |
163 HTMLMediaElement* m_mediaElement; | 168 HTMLMediaElement* m_mediaElement; |
164 }; | 169 }; |
165 | 170 |
| 171 static const AtomicString& AudioKindToString(WebMediaPlayerClient::AudioTrackKin
d kind) |
| 172 { |
| 173 switch (kind) { |
| 174 case WebMediaPlayerClient::AudioTrackKindNone: |
| 175 return emptyAtom; |
| 176 case WebMediaPlayerClient::AudioTrackKindAlternative: |
| 177 return AudioTrack::alternativeKeyword(); |
| 178 case WebMediaPlayerClient::AudioTrackKindDescriptions: |
| 179 return AudioTrack::descriptionsKeyword(); |
| 180 case WebMediaPlayerClient::AudioTrackKindMain: |
| 181 return AudioTrack::mainKeyword(); |
| 182 case WebMediaPlayerClient::AudioTrackKindMainDescriptions: |
| 183 return AudioTrack::mainDescriptionsKeyword(); |
| 184 case WebMediaPlayerClient::AudioTrackKindTranslation: |
| 185 return AudioTrack::translationKeyword(); |
| 186 case WebMediaPlayerClient::AudioTrackKindCommentary: |
| 187 return AudioTrack::commentaryKeyword(); |
| 188 } |
| 189 |
| 190 ASSERT_NOT_REACHED(); |
| 191 return emptyAtom; |
| 192 } |
| 193 |
| 194 static const AtomicString& VideoKindToString(WebMediaPlayerClient::VideoTrackKin
d kind) |
| 195 { |
| 196 switch (kind) { |
| 197 case WebMediaPlayerClient::VideoTrackKindNone: |
| 198 return emptyAtom; |
| 199 case WebMediaPlayerClient::VideoTrackKindAlternative: |
| 200 return VideoTrack::alternativeKeyword(); |
| 201 case WebMediaPlayerClient::VideoTrackKindCaptions: |
| 202 return VideoTrack::captionsKeyword(); |
| 203 case WebMediaPlayerClient::VideoTrackKindMain: |
| 204 return VideoTrack::mainKeyword(); |
| 205 case WebMediaPlayerClient::VideoTrackKindSign: |
| 206 return VideoTrack::signKeyword(); |
| 207 case WebMediaPlayerClient::VideoTrackKindSubtitles: |
| 208 return VideoTrack::subtitlesKeyword(); |
| 209 case WebMediaPlayerClient::VideoTrackKindCommentary: |
| 210 return VideoTrack::commentaryKeyword(); |
| 211 } |
| 212 |
| 213 ASSERT_NOT_REACHED(); |
| 214 return emptyAtom; |
| 215 } |
| 216 |
166 static bool canLoadURL(const KURL& url, const ContentType& contentType, const St
ring& keySystem) | 217 static bool canLoadURL(const KURL& url, const ContentType& contentType, const St
ring& keySystem) |
167 { | 218 { |
168 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs")); | 219 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs")); |
169 | 220 |
170 String contentMIMEType = contentType.type().lower(); | 221 String contentMIMEType = contentType.type().lower(); |
171 String contentTypeCodecs = contentType.parameter(codecs); | 222 String contentTypeCodecs = contentType.parameter(codecs); |
172 | 223 |
173 // If the MIME type is missing or is not meaningful, try to figure it out fr
om the URL. | 224 // If the MIME type is missing or is not meaningful, try to figure it out fr
om the URL. |
174 if (contentMIMEType.isEmpty() || contentMIMEType == "application/octet-strea
m" || contentMIMEType == "text/plain") { | 225 if (contentMIMEType.isEmpty() || contentMIMEType == "application/octet-strea
m" || contentMIMEType == "text/plain") { |
175 if (url.protocolIsData()) | 226 if (url.protocolIsData()) |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 { | 278 { |
228 return s_mediaStreamRegistry ? s_mediaStreamRegistry->contains(url) : false; | 279 return s_mediaStreamRegistry ? s_mediaStreamRegistry->contains(url) : false; |
229 } | 280 } |
230 | 281 |
231 HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum
ent) | 282 HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum
ent) |
232 : HTMLElement(tagName, document) | 283 : HTMLElement(tagName, document) |
233 , ActiveDOMObject(&document) | 284 , ActiveDOMObject(&document) |
234 , m_loadTimer(this, &HTMLMediaElement::loadTimerFired) | 285 , m_loadTimer(this, &HTMLMediaElement::loadTimerFired) |
235 , m_progressEventTimer(this, &HTMLMediaElement::progressEventTimerFired) | 286 , m_progressEventTimer(this, &HTMLMediaElement::progressEventTimerFired) |
236 , m_playbackProgressTimer(this, &HTMLMediaElement::playbackProgressTimerFire
d) | 287 , m_playbackProgressTimer(this, &HTMLMediaElement::playbackProgressTimerFire
d) |
| 288 , m_audioTracksTimer(this, &HTMLMediaElement::audioTracksTimerFired) |
237 , m_playedTimeRanges() | 289 , m_playedTimeRanges() |
238 , m_asyncEventQueue(GenericEventQueue::create(this)) | 290 , m_asyncEventQueue(GenericEventQueue::create(this)) |
239 , m_playbackRate(1.0f) | 291 , m_playbackRate(1.0f) |
240 , m_defaultPlaybackRate(1.0f) | 292 , m_defaultPlaybackRate(1.0f) |
241 , m_networkState(NETWORK_EMPTY) | 293 , m_networkState(NETWORK_EMPTY) |
242 , m_readyState(HAVE_NOTHING) | 294 , m_readyState(HAVE_NOTHING) |
243 , m_readyStateMaximum(HAVE_NOTHING) | 295 , m_readyStateMaximum(HAVE_NOTHING) |
244 , m_volume(1.0f) | 296 , m_volume(1.0f) |
245 , m_lastSeekTime(0) | 297 , m_lastSeekTime(0) |
246 , m_previousProgressTime(numeric_limits<double>::max()) | 298 , m_previousProgressTime(numeric_limits<double>::max()) |
(...skipping 23 matching lines...) Expand all Loading... |
270 , m_sentStalledEvent(false) | 322 , m_sentStalledEvent(false) |
271 , m_sentEndEvent(false) | 323 , m_sentEndEvent(false) |
272 , m_pausedInternal(false) | 324 , m_pausedInternal(false) |
273 , m_closedCaptionsVisible(false) | 325 , m_closedCaptionsVisible(false) |
274 , m_completelyLoaded(false) | 326 , m_completelyLoaded(false) |
275 , m_havePreparedToPlay(false) | 327 , m_havePreparedToPlay(false) |
276 , m_tracksAreReady(true) | 328 , m_tracksAreReady(true) |
277 , m_haveVisibleTextTrack(false) | 329 , m_haveVisibleTextTrack(false) |
278 , m_processingPreferenceChange(false) | 330 , m_processingPreferenceChange(false) |
279 , m_lastTextTrackUpdateTime(-1) | 331 , m_lastTextTrackUpdateTime(-1) |
| 332 , m_audioTracks(AudioTrackList::create(*this)) |
| 333 , m_videoTracks(VideoTrackList::create(*this)) |
280 , m_textTracks(nullptr) | 334 , m_textTracks(nullptr) |
281 , m_ignoreTrackDisplayUpdate(0) | 335 , m_ignoreTrackDisplayUpdate(0) |
282 #if ENABLE(WEB_AUDIO) | 336 #if ENABLE(WEB_AUDIO) |
283 , m_audioSourceNode(0) | 337 , m_audioSourceNode(0) |
284 #endif | 338 #endif |
285 { | 339 { |
286 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); | 340 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); |
287 | 341 |
288 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement"); | 342 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement"); |
289 ScriptWrappable::init(this); | 343 ScriptWrappable::init(this); |
(...skipping 12 matching lines...) Expand all Loading... |
302 { | 356 { |
303 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement"); | 357 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement"); |
304 | 358 |
305 m_asyncEventQueue->close(); | 359 m_asyncEventQueue->close(); |
306 | 360 |
307 setShouldDelayLoadEvent(false); | 361 setShouldDelayLoadEvent(false); |
308 | 362 |
309 if (m_textTracks) | 363 if (m_textTracks) |
310 m_textTracks->clearOwner(); | 364 m_textTracks->clearOwner(); |
311 | 365 |
| 366 m_audioTracks->shutdown(); |
| 367 m_videoTracks->shutdown(); |
| 368 |
312 if (m_mediaController) { | 369 if (m_mediaController) { |
313 m_mediaController->removeMediaElement(this); | 370 m_mediaController->removeMediaElement(this); |
314 m_mediaController = nullptr; | 371 m_mediaController = nullptr; |
315 } | 372 } |
316 | 373 |
317 closeMediaSource(); | 374 closeMediaSource(); |
318 | 375 |
319 removeElementFromDocumentMap(this, &document()); | 376 removeElementFromDocumentMap(this, &document()); |
320 | 377 |
321 // Destroying the player may cause a resource load to be canceled, | 378 // Destroying the player may cause a resource load to be canceled, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 // previous document. A proper fix would provide a mechanism to allow this | 418 // previous document. A proper fix would provide a mechanism to allow this |
362 // object to refresh the MediaPlayer's LocalFrame and FrameLoader references
on | 419 // object to refresh the MediaPlayer's LocalFrame and FrameLoader references
on |
363 // document changes so that playback can be resumed properly. | 420 // document changes so that playback can be resumed properly. |
364 userCancelledLoad(); | 421 userCancelledLoad(); |
365 | 422 |
366 // Decrement the load event delay count on oldDocument now that m_player has
been destroyed | 423 // Decrement the load event delay count on oldDocument now that m_player has
been destroyed |
367 // and there is no risk of dispatching a load event from within the destruct
or. | 424 // and there is no risk of dispatching a load event from within the destruct
or. |
368 oldDocument.decrementLoadEventDelayCount(); | 425 oldDocument.decrementLoadEventDelayCount(); |
369 | 426 |
370 ActiveDOMObject::didMoveToNewExecutionContext(&document()); | 427 ActiveDOMObject::didMoveToNewExecutionContext(&document()); |
| 428 |
371 HTMLElement::didMoveToNewDocument(oldDocument); | 429 HTMLElement::didMoveToNewDocument(oldDocument); |
372 } | 430 } |
373 | 431 |
374 bool HTMLMediaElement::hasCustomFocusLogic() const | 432 bool HTMLMediaElement::hasCustomFocusLogic() const |
375 { | 433 { |
376 return true; | 434 return true; |
377 } | 435 } |
378 | 436 |
379 bool HTMLMediaElement::supportsFocus() const | 437 bool HTMLMediaElement::supportsFocus() const |
380 { | 438 { |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 prepareToPlay(); | 655 prepareToPlay(); |
598 } | 656 } |
599 | 657 |
600 void HTMLMediaElement::prepareForLoad() | 658 void HTMLMediaElement::prepareForLoad() |
601 { | 659 { |
602 WTF_LOG(Media, "HTMLMediaElement::prepareForLoad"); | 660 WTF_LOG(Media, "HTMLMediaElement::prepareForLoad"); |
603 | 661 |
604 // Perform the cleanup required for the resource load algorithm to run. | 662 // Perform the cleanup required for the resource load algorithm to run. |
605 stopPeriodicTimers(); | 663 stopPeriodicTimers(); |
606 m_loadTimer.stop(); | 664 m_loadTimer.stop(); |
| 665 m_audioTracksTimer.stop(); |
607 m_sentEndEvent = false; | 666 m_sentEndEvent = false; |
608 m_sentStalledEvent = false; | 667 m_sentStalledEvent = false; |
609 m_haveFiredLoadedData = false; | 668 m_haveFiredLoadedData = false; |
610 m_completelyLoaded = false; | 669 m_completelyLoaded = false; |
611 m_havePreparedToPlay = false; | 670 m_havePreparedToPlay = false; |
612 m_displayMode = Unknown; | 671 m_displayMode = Unknown; |
613 | 672 |
614 // 1 - Abort any already-running instance of the resource selection algorith
m for this element. | 673 // 1 - Abort any already-running instance of the resource selection algorith
m for this element. |
615 m_loadState = WaitingForSource; | 674 m_loadState = WaitingForSource; |
616 m_currentSourceNode = nullptr; | 675 m_currentSourceNode = nullptr; |
(...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1559 finishSeek(); | 1618 finishSeek(); |
1560 } else { | 1619 } else { |
1561 if (wasPotentiallyPlaying && m_readyState < HAVE_FUTURE_DATA) { | 1620 if (wasPotentiallyPlaying && m_readyState < HAVE_FUTURE_DATA) { |
1562 // 4.8.10.8 | 1621 // 4.8.10.8 |
1563 scheduleTimeupdateEvent(false); | 1622 scheduleTimeupdateEvent(false); |
1564 scheduleEvent(EventTypeNames::waiting); | 1623 scheduleEvent(EventTypeNames::waiting); |
1565 } | 1624 } |
1566 } | 1625 } |
1567 | 1626 |
1568 if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA) { | 1627 if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA) { |
| 1628 createPlaceholderTracksIfNecessary(); |
| 1629 |
1569 prepareMediaFragmentURI(); | 1630 prepareMediaFragmentURI(); |
| 1631 |
| 1632 selectInitialTracksIfNecessary(); |
| 1633 |
1570 scheduleEvent(EventTypeNames::durationchange); | 1634 scheduleEvent(EventTypeNames::durationchange); |
1571 if (isHTMLVideoElement(*this)) | 1635 if (isHTMLVideoElement(*this)) |
1572 scheduleEvent(EventTypeNames::resize); | 1636 scheduleEvent(EventTypeNames::resize); |
1573 scheduleEvent(EventTypeNames::loadedmetadata); | 1637 scheduleEvent(EventTypeNames::loadedmetadata); |
1574 if (hasMediaControls()) | 1638 if (hasMediaControls()) |
1575 mediaControls()->reset(); | 1639 mediaControls()->reset(); |
1576 if (renderer()) | 1640 if (renderer()) |
1577 renderer()->updateFromElement(); | 1641 renderer()->updateFromElement(); |
1578 } | 1642 } |
1579 | 1643 |
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2182 m_lastTimeUpdateEventWallTime = now; | 2246 m_lastTimeUpdateEventWallTime = now; |
2183 m_lastTimeUpdateEventMovieTime = movieTime; | 2247 m_lastTimeUpdateEventMovieTime = movieTime; |
2184 } | 2248 } |
2185 } | 2249 } |
2186 | 2250 |
2187 bool HTMLMediaElement::canPlay() const | 2251 bool HTMLMediaElement::canPlay() const |
2188 { | 2252 { |
2189 return paused() || ended() || m_readyState < HAVE_METADATA; | 2253 return paused() || ended() || m_readyState < HAVE_METADATA; |
2190 } | 2254 } |
2191 | 2255 |
| 2256 AudioTrackList& HTMLMediaElement::audioTracks() |
| 2257 { |
| 2258 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); |
| 2259 return *m_audioTracks; |
| 2260 } |
| 2261 |
| 2262 void HTMLMediaElement::audioTrackChanged(const String& audioTrackID) |
| 2263 { |
| 2264 WTF_LOG(Media, "HTMLMediaElement::audioTrackChanged('%s')", audioTrackID.asc
ii().data()); |
| 2265 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); |
| 2266 ASSERT(!audioTrackID.isEmpty()); |
| 2267 |
| 2268 audioTracks().scheduleChangeEvent(); |
| 2269 |
| 2270 // FIXME: Add call on m_mediaSource to notify it of track changes once the S
ourceBuffer.audioTracks attribute is added. |
| 2271 |
| 2272 if (!m_audioTracksTimer.isActive()) |
| 2273 m_audioTracksTimer.startOneShot(0, FROM_HERE); |
| 2274 } |
| 2275 |
| 2276 void HTMLMediaElement::addAudioTrack(const String& id, blink::WebMediaPlayerClie
nt::AudioTrackKind kind, const AtomicString& label, const AtomicString& language
, bool enabled) |
| 2277 { |
| 2278 AtomicString kindString = AudioKindToString(kind); |
| 2279 WTF_LOG(Media, "HTMLMediaElement::addAudioTrack('%s', '%s', '%s', '%s', %d)"
, |
| 2280 id.ascii().data(), kindString.ascii().data(), label.ascii().data(), lang
uage.ascii().data(), enabled); |
| 2281 ASSERT(!id.isEmpty()); |
| 2282 |
| 2283 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) |
| 2284 return; |
| 2285 |
| 2286 RefPtr<AudioTrack> audioTrack = AudioTrack::create(this, id, kindString, lab
el, language); |
| 2287 audioTracks().add(audioTrack.get()); |
| 2288 |
| 2289 if (enabled) |
| 2290 audioTrack->setEnabled(true); |
| 2291 } |
| 2292 |
| 2293 void HTMLMediaElement::removeAudioTrack(const String& id) |
| 2294 { |
| 2295 WTF_LOG(Media, "HTMLMediaElement::removeAudioTrack('%s')", id.ascii().data()
); |
| 2296 ASSERT(!id.isEmpty()); |
| 2297 |
| 2298 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) |
| 2299 return; |
| 2300 |
| 2301 audioTracks().remove(id); |
| 2302 } |
| 2303 |
| 2304 VideoTrackList& HTMLMediaElement::videoTracks() |
| 2305 { |
| 2306 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); |
| 2307 return *m_videoTracks; |
| 2308 } |
| 2309 |
| 2310 void HTMLMediaElement::selectedVideoTrackChanged(const String& selectedTrackID) |
| 2311 { |
| 2312 WTF_LOG(Media, "HTMLMediaElement::selectedVideoTrackChanged('%s')", selected
TrackID.ascii().data()); |
| 2313 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); |
| 2314 |
| 2315 String unselectedTrackID; |
| 2316 |
| 2317 int oldSelectedIndex = videoTracks().selectedIndex(); |
| 2318 if (oldSelectedIndex != -1) |
| 2319 unselectedTrackID = videoTracks().anonymousIndexedGetter(oldSelectedInde
x)->id(); |
| 2320 |
| 2321 ASSERT(unselectedTrackID != selectedTrackID); |
| 2322 ASSERT(!unselectedTrackID.isEmpty() || !selectedTrackID.isEmpty()); |
| 2323 |
| 2324 videoTracks().trackSelected(selectedTrackID); |
| 2325 |
| 2326 // FIXME: Add call on m_mediaSource to notify it of track changes once the S
ourceBuffer.videoTracks attribute is added. |
| 2327 |
| 2328 if (webMediaPlayer()) |
| 2329 webMediaPlayer()->selectedVideoTrackChanged(selectedTrackID); |
| 2330 } |
| 2331 |
| 2332 void HTMLMediaElement::addVideoTrack(const String& id, blink::WebMediaPlayerClie
nt::VideoTrackKind kind, const AtomicString& label, const AtomicString& language
, bool selected) |
| 2333 { |
| 2334 AtomicString kindString = VideoKindToString(kind); |
| 2335 WTF_LOG(Media, "HTMLMediaElement::addVideoTrack('%s', '%s', '%s', '%s', %d)"
, |
| 2336 id.ascii().data(), kindString.ascii().data(), label.ascii().data(), lang
uage.ascii().data(), selected); |
| 2337 ASSERT(!id.isEmpty()); |
| 2338 |
| 2339 RefPtr<VideoTrack> videoTrack = VideoTrack::create(this, id, kindString, lab
el, language); |
| 2340 videoTracks().add(videoTrack.get()); |
| 2341 |
| 2342 if (selected) |
| 2343 videoTrack->setSelected(true); |
| 2344 } |
| 2345 |
| 2346 void HTMLMediaElement::removeVideoTrack(const String& id) |
| 2347 { |
| 2348 WTF_LOG(Media, "HTMLMediaElement::removeVideoTrack('%s')", id.ascii().data()
); |
| 2349 ASSERT(!id.isEmpty()); |
| 2350 |
| 2351 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) |
| 2352 return; |
| 2353 |
| 2354 videoTracks().remove(id); |
| 2355 } |
| 2356 |
2192 void HTMLMediaElement::mediaPlayerDidAddTextTrack(WebInbandTextTrack* webTrack) | 2357 void HTMLMediaElement::mediaPlayerDidAddTextTrack(WebInbandTextTrack* webTrack) |
2193 { | 2358 { |
2194 if (!RuntimeEnabledFeatures::videoTrackEnabled()) | 2359 if (!RuntimeEnabledFeatures::videoTrackEnabled()) |
2195 return; | 2360 return; |
2196 | 2361 |
2197 // 4.8.10.12.2 Sourcing in-band text tracks | 2362 // 4.8.10.12.2 Sourcing in-band text tracks |
2198 // 1. Associate the relevant data with a new text track and its correspondin
g new TextTrack object. | 2363 // 1. Associate the relevant data with a new text track and its correspondin
g new TextTrack object. |
2199 RefPtr<InbandTextTrack> textTrack = InbandTextTrack::create(document(), webT
rack); | 2364 RefPtr<InbandTextTrack> textTrack = InbandTextTrack::create(document(), webT
rack); |
2200 | 2365 |
2201 // 2. Set the new text track's kind, label, and language based on the semant
ics of the relevant data, | 2366 // 2. Set the new text track's kind, label, and language based on the semant
ics of the relevant data, |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2257 void HTMLMediaElement::removeTextTrack(TextTrack* track) | 2422 void HTMLMediaElement::removeTextTrack(TextTrack* track) |
2258 { | 2423 { |
2259 TrackDisplayUpdateScope scope(this); | 2424 TrackDisplayUpdateScope scope(this); |
2260 m_textTracks->remove(track); | 2425 m_textTracks->remove(track); |
2261 | 2426 |
2262 closeCaptionTracksChanged(); | 2427 closeCaptionTracksChanged(); |
2263 } | 2428 } |
2264 | 2429 |
2265 void HTMLMediaElement::forgetResourceSpecificTracks() | 2430 void HTMLMediaElement::forgetResourceSpecificTracks() |
2266 { | 2431 { |
| 2432 // Implements the "forget the media element's media-resource-specific tracks
" algorithm. |
| 2433 // The order is explicitly specified as text, then audio, and finally video.
Also |
| 2434 // 'removetrack' events should not be fired. |
2267 if (m_textTracks) { | 2435 if (m_textTracks) { |
2268 TrackDisplayUpdateScope scope(this); | 2436 TrackDisplayUpdateScope scope(this); |
2269 m_textTracks->removeAllInbandTracks(); | 2437 m_textTracks->removeAllInbandTracks(); |
2270 closeCaptionTracksChanged(); | 2438 closeCaptionTracksChanged(); |
2271 } | 2439 } |
| 2440 |
| 2441 m_audioTracks->removeAll(); |
| 2442 m_videoTracks->removeAll(); |
2272 } | 2443 } |
2273 | 2444 |
2274 PassRefPtr<TextTrack> HTMLMediaElement::addTextTrack(const AtomicString& kind, c
onst AtomicString& label, const AtomicString& language, ExceptionState& exceptio
nState) | 2445 PassRefPtr<TextTrack> HTMLMediaElement::addTextTrack(const AtomicString& kind, c
onst AtomicString& label, const AtomicString& language, ExceptionState& exceptio
nState) |
2275 { | 2446 { |
2276 ASSERT(RuntimeEnabledFeatures::videoTrackEnabled()); | 2447 ASSERT(RuntimeEnabledFeatures::videoTrackEnabled()); |
2277 | 2448 |
2278 // 4.8.10.12.4 Text track API | 2449 // 4.8.10.12.4 Text track API |
2279 // The addTextTrack(kind, label, language) method of media elements, when in
voked, must run the following steps: | 2450 // The addTextTrack(kind, label, language) method of media elements, when in
voked, must run the following steps: |
2280 | 2451 |
2281 // 1. If kind is not one of the following strings, then throw a SyntaxError
exception and abort these steps | 2452 // 1. If kind is not one of the following strings, then throw a SyntaxError
exception and abort these steps |
(...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3116 void HTMLMediaElement::clearMediaPlayer(int flags) | 3287 void HTMLMediaElement::clearMediaPlayer(int flags) |
3117 { | 3288 { |
3118 forgetResourceSpecificTracks(); | 3289 forgetResourceSpecificTracks(); |
3119 | 3290 |
3120 closeMediaSource(); | 3291 closeMediaSource(); |
3121 | 3292 |
3122 clearMediaPlayerAndAudioSourceProviderClient(); | 3293 clearMediaPlayerAndAudioSourceProviderClient(); |
3123 | 3294 |
3124 stopPeriodicTimers(); | 3295 stopPeriodicTimers(); |
3125 m_loadTimer.stop(); | 3296 m_loadTimer.stop(); |
| 3297 m_audioTracksTimer.stop(); |
3126 | 3298 |
3127 m_pendingActionFlags &= ~flags; | 3299 m_pendingActionFlags &= ~flags; |
3128 m_loadState = WaitingForSource; | 3300 m_loadState = WaitingForSource; |
3129 | 3301 |
3130 if (m_textTracks) | 3302 if (m_textTracks) |
3131 configureTextTrackDisplay(AssumeNoVisibleChange); | 3303 configureTextTrackDisplay(AssumeNoVisibleChange); |
3132 } | 3304 } |
3133 | 3305 |
3134 void HTMLMediaElement::stop() | 3306 void HTMLMediaElement::stop() |
3135 { | 3307 { |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3559 m_fragmentStartTime = MediaPlayer::invalidTime(); | 3731 m_fragmentStartTime = MediaPlayer::invalidTime(); |
3560 | 3732 |
3561 double end = fragmentParser.endTime(); | 3733 double end = fragmentParser.endTime(); |
3562 if (end != MediaFragmentURIParser::invalidTimeValue() && end > 0 && end > m_
fragmentStartTime) { | 3734 if (end != MediaFragmentURIParser::invalidTimeValue() && end > 0 && end > m_
fragmentStartTime) { |
3563 m_fragmentEndTime = end; | 3735 m_fragmentEndTime = end; |
3564 if (m_fragmentEndTime > dur) | 3736 if (m_fragmentEndTime > dur) |
3565 m_fragmentEndTime = dur; | 3737 m_fragmentEndTime = dur; |
3566 } else | 3738 } else |
3567 m_fragmentEndTime = MediaPlayer::invalidTime(); | 3739 m_fragmentEndTime = MediaPlayer::invalidTime(); |
3568 | 3740 |
| 3741 // FIXME: Add support for selecting tracks by ID with the Media Fragments tr
ack dimension. |
| 3742 |
3569 if (m_fragmentStartTime != MediaPlayer::invalidTime() && m_readyState < HAVE
_FUTURE_DATA) | 3743 if (m_fragmentStartTime != MediaPlayer::invalidTime() && m_readyState < HAVE
_FUTURE_DATA) |
3570 prepareToPlay(); | 3744 prepareToPlay(); |
3571 } | 3745 } |
3572 | 3746 |
3573 void HTMLMediaElement::applyMediaFragmentURI() | 3747 void HTMLMediaElement::applyMediaFragmentURI() |
3574 { | 3748 { |
3575 if (m_fragmentStartTime != MediaPlayer::invalidTime()) { | 3749 if (m_fragmentStartTime != MediaPlayer::invalidTime()) { |
3576 m_sentEndEvent = false; | 3750 m_sentEndEvent = false; |
3577 UseCounter::count(document(), UseCounter::HTMLMediaElementSeekToFragment
Start); | 3751 UseCounter::count(document(), UseCounter::HTMLMediaElementSeekToFragment
Start); |
3578 seek(m_fragmentStartTime, IGNORE_EXCEPTION); | 3752 seek(m_fragmentStartTime, IGNORE_EXCEPTION); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3617 void HTMLMediaElement::mediaPlayerMediaSourceOpened(blink::WebMediaSource* webMe
diaSource) | 3791 void HTMLMediaElement::mediaPlayerMediaSourceOpened(blink::WebMediaSource* webMe
diaSource) |
3618 { | 3792 { |
3619 m_mediaSource->setWebMediaSourceAndOpen(adoptPtr(webMediaSource)); | 3793 m_mediaSource->setWebMediaSourceAndOpen(adoptPtr(webMediaSource)); |
3620 } | 3794 } |
3621 | 3795 |
3622 bool HTMLMediaElement::isInteractiveContent() const | 3796 bool HTMLMediaElement::isInteractiveContent() const |
3623 { | 3797 { |
3624 return fastHasAttribute(controlsAttr); | 3798 return fastHasAttribute(controlsAttr); |
3625 } | 3799 } |
3626 | 3800 |
| 3801 void HTMLMediaElement::createPlaceholderTracksIfNecessary() |
| 3802 { |
| 3803 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) |
| 3804 return; |
| 3805 |
| 3806 // Create a placeholder audio track if |m_player| says it has audio but it d
idn't explicitly announce the tracks. |
| 3807 if (m_player->hasAudio() && !audioTracks().length()) |
| 3808 addAudioTrack("audio", WebMediaPlayerClient::AudioTrackKindMain, "Audio
Track", "", true); |
| 3809 |
| 3810 // Create a placeholder video track if |m_player| says it has video but it d
idn't explicitly announce the tracks. |
| 3811 if (m_player->hasVideo() && !videoTracks().length()) |
| 3812 addVideoTrack("video", WebMediaPlayerClient::VideoTrackKindMain, "Video
Track", "", true); |
3627 } | 3813 } |
| 3814 |
| 3815 void HTMLMediaElement::selectInitialTracksIfNecessary() |
| 3816 { |
| 3817 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) |
| 3818 return; |
| 3819 |
| 3820 // Enable the first audio track if an audio track hasn't been enabled yet. |
| 3821 if (audioTracks().length() > 0 && !audioTracks().hasEnabledTrack()) |
| 3822 audioTracks().anonymousIndexedGetter(0)->setEnabled(true); |
| 3823 |
| 3824 // Select the first video track if a video track hasn't been selected yet. |
| 3825 if (videoTracks().length() > 0 && videoTracks().selectedIndex() == -1) |
| 3826 videoTracks().anonymousIndexedGetter(0)->setSelected(true); |
| 3827 } |
| 3828 |
| 3829 void HTMLMediaElement::audioTracksTimerFired(Timer<HTMLMediaElement>*) |
| 3830 { |
| 3831 if (!webMediaPlayer()) |
| 3832 return; |
| 3833 |
| 3834 Vector<String> enabledTrackIDs; |
| 3835 for (unsigned i = 0; i < audioTracks().length(); ++i) { |
| 3836 RefPtr<AudioTrack> track = audioTracks().anonymousIndexedGetter(i); |
| 3837 if (track->enabled()) |
| 3838 enabledTrackIDs.append(track->id()); |
| 3839 } |
| 3840 |
| 3841 webMediaPlayer()->enabledAudioTracksChanged(enabledTrackIDs); |
| 3842 } |
| 3843 |
| 3844 } |
OLD | NEW |