Title: [238083] trunk/Source/WebCore
Revision
238083
Author
calva...@igalia.com
Date
2018-11-12 04:40:12 -0800 (Mon, 12 Nov 2018)

Log Message

[GStreamer][EME] waitingforkey event should consider decryptors' waiting status
https://bugs.webkit.org/show_bug.cgi?id=191459

Reviewed by Carlos Garcia Campos.

The new cross platform architecture to report waitingforkey and
recover from it requires a more accurate knowledge of what is
going on with the decryptors because events are reported only once
(per key exchange run) and crossplatform only continues if we are
actually ready to continue, meaning that no decryptors are
waiting.

* platform/graphics/gstreamer/GUniquePtrGStreamer.h: Added
GstIterator deleter.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
(WebCore::MediaPlayerPrivateGStreamerBase::setWaitingForKey): Bail
out if we are requested to not wait anymore but there are still
waiting decryptors.
(WebCore::MediaPlayerPrivateGStreamerBase::waitingForKey const):
Query the pipeline, just a query after pipeline is built and
manual inspection during build. The query is optimal but sometimes
we can get this request when the pipeline is under construction so
queries do not arrive at the decryptors and we have to deliver it
by ourselves.
(WebCore::MediaPlayerPrivateGStreamerBase::reportWaitingForKey:
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
(WebCore::MediaPlayerPrivateGStreamerBase::reportWaitingForKey:
Deleted because it is now inlined.
* platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp:
(webKitMediaClearKeyDecryptorDecrypt): Fixed small compiler warning.
* platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp:
(webkit_media_common_encryption_decrypt_class_init): Override
query method.
(webkitMediaCommonEncryptionDecryptTransformInPlace): When the
decryptor is going to block to wait, report before. When the
decryptor receives the key, report it got it.
(webkitMediaCommonEncryptionDecryptSinkEventHandler): Do not
handle waitingforkey here.
(webkitMediaCommonEncryptionDecryptorQueryHandler): Report if the
decryptor is waiting.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (238082 => 238083)


--- trunk/Source/WebCore/ChangeLog	2018-11-12 09:05:49 UTC (rev 238082)
+++ trunk/Source/WebCore/ChangeLog	2018-11-12 12:40:12 UTC (rev 238083)
@@ -1,3 +1,46 @@
+2018-11-12  Xabier Rodriguez Calvar  <calva...@igalia.com>
+
+        [GStreamer][EME] waitingforkey event should consider decryptors' waiting status
+        https://bugs.webkit.org/show_bug.cgi?id=191459
+
+        Reviewed by Carlos Garcia Campos.
+
+        The new cross platform architecture to report waitingforkey and
+        recover from it requires a more accurate knowledge of what is
+        going on with the decryptors because events are reported only once
+        (per key exchange run) and crossplatform only continues if we are
+        actually ready to continue, meaning that no decryptors are
+        waiting.
+
+        * platform/graphics/gstreamer/GUniquePtrGStreamer.h: Added
+        GstIterator deleter.
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
+        (WebCore::MediaPlayerPrivateGStreamerBase::setWaitingForKey): Bail
+        out if we are requested to not wait anymore but there are still
+        waiting decryptors.
+        (WebCore::MediaPlayerPrivateGStreamerBase::waitingForKey const):
+        Query the pipeline, just a query after pipeline is built and
+        manual inspection during build. The query is optimal but sometimes
+        we can get this request when the pipeline is under construction so
+        queries do not arrive at the decryptors and we have to deliver it
+        by ourselves.
+        (WebCore::MediaPlayerPrivateGStreamerBase::reportWaitingForKey:
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
+        (WebCore::MediaPlayerPrivateGStreamerBase::reportWaitingForKey:
+        Deleted because it is now inlined.
+        * platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp:
+        (webKitMediaClearKeyDecryptorDecrypt): Fixed small compiler warning.
+        * platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp:
+        (webkit_media_common_encryption_decrypt_class_init): Override
+        query method.
+        (webkitMediaCommonEncryptionDecryptTransformInPlace): When the
+        decryptor is going to block to wait, report before. When the
+        decryptor receives the key, report it got it.
+        (webkitMediaCommonEncryptionDecryptSinkEventHandler): Do not
+        handle waitingforkey here.
+        (webkitMediaCommonEncryptionDecryptorQueryHandler): Report if the
+        decryptor is waiting.
+
 2018-11-12  Michael Catanzaro  <mcatanz...@igalia.com>
 
         [GTK] Silence ATK_XY_PARENT warnings

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/GUniquePtrGStreamer.h (238082 => 238083)


--- trunk/Source/WebCore/platform/graphics/gstreamer/GUniquePtrGStreamer.h	2018-11-12 09:05:49 UTC (rev 238082)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GUniquePtrGStreamer.h	2018-11-12 12:40:12 UTC (rev 238083)
@@ -32,6 +32,7 @@
 
 WTF_DEFINE_GPTR_DELETER(GstStructure, gst_structure_free)
 WTF_DEFINE_GPTR_DELETER(GstInstallPluginsContext, gst_install_plugins_context_free)
+WTF_DEFINE_GPTR_DELETER(GstIterator, gst_iterator_free)
 WTF_DEFINE_GPTR_DELETER(GstSegment, gst_segment_free)
 WTF_DEFINE_GPTR_DELETER(GstFlowCombiner, gst_flow_combiner_free)
 WTF_DEFINE_GPTR_DELETER(GstByteReader, gst_byte_reader_free)

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp (238082 => 238083)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp	2018-11-12 09:05:49 UTC (rev 238082)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp	2018-11-12 12:40:12 UTC (rev 238083)
@@ -50,6 +50,7 @@
 #include "CDMInstance.h"
 #include "GStreamerEMEUtilities.h"
 #include "SharedBuffer.h"
+#include "WebKitCommonEncryptionDecryptorGStreamer.h"
 #endif
 
 #if USE(GSTREAMER_GL)
@@ -1335,24 +1336,51 @@
     initializationDataEncountered(event);
 }
 
-void MediaPlayerPrivateGStreamerBase::reportWaitingForKey()
-{
-    GST_TRACE("waiting for key");
-    m_player->waitingForKeyChanged();
-}
-
 void MediaPlayerPrivateGStreamerBase::setWaitingForKey(bool waitingForKey)
 {
-    if (waitingForKey == m_waitingForKey)
+    // We bail out if values did not change or if we are requested to not wait anymore but there are still waiting decryptors.
+    GST_TRACE("waitingForKey %s, m_waitingForKey %s", boolForPrinting(waitingForKey), boolForPrinting(m_waitingForKey));
+    if (waitingForKey == m_waitingForKey || (!waitingForKey && this->waitingForKey()))
         return;
 
     m_waitingForKey = waitingForKey;
-    reportWaitingForKey();
+    GST_DEBUG("waiting for key changed %s", boolForPrinting(m_waitingForKey));
+    m_player->waitingForKeyChanged();
 }
 
 bool MediaPlayerPrivateGStreamerBase::waitingForKey() const
 {
-    return m_waitingForKey;
+    if (!m_pipeline)
+        return false;
+
+    GstState state;
+    gst_element_get_state(m_pipeline.get(), &state, nullptr, 0);
+
+    bool result = false;
+    GRefPtr<GstQuery> query = adoptGRef(gst_query_new_custom(GST_QUERY_CUSTOM, gst_structure_new_empty("any-decryptor-waiting-for-key")));
+    if (state >= GST_STATE_PAUSED) {
+        result = gst_element_query(m_pipeline.get(), query.get());
+        GST_TRACE("query result %s, on %s", boolForPrinting(result), gst_element_state_get_name(state));
+    } else if (state >= GST_STATE_READY) {
+        // Running a query in the pipeline is easier but it only works when the pipeline is set up and running, otherwise we need to inspect it and ask the decryptors directly.
+        GUniquePtr<GstIterator> iterator(gst_bin_iterate_recurse(GST_BIN(m_pipeline.get())));
+        GstIteratorResult iteratorResult;
+        do {
+            iteratorResult = gst_iterator_fold(iterator.get(), [](const GValue *item, GValue *, gpointer data) -> gboolean {
+                GstElement* element = GST_ELEMENT(g_value_get_object(item));
+                GstQuery* query = GST_QUERY(data);
+                return !WEBKIT_IS_MEDIA_CENC_DECRYPT(element) || !gst_element_query(element, query);
+            }, nullptr, query.get());
+            if (iteratorResult == GST_ITERATOR_RESYNC)
+                gst_iterator_resync(iterator.get());
+        } while (iteratorResult == GST_ITERATOR_RESYNC);
+        if (iteratorResult == GST_ITERATOR_ERROR)
+            GST_WARNING("iterator returned an error");
+        result = iteratorResult == GST_ITERATOR_OK;
+        GST_TRACE("iterator result %d, waiting %s", iteratorResult, boolForPrinting(result));
+    }
+
+    return result;
 }
 #endif
 

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h (238082 => 238083)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h	2018-11-12 09:05:49 UTC (rev 238082)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h	2018-11-12 12:40:12 UTC (rev 238083)
@@ -154,8 +154,7 @@
     void dispatchCDMInstance();
     void initializationDataEncountered(GstEvent*);
     void setWaitingForKey(bool);
-    bool waitingForKey() const;
-    void reportWaitingForKey();
+    bool waitingForKey() const override;
 #endif
 
     static bool supportsKeySystem(const String& keySystem, const String& mimeType);

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp (238082 => 238083)


--- trunk/Source/WebCore/platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp	2018-11-12 09:05:49 UTC (rev 238082)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp	2018-11-12 12:40:12 UTC (rev 238083)
@@ -283,7 +283,7 @@
         GST_TRACE_OBJECT(self, "subsample index %u - %hu bytes clear (todo=%zu)", sampleIndex, nBytesClear, mappedBuffer.size() - position);
         position += nBytesClear;
         if (nBytesEncrypted) {
-            GST_TRACE_OBJECT(self, "subsample index %u - %hu bytes encrypted (todo=%zu)", sampleIndex, nBytesEncrypted, mappedBuffer.size() - position);
+            GST_TRACE_OBJECT(self, "subsample index %u - %u bytes encrypted (todo=%zu)", sampleIndex, nBytesEncrypted, mappedBuffer.size() - position);
             cipherError = gcry_cipher_decrypt(priv->handle, mappedBuffer.data() + position, nBytesEncrypted, 0, 0);
             if (cipherError) {
                 GST_ERROR_OBJECT(self, "sub sample index %u decryption failed: %s", sampleIndex, gpg_strerror(cipherError));

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp (238082 => 238083)


--- trunk/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp	2018-11-12 09:05:49 UTC (rev 238082)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp	2018-11-12 12:40:12 UTC (rev 238083)
@@ -27,6 +27,7 @@
 
 #include "GStreamerCommon.h"
 #include <wtf/Condition.h>
+#include <wtf/PrintStream.h>
 #include <wtf/RunLoop.h>
 
 #define WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_MEDIA_CENC_DECRYPT, WebKitMediaCommonEncryptionDecryptPrivate))
@@ -44,6 +45,7 @@
 static GstCaps* webkitMediaCommonEncryptionDecryptTransformCaps(GstBaseTransform*, GstPadDirection, GstCaps*, GstCaps*);
 static GstFlowReturn webkitMediaCommonEncryptionDecryptTransformInPlace(GstBaseTransform*, GstBuffer*);
 static gboolean webkitMediaCommonEncryptionDecryptSinkEventHandler(GstBaseTransform*, GstEvent*);
+static gboolean webkitMediaCommonEncryptionDecryptorQueryHandler(GstBaseTransform*, GstPadDirection, GstQuery*);
 
 
 GST_DEBUG_CATEGORY_STATIC(webkit_media_common_encryption_decrypt_debug_category);
@@ -68,6 +70,7 @@
     baseTransformClass->transform_caps = GST_DEBUG_FUNCPTR(webkitMediaCommonEncryptionDecryptTransformCaps);
     baseTransformClass->transform_ip_on_passthrough = FALSE;
     baseTransformClass->sink_event = GST_DEBUG_FUNCPTR(webkitMediaCommonEncryptionDecryptSinkEventHandler);
+    baseTransformClass->query = GST_DEBUG_FUNCPTR(webkitMediaCommonEncryptionDecryptorQueryHandler);
 
     g_type_class_add_private(klass, sizeof(WebKitMediaCommonEncryptionDecryptPrivate));
 }
@@ -215,6 +218,8 @@
             return GST_FLOW_NOT_SUPPORTED;
         }
         GST_DEBUG_OBJECT(self, "key received, continuing");
+        priv->waitingForKey = false;
+        gst_element_post_message(GST_ELEMENT(self), gst_message_new_element(GST_OBJECT(self), gst_structure_new_empty("drm-key-received")));
     }
 
     GstProtectionMeta* protectionMeta = reinterpret_cast<GstProtectionMeta*>(gst_buffer_get_protection_meta(buffer));
@@ -306,12 +311,7 @@
         if (klass->handleKeyResponse(self, event)) {
             GST_DEBUG_OBJECT(self, "key received");
             priv->keyReceived = true;
-            priv->waitingForKey = false;
-            gst_element_post_message(GST_ELEMENT(self), gst_message_new_element(GST_OBJECT(self), gst_structure_new_empty("drm-key-received")));
             priv->condition.notifyOne();
-        } else if (priv->waitingForKey) {
-            GST_DEBUG_OBJECT(self, "still waiting for key, reposting");
-            gst_element_post_message(GST_ELEMENT(self), gst_message_new_element(GST_OBJECT(self), gst_structure_new_empty("drm-waiting-for-key")));
         }
 
         gst_event_unref(event);
@@ -326,6 +326,16 @@
     return result;
 }
 
+static gboolean webkitMediaCommonEncryptionDecryptorQueryHandler(GstBaseTransform* trans, GstPadDirection direction, GstQuery* query)
+{
+    if (gst_structure_has_name(gst_query_get_structure(query), "any-decryptor-waiting-for-key")) {
+        WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(trans);
+        GST_TRACE_OBJECT(trans, "any-decryptor-waiting-for-key query, waitingforkey %s", boolForPrinting(priv->waitingForKey));
+        return priv->waitingForKey;
+    }
+    return GST_BASE_TRANSFORM_CLASS(parent_class)->query(trans, direction, query);
+}
+
 static GstStateChangeReturn webKitMediaCommonEncryptionDecryptorChangeState(GstElement* element, GstStateChange transition)
 {
     WebKitMediaCommonEncryptionDecrypt* self = WEBKIT_MEDIA_CENC_DECRYPT(element);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to