Diff
Modified: trunk/Source/WebCore/ChangeLog (259302 => 259303)
--- trunk/Source/WebCore/ChangeLog 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/ChangeLog 2020-03-31 19:40:05 UTC (rev 259303)
@@ -1,3 +1,52 @@
+2020-03-31 Eric Carlson <[email protected]>
+
+ [iPad] Use AVAudioSession to detect AirPlay route changes
+ https://bugs.webkit.org/show_bug.cgi?id=209789
+ <rdar://problem/58065279>
+
+ Reviewed by Jer Noble.
+
+ No new tests: changes only affect playback on device to an actual AirPlay device, which
+ is not testable on our current testing infrastructure.
+
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::checkPlaybackTargetCompatablity): Drive-by fix: pass log identifier
+ into lambda so the method name is logged.
+ (WebCore::HTMLMediaElement::setIsPlayingToWirelessTarget): Ditto.
+ (WebCore::HTMLMediaElement::setWirelessPlaybackTarget): Update logging.
+ (WebCore::HTMLMediaElement::setShouldPlayToPlaybackTarget): Call setIsPlayingToWirelessTarget
+ so we kick off a media player compatibility check.
+
+ * platform/audio/PlatformMediaSessionManager.h: Remove unused instance variables.
+ * platform/audio/ios/MediaSessionHelperIOS.mm:
+ (MediaSessionHelperiOS::activeAudioRouteDidChange): Change parameter to bool as it is always
+ present.
+ (MediaSessionHelperiOS::activeVideoRouteDidChange): Remove parameters, use the new
+ MediaPlaybackTargetCocoa create method and ask it if the target supports AirPlay.
+ (-[WebMediaSessionHelper initWithCallback:]): Listen for AVAudioSessionRouteChangeNotification.
+ (-[WebMediaSessionHelper activeOutputDeviceDidChange:]): Update for new notification source.
+ (-[WebMediaSessionHelper activeAudioRouteDidChange:]): Deleted.
+
+ * platform/audio/ios/MediaSessionManagerIOS.h:
+ * platform/audio/ios/MediaSessionManagerIOS.mm:
+ (WebCore::MediaSessionManageriOS::sessionWillBeginPlayback): Set playback target on session
+ that is about to begin playback.
+ (WebCore::MediaSessionManageriOS::activeVideoRouteDidChange): Save the target and state.
+
+ * platform/graphics/MediaPlaybackTarget.h:
+ * platform/graphics/avfoundation/MediaPlaybackTargetCocoa.h:
+ * platform/graphics/avfoundation/MediaPlaybackTargetCocoa.mm:
+ (WebCore::MediaPlaybackTargetCocoa::create): Create a target from the application's currently
+ active AVOutputContext.
+ (WebCore::MediaPlaybackTargetCocoa::supportsAirPlayVideo const): New.
+ (WebCore::MediaPlaybackTargetCocoa::hasActiveRoute const): Use new API if available instead
+ of just checking for the AVOutputContext name.
+
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
+ (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::setWirelessPlaybackTarget): Log.
+ (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::setShouldPlayToPlaybackTarget):
+ * platform/mock/MediaPlaybackTargetMock.h:
+
2020-03-31 Jer Noble <[email protected]>
REGRESSION: [ Mac wk2 Release ] Flaky crash in WebCore::MediaPlayer::createVideoFullscreenLayer
Modified: trunk/Source/WebCore/PAL/ChangeLog (259302 => 259303)
--- trunk/Source/WebCore/PAL/ChangeLog 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/PAL/ChangeLog 2020-03-31 19:40:05 UTC (rev 259303)
@@ -1,3 +1,15 @@
+2020-03-31 Eric Carlson <[email protected]>
+
+ [iPad] Use AVAudioSession to detect AirPlay route changes
+ https://bugs.webkit.org/show_bug.cgi?id=209789
+ <rdar://problem/58065279>
+
+ Reviewed by Jer Noble.
+
+ * pal/cocoa/AVFoundationSoftLink.h:
+ * pal/cocoa/AVFoundationSoftLink.mm:
+ * pal/spi/cocoa/AVFoundationSPI.h:
+
2020-03-30 Megan Gardner <[email protected]>
Update to new Data Detectors SPI
Modified: trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h (259302 => 259303)
--- trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h 2020-03-31 19:40:05 UTC (rev 259303)
@@ -291,6 +291,10 @@
#define AVRouteDetectorMultipleRoutesDetectedDidChangeNotification PAL::get_AVFoundation_AVRouteDetectorMultipleRoutesDetectedDidChangeNotification()
SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AVFoundation, AVAudioSessionMediaServicesWereResetNotification, NSString *)
#define AVAudioSessionMediaServicesWereResetNotification PAL::get_AVFoundation_AVAudioSessionMediaServicesWereResetNotification()
+SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AVFoundation, AVAudioSessionRouteChangeNotification, NSString *)
+#define AVAudioSessionRouteChangeNotification PAL::get_AVFoundation_AVAudioSessionRouteChangeNotification()
+SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AVFoundation, AVAudioSessionRouteChangeReasonKey, NSString *)
+#define AVAudioSessionRouteChangeReasonKey PAL::get_AVFoundation_AVAudioSessionRouteChangeReasonKey()
#endif // PLATFORM(IOS_FAMILY)
#endif // USE(AVFOUNDATION)
Modified: trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm (259302 => 259303)
--- trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm 2020-03-31 19:40:05 UTC (rev 259303)
@@ -213,6 +213,8 @@
SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVRouteDetectorMultipleRoutesDetectedDidChangeNotification, NSString *, PAL_EXPORT)
SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVURLAssetBoundNetworkInterfaceName, NSString *, PAL_EXPORT)
SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVURLAssetClientBundleIdentifierKey, NSString *, PAL_EXPORT)
+SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVAudioSessionRouteChangeNotification, NSString *, PAL_EXPORT)
+SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVAudioSessionRouteChangeReasonKey, NSString *, PAL_EXPORT)
SOFT_LINK_CONSTANT_MAY_FAIL_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVURLAssetHTTPCookiesKey, NSString *, PAL_EXPORT)
SOFT_LINK_CONSTANT_MAY_FAIL_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVURLAssetRequiresCustomURLLoadingKey, NSString *, PAL_EXPORT)
Modified: trunk/Source/WebCore/PAL/pal/spi/cocoa/AVFoundationSPI.h (259302 => 259303)
--- trunk/Source/WebCore/PAL/pal/spi/cocoa/AVFoundationSPI.h 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/PAL/pal/spi/cocoa/AVFoundationSPI.h 2020-03-31 19:40:05 UTC (rev 259303)
@@ -77,12 +77,21 @@
@property (nonatomic, readonly) NSString *deviceName;
+ (instancetype)outputContext;
+ (nullable AVOutputContext *)sharedAudioPresentationOutputContext;
++ (nullable AVOutputContext *)outputContextForID:(NSString *)ID;
@property (readonly) BOOL supportsMultipleOutputDevices;
@property (readonly) NSArray<AVOutputDevice *> *outputDevices;
+@property (nonatomic, readonly, nullable) AVOutputDevice *outputDevice;
@end
+typedef NS_OPTIONS(NSUInteger, AVOutputDeviceFeatures) {
+ AVOutputDeviceFeatureAudio = (1UL << 0),
+ AVOutputDeviceFeatureScreen = (1UL << 1),
+ AVOutputDeviceFeatureVideo = (1UL << 2),
+};
+
@interface AVOutputDevice : NSObject
@property (nonatomic, readonly) NSString *name;
+@property (nonatomic, readonly) AVOutputDeviceFeatures deviceFeatures;
@end
#if !PLATFORM(IOS_FAMILY)
Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (259302 => 259303)
--- trunk/Source/WebCore/html/HTMLMediaElement.cpp 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp 2020-03-31 19:40:05 UTC (rev 259303)
@@ -1050,11 +1050,8 @@
void HTMLMediaElement::checkPlaybackTargetCompatablity()
{
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
- auto logSiteIdentifier = LOGIDENTIFIER;
- ALWAYS_LOG(logSiteIdentifier, "task scheduled");
if (m_isPlayingToWirelessTarget && !m_player->canPlayToWirelessPlaybackTarget()) {
- UNUSED_PARAM(logSiteIdentifier);
- INFO_LOG(logSiteIdentifier, "calling setShouldPlayToPlaybackTarget(false)");
+ INFO_LOG(LOGIDENTIFIER, "calling setShouldPlayToPlaybackTarget(false)");
m_failedToPlayToWirelessTarget = true;
m_player->setShouldPlayToPlaybackTarget(false);
}
@@ -5850,12 +5847,18 @@
void HTMLMediaElement::setIsPlayingToWirelessTarget(bool isPlayingToWirelessTarget)
{
- m_playbackTargetIsWirelessQueue.enqueueTask([this, isPlayingToWirelessTarget] {
+ auto logSiteIdentifier = LOGIDENTIFIER;
+ ALWAYS_LOG(logSiteIdentifier, isPlayingToWirelessTarget);
+ m_playbackTargetIsWirelessQueue.enqueueTask([this, isPlayingToWirelessTarget, logSiteIdentifier] {
+ UNUSED_PARAM(logSiteIdentifier);
+ ALWAYS_LOG(logSiteIdentifier, "lambda(), task fired");
+
if (isPlayingToWirelessTarget == m_isPlayingToWirelessTarget)
return;
+
m_isPlayingToWirelessTarget = m_player && m_player->isCurrentPlaybackTargetWireless();
m_remote->isPlayingToRemoteTargetChanged(m_isPlayingToWirelessTarget);
- ALWAYS_LOG(LOGIDENTIFIER, m_isPlayingToWirelessTarget);
+ ALWAYS_LOG(logSiteIdentifier, m_isPlayingToWirelessTarget);
configureMediaControls();
m_mediaSession->isPlayingToWirelessPlaybackTargetChanged(m_isPlayingToWirelessTarget);
m_mediaSession->canProduceAudioChanged();
@@ -5949,11 +5952,11 @@
void HTMLMediaElement::setWirelessPlaybackTarget(Ref<MediaPlaybackTarget>&& device)
{
- ALWAYS_LOG(LOGIDENTIFIER);
bool hasActiveRoute = device->hasActiveRoute();
+ ALWAYS_LOG(LOGIDENTIFIER, hasActiveRoute);
+
if (m_player)
m_player->setWirelessPlaybackTarget(WTFMove(device));
-
m_remote->shouldPlayToRemoteTargetChanged(hasActiveRoute);
}
@@ -5961,8 +5964,10 @@
{
ALWAYS_LOG(LOGIDENTIFIER, shouldPlay);
- if (m_player)
+ if (m_player) {
m_player->setShouldPlayToPlaybackTarget(shouldPlay);
+ setIsPlayingToWirelessTarget(m_player->isCurrentPlaybackTargetWireless());
+ }
}
void HTMLMediaElement::playbackTargetPickerWasDismissed()
Modified: trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h (259302 => 259303)
--- trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/platform/audio/PlatformMediaSessionManager.h 2020-03-31 19:40:05 UTC (rev 259303)
@@ -183,11 +183,6 @@
SessionRestrictions m_restrictions[static_cast<unsigned>(PlatformMediaSession::MediaType::WebAudio) + 1];
mutable Vector<WeakPtr<PlatformMediaSession>> m_sessions;
-#if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
- RefPtr<MediaPlaybackTarget> m_playbackTarget;
- bool m_canPlayToTarget { false };
-#endif
-
bool m_interrupted { false };
mutable bool m_isApplicationInBackground { false };
bool m_willIgnoreSystemInterruptions { false };
Modified: trunk/Source/WebCore/platform/audio/cocoa/MediaSessionManagerCocoa.h (259302 => 259303)
--- trunk/Source/WebCore/platform/audio/cocoa/MediaSessionManagerCocoa.h 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/platform/audio/cocoa/MediaSessionManagerCocoa.h 2020-03-31 19:40:05 UTC (rev 259303)
@@ -68,7 +68,7 @@
void addSession(PlatformMediaSession&) final;
void setCurrentSession(PlatformMediaSession&) final;
- bool sessionWillBeginPlayback(PlatformMediaSession&) final;
+ bool sessionWillBeginPlayback(PlatformMediaSession&) override;
void sessionWillEndPlayback(PlatformMediaSession&, DelayCallingUpdateNowPlaying) override;
void sessionDidEndRemoteScrubbing(const PlatformMediaSession&) final;
void clientCharacteristicsChanged(PlatformMediaSession&) final;
Modified: trunk/Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.mm (259302 => 259303)
--- trunk/Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.mm 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.mm 2020-03-31 19:40:05 UTC (rev 259303)
@@ -56,10 +56,6 @@
SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_CarPlayIsConnectedDidChangeNotification, NSString *)
SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_CarPlayIsConnectedNotificationParameter, NSString *)
SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_ServerConnectionDiedNotification, NSString *)
-SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_ActiveAudioRouteDidChangeNotification, NSString *)
-SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_ActiveAudioRouteDidChangeNotificationParameter_ShouldPause, NSString *)
-SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_PickedRouteAttribute, NSString *)
-SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_RouteDescriptionKey_RouteSupportsAirPlayVideo, NSString *)
#endif
using namespace WebCore;
@@ -104,9 +100,11 @@
#if HAVE(CELESTIAL)
void carPlayServerDied();
void updateCarPlayIsConnected(Optional<bool>&&);
- void activeAudioRouteDidChange(Optional<bool>&&);
- void activeVideoRouteDidChange(Optional<bool>&&);
#endif
+#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR) && !PLATFORM(MACCATALYST) && !PLATFORM(WATCHOS)
+ void activeAudioRouteDidChange(bool);
+ void activeVideoRouteDidChange();
+#endif
private:
using HasAvailableTargets = MediaSessionHelperClient::HasAvailableTargets;
@@ -257,18 +255,19 @@
for (auto& client : m_clients)
client.isPlayingToAutomotiveHeadUnitDidChange(m_isPlayingToAutomotiveHeadUnit ? PlayingToAutomotiveHeadUnit::Yes : PlayingToAutomotiveHeadUnit::No);
}
+#endif // HAVE(CELESTIAL)
-void MediaSessionHelperiOS::activeAudioRouteDidChange(Optional<bool>&& shouldPause)
+#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR) && !PLATFORM(MACCATALYST) && !PLATFORM(WATCHOS)
+void MediaSessionHelperiOS::activeAudioRouteDidChange(bool shouldPause)
{
for (auto& client : m_clients)
- client.activeAudioRouteDidChange(shouldPause.valueOr(false) ? ShouldPause::Yes : ShouldPause::No);
+ client.activeAudioRouteDidChange(shouldPause ? ShouldPause::Yes : ShouldPause::No);
}
-void MediaSessionHelperiOS::activeVideoRouteDidChange(Optional<bool>&& supportsAirPlayVideo)
+void MediaSessionHelperiOS::activeVideoRouteDidChange()
{
- m_activeVideoRouteSupportsAirPlayVideo = supportsAirPlayVideo.valueOr(false);
-
- auto playbackTarget = MediaPlaybackTargetCocoa::create([PAL::getAVOutputContextClass() sharedAudioPresentationOutputContext]);
+ auto playbackTarget = MediaPlaybackTargetCocoa::create();
+ m_activeVideoRouteSupportsAirPlayVideo = playbackTarget->supportsRemoteVideoPlayback();
for (auto& client : m_clients)
client.activeVideoRouteDidChange(m_activeVideoRouteSupportsAirPlayVideo ? SupportsAirPlayVideo::Yes : SupportsAirPlayVideo::No, playbackTarget.copyRef());
}
@@ -328,13 +327,15 @@
[center addObserver:self selector:@selector(applicationWillResignActive:) name:WebUIApplicationWillResignActiveNotification object:nil];
[center addObserver:self selector:@selector(applicationDidEnterBackground:) name:PAL::get_UIKit_UIApplicationDidEnterBackgroundNotification() object:nil];
[center addObserver:self selector:@selector(applicationDidEnterBackground:) name:WebUIApplicationDidEnterBackgroundNotification object:nil];
+#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR) && !PLATFORM(MACCATALYST) && !PLATFORM(WATCHOS)
+ [center addObserver:self selector:@selector(activeOutputDeviceDidChange:) name:PAL::get_AVFoundation_AVAudioSessionRouteChangeNotification() object:nil];
+#endif
+
#if HAVE(CELESTIAL)
if (canLoadAVSystemController_ServerConnectionDiedNotification())
[center addObserver:self selector:@selector(carPlayServerDied:) name:getAVSystemController_ServerConnectionDiedNotification() object:nil];
if (canLoadAVSystemController_CarPlayIsConnectedDidChangeNotification())
[center addObserver:self selector:@selector(carPlayIsConnectedDidChange:) name:getAVSystemController_CarPlayIsConnectedDidChangeNotification() object:nil];
- if (canLoadAVSystemController_ActiveAudioRouteDidChangeNotification())
- [center addObserver:self selector:@selector(activeAudioRouteDidChange:) name:getAVSystemController_ActiveAudioRouteDidChangeNotification() object:nil];
#endif
// Now playing won't work unless we turn on the delivery of remote control events.
@@ -541,39 +542,25 @@
callback->updateCarPlayIsConnected(WTFMove(carPlayIsConnected));
});
}
+#endif // HAVE(CELESTIAL)
-- (void)activeAudioRouteDidChange:(NSNotification *)notification
+#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR) && !PLATFORM(MACCATALYST) && !PLATFORM(WATCHOS)
+- (void)activeOutputDeviceDidChange:(NSNotification *)notification
{
if (!_callback)
return;
- UNUSED_PARAM(notification);
- Optional<bool> shouldPause;
- if (notification && canLoadAVSystemController_ActiveAudioRouteDidChangeNotificationParameter_ShouldPause()) {
- NSNumber* nsShouldPause = [notification.userInfo valueForKey:getAVSystemController_ActiveAudioRouteDidChangeNotificationParameter_ShouldPause()];
- if (nsShouldPause)
- shouldPause = nsShouldPause.boolValue;
- }
-
- Optional<bool> supportsAirPlayVideo;
- if (canLoadAVSystemController_PickedRouteAttribute() && canLoadAVSystemController_RouteDescriptionKey_RouteSupportsAirPlayVideo()) {
- NSDictionary* pickedRoute = [[getAVSystemControllerClass() sharedAVSystemController] attributeForKey:getAVSystemController_PickedRouteAttribute()];
- if ([pickedRoute isKindOfClass:NSDictionary.class]) {
- NSNumber* nsSupportsAirPlayVideo = [pickedRoute valueForKey:getAVSystemController_RouteDescriptionKey_RouteSupportsAirPlayVideo()];
- if (nsSupportsAirPlayVideo)
- supportsAirPlayVideo = nsSupportsAirPlayVideo.boolValue;
- }
- }
-
- callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), shouldPause = WTFMove(shouldPause), supportsAirPlayVideo = WTFMove(supportsAirPlayVideo)]() mutable {
+ bool shouldPause = [[notification.userInfo objectForKey:PAL::get_AVFoundation_AVAudioSessionRouteChangeReasonKey()] unsignedIntegerValue] == AVAudioSessionRouteChangeReasonOldDeviceUnavailable;
+ callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), shouldPause]() mutable {
if (auto* callback = protectedSelf->_callback) {
- callback->activeAudioRouteDidChange(WTFMove(shouldPause));
- callback->activeVideoRouteDidChange(WTFMove(supportsAirPlayVideo));
+ callback->activeAudioRouteDidChange(shouldPause);
+ callback->activeVideoRouteDidChange();
}
});
}
-#endif // HAVE(CELESTIAL)
+#endif
+
@end
#endif
Modified: trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h (259302 => 259303)
--- trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h 2020-03-31 19:40:05 UTC (rev 259303)
@@ -53,7 +53,6 @@
bool hasWirelessTargetsAvailable() override;
static WEBCORE_EXPORT void providePresentingApplicationPID();
- using WeakValueType = MediaSessionHelperClient::WeakValueType;
using MediaSessionHelperClient::weakPtrFactory;
private:
@@ -61,10 +60,11 @@
MediaSessionManageriOS();
- void resetRestrictions() override;
+ void resetRestrictions() final;
- void configureWireLessTargetMonitoring() override;
+ void configureWireLessTargetMonitoring() final;
void providePresentingApplicationPIDIfNecessary() final;
+ bool sessionWillBeginPlayback(PlatformMediaSession&) final;
void sessionWillEndPlayback(PlatformMediaSession&, DelayCallingUpdateNowPlaying) final;
// AudioSession::InterruptionObserver
@@ -84,6 +84,11 @@
const char* logClassName() const final { return "MediaSessionManageriOS"; }
#endif
+#if !PLATFORM(WATCHOS)
+ RefPtr<MediaPlaybackTarget> m_playbackTarget;
+ bool m_playbackTargetSupportsAirPlayVideo { false };
+#endif
+
bool m_isMonitoringWirelessRoutes { false };
bool m_havePresentedApplicationPID { false };
};
Modified: trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm (259302 => 259303)
--- trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm 2020-03-31 19:40:05 UTC (rev 259303)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -120,6 +120,26 @@
MediaSessionHelper::sharedHelper().providePresentingApplicationPID(presentingApplicationPID());
}
+bool MediaSessionManageriOS::sessionWillBeginPlayback(PlatformMediaSession& session)
+{
+ if (!PlatformMediaSessionManager::sessionWillBeginPlayback(session))
+ return false;
+
+#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR) && !PLATFORM(MACCATALYST) && !PLATFORM(WATCHOS)
+ if (!m_playbackTarget) {
+ m_playbackTarget = MediaPlaybackTargetCocoa::create();
+ m_playbackTargetSupportsAirPlayVideo = m_playbackTarget->supportsRemoteVideoPlayback();
+ }
+
+ ALWAYS_LOG(LOGIDENTIFIER, m_playbackTargetSupportsAirPlayVideo);
+ if (m_playbackTargetSupportsAirPlayVideo)
+ session.setPlaybackTarget(*m_playbackTarget.copyRef());
+ session.setShouldPlayToPlaybackTarget(m_playbackTargetSupportsAirPlayVideo);
+#endif
+
+ return true;
+}
+
void MediaSessionManageriOS::sessionWillEndPlayback(PlatformMediaSession& session, DelayCallingUpdateNowPlaying delayCallingUpdateNowPlaying)
{
MediaSessionManagerCocoa::sessionWillEndPlayback(session, delayCallingUpdateNowPlaying);
@@ -160,6 +180,12 @@
void MediaSessionManageriOS::activeVideoRouteDidChange(SupportsAirPlayVideo supportsAirPlayVideo, Ref<MediaPlaybackTarget>&& playbackTarget)
{
ALWAYS_LOG(LOGIDENTIFIER, supportsAirPlayVideo);
+
+#if !PLATFORM(WATCHOS)
+ m_playbackTarget = playbackTarget.ptr();
+ m_playbackTargetSupportsAirPlayVideo = supportsAirPlayVideo == SupportsAirPlayVideo::Yes;
+#endif
+
auto nowPlayingSession = nowPlayingEligibleSession();
if (!nowPlayingSession)
return;
Modified: trunk/Source/WebCore/platform/graphics/MediaPlaybackTarget.h (259302 => 259303)
--- trunk/Source/WebCore/platform/graphics/MediaPlaybackTarget.h 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/platform/graphics/MediaPlaybackTarget.h 2020-03-31 19:40:05 UTC (rev 259303)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -44,6 +44,7 @@
virtual const MediaPlaybackTargetContext& targetContext() const = 0;
virtual bool hasActiveRoute() const = 0;
virtual String deviceName() const = 0;
+ virtual bool supportsRemoteVideoPlayback() const = 0;
};
}
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlaybackTargetCocoa.h (259302 => 259303)
--- trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlaybackTargetCocoa.h 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlaybackTargetCocoa.h 2020-03-31 19:40:05 UTC (rev 259303)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,15 +37,19 @@
public:
WEBCORE_EXPORT static Ref<MediaPlaybackTarget> create(AVOutputContext *);
+#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR) && !PLATFORM(MACCATALYST)
+ static Ref<MediaPlaybackTarget> create();
+#endif
+
virtual ~MediaPlaybackTargetCocoa();
- TargetType targetType() const override { return AVFoundation; }
+ TargetType targetType() const final { return AVFoundation; }
- const MediaPlaybackTargetContext& targetContext() const override;
- bool hasActiveRoute() const override;
+ const MediaPlaybackTargetContext& targetContext() const final;
+ bool hasActiveRoute() const final;
+ String deviceName() const final;
+ bool supportsRemoteVideoPlayback() const final;
- String deviceName() const override;
-
AVOutputContext *outputContext() const { return m_outputContext.get(); }
protected:
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlaybackTargetCocoa.mm (259302 => 259303)
--- trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlaybackTargetCocoa.mm 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/MediaPlaybackTargetCocoa.mm 2020-03-31 19:40:05 UTC (rev 259303)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,7 +30,6 @@
#import <objc/runtime.h>
#import <pal/spi/cocoa/AVFoundationSPI.h>
-
#import <pal/cocoa/AVFoundationSoftLink.h>
namespace WebCore {
@@ -46,6 +45,36 @@
{
}
+#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR) && !PLATFORM(MACCATALYST)
+Ref<MediaPlaybackTarget> MediaPlaybackTargetCocoa::create()
+{
+ auto *routingContextUID = [[PAL::getAVAudioSessionClass() sharedInstance] routingContextUID];
+ return adoptRef(*new MediaPlaybackTargetCocoa([PAL::getAVOutputContextClass() outputContextForID:routingContextUID]));
+}
+#endif
+
+bool MediaPlaybackTargetCocoa::supportsRemoteVideoPlayback() const
+{
+ if (!m_outputContext)
+ return false;
+
+ if (![m_outputContext respondsToSelector:@selector(supportsMultipleOutputDevices)] || ![m_outputContext supportsMultipleOutputDevices] || ![m_outputContext respondsToSelector:@selector(outputDevices)]) {
+ if (auto *outputDevice = [m_outputContext outputDevice]) {
+ if (outputDevice.deviceFeatures & AVOutputDeviceFeatureVideo)
+ return true;
+ }
+
+ return false;
+ }
+
+ for (AVOutputDevice *outputDevice in [m_outputContext outputDevices]) {
+ if (outputDevice.deviceFeatures & AVOutputDeviceFeatureVideo)
+ return true;
+ }
+
+ return false;
+}
+
MediaPlaybackTargetCocoa::~MediaPlaybackTargetCocoa()
{
}
@@ -58,7 +87,24 @@
bool MediaPlaybackTargetCocoa::hasActiveRoute() const
{
- return m_outputContext && m_outputContext.get().deviceName;
+ if (!m_outputContext)
+ return false;
+
+ if ([m_outputContext respondsToSelector:@selector(supportsMultipleOutputDevices)] && [m_outputContext supportsMultipleOutputDevices] && [m_outputContext respondsToSelector:@selector(outputDevices)]) {
+ for (AVOutputDevice *outputDevice in [m_outputContext outputDevices]) {
+ if (outputDevice.deviceFeatures & (AVOutputDeviceFeatureVideo | AVOutputDeviceFeatureAudio))
+ return true;
+ }
+
+ return false;
+ }
+
+ if ([m_outputContext respondsToSelector:@selector(outputDevice)]) {
+ if (auto *outputDevice = [m_outputContext outputDevice])
+ return outputDevice.deviceFeatures & (AVOutputDeviceFeatureVideo | AVOutputDeviceFeatureAudio);
+ }
+
+ return m_outputContext.get().deviceName;
}
String MediaPlaybackTargetCocoa::deviceName() const
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm (259302 => 259303)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm 2020-03-31 19:40:05 UTC (rev 259303)
@@ -1221,6 +1221,7 @@
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
void MediaPlayerPrivateMediaSourceAVFObjC::setWirelessPlaybackTarget(Ref<MediaPlaybackTarget>&& target)
{
+ ALWAYS_LOG(LOGIDENTIFIER);
m_playbackTarget = WTFMove(target);
}
@@ -1233,7 +1234,7 @@
m_shouldPlayToTarget = shouldPlayToTarget;
if (m_player)
- m_player->currentPlaybackTargetIsWirelessChanged(m_player->isCurrentPlaybackTargetWireless());
+ m_player->currentPlaybackTargetIsWirelessChanged(isCurrentPlaybackTargetWireless());
}
bool MediaPlayerPrivateMediaSourceAVFObjC::isCurrentPlaybackTargetWireless() const
Modified: trunk/Source/WebCore/platform/mock/MediaPlaybackTargetMock.h (259302 => 259303)
--- trunk/Source/WebCore/platform/mock/MediaPlaybackTargetMock.h 2020-03-31 19:19:43 UTC (rev 259302)
+++ trunk/Source/WebCore/platform/mock/MediaPlaybackTargetMock.h 2020-03-31 19:40:05 UTC (rev 259303)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -40,13 +40,14 @@
virtual ~MediaPlaybackTargetMock();
- TargetType targetType() const override { return Mock; }
+ TargetType targetType() const final { return Mock; }
- const MediaPlaybackTargetContext& targetContext() const override;
+ const MediaPlaybackTargetContext& targetContext() const final;
- bool hasActiveRoute() const override { return !m_name.isEmpty(); }
+ bool hasActiveRoute() const final { return !m_name.isEmpty(); }
+ bool supportsRemoteVideoPlayback() const final { return !m_name.isEmpty(); }
- String deviceName() const override { return m_name; }
+ String deviceName() const final { return m_name; }
MediaPlaybackTargetContext::State state() const;