Modified: branches/safari-537.74-branch/Source/WebCore/ChangeLog (160423 => 160424)
--- branches/safari-537.74-branch/Source/WebCore/ChangeLog 2013-12-11 12:12:06 UTC (rev 160423)
+++ branches/safari-537.74-branch/Source/WebCore/ChangeLog 2013-12-11 12:14:24 UTC (rev 160424)
@@ -1,5 +1,26 @@
2013-12-11 Lucas Forschler <[email protected]>
+ Merge r159691
+
+ 2013-11-22 Brent Fulgham <[email protected]>
+
+ [Win] Avoid deadlock when interacting with some AVFoundationCF content
+ <rdar://problem/15482977> and https://bugs.webkit.org/show_bug.cgi?id=124752
+
+ Prevent deadlock caused by conflict over the "mapLock" mutex. Notification handling in the file,
+ which modify assets and make other changes, are required to happen on the main thread. This
+ patch enforces this requirement.
+
+ Reviewed by Eric Carlson.
+
+ * platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp:
+ (WebCore::NotificationCallbackData::NotificationCallbackData): Added
+ (WebCore::AVFWrapper::processNotification): Moved logic from 'notificationCallback', which was
+ sometimes happening on a background thread.
+ (WebCore::AVFWrapper::notificationCallback): Dispatch calls to main thread.
+
+2013-12-11 Lucas Forschler <[email protected]>
+
Merge r159460
2013-11-18 David Hyatt <[email protected]>
Modified: branches/safari-537.74-branch/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp (160423 => 160424)
--- branches/safari-537.74-branch/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp 2013-12-11 12:12:06 UTC (rev 160423)
+++ branches/safari-537.74-branch/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp 2013-12-11 12:14:24 UTC (rev 160424)
@@ -115,6 +115,7 @@
static void periodicTimeObserverCallback(AVCFPlayerRef, CMTime, void*);
static void seekCompletedCallback(AVCFPlayerItemRef, Boolean, void*);
static void notificationCallback(CFNotificationCenterRef, void*, CFStringRef, const void*, CFDictionaryRef);
+ static void processNotification(void* context);
inline AVCFPlayerLayerRef videoLayer() const { return (AVCFPlayerLayerRef)m_avCFVideoLayer.get(); }
inline AVCFPlayerRef avPlayer() const { return (AVCFPlayerRef)m_avPlayer.get(); }
@@ -1392,21 +1393,34 @@
self->m_owner->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::PlayerTimeChanged, time);
}
-void AVFWrapper::notificationCallback(CFNotificationCenterRef, void* observer, CFStringRef propertyName, const void* object, CFDictionaryRef)
+struct NotificationCallbackData {
+ RetainPtr<CFStringRef> m_propertyName;
+ void* m_context;
+
+ NotificationCallbackData(CFStringRef propertyName, void* context)
+ : m_propertyName(propertyName), m_context(context)
+ {
+ }
+};
+
+void AVFWrapper::processNotification(void* context)
{
+ ASSERT(dispatch_get_main_queue() == dispatch_get_current_queue());
+ ASSERT(context);
+
+ if (!context)
+ return;
+
+ OwnPtr<NotificationCallbackData> notificationData = adoptPtr(reinterpret_cast<NotificationCallbackData*>(context));
+
MutexLocker locker(mapLock());
- AVFWrapper* self = avfWrapperForCallbackContext(observer);
-
+ AVFWrapper* self = avfWrapperForCallbackContext(notificationData->m_context);
if (!self) {
- LOG(Media, "AVFWrapper::notificationCallback invoked for deleted AVFWrapper %d", reinterpret_cast<uintptr_t>(observer));
+ LOG(Media, "AVFWrapper::processNotification invoked for deleted AVFWrapper %d", reinterpret_cast<uintptr_t>(context));
return;
}
-#if !LOG_DISABLED
- char notificationName[256];
- CFStringGetCString(propertyName, notificationName, sizeof(notificationName), kCFStringEncodingASCII);
- LOG(Media, "AVFWrapper::notificationCallback(%p) %s", self, notificationName);
-#endif
+ CFStringRef propertyName = notificationData->m_propertyName.get();
if (CFEqual(propertyName, AVCFPlayerItemDidPlayToEndTimeNotification))
self->m_owner->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemDidPlayToEndTime);
@@ -1437,6 +1451,19 @@
ASSERT_NOT_REACHED();
}
+void AVFWrapper::notificationCallback(CFNotificationCenterRef, void* observer, CFStringRef propertyName, const void* object, CFDictionaryRef)
+{
+#if !LOG_DISABLED
+ char notificationName[256];
+ CFStringGetCString(propertyName, notificationName, sizeof(notificationName), kCFStringEncodingASCII);
+ LOG(Media, "AVFWrapper::notificationCallback(if=%d) %s", reinterpret_cast<uintptr_t>(observer), notificationName);
+#endif
+
+ OwnPtr<NotificationCallbackData> notificationData = adoptPtr(new NotificationCallbackData(propertyName, observer));
+
+ dispatch_async_f(dispatch_get_main_queue(), notificationData.leakPtr(), processNotification);
+}
+
void AVFWrapper::loadPlayableCompletionCallback(AVCFAssetRef, void* context)
{
MutexLocker locker(mapLock());