⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 201524 in webkit


Ignore:
Timestamp:
May 31, 2016, 2:24:19 PM (10 years ago)
Author:
jer.noble@apple.com
Message:

[EME] Sound continues playing when video's src is changed
https://bugs.webkit.org/show_bug.cgi?id=158233

Reviewed by Eric Carlson.

When CDMSessionAVFoundation began listening for outputObscuredDueToInsufficientExternalProtection
KVO notifications, it retained the AVPlayer owned by MediaPlayerPrivateAVFoundationObjC, which
caused the AVPlayer to outlive its original owner, and to continue playing even after the
MediaPlayerPrivateAVFoundationObjC had been destroyed.

Rather than observe for outputObscuredDueToInsufficientExternalProtection changes in
CDMSessionAVFoundation, add a backreference from the media player to the session, listen for changes
in the player, and have the player notify the session when the value of that property changes.

  • platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.h:

(WebCore::CDMSessionAVFoundationObjC::createWeakPtr):

  • platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.mm:

(WebCore::CDMSessionAVFoundationObjC::CDMSessionAVFoundationObjC):
(-[WebCDMSessionAVFoundationObjCListener initWithParent:player:]): Deleted.
(-[WebCDMSessionAVFoundationObjCListener invalidate]): Deleted.
(-[WebCDMSessionAVFoundationObjCListener observeValueForKeyPath:ofObject:change:context:]): Deleted.
(WebCore::CDMSessionAVFoundationObjC::~CDMSessionAVFoundationObjC): Deleted.

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

(WebCore::MediaPlayerPrivateAVFoundationObjC::removeSession):
(WebCore::MediaPlayerPrivateAVFoundationObjC::createSession):
(WebCore::MediaPlayerPrivateAVFoundationObjC::outputObscuredDueToInsufficientExternalProtectionChanged):
(WebCore::playerKVOProperties):
(-[WebCoreAVFMovieObserver observeValueForKeyPath:ofObject:change:context:]):

Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r201522 r201524  
     12016-05-31  Jer Noble  <jer.noble@apple.com>
     2
     3        [EME] Sound continues playing when video's src is changed
     4        https://bugs.webkit.org/show_bug.cgi?id=158233
     5
     6        Reviewed by Eric Carlson.
     7
     8        When CDMSessionAVFoundation began listening for outputObscuredDueToInsufficientExternalProtection
     9        KVO notifications, it retained the AVPlayer owned by MediaPlayerPrivateAVFoundationObjC, which
     10        caused the AVPlayer to outlive its original owner, and to continue playing even after the
     11        MediaPlayerPrivateAVFoundationObjC had been destroyed.
     12
     13        Rather than observe for outputObscuredDueToInsufficientExternalProtection changes in
     14        CDMSessionAVFoundation, add a backreference from the media player to the session, listen for changes
     15        in the player, and have the player notify the session when the value of that property changes.
     16
     17        * platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.h:
     18        (WebCore::CDMSessionAVFoundationObjC::createWeakPtr):
     19        * platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.mm:
     20        (WebCore::CDMSessionAVFoundationObjC::CDMSessionAVFoundationObjC):
     21        (-[WebCDMSessionAVFoundationObjCListener initWithParent:player:]): Deleted.
     22        (-[WebCDMSessionAVFoundationObjCListener invalidate]): Deleted.
     23        (-[WebCDMSessionAVFoundationObjCListener observeValueForKeyPath:ofObject:change:context:]): Deleted.
     24        (WebCore::CDMSessionAVFoundationObjC::~CDMSessionAVFoundationObjC): Deleted.
     25        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
     26        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
     27        (WebCore::MediaPlayerPrivateAVFoundationObjC::removeSession):
     28        (WebCore::MediaPlayerPrivateAVFoundationObjC::createSession):
     29        (WebCore::MediaPlayerPrivateAVFoundationObjC::outputObscuredDueToInsufficientExternalProtectionChanged):
     30        (WebCore::playerKVOProperties):
     31        (-[WebCoreAVFMovieObserver observeValueForKeyPath:ofObject:change:context:]):
     32
    1332016-05-31  Eric Carlson  <eric.carlson@apple.com>
    234
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.h

    r199672 r201524  
    5454    void playerDidReceiveError(NSError *);
    5555
     56    WeakPtr<CDMSessionAVFoundationObjC> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
     57
    5658protected:
    5759    WeakPtr<MediaPlayerPrivateAVFoundationObjC> m_parent;
     
    5961    String m_sessionId;
    6062    RetainPtr<AVAssetResourceLoadingRequest> m_request;
    61     RetainPtr<WebCDMSessionAVFoundationObjCListener> m_listener;
     63    WeakPtrFactory<CDMSessionAVFoundationObjC> m_weakPtrFactory;
    6264};
    6365
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.mm

    r201482 r201524  
    4747#define AVAssetResourceLoadingRequest getAVAssetResourceLoadingRequest()
    4848
    49 @interface WebCDMSessionAVFoundationObjCListener : NSObject {
    50     WebCore::CDMSessionAVFoundationObjC* _parent;
    51     RetainPtr<AVPlayer> _player;
    52 }
    53 - (id)initWithParent:(WebCore::CDMSessionAVFoundationObjC*)parent player:(AVPlayer *)player;
    54 - (void)invalidate;
    55 @end
    56 
    57 @implementation WebCDMSessionAVFoundationObjCListener
    58 - (id)initWithParent:(WebCore::CDMSessionAVFoundationObjC*)parent player:(AVPlayer *)player
    59 {
    60     self = [super init];
    61     if (!self)
    62         return nil;
    63 
    64     _parent = parent;
    65     _player = player;
    66     [player addObserver:self forKeyPath:@"outputObscuredDueToInsufficientExternalProtection" options:NSKeyValueObservingOptionNew context:nil];
    67 
    68     return self;
    69 }
    70 
    71 - (void)invalidate
    72 {
    73     _parent = nullptr;
    74     [_player removeObserver:self forKeyPath:@"outputObscuredDueToInsufficientExternalProtection"];
    75     _player = nullptr;
    76 }
    77 
    78 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    79 {
    80     UNUSED_PARAM(context);
    81     UNUSED_PARAM(object);
    82     ASSERT(_parent);
    83 
    84     if ([keyPath isEqualTo:@"outputObscuredDueToInsufficientExternalProtection"]) {
    85         if ([[change valueForKey:NSKeyValueChangeNewKey] intValue] == 1) {
    86             RetainPtr<NSError> error = [NSError errorWithDomain:@"com.apple.WebKit" code:'HDCP' userInfo:nil];
    87             RetainPtr<WebCDMSessionAVFoundationObjCListener> protectedSelf = { self };
    88             callOnMainThread([protectedSelf = WTFMove(protectedSelf), error = WTFMove(error)] {
    89                 if (protectedSelf->_parent)
    90                     protectedSelf->_parent->playerDidReceiveError(error.get());
    91             });
    92         }
    93     } else
    94         ASSERT_NOT_REACHED();
    95 }
    96 @end
    97 
    9849namespace WebCore {
    9950
     
    10253    , m_client(client)
    10354    , m_sessionId(createCanonicalUUIDString())
    104     , m_listener(adoptNS([[WebCDMSessionAVFoundationObjCListener alloc] initWithParent:this player:parent->avPlayer()]))
     55    , m_weakPtrFactory(this)
    10556{
    10657}
     
    10859CDMSessionAVFoundationObjC::~CDMSessionAVFoundationObjC()
    10960{
    110     [m_listener invalidate];
    11161}
    11262
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h

    r201474 r201524  
    6868class AudioSourceProviderAVFObjC;
    6969class AudioTrackPrivateAVFObjC;
     70class CDMSessionAVFoundationObjC;
    7071class InbandMetadataTextTrackPrivateAVF;
    7172class InbandTextTrackPrivateAVFObjC;
     
    143144    void playbackTargetIsWirelessDidChange();
    144145#endif
    145    
     146
     147#if ENABLE(ENCRYPTED_MEDIA_V2)
     148    void outputObscuredDueToInsufficientExternalProtectionChanged(bool);
     149#endif
     150
    146151#if ENABLE(AVF_CAPTIONS)
    147152    void notifyTrackModeChanged() override;
    148153    void synchronizeTextTrackState() override;
    149154#endif
    150    
     155
     156#if ENABLE(ENCRYPTED_MEDIA_V2)
     157    void removeSession(CDMSession&);
     158#endif
     159
    151160    WeakPtr<MediaPlayerPrivateAVFoundationObjC> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
    152161
     
    391400    RetainPtr<AVOutputContext> m_outputContext;
    392401    RefPtr<MediaPlaybackTarget> m_playbackTarget { nullptr };
     402#endif
     403
     404#if ENABLE(ENCRYPTED_MEDIA_V2)
     405    WeakPtr<CDMSessionAVFoundationObjC> m_session;
    393406#endif
    394407
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm

    r201482 r201524  
    25862586}
    25872587
     2588void MediaPlayerPrivateAVFoundationObjC::removeSession(CDMSession& session)
     2589{
     2590    ASSERT(&session == m_session);
     2591    m_session = nullptr;
     2592}
     2593
    25882594std::unique_ptr<CDMSession> MediaPlayerPrivateAVFoundationObjC::createSession(const String& keySystem, CDMSessionClient* client)
    25892595{
    25902596    if (!keySystemIsSupported(keySystem))
    25912597        return nullptr;
    2592 
    2593     return std::make_unique<CDMSessionAVFoundationObjC>(this, client);
     2598    auto session = std::make_unique<CDMSessionAVFoundationObjC>(this, client);
     2599    m_session = session->createWeakPtr();
     2600    return WTFMove(session);
     2601}
     2602
     2603void MediaPlayerPrivateAVFoundationObjC::outputObscuredDueToInsufficientExternalProtectionChanged(bool newValue)
     2604{
     2605    if (m_session && newValue)
     2606        m_session->playerDidReceiveError([NSError errorWithDomain:@"com.apple.WebKit" code:'HDCP' userInfo:nil]);
    25942607}
    25952608#endif
     
    32943307#if ENABLE(WIRELESS_PLAYBACK_TARGET)
    32953308                            @"externalPlaybackActive", @"allowsExternalPlayback",
     3309#endif
     3310#if ENABLE(ENCRYPTED_MEDIA_V2)
     3311                            @"outputObscuredDueToInsufficientExternalProtection",
    32963312#endif
    32973313                            nil];
     
    34173433            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::playbackTargetIsWirelessDidChange, m_callback);
    34183434#endif
     3435#if ENABLE(ENCRYPTED_MEDIA_V2)
     3436        else if ([keyPath isEqualToString:@"outputObscuredDueToInsufficientExternalProtection"])
     3437            function = std::bind(&MediaPlayerPrivateAVFoundationObjC::outputObscuredDueToInsufficientExternalProtectionChanged, m_callback, [newValue boolValue]);
     3438#endif
    34193439    }
    34203440   
Note: See TracChangeset for help on using the changeset viewer.