Chromium Code Reviews| 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 44 #include "core/frame/UseCounter.h" | 44 #include "core/frame/UseCounter.h" |
| 45 #include "core/frame/csp/ContentSecurityPolicy.h" | 45 #include "core/frame/csp/ContentSecurityPolicy.h" |
| 46 #include "core/html/HTMLMediaSource.h" | 46 #include "core/html/HTMLMediaSource.h" |
| 47 #include "core/html/HTMLSourceElement.h" | 47 #include "core/html/HTMLSourceElement.h" |
| 48 #include "core/html/HTMLTrackElement.h" | 48 #include "core/html/HTMLTrackElement.h" |
| 49 #include "core/html/MediaController.h" | 49 #include "core/html/MediaController.h" |
| 50 #include "core/html/MediaError.h" | 50 #include "core/html/MediaError.h" |
| 51 #include "core/html/MediaFragmentURIParser.h" | 51 #include "core/html/MediaFragmentURIParser.h" |
| 52 #include "core/html/TimeRanges.h" | 52 #include "core/html/TimeRanges.h" |
| 53 #include "core/html/shadow/MediaControls.h" | 53 #include "core/html/shadow/MediaControls.h" |
| 54 #include "core/html/track/AudioTrack.h" | |
| 55 #include "core/html/track/AudioTrackList.h" | |
| 54 #include "core/html/track/InbandTextTrack.h" | 56 #include "core/html/track/InbandTextTrack.h" |
| 55 #include "core/html/track/TextTrackCueList.h" | 57 #include "core/html/track/TextTrackCueList.h" |
| 56 #include "core/html/track/TextTrackList.h" | 58 #include "core/html/track/TextTrackList.h" |
| 59 #include "core/html/track/VideoTrack.h" | |
| 60 #include "core/html/track/VideoTrackList.h" | |
| 57 #include "core/loader/FrameLoader.h" | 61 #include "core/loader/FrameLoader.h" |
| 58 #include "core/rendering/RenderVideo.h" | 62 #include "core/rendering/RenderVideo.h" |
| 59 #include "core/rendering/RenderView.h" | 63 #include "core/rendering/RenderView.h" |
| 60 #include "core/rendering/compositing/RenderLayerCompositor.h" | 64 #include "core/rendering/compositing/RenderLayerCompositor.h" |
| 61 #include "platform/ContentType.h" | 65 #include "platform/ContentType.h" |
| 62 #include "platform/Language.h" | 66 #include "platform/Language.h" |
| 63 #include "platform/Logging.h" | 67 #include "platform/Logging.h" |
| 64 #include "platform/MIMETypeFromURL.h" | 68 #include "platform/MIMETypeFromURL.h" |
| 65 #include "platform/MIMETypeRegistry.h" | 69 #include "platform/MIMETypeRegistry.h" |
| 66 #include "platform/NotImplemented.h" | 70 #include "platform/NotImplemented.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 78 | 82 |
| 79 #if ENABLE(WEB_AUDIO) | 83 #if ENABLE(WEB_AUDIO) |
| 80 #include "platform/audio/AudioSourceProvider.h" | 84 #include "platform/audio/AudioSourceProvider.h" |
| 81 #include "modules/webaudio/MediaElementAudioSourceNode.h" | 85 #include "modules/webaudio/MediaElementAudioSourceNode.h" |
| 82 #endif | 86 #endif |
| 83 | 87 |
| 84 using namespace std; | 88 using namespace std; |
| 85 using blink::WebInbandTextTrack; | 89 using blink::WebInbandTextTrack; |
| 86 using blink::WebMediaPlayer; | 90 using blink::WebMediaPlayer; |
| 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 24 matching lines...) Expand all Loading... | |
| 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_delayingLoadForPreloadNone(false) | 328 , m_delayingLoadForPreloadNone(false) |
| 277 , m_tracksAreReady(true) | 329 , m_tracksAreReady(true) |
| 278 , m_haveVisibleTextTrack(false) | 330 , m_haveVisibleTextTrack(false) |
| 279 , m_processingPreferenceChange(false) | 331 , m_processingPreferenceChange(false) |
| 280 , m_lastTextTrackUpdateTime(-1) | 332 , m_lastTextTrackUpdateTime(-1) |
| 333 , m_audioTracks(AudioTrackList::create(*this)) | |
| 334 , m_videoTracks(VideoTrackList::create(*this)) | |
| 281 , m_textTracks(nullptr) | 335 , m_textTracks(nullptr) |
| 282 , m_ignoreTrackDisplayUpdate(0) | 336 , m_ignoreTrackDisplayUpdate(0) |
| 283 #if ENABLE(WEB_AUDIO) | 337 #if ENABLE(WEB_AUDIO) |
| 284 , m_audioSourceNode(0) | 338 , m_audioSourceNode(0) |
| 285 #endif | 339 #endif |
| 286 { | 340 { |
| 287 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); | 341 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); |
| 288 | 342 |
| 289 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement"); | 343 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement"); |
| 290 ScriptWrappable::init(this); | 344 ScriptWrappable::init(this); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 303 { | 357 { |
| 304 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement"); | 358 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement"); |
| 305 | 359 |
| 306 m_asyncEventQueue->close(); | 360 m_asyncEventQueue->close(); |
| 307 | 361 |
| 308 setShouldDelayLoadEvent(false); | 362 setShouldDelayLoadEvent(false); |
| 309 | 363 |
| 310 if (m_textTracks) | 364 if (m_textTracks) |
| 311 m_textTracks->clearOwner(); | 365 m_textTracks->clearOwner(); |
| 312 | 366 |
| 367 m_audioTracks->shutdown(); | |
| 368 m_videoTracks->shutdown(); | |
| 369 | |
| 313 if (m_mediaController) { | 370 if (m_mediaController) { |
| 314 m_mediaController->removeMediaElement(this); | 371 m_mediaController->removeMediaElement(this); |
| 315 m_mediaController = nullptr; | 372 m_mediaController = nullptr; |
| 316 } | 373 } |
| 317 | 374 |
| 318 closeMediaSource(); | 375 closeMediaSource(); |
| 319 | 376 |
| 320 removeElementFromDocumentMap(this, &document()); | 377 removeElementFromDocumentMap(this, &document()); |
| 321 | 378 |
| 322 // Destroying the player may cause a resource load to be canceled, | 379 // Destroying the player may cause a resource load to be canceled, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 362 // previous document. A proper fix would provide a mechanism to allow this | 419 // previous document. A proper fix would provide a mechanism to allow this |
| 363 // object to refresh the MediaPlayer's LocalFrame and FrameLoader references on | 420 // object to refresh the MediaPlayer's LocalFrame and FrameLoader references on |
| 364 // document changes so that playback can be resumed properly. | 421 // document changes so that playback can be resumed properly. |
| 365 userCancelledLoad(); | 422 userCancelledLoad(); |
| 366 | 423 |
| 367 // Decrement the load event delay count on oldDocument now that m_player has been destroyed | 424 // Decrement the load event delay count on oldDocument now that m_player has been destroyed |
| 368 // and there is no risk of dispatching a load event from within the destruct or. | 425 // and there is no risk of dispatching a load event from within the destruct or. |
| 369 oldDocument.decrementLoadEventDelayCount(); | 426 oldDocument.decrementLoadEventDelayCount(); |
| 370 | 427 |
| 371 ActiveDOMObject::didMoveToNewExecutionContext(&document()); | 428 ActiveDOMObject::didMoveToNewExecutionContext(&document()); |
| 429 | |
| 372 HTMLElement::didMoveToNewDocument(oldDocument); | 430 HTMLElement::didMoveToNewDocument(oldDocument); |
| 373 } | 431 } |
| 374 | 432 |
| 375 bool HTMLMediaElement::hasCustomFocusLogic() const | 433 bool HTMLMediaElement::hasCustomFocusLogic() const |
| 376 { | 434 { |
| 377 return true; | 435 return true; |
| 378 } | 436 } |
| 379 | 437 |
| 380 bool HTMLMediaElement::supportsFocus() const | 438 bool HTMLMediaElement::supportsFocus() const |
| 381 { | 439 { |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 595 | 653 |
| 596 void HTMLMediaElement::prepareForLoad() | 654 void HTMLMediaElement::prepareForLoad() |
| 597 { | 655 { |
| 598 WTF_LOG(Media, "HTMLMediaElement::prepareForLoad"); | 656 WTF_LOG(Media, "HTMLMediaElement::prepareForLoad"); |
| 599 | 657 |
| 600 // Perform the cleanup required for the resource load algorithm to run. | 658 // Perform the cleanup required for the resource load algorithm to run. |
| 601 stopPeriodicTimers(); | 659 stopPeriodicTimers(); |
| 602 m_loadTimer.stop(); | 660 m_loadTimer.stop(); |
| 603 // FIXME: Figure out appropriate place to reset LoadTextTrackResource if nec essary and set m_pendingActionFlags to 0 here. | 661 // FIXME: Figure out appropriate place to reset LoadTextTrackResource if nec essary and set m_pendingActionFlags to 0 here. |
| 604 m_pendingActionFlags &= ~LoadMediaResource; | 662 m_pendingActionFlags &= ~LoadMediaResource; |
| 663 m_audioTracksTimer.stop(); | |
| 605 m_sentEndEvent = false; | 664 m_sentEndEvent = false; |
| 606 m_sentStalledEvent = false; | 665 m_sentStalledEvent = false; |
| 607 m_haveFiredLoadedData = false; | 666 m_haveFiredLoadedData = false; |
| 608 m_completelyLoaded = false; | 667 m_completelyLoaded = false; |
| 609 m_havePreparedToPlay = false; | 668 m_havePreparedToPlay = false; |
| 610 m_displayMode = Unknown; | 669 m_displayMode = Unknown; |
| 611 | 670 |
| 612 // 1 - Abort any already-running instance of the resource selection algorith m for this element. | 671 // 1 - Abort any already-running instance of the resource selection algorith m for this element. |
| 613 m_loadState = WaitingForSource; | 672 m_loadState = WaitingForSource; |
| 614 m_currentSourceNode = nullptr; | 673 m_currentSourceNode = nullptr; |
| (...skipping 966 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1581 finishSeek(); | 1640 finishSeek(); |
| 1582 } else { | 1641 } else { |
| 1583 if (wasPotentiallyPlaying && m_readyState < HAVE_FUTURE_DATA) { | 1642 if (wasPotentiallyPlaying && m_readyState < HAVE_FUTURE_DATA) { |
| 1584 // 4.8.10.8 | 1643 // 4.8.10.8 |
| 1585 scheduleTimeupdateEvent(false); | 1644 scheduleTimeupdateEvent(false); |
| 1586 scheduleEvent(EventTypeNames::waiting); | 1645 scheduleEvent(EventTypeNames::waiting); |
| 1587 } | 1646 } |
| 1588 } | 1647 } |
| 1589 | 1648 |
| 1590 if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA) { | 1649 if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA) { |
| 1650 createPlaceholderTracksIfNecessary(); | |
| 1651 | |
| 1591 prepareMediaFragmentURI(); | 1652 prepareMediaFragmentURI(); |
| 1653 | |
| 1654 selectInitialTracksIfNecessary(); | |
| 1655 | |
| 1592 scheduleEvent(EventTypeNames::durationchange); | 1656 scheduleEvent(EventTypeNames::durationchange); |
| 1593 if (isHTMLVideoElement(*this)) | 1657 if (isHTMLVideoElement(*this)) |
| 1594 scheduleEvent(EventTypeNames::resize); | 1658 scheduleEvent(EventTypeNames::resize); |
| 1595 scheduleEvent(EventTypeNames::loadedmetadata); | 1659 scheduleEvent(EventTypeNames::loadedmetadata); |
| 1596 if (hasMediaControls()) | 1660 if (hasMediaControls()) |
| 1597 mediaControls()->reset(); | 1661 mediaControls()->reset(); |
| 1598 if (renderer()) | 1662 if (renderer()) |
| 1599 renderer()->updateFromElement(); | 1663 renderer()->updateFromElement(); |
| 1600 } | 1664 } |
| 1601 | 1665 |
| (...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2179 m_lastTimeUpdateEventWallTime = now; | 2243 m_lastTimeUpdateEventWallTime = now; |
| 2180 m_lastTimeUpdateEventMovieTime = movieTime; | 2244 m_lastTimeUpdateEventMovieTime = movieTime; |
| 2181 } | 2245 } |
| 2182 } | 2246 } |
| 2183 | 2247 |
| 2184 bool HTMLMediaElement::canPlay() const | 2248 bool HTMLMediaElement::canPlay() const |
| 2185 { | 2249 { |
| 2186 return paused() || ended() || m_readyState < HAVE_METADATA; | 2250 return paused() || ended() || m_readyState < HAVE_METADATA; |
| 2187 } | 2251 } |
| 2188 | 2252 |
| 2253 | |
| 2189 void HTMLMediaElement::togglePlayState() | 2254 void HTMLMediaElement::togglePlayState() |
| 2190 { | 2255 { |
| 2191 ASSERT(controls()); | 2256 ASSERT(controls()); |
| 2192 // The activation behavior of a media element that is exposing a user interf ace to the user | 2257 // The activation behavior of a media element that is exposing a user interf ace to the user |
| 2193 if (m_mediaController) { | 2258 if (m_mediaController) { |
| 2194 if (m_mediaController->isRestrained()) | 2259 if (m_mediaController->isRestrained()) |
| 2195 m_mediaController->play(); | 2260 m_mediaController->play(); |
| 2196 else if (m_mediaController->paused()) | 2261 else if (m_mediaController->paused()) |
| 2197 m_mediaController->unpause(); | 2262 m_mediaController->unpause(); |
| 2198 else | 2263 else |
| 2199 m_mediaController->pause(); | 2264 m_mediaController->pause(); |
| 2200 } else { | 2265 } else { |
| 2201 if (paused()) | 2266 if (paused()) |
| 2202 play(); | 2267 play(); |
| 2203 else | 2268 else |
| 2204 pause(); | 2269 pause(); |
| 2205 } | 2270 } |
| 2271 | |
| 2272 AudioTrackList& HTMLMediaElement::audioTracks() | |
| 2273 { | |
| 2274 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); | |
| 2275 return *m_audioTracks; | |
| 2276 } | |
| 2277 | |
| 2278 void HTMLMediaElement::audioTrackChanged(const String& audioTrackID) | |
| 2279 { | |
| 2280 WTF_LOG(Media, "HTMLMediaElement::audioTrackChanged('%s')", audioTrackID.asc ii().data()); | |
| 2281 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); | |
| 2282 ASSERT(!audioTrackID.isEmpty()); | |
| 2283 | |
| 2284 audioTracks().scheduleChangeEvent(); | |
| 2285 | |
| 2286 // FIXME: Add call on m_mediaSource to notify it of track changes once the S ourceBuffer.audioTracks attribute is added. | |
| 2287 | |
| 2288 if (!m_audioTracksTimer.isActive()) | |
| 2289 m_audioTracksTimer.startOneShot(0, FROM_HERE); | |
| 2290 } | |
| 2291 | |
| 2292 void HTMLMediaElement::addAudioTrack(const String& id, blink::WebMediaPlayerClie nt::AudioTrackKind kind, const AtomicString& label, const AtomicString& language , bool enabled) | |
| 2293 { | |
| 2294 AtomicString kindString = AudioKindToString(kind); | |
| 2295 WTF_LOG(Media, "HTMLMediaElement::addAudioTrack('%s', '%s', '%s', '%s', %d)" , | |
| 2296 id.ascii().data(), kindString.ascii().data(), label.ascii().data(), lang uage.ascii().data(), enabled); | |
| 2297 ASSERT(!id.isEmpty()); | |
|
philipj_slow
2014/04/23 12:08:07
We've made a little discovery on this point. The s
| |
| 2298 | |
| 2299 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) | |
| 2300 return; | |
| 2301 | |
| 2302 RefPtr<AudioTrack> audioTrack = AudioTrack::create(this, id, kindString, lab el, language); | |
| 2303 audioTracks().add(audioTrack.get()); | |
| 2304 | |
| 2305 if (enabled) | |
| 2306 audioTrack->setEnabled(true); | |
| 2307 } | |
| 2308 | |
| 2309 void HTMLMediaElement::removeAudioTrack(const String& id) | |
| 2310 { | |
| 2311 WTF_LOG(Media, "HTMLMediaElement::removeAudioTrack('%s')", id.ascii().data() ); | |
| 2312 ASSERT(!id.isEmpty()); | |
| 2313 | |
| 2314 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) | |
| 2315 return; | |
| 2316 | |
| 2317 audioTracks().remove(id); | |
| 2318 } | |
| 2319 | |
| 2320 VideoTrackList& HTMLMediaElement::videoTracks() | |
| 2321 { | |
| 2322 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); | |
| 2323 return *m_videoTracks; | |
| 2324 } | |
| 2325 | |
| 2326 void HTMLMediaElement::selectedVideoTrackChanged(const String& selectedTrackID) | |
| 2327 { | |
| 2328 WTF_LOG(Media, "HTMLMediaElement::selectedVideoTrackChanged('%s')", selected TrackID.ascii().data()); | |
| 2329 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); | |
| 2330 | |
| 2331 String unselectedTrackID; | |
| 2332 | |
| 2333 int oldSelectedIndex = videoTracks().selectedIndex(); | |
| 2334 if (oldSelectedIndex != -1) | |
| 2335 unselectedTrackID = videoTracks().anonymousIndexedGetter(oldSelectedInde x)->id(); | |
| 2336 | |
| 2337 ASSERT(unselectedTrackID != selectedTrackID); | |
| 2338 ASSERT(!unselectedTrackID.isEmpty() || !selectedTrackID.isEmpty()); | |
| 2339 | |
| 2340 videoTracks().trackSelected(selectedTrackID); | |
| 2341 | |
| 2342 // FIXME: Add call on m_mediaSource to notify it of track changes once the S ourceBuffer.videoTracks attribute is added. | |
| 2343 | |
| 2344 if (webMediaPlayer()) | |
| 2345 webMediaPlayer()->selectedVideoTrackChanged(selectedTrackID); | |
| 2346 } | |
| 2347 | |
| 2348 void HTMLMediaElement::addVideoTrack(const String& id, blink::WebMediaPlayerClie nt::VideoTrackKind kind, const AtomicString& label, const AtomicString& language , bool selected) | |
| 2349 { | |
| 2350 AtomicString kindString = VideoKindToString(kind); | |
| 2351 WTF_LOG(Media, "HTMLMediaElement::addVideoTrack('%s', '%s', '%s', '%s', %d)" , | |
| 2352 id.ascii().data(), kindString.ascii().data(), label.ascii().data(), lang uage.ascii().data(), selected); | |
| 2353 ASSERT(!id.isEmpty()); | |
| 2354 | |
| 2355 RefPtr<VideoTrack> videoTrack = VideoTrack::create(this, id, kindString, lab el, language); | |
| 2356 videoTracks().add(videoTrack.get()); | |
| 2357 | |
| 2358 if (selected) | |
| 2359 videoTrack->setSelected(true); | |
| 2360 } | |
| 2361 | |
| 2362 void HTMLMediaElement::removeVideoTrack(const String& id) | |
| 2363 { | |
| 2364 WTF_LOG(Media, "HTMLMediaElement::removeVideoTrack('%s')", id.ascii().data() ); | |
| 2365 ASSERT(!id.isEmpty()); | |
| 2366 | |
| 2367 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) | |
| 2368 return; | |
| 2369 | |
| 2370 videoTracks().remove(id); | |
| 2206 } | 2371 } |
| 2207 | 2372 |
| 2208 void HTMLMediaElement::mediaPlayerDidAddTextTrack(WebInbandTextTrack* webTrack) | 2373 void HTMLMediaElement::mediaPlayerDidAddTextTrack(WebInbandTextTrack* webTrack) |
| 2209 { | 2374 { |
| 2210 if (!RuntimeEnabledFeatures::videoTrackEnabled()) | 2375 if (!RuntimeEnabledFeatures::videoTrackEnabled()) |
| 2211 return; | 2376 return; |
| 2212 | 2377 |
| 2213 // 4.8.10.12.2 Sourcing in-band text tracks | 2378 // 4.8.10.12.2 Sourcing in-band text tracks |
| 2214 // 1. Associate the relevant data with a new text track and its correspondin g new TextTrack object. | 2379 // 1. Associate the relevant data with a new text track and its correspondin g new TextTrack object. |
| 2215 RefPtr<InbandTextTrack> textTrack = InbandTextTrack::create(document(), webT rack); | 2380 RefPtr<InbandTextTrack> textTrack = InbandTextTrack::create(document(), webT rack); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2273 void HTMLMediaElement::removeTextTrack(TextTrack* track) | 2438 void HTMLMediaElement::removeTextTrack(TextTrack* track) |
| 2274 { | 2439 { |
| 2275 TrackDisplayUpdateScope scope(this); | 2440 TrackDisplayUpdateScope scope(this); |
| 2276 m_textTracks->remove(track); | 2441 m_textTracks->remove(track); |
| 2277 | 2442 |
| 2278 closeCaptionTracksChanged(); | 2443 closeCaptionTracksChanged(); |
| 2279 } | 2444 } |
| 2280 | 2445 |
| 2281 void HTMLMediaElement::forgetResourceSpecificTracks() | 2446 void HTMLMediaElement::forgetResourceSpecificTracks() |
| 2282 { | 2447 { |
| 2448 // Implements the "forget the media element's media-resource-specific tracks " algorithm. | |
| 2449 // The order is explicitly specified as text, then audio, and finally video. Also | |
| 2450 // 'removetrack' events should not be fired. | |
| 2283 if (m_textTracks) { | 2451 if (m_textTracks) { |
| 2284 TrackDisplayUpdateScope scope(this); | 2452 TrackDisplayUpdateScope scope(this); |
| 2285 m_textTracks->removeAllInbandTracks(); | 2453 m_textTracks->removeAllInbandTracks(); |
| 2286 closeCaptionTracksChanged(); | 2454 closeCaptionTracksChanged(); |
| 2287 } | 2455 } |
| 2456 | |
| 2457 m_audioTracks->removeAll(); | |
| 2458 m_videoTracks->removeAll(); | |
| 2288 } | 2459 } |
| 2289 | 2460 |
| 2290 PassRefPtr<TextTrack> HTMLMediaElement::addTextTrack(const AtomicString& kind, c onst AtomicString& label, const AtomicString& language, ExceptionState& exceptio nState) | 2461 PassRefPtr<TextTrack> HTMLMediaElement::addTextTrack(const AtomicString& kind, c onst AtomicString& label, const AtomicString& language, ExceptionState& exceptio nState) |
| 2291 { | 2462 { |
| 2292 ASSERT(RuntimeEnabledFeatures::videoTrackEnabled()); | 2463 ASSERT(RuntimeEnabledFeatures::videoTrackEnabled()); |
| 2293 | 2464 |
| 2294 // 4.8.10.12.4 Text track API | 2465 // 4.8.10.12.4 Text track API |
| 2295 // The addTextTrack(kind, label, language) method of media elements, when in voked, must run the following steps: | 2466 // The addTextTrack(kind, label, language) method of media elements, when in voked, must run the following steps: |
| 2296 | 2467 |
| 2297 // 1. If kind is not one of the following strings, then throw a SyntaxError exception and abort these steps | 2468 // 1. If kind is not one of the following strings, then throw a SyntaxError exception and abort these steps |
| (...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3129 forgetResourceSpecificTracks(); | 3300 forgetResourceSpecificTracks(); |
| 3130 | 3301 |
| 3131 closeMediaSource(); | 3302 closeMediaSource(); |
| 3132 | 3303 |
| 3133 m_delayingLoadForPreloadNone = false; | 3304 m_delayingLoadForPreloadNone = false; |
| 3134 | 3305 |
| 3135 clearMediaPlayerAndAudioSourceProviderClient(); | 3306 clearMediaPlayerAndAudioSourceProviderClient(); |
| 3136 | 3307 |
| 3137 stopPeriodicTimers(); | 3308 stopPeriodicTimers(); |
| 3138 m_loadTimer.stop(); | 3309 m_loadTimer.stop(); |
| 3310 m_audioTracksTimer.stop(); | |
| 3139 | 3311 |
| 3140 m_pendingActionFlags &= ~flags; | 3312 m_pendingActionFlags &= ~flags; |
| 3141 m_loadState = WaitingForSource; | 3313 m_loadState = WaitingForSource; |
| 3142 | 3314 |
| 3143 if (m_textTracks) | 3315 if (m_textTracks) |
| 3144 configureTextTrackDisplay(AssumeNoVisibleChange); | 3316 configureTextTrackDisplay(AssumeNoVisibleChange); |
| 3145 } | 3317 } |
| 3146 | 3318 |
| 3147 void HTMLMediaElement::stop() | 3319 void HTMLMediaElement::stop() |
| 3148 { | 3320 { |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3586 m_fragmentStartTime = MediaPlayer::invalidTime(); | 3758 m_fragmentStartTime = MediaPlayer::invalidTime(); |
| 3587 | 3759 |
| 3588 double end = fragmentParser.endTime(); | 3760 double end = fragmentParser.endTime(); |
| 3589 if (end != MediaFragmentURIParser::invalidTimeValue() && end > 0 && end > m_ fragmentStartTime) { | 3761 if (end != MediaFragmentURIParser::invalidTimeValue() && end > 0 && end > m_ fragmentStartTime) { |
| 3590 m_fragmentEndTime = end; | 3762 m_fragmentEndTime = end; |
| 3591 if (m_fragmentEndTime > dur) | 3763 if (m_fragmentEndTime > dur) |
| 3592 m_fragmentEndTime = dur; | 3764 m_fragmentEndTime = dur; |
| 3593 } else | 3765 } else |
| 3594 m_fragmentEndTime = MediaPlayer::invalidTime(); | 3766 m_fragmentEndTime = MediaPlayer::invalidTime(); |
| 3595 | 3767 |
| 3768 // FIXME: Add support for selecting tracks by ID with the Media Fragments tr ack dimension. | |
| 3769 | |
| 3596 if (m_fragmentStartTime != MediaPlayer::invalidTime() && m_readyState < HAVE _FUTURE_DATA) | 3770 if (m_fragmentStartTime != MediaPlayer::invalidTime() && m_readyState < HAVE _FUTURE_DATA) |
| 3597 prepareToPlay(); | 3771 prepareToPlay(); |
| 3598 } | 3772 } |
| 3599 | 3773 |
| 3600 void HTMLMediaElement::applyMediaFragmentURI() | 3774 void HTMLMediaElement::applyMediaFragmentURI() |
| 3601 { | 3775 { |
| 3602 if (m_fragmentStartTime != MediaPlayer::invalidTime()) { | 3776 if (m_fragmentStartTime != MediaPlayer::invalidTime()) { |
| 3603 m_sentEndEvent = false; | 3777 m_sentEndEvent = false; |
| 3604 UseCounter::count(document(), UseCounter::HTMLMediaElementSeekToFragment Start); | 3778 UseCounter::count(document(), UseCounter::HTMLMediaElementSeekToFragment Start); |
| 3605 seek(m_fragmentStartTime, IGNORE_EXCEPTION); | 3779 seek(m_fragmentStartTime, IGNORE_EXCEPTION); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3644 void HTMLMediaElement::mediaPlayerMediaSourceOpened(blink::WebMediaSource* webMe diaSource) | 3818 void HTMLMediaElement::mediaPlayerMediaSourceOpened(blink::WebMediaSource* webMe diaSource) |
| 3645 { | 3819 { |
| 3646 m_mediaSource->setWebMediaSourceAndOpen(adoptPtr(webMediaSource)); | 3820 m_mediaSource->setWebMediaSourceAndOpen(adoptPtr(webMediaSource)); |
| 3647 } | 3821 } |
| 3648 | 3822 |
| 3649 bool HTMLMediaElement::isInteractiveContent() const | 3823 bool HTMLMediaElement::isInteractiveContent() const |
| 3650 { | 3824 { |
| 3651 return fastHasAttribute(controlsAttr); | 3825 return fastHasAttribute(controlsAttr); |
| 3652 } | 3826 } |
| 3653 | 3827 |
| 3828 void HTMLMediaElement::createPlaceholderTracksIfNecessary() | |
| 3829 { | |
| 3830 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) | |
| 3831 return; | |
| 3832 | |
| 3833 // Create a placeholder audio track if |m_player| says it has audio but it d idn't explicitly announce the tracks. | |
| 3834 if (m_player->hasAudio() && !audioTracks().length()) | |
| 3835 addAudioTrack("audio", WebMediaPlayerClient::AudioTrackKindMain, "Audio Track", "", true); | |
| 3836 | |
| 3837 // Create a placeholder video track if |m_player| says it has video but it d idn't explicitly announce the tracks. | |
| 3838 if (m_player->hasVideo() && !videoTracks().length()) | |
| 3839 addVideoTrack("video", WebMediaPlayerClient::VideoTrackKindMain, "Video Track", "", true); | |
| 3654 } | 3840 } |
| 3841 | |
| 3842 void HTMLMediaElement::selectInitialTracksIfNecessary() | |
| 3843 { | |
| 3844 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) | |
| 3845 return; | |
| 3846 | |
| 3847 // Enable the first audio track if an audio track hasn't been enabled yet. | |
| 3848 if (audioTracks().length() > 0 && !audioTracks().hasEnabledTrack()) | |
| 3849 audioTracks().anonymousIndexedGetter(0)->setEnabled(true); | |
| 3850 | |
| 3851 // Select the first video track if a video track hasn't been selected yet. | |
| 3852 if (videoTracks().length() > 0 && videoTracks().selectedIndex() == -1) | |
| 3853 videoTracks().anonymousIndexedGetter(0)->setSelected(true); | |
| 3854 } | |
| 3855 | |
| 3856 void HTMLMediaElement::audioTracksTimerFired(Timer<HTMLMediaElement>*) | |
| 3857 { | |
| 3858 if (!webMediaPlayer()) | |
| 3859 return; | |
| 3860 | |
| 3861 Vector<String> enabledTrackIDs; | |
| 3862 for (unsigned i = 0; i < audioTracks().length(); ++i) { | |
| 3863 RefPtr<AudioTrack> track = audioTracks().anonymousIndexedGetter(i); | |
| 3864 if (track->enabled()) | |
| 3865 enabledTrackIDs.append(track->id()); | |
| 3866 } | |
| 3867 | |
| 3868 webMediaPlayer()->enabledAudioTracksChanged(enabledTrackIDs); | |
| 3869 } | |
| 3870 | |
| 3871 } | |
| OLD | NEW |