Title: [259303] trunk/Source/WebCore
Revision
259303
Author
[email protected]
Date
2020-03-31 12:40:05 -0700 (Tue, 31 Mar 2020)

Log Message

[iPad] Use AVAudioSession to detect AirPlay route changes
https://bugs.webkit.org/show_bug.cgi?id=209789
<rdar://problem/58065279>

Reviewed by Jer Noble.

Source/WebCore:

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:

Source/WebCore/PAL:

* pal/cocoa/AVFoundationSoftLink.h:
* pal/cocoa/AVFoundationSoftLink.mm:
* pal/spi/cocoa/AVFoundationSPI.h:

Modified Paths

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;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to