Changeset 237350 in webkit


Ignore:
Timestamp:
Oct 23, 2018 7:40:58 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

    r237347 r237350  
     12018-10-23  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-22  Justin Michaud  <justin_michaud@apple.com>
    244
  • trunk/Source/WebCore/platform/GenericTaskQueue.cpp

    r232613 r237350  
    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{
     
    5875    // Copy the pending events first because we don't want to process synchronously the new events
    5976    // queued by the JS events handlers that are executed in the loop below.
    60     Deque<WeakPtr<TaskDispatcher<Timer>>> queuedDispatchers = WTFMove(pendingDispatchers());
     77    Deque<WeakPtr<TaskDispatcher<Timer>>> queuedDispatchers;
     78    {
     79        auto locker = holdLock(sharedLock());
     80        queuedDispatchers = WTFMove(pendingDispatchers());
     81    }
    6182    while (!queuedDispatchers.isEmpty()) {
    6283        WeakPtr<TaskDispatcher<Timer>> dispatcher = queuedDispatchers.takeFirst();
     
    6788}
    6889
     90
    6991Deque<WeakPtr<TaskDispatcher<Timer>>>& TaskDispatcher<Timer>::pendingDispatchers()
    7092{
    71     ASSERT(isMainThread());
    72     static NeverDestroyed<Deque<WeakPtr<TaskDispatcher<Timer>>>> dispatchers;
     93    static LazyNeverDestroyed<Deque<WeakPtr<TaskDispatcher<Timer>>>> dispatchers;
     94
     95    static std::once_flag onceFlag;
     96    std::call_once(onceFlag, [] {
     97        dispatchers.construct();
     98    });
     99
    73100    return dispatchers.get();
    74101}
     
    76103void TaskDispatcher<Timer>::dispatchOneTask()
    77104{
    78     ASSERT(!m_pendingTasks.isEmpty());
    79     auto task = m_pendingTasks.takeFirst();
     105    WTF::Function<void()> task;
     106    {
     107        auto locker = holdLock(sharedLock());
     108        ASSERT(!m_pendingTasks.isEmpty());
     109        task = m_pendingTasks.takeFirst();
     110    }
    80111    task();
    81112}
  • trunk/Source/WebCore/platform/GenericTaskQueue.h

    r237209 r237350  
    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

    r237266 r237350  
    331331    AVPlayer *objCAVFoundationAVPlayer() const final { return m_avPlayer.get(); }
    332332
     333    WeakPtrFactory<MediaPlayerPrivateAVFoundationObjC> m_weakPtrFactory;
    333334    RetainPtr<AVURLAsset> m_avAsset;
    334335    RetainPtr<AVPlayer> m_avPlayer;
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm

    r237266 r237350  
    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
     
    33503350@implementation WebCoreAVFMovieObserver
    33513351
    3352 - (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback
     3352- (id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)player
    33533353{
    33543354    self = [super init];
    33553355    if (!self)
    33563356        return nil;
    3357     m_callback = callback;
     3357    m_player = WTFMove(player);
    33583358    return self;
    33593359}
     
    33613361- (void)disconnect
    33623362{
    3363     [NSObject cancelPreviousPerformRequestsWithTarget:self];
    3364     m_callback = nil;
     3363    m_player = nullptr;
    33653364}
    33663365
    33673366- (void)metadataLoaded
    33683367{
    3369     if (!m_callback)
    3370         return;
    3371     m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::AssetMetadataLoaded);
     3368    m_taskQueue.enqueueTask([player = m_player] {
     3369        if (player)
     3370            player->metadataLoaded();
     3371    });
    33723372}
    33733373
     
    33753375{
    33763376    UNUSED_PARAM(unusedNotification);
    3377     if (!m_callback)
    3378         return;
    3379     m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemDidPlayToEndTime);
     3377    m_taskQueue.enqueueTask([player = m_player] {
     3378        if (player)
     3379            player->didEnd();
     3380    });
    33803381}
    33813382
    33823383- (void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(MediaPlayerAVFoundationObservationContext)context
    33833384{
    3384     UNUSED_PARAM(object);
    3385     id newValue = [change valueForKey:NSKeyValueChangeNewKey];
    3386 
    3387     if (!m_callback)
    3388         return;
    3389 
    3390     bool willChange = [[change valueForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue];
    3391     bool shouldLogValue = !willChange;
    3392     WTF::Function<void ()> function;
    3393 
    3394     if (context == MediaPlayerAVFoundationObservationContextAVPlayerLayer) {
    3395         if ([keyPath isEqualToString:@"readyForDisplay"])
    3396             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::firstFrameAvailableDidChange, m_callback, [newValue boolValue]);
    3397     }
    3398 
    3399     if (context == MediaPlayerAVFoundationObservationContextPlayerItemTrack) {
    3400         if ([keyPath isEqualToString:@"enabled"])
    3401             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::trackEnabledDidChange, m_callback, [newValue boolValue]);
    3402     }
    3403 
    3404     if (context == MediaPlayerAVFoundationObservationContextPlayerItem && willChange) {
    3405         if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
    3406             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackLikelyToKeepUpWillChange, m_callback);
    3407         else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
    3408             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackBufferEmptyWillChange, m_callback);
    3409         else if ([keyPath isEqualToString:@"playbackBufferFull"])
    3410             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackBufferFullWillChange, m_callback);
    3411     }
    3412 
    3413     if (context == MediaPlayerAVFoundationObservationContextPlayerItem && !willChange) {
    3414         // A value changed for an AVPlayerItem
    3415         if ([keyPath isEqualToString:@"status"])
    3416             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playerItemStatusDidChange, m_callback, [newValue intValue]);
    3417         else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
    3418             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackLikelyToKeepUpDidChange, m_callback, [newValue boolValue]);
    3419         else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
    3420             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackBufferEmptyDidChange, m_callback, [newValue boolValue]);
    3421         else if ([keyPath isEqualToString:@"playbackBufferFull"])
    3422             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackBufferFullDidChange, m_callback, [newValue boolValue]);
    3423         else if ([keyPath isEqualToString:@"asset"]) {
    3424             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::setAsset, m_callback, RetainPtr<id>(newValue));
    3425             shouldLogValue = false;
    3426         } else if ([keyPath isEqualToString:@"loadedTimeRanges"])
    3427             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::loadedTimeRangesDidChange, m_callback, RetainPtr<NSArray>(newValue));
    3428         else if ([keyPath isEqualToString:@"seekableTimeRanges"])
    3429             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::seekableTimeRangesDidChange, m_callback, RetainPtr<NSArray>(newValue));
    3430         else if ([keyPath isEqualToString:@"tracks"]) {
    3431             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::tracksDidChange, m_callback, RetainPtr<NSArray>(newValue));
    3432             shouldLogValue = false;
    3433         } else if ([keyPath isEqualToString:@"hasEnabledAudio"])
    3434             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::hasEnabledAudioDidChange, m_callback, [newValue boolValue]);
    3435         else if ([keyPath isEqualToString:@"presentationSize"])
    3436             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::presentationSizeDidChange, m_callback, FloatSize([newValue sizeValue]));
    3437         else if ([keyPath isEqualToString:@"duration"])
    3438             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::durationDidChange, m_callback, PAL::toMediaTime([newValue CMTimeValue]));
    3439         else if ([keyPath isEqualToString:@"timedMetadata"] && newValue) {
    3440             MediaTime now;
    3441             CMTime itemTime = [(AVPlayerItemType *)object currentTime];
    3442             if (CMTIME_IS_NUMERIC(itemTime))
    3443                 now = std::max(PAL::toMediaTime(itemTime), MediaTime::zeroTime());
    3444             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::metadataDidArrive, m_callback, RetainPtr<NSArray>(newValue), now);
    3445             shouldLogValue = false;
    3446         } else if ([keyPath isEqualToString:@"canPlayFastReverse"])
    3447             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::canPlayFastReverseDidChange, m_callback, [newValue boolValue]);
    3448         else if ([keyPath isEqualToString:@"canPlayFastForward"])
    3449             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::canPlayFastForwardDidChange, m_callback, [newValue boolValue]);
    3450     }
    3451 
    3452     if (context == MediaPlayerAVFoundationObservationContextPlayer && !willChange) {
    3453         // A value changed for an AVPlayer.
    3454         if ([keyPath isEqualToString:@"rate"])
    3455             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::rateDidChange, m_callback, [newValue doubleValue]);
     3385    m_taskQueue.enqueueTask([player = m_player, keyPath = retainPtr(keyPath), change = retainPtr(change), object = retainPtr(object), context] {
     3386        if (!player)
     3387            return;
     3388        id newValue = [change valueForKey:NSKeyValueChangeNewKey];
     3389        bool willChange = [[change valueForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue];
     3390        bool shouldLogValue = !willChange;
     3391
     3392        if (context == MediaPlayerAVFoundationObservationContextAVPlayerLayer) {
     3393            if ([keyPath isEqualToString:@"readyForDisplay"])
     3394                player->firstFrameAvailableDidChange([newValue boolValue]);
     3395        }
     3396
     3397        if (context == MediaPlayerAVFoundationObservationContextPlayerItemTrack) {
     3398            if ([keyPath isEqualToString:@"enabled"])
     3399                player->trackEnabledDidChange([newValue boolValue]);
     3400        }
     3401
     3402        if (context == MediaPlayerAVFoundationObservationContextPlayerItem && willChange) {
     3403            if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
     3404                player->playbackLikelyToKeepUpWillChange();
     3405            else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
     3406                player->playbackBufferEmptyWillChange();
     3407            else if ([keyPath isEqualToString:@"playbackBufferFull"])
     3408                player->playbackBufferFullWillChange();
     3409        }
     3410
     3411        if (context == MediaPlayerAVFoundationObservationContextPlayerItem && !willChange) {
     3412            // A value changed for an AVPlayerItem
     3413            if ([keyPath isEqualToString:@"status"])
     3414                player->playerItemStatusDidChange([newValue intValue]);
     3415            else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
     3416                player->playbackLikelyToKeepUpDidChange([newValue boolValue]);
     3417            else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
     3418                player->playbackBufferEmptyDidChange([newValue boolValue]);
     3419            else if ([keyPath isEqualToString:@"playbackBufferFull"])
     3420                player->playbackBufferFullDidChange([newValue boolValue]);
     3421            else if ([keyPath isEqualToString:@"asset"]) {
     3422                player->setAsset(RetainPtr<id>(newValue));
     3423                shouldLogValue = false;
     3424            } else if ([keyPath isEqualToString:@"loadedTimeRanges"])
     3425                player->loadedTimeRangesDidChange(RetainPtr<NSArray>(newValue));
     3426            else if ([keyPath isEqualToString:@"seekableTimeRanges"])
     3427                player->seekableTimeRangesDidChange(RetainPtr<NSArray>(newValue));
     3428            else if ([keyPath isEqualToString:@"tracks"]) {
     3429                player->tracksDidChange(RetainPtr<NSArray>(newValue));
     3430                shouldLogValue = false;
     3431            } else if ([keyPath isEqualToString:@"hasEnabledAudio"])
     3432                player->hasEnabledAudioDidChange([newValue boolValue]);
     3433            else if ([keyPath isEqualToString:@"presentationSize"])
     3434                player->presentationSizeDidChange(FloatSize([newValue sizeValue]));
     3435            else if ([keyPath isEqualToString:@"duration"])
     3436                player->durationDidChange(PAL::toMediaTime([newValue CMTimeValue]));
     3437            else if ([keyPath isEqualToString:@"timedMetadata"] && newValue) {
     3438                MediaTime now;
     3439                CMTime itemTime = [(AVPlayerItemType *)object.get() currentTime];
     3440                if (CMTIME_IS_NUMERIC(itemTime))
     3441                    now = std::max(PAL::toMediaTime(itemTime), MediaTime::zeroTime());
     3442                player->metadataDidArrive(RetainPtr<NSArray>(newValue), now);
     3443                shouldLogValue = false;
     3444            } else if ([keyPath isEqualToString:@"canPlayFastReverse"])
     3445                player->canPlayFastReverseDidChange([newValue boolValue]);
     3446            else if ([keyPath isEqualToString:@"canPlayFastForward"])
     3447                player->canPlayFastForwardDidChange([newValue boolValue]);
     3448        }
     3449
     3450        if (context == MediaPlayerAVFoundationObservationContextPlayer && !willChange) {
     3451            // A value changed for an AVPlayer.
     3452            if ([keyPath isEqualToString:@"rate"])
     3453                player->rateDidChange([newValue doubleValue]);
    34563454#if ENABLE(WIRELESS_PLAYBACK_TARGET)
    3457         else if ([keyPath isEqualToString:@"externalPlaybackActive"] || [keyPath isEqualToString:@"allowsExternalPlayback"])
    3458             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackTargetIsWirelessDidChange, m_callback);
     3455            else if ([keyPath isEqualToString:@"externalPlaybackActive"] || [keyPath isEqualToString:@"allowsExternalPlayback"])
     3456                player->playbackTargetIsWirelessDidChange();
    34593457#endif
    34603458#if ENABLE(LEGACY_ENCRYPTED_MEDIA) || ENABLE(ENCRYPTED_MEDIA)
    3461         else if ([keyPath isEqualToString:@"outputObscuredDueToInsufficientExternalProtection"])
    3462             function = std::bind(&MediaPlayerPrivateAVFoundationObjC::outputObscuredDueToInsufficientExternalProtectionChanged, m_callback, [newValue boolValue]);
    3463 #endif
    3464     }
     3459            else if ([keyPath isEqualToString:@"outputObscuredDueToInsufficientExternalProtection"])
     3460                player->outputObscuredDueToInsufficientExternalProtectionChanged([newValue boolValue]);
     3461#endif
     3462        }
    34653463
    34663464#if !RELEASE_LOG_DISABLED
    3467     if (m_callback->logger().willLog(m_callback->logChannel(), WTFLogLevelDebug) && !([keyPath isEqualToString:@"loadedTimeRanges"] || [keyPath isEqualToString:@"seekableTimeRanges"])) {
    3468         auto identifier = Logger::LogSiteIdentifier("MediaPlayerPrivateAVFoundation", "observeValueForKeyPath", m_callback->logIdentifier());
    3469 
    3470         if (shouldLogValue) {
    3471             if ([keyPath isEqualToString:@"duration"])
    3472                 m_callback->logger().debug(m_callback->logChannel(), identifier, "did change '", [keyPath UTF8String], "' to ", PAL::toMediaTime([newValue CMTimeValue]));
    3473             else {
    3474                 RetainPtr<NSString> valueString = adoptNS([[NSString alloc] initWithFormat:@"%@", newValue]);
    3475                 m_callback->logger().debug(m_callback->logChannel(), identifier, "did change '", [keyPath UTF8String], "' to ", [valueString.get() UTF8String]);
    3476             }
    3477         } else
    3478             m_callback->logger().debug(m_callback->logChannel(), identifier, willChange ? "will" : "did", " change '", [keyPath UTF8String], "'");
    3479     }
    3480 #endif
    3481 
    3482     if (!function)
    3483         return;
    3484 
    3485     auto weakThis = makeWeakPtr(*m_callback);
    3486     m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification([weakThis, function = WTFMove(function)]{
    3487         // weakThis and function both refer to the same MediaPlayerPrivateAVFoundationObjC instance. If the WeakPtr has
    3488         // been cleared, the underlying object has been destroyed, and it is unsafe to call function().
    3489         if (!weakThis)
    3490             return;
    3491         function();
    3492     }));
     3465        if (player->logger().willLog(player->logChannel(), WTFLogLevelDebug) && !([keyPath isEqualToString:@"loadedTimeRanges"] || [keyPath isEqualToString:@"seekableTimeRanges"])) {
     3466            auto identifier = Logger::LogSiteIdentifier("MediaPlayerPrivateAVFoundation", "observeValueForKeyPath", player->logIdentifier());
     3467
     3468            if (shouldLogValue) {
     3469                if ([keyPath isEqualToString:@"duration"])
     3470                    player->logger().debug(player->logChannel(), identifier, "did change '", [keyPath UTF8String], "' to ", PAL::toMediaTime([newValue CMTimeValue]));
     3471                else {
     3472                    RetainPtr<NSString> valueString = adoptNS([[NSString alloc] initWithFormat:@"%@", newValue]);
     3473                    player->logger().debug(player->logChannel(), identifier, "did change '", [keyPath UTF8String], "' to ", [valueString.get() UTF8String]);
     3474                }
     3475            } else
     3476                player->logger().debug(player->logChannel(), identifier, willChange ? "will" : "did", " change '", [keyPath UTF8String], "'");
     3477        }
     3478#endif
     3479    });
    34933480}
    34943481
     
    34983485{
    34993486    UNUSED_PARAM(output);
    3500     UNUSED_PARAM(nativeSamples);
    3501 
    3502     if (!m_callback)
    3503         return;
    3504 
    3505     RetainPtr<WebCoreAVFMovieObserver> protectedSelf = self;
    3506     RetainPtr<NSArray> protectedStrings = strings;
    3507     RetainPtr<NSArray> protectedNativeSamples = nativeSamples;
    3508     callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedStrings = WTFMove(protectedStrings), protectedNativeSamples = WTFMove(protectedNativeSamples), itemTime] {
    3509         MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback;
    3510         if (!callback)
     3487
     3488    m_taskQueue.enqueueTask([player = m_player, strings = retainPtr(strings), nativeSamples = retainPtr(nativeSamples), itemTime] {
     3489        if (!player)
    35113490            return;
    35123491        MediaTime time = std::max(PAL::toMediaTime(itemTime), MediaTime::zeroTime());
    3513         callback->processCue(protectedStrings.get(), protectedNativeSamples.get(), time);
     3492        player->processCue(strings.get(), nativeSamples.get(), time);
    35143493    });
    35153494}
     
    35193498    UNUSED_PARAM(output);
    35203499
    3521     if (!m_callback)
    3522         return;
    3523    
    3524     callOnMainThread([protectedSelf = RetainPtr<WebCoreAVFMovieObserver>(self)] {
    3525         if (MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback)
    3526             callback->flushCues();
     3500    m_taskQueue.enqueueTask([player = m_player] {
     3501        if (player)
     3502            player->flushCues();
    35273503    });
    35283504}
     
    35363512@implementation WebCoreAVFLoaderDelegate
    35373513
    3538 - (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback
     3514- (id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)player
    35393515{
    35403516    self = [super init];
    35413517    if (!self)
    35423518        return nil;
    3543     m_callback = callback;
     3519    m_player = WTFMove(player);
    35443520    return self;
    35453521}
     
    35483524{
    35493525    UNUSED_PARAM(resourceLoader);
    3550     if (!m_callback)
     3526    if (!m_player)
    35513527        return NO;
    35523528
    3553     RetainPtr<WebCoreAVFLoaderDelegate> protectedSelf = self;
    3554     RetainPtr<AVAssetResourceLoadingRequest> protectedLoadingRequest = loadingRequest;
    3555     callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedLoadingRequest = WTFMove(protectedLoadingRequest)] {
    3556         MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback;
    3557         if (!callback) {
    3558             [protectedLoadingRequest finishLoadingWithError:nil];
     3529    m_taskQueue.enqueueTask([player = m_player, loadingRequest = retainPtr(loadingRequest)] {
     3530        if (!player) {
     3531            [loadingRequest finishLoadingWithError:nil];
    35593532            return;
    35603533        }
    35613534
    3562         if (!callback->shouldWaitForLoadingOfResource(protectedLoadingRequest.get()))
    3563             [protectedLoadingRequest finishLoadingWithError:nil];
     3535        if (!player->shouldWaitForLoadingOfResource(loadingRequest.get()))
     3536            [loadingRequest finishLoadingWithError:nil];
    35643537    });
    35653538
     
    35783551{
    35793552    UNUSED_PARAM(resourceLoader);
    3580     if (!m_callback)
    3581         return;
    3582 
    3583     RetainPtr<WebCoreAVFLoaderDelegate> protectedSelf = self;
    3584     RetainPtr<AVAssetResourceLoadingRequest> protectedLoadingRequest = loadingRequest;
    3585     callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedLoadingRequest = WTFMove(protectedLoadingRequest)] {
    3586         MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback;
    3587         if (callback)
    3588             callback->didCancelLoadingRequest(protectedLoadingRequest.get());
     3553    m_taskQueue.enqueueTask([player = m_player, loadingRequest = retainPtr(loadingRequest)] {
     3554        if (player)
     3555            player->didCancelLoadingRequest(loadingRequest.get());
    35893556    });
    35903557}
    35913558
    3592 - (void)setCallback:(MediaPlayerPrivateAVFoundationObjC*)callback
    3593 {
    3594     m_callback = callback;
    3595 }
    35963559@end
    35973560
     
    36023565@implementation WebCoreAVFPullDelegate
    36033566
    3604 - (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC *)callback
     3567- (id)initWithPlayer:(WeakPtr<MediaPlayerPrivateAVFoundationObjC>&&)player
    36053568{
    36063569    self = [super init];
    36073570    if (self)
    3608         m_callback = callback;
     3571        m_player = WTFMove(player);
    36093572    return self;
    36103573}
    36113574
    3612 - (void)setCallback:(MediaPlayerPrivateAVFoundationObjC *)callback
    3613 {
    3614     m_callback = callback;
    3615 }
    3616 
    36173575- (void)outputMediaDataWillChange:(AVPlayerItemVideoOutputType *)output
    36183576{
    3619     if (m_callback)
    3620         m_callback->outputMediaDataWillChange(output);
     3577    if (m_player)
     3578        m_player->outputMediaDataWillChange(output);
    36213579}
    36223580
Note: See TracChangeset for help on using the changeset viewer.