2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef HTMLMediaElement_h
27 #define HTMLMediaElement_h
29 #include "core/dom/ActiveDOMObject.h"
30 #include "core/events/GenericEventQueue.h"
31 #include "core/html/HTMLElement.h"
32 #include "core/html/MediaControllerInterface.h"
33 #include "core/html/track/TextTrack.h"
34 #include "core/html/track/TextTrackCue.h"
35 #include "core/html/track/vtt/VTTCue.h"
36 #include "platform/PODIntervalTree.h"
37 #include "platform/graphics/media/MediaPlayer.h"
38 #include "public/platform/WebMimeRegistry.h"
41 class WebContentDecryptionModule;
42 class WebInbandTextTrack;
49 class AudioSourceProvider;
50 class MediaElementAudioSourceNode;
55 class HTMLSourceElement;
56 class HTMLTrackElement;
58 class MediaController;
61 class HTMLMediaSource;
66 typedef PODIntervalTree<double, TextTrackCue*> CueIntervalTree;
67 typedef CueIntervalTree::IntervalType CueInterval;
68 typedef Vector<CueInterval> CueList;
70 // FIXME: The inheritance from MediaPlayerClient here should be private inheritance.
71 // But it can't be until the Chromium WebMediaPlayerClientImpl class is fixed so it
72 // no longer depends on typecasting a MediaPlayerClient to an HTMLMediaElement.
74 class HTMLMediaElement : public Supplementable<HTMLMediaElement>, public HTMLElement, public MediaPlayerClient, public ActiveDOMObject, public MediaControllerInterface
77 static blink::WebMimeRegistry::SupportsType supportsType(const ContentType&, const String& keySystem = String());
79 static void setMediaStreamRegistry(URLRegistry*);
80 static bool isMediaStreamURL(const String& url);
82 // Do not use player().
83 // FIXME: Replace all uses with webMediaPlayer() and remove this API.
84 MediaPlayer* player() const { return m_player.get(); }
85 blink::WebMediaPlayer* webMediaPlayer() const { return m_player ? m_player->webMediaPlayer() : 0; }
87 virtual bool hasVideo() const { return false; }
88 virtual bool hasAudio() const OVERRIDE FINAL;
90 bool supportsSave() const;
92 blink::WebLayer* platformLayer() const;
94 enum DelayedActionType {
95 LoadMediaResource = 1 << 0,
96 LoadTextTrackResource = 1 << 1,
97 TextTrackChangesNotification = 1 << 2
99 void scheduleDelayedAction(DelayedActionType);
101 bool isActive() const { return m_active; }
104 PassRefPtr<MediaError> error() const;
107 void setSrc(const AtomicString&);
108 const KURL& currentSrc() const { return m_currentSrc; }
110 enum NetworkState { NETWORK_EMPTY, NETWORK_IDLE, NETWORK_LOADING, NETWORK_NO_SOURCE };
111 NetworkState networkState() const;
113 String preload() const;
114 void setPreload(const AtomicString&);
116 PassRefPtr<TimeRanges> buffered() const;
118 String canPlayType(const String& mimeType, const String& keySystem = String()) const;
121 enum ReadyState { HAVE_NOTHING, HAVE_METADATA, HAVE_CURRENT_DATA, HAVE_FUTURE_DATA, HAVE_ENOUGH_DATA };
122 ReadyState readyState() const;
123 bool seeking() const;
126 virtual double currentTime() const OVERRIDE FINAL;
127 virtual void setCurrentTime(double, ExceptionState&) OVERRIDE FINAL;
128 virtual double duration() const OVERRIDE FINAL;
130 double defaultPlaybackRate() const;
131 void setDefaultPlaybackRate(double);
132 double playbackRate() const;
133 void setPlaybackRate(double);
134 void updatePlaybackRate();
135 PassRefPtr<TimeRanges> played();
136 PassRefPtr<TimeRanges> seekable() const;
138 bool autoplay() const;
140 void setLoop(bool b);
145 unsigned webkitAudioDecodedByteCount() const;
146 unsigned webkitVideoDecodedByteCount() const;
148 // media source extensions
149 void closeMediaSource();
150 void durationChanged(double duration);
153 bool controls() const;
154 void setControls(bool);
155 virtual double volume() const OVERRIDE FINAL;
156 virtual void setVolume(double, ExceptionState&) OVERRIDE FINAL;
157 virtual bool muted() const OVERRIDE FINAL;
158 virtual void setMuted(bool) OVERRIDE FINAL;
160 // play/pause toggling that uses the media controller if present. togglePlayStateWillPlay() is
161 // true if togglePlayState() will call play() or unpause() on the media element or controller.
162 bool togglePlayStateWillPlay() const;
163 void togglePlayState();
165 PassRefPtr<TextTrack> addTextTrack(const AtomicString& kind, const AtomicString& label, const AtomicString& language, ExceptionState&);
166 PassRefPtr<TextTrack> addTextTrack(const AtomicString& kind, const AtomicString& label, ExceptionState& exceptionState) { return addTextTrack(kind, label, emptyAtom, exceptionState); }
167 PassRefPtr<TextTrack> addTextTrack(const AtomicString& kind, ExceptionState& exceptionState) { return addTextTrack(kind, emptyAtom, emptyAtom, exceptionState); }
169 TextTrackList* textTracks();
170 CueList currentlyActiveCues() const { return m_currentlyActiveCues; }
172 void addTextTrack(TextTrack*);
173 void removeTextTrack(TextTrack*);
174 void closeCaptionTracksChanged();
175 void notifyMediaPlayerOfTextTrackChanges();
177 // Implements the "forget the media element's media-resource-specific tracks" algorithm in the HTML5 spec.
178 void forgetResourceSpecificTracks();
180 void didAddTrackElement(HTMLTrackElement*);
181 void didRemoveTrackElement(HTMLTrackElement*);
183 virtual void mediaPlayerDidAddTextTrack(blink::WebInbandTextTrack*) OVERRIDE FINAL;
184 virtual void mediaPlayerDidRemoveTextTrack(blink::WebInbandTextTrack*) OVERRIDE FINAL;
185 // FIXME: Remove this when WebMediaPlayerClientImpl::loadInternal does not depend on it.
186 virtual KURL mediaPlayerPosterURL() OVERRIDE { return KURL(); }
189 enum GroupKind { CaptionsAndSubtitles, Description, Chapter, Metadata, Other };
191 TrackGroup(GroupKind kind)
192 : visibleTrack(nullptr)
193 , defaultTrack(nullptr)
199 Vector<RefPtr<TextTrack> > tracks;
200 RefPtr<TextTrack> visibleTrack;
201 RefPtr<TextTrack> defaultTrack;
206 void configureTextTrackGroupForLanguage(const TrackGroup&) const;
207 void configureTextTracks();
208 void configureTextTrackGroup(const TrackGroup&);
210 bool textTracksAreReady() const;
211 enum VisibilityChangeAssumption {
212 AssumeNoVisibleChange,
215 void configureTextTrackDisplay(VisibilityChangeAssumption);
216 void updateTextTrackDisplay();
217 void textTrackReadyStateChanged(TextTrack*);
219 void textTrackKindChanged(TextTrack*);
220 void textTrackModeChanged(TextTrack*);
221 void textTrackAddCues(TextTrack*, const TextTrackCueList*);
222 void textTrackRemoveCues(TextTrack*, const TextTrackCueList*);
223 void textTrackAddCue(TextTrack*, PassRefPtr<TextTrackCue>);
224 void textTrackRemoveCue(TextTrack*, PassRefPtr<TextTrackCue>);
226 // EventTarget function.
227 // Both Node (via HTMLElement) and ActiveDOMObject define this method, which
228 // causes an ambiguity error at compile time. This class's constructor
229 // ensures that both implementations return document, so return the result
230 // of one of them here.
231 virtual ExecutionContext* executionContext() const OVERRIDE FINAL { return HTMLElement::executionContext(); }
233 bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); }
235 bool isFullscreen() const;
236 void enterFullscreen();
237 void exitFullscreen();
239 bool hasClosedCaptions() const;
240 bool closedCaptionsVisible() const;
241 void setClosedCaptionsVisible(bool);
243 MediaControls* mediaControls() const;
245 void sourceWasRemoved(HTMLSourceElement*);
246 void sourceWasAdded(HTMLSourceElement*);
248 bool isPlaying() const { return m_playing; }
250 // ActiveDOMObject functions.
251 virtual bool hasPendingActivity() const OVERRIDE FINAL;
252 virtual void contextDestroyed() OVERRIDE FINAL;
254 #if ENABLE(WEB_AUDIO)
255 MediaElementAudioSourceNode* audioSourceNode() { return m_audioSourceNode; }
256 void setAudioSourceNode(MediaElementAudioSourceNode*);
258 AudioSourceProvider* audioSourceProvider();
261 enum InvalidURLAction { DoNothing, Complain };
262 bool isSafeToLoadURL(const KURL&, InvalidURLAction);
264 MediaController* controller() const;
265 void setController(PassRefPtr<MediaController>); // Resets the MediaGroup and sets the MediaController.
267 void scheduleEvent(PassRefPtr<Event>);
269 // Current volume that should be used by the webMediaPlayer(). This method takes muted state
270 // and m_mediaController multipliers into account.
271 double playerVolume() const;
274 HTMLMediaElement(const QualifiedName&, Document&);
275 virtual ~HTMLMediaElement();
277 virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
278 virtual void finishParsingChildren() OVERRIDE FINAL;
279 virtual bool isURLAttribute(const Attribute&) const OVERRIDE;
280 virtual void attach(const AttachContext& = AttachContext()) OVERRIDE;
282 virtual void didMoveToNewDocument(Document& oldDocument) OVERRIDE;
284 enum DisplayMode { Unknown, Poster, PosterWaitingForVideo, Video };
285 DisplayMode displayMode() const { return m_displayMode; }
286 virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; }
288 void setControllerInternal(PassRefPtr<MediaController>);
290 bool ignoreTrackDisplayUpdateRequests() const { return m_ignoreTrackDisplayUpdate > 0; }
291 void beginIgnoringTrackDisplayUpdateRequests();
292 void endIgnoringTrackDisplayUpdateRequests();
295 void createMediaPlayer();
297 virtual bool alwaysCreateUserAgentShadowRoot() const OVERRIDE FINAL { return true; }
298 virtual bool areAuthorShadowsAllowed() const OVERRIDE FINAL { return false; }
300 virtual bool hasCustomFocusLogic() const OVERRIDE FINAL;
301 virtual bool supportsFocus() const OVERRIDE FINAL;
302 virtual bool isMouseFocusable() const OVERRIDE FINAL;
303 virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE;
304 virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE;
305 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE FINAL;
306 virtual void removedFrom(ContainerNode*) OVERRIDE FINAL;
307 virtual void didRecalcStyle(StyleRecalcChange) OVERRIDE FINAL;
309 virtual void didBecomeFullscreenElement() OVERRIDE FINAL;
310 virtual void willStopBeingFullscreenElement() OVERRIDE FINAL;
311 virtual bool isInteractiveContent() const OVERRIDE FINAL;
313 // ActiveDOMObject functions.
314 virtual void stop() OVERRIDE FINAL;
316 virtual void updateDisplayState() { }
318 void setReadyState(MediaPlayer::ReadyState);
319 void setNetworkState(MediaPlayer::NetworkState);
321 virtual void mediaPlayerNetworkStateChanged() OVERRIDE FINAL;
322 virtual void mediaPlayerReadyStateChanged() OVERRIDE FINAL;
323 virtual void mediaPlayerTimeChanged() OVERRIDE FINAL;
324 virtual void mediaPlayerDurationChanged() OVERRIDE FINAL;
325 virtual void mediaPlayerPlaybackStateChanged() OVERRIDE FINAL;
326 virtual void mediaPlayerRequestFullscreen() OVERRIDE FINAL;
327 virtual void mediaPlayerRequestSeek(double) OVERRIDE FINAL;
328 virtual void mediaPlayerRepaint() OVERRIDE FINAL;
329 virtual void mediaPlayerSizeChanged() OVERRIDE FINAL;
330 virtual void mediaPlayerSetWebLayer(blink::WebLayer*) OVERRIDE FINAL;
331 virtual void mediaPlayerSetOpaque(bool) OVERRIDE FINAL;
332 virtual void mediaPlayerMediaSourceOpened(blink::WebMediaSource*) OVERRIDE FINAL;
334 void loadTimerFired(Timer<HTMLMediaElement>*);
335 void progressEventTimerFired(Timer<HTMLMediaElement>*);
336 void playbackProgressTimerFired(Timer<HTMLMediaElement>*);
337 void startPlaybackProgressTimer();
338 void startProgressEventTimer();
339 void stopPeriodicTimers();
341 void seek(double time, ExceptionState&);
343 void checkIfSeekNeeded();
344 void addPlayedRange(double start, double end);
346 void scheduleTimeupdateEvent(bool periodicEvent);
347 void scheduleEvent(const AtomicString& eventName); // FIXME: Rename to scheduleNamedEvent for clarity.
350 void prepareForLoad();
352 void selectMediaResource();
353 void loadResource(const KURL&, ContentType&, const String& keySystem);
354 void setPlayerPreload();
355 void startDelayedLoad();
356 blink::WebMediaPlayer::LoadType loadType() const;
357 void scheduleNextSourceChild();
358 void loadNextSourceChild();
359 void userCancelledLoad();
360 void clearMediaPlayer(int flags);
361 void clearMediaPlayerAndAudioSourceProviderClient();
362 bool havePotentialSourceChild();
363 void noneSupported();
364 void mediaEngineError(PassRefPtr<MediaError> err);
365 void cancelPendingEventsAndCallbacks();
366 void waitForSourceChange();
367 void prepareToPlay();
369 KURL selectNextSourceChild(ContentType*, String* keySystem, InvalidURLAction);
371 void mediaLoadingFailed(MediaPlayer::NetworkState);
373 void updateActiveTextTrackCues(double);
374 HTMLTrackElement* showingTrackWithSameKind(HTMLTrackElement*) const;
376 void markCaptionAndSubtitleTracksAsUnconfigured();
378 // This does not check user gesture restrictions.
381 void allowVideoRendering();
384 void updatePlayState();
385 bool potentiallyPlaying() const;
386 bool endedPlayback() const;
387 bool stoppedDueToErrors() const;
388 bool pausedForUserInteraction() const;
389 bool couldPlayIfEnoughData() const;
391 // Pauses playback without changing any states or generating events
392 void setPausedInternal(bool);
394 void setPlaybackRateInternal(double);
396 void setShouldDelayLoadEvent(bool);
397 void invalidateCachedTime();
398 void refreshCachedTime() const;
400 bool hasMediaControls() const;
401 bool createMediaControls();
402 void configureMediaControls();
404 void prepareMediaFragmentURI();
405 void applyMediaFragmentURI();
407 virtual bool willRespondToMouseClickEvents() OVERRIDE FINAL;
408 virtual void* preDispatchEventHandler(Event*) OVERRIDE FINAL;
409 virtual void defaultEventHandler(Event*) OVERRIDE FINAL;
411 void changeNetworkStateFromLoadingToIdle();
413 const AtomicString& mediaGroup() const;
414 void setMediaGroup(const AtomicString&);
415 void updateMediaController();
416 bool isBlocked() const;
417 bool isBlockedOnMediaController() const;
418 bool isAutoplaying() const { return m_autoplaying; }
420 blink::WebMediaPlayer::CORSMode corsMode() const;
422 Timer<HTMLMediaElement> m_loadTimer;
423 Timer<HTMLMediaElement> m_progressEventTimer;
424 Timer<HTMLMediaElement> m_playbackProgressTimer;
425 RefPtr<TimeRanges> m_playedTimeRanges;
426 OwnPtr<GenericEventQueue> m_asyncEventQueue;
428 double m_playbackRate;
429 double m_defaultPlaybackRate;
430 NetworkState m_networkState;
431 ReadyState m_readyState;
432 ReadyState m_readyStateMaximum;
435 RefPtr<MediaError> m_error;
438 double m_lastSeekTime;
440 double m_previousProgressTime;
442 // Cached duration to suppress duplicate events if duration unchanged.
445 // The last time a timeupdate event was sent (wall clock).
446 double m_lastTimeUpdateEventWallTime;
448 // The last time a timeupdate event was sent in movie time.
449 double m_lastTimeUpdateEventMovieTime;
452 enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement };
453 LoadState m_loadState;
454 RefPtr<HTMLSourceElement> m_currentSourceNode;
455 RefPtr<Node> m_nextChildNodeToConsider;
457 OwnPtr<MediaPlayer> m_player;
458 blink::WebLayer* m_webLayer;
461 MediaPlayer::Preload m_preload;
463 DisplayMode m_displayMode;
465 RefPtr<HTMLMediaSource> m_mediaSource;
467 mutable double m_cachedTime;
468 mutable double m_cachedTimeWallClockUpdateTime;
469 mutable double m_minimumWallClockTimeToCacheMediaTime;
471 double m_fragmentStartTime;
472 double m_fragmentEndTime;
474 typedef unsigned PendingActionFlags;
475 PendingActionFlags m_pendingActionFlags;
477 // FIXME: MediaElement has way too many state bits.
478 bool m_userGestureRequiredForPlay : 1;
480 bool m_shouldDelayLoadEvent : 1;
481 bool m_haveFiredLoadedData : 1;
483 bool m_autoplaying : 1;
488 // data has not been loaded since sending a "stalled" event
489 bool m_sentStalledEvent : 1;
491 // time has not changed since sending an "ended" event
492 bool m_sentEndEvent : 1;
494 bool m_pausedInternal : 1;
496 bool m_closedCaptionsVisible : 1;
498 bool m_completelyLoaded : 1;
499 bool m_havePreparedToPlay : 1;
500 bool m_delayingLoadForPreloadNone : 1;
502 bool m_tracksAreReady : 1;
503 bool m_haveVisibleTextTrack : 1;
504 bool m_processingPreferenceChange : 1;
505 double m_lastTextTrackUpdateTime;
507 RefPtr<TextTrackList> m_textTracks;
508 Vector<RefPtr<TextTrack> > m_textTracksWhenResourceSelectionBegan;
510 CueIntervalTree m_cueTree;
512 CueList m_currentlyActiveCues;
513 int m_ignoreTrackDisplayUpdate;
515 #if ENABLE(WEB_AUDIO)
516 // This is a weak reference, since m_audioSourceNode holds a reference to us.
517 // The value is set just after the MediaElementAudioSourceNode is created.
518 // The value is cleared in MediaElementAudioSourceNode::~MediaElementAudioSourceNode().
519 MediaElementAudioSourceNode* m_audioSourceNode;
522 friend class MediaController;
523 RefPtr<MediaController> m_mediaController;
525 friend class Internals;
526 friend class TrackDisplayUpdateScope;
528 static URLRegistry* s_mediaStreamRegistry;
532 // Template specializations required by PodIntervalTree in debug mode.
534 struct ValueToString<double> {
535 static String string(const double value)
537 return String::number(value);
542 struct ValueToString<TextTrackCue*> {
543 static String string(TextTrackCue* const& cue)
545 return cue->toString();
550 inline bool isHTMLMediaElement(const Element& element)
552 return isHTMLAudioElement(element) || isHTMLVideoElement(element);
555 inline bool isHTMLMediaElement(const HTMLElement& element)
557 return isHTMLAudioElement(element) || isHTMLVideoElement(element);
560 DEFINE_HTMLELEMENT_TYPE_CASTS_WITH_FUNCTION(HTMLMediaElement);