[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 6eac60018876e7c9b8f4f1027dc6578de71ee43b..3b054576e0cf33957aa7263ce5191a45ab1c81cc 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 f9d14af48626caa94b3ffa89f355a08605d5988c..a7ce21ea2a18ca88cddf2c3103f329ffa2659099 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 3d6f6c94f06b6c8db18e4ec694d6662fd0364b82..da13ea18a095d7f45ef472c852154ad894136029 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 afcb70644eb54732212351df385b4a1f04a1d559..e6ca4444e7251e86c86604921c3fd02fe030f26b 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 5fdf1ebc5c726076f85af5e948b464fd92c91dfd..a15c9c35210bfa0615b3cde90006b738cd155d39 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 7fcc6a8384b12bda20e09a6a97f8d7c8d3247781..3966d6a74ae61bfac34b9a97fb1733a8be207c26 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 c5320be20f290093b6ec2f4abe9cd5f29e1102c7..5f4bb97cc57bd0fa8e5e3d0e21c7d15d9a1e1c22 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];