[Win] Extend AVFoundationCF Media Implementation
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 6 Oct 2014 17:49:24 +0000 (17:49 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 6 Oct 2014 17:49:24 +0000 (17:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=137409

Reviewed by Eric Carlson.

This code is not yet being built and tested by our system. Appropriate
tests will be activated when we enable the build.

Most of this patch involves correcting some misuse of the AVFoundationCF API.
1. It is never appropriate in AVCF to pass a null CFErrorRef; instead you must
   pass a CFErrorRef with error type kCFURLErrorUnknown.
2. Because of the asynchronous way we handle the request/response, it is possible
   for AVCF to make two AVCF requests while negotiating the key exchange.

* platform/graphics/avfoundation/cf/AVFoundationCFSoftLinking.h: Add
missing declaration.
* platform/graphics/avfoundation/cf/CDMSessionAVFoundationCF.cpp:
(WebCore::CDMSessionAVFoundationCF::generateKeyRequest): Tighten up scope
of 'underlyingError'.
(WebCore::CDMSessionAVFoundationCF::update): Add call to complete the
loading process.
* platform/graphics/avfoundation/cf/InbandTextTrackPrivateAVCF.cpp:
(WebCore::InbandTextTrackPrivateAVCF::label): Handle null titles CFArray
found during testing.
(WebCore::InbandTextTrackPrivateAVCF::language): Ditto for a null locale.
* platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp:
(WebCore::MediaPlayerPrivateAVFoundationCF::registerMediaEngine): Add support
for the new 'supportsKeySystem' method.
(WebCore::MediaPlayerPrivateAVFoundationCF::createContextVideoRenderer): Add
assertion for mainThread.
(WebCore::MediaPlayerPrivateAVFoundationCF::destroyContextVideoRenderer): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationCF::createVideoLayer): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationCF::destroyVideoLayer): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationCF::createAVPlayer): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationCF::createAVPlayerItem): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationCF::platformLayer): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationCF::platformSetVisible): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationCF::paintCurrentFrameInContext): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationCF::paint): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationCF::supportsKeySystem): Added.
(WebCore::MediaPlayerPrivateAVFoundationCF::sizeChanged): Add assertion that this
is being called on the main thread.
(WebCore::MediaPlayerPrivateAVFoundationCF::processMediaSelectionOptions): Handle
the allows empty media selection properly based on test behavior.
(WebCore::AVFWrapper::AVFWrapper): Initialize resource loader callback structure
when building with AVFOUNDATION_LOADER_DELEGATE.
(WebCore::AVFWrapper::createAssetForURL): Use AVFWrapper's loader callback struct,
rather than passing the address of a temporary value.
(WebCore::AVFWrapper::processNotification): Stop using the deprecated
'dispatch_get_current_queue' function.
(WebCore::AVFWrapper::processCue): Ditto.
(WebCore::AVFWrapper::legibleOutputCallback): Ditto.
(WebCore::AVFWrapper::processShouldWaitForLoadingOfResource): Pass a valid CFError
object; nullptr is not allowed as an argument to the "...FinishedLoadingWithError"
method.
(WebCore::AVFWrapper::shouldWaitForLoadingOfResource): Add support for multiple
in-flight requests.
(WebCore::AVFWrapper::platformLayer): Assert we are on the main thread.
(WebCore::AVFWrapper::setRequestForKey): Add support for multiple in-flight requests.
(WebCore::AVFWrapper::takeRequestForKeyURI): Ditto.
(WebCore::LayerClient::platformCALayerLayoutSublayersOfLayer): Ditto.
* platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.h:
* platform/graphics/avfoundation/cf/WebCoreAVCFResourceLoader.cpp: Make sure we pass
valid CFError objects, rather than nullptr.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@174346 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/avfoundation/cf/AVFoundationCFSoftLinking.h
Source/WebCore/platform/graphics/avfoundation/cf/CDMSessionAVFoundationCF.cpp
Source/WebCore/platform/graphics/avfoundation/cf/InbandTextTrackPrivateAVCF.cpp
Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp
Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.h
Source/WebCore/platform/graphics/avfoundation/cf/WebCoreAVCFResourceLoader.cpp

index 6eac600..3b05457 100644 (file)
@@ -1,3 +1,70 @@
+2014-10-06  Brent Fulgham  <bfulgham@apple.com>
+
+        [Win] Extend AVFoundationCF Media Implementation
+        https://bugs.webkit.org/show_bug.cgi?id=137409
+
+        Reviewed by Eric Carlson.
+
+        This code is not yet being built and tested by our system. Appropriate
+        tests will be activated when we enable the build.
+
+        Most of this patch involves correcting some misuse of the AVFoundationCF API.
+        1. It is never appropriate in AVCF to pass a null CFErrorRef; instead you must
+           pass a CFErrorRef with error type kCFURLErrorUnknown.
+        2. Because of the asynchronous way we handle the request/response, it is possible
+           for AVCF to make two AVCF requests while negotiating the key exchange.
+
+        * platform/graphics/avfoundation/cf/AVFoundationCFSoftLinking.h: Add
+        missing declaration.
+        * platform/graphics/avfoundation/cf/CDMSessionAVFoundationCF.cpp:
+        (WebCore::CDMSessionAVFoundationCF::generateKeyRequest): Tighten up scope
+        of 'underlyingError'.
+        (WebCore::CDMSessionAVFoundationCF::update): Add call to complete the
+        loading process.
+        * platform/graphics/avfoundation/cf/InbandTextTrackPrivateAVCF.cpp:
+        (WebCore::InbandTextTrackPrivateAVCF::label): Handle null titles CFArray
+        found during testing.
+        (WebCore::InbandTextTrackPrivateAVCF::language): Ditto for a null locale.
+        * platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp:
+        (WebCore::MediaPlayerPrivateAVFoundationCF::registerMediaEngine): Add support
+        for the new 'supportsKeySystem' method.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::createContextVideoRenderer): Add
+        assertion for mainThread.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::destroyContextVideoRenderer): Ditto.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::createVideoLayer): Ditto.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::destroyVideoLayer): Ditto.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::createAVPlayer): Ditto.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::createAVPlayerItem): Ditto.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::platformLayer): Ditto.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::platformSetVisible): Ditto.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::paintCurrentFrameInContext): Ditto.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::paint): Ditto.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::supportsKeySystem): Added.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::sizeChanged): Add assertion that this
+        is being called on the main thread.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::processMediaSelectionOptions): Handle
+        the allows empty media selection properly based on test behavior.
+        (WebCore::AVFWrapper::AVFWrapper): Initialize resource loader callback structure
+        when building with AVFOUNDATION_LOADER_DELEGATE.
+        (WebCore::AVFWrapper::createAssetForURL): Use AVFWrapper's loader callback struct,
+        rather than passing the address of a temporary value.
+        (WebCore::AVFWrapper::processNotification): Stop using the deprecated 
+        'dispatch_get_current_queue' function.
+        (WebCore::AVFWrapper::processCue): Ditto.
+        (WebCore::AVFWrapper::legibleOutputCallback): Ditto.
+        (WebCore::AVFWrapper::processShouldWaitForLoadingOfResource): Pass a valid CFError
+        object; nullptr is not allowed as an argument to the "...FinishedLoadingWithError"
+        method.
+        (WebCore::AVFWrapper::shouldWaitForLoadingOfResource): Add support for multiple
+        in-flight requests.
+        (WebCore::AVFWrapper::platformLayer): Assert we are on the main thread.
+        (WebCore::AVFWrapper::setRequestForKey): Add support for multiple in-flight requests.
+        (WebCore::AVFWrapper::takeRequestForKeyURI): Ditto.
+        (WebCore::LayerClient::platformCALayerLayoutSublayersOfLayer): Ditto.
+        * platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.h:
+        * platform/graphics/avfoundation/cf/WebCoreAVCFResourceLoader.cpp: Make sure we pass
+        valid CFError objects, rather than nullptr.
+
 2014-10-06  Chris Fleizach  <cfleizach@apple.com>
 
         AX: Performance: Certain Web site causes Safari to hang completely while entering form data
index f9d14af..a7ce21e 100644 (file)
@@ -302,6 +302,9 @@ SOFT_LINK_DLL_IMPORT(AVFoundationCF, AVCFAssetResourceLoadingRequestFinishLoadin
 SOFT_LINK_DLL_IMPORT(AVFoundationCF, AVCFAssetResourceLoadingRequestGetURLRequest, CFURLRequestRef, __cdecl, (AVCFAssetResourceLoadingRequestRef loadingRequest), (loadingRequest))
 #define AVCFAssetResourceLoadingRequestGetURLRequest  softLink_AVCFAssetResourceLoadingRequestGetURLRequest 
 
+SOFT_LINK_DLL_IMPORT(AVFoundationCF, AVCFAssetResourceLoadingRequestFinishLoadingWithResponse, void, __cdecl, (AVCFAssetResourceLoadingRequestRef loadingRequest, CFURLResponseRef response, CFDataRef data, CFURLRequestRef redirect), (loadingRequest, response, data, redirect))
+#define AVCFAssetResourceLoadingRequestFinishLoadingWithResponse  softLink_AVCFAssetResourceLoadingRequestFinishLoadingWithResponse 
+
 #endif
 
 // Variables
index 3d6f6c9..da13ea1 100644 (file)
@@ -85,8 +85,7 @@ PassRefPtr<Uint8Array> CDMSessionAVFoundationCF::generateKeyRequest(const String
             userInfo = adoptCF(CFErrorCopyUserInfo(cfError));
 
             if (userInfo) {
-                CFErrorRef underlyingError = (CFErrorRef)CFDictionaryGetValue(userInfo.get(), kCFErrorUnderlyingErrorKey);
-                if (underlyingError)
+                if (CFErrorRef underlyingError = (CFErrorRef)CFDictionaryGetValue(userInfo.get(), kCFErrorUnderlyingErrorKey))
                     systemCode = CFErrorGetCode(underlyingError);
             }
 
@@ -113,9 +112,7 @@ bool CDMSessionAVFoundationCF::update(Uint8Array* key, RefPtr<Uint8Array>& nextM
     RetainPtr<CFMutableDataRef> keyData = adoptCF(CFDataCreateMutable(kCFAllocatorDefault, key->byteLength()));
     CFDataAppendBytes(keyData.get(), reinterpret_cast<const UInt8*>(key->baseAddress()), key->byteLength());
 
-    // TODO: AVCFAssetResourceLoadingDataRequestRespondWithData(m_request.get(), keyData.get());
-    // TODO: AVCFAssetResourceLoadingRequestFinishedLoading(m_request.get());
-    notImplemented();
+    AVCFAssetResourceLoadingRequestFinishLoadingWithResponse(m_request.get(), nullptr, keyData.get(), nullptr);
 
     errorCode = MediaPlayer::NoError;
     systemCode = 0;
index afcb706..e6ca444 100644 (file)
@@ -143,6 +143,9 @@ AtomicString InbandTextTrackPrivateAVCF::label() const
 
     RetainPtr<CFArrayRef> commonMetaData = adoptCF(AVCFMediaSelectionOptionCopyCommonMetadata(mediaSelectionOption()));
     RetainPtr<CFArrayRef> titles = adoptCF(AVCFMetadataItemCopyItemsWithKeyAndKeySpace(commonMetaData.get(), AVCFMetadataCommonKeyTitle, AVCFMetadataKeySpaceCommon));
+    if (!titles)
+        return emptyAtom;
+
     CFIndex titlesCount = CFArrayGetCount(titles.get());
     if (!titlesCount)
         return emptyAtom;
@@ -170,6 +173,9 @@ AtomicString InbandTextTrackPrivateAVCF::language() const
         return emptyAtom;
 
     RetainPtr<CFLocaleRef> locale = adoptCF(AVCFMediaSelectionOptionCopyLocale(mediaSelectionOption()));
+    if (!locale)
+        return emptyAtom;
+
     return CFLocaleGetIdentifier(locale.get());
 }
 
index 5fdf1eb..a15c9c3 100644 (file)
@@ -153,6 +153,7 @@ public:
 
 #if ENABLE(ENCRYPTED_MEDIA_V2)
     RetainPtr<AVCFAssetResourceLoadingRequestRef> takeRequestForKeyURI(const String&);
+    void setRequestForKey(const String& keyURI, AVCFAssetResourceLoadingRequestRef avRequest);
 #endif
 
 private:
@@ -197,7 +198,8 @@ private:
     InbandTextTrackPrivateAVF* m_currentTextTrack;
 
 #if ENABLE(ENCRYPTED_MEDIA_V2)
-    HashMap<String, RetainPtr<AVCFAssetResourceLoadingRequestRef>> m_keyURIToRequestMap;
+    HashMap<String, Vector<RetainPtr<AVCFAssetResourceLoadingRequestRef>>> m_keyURIToRequestMap;
+    AVCFAssetResourceLoaderCallbacks m_resourceLoaderCallbacks;
 #endif
 };
 
@@ -342,7 +344,7 @@ PassOwnPtr<MediaPlayerPrivateInterface> MediaPlayerPrivateAVFoundationCF::create
 void MediaPlayerPrivateAVFoundationCF::registerMediaEngine(MediaEngineRegistrar registrar)
 {
     if (isAvailable())
-        registrar(create, getSupportedTypes, supportsType, 0, 0, 0, 0);
+        registrar(create, getSupportedTypes, supportsType, 0, 0, 0, supportsKeySystem);
 }
 
 MediaPlayerPrivateAVFoundationCF::MediaPlayerPrivateAVFoundationCF(MediaPlayer* player)
@@ -407,6 +409,7 @@ bool MediaPlayerPrivateAVFoundationCF::hasContextRenderer() const
 void MediaPlayerPrivateAVFoundationCF::createContextVideoRenderer()
 {
     LOG(Media, "MediaPlayerPrivateAVFoundationCF::createContextVideoRenderer(%p)", this);
+    ASSERT(isMainThread());
 
     if (imageGenerator(m_avfWrapper))
         return;
@@ -417,12 +420,14 @@ void MediaPlayerPrivateAVFoundationCF::createContextVideoRenderer()
 
 void MediaPlayerPrivateAVFoundationCF::destroyContextVideoRenderer()
 {
+    ASSERT(isMainThread());
     if (m_avfWrapper)
         m_avfWrapper->destroyImageGenerator();
 }
 
 void MediaPlayerPrivateAVFoundationCF::createVideoLayer()
 {
+    ASSERT(isMainThread());
     ASSERT(supportsAcceleratedRendering());
 
     if (m_avfWrapper)
@@ -431,6 +436,7 @@ void MediaPlayerPrivateAVFoundationCF::createVideoLayer()
 
 void MediaPlayerPrivateAVFoundationCF::destroyVideoLayer()
 {
+    ASSERT(isMainThread());
     LOG(Media, "MediaPlayerPrivateAVFoundationCF::destroyVideoLayer(%p) - destroying %p", this, videoLayer(m_avfWrapper));
     if (m_avfWrapper)
         m_avfWrapper->destroyVideoLayer();
@@ -470,6 +476,7 @@ void MediaPlayerPrivateAVFoundationCF::createAVAssetForURL(const String& url)
 
 void MediaPlayerPrivateAVFoundationCF::createAVPlayer()
 {
+    ASSERT(isMainThread());
     ASSERT(m_avfWrapper);
     
     setDelayCallbacks(true);
@@ -479,6 +486,7 @@ void MediaPlayerPrivateAVFoundationCF::createAVPlayer()
 
 void MediaPlayerPrivateAVFoundationCF::createAVPlayerItem()
 {
+    ASSERT(isMainThread());
     ASSERT(m_avfWrapper);
     
     setDelayCallbacks(true);
@@ -529,6 +537,7 @@ PlatformMedia MediaPlayerPrivateAVFoundationCF::platformMedia() const
 
 PlatformLayer* MediaPlayerPrivateAVFoundationCF::platformLayer() const
 {
+    ASSERT(isMainThread());
     if (!m_avfWrapper)
         return 0;
 
@@ -537,6 +546,7 @@ PlatformLayer* MediaPlayerPrivateAVFoundationCF::platformLayer() const
 
 void MediaPlayerPrivateAVFoundationCF::platformSetVisible(bool isVisible)
 {
+    ASSERT(isMainThread());
     if (!m_avfWrapper)
         return;
     
@@ -829,6 +839,7 @@ MediaPlayerPrivateAVFoundation::AssetStatus MediaPlayerPrivateAVFoundationCF::as
 
 void MediaPlayerPrivateAVFoundationCF::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& rect)
 {
+    ASSERT(isMainThread());
     if (!metaDataAvailable() || context->paintingDisabled())
         return;
 
@@ -843,6 +854,7 @@ void MediaPlayerPrivateAVFoundationCF::paintCurrentFrameInContext(GraphicsContex
 
 void MediaPlayerPrivateAVFoundationCF::paint(GraphicsContext* context, const IntRect& rect)
 {
+    ASSERT(isMainThread());
     if (!metaDataAvailable() || context->paintingDisabled() || !imageGenerator(m_avfWrapper))
         return;
 
@@ -911,6 +923,25 @@ MediaPlayer::SupportsType MediaPlayerPrivateAVFoundationCF::supportsType(const M
     return MediaPlayer::IsNotSupported;
 }
 
+bool MediaPlayerPrivateAVFoundationCF::supportsKeySystem(const String& keySystem, const String& mimeType)
+{
+#if ENABLE(ENCRYPTED_MEDIA) || ENABLE(ENCRYPTED_MEDIA_V2)
+    if (keySystem.isEmpty())
+        return false;
+
+    if (!keySystemIsSupported(keySystem))
+        return false;
+
+    if (!mimeType.isEmpty() && !mimeTypeCache().contains(mimeType))
+        return false;
+
+    return true;
+#else
+    UNUSED_PARAM(keySystem);
+    UNUSED_PARAM(mimeType);
+    return false;
+#endif
+}
 
 bool MediaPlayerPrivateAVFoundationCF::isAvailable()
 {
@@ -1037,6 +1068,7 @@ void MediaPlayerPrivateAVFoundationCF::tracksChanged()
 
 void MediaPlayerPrivateAVFoundationCF::sizeChanged()
 {
+    ASSERT(isMainThread());
     if (!avAsset(m_avfWrapper))
         return;
     
@@ -1157,11 +1189,8 @@ void MediaPlayerPrivateAVFoundationCF::processMediaSelectionOptions()
 
     // We enabled automatic media selection because we want alternate audio tracks to be enabled/disabled automatically,
     // but set the selected legible track to nil so text tracks will not be automatically configured.
-    if (!m_textTracks.size()) {
-        ASSERT(AVCFMediaSelectionGroupAllowsEmptySelection(legibleGroup));
-        AVCFPlayerItemRef playerItem = avPlayerItem(m_avfWrapper);
-
-        if (playerItem)
+    if (!m_textTracks.size() && AVCFMediaSelectionGroupAllowsEmptySelection(legibleGroup)) {
+        if (AVCFPlayerItemRef playerItem = avPlayerItem(m_avfWrapper))
             AVCFPlayerItemSelectMediaOptionInMediaSelectionGroup(playerItem, 0, legibleGroup);
     }
 
@@ -1285,6 +1314,13 @@ AVFWrapper::AVFWrapper(MediaPlayerPrivateAVFoundationCF* owner)
     LOG(Media, "AVFWrapper::AVFWrapper(%p)", this);
 
     m_notificationQueue = dispatch_queue_create("MediaPlayerPrivateAVFoundationCF.notificationQueue", 0);
+
+#if HAVE(AVFOUNDATION_LOADER_DELEGATE)
+    m_resourceLoaderCallbacks.version = kAVCFAssetResourceLoader_CallbacksVersion_1;
+    m_resourceLoaderCallbacks.context = nullptr;
+    m_resourceLoaderCallbacks.resourceLoaderShouldWaitForLoadingOfRequestedResource = AVFWrapper::resourceLoaderShouldWaitForLoadingOfRequestedResource;
+#endif
+
     addToMap();
 }
 
@@ -1431,14 +1467,11 @@ void AVFWrapper::createAssetForURL(const String& url, bool inheritURI)
     m_avAsset = adoptCF(AVCFURLAssetCreateWithURLAndOptions(kCFAllocatorDefault, urlRef.get(), optionsRef.get(), m_notificationQueue));
 
 #if HAVE(AVFOUNDATION_LOADER_DELEGATE)
-    AVCFAssetResourceLoaderCallbacks loaderCallbacks;
-    loaderCallbacks.version = kAVCFAssetResourceLoader_CallbacksVersion_1;
     ASSERT(callbackContext());
-    loaderCallbacks.context = callbackContext();
-    loaderCallbacks.resourceLoaderShouldWaitForLoadingOfRequestedResource = AVFWrapper::resourceLoaderShouldWaitForLoadingOfRequestedResource;
+    m_resourceLoaderCallbacks.context = callbackContext();
 
     AVCFAssetResourceLoaderRef resourceLoader = AVCFURLAssetGetResourceLoader(m_avAsset.get());
-    AVCFAssetResourceLoaderSetCallbacks(resourceLoader, &loaderCallbacks, globalLoaderDelegateQueue());
+    AVCFAssetResourceLoaderSetCallbacks(resourceLoader, &m_resourceLoaderCallbacks, globalLoaderDelegateQueue());
 #endif
 }
 
@@ -1572,7 +1605,7 @@ struct NotificationCallbackData {
 
 void AVFWrapper::processNotification(void* context)
 {
-    ASSERT(dispatch_get_main_queue() == dispatch_get_current_queue());
+    ASSERT(isMainThread());
     ASSERT(context);
 
     if (!context)
@@ -1718,7 +1751,7 @@ struct LegibleOutputData {
 
 void AVFWrapper::processCue(void* context)
 {
-    ASSERT(dispatch_get_main_queue() == dispatch_get_current_queue());
+    ASSERT(isMainThread());
     ASSERT(context);
 
     if (!context)
@@ -1741,7 +1774,7 @@ void AVFWrapper::processCue(void* context)
 
 void AVFWrapper::legibleOutputCallback(void* context, AVCFPlayerItemLegibleOutputRef legibleOutput, CFArrayRef attributedStrings, CFArrayRef nativeSampleBuffers, CMTime itemTime)
 {
-    ASSERT(dispatch_get_main_queue() != dispatch_get_current_queue());
+    ASSERT(!isMainThread());
     MutexLocker locker(mapLock());
     AVFWrapper* self = avfWrapperForCallbackContext(context);
     if (!self) {
@@ -1784,12 +1817,15 @@ void AVFWrapper::processShouldWaitForLoadingOfResource(void* context)
     AVFWrapper* self = avfWrapperForCallbackContext(loadRequestData->m_context);
     if (!self) {
         LOG(Media, "AVFWrapper::processShouldWaitForLoadingOfResource invoked for deleted AVFWrapper %d", reinterpret_cast<uintptr_t>(context));
-        AVCFAssetResourceLoadingRequestFinishLoadingWithError(loadRequestData->m_request.get(), nullptr);
+        RetainPtr<CFErrorRef> error = adoptCF(CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainCFNetwork, kCFURLErrorUnknown, nullptr));
+        AVCFAssetResourceLoadingRequestFinishLoadingWithError(loadRequestData->m_request.get(), error.get());
         return;
     }
 
-    if (!self->shouldWaitForLoadingOfResource(loadRequestData->m_request.get()))
-        AVCFAssetResourceLoadingRequestFinishLoadingWithError(loadRequestData->m_request.get(), nullptr);
+    if (!self->shouldWaitForLoadingOfResource(loadRequestData->m_request.get())) {
+        RetainPtr<CFErrorRef> error = adoptCF(CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainCFNetwork, kCFURLErrorUnknown, nullptr));
+        AVCFAssetResourceLoadingRequestFinishLoadingWithError(loadRequestData->m_request.get(), error.get());
+    }
 }
 
 bool AVFWrapper::shouldWaitForLoadingOfResource(AVCFAssetResourceLoadingRequestRef avRequest)
@@ -1819,7 +1855,7 @@ bool AVFWrapper::shouldWaitForLoadingOfResource(AVCFAssetResourceLoadingRequestR
         if (!m_owner->player()->keyNeeded(initData.get()))
             return false;
 
-        m_keyURIToRequestMap.set(keyURI, avRequest);
+        setRequestForKey(keyURI, avRequest);
         return true;
     }
 #endif
@@ -1861,6 +1897,7 @@ void AVFWrapper::setAsset(AVCFURLAssetRef asset)
 
 PlatformLayer* AVFWrapper::platformLayer()
 {
+    ASSERT(isMainThread());
     if (m_videoLayerWrapper)
         return m_videoLayerWrapper->platformLayer();
 
@@ -1991,14 +2028,36 @@ void AVFWrapper::updateVideoLayerGravity()
 }
 
 #if ENABLE(ENCRYPTED_MEDIA_V2)
+void AVFWrapper::setRequestForKey(const String& keyURI, AVCFAssetResourceLoadingRequestRef avRequest)
+{
+    auto requestsIterator = m_keyURIToRequestMap.find(keyURI);
+    if (requestsIterator != m_keyURIToRequestMap.end()) {
+        requestsIterator->value.append(avRequest);
+        return;
+    }
+
+    Vector<RetainPtr<AVCFAssetResourceLoadingRequestRef>> requests;
+    requests.append(avRequest);
+    m_keyURIToRequestMap.set(keyURI, requests);
+}
+
 RetainPtr<AVCFAssetResourceLoadingRequestRef> AVFWrapper::takeRequestForKeyURI(const String& keyURI)
 {
-    return m_keyURIToRequestMap.take(keyURI);
+    auto requestsIterator = m_keyURIToRequestMap.find(keyURI);
+    if (requestsIterator == m_keyURIToRequestMap.end())
+        return RetainPtr<AVCFAssetResourceLoadingRequestRef>();
+
+    auto request = requestsIterator->value.takeLast();
+    if (requestsIterator->value.isEmpty())
+        m_keyURIToRequestMap.take(keyURI);
+
+    return request;
 }
 #endif
 
 void LayerClient::platformCALayerLayoutSublayersOfLayer(PlatformCALayer* wrapperLayer)
 {
+    ASSERT(isMainThread());
     ASSERT(m_parent);
     ASSERT(m_parent->videoLayerWrapper() == wrapperLayer->platformLayer());
 
index 7fcc6a8..3966d6a 100644 (file)
@@ -64,6 +64,7 @@ private:
     static PassOwnPtr<MediaPlayerPrivateInterface> create(MediaPlayer*);
     static void getSupportedTypes(HashSet<String>& types);
     static MediaPlayer::SupportsType supportsType(const MediaEngineSupportParameters&);
+    static bool supportsKeySystem(const String& keySystem, const String& mimeType);
     static bool isAvailable();
 
     virtual void cancelLoad();
index c5320be..5f4bb97 100644 (file)
@@ -81,7 +81,8 @@ void WebCoreAVCFResourceLoader::startLoading()
         m_resource->addClient(this);
     else {
         LOG_ERROR("Failed to start load for media at url %s", requestURL.string().ascii().data());
-        AVCFAssetResourceLoadingRequestFinishLoadingWithError(m_avRequest.get(), nullptr);
+        RetainPtr<CFErrorRef> error = adoptCF(CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainCFNetwork, kCFURLErrorUnknown, nullptr));
+        AVCFAssetResourceLoadingRequestFinishLoadingWithError(m_avRequest.get(), error.get());
     }
 }
 
@@ -110,7 +111,8 @@ void WebCoreAVCFResourceLoader::responseReceived(CachedResource* resource, const
 
     int status = response.httpStatusCode();
     if (status && (status < 200 || status > 299)) {
-        AVCFAssetResourceLoadingRequestFinishLoadingWithError(m_avRequest.get(), nullptr);
+        RetainPtr<CFErrorRef> error = adoptCF(CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainCFNetwork, status, nullptr));
+        AVCFAssetResourceLoadingRequestFinishLoadingWithError(m_avRequest.get(), error.get());
         return;
     }
 
@@ -131,7 +133,8 @@ void WebCoreAVCFResourceLoader::notifyFinished(CachedResource* resource)
         // FIXME:    [[m_avRequest.get() contentInformationRequest] setContentType:@""];
         notImplemented();
 
-        AVCFAssetResourceLoadingRequestFinishLoadingWithError(m_avRequest.get(), nullptr);
+        RetainPtr<CFErrorRef> error = adoptCF(CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainCFNetwork, kCFURLErrorUnknown, nullptr));
+        AVCFAssetResourceLoadingRequestFinishLoadingWithError(m_avRequest.get(), error.get());
     } else {
         fulfillRequestWithResource(resource);
         // FIXME: [m_avRequest.get() finishLoading];