Diff
Modified: releases/WebKitGTK/webkit-2.32/Source/WebCore/ChangeLog (276707 => 276708)
--- releases/WebKitGTK/webkit-2.32/Source/WebCore/ChangeLog 2021-04-28 13:30:36 UTC (rev 276707)
+++ releases/WebKitGTK/webkit-2.32/Source/WebCore/ChangeLog 2021-04-28 14:31:25 UTC (rev 276708)
@@ -1,3 +1,80 @@
+2021-04-07 Enrique Ocaña González <[email protected]>
+
+ [EME][GStreamer] Abort decryptor operations immediately and without errors on flush
+ https://bugs.webkit.org/show_bug.cgi?id=223742
+
+ Reviewed by Xabier Rodriguez-Calvar.
+
+ A decryptor transformInPlace() operation can cause potentially long waits in
+ two situations:
+
+ - transformInPlace() is waiting to get the cdmProxy.
+ - The CDMProxy::decrypt() method is internally waiting for a specific key to
+ become available.
+
+ If a seek operation is performed during those long waits, the main thread will
+ be blocked until the seek finishes the conditions those long waits are waiting
+ for will never be fulfilled (because the operations that complete them happen
+ in the main thread, which is blocked), the internal wait timeouts will trigger
+ and the decoder will trigger an unrecoverable error.
+
+ The solution for this is to break the waits by issuing the right notifications,
+ and to detect the flushes performed by the seek, distinguising this special
+ "abort" case from a regular error, so that the situation is no longer
+ unrecoverable.
+
+ This solution involves changes in several layers. A public
+ CDMProxy::abortWaitingForKey() method is exposed to allow the decryptor to
+ awake the inner waitFor() that checks for the key. The cdmProxy wait is also
+ awaken in case there's no cdmProxy available yet.
+
+ In order to distinguish if the awakenings are caused by real errors (no
+ cdmProxy, no key available) or by a flush operation (caused by the seek), the
+ decryptor first needs to keep track of the "flushing" state and allow other
+ objects to know about it. CDMProxy is one of those objects, but due to layer
+ limitations it can't directly ask about it to the decryptor (it can't "see"
+ it).
+
+ A new CDMProxyDecryptionClient interface is created, and the decryptor will
+ hold an implementation of it (as CDMProxyDecryptorClientImplementation).
+ CDMProxy can then know the client isAborting(), and the client will know the
+ decryptor and will ask about it.
+
+ As the pipeline, and thus the decryptor, can be destroyed at any moment,
+ the client holds a WeakPtr to the decryptor and will only ask if isAborting()
+ if the pointer is still alive.
+
+ * platform/encryptedmedia/CDMProxy.cpp:
+ (WebCore::CDMProxy::abortWaitingForKey const): Notify waiting threads.
+ (WebCore::CDMProxy::tryWaitForKeyHandle const): Take a client and ask it if it's aborting.
+ (WebCore::CDMProxy::getOrWaitForKeyHandle const): Pass the client along.
+ (WebCore::CDMProxy::getOrWaitForKeyValue const): Ditto.
+ * platform/encryptedmedia/CDMProxy.h: Declaration and usage of the CDMProxyDecryptionClient interface.
+ * platform/graphics/gstreamer/eme/CDMProxyClearKey.cpp:
+ (WebCore::CDMProxyClearKey::cencSetDecryptionKey): Pass the client along from the context.
+ * platform/graphics/gstreamer/eme/CDMProxyClearKey.h: Store client in the cencDecryptContext.
+ * platform/graphics/gstreamer/eme/CDMProxyThunder.cpp:
+ (WebCore::CDMProxyThunder::getDecryptionSession const): Pass the client along from the context.
+ (WebCore::CDMProxyThunder::decrypt): Abort operations aren't an error, so just trigger a warning if there's no session.
+ * platform/graphics/gstreamer/eme/CDMProxyThunder.h: Store client in DecryptionContext.
+ * platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp:
+ (decrypt): Ask for client to the superclass and store it in the context.
+ * platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp:
+ (CDMProxyDecryptionClientImplementation::CDMProxyDecryptionClientImplementation): Implementation of the CDMProxyDecryptionClient interface.
+ (CDMProxyDecryptionClientImplementation::isAborting): Ask if the decryptor is flushing.
+ (constructed): Initialize the client.
+ (transformInPlace): Check the flush status after waiting for the CDMProxy and for the decryption performed by the subclasses. Release the lock when not needed.
+ (isCDMProxyAvailable): Renamed mutex to be more generic.
+ (attachCDMProxy): Ditto. Also renamed condition for the same reason.
+ (sinkEventHandler): Manage isFlushing status and awake waits for cdmProxy or for session depending on the lifecycle stage.
+ (webKitMediaCommonEncryptionDecryptIsFlushing): Expose isFlushing status.
+ (webKitMediaCommonEncryptionDecryptGetCDMProxyDecryptionClient): Return Weak reference to the client.
+ (changeState): Renamed condition.
+ (setContext): Renamed mutex.
+ * platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.h: New getters for isFlushing and the client.
+ * platform/graphics/gstreamer/eme/WebKitThunderDecryptorGStreamer.cpp:
+ (decrypt): Ask for client to the superclass and store it in the context.
+
2021-04-06 Alicia Boya García <[email protected]>
[GStreamer] At EOS, change position to match duration, not the other way around.
Modified: releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/encryptedmedia/CDMProxy.cpp (276707 => 276708)
--- releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/encryptedmedia/CDMProxy.cpp 2021-04-28 13:30:36 UTC (rev 276707)
+++ releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/encryptedmedia/CDMProxy.cpp 2021-04-28 14:31:25 UTC (rev 276708)
@@ -271,8 +271,14 @@
m_instance->stoppedWaitingForKey();
}
-Optional<Ref<KeyHandle>> CDMProxy::tryWaitForKeyHandle(const KeyIDType& keyID) const
+void CDMProxy::abortWaitingForKey() const
{
+ LOG(EME, "EME - CDMProxy - abort waiting for key ID");
+ m_keysCondition.notifyAll();
+}
+
+Optional<Ref<KeyHandle>> CDMProxy::tryWaitForKeyHandle(const KeyIDType& keyID, WeakPtr<CDMProxyDecryptionClient>&& client) const
+{
startedWaitingForKey();
// Unconditionally saying we have stopped waiting for a key means that decryptors only get
// one shot at fetching a key. If MaxKeyWaitTimeSeconds expires, that's it, no more clear bytes
@@ -281,21 +287,25 @@
stoppedWaitingForKey();
});
LOG(EME, "EME - CDMProxy - trying to wait for key ID %s", vectorToHexString(keyID).ascii().data());
- bool wasKeyReceived = false;
+ bool wasKeyAvailable = false;
{
auto locker = holdLock(m_keysMutex);
- wasKeyReceived = m_keysCondition.waitFor(m_keysMutex, CDMProxy::MaxKeyWaitTimeSeconds, [&, this, keyID]() {
- return keyAvailableUnlocked(keyID);
+
+ m_keysCondition.waitFor(m_keysMutex, CDMProxy::MaxKeyWaitTimeSeconds, [this, keyID, client = WTFMove(client), &wasKeyAvailable]() {
+ if (!client || client->isAborting())
+ return true;
+ wasKeyAvailable = keyAvailableUnlocked(keyID);
+ return wasKeyAvailable;
});
}
- if (wasKeyReceived) {
+ if (wasKeyAvailable) {
+ RefPtr<KeyHandle> handle = keyHandle(keyID);
LOG(EME, "EME - CDMProxy - successfully waited for key ID %s", vectorToHexString(keyID).ascii().data());
- RefPtr<KeyHandle> handle = keyHandle(keyID);
return makeOptional(handle.releaseNonNull());
}
-
- LOG(EME, "EME - CDMProxy - key ID %s not available", vectorToHexString(keyID).ascii().data());
+
+ LOG(EME, "EME - CDMProxy - key ID %s not available or operation aborted", vectorToHexString(keyID).ascii().data());
return WTF::nullopt;
}
@@ -310,11 +320,11 @@
return keyAvailableUnlocked(keyID);
}
-Optional<Ref<KeyHandle>> CDMProxy::getOrWaitForKeyHandle(const KeyIDType& keyID) const
+Optional<Ref<KeyHandle>> CDMProxy::getOrWaitForKeyHandle(const KeyIDType& keyID, WeakPtr<CDMProxyDecryptionClient>&& client) const
{
if (!keyAvailable(keyID)) {
LOG(EME, "EME - CDMProxy key cache does not contain key ID %s", vectorToHexString(keyID).ascii().data());
- return tryWaitForKeyHandle(keyID);
+ return tryWaitForKeyHandle(keyID, WTFMove(client));
}
RefPtr<KeyHandle> handle = keyHandle(keyID);
@@ -321,9 +331,9 @@
return makeOptional(handle.releaseNonNull());
}
-Optional<KeyHandleValueVariant> CDMProxy::getOrWaitForKeyValue(const KeyIDType& keyID) const
+Optional<KeyHandleValueVariant> CDMProxy::getOrWaitForKeyValue(const KeyIDType& keyID, WeakPtr<CDMProxyDecryptionClient>&& client) const
{
- if (auto keyHandle = getOrWaitForKeyHandle(keyID))
+ if (auto keyHandle = getOrWaitForKeyHandle(keyID, WTFMove(client)))
return makeOptional((*keyHandle)->value());
return WTF::nullopt;
}
Modified: releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/encryptedmedia/CDMProxy.h (276707 => 276708)
--- releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/encryptedmedia/CDMProxy.h 2021-04-28 13:30:36 UTC (rev 276707)
+++ releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/encryptedmedia/CDMProxy.h 2021-04-28 14:31:25 UTC (rev 276708)
@@ -146,6 +146,7 @@
};
class CDMInstanceProxy;
+class CDMProxyDecryptionClient;
// Handle to a "real" CDM, not the _javascript_ facade. This can be used
// from background threads (i.e. decryptors).
@@ -157,6 +158,7 @@
void updateKeyStore(const KeyStore& newKeyStore);
void setInstance(CDMInstanceProxy*);
+ void abortWaitingForKey() const;
virtual void releaseDecryptionResources()
{
@@ -168,9 +170,9 @@
RefPtr<KeyHandle> keyHandle(const KeyIDType&) const;
bool keyAvailable(const KeyIDType&) const;
bool keyAvailableUnlocked(const KeyIDType&) const;
- Optional<Ref<KeyHandle>> tryWaitForKeyHandle(const KeyIDType&) const;
- Optional<Ref<KeyHandle>> getOrWaitForKeyHandle(const KeyIDType&) const;
- Optional<KeyHandleValueVariant> getOrWaitForKeyValue(const KeyIDType&) const;
+ Optional<Ref<KeyHandle>> tryWaitForKeyHandle(const KeyIDType&, WeakPtr<CDMProxyDecryptionClient>&&) const;
+ Optional<Ref<KeyHandle>> getOrWaitForKeyHandle(const KeyIDType&, WeakPtr<CDMProxyDecryptionClient>&&) const;
+ Optional<KeyHandleValueVariant> getOrWaitForKeyValue(const KeyIDType&, WeakPtr<CDMProxyDecryptionClient>&&) const;
void startedWaitingForKey() const;
void stoppedWaitingForKey() const;
const CDMInstanceProxy* instance() const { return m_instance; }
@@ -279,6 +281,12 @@
KeyStore m_keyStore;
};
+class CDMProxyDecryptionClient : public CanMakeWeakPtr<CDMProxyDecryptionClient, WeakPtrFactoryInitialization::Eager> {
+public:
+ virtual bool isAborting() = 0;
+ virtual ~CDMProxyDecryptionClient() = default;
+};
+
} // namespace WebCore
#endif // ENABLE(ENCRYPTED_MEDIA)
Modified: releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.cpp (276707 => 276708)
--- releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.cpp 2021-04-28 13:30:36 UTC (rev 276707)
+++ releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.cpp 2021-04-28 14:31:25 UTC (rev 276708)
@@ -113,7 +113,7 @@
return true;
}
-bool CDMProxyClearKey::cencSetDecryptionKey(const cencDecryptContext& in)
+bool CDMProxyClearKey::cencSetDecryptionKey(cencDecryptContext& in)
{
// FIXME: Unnecessary copy, can we avoid this while still exposing
// a non-GStreamer-specific DecryptInput API? These buffers are
@@ -121,7 +121,7 @@
Vector<uint8_t> keyIDVec;
keyIDVec.append(in.keyID, in.keyIDSizeInBytes);
- auto keyData = getOrWaitForKeyValue(keyIDVec);
+ auto keyData = getOrWaitForKeyValue(keyIDVec, WTFMove(in.cdmProxyDecryptionClient));
if (!keyData)
return false;
Modified: releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.h (276707 => 276708)
--- releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.h 2021-04-28 13:30:36 UTC (rev 276707)
+++ releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.h 2021-04-28 14:31:25 UTC (rev 276708)
@@ -91,6 +91,7 @@
const uint8_t* subsamplesBuffer;
size_t subsamplesBufferSizeInBytes;
size_t numSubsamples;
+ WeakPtr<CDMProxyDecryptionClient> cdmProxyDecryptionClient;
bool isSubsampled() const { return numSubsamples; }
};
@@ -107,7 +108,7 @@
// we will surely have to support more protection schemes. Can we
// reuse some Crypto APIs in WebCore?
bool cencSetCounterVector(const cencDecryptContext&);
- bool cencSetDecryptionKey(const cencDecryptContext&);
+ bool cencSetDecryptionKey(cencDecryptContext&);
bool cencDecryptFullSample(cencDecryptContext&);
bool cencDecryptSubsampled(cencDecryptContext&);
Modified: releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.cpp (276707 => 276708)
--- releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.cpp 2021-04-28 13:30:36 UTC (rev 276707)
+++ releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.cpp 2021-04-28 14:31:25 UTC (rev 276708)
@@ -44,7 +44,7 @@
// NOTE: YouTube 2019 EME conformance tests expect this to be >=5s.
const WTF::Seconds s_licenseKeyResponseTimeout = WTF::Seconds(6);
-BoxPtr<OpenCDMSession> CDMProxyThunder::getDecryptionSession(const DecryptionContext& in) const
+BoxPtr<OpenCDMSession> CDMProxyThunder::getDecryptionSession(DecryptionContext& in) const
{
GstMappedBuffer mappedKeyID(in.keyIDBuffer, GST_MAP_READ);
if (!mappedKeyID) {
@@ -54,7 +54,7 @@
auto keyID = mappedKeyID.createVector();
- auto keyHandle = getOrWaitForKeyHandle(keyID);
+ auto keyHandle = getOrWaitForKeyHandle(keyID, WTFMove(in.cdmProxyDecryptionClient));
if (!keyHandle.hasValue() || !keyHandle.value()->isStatusCurrentlyValid())
return nullptr;
@@ -84,7 +84,7 @@
{
BoxPtr<OpenCDMSession> session = getDecryptionSession(input);
if (!session) {
- GST_ERROR("there is no valid session to decrypt for the provided key ID");
+ GST_WARNING("there is no valid session to decrypt for the provided key ID (or the operation was aborted)");
return false;
}
Modified: releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.h (276707 => 276708)
--- releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.h 2021-04-28 13:30:36 UTC (rev 276707)
+++ releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.h 2021-04-28 14:31:25 UTC (rev 276708)
@@ -53,6 +53,7 @@
GstBuffer* dataBuffer;
GstBuffer* subsamplesBuffer;
size_t numSubsamples;
+ WeakPtr<CDMProxyDecryptionClient> cdmProxyDecryptionClient;
};
bool decrypt(DecryptionContext&);
@@ -59,7 +60,7 @@
const String& keySystem() { return m_keySystem; }
private:
- BoxPtr<OpenCDMSession> getDecryptionSession(const DecryptionContext&) const;
+ BoxPtr<OpenCDMSession> getDecryptionSession(DecryptionContext&) const;
String m_keySystem;
};
Modified: releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp (276707 => 276708)
--- releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp 2021-04-28 13:30:36 UTC (rev 276707)
+++ releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp 2021-04-28 14:31:25 UTC (rev 276708)
@@ -125,7 +125,7 @@
return false;
}
- CDMProxyClearKey::cencDecryptContext context;
+ CDMProxyClearKey::cencDecryptContext context = { };
context.keyID = mappedKeyIdBuffer.data();
context.keyIDSizeInBytes = mappedKeyIdBuffer.size();
context.iv = mappedIVBuffer.data();
@@ -145,6 +145,7 @@
context.subsamplesBuffer = mappedSubsamplesBuffer.data();
context.subsamplesBufferSizeInBytes = mappedSubsamplesBuffer.size();
}
+ context.cdmProxyDecryptionClient = webKitMediaCommonEncryptionDecryptGetCDMProxyDecryptionClient(self);
return priv->cdmProxy->cencDecrypt(context);
}
Modified: releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp (276707 => 276708)
--- releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp 2021-04-28 13:30:36 UTC (rev 276707)
+++ releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp 2021-04-28 14:31:25 UTC (rev 276708)
@@ -36,12 +36,31 @@
using WebCore::CDMProxy;
+// Instances of this class are tied to the decryptor lifecycle. They can't be alive after the decryptor has been destroyed.
+class CDMProxyDecryptionClientImplementation : public WebCore::CDMProxyDecryptionClient {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ CDMProxyDecryptionClientImplementation(WebKitMediaCommonEncryptionDecrypt* decryptor)
+ : m_decryptor(decryptor) { }
+ virtual bool isAborting()
+ {
+ return webKitMediaCommonEncryptionDecryptIsFlushing(m_decryptor);
+ }
+ virtual ~CDMProxyDecryptionClientImplementation() = default;
+private:
+ WebKitMediaCommonEncryptionDecrypt* m_decryptor;
+};
+
#define WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_MEDIA_CENC_DECRYPT, WebKitMediaCommonEncryptionDecryptPrivate))
struct _WebKitMediaCommonEncryptionDecryptPrivate {
RefPtr<CDMProxy> cdmProxy;
- Lock cdmAttachmentMutex;
- Condition cdmAttachmentCondition;
+ // Protect the access to the structure members.
+ Lock mutex;
+ Condition condition;
+
+ bool isFlushing { false };
+ std::unique_ptr<CDMProxyDecryptionClientImplementation> cdmProxyDecryptionClientImplementation;
};
static constexpr Seconds MaxSecondsToWaitForCDMProxy = 5_s;
@@ -85,6 +104,10 @@
gst_base_transform_set_in_place(base, TRUE);
gst_base_transform_set_passthrough(base, FALSE);
gst_base_transform_set_gap_aware(base, FALSE);
+
+ WebKitMediaCommonEncryptionDecrypt* self = WEBKIT_MEDIA_CENC_DECRYPT(base);
+ WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(self);
+ priv->cdmProxyDecryptionClientImplementation = WTF::makeUnique<CDMProxyDecryptionClientImplementation>(self);
}
static GstCaps* transformCaps(GstBaseTransform* base, GstPadDirection direction, GstCaps* caps, GstCaps* filter)
@@ -168,14 +191,24 @@
return GST_FLOW_OK;
}
- LockHolder locker(priv->cdmAttachmentMutex);
+ LockHolder locker(priv->mutex);
+ if (priv->isFlushing) {
+ GST_DEBUG_OBJECT(self, "Decryption aborted because of flush");
+ return GST_FLOW_FLUSHING;
+ }
+
// The CDM instance needs to be negotiated before we can begin decryption.
if (!priv->cdmProxy) {
GST_DEBUG_OBJECT(self, "CDM not available, going to wait for it");
- priv->cdmAttachmentCondition.waitFor(priv->cdmAttachmentMutex, MaxSecondsToWaitForCDMProxy, [priv] {
- return priv->cdmProxy;
+ priv->condition.waitFor(priv->mutex, MaxSecondsToWaitForCDMProxy, [priv] {
+ return priv->isFlushing || priv->cdmProxy;
});
+ // Note that waitFor() releases the mutex lock internally while it waits, so isFlushing may have been changed.
+ if (priv->isFlushing) {
+ GST_DEBUG_OBJECT(self, "Decryption aborted because of flush");
+ return GST_FLOW_FLUSHING;
+ }
if (!priv->cdmProxy) {
GST_ERROR_OBJECT(self, "CDMProxy was not retrieved in time");
return GST_FLOW_NOT_SUPPORTED;
@@ -182,6 +215,7 @@
}
GST_DEBUG_OBJECT(self, "CDM now available with address %p", priv->cdmProxy.get());
}
+
auto removeProtectionMetaOnReturn = makeScopeExit([buffer, protectionMeta] {
gst_buffer_remove_meta(buffer, reinterpret_cast<GstMeta*>(protectionMeta));
});
@@ -245,7 +279,21 @@
WebKitMediaCommonEncryptionDecryptClass* klass = WEBKIT_MEDIA_CENC_DECRYPT_GET_CLASS(self);
GST_TRACE_OBJECT(self, "decrypting");
- if (!klass->decrypt(self, ivBuffer, keyIDBuffer, buffer, subSampleCount, subSamplesBuffer)) {
+
+ // Temporarily release the lock while we don't need to access priv. The lower level API is used
+ // in order to avoid creating several scopes with different LockHolder instances in each one.
+ priv->mutex.unlock();
+
+ bool didDecryptionSucceed = klass->decrypt(self, ivBuffer, keyIDBuffer, buffer, subSampleCount, subSamplesBuffer);
+
+ // Accessing priv members again.
+ priv->mutex.lock();
+
+ if (!didDecryptionSucceed) {
+ if (priv->isFlushing) {
+ GST_DEBUG_OBJECT(self, "Decryption aborted because of flush");
+ return GST_FLOW_FLUSHING;
+ }
GST_ERROR_OBJECT(self, "Decryption failed");
return GST_FLOW_NOT_SUPPORTED;
}
@@ -256,7 +304,7 @@
static bool isCDMProxyAvailable(WebKitMediaCommonEncryptionDecrypt* self)
{
WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(self);
- auto locker = holdLock(priv->cdmAttachmentMutex);
+ auto locker = holdLock(priv->mutex);
return priv->cdmProxy;
}
@@ -289,11 +337,11 @@
WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(self);
WebKitMediaCommonEncryptionDecryptClass* klass = WEBKIT_MEDIA_CENC_DECRYPT_GET_CLASS(self);
- auto locker = holdLock(priv->cdmAttachmentMutex);
+ auto locker = holdLock(priv->mutex);
GST_ERROR_OBJECT(self, "Attaching CDMProxy %p", proxy);
priv->cdmProxy = proxy;
klass->cdmProxyAttached(self, priv->cdmProxy);
- priv->cdmAttachmentCondition.notifyOne();
+ priv->condition.notifyOne();
}
static gboolean installCDMProxyIfNotAvailable(WebKitMediaCommonEncryptionDecrypt* self)
@@ -318,7 +366,7 @@
static gboolean sinkEventHandler(GstBaseTransform* trans, GstEvent* event)
{
WebKitMediaCommonEncryptionDecrypt* self = WEBKIT_MEDIA_CENC_DECRYPT(trans);
- gboolean result = FALSE;
+ WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(self);
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=191355
// We should be handling protection events in this class in
@@ -330,18 +378,50 @@
case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: {
ASSERT(gst_event_has_name(event, "attempt-to-decrypt"));
GST_DEBUG_OBJECT(self, "Handling attempt-to-decrypt");
- result = installCDMProxyIfNotAvailable(self);
+ gboolean result = installCDMProxyIfNotAvailable(self);
gst_event_unref(event);
+ return result;
+ }
+ case GST_EVENT_FLUSH_START:
+ GST_DEBUG_OBJECT(self, "Flush-start");
+ {
+ LockHolder locker(priv->mutex);
+ bool isCdmProxyAttached = priv->cdmProxy;
+ priv->isFlushing = true;
+ if (isCdmProxyAttached) {
+ locker.unlockEarly();
+ priv->cdmProxy->abortWaitingForKey();
+ } else
+ priv->condition.notifyOne();
+ }
break;
- }
+ case GST_EVENT_FLUSH_STOP:
+ GST_DEBUG_OBJECT(self, "Flush-stop");
+ {
+ LockHolder locker(priv->mutex);
+ priv->isFlushing = false;
+ }
+ break;
default:
- result = GST_BASE_TRANSFORM_CLASS(parent_class)->sink_event(trans, event);
break;
}
- return result;
+ return GST_BASE_TRANSFORM_CLASS(parent_class)->sink_event(trans, event);
}
+bool webKitMediaCommonEncryptionDecryptIsFlushing(WebKitMediaCommonEncryptionDecrypt* self)
+{
+ WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(self);
+ LockHolder locker(priv->mutex);
+ return priv->isFlushing;
+}
+
+WeakPtr<WebCore::CDMProxyDecryptionClient> webKitMediaCommonEncryptionDecryptGetCDMProxyDecryptionClient(WebKitMediaCommonEncryptionDecrypt* self)
+{
+ WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(self);
+ return makeWeakPtr(*priv->cdmProxyDecryptionClientImplementation);
+}
+
static GstStateChangeReturn changeState(GstElement* element, GstStateChange transition)
{
WebKitMediaCommonEncryptionDecrypt* self = WEBKIT_MEDIA_CENC_DECRYPT(element);
@@ -350,7 +430,7 @@
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
GST_DEBUG_OBJECT(self, "PAUSED->READY");
- priv->cdmAttachmentCondition.notifyOne();
+ priv->condition.notifyOne();
break;
default:
break;
@@ -371,7 +451,7 @@
if (gst_context_has_context_type(context, "drm-cdm-proxy")) {
const GValue* value = gst_structure_get_value(gst_context_get_structure(context), "cdm-proxy");
- LockHolder locker(priv->cdmAttachmentMutex);
+ LockHolder locker(priv->mutex);
priv->cdmProxy = value ? reinterpret_cast<CDMProxy*>(g_value_get_pointer(value)) : nullptr;
GST_DEBUG_OBJECT(self, "received new CDMInstance %p", priv->cdmProxy.get());
klass->cdmProxyAttached(self, priv->cdmProxy);
Modified: releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.h (276707 => 276708)
--- releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.h 2021-04-28 13:30:36 UTC (rev 276707)
+++ releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.h 2021-04-28 14:31:25 UTC (rev 276708)
@@ -28,6 +28,7 @@
#include <gst/base/gstbasetransform.h>
#include <gst/gst.h>
#include <wtf/RefPtr.h>
+#include <wtf/WeakPtr.h>
G_BEGIN_DECLS
@@ -45,6 +46,9 @@
GType webkit_media_common_encryption_decrypt_get_type(void);
+bool webKitMediaCommonEncryptionDecryptIsFlushing(WebKitMediaCommonEncryptionDecrypt*);
+WeakPtr<WebCore::CDMProxyDecryptionClient> webKitMediaCommonEncryptionDecryptGetCDMProxyDecryptionClient(WebKitMediaCommonEncryptionDecrypt*);
+
struct _WebKitMediaCommonEncryptionDecrypt {
GstBaseTransform parent;
Modified: releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitThunderDecryptorGStreamer.cpp (276707 => 276708)
--- releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitThunderDecryptorGStreamer.cpp 2021-04-28 13:30:36 UTC (rev 276707)
+++ releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitThunderDecryptorGStreamer.cpp 2021-04-28 14:31:25 UTC (rev 276708)
@@ -156,14 +156,16 @@
return false;
}
- CDMProxyThunder::DecryptionContext context;
+ CDMProxyThunder::DecryptionContext context = { };
context.keyIDBuffer = keyIDBuffer;
context.ivBuffer = ivBuffer;
context.dataBuffer = buffer;
context.numSubsamples = subsampleCount;
context.subsamplesBuffer = subsampleCount ? subsamplesBuffer : nullptr;
+ context.cdmProxyDecryptionClient = webKitMediaCommonEncryptionDecryptGetCDMProxyDecryptionClient(self);
+ bool result = priv->cdmProxy->decrypt(context);
- return priv->cdmProxy->decrypt(context);
+ return result;
}
#endif // ENABLE(ENCRYPTED_MEDIA) && ENABLE(THUNDER) && USE(GSTREAMER)