Diff
Modified: trunk/Source/WTF/ChangeLog (279785 => 279786)
--- trunk/Source/WTF/ChangeLog 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WTF/ChangeLog 2021-07-09 16:46:05 UTC (rev 279786)
@@ -1,3 +1,19 @@
+2021-07-09 Jer Noble <[email protected]>
+
+ [Cocoa] Make Coordinator playback commands more precise
+ https://bugs.webkit.org/show_bug.cgi?id=227756
+
+ Reviewed by Eric Carlson.
+
+ Add a method to convert from a MonotonicTime to a MachAbsoluteTime.
+
+ * wtf/CurrentTime.cpp:
+ (WTF::machTimebaseInfo):
+ (WTF::MonotonicTime::fromMachAbsoluteTime):
+ (WTF::MonotonicTime::toMachAbsoluteTime const):
+ * wtf/MonotonicTime.h:
+ * wtf/PlatformHave.h:
+
2021-07-08 Alex Christensen <[email protected]>
Fix some whitespace handling issues in URL setters
Modified: trunk/Source/WTF/wtf/CurrentTime.cpp (279785 => 279786)
--- trunk/Source/WTF/wtf/CurrentTime.cpp 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WTF/wtf/CurrentTime.cpp 2021-07-09 16:46:05 UTC (rev 279786)
@@ -251,7 +251,7 @@
}
#if OS(DARWIN)
-MonotonicTime MonotonicTime::fromMachAbsoluteTime(uint64_t machAbsoluteTime)
+static mach_timebase_info_data_t& machTimebaseInfo()
{
// Based on listing #2 from Apple QA 1398, but modified to be thread-safe.
static mach_timebase_info_data_t timebaseInfo;
@@ -261,8 +261,18 @@
ASSERT_UNUSED(kr, kr == KERN_SUCCESS);
ASSERT(timebaseInfo.denom);
});
- return fromRawSeconds((machAbsoluteTime * timebaseInfo.numer) / (1.0e9 * timebaseInfo.denom));
+ return timebaseInfo;
}
+
+MonotonicTime MonotonicTime::fromMachAbsoluteTime(uint64_t machAbsoluteTime)
+{
+ return fromRawSeconds((machAbsoluteTime * machTimebaseInfo().numer) / (1.0e9 * machTimebaseInfo().denom));
+}
+
+uint64_t MonotonicTime::toMachAbsoluteTime() const
+{
+ return static_cast<uint64_t>((m_value * 1.0e9 * machTimebaseInfo().denom) / machTimebaseInfo().numer);
+}
#endif
MonotonicTime MonotonicTime::now()
Modified: trunk/Source/WTF/wtf/MonotonicTime.h (279785 => 279786)
--- trunk/Source/WTF/wtf/MonotonicTime.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WTF/wtf/MonotonicTime.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -54,6 +54,7 @@
#if OS(DARWIN)
WTF_EXPORT_PRIVATE static MonotonicTime fromMachAbsoluteTime(uint64_t);
+ WTF_EXPORT_PRIVATE uint64_t toMachAbsoluteTime() const;
#endif
WTF_EXPORT_PRIVATE static MonotonicTime now();
Modified: trunk/Source/WTF/wtf/PlatformHave.h (279785 => 279786)
--- trunk/Source/WTF/wtf/PlatformHave.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WTF/wtf/PlatformHave.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -1097,3 +1097,11 @@
#if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000)
#define HAVE_WEBGL_COMPATIBLE_METAL 1
#endif
+
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 110300 \
+ || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 140500) \
+ || (PLATFORM(WATCHOS) && __WATCH_OS_VERSION_MAX_ALLOWED >= 70400) \
+ || (PLATFORM(APPLETV) && __TV_OS_VERSION_MAX_ALLOWED >= 140500) \
+ || (PLATFORM(MACCATALYST) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 140500))
+#define HAVE_AVSAMPLEBUFFERRENDERSYNCHRONIZER_RATEATHOSTTIME 1
+#endif
Modified: trunk/Source/WebCore/ChangeLog (279785 => 279786)
--- trunk/Source/WebCore/ChangeLog 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/ChangeLog 2021-07-09 16:46:05 UTC (rev 279786)
@@ -1,3 +1,59 @@
+2021-07-09 Jer Noble <[email protected]>
+
+ [Cocoa] Make Coordinator playback commands more precise
+ https://bugs.webkit.org/show_bug.cgi?id=227756
+
+ Reviewed by Eric Carlson.
+
+ Add support for precise playback commands from MediaSessionCoordinator to the underlying MediaPlayer.
+
+ In the case where a play() command is issued to a HTMLMediaElement and:
+ - There is an active MediaSession
+ - The MediaSession's active HTMLMediaElement is the current one
+ - There is a pending playSession command
+ - That command has a hostTime parameter
+ - The MediaPlayer backing the element supports playing at a specific host time
+
+ Then use the MediaPlayer's playAtHostTime() facility to begin playback, synchronized with the specified
+ hostTime.
+
+ Add support for playAtHostTime() to both MediaPlayerPrivateAVFoundationObjC and MediaPlayerPrivateMediaSourceAVFObjC.
+
+ * Modules/mediasession/MediaSession.h:
+ * Modules/mediasession/MediaSessionCoordinator.cpp:
+ (WebCore::MediaSessionCoordinator::playSession):
+ * Modules/mediasession/MediaSessionCoordinator.h:
+ (WebCore::MediaSessionCoordinator::currentPlaySessionCommand const):
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::updatePlayState):
+ (WebCore::HTMLMediaElement::playPlayer):
+ (WebCore::HTMLMediaElement::pausePlayer):
+ * html/HTMLMediaElement.h:
+ * html/MediaElementSession.h:
+ * platform/graphics/MediaPlayer.cpp:
+ (WebCore::MediaPlayer::supportsPlayAtHostTime const):
+ (WebCore::MediaPlayer::supportsPauseAtHostTime const):
+ (WebCore::MediaPlayer::playAtHostTime):
+ (WebCore::MediaPlayer::pauseAtHostTime):
+ * platform/graphics/MediaPlayer.h:
+ * platform/graphics/MediaPlayerPrivate.h:
+ (WebCore::MediaPlayerPrivateInterface::supportsPlayAtHostTime const):
+ (WebCore::MediaPlayerPrivateInterface::supportsPauseAtHostTime const):
+ (WebCore::MediaPlayerPrivateInterface::playAtHostTime):
+ (WebCore::MediaPlayerPrivateInterface::pauseAtHostTime):
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+ (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayer):
+ (WebCore::MediaPlayerPrivateAVFoundationObjC::playAtHostTime):
+ (WebCore::MediaPlayerPrivateAVFoundationObjC::pauseAtHostTime):
+ (WebCore::MediaPlayerPrivateAVFoundationObjC::setPlayerRate):
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
+ (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::playInternal):
+ (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::pauseInternal):
+ (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::playAtHostTime):
+ (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::pauseAtHostTime):
+
2021-07-09 Yusuke Suzuki <[email protected]>
Add BigInt64Array and BigUint64Array support to crypto.getRandomValues
Modified: trunk/Source/WebCore/Modules/mediasession/MediaSession.h (279785 => 279786)
--- trunk/Source/WebCore/Modules/mediasession/MediaSession.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/Modules/mediasession/MediaSession.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -111,6 +111,8 @@
void addObserver(Observer&);
void removeObserver(Observer&);
+ RefPtr<HTMLMediaElement> activeMediaElement() const;
+
private:
explicit MediaSession(Navigator&);
@@ -128,8 +130,6 @@
void suspend(ReasonForSuspension) final;
void stop() final;
- RefPtr<HTMLMediaElement> activeMediaElement() const;
-
WeakPtr<Navigator> m_navigator;
RefPtr<MediaMetadata> m_metadata;
MediaSessionPlaybackState m_playbackState { MediaSessionPlaybackState::None };
Modified: trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.cpp (279785 => 279786)
--- trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.cpp 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.cpp 2021-07-09 16:46:05 UTC (rev 279786)
@@ -376,20 +376,9 @@
if (atTime && !currentPositionApproximatelyEqualTo(*atTime))
m_session->callActionHandler({ .action = "" .seekTime = *atTime });
- if (!std::isfinite(delta) || delta <= 0_s) {
- m_session->callActionHandler({ .action = "" });
- completionHandler(true);
- return;
- }
-
- RunLoop::main().dispatchAfter(delta, [weakThis = makeWeakPtr(this), completionHandler = WTFMove(completionHandler)] () mutable {
- if (!weakThis || !weakThis->m_session) {
- completionHandler(false);
- return;
- }
- weakThis->m_session->callActionHandler({ .action = "" });
- completionHandler(true);
- });
+ m_currentPlaySessionCommand = { atTime, hostTime };
+ m_session->callActionHandler({ .action = "" });
+ completionHandler(true);
}
void MediaSessionCoordinator::pauseSession(CompletionHandler<void(bool)>&& completionHandler)
Modified: trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.h (279785 => 279786)
--- trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/Modules/mediasession/MediaSessionCoordinator.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -70,6 +70,12 @@
using RefCounted::ref;
using RefCounted::deref;
+ struct PlaySessionCommand {
+ std::optional<double> atTime;
+ std::optional<MonotonicTime> hostTime;
+ };
+ std::optional<PlaySessionCommand> takeCurrentPlaySessionCommand() { return WTFMove(m_currentPlaySessionCommand); }
+
private:
MediaSessionCoordinator(ScriptExecutionContext*);
@@ -111,6 +117,7 @@
const void* m_logIdentifier;
MediaSessionCoordinatorState m_state { MediaSessionCoordinatorState::Closed };
bool m_hasCoordinatorsStateChangeEventListener { false };
+ std::optional<PlaySessionCommand> m_currentPlaySessionCommand;
};
}
Modified: trunk/Source/WebCore/PAL/ChangeLog (279785 => 279786)
--- trunk/Source/WebCore/PAL/ChangeLog 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/PAL/ChangeLog 2021-07-09 16:46:05 UTC (rev 279786)
@@ -1,3 +1,15 @@
+2021-07-09 Jer Noble <[email protected]>
+
+ [Cocoa] Make Coordinator playback commands more precise
+ https://bugs.webkit.org/show_bug.cgi?id=227756
+
+ Reviewed by Eric Carlson.
+
+ Add SoftLink macros for CMClockMakeHostTimeFromSystemUnits.
+
+ * pal/cf/CoreMediaSoftLink.cpp:
+ * pal/cf/CoreMediaSoftLink.h:
+
2021-07-07 Tim Horton <[email protected]>
Add WKHoverPlatter and some knobs to tweak its appearance
Modified: trunk/Source/WebCore/PAL/pal/cf/CoreMediaSoftLink.cpp (279785 => 279786)
--- trunk/Source/WebCore/PAL/pal/cf/CoreMediaSoftLink.cpp 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/PAL/pal/cf/CoreMediaSoftLink.cpp 2021-07-09 16:46:05 UTC (rev 279786)
@@ -208,6 +208,7 @@
SOFT_LINK_FUNCTION_FOR_SOURCE_WITH_EXPORT(PAL, CoreMedia, CMClockGetHostTimeClock, CMClockRef, (void), (), PAL_EXPORT)
SOFT_LINK_FUNCTION_FOR_SOURCE_WITH_EXPORT(PAL, CoreMedia, CMClockGetTime, CMTime, (CMClockRef clock), (clock), PAL_EXPORT)
SOFT_LINK_FUNCTION_FOR_SOURCE_WITH_EXPORT(PAL, CoreMedia, CMClockConvertHostTimeToSystemUnits, uint64_t, (CMTime hostTime), (hostTime), PAL_EXPORT)
+SOFT_LINK_FUNCTION_FOR_SOURCE_WITH_EXPORT(PAL, CoreMedia, CMClockMakeHostTimeFromSystemUnits, CMTime, (uint64_t hostTime), (hostTime), PAL_EXPORT)
SOFT_LINK_FUNCTION_FOR_SOURCE_WITH_EXPORT(PAL, CoreMedia, CMSampleBufferCallForEachSample, OSStatus, (CMSampleBufferRef sbuf, OSStatus (*CMSAMPLEBUFFERCALL_NOESCAPE callback)(CMSampleBufferRef sampleBuffer, CMItemCount index, void* refcon), void* refcon), (sbuf, callback, refcon), PAL_EXPORT)
SOFT_LINK_FUNCTION_FOR_SOURCE_WITH_EXPORT(PAL, CoreMedia, CMSampleBufferCallBlockForEachSample, OSStatus, (CMSampleBufferRef sbuf, OSStatus (^CMSAMPLEBUFFERCALL_NOESCAPE handler)(CMSampleBufferRef, CMItemCount)), (sbuf, handler), PAL_EXPORT)
Modified: trunk/Source/WebCore/PAL/pal/cf/CoreMediaSoftLink.h (279785 => 279786)
--- trunk/Source/WebCore/PAL/pal/cf/CoreMediaSoftLink.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/PAL/pal/cf/CoreMediaSoftLink.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -353,6 +353,8 @@
#define CMClockGetTime softLink_CoreMedia_CMClockGetTime
SOFT_LINK_FUNCTION_FOR_HEADER(PAL, CoreMedia, CMClockConvertHostTimeToSystemUnits, uint64_t, (CMTime hostTime), (hostTime))
#define CMClockConvertHostTimeToSystemUnits softLink_CoreMedia_CMClockConvertHostTimeToSystemUnits
+SOFT_LINK_FUNCTION_FOR_HEADER(PAL, CoreMedia, CMClockMakeHostTimeFromSystemUnits, CMTime, (uint64_t hostTime), (hostTime))
+#define CMClockMakeHostTimeFromSystemUnits softLink_CoreMedia_CMClockMakeHostTimeFromSystemUnits
SOFT_LINK_FUNCTION_FOR_HEADER(PAL, CoreMedia, CMSampleBufferCallForEachSample, OSStatus, (CMSampleBufferRef sbuf, OSStatus (*CMSAMPLEBUFFERCALL_NOESCAPE callback)(CMSampleBufferRef sampleBuffer, CMItemCount index, void* refcon), void* refcon), (sbuf, callback, refcon))
#define CMSampleBufferCallForEachSample softLink_CoreMedia_CMSampleBufferCallForEachSample
Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (279785 => 279786)
--- trunk/Source/WebCore/html/HTMLMediaElement.cpp 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp 2021-07-09 16:46:05 UTC (rev 279786)
@@ -166,6 +166,14 @@
#include "VideoFullscreenModel.h"
#endif
+#if ENABLE(MEDIA_SESSION)
+#include "MediaSession.h"
+#endif
+
+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+#include "MediaSessionCoordinator.h"
+#endif
+
namespace WTF {
template <>
struct LogArgument<URL> {
@@ -5326,7 +5334,7 @@
if (m_pausedInternal) {
if (!m_player->paused())
- m_player->pause();
+ pausePlayer();
refreshCachedTime();
m_playbackProgressTimer.stop();
return;
@@ -5368,7 +5376,7 @@
m_firstTimePlaying = false;
}
- m_player->play();
+ playPlayer();
}
startPlaybackProgressTimer();
@@ -5377,7 +5385,7 @@
schedulePlaybackControlsManagerUpdate();
if (!playerPaused)
- m_player->pause();
+ pausePlayer();
refreshCachedTime();
m_playbackProgressTimer.stop();
@@ -5396,6 +5404,48 @@
checkForAudioAndVideo();
}
+void HTMLMediaElement::playPlayer()
+{
+ ASSERT(m_player);
+ if (!m_player)
+ return;
+
+#if ENABLE(MEDIA_SESSION) && ENABLE(MEDIA_SESSION_COORDINATOR)
+ do {
+ if (!m_player->supportsPlayAtHostTime())
+ break;
+
+ auto* mediaSession = this->mediaSession().mediaSession();
+ if (!mediaSession)
+ break;
+
+ if (mediaSession->activeMediaElement() != this)
+ break;
+
+ auto currentPlaySessionCommand = mediaSession->coordinator().takeCurrentPlaySessionCommand();
+ if (!currentPlaySessionCommand)
+ break;
+
+ if (!currentPlaySessionCommand->hostTime)
+ break;
+
+ m_player->playAtHostTime(*currentPlaySessionCommand->hostTime);
+ return;
+ } while (false);
+#endif
+
+ m_player->play();
+}
+
+void HTMLMediaElement::pausePlayer()
+{
+ ASSERT(m_player);
+ if (!m_player)
+ return;
+
+ m_player->pause();
+}
+
void HTMLMediaElement::checkForAudioAndVideo()
{
m_hasEverHadAudio |= hasAudio();
Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (279785 => 279786)
--- trunk/Source/WebCore/html/HTMLMediaElement.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -931,6 +931,9 @@
void checkForAudioAndVideo();
bool hasLiveSource() const;
+ void playPlayer();
+ void pausePlayer();
+
#if !RELEASE_LOG_DISABLED
const void* mediaPlayerLogIdentifier() final { return logIdentifier(); }
const Logger& mediaPlayerLogger() final { return logger(); }
Modified: trunk/Source/WebCore/html/MediaElementSession.h (279785 => 279786)
--- trunk/Source/WebCore/html/MediaElementSession.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/html/MediaElementSession.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -180,6 +180,8 @@
void playbackStateChanged(MediaSessionPlaybackState);
void actionHandlersChanged();
+ MediaSession* mediaSession() const;
+
private:
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
@@ -195,7 +197,6 @@
bool requiresPlaybackTargetRouteMonitoring() const override;
#endif
void ensureIsObservingMediaSession();
- MediaSession* mediaSession() const;
bool updateIsMainContent() const;
void mainContentCheckTimerFired();
Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (279785 => 279786)
--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp 2021-07-09 16:46:05 UTC (rev 279786)
@@ -1685,6 +1685,32 @@
return client().mediaPlayerElementId();
}
+bool MediaPlayer::supportsPlayAtHostTime() const
+{
+ return m_private->supportsPlayAtHostTime();
+}
+
+bool MediaPlayer::supportsPauseAtHostTime() const
+{
+ return m_private->supportsPauseAtHostTime();
+}
+
+bool MediaPlayer::playAtHostTime(const MonotonicTime& hostTime)
+{
+ // It is invalid to call playAtHostTime() if the underlying
+ // media player does not support it.
+ ASSERT(supportsPlayAtHostTime());
+ return m_private->playAtHostTime(hostTime);
+}
+
+bool MediaPlayer::pauseAtHostTime(const MonotonicTime& hostTime)
+{
+ // It is invalid to call pauseAtHostTime() if the underlying
+ // media player does not support it.
+ ASSERT(supportsPauseAtHostTime());
+ return m_private->pauseAtHostTime(hostTime);
+}
+
#if !RELEASE_LOG_DISABLED
const Logger& MediaPlayer::mediaPlayerLogger()
{
Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (279785 => 279786)
--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -413,6 +413,11 @@
void setRate(double);
double requestedRate() const;
+ bool supportsPlayAtHostTime() const;
+ bool supportsPauseAtHostTime() const;
+ bool playAtHostTime(const MonotonicTime&);
+ bool pauseAtHostTime(const MonotonicTime&);
+
bool preservesPitch() const;
void setPreservesPitch(bool);
Modified: trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h (279785 => 279786)
--- trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -307,6 +307,11 @@
virtual void audioOutputDeviceChanged() { }
virtual MediaPlayerIdentifier identifier() const { return { }; }
+
+ virtual bool supportsPlayAtHostTime() const { return false; }
+ virtual bool supportsPauseAtHostTime() const { return false; }
+ virtual bool playAtHostTime(const MonotonicTime&) { return false; }
+ virtual bool pauseAtHostTime(const MonotonicTime&) { return false; }
};
}
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h (279785 => 279786)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -171,7 +171,7 @@
void setVideoFullscreenMode(MediaPlayer::VideoFullscreenMode) final;
void videoFullscreenStandbyChanged() final;
#endif
- void setPlayerRate(double);
+ void setPlayerRate(double, std::optional<MonotonicTime>&& = std::nullopt);
#if PLATFORM(IOS_FAMILY)
NSArray *timedMetadata() const final;
@@ -324,6 +324,13 @@
void currentMediaTimeDidChange(MediaTime&&) const;
bool setCurrentTimeDidChangeCallback(MediaPlayer::CurrentTimeDidChangeCallback&&) final;
+ bool currentMediaTimeIsBuffered() const;
+
+ bool supportsPlayAtHostTime() const final { return true; }
+ bool supportsPauseAtHostTime() const final { return true; }
+ bool playAtHostTime(const MonotonicTime&) final;
+ bool pauseAtHostTime(const MonotonicTime&) final;
+
RetainPtr<AVURLAsset> m_avAsset;
RetainPtr<AVPlayer> m_avPlayer;
RetainPtr<AVPlayerItem> m_avPlayerItem;
@@ -422,6 +429,7 @@
bool m_muted { false };
bool m_shouldObserveTimeControlStatus { false };
mutable std::optional<bool> m_tracksArePlayable;
+ bool m_automaticallyWaitsToMinimizeStalling { false };
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
mutable bool m_allowsWirelessVideoPlayback { true };
bool m_shouldPlayToPlaybackTarget { false };
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (279785 => 279786)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm 2021-07-09 16:46:05 UTC (rev 279786)
@@ -1034,6 +1034,7 @@
m_avPlayer = adoptNS([PAL::allocAVPlayerInstance() init]);
for (NSString *keyName in playerKVOProperties())
[m_avPlayer.get() addObserver:m_objcObserver.get() forKeyPath:keyName options:NSKeyValueObservingOptionNew context:(void *)MediaPlayerAVFoundationObservationContextPlayer];
+ m_automaticallyWaitsToMinimizeStalling = [m_avPlayer automaticallyWaitsToMinimizeStalling];
setShouldObserveTimeControlStatus(true);
@@ -1380,6 +1381,32 @@
setPlayerRate(0);
}
+bool MediaPlayerPrivateAVFoundationObjC::playAtHostTime(const MonotonicTime& hostTime)
+{
+ if (!metaDataAvailable())
+ return false;
+
+ ALWAYS_LOG(LOGIDENTIFIER);
+
+ m_requestedPlaying = true;
+ setPlayerRate(m_requestedRate, hostTime);
+
+ return true;
+}
+
+bool MediaPlayerPrivateAVFoundationObjC::pauseAtHostTime(const MonotonicTime& hostTime)
+{
+ if (!metaDataAvailable())
+ return false;
+
+ ALWAYS_LOG(LOGIDENTIFIER);
+
+ m_requestedPlaying = false;
+ setPlayerRate(0, hostTime);
+
+ return true;
+}
+
bool MediaPlayerPrivateAVFoundationObjC::platformPaused() const
{
return m_cachedTimeControlStatus == AVPlayerTimeControlStatusPaused;
@@ -1529,7 +1556,7 @@
m_wallClockAtCachedCurrentTime = std::nullopt;
}
-void MediaPlayerPrivateAVFoundationObjC::setPlayerRate(double rate)
+void MediaPlayerPrivateAVFoundationObjC::setPlayerRate(double rate, std::optional<MonotonicTime>&& hostTime)
{
setDelayCallbacks(true);
@@ -1536,7 +1563,23 @@
[m_avPlayerItem setAudioTimePitchAlgorithm:audioTimePitchAlgorithmForMediaPlayerPitchCorrectionAlgorithm(player()->pitchCorrectionAlgorithm(), player()->preservesPitch(), m_requestedRate)];
setShouldObserveTimeControlStatus(false);
- [m_avPlayer setRate:rate];
+
+ // -[AVPlayer setRate:time:atHostTime:] will throw if AVPlayer.automaticallyWaitsToMinimizeStalling
+ // is set to YES. Disable when synchronized playback is indicated by the optional hostTime parameter
+ // and enable otherwise.
+ bool shouldAutomaticallyWait = !hostTime;
+ if (m_automaticallyWaitsToMinimizeStalling != shouldAutomaticallyWait) {
+ [m_avPlayer setAutomaticallyWaitsToMinimizeStalling:shouldAutomaticallyWait];
+ m_automaticallyWaitsToMinimizeStalling = shouldAutomaticallyWait;
+ }
+
+ if (hostTime) {
+ auto cmHostTime = PAL::CMClockMakeHostTimeFromSystemUnits(hostTime->toMachAbsoluteTime());
+ INFO_LOG(LOGIDENTIFIER, "setting rate to ", rate, " at host time ", PAL::CMTimeGetSeconds(cmHostTime));
+ [m_avPlayer setRate:rate time:PAL::kCMTimeInvalid atHostTime:cmHostTime];
+ } else
+ [m_avPlayer setRate:rate];
+
m_cachedTimeControlStatus = [m_avPlayer timeControlStatus];
setShouldObserveTimeControlStatus(true);
setDelayCallbacks(false);
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h (279785 => 279786)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -178,10 +178,10 @@
bool supportsFullscreen() const override { return true; }
void play() override;
- void playInternal();
+ void playInternal(std::optional<MonotonicTime>&& = std::nullopt);
void pause() override;
- void pauseInternal();
+ void pauseInternal(std::optional<MonotonicTime>&& = std::nullopt);
bool paused() const override;
@@ -265,6 +265,13 @@
bool setCurrentTimeDidChangeCallback(MediaPlayer::CurrentTimeDidChangeCallback&&) final;
+#if HAVE(AVSAMPLEBUFFERRENDERSYNCHRONIZER_RATEATHOSTTIME)
+ bool supportsPlayAtHostTime() const final { return true; }
+ bool supportsPauseAtHostTime() const final { return true; }
+ bool playAtHostTime(const MonotonicTime&) final;
+ bool pauseAtHostTime(const MonotonicTime&) final;
+#endif
+
friend class MediaSourcePrivateAVFObjC;
struct PendingSeek {
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm (279785 => 279786)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm 2021-07-09 16:46:05 UTC (rev 279786)
@@ -317,7 +317,7 @@
});
}
-void MediaPlayerPrivateMediaSourceAVFObjC::playInternal()
+void MediaPlayerPrivateMediaSourceAVFObjC::playInternal(std::optional<MonotonicTime>&& hostTime)
{
if (!m_mediaSourcePrivate)
return;
@@ -332,8 +332,22 @@
m_mediaSourcePrivate->flushActiveSourceBuffersIfNeeded();
#endif
m_playing = true;
- if (shouldBePlaying())
+ if (!shouldBePlaying())
+ return;
+
+#if HAVE(AVSAMPLEBUFFERRENDERSYNCHRONIZER_RATEATHOSTTIME)
+ ALLOW_NEW_API_WITHOUT_GUARDS_BEGIN
+ if (hostTime && [m_synchronizer respondsToSelector:@selector(setRate:time:atHostTime:)]) {
+ auto cmHostTime = PAL::CMClockMakeHostTimeFromSystemUnits(hostTime->toMachAbsoluteTime());
+ INFO_LOG(LOGIDENTIFIER, "setting rate to ", m_rate, " at host time ", PAL::CMTimeGetSeconds(cmHostTime));
+ [m_synchronizer setRate:m_rate time:PAL::kCMTimeInvalid atHostTime:cmHostTime];
+ } else
[m_synchronizer setRate:m_rate];
+ ALLOW_NEW_API_WITHOUT_GUARDS_END
+#else
+ UNUSED_PARAM(hostTime);
+ [m_synchronizer setRate:m_rate];
+#endif
}
void MediaPlayerPrivateMediaSourceAVFObjC::pause()
@@ -346,11 +360,24 @@
});
}
-void MediaPlayerPrivateMediaSourceAVFObjC::pauseInternal()
+void MediaPlayerPrivateMediaSourceAVFObjC::pauseInternal(std::optional<MonotonicTime>&& hostTime)
{
ALWAYS_LOG(LOGIDENTIFIER);
m_playing = false;
+
+#if HAVE(AVSAMPLEBUFFERRENDERSYNCHRONIZER_RATEATHOSTTIME)
+ ALLOW_NEW_API_WITHOUT_GUARDS_BEGIN
+ if (hostTime && [m_synchronizer respondsToSelector:@selector(setRate:time:atHostTime:)]) {
+ auto cmHostTime = PAL::CMClockMakeHostTimeFromSystemUnits(hostTime->toMachAbsoluteTime());
+ INFO_LOG(LOGIDENTIFIER, "setting rate to 0 at host time ", PAL::CMTimeGetSeconds(cmHostTime));
+ [m_synchronizer setRate:0 time:PAL::kCMTimeInvalid atHostTime:cmHostTime];
+ } else
+ [m_synchronizer setRate:0];
+ ALLOW_NEW_API_WITHOUT_GUARDS_END
+#else
+ UNUSED_PARAM(hostTime);
[m_synchronizer setRate:0];
+#endif
}
bool MediaPlayerPrivateMediaSourceAVFObjC::paused() const
@@ -440,6 +467,30 @@
return true;
}
+#if HAVE(AVSAMPLEBUFFERRENDERSYNCHRONIZER_RATEATHOSTTIME)
+bool MediaPlayerPrivateMediaSourceAVFObjC::playAtHostTime(const MonotonicTime& time)
+{
+ ALWAYS_LOG(LOGIDENTIFIER);
+ callOnMainThread([weakThis = makeWeakPtr(*this), time = time] {
+ if (!weakThis)
+ return;
+ weakThis.get()->playInternal(time);
+ });
+ return true;
+}
+
+bool MediaPlayerPrivateMediaSourceAVFObjC::pauseAtHostTime(const MonotonicTime& time)
+{
+ ALWAYS_LOG(LOGIDENTIFIER);
+ callOnMainThread([weakThis = makeWeakPtr(*this), time = time] {
+ if (!weakThis)
+ return;
+ weakThis.get()->pauseInternal(time);
+ });
+ return true;
+}
+#endif
+
MediaTime MediaPlayerPrivateMediaSourceAVFObjC::startTime() const
{
return MediaTime::zeroTime();
Modified: trunk/Source/WebKit/ChangeLog (279785 => 279786)
--- trunk/Source/WebKit/ChangeLog 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebKit/ChangeLog 2021-07-09 16:46:05 UTC (rev 279786)
@@ -1,3 +1,27 @@
+2021-07-09 Jer Noble <[email protected]>
+
+ [Cocoa] Make Coordinator playback commands more precise
+ https://bugs.webkit.org/show_bug.cgi?id=227756
+
+ Reviewed by Eric Carlson.
+
+ Pass through new {play,pause}AtHostTime() and supports{Play,Pause}AtHostTime() methods
+ to and from the GPU process.
+
+ * GPUProcess/media/RemoteMediaPlayerProxy.cpp:
+ (WebKit::RemoteMediaPlayerProxy::getConfiguration):
+ (WebKit::RemoteMediaPlayerProxy::playAtHostTime):
+ (WebKit::RemoteMediaPlayerProxy::pauseAtHostTime):
+ * GPUProcess/media/RemoteMediaPlayerProxy.h:
+ * GPUProcess/media/RemoteMediaPlayerProxy.messages.in:
+ * WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp:
+ (WebKit::MediaPlayerPrivateRemote::playAtHostTime):
+ (WebKit::MediaPlayerPrivateRemote::pauseAtHostTime):
+ * WebProcess/GPU/media/MediaPlayerPrivateRemote.h:
+ * WebProcess/GPU/media/RemoteMediaPlayerConfiguration.h:
+ (WebKit::RemoteMediaPlayerConfiguration::encode const):
+ (WebKit::RemoteMediaPlayerConfiguration::decode):
+
2021-07-09 Youenn Fablet <[email protected]>
Use nw_parameters_allow_sharing_port_with_listener if available
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.cpp (279785 => 279786)
--- trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.cpp 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.cpp 2021-07-09 16:46:05 UTC (rev 279786)
@@ -114,6 +114,9 @@
configuration.supportsFullscreen = m_player->supportsFullscreen();
configuration.supportsPictureInPicture = m_player->supportsPictureInPicture();
configuration.supportsAcceleratedRendering = m_player->supportsAcceleratedRendering();
+ configuration.supportsPlayAtHostTime = m_player->supportsPlayAtHostTime();
+ configuration.supportsPauseAtHostTime = m_player->supportsPauseAtHostTime();
+
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
configuration.canPlayToWirelessPlaybackTarget = m_player->canPlayToWirelessPlaybackTarget();
#endif
@@ -1069,6 +1072,18 @@
#endif
}
+void RemoteMediaPlayerProxy::playAtHostTime(MonotonicTime time)
+{
+ if (m_player)
+ m_player->playAtHostTime(time);
+}
+
+void RemoteMediaPlayerProxy::pauseAtHostTime(MonotonicTime time)
+{
+ if (m_player)
+ m_player->pauseAtHostTime(time);
+}
+
#if !RELEASE_LOG_DISABLED
WTFLogChannel& RemoteMediaPlayerProxy::logChannel() const
{
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.h (279785 => 279786)
--- trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -301,6 +301,9 @@
void createAudioSourceProvider();
void setShouldEnableAudioSourceProvider(bool);
+ void playAtHostTime(MonotonicTime);
+ void pauseAtHostTime(MonotonicTime);
+
bool mediaPlayerPausedOrStalled() const;
void currentTimeChanged(const MediaTime&);
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.messages.in (279785 => 279786)
--- trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.messages.in 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.messages.in 2021-07-09 16:46:05 UTC (rev 279786)
@@ -128,6 +128,9 @@
#if USE(AVFOUNDATION)
PixelBufferForCurrentTime() -> (RetainPtr<CVPixelBufferRef> pixelBuffer) Synchronous
#endif
+
+ PlayAtHostTime(MonotonicTime time)
+ PauseAtHostTime(MonotonicTime time)
}
#endif
Modified: trunk/Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp (279785 => 279786)
--- trunk/Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp 2021-07-09 16:46:05 UTC (rev 279786)
@@ -1313,6 +1313,22 @@
return true;
}
+bool MediaPlayerPrivateRemote::playAtHostTime(const MonotonicTime& time)
+{
+ if (!m_configuration.supportsPlayAtHostTime)
+ return false;
+ connection().send(Messages::RemoteMediaPlayerProxy::PlayAtHostTime(time), m_id);
+ return true;
+}
+
+bool MediaPlayerPrivateRemote::pauseAtHostTime(const MonotonicTime& time)
+{
+ if (!m_configuration.supportsPauseAtHostTime)
+ return false;
+ connection().send(Messages::RemoteMediaPlayerProxy::PauseAtHostTime(time), m_id);
+ return true;
+}
+
void MediaPlayerPrivateRemote::requestResource(RemoteMediaResourceIdentifier remoteMediaResourceIdentifier, WebCore::ResourceRequest&& request, WebCore::PlatformMediaResourceLoader::LoadOptions options, CompletionHandler<void()>&& completionHandler)
{
ASSERT(!m_mediaResources.contains(remoteMediaResourceIdentifier));
Modified: trunk/Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.h (279785 => 279786)
--- trunk/Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -392,6 +392,12 @@
bool performTaskAtMediaTime(Function<void()>&&, const MediaTime&) final;
+ bool supportsPlayAtHostTime() const final { return m_configuration.supportsPlayAtHostTime; }
+ bool supportsPauseAtHostTime() const final { return m_configuration.supportsPauseAtHostTime; }
+ bool playAtHostTime(const MonotonicTime&) final;
+ bool pauseAtHostTime(const MonotonicTime&) final;
+
+
WeakPtr<WebCore::MediaPlayer> m_player;
Ref<WebCore::PlatformMediaResourceLoader> m_mediaResourceLoader;
#if PLATFORM(COCOA)
Modified: trunk/Source/WebKit/WebProcess/GPU/media/RemoteMediaPlayerConfiguration.h (279785 => 279786)
--- trunk/Source/WebKit/WebProcess/GPU/media/RemoteMediaPlayerConfiguration.h 2021-07-09 16:02:33 UTC (rev 279785)
+++ trunk/Source/WebKit/WebProcess/GPU/media/RemoteMediaPlayerConfiguration.h 2021-07-09 16:46:05 UTC (rev 279786)
@@ -40,6 +40,8 @@
bool supportsFullscreen { false };
bool supportsPictureInPicture { false };
bool supportsAcceleratedRendering { false };
+ bool supportsPlayAtHostTime { false };
+ bool supportsPauseAtHostTime { false };
bool canPlayToWirelessPlaybackTarget { false };
bool shouldIgnoreIntrinsicSize { false };
@@ -52,6 +54,8 @@
encoder << supportsFullscreen;
encoder << supportsPictureInPicture;
encoder << supportsAcceleratedRendering;
+ encoder << supportsPlayAtHostTime;
+ encoder << supportsPauseAtHostTime;
encoder << canPlayToWirelessPlaybackTarget;
encoder << shouldIgnoreIntrinsicSize;
}
@@ -89,6 +93,16 @@
if (!supportsAcceleratedRendering)
return std::nullopt;
+ std::optional<bool> supportsPlayAtHostTime;
+ decoder >> supportsPlayAtHostTime;
+ if (!supportsPlayAtHostTime)
+ return std::nullopt;
+
+ std::optional<bool> supportsPauseAtHostTime;
+ decoder >> supportsPauseAtHostTime;
+ if (!supportsPauseAtHostTime)
+ return std::nullopt;
+
std::optional<bool> canPlayToWirelessPlaybackTarget;
decoder >> canPlayToWirelessPlaybackTarget;
if (!canPlayToWirelessPlaybackTarget)
@@ -106,6 +120,8 @@
*supportsFullscreen,
*supportsPictureInPicture,
*supportsAcceleratedRendering,
+ *supportsPlayAtHostTime,
+ *supportsPauseAtHostTime,
*canPlayToWirelessPlaybackTarget,
*shouldIgnoreIntrinsicSize,
}};