Changeset 249321 in webkit
- Timestamp:
- Aug 30, 2019 4:02:18 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r249316 r249321 1 2019-08-30 Charlie Turner <cturner@igalia.com> 2 3 [GStreamer] Do not ref the player count from background threads. 4 https://bugs.webkit.org/show_bug.cgi?id=201222 5 6 Reviewed by Xabier Rodriguez-Calvar. 7 8 Test: imported/w3c/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html 9 10 In the sync-message handler, a ref() was being taken waiting for a 11 CDM instance to be attached. This hits asserts since you are not 12 allowed to ref() an object created on the main thread 13 (BasePlayer) on a background thread. 14 15 The protection condition was overly scoped, tidied up the locking 16 and made it more granular. To avoid needing to hold a ref() in the 17 background thread, use instead a semaphore to signal when a CDM 18 instance is attached, or the player has been destroyed. 19 20 Also remove an erroneous safe-guard, the operator= in 21 isCDMInstanceAvailable will ref() the CDMInstance for us. This use 22 of holding a reference to CDMInstance in the decryptors is not 23 thread-safe, and now we have a problem since there's no clean way 24 to communicate with CDMInstance from background threads without 25 being thread unsafe. For ClearKey and Widevine, a thread safe 26 ProxyCDM needs to be designed and passed to background 27 threads (upcoming patch). 28 29 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp: 30 (WebCore::MediaPlayerPrivateGStreamerBase::~MediaPlayerPrivateGStreamerBase): 31 (WebCore::MediaPlayerPrivateGStreamerBase::handleSyncMessage): 32 (WebCore::MediaPlayerPrivateGStreamerBase::cdmInstanceAttached): 33 (WebCore::MediaPlayerPrivateGStreamerBase::cdmInstanceDetached): 34 (WebCore::MediaPlayerPrivateGStreamerBase::handleProtectionEvent): 35 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h: 36 * platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp: 37 (isCDMInstanceAvailable): 38 1 39 2019-08-30 Sihui Liu <sihui_liu@apple.com> 2 40 -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
r249217 r249321 245 245 #endif 246 246 247 #if ENABLE(ENCRYPTED_MEDIA)248 m_protectionCondition.notifyAll();249 #endif250 247 m_notifier->invalidate(); 251 248 … … 266 263 // waiting there, and ensure that any triggerRepaint call reaching the lock won't wait on m_drawCondition. 267 264 cancelRepaint(true); 265 266 #if ENABLE(ENCRYPTED_MEDIA) 267 m_cdmAttachmentSemaphore.signal(); 268 #endif 268 269 269 270 // The change to GST_STATE_NULL state is always synchronous. So after this gets executed we don't need to worry … … 328 329 } 329 330 GST_DEBUG_OBJECT(pipeline(), "handling drm-preferred-decryption-system-id need context message"); 330 LockHolder lock(m_protectionMutex); 331 ProtectionSystemEvents protectionSystemEvents(message); 332 GST_TRACE("found %zu protection events, %zu decryptors available", protectionSystemEvents.events().size(), protectionSystemEvents.availableSystems().size()); 331 333 332 InitData initData; 334 335 for (auto& event : protectionSystemEvents.events()) { 336 const char* eventKeySystemId = nullptr; 337 GstBuffer* data = nullptr; 338 gst_event_parse_protection(event.get(), &eventKeySystemId, &data, nullptr); 339 340 initData.append({eventKeySystemId, data}); 341 m_handledProtectionEvents.add(GST_EVENT_SEQNUM(event.get())); 333 { 334 LockHolder lock(m_protectionMutex); 335 ProtectionSystemEvents protectionSystemEvents(message); 336 GST_TRACE("found %zu protection events, %zu decryptors available", protectionSystemEvents.events().size(), protectionSystemEvents.availableSystems().size()); 337 338 for (auto& event : protectionSystemEvents.events()) { 339 const char* eventKeySystemId = nullptr; 340 GstBuffer* data = nullptr; 341 gst_event_parse_protection(event.get(), &eventKeySystemId, &data, nullptr); 342 343 initData.append({eventKeySystemId, data}); 344 m_handledProtectionEvents.add(GST_EVENT_SEQNUM(event.get())); 345 } 342 346 } 343 344 347 initializationDataEncountered(WTFMove(initData)); 345 348 346 349 GST_INFO_OBJECT(pipeline(), "waiting for a CDM instance"); 347 m_protectionCondition.waitFor(m_protectionMutex, Seconds(4), [this] { 348 return this->m_cdmInstance; 349 }); 350 351 if (m_cdmInstance && !m_cdmInstance->keySystem().isEmpty()) { 350 if (m_cdmAttachmentSemaphore.waitFor(4_s) 351 && m_notifier->isValid() // Check the player is not being destroyed. 352 && !m_cdmInstance->keySystem().isEmpty()) { 352 353 const char* preferredKeySystemUuid = GStreamerEMEUtilities::keySystemToUuid(m_cdmInstance->keySystem()); 353 354 GST_INFO_OBJECT(pipeline(), "working with key system %s, continuing with key system %s on %s", m_cdmInstance->keySystem().utf8().data(), preferredKeySystemUuid, GST_MESSAGE_SRC_NAME(message)); … … 1322 1323 GST_DEBUG_OBJECT(m_pipeline.get(), "CDM instance %p dispatched as context", m_cdmInstance.get()); 1323 1324 1324 m_ protectionCondition.notifyAll();1325 m_cdmAttachmentSemaphore.signal(); 1325 1326 } 1326 1327 … … 1342 1343 GRefPtr<GstContext> context = adoptGRef(gst_context_new("drm-cdm-instance", FALSE)); 1343 1344 gst_element_set_context(GST_ELEMENT(m_pipeline.get()), context.get()); 1344 1345 m_protectionCondition.notifyAll();1346 1345 } 1347 1346 … … 1361 1360 void MediaPlayerPrivateGStreamerBase::handleProtectionEvent(GstEvent* event) 1362 1361 { 1363 if (m_handledProtectionEvents.contains(GST_EVENT_SEQNUM(event))) { 1364 GST_DEBUG_OBJECT(pipeline(), "event %u already handled", GST_EVENT_SEQNUM(event)); 1365 return; 1362 { 1363 LockHolder lock(m_protectionMutex); 1364 if (m_handledProtectionEvents.contains(GST_EVENT_SEQNUM(event))) { 1365 GST_DEBUG_OBJECT(pipeline(), "event %u already handled", GST_EVENT_SEQNUM(event)); 1366 return; 1367 } 1366 1368 } 1367 1369 GST_DEBUG_OBJECT(pipeline(), "handling event %u from MSE", GST_EVENT_SEQNUM(event)); -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h
r249276 r249321 37 37 #include <wtf/RunLoop.h> 38 38 #include <wtf/WeakPtr.h> 39 #include <wtf/threads/BinarySemaphore.h> 39 40 40 41 #if USE(GSTREAMER_GL) … … 301 302 302 303 #if ENABLE(ENCRYPTED_MEDIA) 303 Lock m_protectionMutex; 304 Condition m_protectionCondition; 304 BinarySemaphore m_cdmAttachmentSemaphore; 305 305 RefPtr<const CDMInstance> m_cdmInstance; 306 307 Lock m_protectionMutex; // Guards access to m_handledProtectionEvents. 306 308 HashSet<uint32_t> m_handledProtectionEvents; 309 307 310 bool m_waitingForKey { false }; 308 311 #endif -
trunk/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp
r242035 r249321 294 294 if (context) { 295 295 const GValue* value = gst_structure_get_value(gst_context_get_structure(context.get()), "cdm-instance"); 296 // Capture the CDMInstance into a separate variable to avoid missing a refcount. 297 CDMInstance* instance = value ? reinterpret_cast<CDMInstance*>(g_value_get_pointer(value)) : nullptr; 298 // ... And force a refcount bump using operator=. 299 priv->cdmInstance = instance; 296 priv->cdmInstance = value ? reinterpret_cast<CDMInstance*>(g_value_get_pointer(value)) : nullptr; 300 297 if (priv->cdmInstance) 301 298 GST_DEBUG_OBJECT(self, "received a new CDM instance %p, refcount %u", priv->cdmInstance.get(), priv->cdmInstance->refCount());
Note: See TracChangeset
for help on using the changeset viewer.