WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-223742-20210326192451.patch (text/plain), 28.61 KB, created by
Enrique Ocaña
on 2021-03-26 11:24:53 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Enrique Ocaña
Created:
2021-03-26 11:24:53 PDT
Size:
28.61 KB
patch
obsolete
>Subversion Revision: 274875 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 27e300a5dfbb8f09ad67799d3320fdbeae29bc4b..02d0b5525710f37c9fb6591b2f600104bbc26731 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,80 @@ >+2021-03-25 Enrique Ocaña González <eocanha@igalia.com> >+ >+ [EME][GStreamer] Abort decryptor operations immediately and without errors on flush >+ https://bugs.webkit.org/show_bug.cgi?id=223742 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ 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-03-23 Jean-Yves Avenard <jya@apple.com> > > Only send image across XPC to GPU process if it changes. >diff --git a/Source/WebCore/platform/encryptedmedia/CDMProxy.cpp b/Source/WebCore/platform/encryptedmedia/CDMProxy.cpp >index 5b1b5dfdbd514de27d66e545e704ceff904d2fc7..b771275972912fe10ba19aa29392ef9ad3259999 100644 >--- a/Source/WebCore/platform/encryptedmedia/CDMProxy.cpp >+++ b/Source/WebCore/platform/encryptedmedia/CDMProxy.cpp >@@ -271,7 +271,13 @@ void CDMProxy::stoppedWaitingForKey() const > 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 >@@ -281,21 +287,25 @@ Optional<Ref<KeyHandle>> CDMProxy::tryWaitForKeyHandle(const KeyIDType& keyID) c > 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) { >- LOG(EME, "EME - CDMProxy - successfully waited for key ID %s", vectorToHexString(keyID).ascii().data()); >+ if (wasKeyAvailable) { > RefPtr<KeyHandle> handle = keyHandle(keyID); >+ LOG(EME, "EME - CDMProxy - successfully waited for key ID %s", vectorToHexString(keyID).ascii().data()); > 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,20 +320,20 @@ bool CDMProxy::keyAvailable(const KeyIDType& keyID) const > 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); > 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; > } >diff --git a/Source/WebCore/platform/encryptedmedia/CDMProxy.h b/Source/WebCore/platform/encryptedmedia/CDMProxy.h >index 83edd9e92549faaef12505e153ecf72feb931fa8..9ebe323afa633c18385218bbad4838ee59c6ca99 100644 >--- a/Source/WebCore/platform/encryptedmedia/CDMProxy.h >+++ b/Source/WebCore/platform/encryptedmedia/CDMProxy.h >@@ -146,6 +146,7 @@ private: > }; > > class CDMInstanceProxy; >+class CDMProxyDecryptionClient; > > // Handle to a "real" CDM, not the JavaScript facade. This can be used > // from background threads (i.e. decryptors). >@@ -157,14 +158,15 @@ public: > > void updateKeyStore(const KeyStore& newKeyStore); > void setInstance(CDMInstanceProxy*); >+ void abortWaitingForKey() const; > > protected: > 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; } >@@ -253,6 +255,12 @@ private: > KeyStore m_keyStore; > }; > >+class CDMProxyDecryptionClient : public CanMakeWeakPtr<CDMProxyDecryptionClient, WeakPtrFactoryInitialization::Eager> { >+public: >+ virtual bool isAborting() = 0; >+ virtual ~CDMProxyDecryptionClient() = default; >+}; >+ > } // namespace WebCore > > #endif // ENABLE(ENCRYPTED_MEDIA) >diff --git a/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.cpp b/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.cpp >index caa972dc6b777d5dddfe4dc5c794c302a3146104..be154255f3d768315e35687690476f7f8ae3bbf2 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.cpp >+++ b/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.cpp >@@ -113,7 +113,7 @@ bool CDMProxyClearKey::cencSetCounterVector(const cencDecryptContext& input) > 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 @@ bool CDMProxyClearKey::cencSetDecryptionKey(const cencDecryptContext& in) > 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; > >diff --git a/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.h b/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.h >index ff96bfac129d6dd3ae7c5dd0774be1ab25417ce0..896abdbd65655920a081d850591abf3ffdf18f54 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.h >+++ b/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.h >@@ -91,6 +91,7 @@ public: > const uint8_t* subsamplesBuffer; > size_t subsamplesBufferSizeInBytes; > size_t numSubsamples; >+ WeakPtr<CDMProxyDecryptionClient> cdmProxyDecryptionClient; > > bool isSubsampled() const { return numSubsamples; } > }; >@@ -107,7 +108,7 @@ private: > // 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&); > >diff --git a/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.cpp b/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.cpp >index 11f6d7ae11367d7f946a6f58f755ff004d84eb3c..7d8352f17328946c4aa811ef909198dc46bb366a 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.cpp >+++ b/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.cpp >@@ -44,7 +44,7 @@ namespace WebCore { > // 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 @@ BoxPtr<OpenCDMSession> CDMProxyThunder::getDecryptionSession(const DecryptionCon > > 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 @@ bool CDMProxyThunder::decrypt(CDMProxyThunder::DecryptionContext& input) > { > 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; > } > >diff --git a/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.h b/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.h >index 0de635554d43166fab5d2bfb2a0e206fdbdebfc1..ad544364a483bebc3094d4acb7f4d62f8648cd0d 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.h >+++ b/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.h >@@ -53,13 +53,14 @@ public: > GstBuffer* dataBuffer; > GstBuffer* subsamplesBuffer; > size_t numSubsamples; >+ WeakPtr<CDMProxyDecryptionClient> cdmProxyDecryptionClient; > }; > > bool decrypt(DecryptionContext&); > const String& keySystem() { return m_keySystem; } > > private: >- BoxPtr<OpenCDMSession> getDecryptionSession(const DecryptionContext&) const; >+ BoxPtr<OpenCDMSession> getDecryptionSession(DecryptionContext&) const; > String m_keySystem; > }; > >diff --git a/Source/WebCore/platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp >index 1ab97bb3b935631781d94e5750c6c45d758bec52..dc9b5a3a4fac597ccaeade75f3edc1ce1d73718b 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp >+++ b/Source/WebCore/platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp >@@ -125,7 +125,7 @@ static bool decrypt(WebKitMediaCommonEncryptionDecrypt* self, GstBuffer* ivBuffe > return false; > } > >- CDMProxyClearKey::cencDecryptContext context; >+ CDMProxyClearKey::cencDecryptContext context = { }; > context.keyID = mappedKeyIdBuffer.data(); > context.keyIDSizeInBytes = mappedKeyIdBuffer.size(); > context.iv = mappedIVBuffer.data(); >@@ -145,6 +145,7 @@ static bool decrypt(WebKitMediaCommonEncryptionDecrypt* self, GstBuffer* ivBuffe > context.subsamplesBuffer = mappedSubsamplesBuffer.data(); > context.subsamplesBufferSizeInBytes = mappedSubsamplesBuffer.size(); > } >+ context.cdmProxyDecryptionClient = webKitMediaCommonEncryptionDecryptGetCDMProxyDecryptionClient(self); > > return priv->cdmProxy->cencDecrypt(context); > } >diff --git a/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp >index 5cd9213159a57c4aaf71f33905daa83c6aa189ed..f5ed5a82f55daa61eb9720997baefe384bf26237 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp >+++ b/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp >@@ -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 @@ static void constructed(GObject* object) > 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,20 +191,34 @@ static GstFlowReturn transformInPlace(GstBaseTransform* base, GstBuffer* buffer) > 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->cdmProxy || priv->isFlushing; > }); >+ // 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; > } > GST_DEBUG_OBJECT(self, "CDM now available with address %p", priv->cdmProxy.get()); > } >+ // 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(); >+ > auto removeProtectionMetaOnReturn = makeScopeExit([buffer, protectionMeta] { > gst_buffer_remove_meta(buffer, reinterpret_cast<GstMeta*>(protectionMeta)); > }); >@@ -245,7 +282,15 @@ static GstFlowReturn transformInPlace(GstBaseTransform* base, GstBuffer* buffer) > WebKitMediaCommonEncryptionDecryptClass* klass = WEBKIT_MEDIA_CENC_DECRYPT_GET_CLASS(self); > > GST_TRACE_OBJECT(self, "decrypting"); >- if (!klass->decrypt(self, ivBuffer, keyIDBuffer, buffer, subSampleCount, subSamplesBuffer)) { >+ 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 +301,7 @@ static GstFlowReturn transformInPlace(GstBaseTransform* base, GstBuffer* buffer) > 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 +334,11 @@ static void attachCDMProxy(WebKitMediaCommonEncryptionDecrypt* self, CDMProxy* p > 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 +363,7 @@ static gboolean installCDMProxyIfNotAvailable(WebKitMediaCommonEncryptionDecrypt > 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,16 +375,48 @@ static gboolean sinkEventHandler(GstBaseTransform* trans, GstEvent* event) > 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); >- break; >+ 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) >+ priv->condition.notifyOne(); >+ locker.unlockEarly(); >+ if (isCdmProxyAttached) >+ priv->cdmProxy->abortWaitingForKey(); >+ } >+ 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) >@@ -350,7 +427,7 @@ static GstStateChangeReturn changeState(GstElement* element, GstStateChange tran > 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 +448,7 @@ static void setContext(GstElement* element, GstContext* context) > > 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); >diff --git a/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.h >index a0465ff53d00007c23f7a9058ac9b347f6b8d5dd..9554609f744aad77515a0fee2632999d421f310d 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.h >+++ b/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.h >@@ -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 @@ typedef struct _WebKitMediaCommonEncryptionDecryptPrivate WebKitMediaCommonEncry > > GType webkit_media_common_encryption_decrypt_get_type(void); > >+bool webKitMediaCommonEncryptionDecryptIsFlushing(WebKitMediaCommonEncryptionDecrypt*); >+WeakPtr<WebCore::CDMProxyDecryptionClient> webKitMediaCommonEncryptionDecryptGetCDMProxyDecryptionClient(WebKitMediaCommonEncryptionDecrypt*); >+ > struct _WebKitMediaCommonEncryptionDecrypt { > GstBaseTransform parent; > >diff --git a/Source/WebCore/platform/graphics/gstreamer/eme/WebKitThunderDecryptorGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/eme/WebKitThunderDecryptorGStreamer.cpp >index a22670d9105d0f465f93a6a8f6ac65dce024d5db..583bd3bbc80d72a36c1554925bcc90b84078f92f 100644 >--- a/Source/WebCore/platform/graphics/gstreamer/eme/WebKitThunderDecryptorGStreamer.cpp >+++ b/Source/WebCore/platform/graphics/gstreamer/eme/WebKitThunderDecryptorGStreamer.cpp >@@ -156,14 +156,16 @@ static bool decrypt(WebKitMediaCommonEncryptionDecrypt* decryptor, GstBuffer* iv > 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)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 223742
:
424378
|
425287
|
425370