Changeset 237378 in webkit


Ignore:
Timestamp:
Oct 24, 2018 3:03:31 AM (5 years ago)
Author:
jer.noble@apple.com
Message:

Use WeakPtr and GenericTaskQueue within ObjC classes used by MediaPlayerPrivateAVFoundationObjC
https://bugs.webkit.org/show_bug.cgi?id=190790

Reviewed by Alex Christensen.

Move towards using WeakPtr callbacks instead of raw pointers within the utility objects used by
MediaPlayerPrivateAVFoundationObjC. Additionally, accessing WeakPtr off the thread which created
the pointer is not allowed, so use a GenericTaskQueue to schedule callbacks instead. Make
GenericTaskQueue<Timer> thread-safe by locking around access to m_pendingTasks, and by making
incrementing the pending task count atomic.

  • platform/GenericTaskQueue.cpp:

(WebCore::TaskDispatcher<Timer>::postTask):
(WebCore::TaskDispatcher<Timer>::sharedLock):
(WebCore::TaskDispatcher<Timer>::sharedTimerFired):
(WebCore::TaskDispatcher<Timer>::dispatchOneTask):
(WebCore::TaskDispatcher<Timer>::pendingDispatchers):

  • platform/GenericTaskQueue.h:
  • platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
  • platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:

(WebCore::MediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC):
(WebCore::MediaPlayerPrivateAVFoundationObjC::~MediaPlayerPrivateAVFoundationObjC):
(-[WebCoreAVFMovieObserver initWithPlayer:]):
(-[WebCoreAVFMovieObserver disconnect]):
(-[WebCoreAVFMovieObserver metadataLoaded]):
(-[WebCoreAVFMovieObserver didEnd:]):
(-[WebCoreAVFMovieObserver observeValueForKeyPath:ofObject:change:context:]):
(-[WebCoreAVFMovieObserver legibleOutput:didOutputAttributedStrings:nativeSampleBuffers:forItemTime:]):
(-[WebCoreAVFMovieObserver outputSequenceWasFlushed:]):
(-[WebCoreAVFLoaderDelegate initWithPlayer:]):
(-[WebCoreAVFLoaderDelegate resourceLoader:shouldWaitForLoadingOfRequestedResource:]):
(-[WebCoreAVFLoaderDelegate resourceLoader:didCancelLoadingRequest:]):
(-[WebCoreAVFPullDelegate initWithPlayer:]):
(-[WebCoreAVFPullDelegate outputMediaDataWillChange:]):
(-[WebCoreAVFMovieObserver initWithCallback:]): Deleted.
(-[WebCoreAVFLoaderDelegate initWithCallback:]): Deleted.
(-[WebCoreAVFLoaderDelegate setCallback:]): Deleted.
(-[WebCoreAVFPullDelegate initWithCallback:]): Deleted.
(-[WebCoreAVFPullDelegate setCallback:]): Deleted.

Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r237376 r237378  
     12018-10-22  Jer Noble  <jer.noble@apple.com>
     2
     3        Use WeakPtr and GenericTaskQueue within ObjC classes used by MediaPlayerPrivateAVFoundationObjC
     4        https://bugs.webkit.org/show_bug.cgi?id=190790
     5
     6        Reviewed by Alex Christensen.
     7
     8        Move towards using WeakPtr callbacks instead of raw pointers within the utility objects used by
     9        MediaPlayerPrivateAVFoundationObjC. Additionally, accessing WeakPtr off the thread which created
     10        the pointer is not allowed, so use a GenericTaskQueue to schedule callbacks instead. Make
     11        GenericTaskQueue<Timer> thread-safe by locking around access to m_pendingTasks, and by making
     12        incrementing the pending task count atomic.
     13
     14        * platform/GenericTaskQueue.cpp:
     15        (WebCore::TaskDispatcher<Timer>::postTask):
     16        (WebCore::TaskDispatcher<Timer>::sharedLock):
     17        (WebCore::TaskDispatcher<Timer>::sharedTimerFired):
     18        (WebCore::TaskDispatcher<Timer>::dispatchOneTask):
     19        (WebCore::TaskDispatcher<Timer>::pendingDispatchers):
     20        * platform/GenericTaskQueue.h:
     21        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
     22        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
     23        (WebCore::MediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC):
     24        (WebCore::MediaPlayerPrivateAVFoundationObjC::~MediaPlayerPrivateAVFoundationObjC):
     25        (-[WebCoreAVFMovieObserver initWithPlayer:]):
     26        (-[WebCoreAVFMovieObserver disconnect]):
     27        (-[WebCoreAVFMovieObserver metadataLoaded]):
     28        (-[WebCoreAVFMovieObserver didEnd:]):
     29        (-[WebCoreAVFMovieObserver observeValueForKeyPath:ofObject:change:context:]):
     30        (-[WebCoreAVFMovieObserver legibleOutput:didOutputAttributedStrings:nativeSampleBuffers:forItemTime:]):
     31        (-[WebCoreAVFMovieObserver outputSequenceWasFlushed:]):
     32        (-[WebCoreAVFLoaderDelegate initWithPlayer:]):
     33        (-[WebCoreAVFLoaderDelegate resourceLoader:shouldWaitForLoadingOfRequestedResource:]):
     34        (-[WebCoreAVFLoaderDelegate resourceLoader:didCancelLoadingRequest:]):
     35        (-[WebCoreAVFPullDelegate initWithPlayer:]):
     36        (-[WebCoreAVFPullDelegate outputMediaDataWillChange:]):
     37        (-[WebCoreAVFMovieObserver initWithCallback:]): Deleted.
     38        (-[WebCoreAVFLoaderDelegate initWithCallback:]): Deleted.
     39        (-[WebCoreAVFLoaderDelegate setCallback:]): Deleted.
     40        (-[WebCoreAVFPullDelegate initWithCallback:]): Deleted.
     41        (-[WebCoreAVFPullDelegate setCallback:]): Deleted.
     42
    1432018-10-23  Jer Noble  <jer.noble@apple.com>
    244
  • trunk/Source/WebCore/platform/GenericTaskQueue.cpp

    r237364 r237378  
    2727#include "GenericTaskQueue.h"
    2828
     29#include <wtf/Lock.h>
    2930#include <wtf/MainThread.h>
    3031#include <wtf/NeverDestroyed.h>
     
    3839void TaskDispatcher<Timer>::postTask(Function<void()>&& function)
    3940{
    40     m_pendingTasks.append(WTFMove(function));
    41     pendingDispatchers().append(makeWeakPtr(*this));
    42     if (!sharedTimer().isActive())
    43         sharedTimer().startOneShot(0_s);
     41    {
     42        auto locker = holdLock(sharedLock());
     43        m_pendingTasks.append(WTFMove(function));
     44        pendingDispatchers().append(makeWeakPtr(*this));
     45    }
     46
     47    auto startTimer = [] {
     48        if (!sharedTimer().isActive())
     49            sharedTimer().startOneShot(0_s);
     50    };
     51    if (isMainThread())
     52        startTimer();
     53    else
     54        callOnMainThread(WTFMove(startTimer));
    4455}
    4556
     
    5162}
    5263
     64Lock& TaskDispatcher<Timer>::sharedLock()
     65{
     66    static NeverDestroyed<Lock> lock;
     67    return lock;
     68}
     69
    5370void TaskDispatcher<Timer>::sharedTimerFired()
    5471{
    5572    ASSERT(!sharedTimer().isActive());
    56     ASSERT(!pendingDispatchers().isEmpty());
    5773
    5874    // Copy the pending events first because we don't want to process synchronously the new events
    5975    // queued by the JS events handlers that are executed in the loop below.
    60     Deque<WeakPtr<TaskDispatcher<Timer>>> queuedDispatchers = WTFMove(pendingDispatchers());
     76    Deque<WeakPtr<TaskDispatcher<Timer>>> queuedDispatchers;
     77    {
     78        auto locker = holdLock(sharedLock());
     79        queuedDispatchers = WTFMove(pendingDispatchers());
     80    }
    6181    while (!queuedDispatchers.isEmpty()) {
    6282        WeakPtr<TaskDispatcher<Timer>> dispatcher = queuedDispatchers.takeFirst();
     
    6787}
    6888
     89
    6990Deque<WeakPtr<TaskDispatcher<Timer>>>& TaskDispatcher<Timer>::pendingDispatchers()
    7091{
    71     ASSERT(isMainThread());
    72     static NeverDestroyed<Deque<WeakPtr<TaskDispatcher<Timer>>>> dispatchers;
     92    static LazyNeverDestroyed<Deque<WeakPtr<TaskDispatcher<Timer>>>> dispatchers;
     93
     94    static std::once_flag onceFlag;
     95    std::call_once(onceFlag, [] {
     96        dispatchers.construct();
     97    });
     98
    7399    return dispatchers.get();
    74100}
     
    76102void TaskDispatcher<Timer>::dispatchOneTask()
    77103{
    78     ASSERT(!m_pendingTasks.isEmpty());
    79     auto task = m_pendingTasks.takeFirst();
     104    WTF::Function<void()> task;
     105    {
     106        auto locker = holdLock(sharedLock());
     107        ASSERT(!m_pendingTasks.isEmpty());
     108        task = m_pendingTasks.takeFirst();
     109    }
    80110    task();
    81111}
  • trunk/Source/WebCore/platform/GenericTaskQueue.h

    r237364 r237378  
    3131#include <wtf/WeakPtr.h>
    3232
     33namespace WTF {
     34class Lock;
     35};
     36
    3337namespace WebCore {
    3438
     
    5963private:
    6064    static Timer& sharedTimer();
     65    static WTF::Lock& sharedLock();
    6166    static void sharedTimerFired();
    6267    static Deque<WeakPtr<TaskDispatcher<Timer>>>& pendingDispatchers();
     
    6772};
    6873
    69 template <typename T>
    70 class GenericTaskQueue : public CanMakeWeakPtr<GenericTaskQueue<T>> {
     74template <typename T, typename C = unsigned>
     75class GenericTaskQueue : public CanMakeWeakPtr<GenericTaskQueue<T, C>> {
    7176public:
    7277    GenericTaskQueue()
     
    120125private:
    121126    TaskDispatcher<T> m_dispatcher;
    122     unsigned m_pendingTasks { 0 };
     127    C m_pendingTasks { 0 };
    123128    bool m_isClosed { false };
    124129};
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h

    r237376 r237378  
    333333    bool performTaskAtMediaTime(WTF::Function<void()>&&, MediaTime) final;
    334334
     335    WeakPtrFactory<MediaPlayerPrivateAVFoundationObjC> m_weakPtrFactory;
    335336    RetainPtr<AVURLAsset> m_avAsset;
    336337    RetainPtr<AVPlayer> m_avPlayer;
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm

    r237376 r237378  
    337337#endif
    338338{
    339     MediaPlayerPrivateAVFoundationObjC* m_callback;
     339    WeakPtr<MediaPlayerPrivateAVFoundationObjC> m_player;
     340    GenericTaskQueue<Timer, std::atomic<unsigned>> m_taskQueue;
    340341    int m_delayCallbacks;
    341342}
    342 -(id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback;
     343-(id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)callback;
    343344-(void)disconnect;
    344345-(void)metadataLoaded;
     
    353354#if HAVE(AVFOUNDATION_LOADER_DELEGATE)
    354355@interface WebCoreAVFLoaderDelegate : NSObject<AVAssetResourceLoaderDelegate> {
    355     MediaPlayerPrivateAVFoundationObjC* m_callback;
    356 }
    357 - (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback;
     356    WeakPtr<MediaPlayerPrivateAVFoundationObjC> m_player;
     357    GenericTaskQueue<Timer, std::atomic<unsigned>> m_taskQueue;
     358}
     359- (id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)player;
    358360- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest;
    359 - (void)setCallback:(MediaPlayerPrivateAVFoundationObjC*)callback;
    360361@end
    361362#endif
     
    363364#if HAVE(AVFOUNDATION_VIDEO_OUTPUT)
    364365@interface WebCoreAVFPullDelegate : NSObject<AVPlayerItemOutputPullDelegate> {
    365     MediaPlayerPrivateAVFoundationObjC *m_callback;
    366 }
    367 - (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC *)callback;
    368 - (void)setCallback:(MediaPlayerPrivateAVFoundationObjC*)callback;
     366    WeakPtr<MediaPlayerPrivateAVFoundationObjC> m_player;
     367}
     368- (id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)player;
    369369- (void)outputMediaDataWillChange:(AVPlayerItemOutput *)sender;
    370370- (void)outputSequenceWasFlushed:(AVPlayerItemOutput *)output;
     
    502502    , m_videoFullscreenLayerManager(std::make_unique<VideoFullscreenLayerManagerObjC>())
    503503    , m_videoFullscreenGravity(MediaPlayer::VideoGravityResizeAspect)
    504     , m_objcObserver(adoptNS([[WebCoreAVFMovieObserver alloc] initWithCallback:this]))
     504    , m_objcObserver(adoptNS([[WebCoreAVFMovieObserver alloc] initWithPlayer:m_weakPtrFactory.createWeakPtr(*this)]))
    505505    , m_videoFrameHasDrawn(false)
    506506    , m_haveCheckedPlayability(false)
    507507#if HAVE(AVFOUNDATION_VIDEO_OUTPUT)
    508     , m_videoOutputDelegate(adoptNS([[WebCoreAVFPullDelegate alloc] initWithCallback:this]))
     508    , m_videoOutputDelegate(adoptNS([[WebCoreAVFPullDelegate alloc] initWithPlayer:m_weakPtrFactory.createWeakPtr(*this)]))
    509509#endif
    510510#if HAVE(AVFOUNDATION_LOADER_DELEGATE)
    511     , m_loaderDelegate(adoptNS([[WebCoreAVFLoaderDelegate alloc] initWithCallback:this]))
     511    , m_loaderDelegate(adoptNS([[WebCoreAVFLoaderDelegate alloc] initWithPlayer:m_weakPtrFactory.createWeakPtr(*this)]))
    512512#endif
    513513    , m_currentTextTrack(0)
     
    531531MediaPlayerPrivateAVFoundationObjC::~MediaPlayerPrivateAVFoundationObjC()
    532532{
     533    m_weakPtrFactory.revokeAll();
     534
    533535#if HAVE(AVFOUNDATION_LOADER_DELEGATE)
    534     [m_loaderDelegate.get() setCallback:0];
    535536    [[m_avAsset.get() resourceLoader] setDelegate:nil queue:0];
    536537
     
    539540#endif
    540541#if HAVE(AVFOUNDATION_VIDEO_OUTPUT)
    541     [m_videoOutputDelegate setCallback:0];
    542542    [m_videoOutput setDelegate:nil queue:0];
    543543#endif
     
    33633363@implementation WebCoreAVFMovieObserver
    33643364
    3365 - (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback
     3365- (id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)player
    33663366{
    33673367    self = [super init];
    33683368    if (!self)
    33693369        return nil;
    3370     m_callback = callback;
     3370    m_player = WTFMove(player);
    33713371    return self;
    33723372}
     
    33743374- (void)disconnect
    33753375{
    3376     [NSObject cancelPreviousPerformRequestsWithTarget:self];
    3377     m_callback = nil;
     3376    m_player = nullptr;
    33783377}
    33793378
    33803379- (void)metadataLoaded
    33813380{
    3382     if (!m_callback)
    3383         return;
    3384     m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::AssetMetadataLoaded);
     3381    m_taskQueue.enqueueTask([player = m_player] {
     3382        if (player)
     3383            player->metadataLoaded();
     3384    });
    33853385}
    33863386
     
    33883388{
    33893389    UNUSED_PARAM(unusedNotification);
    3390     if (!m_callback)
    3391         return;
    3392     m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemDidPlayToEndTime);
     3390    m_taskQueue.enqueueTask([player = m_player] {
     3391        if (player)
     3392            player->didEnd();
     3393    });
    33933394}
    33943395
    33953396- (void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(MediaPlayerAVFoundationObservationContext)context
    33963397{
    3397     UNUSED_PARAM(object);
    3398     id newValue = [change valueForKey:NSKeyValueChangeNewKey];
    3399 
    3400     if (!m_callback)
    3401         return;
    3402 
    3403     bool willChange = [[change valueForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue];
    3404     bool shouldLogValue = !willChange;
    3405     WTF::Function<void ()> function;
    3406 
    3407     if (context == MediaPlayerAVFoundationObservationContextAVPlayerLayer) {
    3408         if ([keyPath isEqualToString:@"readyForDisplay"])
    3409             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::firstFrameAvailableDidChange, m_callback, [newValue boolValue]);
    3410     }
    3411 
    3412     if (context == MediaPlayerAVFoundationObservationContextPlayerItemTrack) {
    3413         if ([keyPath isEqualToString:@"enabled"])
    3414             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::trackEnabledDidChange, m_callback, [newValue boolValue]);
    3415     }
    3416 
    3417     if (context == MediaPlayerAVFoundationObservationContextPlayerItem && willChange) {
    3418         if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
    3419             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackLikelyToKeepUpWillChange, m_callback);
    3420         else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
    3421             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackBufferEmptyWillChange, m_callback);
    3422         else if ([keyPath isEqualToString:@"playbackBufferFull"])
    3423             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackBufferFullWillChange, m_callback);
    3424     }
    3425 
    3426     if (context == MediaPlayerAVFoundationObservationContextPlayerItem && !willChange) {
    3427         // A value changed for an AVPlayerItem
    3428         if ([keyPath isEqualToString:@"status"])
    3429             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playerItemStatusDidChange, m_callback, [newValue intValue]);
    3430         else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
    3431             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackLikelyToKeepUpDidChange, m_callback, [newValue boolValue]);
    3432         else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
    3433             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackBufferEmptyDidChange, m_callback, [newValue boolValue]);
    3434         else if ([keyPath isEqualToString:@"playbackBufferFull"])
    3435             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackBufferFullDidChange, m_callback, [newValue boolValue]);
    3436         else if ([keyPath isEqualToString:@"asset"]) {
    3437             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::setAsset, m_callback, RetainPtr<id>(newValue));
    3438             shouldLogValue = false;
    3439         } else if ([keyPath isEqualToString:@"loadedTimeRanges"])
    3440             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::loadedTimeRangesDidChange, m_callback, RetainPtr<NSArray>(newValue));
    3441         else if ([keyPath isEqualToString:@"seekableTimeRanges"])
    3442             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::seekableTimeRangesDidChange, m_callback, RetainPtr<NSArray>(newValue));
    3443         else if ([keyPath isEqualToString:@"tracks"]) {
    3444             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::tracksDidChange, m_callback, RetainPtr<NSArray>(newValue));
    3445             shouldLogValue = false;
    3446         } else if ([keyPath isEqualToString:@"hasEnabledAudio"])
    3447             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::hasEnabledAudioDidChange, m_callback, [newValue boolValue]);
    3448         else if ([keyPath isEqualToString:@"presentationSize"])
    3449             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::presentationSizeDidChange, m_callback, FloatSize([newValue sizeValue]));
    3450         else if ([keyPath isEqualToString:@"duration"])
    3451             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::durationDidChange, m_callback, PAL::toMediaTime([newValue CMTimeValue]));
    3452         else if ([keyPath isEqualToString:@"timedMetadata"] && newValue) {
    3453             MediaTime now;
    3454             CMTime itemTime = [(AVPlayerItemType *)object currentTime];
    3455             if (CMTIME_IS_NUMERIC(itemTime))
    3456                 now = std::max(PAL::toMediaTime(itemTime), MediaTime::zeroTime());
    3457             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::metadataDidArrive, m_callback, RetainPtr<NSArray>(newValue), now);
    3458             shouldLogValue = false;
    3459         } else if ([keyPath isEqualToString:@"canPlayFastReverse"])
    3460             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::canPlayFastReverseDidChange, m_callback, [newValue boolValue]);
    3461         else if ([keyPath isEqualToString:@"canPlayFastForward"])
    3462             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::canPlayFastForwardDidChange, m_callback, [newValue boolValue]);
    3463     }
    3464 
    3465     if (context == MediaPlayerAVFoundationObservationContextPlayer && !willChange) {
    3466         // A value changed for an AVPlayer.
    3467         if ([keyPath isEqualToString:@"rate"])
    3468             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::rateDidChange, m_callback, [newValue doubleValue]);
     3398    m_taskQueue.enqueueTask([player = m_player, keyPath = retainPtr(keyPath), change = retainPtr(change), object = retainPtr(object), context] {
     3399        if (!player)
     3400            return;
     3401        id newValue = [change valueForKey:NSKeyValueChangeNewKey];
     3402        bool willChange = [[change valueForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue];
     3403        bool shouldLogValue = !willChange;
     3404
     3405        if (context == MediaPlayerAVFoundationObservationContextAVPlayerLayer) {
     3406            if ([keyPath isEqualToString:@"readyForDisplay"])
     3407                player->firstFrameAvailableDidChange([newValue boolValue]);
     3408        }
     3409
     3410        if (context == MediaPlayerAVFoundationObservationContextPlayerItemTrack) {
     3411            if ([keyPath isEqualToString:@"enabled"])
     3412                player->trackEnabledDidChange([newValue boolValue]);
     3413        }
     3414
     3415        if (context == MediaPlayerAVFoundationObservationContextPlayerItem && willChange) {
     3416            if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
     3417                player->playbackLikelyToKeepUpWillChange();
     3418            else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
     3419                player->playbackBufferEmptyWillChange();
     3420            else if ([keyPath isEqualToString:@"playbackBufferFull"])
     3421                player->playbackBufferFullWillChange();
     3422        }
     3423
     3424        if (context == MediaPlayerAVFoundationObservationContextPlayerItem && !willChange) {
     3425            // A value changed for an AVPlayerItem
     3426            if ([keyPath isEqualToString:@"status"])
     3427                player->playerItemStatusDidChange([newValue intValue]);
     3428            else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
     3429                player->playbackLikelyToKeepUpDidChange([newValue boolValue]);
     3430            else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
     3431                player->playbackBufferEmptyDidChange([newValue boolValue]);
     3432            else if ([keyPath isEqualToString:@"playbackBufferFull"])
     3433                player->playbackBufferFullDidChange([newValue boolValue]);
     3434            else if ([keyPath isEqualToString:@"asset"]) {
     3435                player->setAsset(RetainPtr<id>(newValue));
     3436                shouldLogValue = false;
     3437            } else if ([keyPath isEqualToString:@"loadedTimeRanges"])
     3438                player->loadedTimeRangesDidChange(RetainPtr<NSArray>(newValue));
     3439            else if ([keyPath isEqualToString:@"seekableTimeRanges"])
     3440                player->seekableTimeRangesDidChange(RetainPtr<NSArray>(newValue));
     3441            else if ([keyPath isEqualToString:@"tracks"]) {
     3442                player->tracksDidChange(RetainPtr<NSArray>(newValue));
     3443                shouldLogValue = false;
     3444            } else if ([keyPath isEqualToString:@"hasEnabledAudio"])
     3445                player->hasEnabledAudioDidChange([newValue boolValue]);
     3446            else if ([keyPath isEqualToString:@"presentationSize"])
     3447                player->presentationSizeDidChange(FloatSize([newValue sizeValue]));
     3448            else if ([keyPath isEqualToString:@"duration"])
     3449                player->durationDidChange(PAL::toMediaTime([newValue CMTimeValue]));
     3450            else if ([keyPath isEqualToString:@"timedMetadata"] && newValue) {
     3451                MediaTime now;
     3452                CMTime itemTime = [(AVPlayerItemType *)object.get() currentTime];
     3453                if (CMTIME_IS_NUMERIC(itemTime))
     3454                    now = std::max(PAL::toMediaTime(itemTime), MediaTime::zeroTime());
     3455                player->metadataDidArrive(RetainPtr<NSArray>(newValue), now);
     3456                shouldLogValue = false;
     3457            } else if ([keyPath isEqualToString:@"canPlayFastReverse"])
     3458                player->canPlayFastReverseDidChange([newValue boolValue]);
     3459            else if ([keyPath isEqualToString:@"canPlayFastForward"])
     3460                player->canPlayFastForwardDidChange([newValue boolValue]);
     3461        }
     3462
     3463        if (context == MediaPlayerAVFoundationObservationContextPlayer && !willChange) {
     3464            // A value changed for an AVPlayer.
     3465            if ([keyPath isEqualToString:@"rate"])
     3466                player->rateDidChange([newValue doubleValue]);
    34693467#if ENABLE(WIRELESS_PLAYBACK_TARGET)
    3470         else if ([keyPath isEqualToString:@"externalPlaybackActive"] || [keyPath isEqualToString:@"allowsExternalPlayback"])
    3471             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackTargetIsWirelessDidChange, m_callback);
     3468            else if ([keyPath isEqualToString:@"externalPlaybackActive"] || [keyPath isEqualToString:@"allowsExternalPlayback"])
     3469                player->playbackTargetIsWirelessDidChange();
    34723470#endif
    34733471#if ENABLE(LEGACY_ENCRYPTED_MEDIA) || ENABLE(ENCRYPTED_MEDIA)
    3474         else if ([keyPath isEqualToString:@"outputObscuredDueToInsufficientExternalProtection"])
    3475             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::outputObscuredDueToInsufficientExternalProtectionChanged, m_callback, [newValue boolValue]);
    3476 #endif
    3477     }
     3472            else if ([keyPath isEqualToString:@"outputObscuredDueToInsufficientExternalProtection"])
     3473                player->outputObscuredDueToInsufficientExternalProtectionChanged([newValue boolValue]);
     3474#endif
     3475        }
    34783476
    34793477#if !RELEASE_LOG_DISABLED
    3480     if (m_callback->logger().willLog(m_callback->logChannel(), WTFLogLevelDebug) && !([keyPath isEqualToString:@"loadedTimeRanges"] || [keyPath isEqualToString:@"seekableTimeRanges"])) {
    3481         auto identifier = Logger::LogSiteIdentifier("MediaPlayerPrivateAVFoundation", "observeValueForKeyPath", m_callback->logIdentifier());
    3482 
    3483         if (shouldLogValue) {
    3484             if ([keyPath isEqualToString:@"duration"])
    3485                 m_callback->logger().debug(m_callback->logChannel(), identifier, "did change '", [keyPath UTF8String], "' to ", PAL::toMediaTime([newValue CMTimeValue]));
    3486             else {
    3487                 RetainPtr<NSString> valueString = adoptNS([[NSString alloc] initWithFormat:@"%@", newValue]);
    3488                 m_callback->logger().debug(m_callback->logChannel(), identifier, "did change '", [keyPath UTF8String], "' to ", [valueString.get() UTF8String]);
    3489             }
    3490         } else
    3491             m_callback->logger().debug(m_callback->logChannel(), identifier, willChange ? "will" : "did", " change '", [keyPath UTF8String], "'");
    3492     }
    3493 #endif
    3494 
    3495     if (!function)
    3496         return;
    3497 
    3498     auto weakThis = makeWeakPtr(*m_callback);
    3499     m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification([weakThis, function = WTFMove(function)]{
    3500         // weakThis and function both refer to the same MediaPlayerPrivateAVFoundationObjC instance. If the WeakPtr has
    3501         // been cleared, the underlying object has been destroyed, and it is unsafe to call function().
    3502         if (!weakThis)
    3503             return;
    3504         function();
    3505     }));
     3478        if (player->logger().willLog(player->logChannel(), WTFLogLevelDebug) && !([keyPath isEqualToString:@"loadedTimeRanges"] || [keyPath isEqualToString:@"seekableTimeRanges"])) {
     3479            auto identifier = Logger::LogSiteIdentifier("MediaPlayerPrivateAVFoundation", "observeValueForKeyPath", player->logIdentifier());
     3480
     3481            if (shouldLogValue) {
     3482                if ([keyPath isEqualToString:@"duration"])
     3483                    player->logger().debug(player->logChannel(), identifier, "did change '", [keyPath UTF8String], "' to ", PAL::toMediaTime([newValue CMTimeValue]));
     3484                else {
     3485                    RetainPtr<NSString> valueString = adoptNS([[NSString alloc] initWithFormat:@"%@", newValue]);
     3486                    player->logger().debug(player->logChannel(), identifier, "did change '", [keyPath UTF8String], "' to ", [valueString.get() UTF8String]);
     3487                }
     3488            } else
     3489                player->logger().debug(player->logChannel(), identifier, willChange ? "will" : "did", " change '", [keyPath UTF8String], "'");
     3490        }
     3491#endif
     3492    });
    35063493}
    35073494
     
    35113498{
    35123499    UNUSED_PARAM(output);
    3513     UNUSED_PARAM(nativeSamples);
    3514 
    3515     if (!m_callback)
    3516         return;
    3517 
    3518     RetainPtr<WebCoreAVFMovieObserver> protectedSelf = self;
    3519     RetainPtr<NSArray> protectedStrings = strings;
    3520     RetainPtr<NSArray> protectedNativeSamples = nativeSamples;
    3521     callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedStrings = WTFMove(protectedStrings), protectedNativeSamples = WTFMove(protectedNativeSamples), itemTime] {
    3522         MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback;
    3523         if (!callback)
     3500
     3501    m_taskQueue.enqueueTask([player = m_player, strings = retainPtr(strings), nativeSamples = retainPtr(nativeSamples), itemTime] {
     3502        if (!player)
    35243503            return;
    35253504        MediaTime time = std::max(PAL::toMediaTime(itemTime), MediaTime::zeroTime());
    3526         callback->processCue(protectedStrings.get(), protectedNativeSamples.get(), time);
     3505        player->processCue(strings.get(), nativeSamples.get(), time);
    35273506    });
    35283507}
     
    35323511    UNUSED_PARAM(output);
    35333512
    3534     if (!m_callback)
    3535         return;
    3536    
    3537     callOnMainThread([protectedSelf = RetainPtr<WebCoreAVFMovieObserver>(self)] {
    3538         if (MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback)
    3539             callback->flushCues();
     3513    m_taskQueue.enqueueTask([player = m_player] {
     3514        if (player)
     3515            player->flushCues();
    35403516    });
    35413517}
     
    35493525@implementation WebCoreAVFLoaderDelegate
    35503526
    3551 - (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback
     3527- (id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)player
    35523528{
    35533529    self = [super init];
    35543530    if (!self)
    35553531        return nil;
    3556     m_callback = callback;
     3532    m_player = WTFMove(player);
    35573533    return self;
    35583534}
     
    35613537{
    35623538    UNUSED_PARAM(resourceLoader);
    3563     if (!m_callback)
     3539    if (!m_player)
    35643540        return NO;
    35653541
    3566     RetainPtr<WebCoreAVFLoaderDelegate> protectedSelf = self;
    3567     RetainPtr<AVAssetResourceLoadingRequest> protectedLoadingRequest = loadingRequest;
    3568     callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedLoadingRequest = WTFMove(protectedLoadingRequest)] {
    3569         MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback;
    3570         if (!callback) {
    3571             [protectedLoadingRequest finishLoadingWithError:nil];
     3542    m_taskQueue.enqueueTask([player = m_player, loadingRequest = retainPtr(loadingRequest)] {
     3543        if (!player) {
     3544            [loadingRequest finishLoadingWithError:nil];
    35723545            return;
    35733546        }
    35743547
    3575         if (!callback->shouldWaitForLoadingOfResource(protectedLoadingRequest.get()))
    3576             [protectedLoadingRequest finishLoadingWithError:nil];
     3548        if (!player->shouldWaitForLoadingOfResource(loadingRequest.get()))
     3549            [loadingRequest finishLoadingWithError:nil];
    35773550    });
    35783551
     
    35913564{
    35923565    UNUSED_PARAM(resourceLoader);
    3593     if (!m_callback)
    3594         return;
    3595 
    3596     RetainPtr<WebCoreAVFLoaderDelegate> protectedSelf = self;
    3597     RetainPtr<AVAssetResourceLoadingRequest> protectedLoadingRequest = loadingRequest;
    3598     callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedLoadingRequest = WTFMove(protectedLoadingRequest)] {
    3599         MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback;
    3600         if (callback)
    3601             callback->didCancelLoadingRequest(protectedLoadingRequest.get());
     3566    m_taskQueue.enqueueTask([player = m_player, loadingRequest = retainPtr(loadingRequest)] {
     3567        if (player)
     3568            player->didCancelLoadingRequest(loadingRequest.get());
    36023569    });
    36033570}
    36043571
    3605 - (void)setCallback:(MediaPlayerPrivateAVFoundationObjC*)callback
    3606 {
    3607     m_callback = callback;
    3608 }
    36093572@end
    36103573
     
    36153578@implementation WebCoreAVFPullDelegate
    36163579
    3617 - (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC *)callback
     3580- (id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)player
    36183581{
    36193582    self = [super init];
    36203583    if (self)
    3621         m_callback = callback;
     3584        m_player = WTFMove(player);
    36223585    return self;
    36233586}
    36243587
    3625 - (void)setCallback:(MediaPlayerPrivateAVFoundationObjC *)callback
    3626 {
    3627     m_callback = callback;
    3628 }
    3629 
    36303588- (void)outputMediaDataWillChange:(AVPlayerItemVideoOutputType *)output
    36313589{
    3632     if (m_callback)
    3633         m_callback->outputMediaDataWillChange(output);
     3590    if (m_player)
     3591        m_player->outputMediaDataWillChange(output);
    36343592}
    36353593
Note: See TracChangeset for help on using the changeset viewer.