Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1090 lines (850 sloc) 38.5 KB
/*
* Copyright (C) 2007-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#if ENABLE(VIDEO)
#include "ActiveDOMObject.h"
#include "GenericEventQueue.h"
#include "GenericTaskQueue.h"
#include "HTMLElement.h"
#include "HTMLMediaElementEnums.h"
#include "MediaCanStartListener.h"
#include "MediaControllerInterface.h"
#include "MediaElementSession.h"
#include "MediaProducer.h"
#include "UserInterfaceLayoutDirection.h"
#if ENABLE(VIDEO_TRACK)
#include "AudioTrack.h"
#include "CaptionUserPreferences.h"
#include "PODIntervalTree.h"
#include "TextTrack.h"
#include "TextTrackCue.h"
#include "VTTCue.h"
#include "VideoTrack.h"
#endif
#ifndef NDEBUG
#include <wtf/StringPrintStream.h>
#endif
namespace WebCore {
class AudioSourceProvider;
class AudioTrackList;
class AudioTrackPrivate;
class Blob;
class DOMError;
class DeferredPromise;
class DisplaySleepDisabler;
class Event;
class HTMLSourceElement;
class HTMLTrackElement;
class InbandTextTrackPrivate;
class MediaController;
class MediaControls;
class MediaControlsHost;
class MediaElementAudioSourceNode;
class MediaError;
class MediaKeys;
class MediaPlayer;
class MediaSession;
class MediaSource;
class MediaStream;
class RenderMedia;
class ScriptExecutionContext;
class SourceBuffer;
class TextTrackList;
class TimeRanges;
class VideoPlaybackQuality;
class VideoTrackList;
class VideoTrackPrivate;
class WebKitMediaKeys;
template<typename> class DOMPromise;
#if ENABLE(VIDEO_TRACK)
using CueIntervalTree = PODIntervalTree<MediaTime, TextTrackCue*>;
using CueInterval = CueIntervalTree::IntervalType;
using CueList = Vector<CueInterval>;
#endif
using MediaProvider = std::optional<Variant<
#if ENABLE(MEDIA_STREAM)
RefPtr<MediaStream>,
#endif
#if ENABLE(MEDIA_SOURCE)
RefPtr<MediaSource>,
#endif
RefPtr<Blob>>>;
class HTMLMediaElement
: public HTMLElement
, public ActiveDOMObject
, public MediaControllerInterface
, public MediaPlayerSupportsTypeClient
, public PlatformMediaSessionClient
, private MediaCanStartListener
, private MediaPlayerClient
, private MediaProducer
#if ENABLE(VIDEO_TRACK)
, private AudioTrackClient
, private TextTrackClient
, private VideoTrackClient
#endif
{
public:
MediaPlayer* player() const { return m_player.get(); }
virtual bool isVideo() const { return false; }
bool hasVideo() const override { return false; }
bool hasAudio() const override;
static HashSet<HTMLMediaElement*>& allMediaElements();
static HTMLMediaElement* bestMediaElementForShowingPlaybackControlsManager(MediaElementSession::PlaybackControlsPurpose);
void rewind(double timeDelta);
WEBCORE_EXPORT void returnToRealtime() override;
// Eventually overloaded in HTMLVideoElement
bool supportsFullscreen(HTMLMediaElementEnums::VideoFullscreenMode) const override { return false; };
bool supportsScanning() const override;
bool canSaveMediaData() const;
bool doesHaveAttribute(const AtomicString&, AtomicString* value = nullptr) const override;
WEBCORE_EXPORT PlatformMedia platformMedia() const;
PlatformLayer* platformLayer() const;
bool isVideoLayerInline();
void setPreparedToReturnVideoLayerToInline(bool);
void waitForPreparedForInlineThen(std::function<void()> completionHandler = [] { });
#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler = [] { });
PlatformLayer* videoFullscreenLayer() const { return m_videoFullscreenLayer.get(); }
void setVideoFullscreenFrame(FloatRect);
void setVideoFullscreenGravity(MediaPlayerEnums::VideoGravity);
MediaPlayerEnums::VideoGravity videoFullscreenGravity() const { return m_videoFullscreenGravity; }
#endif
using HTMLMediaElementEnums::DelayedActionType;
void scheduleDelayedAction(DelayedActionType);
void scheduleResolvePendingPlayPromises();
void rejectPendingPlayPromises(DOMError&);
void resolvePendingPlayPromises();
void scheduleNotifyAboutPlaying();
void notifyAboutPlaying();
MediaPlayerEnums::MovieLoadType movieLoadType() const;
bool inActiveDocument() const { return m_inActiveDocument; }
const Document* hostingDocument() const override { return &document(); }
// DOM API
// error state
WEBCORE_EXPORT MediaError* error() const;
void setSrc(const String&);
const URL& currentSrc() const { return m_currentSrc; }
const MediaProvider& srcObject() const { return m_mediaProvider; }
void setSrcObject(MediaProvider&&);
WEBCORE_EXPORT void setCrossOrigin(const AtomicString&);
WEBCORE_EXPORT String crossOrigin() const;
// network state
using HTMLMediaElementEnums::NetworkState;
WEBCORE_EXPORT NetworkState networkState() const;
WEBCORE_EXPORT String preload() const;
WEBCORE_EXPORT void setPreload(const String&);
Ref<TimeRanges> buffered() const override;
WEBCORE_EXPORT void load();
WEBCORE_EXPORT String canPlayType(const String& mimeType) const;
// ready state
using HTMLMediaElementEnums::ReadyState;
ReadyState readyState() const override;
WEBCORE_EXPORT bool seeking() const;
// playback state
WEBCORE_EXPORT double currentTime() const override;
void setCurrentTime(double) override;
double currentTimeForBindings() const { return currentTime(); }
WEBCORE_EXPORT ExceptionOr<void> setCurrentTimeForBindings(double);
WEBCORE_EXPORT double getStartDate() const;
WEBCORE_EXPORT double duration() const override;
WEBCORE_EXPORT bool paused() const override;
double defaultPlaybackRate() const override;
void setDefaultPlaybackRate(double) override;
WEBCORE_EXPORT double playbackRate() const override;
void setPlaybackRate(double) override;
// MediaTime versions of playback state
MediaTime currentMediaTime() const;
void setCurrentTime(const MediaTime&);
MediaTime durationMediaTime() const;
WEBCORE_EXPORT void fastSeek(const MediaTime&);
void updatePlaybackRate();
WEBCORE_EXPORT bool webkitPreservesPitch() const;
WEBCORE_EXPORT void setWebkitPreservesPitch(bool);
Ref<TimeRanges> played() override;
Ref<TimeRanges> seekable() const override;
WEBCORE_EXPORT bool ended() const;
bool autoplay() const;
bool isAutoplaying() const { return m_autoplaying; }
bool loop() const;
void setLoop(bool b);
void play(DOMPromise<void>&&);
WEBCORE_EXPORT void play() override;
WEBCORE_EXPORT void pause() override;
void setShouldBufferData(bool) override;
WEBCORE_EXPORT void fastSeek(double);
double minFastReverseRate() const;
double maxFastForwardRate() const;
void purgeBufferedDataIfPossible();
// captions
WEBCORE_EXPORT bool webkitHasClosedCaptions() const;
WEBCORE_EXPORT bool webkitClosedCaptionsVisible() const;
WEBCORE_EXPORT void setWebkitClosedCaptionsVisible(bool);
bool elementIsHidden() const override { return m_elementIsHidden; }
#if ENABLE(MEDIA_STATISTICS)
// Statistics
unsigned webkitAudioDecodedByteCount() const;
unsigned webkitVideoDecodedByteCount() const;
#endif
#if ENABLE(MEDIA_SOURCE)
// Media Source.
void detachMediaSource();
void incrementDroppedFrameCount() { ++m_droppedVideoFrames; }
size_t maximumSourceBufferSize(const SourceBuffer&) const;
#endif
#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
WebKitMediaKeys* webkitKeys() const { return m_webKitMediaKeys.get(); }
void webkitSetMediaKeys(WebKitMediaKeys*);
void keyAdded();
#endif
#if ENABLE(ENCRYPTED_MEDIA)
MediaKeys* mediaKeys() const;
void setMediaKeys(MediaKeys*, Ref<DeferredPromise>&&);
#endif
// controls
WEBCORE_EXPORT bool controls() const;
WEBCORE_EXPORT void setControls(bool);
WEBCORE_EXPORT double volume() const override;
ExceptionOr<void> setVolume(double) override;
WEBCORE_EXPORT bool muted() const override;
WEBCORE_EXPORT void setMuted(bool) override;
WEBCORE_EXPORT void togglePlayState();
WEBCORE_EXPORT void beginScrubbing() override;
WEBCORE_EXPORT void endScrubbing() override;
void beginScanning(ScanDirection) override;
void endScanning() override;
double nextScanRate();
WEBCORE_EXPORT bool canPlay() const override;
double percentLoaded() const;
#if ENABLE(VIDEO_TRACK)
ExceptionOr<TextTrack&> addTextTrack(const String& kind, const String& label, const String& language);
AudioTrackList& audioTracks();
TextTrackList& textTracks();
VideoTrackList& videoTracks();
CueList currentlyActiveCues() const { return m_currentlyActiveCues; }
void addAudioTrack(Ref<AudioTrack>&&);
void addTextTrack(Ref<TextTrack>&&);
void addVideoTrack(Ref<VideoTrack>&&);
void removeAudioTrack(AudioTrack&);
void removeTextTrack(TextTrack&, bool scheduleEvent = true);
void removeVideoTrack(VideoTrack&);
void forgetResourceSpecificTracks();
void closeCaptionTracksChanged();
void notifyMediaPlayerOfTextTrackChanges();
virtual void didAddTextTrack(HTMLTrackElement&);
virtual void didRemoveTextTrack(HTMLTrackElement&);
void mediaPlayerDidAddAudioTrack(AudioTrackPrivate&) final;
void mediaPlayerDidAddTextTrack(InbandTextTrackPrivate&) final;
void mediaPlayerDidAddVideoTrack(VideoTrackPrivate&) final;
void mediaPlayerDidRemoveAudioTrack(AudioTrackPrivate&) final;
void mediaPlayerDidRemoveTextTrack(InbandTextTrackPrivate&) final;
void mediaPlayerDidRemoveVideoTrack(VideoTrackPrivate&) final;
#if ENABLE(AVF_CAPTIONS)
Vector<RefPtr<PlatformTextTrack>> outOfBandTrackSources() final;
#endif
struct TrackGroup;
void configureTextTrackGroupForLanguage(const TrackGroup&) const;
void configureTextTracks();
void configureTextTrackGroup(const TrackGroup&);
void setSelectedTextTrack(TextTrack*);
bool textTracksAreReady() const;
using HTMLMediaElementEnums::TextTrackVisibilityCheckType;
void configureTextTrackDisplay(TextTrackVisibilityCheckType checkType = CheckTextTrackVisibility);
void updateTextTrackDisplay();
// AudioTrackClient
void audioTrackEnabledChanged(AudioTrack&) final;
void textTrackReadyStateChanged(TextTrack*);
// TextTrackClient
void textTrackKindChanged(TextTrack&) override;
void textTrackModeChanged(TextTrack&) override;
void textTrackAddCues(TextTrack&, const TextTrackCueList&) override;
void textTrackRemoveCues(TextTrack&, const TextTrackCueList&) override;
void textTrackAddCue(TextTrack&, TextTrackCue&) override;
void textTrackRemoveCue(TextTrack&, TextTrackCue&) override;
// VideoTrackClient
void videoTrackSelectedChanged(VideoTrack&) final;
bool requiresTextTrackRepresentation() const;
void setTextTrackRepresentation(TextTrackRepresentation*);
void syncTextTrackBounds();
#endif
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
void webkitShowPlaybackTargetPicker();
bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&) override;
void wirelessRoutesAvailableDidChange() override;
bool canPlayToWirelessPlaybackTarget() const override;
bool isPlayingToWirelessPlaybackTarget() const override;
void setWirelessPlaybackTarget(Ref<MediaPlaybackTarget>&&) override;
void setShouldPlayToPlaybackTarget(bool) override;
#endif
bool webkitCurrentPlaybackTargetIsWireless() const;
// EventTarget function.
// Both Node (via HTMLElement) and ActiveDOMObject define this method, which
// causes an ambiguity error at compile time. This class's constructor
// ensures that both implementations return document, so return the result
// of one of them here.
using HTMLElement::scriptExecutionContext;
bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); }
WEBCORE_EXPORT bool isFullscreen() const override;
bool isStandardFullscreen() const;
void toggleStandardFullscreenState();
using MediaPlayerEnums::VideoFullscreenMode;
VideoFullscreenMode fullscreenMode() const { return m_videoFullscreenMode; }
virtual void fullscreenModeChanged(VideoFullscreenMode);
void enterFullscreen(VideoFullscreenMode);
void enterFullscreen() override;
WEBCORE_EXPORT void exitFullscreen();
bool hasClosedCaptions() const override;
bool closedCaptionsVisible() const override;
void setClosedCaptionsVisible(bool) override;
MediaControls* mediaControls() const;
void sourceWasRemoved(HTMLSourceElement*);
void sourceWasAdded(HTMLSourceElement*);
void privateBrowsingStateDidChange() override;
// Media cache management.
WEBCORE_EXPORT static void setMediaCacheDirectory(const String&);
WEBCORE_EXPORT static const String& mediaCacheDirectory();
WEBCORE_EXPORT static HashSet<RefPtr<SecurityOrigin>> originsInMediaCache(const String&);
WEBCORE_EXPORT static void clearMediaCache(const String&, std::chrono::system_clock::time_point modifiedSince = { });
WEBCORE_EXPORT static void clearMediaCacheForOrigins(const String&, const HashSet<RefPtr<SecurityOrigin>>&);
static void resetMediaEngines();
bool isPlaying() const { return m_playing; }
bool hasPendingActivity() const override;
#if ENABLE(WEB_AUDIO)
MediaElementAudioSourceNode* audioSourceNode() { return m_audioSourceNode; }
void setAudioSourceNode(MediaElementAudioSourceNode*);
AudioSourceProvider* audioSourceProvider();
#endif
using HTMLMediaElementEnums::InvalidURLAction;
bool isSafeToLoadURL(const URL&, InvalidURLAction);
const String& mediaGroup() const;
void setMediaGroup(const String&);
MediaController* controller() const;
void setController(RefPtr<MediaController>&&);
MediaController* controllerForBindings() const { return controller(); }
void setControllerForBindings(MediaController*);
void enteredOrExitedFullscreen() { configureMediaControls(); }
unsigned long long fileSize() const;
void mediaLoadingFailed(MediaPlayerEnums::NetworkState);
void mediaLoadingFailedFatally(MediaPlayerEnums::NetworkState);
#if ENABLE(MEDIA_SESSION)
WEBCORE_EXPORT double playerVolume() const;
const String& kind() const { return m_kind; }
void setKind(const String& kind) { m_kind = kind; }
MediaSession* session() const;
void setSession(MediaSession*);
void setShouldDuck(bool);
static HTMLMediaElement* elementWithID(uint64_t);
uint64_t elementID() const { return m_elementID; }
#endif
#if ENABLE(MEDIA_SOURCE)
RefPtr<VideoPlaybackQuality> getVideoPlaybackQuality();
#endif
MediaPlayerEnums::Preload preloadValue() const { return m_preload; }
MediaElementSession& mediaSession() const { return *m_mediaSession; }
#if ENABLE(MEDIA_CONTROLS_SCRIPT)
void pageScaleFactorChanged();
void userInterfaceLayoutDirectionChanged();
WEBCORE_EXPORT String getCurrentMediaControlsStatus();
MediaControlsHost* mediaControlsHost() { return m_mediaControlsHost.get(); }
#endif
bool isDisablingSleep() const { return m_sleepDisabler.get(); }
double maxBufferedTime() const;
MediaProducer::MediaStateFlags mediaState() const override;
void layoutSizeChanged();
void visibilityDidChange();
void allowsMediaDocumentInlinePlaybackChanged();
void updateShouldPlay();
RenderMedia* renderer() const;
void resetPlaybackSessionState();
bool isVisibleInViewport() const;
bool hasEverNotifiedAboutPlaying() const;
void setShouldDelayLoadEvent(bool);
bool hasEverHadAudio() const { return m_hasEverHadAudio; }
bool hasEverHadVideo() const { return m_hasEverHadVideo; }
double playbackStartedTime() const { return m_playbackStartedTime; }
bool isTemporarilyAllowingInlinePlaybackAfterFullscreen() const {return m_temporarilyAllowingInlinePlaybackAfterFullscreen; }
protected:
HTMLMediaElement(const QualifiedName&, Document&, bool createdByParser);
virtual ~HTMLMediaElement();
void parseAttribute(const QualifiedName&, const AtomicString&) override;
void finishParsingChildren() override;
bool isURLAttribute(const Attribute&) const override;
void willAttachRenderers() override;
void didAttachRenderers() override;
void willDetachRenderers() override;
void didDetachRenderers() override;
void didMoveToNewDocument(Document& oldDocument) override;
enum DisplayMode { Unknown, None, Poster, PosterWaitingForVideo, Video };
DisplayMode displayMode() const { return m_displayMode; }
virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; }
bool isMediaElement() const final { return true; }
#if ENABLE(VIDEO_TRACK)
bool ignoreTrackDisplayUpdateRequests() const { return m_ignoreTrackDisplayUpdate > 0 || !m_textTracks || !m_cueTree.size(); }
void beginIgnoringTrackDisplayUpdateRequests();
void endIgnoringTrackDisplayUpdateRequests();
#endif
RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override;
#if ENABLE(MEDIA_CONTROLS_SCRIPT)
bool mediaControlsDependOnPageScaleFactor() const { return m_mediaControlsDependOnPageScaleFactor; }
void setMediaControlsDependOnPageScaleFactor(bool);
void updateMediaControlsAfterPresentationModeChange();
#endif
void scheduleEvent(const AtomicString& eventName);
private:
void createMediaPlayer();
bool alwaysCreateUserAgentShadowRoot() const override { return true; }
bool supportsFocus() const override;
bool isMouseFocusable() const override;
bool rendererIsNeeded(const RenderStyle&) override;
bool childShouldCreateRenderer(const Node&) const override;
InsertionNotificationRequest insertedInto(ContainerNode&) override;
void finishedInsertingSubtree() override;
void removedFrom(ContainerNode&) override;
void didRecalcStyle(Style::Change) override;
void willBecomeFullscreenElement() override;
void didBecomeFullscreenElement() override;
void willStopBeingFullscreenElement() override;
// ActiveDOMObject API.
const char* activeDOMObjectName() const override;
bool canSuspendForDocumentSuspension() const override;
void suspend(ReasonForSuspension) override;
void resume() override;
void stop() override;
void stopWithoutDestroyingMediaPlayer();
void contextDestroyed() override;
void mediaVolumeDidChange() override;
void visibilityStateChanged() override;
virtual void updateDisplayState() { }
void setReadyState(MediaPlayerEnums::ReadyState);
void setNetworkState(MediaPlayerEnums::NetworkState);
double effectivePlaybackRate() const;
double requestedPlaybackRate() const;
void mediaPlayerNetworkStateChanged(MediaPlayer*) override;
void mediaPlayerReadyStateChanged(MediaPlayer*) override;
void mediaPlayerTimeChanged(MediaPlayer*) override;
void mediaPlayerVolumeChanged(MediaPlayer*) override;
void mediaPlayerMuteChanged(MediaPlayer*) override;
void mediaPlayerDurationChanged(MediaPlayer*) override;
void mediaPlayerRateChanged(MediaPlayer*) override;
void mediaPlayerPlaybackStateChanged(MediaPlayer*) override;
void mediaPlayerSawUnsupportedTracks(MediaPlayer*) override;
void mediaPlayerResourceNotSupported(MediaPlayer*) override;
void mediaPlayerRepaint(MediaPlayer*) override;
void mediaPlayerSizeChanged(MediaPlayer*) override;
bool mediaPlayerRenderingCanBeAccelerated(MediaPlayer*) override;
void mediaPlayerRenderingModeChanged(MediaPlayer*) override;
bool mediaPlayerAcceleratedCompositingEnabled() override;
void mediaPlayerEngineUpdated(MediaPlayer*) override;
void mediaEngineWasUpdated();
void mediaPlayerFirstVideoFrameAvailable(MediaPlayer*) override;
void mediaPlayerCharacteristicChanged(MediaPlayer*) override;
#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
RefPtr<ArrayBuffer> mediaPlayerCachedKeyForKeyId(const String& keyId) const override;
bool mediaPlayerKeyNeeded(MediaPlayer*, Uint8Array*) override;
String mediaPlayerMediaKeysStorageDirectory() const override;
#endif
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
void mediaPlayerCurrentPlaybackTargetIsWirelessChanged(MediaPlayer*) override;
void enqueuePlaybackTargetAvailabilityChangedEvent();
using EventTarget::dispatchEvent;
bool dispatchEvent(Event&) override;
#endif
#if ENABLE(MEDIA_SESSION)
void setSessionInternal(MediaSession&);
#endif
String mediaPlayerReferrer() const override;
String mediaPlayerUserAgent() const override;
bool mediaPlayerNeedsSiteSpecificHacks() const override;
String mediaPlayerDocumentHost() const override;
void mediaPlayerEnterFullscreen() override;
void mediaPlayerExitFullscreen() override;
bool mediaPlayerIsFullscreen() const override;
bool mediaPlayerIsFullscreenPermitted() const override;
bool mediaPlayerIsVideo() const override;
LayoutRect mediaPlayerContentBoxRect() const override;
float mediaPlayerContentsScale() const override;
void mediaPlayerSetSize(const IntSize&) override;
void mediaPlayerPause() override;
void mediaPlayerPlay() override;
bool mediaPlayerPlatformVolumeConfigurationRequired() const override;
bool mediaPlayerIsPaused() const override;
bool mediaPlayerIsLooping() const override;
CachedResourceLoader* mediaPlayerCachedResourceLoader() override;
RefPtr<PlatformMediaResourceLoader> mediaPlayerCreateResourceLoader() override;
bool mediaPlayerShouldUsePersistentCache() const override;
const String& mediaPlayerMediaCacheDirectory() const override;
#if PLATFORM(WIN) && USE(AVFOUNDATION)
GraphicsDeviceAdapter* mediaPlayerGraphicsDeviceAdapter(const MediaPlayer*) const override;
#endif
void mediaPlayerActiveSourceBuffersChanged(const MediaPlayer*) override;
bool mediaPlayerShouldWaitForResponseToAuthenticationChallenge(const AuthenticationChallenge&) override;
void mediaPlayerHandlePlaybackCommand(PlatformMediaSession::RemoteControlCommandType command) override { didReceiveRemoteControlCommand(command, nullptr); }
String sourceApplicationIdentifier() const override;
String mediaPlayerSourceApplicationIdentifier() const override { return sourceApplicationIdentifier(); }
Vector<String> mediaPlayerPreferredAudioCharacteristics() const override;
#if PLATFORM(IOS)
String mediaPlayerNetworkInterfaceName() const override;
bool mediaPlayerGetRawCookies(const URL&, Vector<Cookie>&) const override;
#endif
bool mediaPlayerIsInMediaDocument() const final;
void mediaPlayerEngineFailedToLoad() const final;
double mediaPlayerRequestedPlaybackRate() const final;
VideoFullscreenMode mediaPlayerFullscreenMode() const final { return fullscreenMode(); }
bool mediaPlayerShouldDisableSleep() const final { return shouldDisableSleep(); }
#if USE(GSTREAMER)
void requestInstallMissingPlugins(const String& details, const String& description, MediaPlayerRequestInstallMissingPluginsCallback&) final;
#endif
void pendingActionTimerFired();
void progressEventTimerFired();
void playbackProgressTimerFired();
void scanTimerFired();
void seekTask();
void startPlaybackProgressTimer();
void startProgressEventTimer();
void stopPeriodicTimers();
void seek(const MediaTime&);
void seekInternal(const MediaTime&);
void seekWithTolerance(const MediaTime&, const MediaTime& negativeTolerance, const MediaTime& positiveTolerance, bool fromDOM);
void finishSeek();
void clearSeeking();
void addPlayedRange(const MediaTime& start, const MediaTime& end);
void scheduleTimeupdateEvent(bool periodicEvent);
virtual void scheduleResizeEvent() { }
virtual void scheduleResizeEventIfSizeChanged() { }
void selectMediaResource();
void loadResource(const URL&, ContentType&, const String& keySystem);
void scheduleNextSourceChild();
void loadNextSourceChild();
void userCancelledLoad();
void clearMediaPlayer(DelayedActionType flags);
bool havePotentialSourceChild();
void noneSupported();
void cancelPendingEventsAndCallbacks();
void waitForSourceChange();
void prepareToPlay();
URL selectNextSourceChild(ContentType*, String* keySystem, InvalidURLAction);
#if ENABLE(VIDEO_TRACK)
void updateActiveTextTrackCues(const MediaTime&);
HTMLTrackElement* showingTrackWithSameKind(HTMLTrackElement*) const;
enum ReconfigureMode {
Immediately,
AfterDelay,
};
void markCaptionAndSubtitleTracksAsUnconfigured(ReconfigureMode);
void captionPreferencesChanged() override;
#endif
// These "internal" functions do not check user gesture restrictions.
bool playInternal();
void pauseInternal();
void prepareForLoad();
void allowVideoRendering();
bool processingMediaPlayerCallback() const { return m_processingMediaPlayerCallback > 0; }
void beginProcessingMediaPlayerCallback() { ++m_processingMediaPlayerCallback; }
void endProcessingMediaPlayerCallback() { ASSERT(m_processingMediaPlayerCallback); --m_processingMediaPlayerCallback; }
enum class UpdateState { Asynchronously, Synchronously };
void updatePlayState(UpdateState updateState = UpdateState::Synchronously);
void updateVolume();
void setPlaying(bool);
bool potentiallyPlaying() const;
bool endedPlayback() const;
bool stoppedDueToErrors() const;
bool pausedForUserInteraction() const;
bool couldPlayIfEnoughData() const;
SuccessOr<MediaPlaybackDenialReason> canTransitionFromAutoplayToPlay() const;
MediaTime minTimeSeekable() const;
MediaTime maxTimeSeekable() const;
// Pauses playback without changing any states or generating events
void setPausedInternal(bool);
void setPlaybackRateInternal(double);
void mediaCanStart(Document&) final;
void invalidateCachedTime() const;
void refreshCachedTime() const;
bool hasMediaControls() const;
bool createMediaControls();
void configureMediaControls();
void prepareMediaFragmentURI();
void applyMediaFragmentURI();
void changeNetworkStateFromLoadingToIdle();
void removeBehaviorsRestrictionsAfterFirstUserGesture(MediaElementSession::BehaviorRestrictions mask = MediaElementSession::AllRestrictions);
void updateMediaController();
bool isBlocked() const;
bool isBlockedOnMediaController() const;
bool hasCurrentSrc() const override { return !m_currentSrc.isEmpty(); }
bool isLiveStream() const override { return movieLoadType() == MediaPlayerEnums::LiveStream; }
void updateSleepDisabling();
bool shouldDisableSleep() const;
#if ENABLE(MEDIA_CONTROLS_SCRIPT)
void didAddUserAgentShadowRoot(ShadowRoot*) override;
DOMWrapperWorld& ensureIsolatedWorld();
bool ensureMediaControlsInjectedScript();
#endif
PlatformMediaSession::MediaType mediaType() const override;
PlatformMediaSession::MediaType presentationType() const override;
PlatformMediaSession::DisplayType displayType() const override;
PlatformMediaSession::CharacteristicsFlags characteristics() const final;
void suspendPlayback() override;
void resumeAutoplaying() override;
void mayResumePlayback(bool shouldResume) override;
String mediaSessionTitle() const override;
double mediaSessionDuration() const override { return duration(); }
double mediaSessionCurrentTime() const override { return currentTime(); }
bool canReceiveRemoteControlCommands() const override { return true; }
void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType, const PlatformMediaSession::RemoteCommandArgument*) override;
bool supportsSeeking() const override;
bool shouldOverrideBackgroundPlaybackRestriction(PlatformMediaSession::InterruptionType) const override;
bool shouldOverrideBackgroundLoadingRestriction() const override;
bool canProduceAudio() const final;
void pageMutedStateDidChange() override;
bool effectiveMuted() const;
void registerWithDocument(Document&);
void unregisterWithDocument(Document&);
void updateCaptionContainer();
void ensureMediaControlsShadowRoot();
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
void prepareForDocumentSuspension() final;
void resumeFromDocumentSuspension() final;
void updateMediaState(UpdateState updateState = UpdateState::Synchronously);
bool hasPlaybackTargetAvailabilityListeners() const { return m_hasPlaybackTargetAvailabilityListeners; }
#endif
bool isVideoTooSmallForInlinePlayback();
void isVisibleInViewportChanged() final;
void updateShouldAutoplay();
void pauseAfterDetachedTask();
void updatePlaybackControlsManager();
void scheduleUpdatePlaybackControlsManager();
void playbackControlsManagerBehaviorRestrictionsTimerFired();
void updateRenderer();
void updatePageScaleFactorJSProperty();
void updateUsesLTRUserInterfaceLayoutDirectionJSProperty();
void setControllerJSProperty(const char*, JSC::JSValue);
void addBehaviorRestrictionsOnEndIfNecessary();
void handleSeekToPlaybackPosition(double);
void seekToPlaybackPositionEndedTimerFired();
Timer m_pendingActionTimer;
Timer m_progressEventTimer;
Timer m_playbackProgressTimer;
Timer m_scanTimer;
Timer m_playbackControlsManagerBehaviorRestrictionsTimer;
Timer m_seekToPlaybackPositionEndedTimer;
GenericTaskQueue<Timer> m_seekTaskQueue;
GenericTaskQueue<Timer> m_resizeTaskQueue;
GenericTaskQueue<Timer> m_shadowDOMTaskQueue;
GenericTaskQueue<Timer> m_promiseTaskQueue;
GenericTaskQueue<Timer> m_pauseAfterDetachedTaskQueue;
GenericTaskQueue<Timer> m_updatePlaybackControlsManagerQueue;
GenericTaskQueue<Timer> m_playbackControlsManagerBehaviorRestrictionsQueue;
GenericTaskQueue<Timer> m_resourceSelectionTaskQueue;
RefPtr<TimeRanges> m_playedTimeRanges;
GenericEventQueue m_asyncEventQueue;
Vector<DOMPromise<void>> m_pendingPlayPromises;
double m_requestedPlaybackRate { 1 };
double m_reportedPlaybackRate { 1 };
double m_defaultPlaybackRate { 1 };
bool m_webkitPreservesPitch { true };
NetworkState m_networkState { NETWORK_EMPTY };
ReadyState m_readyState { HAVE_NOTHING };
ReadyState m_readyStateMaximum { HAVE_NOTHING };
URL m_currentSrc;
RefPtr<MediaError> m_error;
struct PendingSeek {
PendingSeek(const MediaTime& now, const MediaTime& targetTime, const MediaTime& negativeTolerance, const MediaTime& positiveTolerance)
: now(now)
, targetTime(targetTime)
, negativeTolerance(negativeTolerance)
, positiveTolerance(positiveTolerance)
{
}
MediaTime now;
MediaTime targetTime;
MediaTime negativeTolerance;
MediaTime positiveTolerance;
};
std::unique_ptr<PendingSeek> m_pendingSeek;
SeekType m_pendingSeekType { NoSeek };
double m_volume { 1 };
bool m_volumeInitialized { false };
MediaTime m_lastSeekTime;
double m_previousProgressTime { std::numeric_limits<double>::max() };
double m_playbackStartedTime { 0 };
// The last time a timeupdate event was sent (based on monotonic clock).
double m_clockTimeAtLastUpdateEvent { 0 };
// The last time a timeupdate event was sent in movie time.
MediaTime m_lastTimeUpdateEventMovieTime;
// Loading state.
enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement };
LoadState m_loadState { WaitingForSource };
RefPtr<HTMLSourceElement> m_currentSourceNode;
RefPtr<Node> m_nextChildNodeToConsider;
VideoFullscreenMode m_videoFullscreenMode { VideoFullscreenModeNone };
bool m_preparedForInline;
std::function<void()> m_preparedForInlineCompletionHandler;
bool m_temporarilyAllowingInlinePlaybackAfterFullscreen { false };
#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
RetainPtr<PlatformLayer> m_videoFullscreenLayer;
FloatRect m_videoFullscreenFrame;
MediaPlayerEnums::VideoGravity m_videoFullscreenGravity { MediaPlayer::VideoGravityResizeAspect };
#endif
RefPtr<MediaPlayer> m_player;
MediaPlayerEnums::Preload m_preload { MediaPlayer::Auto };
DisplayMode m_displayMode { Unknown };
// Counter incremented while processing a callback from the media player, so we can avoid
// calling the media engine recursively.
int m_processingMediaPlayerCallback { 0 };
#if ENABLE(MEDIA_SESSION)
String m_kind;
RefPtr<MediaSession> m_session;
bool m_shouldDuck { false };
uint64_t m_elementID;
#endif
#if ENABLE(MEDIA_SOURCE)
RefPtr<MediaSource> m_mediaSource;
unsigned m_droppedVideoFrames { 0 };
#endif
mutable MediaTime m_cachedTime;
mutable double m_clockTimeAtLastCachedTimeUpdate { 0 };
mutable double m_minimumClockTimeToUpdateCachedTime { 0 };
MediaTime m_fragmentStartTime;
MediaTime m_fragmentEndTime;
using PendingActionFlags = unsigned;
PendingActionFlags m_pendingActionFlags { 0 };
enum ActionAfterScanType { Nothing, Play, Pause };
ActionAfterScanType m_actionAfterScan { Nothing };
enum ScanType { Seek, Scan };
ScanType m_scanType { Scan };
ScanDirection m_scanDirection { Forward };
bool m_firstTimePlaying : 1;
bool m_playing : 1;
bool m_isWaitingUntilMediaCanStart : 1;
bool m_shouldDelayLoadEvent : 1;
bool m_haveFiredLoadedData : 1;
bool m_inActiveDocument : 1;
bool m_autoplaying : 1;
bool m_muted : 1;
bool m_explicitlyMuted : 1;
bool m_initiallyMuted : 1;
bool m_paused : 1;
bool m_seeking : 1;
// data has not been loaded since sending a "stalled" event
bool m_sentStalledEvent : 1;
// time has not changed since sending an "ended" event
bool m_sentEndEvent : 1;
bool m_pausedInternal : 1;
// Not all media engines provide enough information about a file to be able to
// support progress events so setting m_sendProgressEvents disables them
bool m_sendProgressEvents : 1;
bool m_closedCaptionsVisible : 1;
bool m_webkitLegacyClosedCaptionOverride : 1;
bool m_completelyLoaded : 1;
bool m_havePreparedToPlay : 1;
bool m_parsingInProgress : 1;
bool m_elementIsHidden : 1;
bool m_creatingControls : 1;
bool m_receivedLayoutSizeChanged : 1;
bool m_hasEverNotifiedAboutPlaying : 1;
bool m_preventedFromPlayingWithoutUserGesture : 1;
bool m_hasEverHadAudio : 1;
bool m_hasEverHadVideo : 1;
#if ENABLE(MEDIA_CONTROLS_SCRIPT)
bool m_mediaControlsDependOnPageScaleFactor : 1;
bool m_haveSetUpCaptionContainer : 1;
#endif
bool m_isScrubbingRemotely : 1;
#if ENABLE(VIDEO_TRACK)
bool m_tracksAreReady : 1;
bool m_haveVisibleTextTrack : 1;
bool m_processingPreferenceChange : 1;
String m_subtitleTrackLanguage;
MediaTime m_lastTextTrackUpdateTime { -1, 1 };
CaptionUserPreferences::CaptionDisplayMode m_captionDisplayMode { CaptionUserPreferences::Automatic };
RefPtr<AudioTrackList> m_audioTracks;
RefPtr<TextTrackList> m_textTracks;
RefPtr<VideoTrackList> m_videoTracks;
Vector<RefPtr<TextTrack>> m_textTracksWhenResourceSelectionBegan;
CueIntervalTree m_cueTree;
CueList m_currentlyActiveCues;
int m_ignoreTrackDisplayUpdate { 0 };
bool m_requireCaptionPreferencesChangedCallbacks { false };
#endif
#if ENABLE(WEB_AUDIO)
// This is a weak reference, since m_audioSourceNode holds a reference to us.
// The value is set just after the MediaElementAudioSourceNode is created.
// The value is cleared in MediaElementAudioSourceNode::~MediaElementAudioSourceNode().
MediaElementAudioSourceNode* m_audioSourceNode { nullptr };
#endif
String m_mediaGroup;
friend class MediaController;
RefPtr<MediaController> m_mediaController;
std::unique_ptr<DisplaySleepDisabler> m_sleepDisabler;
friend class TrackDisplayUpdateScope;
RefPtr<Blob> m_blob;
MediaProvider m_mediaProvider;
#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
RefPtr<WebKitMediaKeys> m_webKitMediaKeys;
#endif
std::unique_ptr<MediaElementSession> m_mediaSession;
size_t m_reportedExtraMemoryCost { 0 };
#if ENABLE(MEDIA_CONTROLS_SCRIPT)
friend class MediaControlsHost;
RefPtr<MediaControlsHost> m_mediaControlsHost;
RefPtr<DOMWrapperWorld> m_isolatedWorld;
#endif
#if ENABLE(MEDIA_STREAM)
RefPtr<MediaStream> m_mediaStreamSrcObject;
bool m_settingMediaStreamSrcObject { false };
#endif
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
MediaProducer::MediaStateFlags m_mediaState { MediaProducer::IsNotPlaying };
bool m_hasPlaybackTargetAvailabilityListeners { false };
bool m_failedToPlayToWirelessTarget { false };
bool m_isPlayingToWirelessTarget { false };
#endif
};
#if ENABLE(VIDEO_TRACK) && !defined(NDEBUG)
// Template specialization required by PodIntervalTree in debug mode.
template <> struct ValueToString<TextTrackCue*> {
static String string(TextTrackCue* const& cue)
{
String text;
if (cue->isRenderable())
text = toVTTCue(cue)->text();
return String::format("%p id=%s interval=%s-->%s cue=%s)", cue, cue->id().utf8().data(), toString(cue->startTime()).utf8().data(), toString(cue->endTime()).utf8().data(), text.utf8().data());
}
};
#endif
#ifndef NDEBUG
template<> struct ValueToString<MediaTime> {
static String string(const MediaTime& time)
{
return toString(time);
}
};
#endif
} // namespace WebCore
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::HTMLMediaElement)
static bool isType(const WebCore::Element& element) { return element.isMediaElement(); }
static bool isType(const WebCore::Node& node) { return is<WebCore::Element>(node) && isType(downcast<WebCore::Element>(node)); }
SPECIALIZE_TYPE_TRAITS_END()
#endif