1 | /* |
2 | * Copyright (C) 2007-2017 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
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. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. |
24 | */ |
25 | |
26 | #pragma once |
27 | |
28 | #if ENABLE(VIDEO) |
29 | |
30 | #include "ActiveDOMObject.h" |
31 | #include "ApplicationStateChangeListener.h" |
32 | #include "AutoplayEvent.h" |
33 | #include "DeferrableTask.h" |
34 | #include "GenericEventQueue.h" |
35 | #include "HTMLElement.h" |
36 | #include "HTMLMediaElementEnums.h" |
37 | #include "MediaCanStartListener.h" |
38 | #include "MediaControllerInterface.h" |
39 | #include "MediaElementSession.h" |
40 | #include "MediaPlayer.h" |
41 | #include "MediaProducer.h" |
42 | #include "VisibilityChangeClient.h" |
43 | #include <wtf/Function.h> |
44 | #include <wtf/LoggerHelper.h> |
45 | #include <wtf/WeakPtr.h> |
46 | |
47 | #if ENABLE(VIDEO_TRACK) |
48 | #include "AudioTrack.h" |
49 | #include "CaptionUserPreferences.h" |
50 | #include "PODIntervalTree.h" |
51 | #include "TextTrack.h" |
52 | #include "TextTrackCue.h" |
53 | #include "VTTCue.h" |
54 | #include "VideoTrack.h" |
55 | #endif |
56 | |
57 | #if USE(AUDIO_SESSION) && PLATFORM(MAC) |
58 | #include "AudioSession.h" |
59 | #endif |
60 | |
61 | #if ENABLE(ENCRYPTED_MEDIA) |
62 | #include "CDMClient.h" |
63 | #endif |
64 | |
65 | #ifndef NDEBUG |
66 | #include <wtf/StringPrintStream.h> |
67 | #endif |
68 | |
69 | namespace PAL { |
70 | class SleepDisabler; |
71 | } |
72 | |
73 | namespace WebCore { |
74 | |
75 | class AudioSourceProvider; |
76 | class AudioTrackList; |
77 | class AudioTrackPrivate; |
78 | class Blob; |
79 | class DOMException; |
80 | class DOMWrapperWorld; |
81 | class DeferredPromise; |
82 | class Event; |
83 | class HTMLSourceElement; |
84 | class HTMLTrackElement; |
85 | class InbandTextTrackPrivate; |
86 | class JSDOMGlobalObject; |
87 | class MediaController; |
88 | class MediaControls; |
89 | class MediaControlsHost; |
90 | class MediaElementAudioSourceNode; |
91 | class MediaError; |
92 | class MediaKeys; |
93 | class MediaResourceLoader; |
94 | class MediaSession; |
95 | class MediaSource; |
96 | class MediaStream; |
97 | class RenderMedia; |
98 | class ScriptController; |
99 | class ScriptExecutionContext; |
100 | class SourceBuffer; |
101 | class TextTrackList; |
102 | class TimeRanges; |
103 | class VideoPlaybackQuality; |
104 | class VideoTrackList; |
105 | class VideoTrackPrivate; |
106 | class WebKitMediaKeys; |
107 | |
108 | template<typename> class DOMPromiseDeferred; |
109 | |
110 | #if ENABLE(VIDEO_TRACK) |
111 | using CueIntervalTree = PODIntervalTree<MediaTime, TextTrackCue*>; |
112 | using CueInterval = CueIntervalTree::IntervalType; |
113 | using CueList = Vector<CueInterval>; |
114 | #endif |
115 | |
116 | using MediaProvider = Optional<Variant< |
117 | #if ENABLE(MEDIA_STREAM) |
118 | RefPtr<MediaStream>, |
119 | #endif |
120 | #if ENABLE(MEDIA_SOURCE) |
121 | RefPtr<MediaSource>, |
122 | #endif |
123 | RefPtr<Blob>>>; |
124 | |
125 | class HTMLMediaElement |
126 | : public HTMLElement |
127 | , public ActiveDOMObject |
128 | , public MediaControllerInterface |
129 | , public PlatformMediaSessionClient |
130 | , private MediaCanStartListener |
131 | , private MediaPlayerClient |
132 | , private MediaProducer |
133 | , private VisibilityChangeClient |
134 | , private ApplicationStateChangeListener |
135 | #if ENABLE(VIDEO_TRACK) |
136 | , private AudioTrackClient |
137 | , private TextTrackClient |
138 | , private VideoTrackClient |
139 | #endif |
140 | #if USE(AUDIO_SESSION) && PLATFORM(MAC) |
141 | , private AudioSession::MutedStateObserver |
142 | #endif |
143 | #if ENABLE(ENCRYPTED_MEDIA) |
144 | , private CDMClient |
145 | #endif |
146 | #if !RELEASE_LOG_DISABLED |
147 | , private LoggerHelper |
148 | #endif |
149 | { |
150 | WTF_MAKE_ISO_ALLOCATED(HTMLMediaElement); |
151 | public: |
152 | using WeakValueType = HTMLElement::WeakValueType; |
153 | using HTMLElement::weakPtrFactory; |
154 | |
155 | RefPtr<MediaPlayer> player() const { return m_player; } |
156 | |
157 | virtual bool isVideo() const { return false; } |
158 | bool hasVideo() const override { return false; } |
159 | bool hasAudio() const override; |
160 | |
161 | static HashSet<HTMLMediaElement*>& allMediaElements(); |
162 | |
163 | WEBCORE_EXPORT static RefPtr<HTMLMediaElement> bestMediaElementForShowingPlaybackControlsManager(MediaElementSession::PlaybackControlsPurpose); |
164 | |
165 | static bool isRunningDestructor(); |
166 | |
167 | WEBCORE_EXPORT void rewind(double timeDelta); |
168 | WEBCORE_EXPORT void returnToRealtime() override; |
169 | |
170 | // Eventually overloaded in HTMLVideoElement |
171 | bool supportsFullscreen(HTMLMediaElementEnums::VideoFullscreenMode) const override { return false; }; |
172 | |
173 | bool supportsScanning() const override; |
174 | |
175 | bool canSaveMediaData() const; |
176 | |
177 | bool doesHaveAttribute(const AtomString&, AtomString* value = nullptr) const override; |
178 | |
179 | PlatformLayer* platformLayer() const; |
180 | bool isVideoLayerInline(); |
181 | void setPreparedToReturnVideoLayerToInline(bool); |
182 | void waitForPreparedForInlineThen(WTF::Function<void()>&& completionHandler = [] { }); |
183 | #if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)) |
184 | void setVideoFullscreenLayer(PlatformLayer*, WTF::Function<void()>&& completionHandler = [] { }); |
185 | #ifdef __OBJC__ |
186 | PlatformLayer* videoFullscreenLayer() const { return m_videoFullscreenLayer.get(); } |
187 | #endif |
188 | void setVideoFullscreenFrame(FloatRect); |
189 | void setVideoFullscreenGravity(MediaPlayerEnums::VideoGravity); |
190 | MediaPlayerEnums::VideoGravity videoFullscreenGravity() const { return m_videoFullscreenGravity; } |
191 | #endif |
192 | |
193 | void scheduleCheckPlaybackTargetCompatability(); |
194 | void checkPlaybackTargetCompatablity(); |
195 | void scheduleResolvePendingPlayPromises(); |
196 | void scheduleRejectPendingPlayPromises(Ref<DOMException>&&); |
197 | using PlayPromiseVector = Vector<DOMPromiseDeferred<void>>; |
198 | void rejectPendingPlayPromises(PlayPromiseVector&&, Ref<DOMException>&&); |
199 | void resolvePendingPlayPromises(PlayPromiseVector&&); |
200 | void scheduleNotifyAboutPlaying(); |
201 | void notifyAboutPlaying(PlayPromiseVector&&); |
202 | |
203 | MediaPlayerEnums::MovieLoadType movieLoadType() const; |
204 | |
205 | bool inActiveDocument() const { return m_inActiveDocument; } |
206 | |
207 | Document* hostingDocument() const final { return &document(); } |
208 | |
209 | // DOM API |
210 | // error state |
211 | WEBCORE_EXPORT MediaError* error() const; |
212 | |
213 | const URL& currentSrc() const { return m_currentSrc; } |
214 | |
215 | const MediaProvider& srcObject() const { return m_mediaProvider; } |
216 | void setSrcObject(MediaProvider&&); |
217 | |
218 | WEBCORE_EXPORT void setCrossOrigin(const AtomString&); |
219 | WEBCORE_EXPORT String crossOrigin() const; |
220 | |
221 | // network state |
222 | using HTMLMediaElementEnums::NetworkState; |
223 | WEBCORE_EXPORT NetworkState networkState() const; |
224 | |
225 | WEBCORE_EXPORT String preload() const; |
226 | WEBCORE_EXPORT void setPreload(const String&); |
227 | |
228 | Ref<TimeRanges> buffered() const override; |
229 | WEBCORE_EXPORT void load(); |
230 | WEBCORE_EXPORT String canPlayType(const String& mimeType) const; |
231 | |
232 | // ready state |
233 | using HTMLMediaElementEnums::ReadyState; |
234 | ReadyState readyState() const override; |
235 | WEBCORE_EXPORT bool seeking() const; |
236 | |
237 | // playback state |
238 | WEBCORE_EXPORT double currentTime() const override; |
239 | WEBCORE_EXPORT void setCurrentTime(double) override; |
240 | void setCurrentTimeWithTolerance(double, double toleranceBefore, double toleranceAfter); |
241 | double currentTimeForBindings() const { return currentTime(); } |
242 | WEBCORE_EXPORT ExceptionOr<void> setCurrentTimeForBindings(double); |
243 | WEBCORE_EXPORT double getStartDate() const; |
244 | WEBCORE_EXPORT double duration() const override; |
245 | WEBCORE_EXPORT bool paused() const override; |
246 | double defaultPlaybackRate() const override; |
247 | void setDefaultPlaybackRate(double) override; |
248 | WEBCORE_EXPORT double playbackRate() const override; |
249 | void setPlaybackRate(double) override; |
250 | |
251 | // MediaTime versions of playback state |
252 | MediaTime currentMediaTime() const; |
253 | void setCurrentTime(const MediaTime&); |
254 | MediaTime durationMediaTime() const; |
255 | WEBCORE_EXPORT void fastSeek(const MediaTime&); |
256 | |
257 | void updatePlaybackRate(); |
258 | WEBCORE_EXPORT bool webkitPreservesPitch() const; |
259 | WEBCORE_EXPORT void setWebkitPreservesPitch(bool); |
260 | Ref<TimeRanges> played() override; |
261 | Ref<TimeRanges> seekable() const override; |
262 | double seekableTimeRangesLastModifiedTime() const; |
263 | double liveUpdateInterval() const; |
264 | WEBCORE_EXPORT bool ended() const; |
265 | bool autoplay() const; |
266 | bool isAutoplaying() const { return m_autoplaying; } |
267 | bool loop() const; |
268 | void setLoop(bool b); |
269 | |
270 | void play(DOMPromiseDeferred<void>&&); |
271 | |
272 | WEBCORE_EXPORT void play() override; |
273 | WEBCORE_EXPORT void pause() override; |
274 | WEBCORE_EXPORT void fastSeek(double); |
275 | double minFastReverseRate() const; |
276 | double maxFastForwardRate() const; |
277 | |
278 | using HTMLMediaElementEnums::BufferingPolicy; |
279 | void setBufferingPolicy(BufferingPolicy); |
280 | WEBCORE_EXPORT BufferingPolicy bufferingPolicy() const; |
281 | WEBCORE_EXPORT void purgeBufferedDataIfPossible(); |
282 | |
283 | // captions |
284 | WEBCORE_EXPORT bool webkitHasClosedCaptions() const; |
285 | WEBCORE_EXPORT bool webkitClosedCaptionsVisible() const; |
286 | WEBCORE_EXPORT void setWebkitClosedCaptionsVisible(bool); |
287 | |
288 | bool elementIsHidden() const { return m_elementIsHidden; } |
289 | |
290 | #if ENABLE(MEDIA_STATISTICS) |
291 | // Statistics |
292 | unsigned webkitAudioDecodedByteCount() const; |
293 | unsigned webkitVideoDecodedByteCount() const; |
294 | #endif |
295 | |
296 | #if ENABLE(MEDIA_SOURCE) |
297 | // Media Source. |
298 | void detachMediaSource(); |
299 | void incrementDroppedFrameCount() { ++m_droppedVideoFrames; } |
300 | size_t maximumSourceBufferSize(const SourceBuffer&) const; |
301 | #endif |
302 | |
303 | #if ENABLE(LEGACY_ENCRYPTED_MEDIA) |
304 | WebKitMediaKeys* webkitKeys() const { return m_webKitMediaKeys.get(); } |
305 | void webkitSetMediaKeys(WebKitMediaKeys*); |
306 | |
307 | void keyAdded(); |
308 | #endif |
309 | |
310 | #if ENABLE(ENCRYPTED_MEDIA) |
311 | MediaKeys* mediaKeys() const; |
312 | |
313 | void setMediaKeys(MediaKeys*, Ref<DeferredPromise>&&); |
314 | #endif |
315 | |
316 | // controls |
317 | WEBCORE_EXPORT bool controls() const; |
318 | WEBCORE_EXPORT void setControls(bool); |
319 | WEBCORE_EXPORT double volume() const override; |
320 | WEBCORE_EXPORT ExceptionOr<void> setVolume(double) override; |
321 | WEBCORE_EXPORT bool muted() const override; |
322 | WEBCORE_EXPORT void setMuted(bool) override; |
323 | |
324 | WEBCORE_EXPORT void togglePlayState(); |
325 | WEBCORE_EXPORT void beginScrubbing() override; |
326 | WEBCORE_EXPORT void endScrubbing() override; |
327 | |
328 | void beginScanning(ScanDirection) override; |
329 | void endScanning() override; |
330 | double nextScanRate(); |
331 | |
332 | WEBCORE_EXPORT bool canPlay() const override; |
333 | |
334 | double percentLoaded() const; |
335 | |
336 | bool shouldForceControlsDisplay() const; |
337 | |
338 | #if ENABLE(VIDEO_TRACK) |
339 | ExceptionOr<TextTrack&> addTextTrack(const String& kind, const String& label, const String& language); |
340 | |
341 | AudioTrackList& ensureAudioTracks(); |
342 | TextTrackList& ensureTextTracks(); |
343 | VideoTrackList& ensureVideoTracks(); |
344 | AudioTrackList* audioTracks() const { return m_audioTracks.get(); } |
345 | TextTrackList* textTracks() const { return m_textTracks.get(); } |
346 | VideoTrackList* videoTracks() const { return m_videoTracks.get(); } |
347 | |
348 | CueList currentlyActiveCues() const { return m_currentlyActiveCues; } |
349 | |
350 | void addAudioTrack(Ref<AudioTrack>&&); |
351 | void addTextTrack(Ref<TextTrack>&&); |
352 | void addVideoTrack(Ref<VideoTrack>&&); |
353 | void removeAudioTrack(Ref<AudioTrack>&&); |
354 | void removeTextTrack(Ref<TextTrack>&&, bool scheduleEvent = true); |
355 | void removeVideoTrack(Ref<VideoTrack>&&); |
356 | void forgetResourceSpecificTracks(); |
357 | void closeCaptionTracksChanged(); |
358 | void notifyMediaPlayerOfTextTrackChanges(); |
359 | |
360 | virtual void didAddTextTrack(HTMLTrackElement&); |
361 | virtual void didRemoveTextTrack(HTMLTrackElement&); |
362 | |
363 | void mediaPlayerDidAddAudioTrack(AudioTrackPrivate&) final; |
364 | void mediaPlayerDidAddTextTrack(InbandTextTrackPrivate&) final; |
365 | void mediaPlayerDidAddVideoTrack(VideoTrackPrivate&) final; |
366 | void mediaPlayerDidRemoveAudioTrack(AudioTrackPrivate&) final; |
367 | void mediaPlayerDidRemoveTextTrack(InbandTextTrackPrivate&) final; |
368 | void mediaPlayerDidRemoveVideoTrack(VideoTrackPrivate&) final; |
369 | |
370 | #if ENABLE(AVF_CAPTIONS) |
371 | Vector<RefPtr<PlatformTextTrack>> outOfBandTrackSources() final; |
372 | #endif |
373 | |
374 | struct TrackGroup; |
375 | void configureTextTrackGroupForLanguage(const TrackGroup&) const; |
376 | void scheduleConfigureTextTracks(); |
377 | void configureTextTracks(); |
378 | void configureTextTrackGroup(const TrackGroup&); |
379 | |
380 | void setSelectedTextTrack(TextTrack*); |
381 | |
382 | bool textTracksAreReady() const; |
383 | using HTMLMediaElementEnums::TextTrackVisibilityCheckType; |
384 | void configureTextTrackDisplay(TextTrackVisibilityCheckType checkType = CheckTextTrackVisibility); |
385 | void updateTextTrackDisplay(); |
386 | |
387 | // AudioTrackClient |
388 | void audioTrackEnabledChanged(AudioTrack&) final; |
389 | |
390 | void textTrackReadyStateChanged(TextTrack*); |
391 | |
392 | // TextTrackClient |
393 | void textTrackKindChanged(TextTrack&) override; |
394 | void textTrackModeChanged(TextTrack&) override; |
395 | void textTrackAddCues(TextTrack&, const TextTrackCueList&) override; |
396 | void textTrackRemoveCues(TextTrack&, const TextTrackCueList&) override; |
397 | void textTrackAddCue(TextTrack&, TextTrackCue&) override; |
398 | void textTrackRemoveCue(TextTrack&, TextTrackCue&) override; |
399 | |
400 | // VideoTrackClient |
401 | void videoTrackSelectedChanged(VideoTrack&) final; |
402 | |
403 | bool requiresTextTrackRepresentation() const; |
404 | void setTextTrackRepresentation(TextTrackRepresentation*); |
405 | void syncTextTrackBounds(); |
406 | #endif |
407 | |
408 | #if ENABLE(WIRELESS_PLAYBACK_TARGET) |
409 | void webkitShowPlaybackTargetPicker(); |
410 | bool addEventListener(const AtomString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override; |
411 | bool removeEventListener(const AtomString& eventType, EventListener&, const ListenerOptions&) override; |
412 | |
413 | void wirelessRoutesAvailableDidChange() override; |
414 | void setWirelessPlaybackTarget(Ref<MediaPlaybackTarget>&&) override; |
415 | void setShouldPlayToPlaybackTarget(bool) override; |
416 | #endif |
417 | bool isPlayingToWirelessPlaybackTarget() const override { return m_isPlayingToWirelessTarget; }; |
418 | void setIsPlayingToWirelessTarget(bool); |
419 | bool webkitCurrentPlaybackTargetIsWireless() const; |
420 | |
421 | void setPlayingOnSecondScreen(bool value); |
422 | bool isPlayingOnSecondScreen() const override { return m_playingOnSecondScreen; } |
423 | |
424 | bool isPlayingToExternalTarget() const { return isPlayingToWirelessPlaybackTarget() || isPlayingOnSecondScreen(); } |
425 | |
426 | // EventTarget function. |
427 | // Both Node (via HTMLElement) and ActiveDOMObject define this method, which |
428 | // causes an ambiguity error at compile time. This class's constructor |
429 | // ensures that both implementations return document, so return the result |
430 | // of one of them here. |
431 | using HTMLElement::scriptExecutionContext; |
432 | |
433 | bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); } |
434 | bool didPassCORSAccessCheck() const { return m_player && m_player->didPassCORSAccessCheck(); } |
435 | bool wouldTaintOrigin(const SecurityOrigin& origin) const { return m_player && m_player->wouldTaintOrigin(origin); } |
436 | |
437 | WEBCORE_EXPORT bool isFullscreen() const override; |
438 | bool isStandardFullscreen() const; |
439 | void toggleStandardFullscreenState(); |
440 | |
441 | using MediaPlayerEnums::VideoFullscreenMode; |
442 | VideoFullscreenMode fullscreenMode() const { return m_videoFullscreenMode; } |
443 | virtual void fullscreenModeChanged(VideoFullscreenMode); |
444 | |
445 | void enterFullscreen(VideoFullscreenMode); |
446 | void enterFullscreen() override; |
447 | WEBCORE_EXPORT void exitFullscreen(); |
448 | WEBCORE_EXPORT void setVideoFullscreenStandby(bool); |
449 | |
450 | bool hasClosedCaptions() const override; |
451 | bool closedCaptionsVisible() const override; |
452 | void setClosedCaptionsVisible(bool) override; |
453 | |
454 | MediaControls* mediaControls() const; |
455 | |
456 | void sourceWasRemoved(HTMLSourceElement&); |
457 | void sourceWasAdded(HTMLSourceElement&); |
458 | |
459 | void privateBrowsingStateDidChange() override; |
460 | |
461 | // Media cache management. |
462 | WEBCORE_EXPORT static void setMediaCacheDirectory(const String&); |
463 | WEBCORE_EXPORT static const String& mediaCacheDirectory(); |
464 | WEBCORE_EXPORT static HashSet<RefPtr<SecurityOrigin>> originsInMediaCache(const String&); |
465 | WEBCORE_EXPORT static void clearMediaCache(const String&, WallTime modifiedSince = { }); |
466 | WEBCORE_EXPORT static void clearMediaCacheForOrigins(const String&, const HashSet<RefPtr<SecurityOrigin>>&); |
467 | static void resetMediaEngines(); |
468 | |
469 | bool isPlaying() const { return m_playing; } |
470 | |
471 | bool hasPendingActivity() const override; |
472 | |
473 | #if ENABLE(WEB_AUDIO) |
474 | MediaElementAudioSourceNode* audioSourceNode() { return m_audioSourceNode; } |
475 | void setAudioSourceNode(MediaElementAudioSourceNode*); |
476 | |
477 | AudioSourceProvider* audioSourceProvider(); |
478 | #endif |
479 | |
480 | using HTMLMediaElementEnums::InvalidURLAction; |
481 | bool isSafeToLoadURL(const URL&, InvalidURLAction); |
482 | |
483 | const String& mediaGroup() const; |
484 | void setMediaGroup(const String&); |
485 | |
486 | MediaController* controller() const; |
487 | void setController(RefPtr<MediaController>&&); |
488 | |
489 | MediaController* controllerForBindings() const { return controller(); } |
490 | void setControllerForBindings(MediaController*); |
491 | |
492 | void enteredOrExitedFullscreen() { configureMediaControls(); } |
493 | |
494 | unsigned long long fileSize() const; |
495 | |
496 | void mediaLoadingFailed(MediaPlayerEnums::NetworkState); |
497 | void mediaLoadingFailedFatally(MediaPlayerEnums::NetworkState); |
498 | |
499 | #if ENABLE(MEDIA_SESSION) |
500 | WEBCORE_EXPORT double playerVolume() const; |
501 | |
502 | const String& kind() const { return m_kind; } |
503 | void setKind(const String& kind) { m_kind = kind; } |
504 | |
505 | MediaSession* session() const; |
506 | void setSession(MediaSession*); |
507 | |
508 | void setShouldDuck(bool); |
509 | |
510 | static HTMLMediaElement* elementWithID(uint64_t); |
511 | uint64_t elementID() const { return m_elementID; } |
512 | #endif |
513 | |
514 | RefPtr<VideoPlaybackQuality> getVideoPlaybackQuality(); |
515 | |
516 | MediaPlayerEnums::Preload preloadValue() const { return m_preload; } |
517 | MediaElementSession& mediaSession() const { return *m_mediaSession; } |
518 | |
519 | #if ENABLE(MEDIA_CONTROLS_SCRIPT) |
520 | void pageScaleFactorChanged(); |
521 | void userInterfaceLayoutDirectionChanged(); |
522 | WEBCORE_EXPORT String getCurrentMediaControlsStatus(); |
523 | |
524 | MediaControlsHost* mediaControlsHost() { return m_mediaControlsHost.get(); } |
525 | #endif |
526 | |
527 | bool isDisablingSleep() const { return m_sleepDisabler.get(); } |
528 | |
529 | double maxBufferedTime() const; |
530 | |
531 | MediaProducer::MediaStateFlags mediaState() const override; |
532 | |
533 | void layoutSizeChanged(); |
534 | void visibilityDidChange(); |
535 | |
536 | void allowsMediaDocumentInlinePlaybackChanged(); |
537 | void updateShouldPlay(); |
538 | |
539 | RenderMedia* renderer() const; |
540 | |
541 | void resetPlaybackSessionState(); |
542 | bool isVisibleInViewport() const; |
543 | bool hasEverNotifiedAboutPlaying() const; |
544 | void setShouldDelayLoadEvent(bool); |
545 | |
546 | bool hasEverHadAudio() const { return m_hasEverHadAudio; } |
547 | bool hasEverHadVideo() const { return m_hasEverHadVideo; } |
548 | |
549 | double playbackStartedTime() const { return m_playbackStartedTime; } |
550 | |
551 | bool isTemporarilyAllowingInlinePlaybackAfterFullscreen() const {return m_temporarilyAllowingInlinePlaybackAfterFullscreen; } |
552 | |
553 | void isVisibleInViewportChanged(); |
554 | void updateRateChangeRestrictions(); |
555 | |
556 | WEBCORE_EXPORT const MediaResourceLoader* lastMediaResourceLoaderForTesting() const; |
557 | |
558 | #if ENABLE(MEDIA_STREAM) |
559 | void mediaStreamCaptureStarted() { resumeAutoplaying(); } |
560 | bool hasMediaStreamSrcObject() const { return m_mediaProvider && WTF::holds_alternative<RefPtr<MediaStream>>(*m_mediaProvider); } |
561 | #endif |
562 | |
563 | bool supportsSeeking() const override; |
564 | |
565 | #if !RELEASE_LOG_DISABLED |
566 | const Logger& logger() const final { return *m_logger.get(); } |
567 | const void* logIdentifier() const final { return m_logIdentifier; } |
568 | const char* logClassName() const final { return "HTMLMediaElement" ; } |
569 | WTFLogChannel& logChannel() const final; |
570 | #endif |
571 | |
572 | bool willLog(WTFLogLevel) const; |
573 | |
574 | bool isSuspended() const final; |
575 | |
576 | WEBCORE_EXPORT void didBecomeFullscreenElement() override; |
577 | WEBCORE_EXPORT void willExitFullscreen(); |
578 | |
579 | enum class AutoplayEventPlaybackState { None, PreventedAutoplay, StartedWithUserGesture, StartedWithoutUserGesture }; |
580 | |
581 | protected: |
582 | HTMLMediaElement(const QualifiedName&, Document&, bool createdByParser); |
583 | virtual void finishInitialization(); |
584 | virtual ~HTMLMediaElement(); |
585 | |
586 | void parseAttribute(const QualifiedName&, const AtomString&) override; |
587 | void finishParsingChildren() override; |
588 | bool isURLAttribute(const Attribute&) const override; |
589 | void willAttachRenderers() override; |
590 | void didAttachRenderers() override; |
591 | void willDetachRenderers() override; |
592 | void didDetachRenderers() override; |
593 | |
594 | void didMoveToNewDocument(Document& oldDocument, Document& newDocument) override; |
595 | |
596 | enum DisplayMode { Unknown, None, Poster, PosterWaitingForVideo, Video }; |
597 | DisplayMode displayMode() const { return m_displayMode; } |
598 | virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; } |
599 | |
600 | bool isMediaElement() const final { return true; } |
601 | |
602 | #if ENABLE(VIDEO_TRACK) |
603 | bool ignoreTrackDisplayUpdateRequests() const { return m_ignoreTrackDisplayUpdate > 0 || !m_textTracks || !m_cueTree.size(); } |
604 | void beginIgnoringTrackDisplayUpdateRequests(); |
605 | void endIgnoringTrackDisplayUpdateRequests(); |
606 | #endif |
607 | |
608 | RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override; |
609 | |
610 | #if ENABLE(MEDIA_CONTROLS_SCRIPT) |
611 | bool mediaControlsDependOnPageScaleFactor() const { return m_mediaControlsDependOnPageScaleFactor; } |
612 | void setMediaControlsDependOnPageScaleFactor(bool); |
613 | void updateMediaControlsAfterPresentationModeChange(); |
614 | #endif |
615 | |
616 | void scheduleEvent(const AtomString& eventName); |
617 | |
618 | private: |
619 | void createMediaPlayer(); |
620 | |
621 | bool supportsFocus() const override; |
622 | bool isMouseFocusable() const override; |
623 | bool rendererIsNeeded(const RenderStyle&) override; |
624 | bool childShouldCreateRenderer(const Node&) const override; |
625 | InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) override; |
626 | void didFinishInsertingNode() override; |
627 | void removedFromAncestor(RemovalType, ContainerNode&) override; |
628 | void didRecalcStyle(Style::Change) override; |
629 | |
630 | void willBecomeFullscreenElement() override; |
631 | void willStopBeingFullscreenElement() override; |
632 | |
633 | // ActiveDOMObject API. |
634 | const char* activeDOMObjectName() const override; |
635 | bool canSuspendForDocumentSuspension() const override; |
636 | void suspend(ReasonForSuspension) override; |
637 | void resume() override; |
638 | void stop() override; |
639 | void stopWithoutDestroyingMediaPlayer(); |
640 | void contextDestroyed() override; |
641 | |
642 | void mediaVolumeDidChange() override; |
643 | |
644 | void visibilityStateChanged() override; |
645 | |
646 | virtual void updateDisplayState() { } |
647 | |
648 | void setReadyState(MediaPlayerEnums::ReadyState); |
649 | void setNetworkState(MediaPlayerEnums::NetworkState); |
650 | |
651 | double effectivePlaybackRate() const; |
652 | double requestedPlaybackRate() const; |
653 | |
654 | void mediaPlayerNetworkStateChanged(MediaPlayer*) override; |
655 | void mediaPlayerReadyStateChanged(MediaPlayer*) override; |
656 | void mediaPlayerTimeChanged(MediaPlayer*) override; |
657 | void mediaPlayerVolumeChanged(MediaPlayer*) override; |
658 | void mediaPlayerMuteChanged(MediaPlayer*) override; |
659 | void mediaPlayerDurationChanged(MediaPlayer*) override; |
660 | void mediaPlayerRateChanged(MediaPlayer*) override; |
661 | void mediaPlayerPlaybackStateChanged(MediaPlayer*) override; |
662 | void mediaPlayerSawUnsupportedTracks(MediaPlayer*) override; |
663 | void mediaPlayerResourceNotSupported(MediaPlayer*) override; |
664 | void mediaPlayerRepaint(MediaPlayer*) override; |
665 | void mediaPlayerSizeChanged(MediaPlayer*) override; |
666 | bool mediaPlayerRenderingCanBeAccelerated(MediaPlayer*) override; |
667 | void mediaPlayerRenderingModeChanged(MediaPlayer*) override; |
668 | bool mediaPlayerAcceleratedCompositingEnabled() override; |
669 | void mediaPlayerEngineUpdated(MediaPlayer*) override; |
670 | |
671 | void scheduleMediaEngineWasUpdated(); |
672 | void mediaEngineWasUpdated(); |
673 | |
674 | void mediaPlayerFirstVideoFrameAvailable(MediaPlayer*) override; |
675 | void mediaPlayerCharacteristicChanged(MediaPlayer*) override; |
676 | |
677 | #if ENABLE(LEGACY_ENCRYPTED_MEDIA) |
678 | RefPtr<ArrayBuffer> mediaPlayerCachedKeyForKeyId(const String& keyId) const override; |
679 | bool mediaPlayerKeyNeeded(MediaPlayer*, Uint8Array*) override; |
680 | String mediaPlayerMediaKeysStorageDirectory() const override; |
681 | #endif |
682 | |
683 | #if ENABLE(ENCRYPTED_MEDIA) |
684 | void mediaPlayerInitializationDataEncountered(const String&, RefPtr<ArrayBuffer>&&) final; |
685 | void mediaPlayerWaitingForKeyChanged() final; |
686 | |
687 | void attemptToDecrypt(); |
688 | void attemptToResumePlaybackIfNecessary(); |
689 | |
690 | // CDMClient |
691 | void cdmClientAttemptToResumePlaybackIfNecessary() final; |
692 | #endif |
693 | |
694 | #if ENABLE(WIRELESS_PLAYBACK_TARGET) |
695 | void mediaPlayerCurrentPlaybackTargetIsWirelessChanged(MediaPlayer*) override; |
696 | void enqueuePlaybackTargetAvailabilityChangedEvent(); |
697 | |
698 | using EventTarget::dispatchEvent; |
699 | void dispatchEvent(Event&) override; |
700 | #endif |
701 | |
702 | #if ENABLE(MEDIA_SESSION) |
703 | void setSessionInternal(MediaSession&); |
704 | #endif |
705 | |
706 | String mediaPlayerReferrer() const override; |
707 | String mediaPlayerUserAgent() const override; |
708 | |
709 | void mediaPlayerEnterFullscreen() override; |
710 | void mediaPlayerExitFullscreen() override; |
711 | bool mediaPlayerIsFullscreen() const override; |
712 | bool mediaPlayerIsFullscreenPermitted() const override; |
713 | bool mediaPlayerIsVideo() const override; |
714 | LayoutRect mediaPlayerContentBoxRect() const override; |
715 | float mediaPlayerContentsScale() const override; |
716 | void mediaPlayerSetSize(const IntSize&) override; |
717 | void mediaPlayerPause() override; |
718 | void mediaPlayerPlay() override; |
719 | bool mediaPlayerPlatformVolumeConfigurationRequired() const override; |
720 | bool mediaPlayerIsPaused() const override; |
721 | bool mediaPlayerIsLooping() const override; |
722 | CachedResourceLoader* mediaPlayerCachedResourceLoader() override; |
723 | RefPtr<PlatformMediaResourceLoader> mediaPlayerCreateResourceLoader() override; |
724 | bool mediaPlayerShouldUsePersistentCache() const override; |
725 | const String& mediaPlayerMediaCacheDirectory() const override; |
726 | |
727 | #if PLATFORM(WIN) && USE(AVFOUNDATION) |
728 | GraphicsDeviceAdapter* mediaPlayerGraphicsDeviceAdapter(const MediaPlayer*) const override; |
729 | #endif |
730 | |
731 | void mediaPlayerActiveSourceBuffersChanged(const MediaPlayer*) override; |
732 | |
733 | void mediaPlayerHandlePlaybackCommand(PlatformMediaSession::RemoteControlCommandType command) override { didReceiveRemoteControlCommand(command, nullptr); } |
734 | String sourceApplicationIdentifier() const override; |
735 | String mediaPlayerSourceApplicationIdentifier() const override { return sourceApplicationIdentifier(); } |
736 | Vector<String> mediaPlayerPreferredAudioCharacteristics() const override; |
737 | |
738 | #if PLATFORM(IOS_FAMILY) |
739 | String mediaPlayerNetworkInterfaceName() const override; |
740 | bool mediaPlayerGetRawCookies(const URL&, Vector<Cookie>&) const override; |
741 | #endif |
742 | |
743 | bool mediaPlayerIsInMediaDocument() const final; |
744 | void mediaPlayerEngineFailedToLoad() const final; |
745 | |
746 | double mediaPlayerRequestedPlaybackRate() const final; |
747 | VideoFullscreenMode mediaPlayerFullscreenMode() const final { return fullscreenMode(); } |
748 | bool mediaPlayerIsVideoFullscreenStandby() const final { return m_videoFullscreenStandby; } |
749 | bool mediaPlayerShouldDisableSleep() const final { return shouldDisableSleep() == SleepType::Display; } |
750 | bool mediaPlayerShouldCheckHardwareSupport() const final; |
751 | const Vector<ContentType>& mediaContentTypesRequiringHardwareSupport() const final; |
752 | |
753 | #if USE(GSTREAMER) |
754 | void requestInstallMissingPlugins(const String& details, const String& description, MediaPlayerRequestInstallMissingPluginsCallback&) final; |
755 | #endif |
756 | |
757 | void pendingActionTimerFired(); |
758 | void progressEventTimerFired(); |
759 | void playbackProgressTimerFired(); |
760 | void scanTimerFired(); |
761 | void seekTask(); |
762 | void startPlaybackProgressTimer(); |
763 | void startProgressEventTimer(); |
764 | void stopPeriodicTimers(); |
765 | void cancelPendingTasks(); |
766 | void closeTaskQueues(); |
767 | |
768 | void seek(const MediaTime&); |
769 | void seekInternal(const MediaTime&); |
770 | void seekWithTolerance(const MediaTime&, const MediaTime& negativeTolerance, const MediaTime& positiveTolerance, bool fromDOM); |
771 | void finishSeek(); |
772 | void clearSeeking(); |
773 | void addPlayedRange(const MediaTime& start, const MediaTime& end); |
774 | |
775 | void scheduleTimeupdateEvent(bool periodicEvent); |
776 | virtual void scheduleResizeEvent() { } |
777 | virtual void scheduleResizeEventIfSizeChanged() { } |
778 | |
779 | void selectMediaResource(); |
780 | void loadResource(const URL&, ContentType&, const String& keySystem); |
781 | void scheduleNextSourceChild(); |
782 | void loadNextSourceChild(); |
783 | void userCancelledLoad(); |
784 | void clearMediaPlayer(); |
785 | bool havePotentialSourceChild(); |
786 | void noneSupported(); |
787 | void cancelPendingEventsAndCallbacks(); |
788 | void waitForSourceChange(); |
789 | void prepareToPlay(); |
790 | |
791 | URL selectNextSourceChild(ContentType*, String* keySystem, InvalidURLAction); |
792 | |
793 | #if ENABLE(VIDEO_TRACK) |
794 | void updateActiveTextTrackCues(const MediaTime&); |
795 | HTMLTrackElement* showingTrackWithSameKind(HTMLTrackElement*) const; |
796 | |
797 | enum ReconfigureMode { |
798 | Immediately, |
799 | AfterDelay, |
800 | }; |
801 | void markCaptionAndSubtitleTracksAsUnconfigured(ReconfigureMode); |
802 | void captionPreferencesChanged() override; |
803 | CaptionUserPreferences::CaptionDisplayMode captionDisplayMode(); |
804 | #endif |
805 | |
806 | // These "internal" functions do not check user gesture restrictions. |
807 | void playInternal(); |
808 | void pauseInternal(); |
809 | |
810 | void prepareForLoad(); |
811 | void allowVideoRendering(); |
812 | |
813 | bool processingMediaPlayerCallback() const { return m_processingMediaPlayerCallback > 0; } |
814 | void beginProcessingMediaPlayerCallback() { ++m_processingMediaPlayerCallback; } |
815 | void endProcessingMediaPlayerCallback() { ASSERT(m_processingMediaPlayerCallback); --m_processingMediaPlayerCallback; } |
816 | |
817 | void scheduleUpdatePlayState(); |
818 | void updatePlayState(); |
819 | |
820 | void updateVolume(); |
821 | void setPlaying(bool); |
822 | bool potentiallyPlaying() const; |
823 | bool endedPlayback() const; |
824 | bool stoppedDueToErrors() const; |
825 | bool pausedForUserInteraction() const; |
826 | bool couldPlayIfEnoughData() const; |
827 | void dispatchPlayPauseEventsIfNeedsQuirks(); |
828 | SuccessOr<MediaPlaybackDenialReason> canTransitionFromAutoplayToPlay() const; |
829 | |
830 | void setAutoplayEventPlaybackState(AutoplayEventPlaybackState); |
831 | void userDidInterfereWithAutoplay(); |
832 | void handleAutoplayEvent(AutoplayEvent); |
833 | |
834 | MediaTime minTimeSeekable() const; |
835 | MediaTime maxTimeSeekable() const; |
836 | |
837 | // Pauses playback without changing any states or generating events |
838 | void setPausedInternal(bool); |
839 | |
840 | void setPlaybackRateInternal(double); |
841 | |
842 | void mediaCanStart(Document&) final; |
843 | |
844 | void invalidateCachedTime() const; |
845 | void refreshCachedTime() const; |
846 | |
847 | bool hasMediaControls() const; |
848 | bool createMediaControls(); |
849 | void configureMediaControls(); |
850 | |
851 | void prepareMediaFragmentURI(); |
852 | void applyMediaFragmentURI(); |
853 | |
854 | void changeNetworkStateFromLoadingToIdle(); |
855 | |
856 | void removeBehaviorRestrictionsAfterFirstUserGesture(MediaElementSession::BehaviorRestrictions mask = MediaElementSession::AllRestrictions); |
857 | |
858 | void updateMediaController(); |
859 | bool isBlocked() const; |
860 | bool isBlockedOnMediaController() const; |
861 | bool hasCurrentSrc() const override { return !m_currentSrc.isEmpty(); } |
862 | bool isLiveStream() const override { return movieLoadType() == MediaPlayerEnums::LiveStream; } |
863 | |
864 | void updateSleepDisabling(); |
865 | enum class SleepType { |
866 | None, |
867 | Display, |
868 | System, |
869 | }; |
870 | SleepType shouldDisableSleep() const; |
871 | |
872 | #if ENABLE(MEDIA_CONTROLS_SCRIPT) |
873 | void didAddUserAgentShadowRoot(ShadowRoot&) override; |
874 | DOMWrapperWorld& ensureIsolatedWorld(); |
875 | bool ensureMediaControlsInjectedScript(); |
876 | #endif |
877 | |
878 | PlatformMediaSession::MediaType mediaType() const override; |
879 | PlatformMediaSession::MediaType presentationType() const override; |
880 | PlatformMediaSession::DisplayType displayType() const override; |
881 | PlatformMediaSession::CharacteristicsFlags characteristics() const final; |
882 | |
883 | void suspendPlayback() override; |
884 | void resumeAutoplaying() override; |
885 | void mayResumePlayback(bool shouldResume) override; |
886 | uint64_t mediaSessionUniqueIdentifier() const final; |
887 | String mediaSessionTitle() const override; |
888 | double mediaSessionDuration() const override { return duration(); } |
889 | double mediaSessionCurrentTime() const override { return currentTime(); } |
890 | bool canReceiveRemoteControlCommands() const override { return true; } |
891 | void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType, const PlatformMediaSession::RemoteCommandArgument*) override; |
892 | bool shouldOverrideBackgroundPlaybackRestriction(PlatformMediaSession::InterruptionType) const override; |
893 | bool shouldOverrideBackgroundLoadingRestriction() const override; |
894 | bool canProduceAudio() const final; |
895 | bool processingUserGestureForMedia() const final; |
896 | bool hasMediaStreamSource() const final; |
897 | |
898 | void pageMutedStateDidChange() override; |
899 | |
900 | #if USE(AUDIO_SESSION) && PLATFORM(MAC) |
901 | void hardwareMutedStateDidChange(AudioSession*) final; |
902 | #endif |
903 | |
904 | bool effectiveMuted() const; |
905 | |
906 | void registerWithDocument(Document&); |
907 | void unregisterWithDocument(Document&); |
908 | |
909 | void updateCaptionContainer(); |
910 | void ensureMediaControlsShadowRoot(); |
911 | |
912 | using JSSetupFunction = WTF::Function<bool(JSDOMGlobalObject&, JSC::ExecState&, ScriptController&, DOMWrapperWorld&)>; |
913 | bool setupAndCallJS(const JSSetupFunction&); |
914 | |
915 | #if ENABLE(WIRELESS_PLAYBACK_TARGET) |
916 | void prepareForDocumentSuspension() final; |
917 | void resumeFromDocumentSuspension() final; |
918 | |
919 | void scheduleUpdateMediaState(); |
920 | void updateMediaState(); |
921 | bool hasPlaybackTargetAvailabilityListeners() const { return m_hasPlaybackTargetAvailabilityListeners; } |
922 | #endif |
923 | |
924 | bool isVideoTooSmallForInlinePlayback(); |
925 | void updateShouldAutoplay(); |
926 | |
927 | void pauseAfterDetachedTask(); |
928 | void updatePlaybackControlsManager(); |
929 | void schedulePlaybackControlsManagerUpdate(); |
930 | void playbackControlsManagerBehaviorRestrictionsTimerFired(); |
931 | |
932 | void updateRenderer(); |
933 | |
934 | void updatePageScaleFactorJSProperty(); |
935 | void updateUsesLTRUserInterfaceLayoutDirectionJSProperty(); |
936 | void setControllerJSProperty(const char*, JSC::JSValue); |
937 | |
938 | void addBehaviorRestrictionsOnEndIfNecessary(); |
939 | void handleSeekToPlaybackPosition(double); |
940 | void seekToPlaybackPositionEndedTimerFired(); |
941 | |
942 | void applicationWillResignActive() final; |
943 | void applicationDidBecomeActive() final; |
944 | |
945 | void setInActiveDocument(bool); |
946 | |
947 | #if !RELEASE_LOG_DISABLED |
948 | const void* mediaPlayerLogIdentifier() final { return logIdentifier(); } |
949 | const Logger& mediaPlayerLogger() final { return logger(); } |
950 | #endif |
951 | |
952 | Timer m_progressEventTimer; |
953 | Timer m_playbackProgressTimer; |
954 | Timer m_scanTimer; |
955 | Timer m_playbackControlsManagerBehaviorRestrictionsTimer; |
956 | Timer m_seekToPlaybackPositionEndedTimer; |
957 | DeferrableTask<Timer> m_configureTextTracksTask; |
958 | DeferrableTask<Timer> m_checkPlaybackTargetCompatablityTask; |
959 | DeferrableTask<Timer> m_updateMediaStateTask; |
960 | DeferrableTask<Timer> m_mediaEngineUpdatedTask; |
961 | DeferrableTask<Timer> m_updatePlayStateTask; |
962 | DeferrableTask<Timer> m_resumeTaskQueue; |
963 | DeferrableTask<Timer> m_seekTaskQueue; |
964 | DeferrableTask<Timer> m_playbackControlsManagerBehaviorRestrictionsQueue; |
965 | GenericTaskQueue<Timer> m_promiseTaskQueue; |
966 | GenericTaskQueue<Timer> m_pauseAfterDetachedTaskQueue; |
967 | GenericTaskQueue<Timer> m_resourceSelectionTaskQueue; |
968 | GenericTaskQueue<Timer> m_visibilityChangeTaskQueue; |
969 | GenericTaskQueue<Timer> m_fullscreenTaskQueue; |
970 | GenericTaskQueue<Timer> m_playbackTargetIsWirelessQueue; |
971 | RefPtr<TimeRanges> m_playedTimeRanges; |
972 | GenericEventQueue m_asyncEventQueue; |
973 | #if PLATFORM(IOS_FAMILY) |
974 | DeferrableTask<Timer> m_volumeRevertTaskQueue; |
975 | #endif |
976 | |
977 | PlayPromiseVector m_pendingPlayPromises; |
978 | |
979 | double m_requestedPlaybackRate { 1 }; |
980 | double m_reportedPlaybackRate { 1 }; |
981 | double m_defaultPlaybackRate { 1 }; |
982 | bool m_webkitPreservesPitch { true }; |
983 | NetworkState m_networkState { NETWORK_EMPTY }; |
984 | ReadyState m_readyState { HAVE_NOTHING }; |
985 | ReadyState m_readyStateMaximum { HAVE_NOTHING }; |
986 | URL m_currentSrc; |
987 | |
988 | RefPtr<MediaError> m_error; |
989 | |
990 | struct PendingSeek { |
991 | PendingSeek(const MediaTime& now, const MediaTime& targetTime, const MediaTime& negativeTolerance, const MediaTime& positiveTolerance) |
992 | : now(now) |
993 | , targetTime(targetTime) |
994 | , negativeTolerance(negativeTolerance) |
995 | , positiveTolerance(positiveTolerance) |
996 | { |
997 | } |
998 | MediaTime now; |
999 | MediaTime targetTime; |
1000 | MediaTime negativeTolerance; |
1001 | MediaTime positiveTolerance; |
1002 | }; |
1003 | std::unique_ptr<PendingSeek> m_pendingSeek; |
1004 | SeekType m_pendingSeekType { NoSeek }; |
1005 | |
1006 | double m_volume { 1 }; |
1007 | bool m_volumeInitialized { false }; |
1008 | MediaTime m_lastSeekTime; |
1009 | |
1010 | MonotonicTime m_previousProgressTime { MonotonicTime::infinity() }; |
1011 | double m_playbackStartedTime { 0 }; |
1012 | |
1013 | // The last time a timeupdate event was sent (based on monotonic clock). |
1014 | MonotonicTime m_clockTimeAtLastUpdateEvent; |
1015 | |
1016 | // The last time a timeupdate event was sent in movie time. |
1017 | MediaTime m_lastTimeUpdateEventMovieTime; |
1018 | |
1019 | // Loading state. |
1020 | enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement }; |
1021 | LoadState m_loadState { WaitingForSource }; |
1022 | RefPtr<HTMLSourceElement> m_currentSourceNode; |
1023 | RefPtr<HTMLSourceElement> m_nextChildNodeToConsider; |
1024 | |
1025 | VideoFullscreenMode m_videoFullscreenMode { VideoFullscreenModeNone }; |
1026 | bool m_videoFullscreenStandby { false }; |
1027 | bool m_preparedForInline; |
1028 | WTF::Function<void()> m_preparedForInlineCompletionHandler; |
1029 | |
1030 | bool m_temporarilyAllowingInlinePlaybackAfterFullscreen { false }; |
1031 | |
1032 | #if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)) |
1033 | RetainPtr<PlatformLayer> m_videoFullscreenLayer; |
1034 | FloatRect m_videoFullscreenFrame; |
1035 | MediaPlayerEnums::VideoGravity m_videoFullscreenGravity { MediaPlayer::VideoGravityResizeAspect }; |
1036 | #endif |
1037 | |
1038 | RefPtr<MediaPlayer> m_player; |
1039 | |
1040 | MediaPlayerEnums::Preload m_preload { MediaPlayer::Auto }; |
1041 | |
1042 | DisplayMode m_displayMode { Unknown }; |
1043 | |
1044 | // Counter incremented while processing a callback from the media player, so we can avoid |
1045 | // calling the media engine recursively. |
1046 | int m_processingMediaPlayerCallback { 0 }; |
1047 | |
1048 | #if ENABLE(MEDIA_SESSION) |
1049 | String m_kind; |
1050 | RefPtr<MediaSession> m_session; |
1051 | bool m_shouldDuck { false }; |
1052 | uint64_t m_elementID; |
1053 | #endif |
1054 | |
1055 | #if ENABLE(MEDIA_SOURCE) |
1056 | RefPtr<MediaSource> m_mediaSource; |
1057 | unsigned m_droppedVideoFrames { 0 }; |
1058 | #endif |
1059 | |
1060 | mutable MediaTime m_cachedTime; |
1061 | mutable MonotonicTime m_clockTimeAtLastCachedTimeUpdate; |
1062 | mutable MonotonicTime m_minimumClockTimeToUpdateCachedTime; |
1063 | |
1064 | MediaTime m_fragmentStartTime; |
1065 | MediaTime m_fragmentEndTime; |
1066 | |
1067 | using PendingActionFlags = unsigned; |
1068 | PendingActionFlags m_pendingActionFlags { 0 }; |
1069 | |
1070 | enum ActionAfterScanType { Nothing, Play, Pause }; |
1071 | ActionAfterScanType m_actionAfterScan { Nothing }; |
1072 | |
1073 | enum ScanType { Seek, Scan }; |
1074 | ScanType m_scanType { Scan }; |
1075 | ScanDirection m_scanDirection { Forward }; |
1076 | |
1077 | BufferingPolicy m_bufferingPolicy { BufferingPolicy::Default }; |
1078 | |
1079 | bool m_firstTimePlaying : 1; |
1080 | bool m_playing : 1; |
1081 | bool m_isWaitingUntilMediaCanStart : 1; |
1082 | bool m_shouldDelayLoadEvent : 1; |
1083 | bool m_haveFiredLoadedData : 1; |
1084 | bool m_inActiveDocument : 1; |
1085 | bool m_autoplaying : 1; |
1086 | bool m_muted : 1; |
1087 | bool m_explicitlyMuted : 1; |
1088 | bool m_initiallyMuted : 1; |
1089 | bool m_paused : 1; |
1090 | bool m_seeking : 1; |
1091 | bool m_seekRequested : 1; |
1092 | |
1093 | // data has not been loaded since sending a "stalled" event |
1094 | bool m_sentStalledEvent : 1; |
1095 | |
1096 | // time has not changed since sending an "ended" event |
1097 | bool m_sentEndEvent : 1; |
1098 | |
1099 | bool m_pausedInternal : 1; |
1100 | |
1101 | bool m_closedCaptionsVisible : 1; |
1102 | bool m_webkitLegacyClosedCaptionOverride : 1; |
1103 | bool m_completelyLoaded : 1; |
1104 | bool m_havePreparedToPlay : 1; |
1105 | bool m_parsingInProgress : 1; |
1106 | bool m_elementIsHidden : 1; |
1107 | bool m_elementWasRemovedFromDOM : 1; |
1108 | bool m_creatingControls : 1; |
1109 | bool m_receivedLayoutSizeChanged : 1; |
1110 | bool m_hasEverNotifiedAboutPlaying : 1; |
1111 | |
1112 | bool m_hasEverHadAudio : 1; |
1113 | bool m_hasEverHadVideo : 1; |
1114 | |
1115 | #if ENABLE(MEDIA_CONTROLS_SCRIPT) |
1116 | bool m_mediaControlsDependOnPageScaleFactor : 1; |
1117 | bool m_haveSetUpCaptionContainer : 1; |
1118 | #endif |
1119 | |
1120 | bool m_isScrubbingRemotely : 1; |
1121 | bool m_waitingToEnterFullscreen : 1; |
1122 | |
1123 | #if ENABLE(VIDEO_TRACK) |
1124 | bool m_tracksAreReady : 1; |
1125 | bool m_haveVisibleTextTrack : 1; |
1126 | bool m_processingPreferenceChange : 1; |
1127 | |
1128 | AutoplayEventPlaybackState m_autoplayEventPlaybackState { AutoplayEventPlaybackState::None }; |
1129 | |
1130 | String m_subtitleTrackLanguage; |
1131 | MediaTime m_lastTextTrackUpdateTime { -1, 1 }; |
1132 | |
1133 | Optional<CaptionUserPreferences::CaptionDisplayMode> m_captionDisplayMode; |
1134 | |
1135 | RefPtr<AudioTrackList> m_audioTracks; |
1136 | RefPtr<TextTrackList> m_textTracks; |
1137 | RefPtr<VideoTrackList> m_videoTracks; |
1138 | Vector<RefPtr<TextTrack>> m_textTracksWhenResourceSelectionBegan; |
1139 | |
1140 | CueIntervalTree m_cueTree; |
1141 | |
1142 | CueList m_currentlyActiveCues; |
1143 | int m_ignoreTrackDisplayUpdate { 0 }; |
1144 | |
1145 | bool m_requireCaptionPreferencesChangedCallbacks { false }; |
1146 | #endif |
1147 | |
1148 | #if ENABLE(WEB_AUDIO) |
1149 | // This is a weak reference, since m_audioSourceNode holds a reference to us. |
1150 | // The value is set just after the MediaElementAudioSourceNode is created. |
1151 | // The value is cleared in MediaElementAudioSourceNode::~MediaElementAudioSourceNode(). |
1152 | MediaElementAudioSourceNode* m_audioSourceNode { nullptr }; |
1153 | #endif |
1154 | |
1155 | String m_mediaGroup; |
1156 | friend class MediaController; |
1157 | RefPtr<MediaController> m_mediaController; |
1158 | |
1159 | std::unique_ptr<PAL::SleepDisabler> m_sleepDisabler; |
1160 | |
1161 | WeakPtr<const MediaResourceLoader> m_lastMediaResourceLoaderForTesting; |
1162 | |
1163 | friend class TrackDisplayUpdateScope; |
1164 | |
1165 | RefPtr<Blob> m_blob; |
1166 | MediaProvider m_mediaProvider; |
1167 | |
1168 | #if ENABLE(LEGACY_ENCRYPTED_MEDIA) |
1169 | RefPtr<WebKitMediaKeys> m_webKitMediaKeys; |
1170 | #endif |
1171 | #if ENABLE(ENCRYPTED_MEDIA) |
1172 | RefPtr<MediaKeys> m_mediaKeys; |
1173 | bool m_attachingMediaKeys { false }; |
1174 | bool m_playbackBlockedWaitingForKey { false }; |
1175 | GenericTaskQueue<Timer> m_encryptedMediaQueue; |
1176 | #endif |
1177 | |
1178 | std::unique_ptr<MediaElementSession> m_mediaSession; |
1179 | size_t { 0 }; |
1180 | |
1181 | #if !RELEASE_LOG_DISABLED |
1182 | RefPtr<Logger> m_logger; |
1183 | const void* m_logIdentifier; |
1184 | #endif |
1185 | |
1186 | #if ENABLE(MEDIA_CONTROLS_SCRIPT) |
1187 | friend class MediaControlsHost; |
1188 | RefPtr<MediaControlsHost> m_mediaControlsHost; |
1189 | RefPtr<DOMWrapperWorld> m_isolatedWorld; |
1190 | #endif |
1191 | |
1192 | #if ENABLE(MEDIA_STREAM) |
1193 | RefPtr<MediaStream> m_mediaStreamSrcObject; |
1194 | bool m_settingMediaStreamSrcObject { false }; |
1195 | #endif |
1196 | |
1197 | #if ENABLE(WIRELESS_PLAYBACK_TARGET) |
1198 | MediaProducer::MediaStateFlags m_mediaState { MediaProducer::IsNotPlaying }; |
1199 | bool m_hasPlaybackTargetAvailabilityListeners { false }; |
1200 | bool m_failedToPlayToWirelessTarget { false }; |
1201 | #endif |
1202 | |
1203 | bool m_isPlayingToWirelessTarget { false }; |
1204 | bool m_playingOnSecondScreen { false }; |
1205 | bool m_removedBehaviorRestrictionsAfterFirstUserGesture { false }; |
1206 | }; |
1207 | |
1208 | String convertEnumerationToString(HTMLMediaElement::AutoplayEventPlaybackState); |
1209 | |
1210 | } // namespace WebCore |
1211 | |
1212 | namespace WTF { |
1213 | |
1214 | template<> struct LogArgument<WebCore::HTMLMediaElement::AutoplayEventPlaybackState> { |
1215 | static String toString(WebCore::HTMLMediaElement::AutoplayEventPlaybackState reason) { return convertEnumerationToString(reason); } |
1216 | }; |
1217 | |
1218 | #if ENABLE(VIDEO_TRACK) && !defined(NDEBUG) |
1219 | |
1220 | // Template specialization required by PodIntervalTree in debug mode. |
1221 | template<> struct ValueToString<WebCore::TextTrackCue*> { |
1222 | static String string(const WebCore::TextTrackCue* cue) { return cue->debugString(); } |
1223 | }; |
1224 | |
1225 | #endif |
1226 | |
1227 | #ifndef NDEBUG |
1228 | |
1229 | template<> struct ValueToString<MediaTime> { |
1230 | static String string(const MediaTime& time) { return toString(time); } |
1231 | }; |
1232 | |
1233 | #endif |
1234 | |
1235 | } // namespace WTF |
1236 | |
1237 | SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::HTMLMediaElement) |
1238 | static bool isType(const WebCore::Element& element) { return element.isMediaElement(); } |
1239 | static bool isType(const WebCore::Node& node) { return is<WebCore::Element>(node) && isType(downcast<WebCore::Element>(node)); } |
1240 | SPECIALIZE_TYPE_TRAITS_END() |
1241 | |
1242 | #endif |
1243 | |