Changeset 238738 in webkit
- Timestamp:
- Nov 30, 2018 8:21:35 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r238737 r238738 1 2018-11-30 Xabier Rodriguez Calvar <calvaris@igalia.com> 2 3 [GStreamer][EME] CDMInstance should be shipped as a GstContext to the decryptors 4 https://bugs.webkit.org/show_bug.cgi?id=192075 5 6 Reviewed by Philippe Normand. 7 8 So far, we were shipping the CDMInstance in an event to the 9 decryptors and they were requesting it with bus messages when it 10 was not found. Now we ship it with a GstContext that is set to the 11 pipeline and read from the decryptors, which is now always 12 available. 13 14 As a consequence of changing this flow, the attemptToDecrypt one 15 was affected as well because it was tied to CDMInstance 16 shipment. A workaround was added: when the decryptors send the 17 waitingForKey, an attemptToDecrypt will be performed. A FIXME was 18 added for this. A subconsequence is that 19 attemptToDecryptWithInstance is reworked to rely always in 20 attemptToDecryptWithLocal instance, the former becomes final and 21 the latter virtual. 22 23 This is a rework, no new tests needed. 24 25 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: 26 (WebCore::MediaPlayerPrivateGStreamer::handleMessage): 27 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp: 28 (WebCore::MediaPlayerPrivateGStreamerBase::cdmInstanceAttached): 29 (WebCore::MediaPlayerPrivateGStreamerBase::cdmInstanceDetached): 30 (WebCore::MediaPlayerPrivateGStreamerBase::attemptToDecryptWithLocalInstance): 31 (WebCore::MediaPlayerPrivateGStreamerBase::dispatchCDMInstance): Deleted. 32 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h: 33 * platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp: 34 (webkit_media_common_encryption_decrypt_class_init): 35 (webkitMediaCommonEncryptionDecryptTransformInPlace): 36 (webkitMediaCommonEncryptionDecryptIsCDMInstanceAvailable): 37 (webkitMediaCommonEncryptionDecryptSinkEventHandler): 38 (webKitMediaCommonEncryptionDecryptorSetContext): 39 * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp: 40 (WebCore::MediaPlayerPrivateGStreamerMSE::attemptToDecryptWithLocalInstance): 41 (WebCore::MediaPlayerPrivateGStreamerMSE::attemptToDecryptWithInstance): Deleted. 42 * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h: 43 1 44 2018-11-30 Zalan Bujtas <zalan@apple.com> 2 45 -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
r238396 r238738 1330 1330 GST_DEBUG_OBJECT(pipeline(), "drm-waiting-for-key message from %s", GST_MESSAGE_SRC_NAME(message)); 1331 1331 setWaitingForKey(true); 1332 // FIXME: The decryptors should be able to attempt to decrypt after being created and linked in a pipeline but currently they are not and current 1333 // architecture does not make this very easy. Fortunately, the arch will change soon and it does not pay off to fix this now with something that could be 1334 // more convoluted. In the meantime, force attempt to decrypt when they get blocked. 1335 attemptToDecryptWithLocalInstance(); 1332 1336 } else if (gst_structure_has_name(structure, "drm-key-received")) { 1333 1337 GST_DEBUG_OBJECT(pipeline(), "drm-key-received message from %s", GST_MESSAGE_SRC_NAME(message)); 1334 1338 setWaitingForKey(false); 1335 } else if (gst_structure_has_name(structure, "drm-cdm-instance-needed")) {1336 GST_DEBUG_OBJECT(pipeline(), "drm-cdm-instance-needed message from %s", GST_MESSAGE_SRC_NAME(message));1337 dispatchCDMInstance();1338 1339 } 1339 1340 #endif -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
r238282 r238738 1198 1198 void MediaPlayerPrivateGStreamerBase::cdmInstanceAttached(CDMInstance& instance) 1199 1199 { 1200 ASSERT(isMainThread()); 1201 1202 if (m_cdmInstance == &instance) 1203 return; 1204 1205 if (!m_pipeline) { 1206 GST_ERROR("no pipeline yet"); 1207 ASSERT_NOT_REACHED(); 1208 return; 1209 } 1210 1211 m_cdmInstance = &instance; 1212 1213 GRefPtr<GstContext> context = adoptGRef(gst_context_new("drm-cdm-instance", FALSE)); 1214 GstStructure* contextStructure = gst_context_writable_structure(context.get()); 1215 gst_structure_set(contextStructure, "cdm-instance", G_TYPE_POINTER, m_cdmInstance.get(), nullptr); 1216 gst_element_set_context(GST_ELEMENT(m_pipeline.get()), context.get()); 1217 1218 GST_DEBUG_OBJECT(m_pipeline.get(), "CDM instance %p dispatched as context", m_cdmInstance.get()); 1219 1220 m_protectionCondition.notifyAll(); 1221 } 1222 1223 void MediaPlayerPrivateGStreamerBase::cdmInstanceDetached(CDMInstance& instance) 1224 { 1225 ASSERT(isMainThread()); 1226 1200 1227 if (m_cdmInstance != &instance) { 1201 m_cdmInstance = &instance; 1202 GST_DEBUG_OBJECT(pipeline(), "CDM instance %p set", m_cdmInstance.get()); 1203 m_protectionCondition.notifyAll(); 1204 } 1205 } 1206 1207 void MediaPlayerPrivateGStreamerBase::cdmInstanceDetached(CDMInstance& instance) 1208 { 1209 #ifdef NDEBUG 1210 UNUSED_PARAM(instance); 1211 #endif 1212 if (m_cdmInstance == &instance) { 1213 GST_DEBUG_OBJECT(pipeline(), "detaching CDM instance %p", m_cdmInstance.get()); 1214 m_cdmInstance = nullptr; 1215 m_protectionCondition.notifyAll(); 1216 } 1228 GST_WARNING("passed CDMInstance %p is different from stored one %p", &instance, m_cdmInstance.get()); 1229 ASSERT_NOT_REACHED(); 1230 return; 1231 } 1232 1233 ASSERT(m_pipeline); 1234 1235 GST_DEBUG_OBJECT(m_pipeline.get(), "detaching CDM instance %p, setting empty context", m_cdmInstance.get()); 1236 m_cdmInstance = nullptr; 1237 1238 GRefPtr<GstContext> context = adoptGRef(gst_context_new("drm-cdm-instance", FALSE)); 1239 gst_element_set_context(GST_ELEMENT(m_pipeline.get()), context.get()); 1240 1241 m_protectionCondition.notifyAll(); 1217 1242 } 1218 1243 … … 1226 1251 void MediaPlayerPrivateGStreamerBase::attemptToDecryptWithLocalInstance() 1227 1252 { 1228 bool eventHandled = gst_element_send_event(pipeline(), gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM_OOB, 1229 gst_structure_new("attempt-to-decrypt", "cdm-instance", G_TYPE_POINTER, m_cdmInstance.get(), nullptr))); 1253 bool eventHandled = gst_element_send_event(pipeline(), gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM_OOB, gst_structure_new_empty("attempt-to-decrypt"))); 1230 1254 GST_DEBUG("attempting to decrypt, event handled %s", boolForPrinting(eventHandled)); 1231 1255 } … … 1236 1260 gst_structure_new("drm-cipher", "key", GST_TYPE_BUFFER, buffer, nullptr))); 1237 1261 GST_TRACE("emitted decryption cipher key on pipeline, event handled %s", boolForPrinting(eventHandled)); 1238 }1239 1240 void MediaPlayerPrivateGStreamerBase::dispatchCDMInstance()1241 {1242 // This function dispatches the CDMInstance in GStreamer playback pipeline.1243 if (m_cdmInstance)1244 m_player->attemptToDecryptWithInstance(const_cast<CDMInstance&>(*m_cdmInstance.get()));1245 1262 } 1246 1263 -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h
r238131 r238738 151 151 void dispatchDecryptionKey(GstBuffer*); 152 152 void handleProtectionEvent(GstEvent*); 153 void attemptToDecryptWithLocalInstance(); 154 void attemptToDecryptWithInstance(CDMInstance&) override; 155 void dispatchCDMInstance(); 153 virtual void attemptToDecryptWithLocalInstance(); 154 void attemptToDecryptWithInstance(CDMInstance&) final; 156 155 void initializationDataEncountered(InitData&&); 157 156 void setWaitingForKey(bool); -
trunk/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp
r238131 r238738 32 32 #include <wtf/RunLoop.h> 33 33 34 using WebCore::CDMInstance; 35 34 36 #define WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_MEDIA_CENC_DECRYPT, WebKitMediaCommonEncryptionDecryptPrivate)) 35 37 struct _WebKitMediaCommonEncryptionDecryptPrivate { 36 38 GRefPtr<GstEvent> protectionEvent; 37 RefPtr< WebCore::CDMInstance> cdmInstance;39 RefPtr<CDMInstance> cdmInstance; 38 40 bool keyReceived; 39 41 bool waitingForKey { false }; … … 43 45 44 46 static GstStateChangeReturn webKitMediaCommonEncryptionDecryptorChangeState(GstElement*, GstStateChange transition); 47 static void webKitMediaCommonEncryptionDecryptorSetContext(GstElement*, GstContext*); 45 48 static void webKitMediaCommonEncryptionDecryptorFinalize(GObject*); 46 49 static GstCaps* webkitMediaCommonEncryptionDecryptTransformCaps(GstBaseTransform*, GstPadDirection, GstCaps*, GstCaps*); … … 48 51 static gboolean webkitMediaCommonEncryptionDecryptSinkEventHandler(GstBaseTransform*, GstEvent*); 49 52 static gboolean webkitMediaCommonEncryptionDecryptorQueryHandler(GstBaseTransform*, GstPadDirection, GstQuery*); 50 53 static bool webkitMediaCommonEncryptionDecryptIsCDMInstanceAvailable(WebKitMediaCommonEncryptionDecrypt*); 51 54 52 55 GST_DEBUG_CATEGORY_STATIC(webkit_media_common_encryption_decrypt_debug_category); … … 66 69 GstElementClass* elementClass = GST_ELEMENT_CLASS(klass); 67 70 elementClass->change_state = GST_DEBUG_FUNCPTR(webKitMediaCommonEncryptionDecryptorChangeState); 71 elementClass->set_context = GST_DEBUG_FUNCPTR(webKitMediaCommonEncryptionDecryptorSetContext); 68 72 69 73 GstBaseTransformClass* baseTransformClass = GST_BASE_TRANSFORM_CLASS(klass); … … 210 214 priv->waitingForKey = true; 211 215 gst_element_post_message(GST_ELEMENT(self), gst_message_new_element(GST_OBJECT(self), gst_structure_new_empty("drm-waiting-for-key"))); 212 gst_element_post_message(GST_ELEMENT(self), gst_message_new_element(GST_OBJECT(self), gst_structure_new_empty("drm-cdm-instance-needed")));213 216 214 217 priv->condition.waitFor(priv->mutex, Seconds(5), [priv] { … … 300 303 } 301 304 305 static bool webkitMediaCommonEncryptionDecryptIsCDMInstanceAvailable(WebKitMediaCommonEncryptionDecrypt* self) 306 { 307 WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(self); 308 309 ASSERT(priv->mutex.isLocked()); 310 311 if (!priv->cdmInstance) { 312 GRefPtr<GstContext> context = adoptGRef(gst_element_get_context(GST_ELEMENT(self), "drm-cdm-instance")); 313 // According to the GStreamer documentation, if we can't find the context, we should run a downstream query, then an upstream one and then send a bus 314 // message. In this case that does not make a lot of sense since only the app (player) answers it, meaning that no query is going to solve it. A message 315 // could be helpful but the player sets the context as soon as it gets the CDMInstance and if it does not have it, we have no way of asking for one as it is 316 // something provided by crossplatform code. This means that we won't be able to answer the bus request in any way either. Summing up, neither queries nor bus 317 // requests are useful here. 318 if (context) { 319 const GValue* value = gst_structure_get_value(gst_context_get_structure(context.get()), "cdm-instance"); 320 priv->cdmInstance = value ? reinterpret_cast<CDMInstance*>(g_value_get_pointer(value)) : nullptr; 321 if (priv->cdmInstance) 322 GST_DEBUG_OBJECT(self, "received new CDMInstance %p", priv->cdmInstance.get()); 323 else 324 GST_TRACE_OBJECT(self, "former instance was detached"); 325 } 326 } 327 328 GST_TRACE_OBJECT(self, "CDMInstance available %s", boolForPrinting(priv->cdmInstance.get())); 329 return priv->cdmInstance; 330 } 302 331 303 332 static gboolean webkitMediaCommonEncryptionDecryptSinkEventHandler(GstBaseTransform* trans, GstEvent* event) … … 307 336 WebKitMediaCommonEncryptionDecryptClass* klass = WEBKIT_MEDIA_CENC_DECRYPT_GET_CLASS(self); 308 337 gboolean result = FALSE; 309 310 338 311 339 switch (GST_EVENT_TYPE(event)) { … … 317 345 // events will not be handled by the demuxer, so the must be 318 346 // handled in here. 319 const GstStructure* structure = gst_event_get_structure(event); 320 gst_structure_get(structure, "cdm-instance", G_TYPE_POINTER, &priv->cdmInstance, nullptr); 321 if (!priv->cdmInstance) { 322 GST_ERROR_OBJECT(self, "No CDM instance received"); 347 LockHolder locker(priv->mutex); 348 if (!webkitMediaCommonEncryptionDecryptIsCDMInstanceAvailable(self)) { 349 GST_ERROR_OBJECT(self, "No CDM instance available"); 323 350 result = FALSE; 324 351 break; 325 352 } 326 GST_DEBUG_OBJECT(self, "received a cdm instance %p", priv->cdmInstance.get());327 353 328 354 if (klass->handleKeyResponse(self, event)) { … … 375 401 } 376 402 403 static void webKitMediaCommonEncryptionDecryptorSetContext(GstElement* element, GstContext* context) 404 { 405 WebKitMediaCommonEncryptionDecrypt* self = WEBKIT_MEDIA_CENC_DECRYPT(element); 406 WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(self); 407 408 if (gst_context_has_context_type(context, "drm-cdm-instance")) { 409 const GValue* value = gst_structure_get_value(gst_context_get_structure(context), "cdm-instance"); 410 LockHolder locker(priv->mutex); 411 priv->cdmInstance = value ? reinterpret_cast<CDMInstance*>(g_value_get_pointer(value)) : nullptr; 412 GST_DEBUG_OBJECT(self, "received new CDMInstance %p", priv->cdmInstance.get()); 413 return; 414 } 415 416 GST_ELEMENT_CLASS(parent_class)->set_context(element, context); 417 } 418 377 419 #endif // ENABLE(ENCRYPTED_MEDIA) && USE(GSTREAMER) -
trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp
r238412 r238738 910 910 911 911 #if ENABLE(ENCRYPTED_MEDIA) 912 void MediaPlayerPrivateGStreamerMSE::attemptToDecryptWith Instance(CDMInstance& instance)913 { 914 if (is<CDMInstanceClearKey>( instance)) {915 auto& c kInstance = downcast<CDMInstanceClearKey>(instance);916 if (c kInstance.keys().isEmpty())912 void MediaPlayerPrivateGStreamerMSE::attemptToDecryptWithLocalInstance() 913 { 914 if (is<CDMInstanceClearKey>(*m_cdmInstance)) { 915 auto& clearkeyCDMInstance = downcast<CDMInstanceClearKey>(*m_cdmInstance); 916 if (clearkeyCDMInstance.keys().isEmpty()) 917 917 return; 918 918 … … 931 931 }; 932 932 933 for (auto& key : c kInstance.keys()) {933 for (auto& key : clearkeyCDMInstance.keys()) { 934 934 appendBuffer(&keyIDList, *key.keyIDData); 935 935 appendBuffer(&keyValueList, *key.keyValueData); … … 939 939 gst_structure_set_value(structure.get(), "key-ids", &keyIDList); 940 940 gst_structure_set_value(structure.get(), "key-values", &keyValueList); 941 gst_structure_set(structure.get(), "cdm-instance", G_TYPE_POINTER, &instance, nullptr);942 941 943 942 gst_element_send_event(m_playbackPipeline->pipeline(), gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure.release())); -
trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.h
r235598 r238738 87 87 88 88 #if ENABLE(ENCRYPTED_MEDIA) 89 void attemptToDecryptWith Instance(CDMInstance&) final;89 void attemptToDecryptWithLocalInstance() final; 90 90 #endif 91 91
Note: See TracChangeset
for help on using the changeset viewer.