⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 276708 in webkit


Ignore:
Timestamp:
Apr 28, 2021, 7:31:25 AM (5 years ago)
Author:
Adrian Perez de Castro
Message:

Merge r275599 - [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.

Location:
releases/WebKitGTK/webkit-2.32/Source/WebCore
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • releases/WebKitGTK/webkit-2.32/Source/WebCore/ChangeLog

    r276703 r276708  
     12021-04-07  Enrique Ocaña González  <eocanha@igalia.com>
     2
     3        [EME][GStreamer] Abort decryptor operations immediately and without errors on flush
     4        https://bugs.webkit.org/show_bug.cgi?id=223742
     5
     6        Reviewed by Xabier Rodriguez-Calvar.
     7
     8        A decryptor transformInPlace() operation can cause potentially long waits in
     9        two situations:
     10
     11        - transformInPlace() is waiting to get the cdmProxy.
     12        - The CDMProxy::decrypt() method is internally waiting for a specific key to
     13          become available.
     14
     15        If a seek operation is performed during those long waits, the main thread will
     16        be blocked until the seek finishes the conditions those long waits are waiting
     17        for will never be fulfilled (because the operations that complete them happen
     18        in the main thread, which is blocked), the internal wait timeouts will trigger
     19        and the decoder will trigger an unrecoverable error.
     20
     21        The solution for this is to break the waits by issuing the right notifications,
     22        and to detect the flushes performed by the seek, distinguising this special
     23        "abort" case from a regular error, so that the situation is no longer
     24        unrecoverable.
     25
     26        This solution involves changes in several layers. A public
     27        CDMProxy::abortWaitingForKey() method is exposed to allow the decryptor to
     28        awake the inner waitFor() that checks for the key. The cdmProxy wait is also
     29        awaken in case there's no cdmProxy available yet.
     30
     31        In order to distinguish if the awakenings are caused by real errors (no
     32        cdmProxy, no key available) or by a flush operation (caused by the seek), the
     33        decryptor first needs to keep track of the "flushing" state and allow other
     34        objects to know about it. CDMProxy is one of those objects, but due to layer
     35        limitations it can't directly ask about it to the decryptor (it can't "see"
     36        it).
     37
     38        A new CDMProxyDecryptionClient interface is created, and the decryptor will
     39        hold an implementation of it (as CDMProxyDecryptorClientImplementation).
     40        CDMProxy can then know the client isAborting(), and the client will know the
     41        decryptor and will ask about it.
     42
     43        As the pipeline, and thus the decryptor, can be destroyed at any moment,
     44        the client holds a WeakPtr to the decryptor and will only ask if isAborting()
     45        if the pointer is still alive.
     46
     47        * platform/encryptedmedia/CDMProxy.cpp:
     48        (WebCore::CDMProxy::abortWaitingForKey const): Notify waiting threads.
     49        (WebCore::CDMProxy::tryWaitForKeyHandle const): Take a client and ask it if it's aborting.
     50        (WebCore::CDMProxy::getOrWaitForKeyHandle const): Pass the client along.
     51        (WebCore::CDMProxy::getOrWaitForKeyValue const): Ditto.
     52        * platform/encryptedmedia/CDMProxy.h: Declaration and usage of the CDMProxyDecryptionClient interface.
     53        * platform/graphics/gstreamer/eme/CDMProxyClearKey.cpp:
     54        (WebCore::CDMProxyClearKey::cencSetDecryptionKey): Pass the client along from the context.
     55        * platform/graphics/gstreamer/eme/CDMProxyClearKey.h: Store client in the cencDecryptContext.
     56        * platform/graphics/gstreamer/eme/CDMProxyThunder.cpp:
     57        (WebCore::CDMProxyThunder::getDecryptionSession const): Pass the client along from the context.
     58        (WebCore::CDMProxyThunder::decrypt): Abort operations aren't an error, so just trigger a warning if there's no session.
     59        * platform/graphics/gstreamer/eme/CDMProxyThunder.h: Store client in DecryptionContext.
     60        * platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp:
     61        (decrypt): Ask for client to the superclass and store it in the context.
     62        * platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp:
     63        (CDMProxyDecryptionClientImplementation::CDMProxyDecryptionClientImplementation): Implementation of the CDMProxyDecryptionClient interface.
     64        (CDMProxyDecryptionClientImplementation::isAborting): Ask if the decryptor is flushing.
     65        (constructed): Initialize the client.
     66        (transformInPlace): Check the flush status after waiting for the CDMProxy and for the decryption performed by the subclasses. Release the lock when not needed.
     67        (isCDMProxyAvailable): Renamed mutex to be more generic.
     68        (attachCDMProxy): Ditto. Also renamed condition for the same reason.
     69        (sinkEventHandler): Manage isFlushing status and awake waits for cdmProxy or for session depending on the lifecycle stage.
     70        (webKitMediaCommonEncryptionDecryptIsFlushing): Expose isFlushing status.
     71        (webKitMediaCommonEncryptionDecryptGetCDMProxyDecryptionClient): Return Weak reference to the client.
     72        (changeState): Renamed condition.
     73        (setContext): Renamed mutex.
     74        * platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.h: New getters for isFlushing and the client.
     75        * platform/graphics/gstreamer/eme/WebKitThunderDecryptorGStreamer.cpp:
     76        (decrypt): Ask for client to the superclass and store it in the context.
     77
    1782021-04-06  Alicia Boya García  <aboya@igalia.com>
    279
  • releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/encryptedmedia/CDMProxy.cpp

    r264219 r276708  
    272272}
    273273
    274 Optional<Ref<KeyHandle>> CDMProxy::tryWaitForKeyHandle(const KeyIDType& keyID) const
     274void CDMProxy::abortWaitingForKey() const
     275{
     276    LOG(EME, "EME - CDMProxy - abort waiting for key ID");
     277    m_keysCondition.notifyAll();
     278}
     279
     280Optional<Ref<KeyHandle>> CDMProxy::tryWaitForKeyHandle(const KeyIDType& keyID, WeakPtr<CDMProxyDecryptionClient>&& client) const
    275281{
    276282    startedWaitingForKey();
    … …  
    282288    });
    283289    LOG(EME, "EME - CDMProxy - trying to wait for key ID %s", vectorToHexString(keyID).ascii().data());
    284     bool wasKeyReceived = false;
     290    bool wasKeyAvailable = false;
    285291    {
    286292        auto locker = holdLock(m_keysMutex);
    287         wasKeyReceived = m_keysCondition.waitFor(m_keysMutex, CDMProxy::MaxKeyWaitTimeSeconds, [&, this, keyID]() {
    288             return keyAvailableUnlocked(keyID);
     293
     294        m_keysCondition.waitFor(m_keysMutex, CDMProxy::MaxKeyWaitTimeSeconds, [this, keyID, client = WTFMove(client), &wasKeyAvailable]() {
     295            if (!client || client->isAborting())
     296                return true;
     297            wasKeyAvailable = keyAvailableUnlocked(keyID);
     298            return wasKeyAvailable;
    289299        });
    290300    }
    291301
    292     if (wasKeyReceived) {
     302    if (wasKeyAvailable) {
     303        RefPtr<KeyHandle> handle = keyHandle(keyID);
    293304        LOG(EME, "EME - CDMProxy - successfully waited for key ID %s", vectorToHexString(keyID).ascii().data());
    294         RefPtr<KeyHandle> handle = keyHandle(keyID);
    295305        return makeOptional(handle.releaseNonNull());
    296306    }
    297    
    298     LOG(EME, "EME - CDMProxy - key ID %s not available", vectorToHexString(keyID).ascii().data());
     307
     308    LOG(EME, "EME - CDMProxy - key ID %s not available or operation aborted", vectorToHexString(keyID).ascii().data());
    299309    return WTF::nullopt;
    300310}
    … …  
    311321}
    312322
    313 Optional<Ref<KeyHandle>> CDMProxy::getOrWaitForKeyHandle(const KeyIDType& keyID) const
     323Optional<Ref<KeyHandle>> CDMProxy::getOrWaitForKeyHandle(const KeyIDType& keyID, WeakPtr<CDMProxyDecryptionClient>&& client) const
    314324{
    315325    if (!keyAvailable(keyID)) {
    316326        LOG(EME, "EME - CDMProxy key cache does not contain key ID %s", vectorToHexString(keyID).ascii().data());
    317         return tryWaitForKeyHandle(keyID);
     327        return tryWaitForKeyHandle(keyID, WTFMove(client));
    318328    }
    319329
    … …  
    322332}
    323333
    324 Optional<KeyHandleValueVariant> CDMProxy::getOrWaitForKeyValue(const KeyIDType& keyID) const
    325 {
    326     if (auto keyHandle = getOrWaitForKeyHandle(keyID))
     334Optional<KeyHandleValueVariant> CDMProxy::getOrWaitForKeyValue(const KeyIDType& keyID, WeakPtr<CDMProxyDecryptionClient>&& client) const
     335{
     336    if (auto keyHandle = getOrWaitForKeyHandle(keyID, WTFMove(client)))
    327337        return makeOptional((*keyHandle)->value());
    328338    return WTF::nullopt;
  • releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/encryptedmedia/CDMProxy.h

    r264219 r276708  
    147147
    148148class CDMInstanceProxy;
     149class CDMProxyDecryptionClient;
    149150
    150151// Handle to a "real" CDM, not the JavaScript facade. This can be used
    … …  
    158159    void updateKeyStore(const KeyStore& newKeyStore);
    159160    void setInstance(CDMInstanceProxy*);
     161    void abortWaitingForKey() const;
    160162
    161163    virtual void releaseDecryptionResources()
    … …  
    169171    bool keyAvailable(const KeyIDType&) const;
    170172    bool keyAvailableUnlocked(const KeyIDType&) const;
    171     Optional<Ref<KeyHandle>> tryWaitForKeyHandle(const KeyIDType&) const;
    172     Optional<Ref<KeyHandle>> getOrWaitForKeyHandle(const KeyIDType&) const;
    173     Optional<KeyHandleValueVariant> getOrWaitForKeyValue(const KeyIDType&) const;
     173    Optional<Ref<KeyHandle>> tryWaitForKeyHandle(const KeyIDType&, WeakPtr<CDMProxyDecryptionClient>&&) const;
     174    Optional<Ref<KeyHandle>> getOrWaitForKeyHandle(const KeyIDType&, WeakPtr<CDMProxyDecryptionClient>&&) const;
     175    Optional<KeyHandleValueVariant> getOrWaitForKeyValue(const KeyIDType&, WeakPtr<CDMProxyDecryptionClient>&&) const;
    174176    void startedWaitingForKey() const;
    175177    void stoppedWaitingForKey() const;
    … …  
    280282};
    281283
     284class CDMProxyDecryptionClient : public CanMakeWeakPtr<CDMProxyDecryptionClient, WeakPtrFactoryInitialization::Eager> {
     285public:
     286    virtual bool isAborting() = 0;
     287    virtual ~CDMProxyDecryptionClient() = default;
     288};
     289
    282290} // namespace WebCore
    283291
  • releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.cpp

    r268975 r276708  
    114114}
    115115
    116 bool CDMProxyClearKey::cencSetDecryptionKey(const cencDecryptContext& in)
     116bool CDMProxyClearKey::cencSetDecryptionKey(cencDecryptContext& in)
    117117{
    118118    // FIXME: Unnecessary copy, can we avoid this while still exposing
    … …  
    122122    keyIDVec.append(in.keyID, in.keyIDSizeInBytes);
    123123
    124     auto keyData = getOrWaitForKeyValue(keyIDVec);
     124    auto keyData = getOrWaitForKeyValue(keyIDVec, WTFMove(in.cdmProxyDecryptionClient));
    125125    if (!keyData)
    126126        return false;
  • releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyClearKey.h

    r263658 r276708  
    9292        size_t subsamplesBufferSizeInBytes;
    9393        size_t numSubsamples;
     94        WeakPtr<CDMProxyDecryptionClient> cdmProxyDecryptionClient;
    9495
    9596        bool isSubsampled() const { return numSubsamples; }
    … …  
    108109    // reuse some Crypto APIs in WebCore?
    109110    bool cencSetCounterVector(const cencDecryptContext&);
    110     bool cencSetDecryptionKey(const cencDecryptContext&);
     111    bool cencSetDecryptionKey(cencDecryptContext&);
    111112    bool cencDecryptFullSample(cencDecryptContext&);
    112113    bool cencDecryptSubsampled(cencDecryptContext&);
  • releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.cpp

    r264762 r276708  
    4545const WTF::Seconds s_licenseKeyResponseTimeout = WTF::Seconds(6);
    4646
    47 BoxPtr<OpenCDMSession> CDMProxyThunder::getDecryptionSession(const DecryptionContext& in) const
     47BoxPtr<OpenCDMSession> CDMProxyThunder::getDecryptionSession(DecryptionContext& in) const
    4848{
    4949    GstMappedBuffer mappedKeyID(in.keyIDBuffer, GST_MAP_READ);
    … …  
    5555    auto keyID = mappedKeyID.createVector();
    5656
    57     auto keyHandle = getOrWaitForKeyHandle(keyID);
     57    auto keyHandle = getOrWaitForKeyHandle(keyID, WTFMove(in.cdmProxyDecryptionClient));
    5858    if (!keyHandle.hasValue() || !keyHandle.value()->isStatusCurrentlyValid())
    5959        return nullptr;
    … …  
    8585    BoxPtr<OpenCDMSession> session = getDecryptionSession(input);
    8686    if (!session) {
    87         GST_ERROR("there is no valid session to decrypt for the provided key ID");
     87        GST_WARNING("there is no valid session to decrypt for the provided key ID (or the operation was aborted)");
    8888        return false;
    8989    }
  • releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.h

    r264219 r276708  
    5454        GstBuffer* subsamplesBuffer;
    5555        size_t numSubsamples;
     56        WeakPtr<CDMProxyDecryptionClient> cdmProxyDecryptionClient;
    5657    };
    5758
    … …  
    6061
    6162private:
    62     BoxPtr<OpenCDMSession> getDecryptionSession(const DecryptionContext&) const;
     63    BoxPtr<OpenCDMSession> getDecryptionSession(DecryptionContext&) const;
    6364    String m_keySystem;
    6465};
  • releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitClearKeyDecryptorGStreamer.cpp

    r266721 r276708  
    126126    }
    127127
    128     CDMProxyClearKey::cencDecryptContext context;
     128    CDMProxyClearKey::cencDecryptContext context = { };
    129129    context.keyID = mappedKeyIdBuffer.data();
    130130    context.keyIDSizeInBytes = mappedKeyIdBuffer.size();
    … …  
    146146        context.subsamplesBufferSizeInBytes = mappedSubsamplesBuffer.size();
    147147    }
     148    context.cdmProxyDecryptionClient = webKitMediaCommonEncryptionDecryptGetCDMProxyDecryptionClient(self);
    148149
    149150    return priv->cdmProxy->cencDecrypt(context);
  • releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp

    r272129 r276708  
    3737using WebCore::CDMProxy;
    3838
     39// Instances of this class are tied to the decryptor lifecycle. They can't be alive after the decryptor has been destroyed.
     40class CDMProxyDecryptionClientImplementation : public WebCore::CDMProxyDecryptionClient {
     41    WTF_MAKE_FAST_ALLOCATED;
     42public:
     43    CDMProxyDecryptionClientImplementation(WebKitMediaCommonEncryptionDecrypt* decryptor)
     44        : m_decryptor(decryptor) { }
     45    virtual bool isAborting()
     46    {
     47        return webKitMediaCommonEncryptionDecryptIsFlushing(m_decryptor);
     48    }
     49    virtual ~CDMProxyDecryptionClientImplementation() = default;
     50private:
     51    WebKitMediaCommonEncryptionDecrypt* m_decryptor;
     52};
     53
    3954#define WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_MEDIA_CENC_DECRYPT, WebKitMediaCommonEncryptionDecryptPrivate))
    4055struct _WebKitMediaCommonEncryptionDecryptPrivate {
    4156    RefPtr<CDMProxy> cdmProxy;
    4257
    43     Lock cdmAttachmentMutex;
    44     Condition cdmAttachmentCondition;
     58    // Protect the access to the structure members.
     59    Lock mutex;
     60    Condition condition;
     61
     62    bool isFlushing { false };
     63    std::unique_ptr<CDMProxyDecryptionClientImplementation> cdmProxyDecryptionClientImplementation;
    4564};
    4665
    … …  
    86105    gst_base_transform_set_passthrough(base, FALSE);
    87106    gst_base_transform_set_gap_aware(base, FALSE);
     107
     108    WebKitMediaCommonEncryptionDecrypt* self = WEBKIT_MEDIA_CENC_DECRYPT(base);
     109    WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(self);
     110    priv->cdmProxyDecryptionClientImplementation = WTF::makeUnique<CDMProxyDecryptionClientImplementation>(self);
    88111}
    89112
    … …  
    169192    }
    170193
    171     LockHolder locker(priv->cdmAttachmentMutex);
     194    LockHolder locker(priv->mutex);
     195
     196    if (priv->isFlushing) {
     197        GST_DEBUG_OBJECT(self, "Decryption aborted because of flush");
     198        return GST_FLOW_FLUSHING;
     199    }
    172200
    173201    // The CDM instance needs to be negotiated before we can begin decryption.
    174202    if (!priv->cdmProxy) {
    175203        GST_DEBUG_OBJECT(self, "CDM not available, going to wait for it");
    176         priv->cdmAttachmentCondition.waitFor(priv->cdmAttachmentMutex, MaxSecondsToWaitForCDMProxy, [priv] {
    177             return priv->cdmProxy;
     204        priv->condition.waitFor(priv->mutex, MaxSecondsToWaitForCDMProxy, [priv] {
     205            return priv->isFlushing || priv->cdmProxy;
    178206        });
     207        // Note that waitFor() releases the mutex lock internally while it waits, so isFlushing may have been changed.
     208        if (priv->isFlushing) {
     209            GST_DEBUG_OBJECT(self, "Decryption aborted because of flush");
     210            return GST_FLOW_FLUSHING;
     211        }
    179212        if (!priv->cdmProxy) {
    180213            GST_ERROR_OBJECT(self, "CDMProxy was not retrieved in time");
    … …  
    183216        GST_DEBUG_OBJECT(self, "CDM now available with address %p", priv->cdmProxy.get());
    184217    }
     218
    185219    auto removeProtectionMetaOnReturn = makeScopeExit([buffer, protectionMeta] {
    186220        gst_buffer_remove_meta(buffer, reinterpret_cast<GstMeta*>(protectionMeta));
    … …  
    246280
    247281    GST_TRACE_OBJECT(self, "decrypting");
    248     if (!klass->decrypt(self, ivBuffer, keyIDBuffer, buffer, subSampleCount, subSamplesBuffer)) {
     282
     283    // Temporarily release the lock while we don't need to access priv. The lower level API is used
     284    // in order to avoid creating several scopes with different LockHolder instances in each one.
     285    priv->mutex.unlock();
     286
     287    bool didDecryptionSucceed = klass->decrypt(self, ivBuffer, keyIDBuffer, buffer, subSampleCount, subSamplesBuffer);
     288
     289    // Accessing priv members again.
     290    priv->mutex.lock();
     291
     292    if (!didDecryptionSucceed) {
     293        if (priv->isFlushing) {
     294            GST_DEBUG_OBJECT(self, "Decryption aborted because of flush");
     295            return GST_FLOW_FLUSHING;
     296        }
    249297        GST_ERROR_OBJECT(self, "Decryption failed");
    250298        return GST_FLOW_NOT_SUPPORTED;
    … …  
    257305{
    258306    WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(self);
    259     auto locker = holdLock(priv->cdmAttachmentMutex);
     307    auto locker = holdLock(priv->mutex);
    260308    return priv->cdmProxy;
    261309}
    … …  
    290338    WebKitMediaCommonEncryptionDecryptClass* klass = WEBKIT_MEDIA_CENC_DECRYPT_GET_CLASS(self);
    291339
    292     auto locker = holdLock(priv->cdmAttachmentMutex);
     340    auto locker = holdLock(priv->mutex);
    293341    GST_ERROR_OBJECT(self, "Attaching CDMProxy %p", proxy);
    294342    priv->cdmProxy = proxy;
    295343    klass->cdmProxyAttached(self, priv->cdmProxy);
    296     priv->cdmAttachmentCondition.notifyOne();
     344    priv->condition.notifyOne();
    297345}
    298346
    … …  
    319367{
    320368    WebKitMediaCommonEncryptionDecrypt* self = WEBKIT_MEDIA_CENC_DECRYPT(trans);
    321     gboolean result = FALSE;
     369    WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(self);
    322370
    323371    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=191355
    … …  
    331379        ASSERT(gst_event_has_name(event, "attempt-to-decrypt"));
    332380        GST_DEBUG_OBJECT(self, "Handling attempt-to-decrypt");
    333         result = installCDMProxyIfNotAvailable(self);
     381        gboolean result = installCDMProxyIfNotAvailable(self);
    334382        gst_event_unref(event);
     383        return result;
     384    }
     385    case GST_EVENT_FLUSH_START:
     386        GST_DEBUG_OBJECT(self, "Flush-start");
     387        {
     388            LockHolder locker(priv->mutex);
     389            bool isCdmProxyAttached = priv->cdmProxy;
     390            priv->isFlushing = true;
     391            if (isCdmProxyAttached) {
     392                locker.unlockEarly();
     393                priv->cdmProxy->abortWaitingForKey();
     394            } else
     395                priv->condition.notifyOne();
     396        }
    335397        break;
    336     }
     398    case GST_EVENT_FLUSH_STOP:
     399        GST_DEBUG_OBJECT(self, "Flush-stop");
     400        {
     401            LockHolder locker(priv->mutex);
     402            priv->isFlushing = false;
     403        }
     404        break;
    337405    default:
    338         result = GST_BASE_TRANSFORM_CLASS(parent_class)->sink_event(trans, event);
    339406        break;
    340407    }
    341408
    342     return result;
     409    return GST_BASE_TRANSFORM_CLASS(parent_class)->sink_event(trans, event);
     410}
     411
     412bool webKitMediaCommonEncryptionDecryptIsFlushing(WebKitMediaCommonEncryptionDecrypt* self)
     413{
     414    WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(self);
     415    LockHolder locker(priv->mutex);
     416    return priv->isFlushing;
     417}
     418
     419WeakPtr<WebCore::CDMProxyDecryptionClient> webKitMediaCommonEncryptionDecryptGetCDMProxyDecryptionClient(WebKitMediaCommonEncryptionDecrypt* self)
     420{
     421    WebKitMediaCommonEncryptionDecryptPrivate* priv = WEBKIT_MEDIA_CENC_DECRYPT_GET_PRIVATE(self);
     422    return makeWeakPtr(*priv->cdmProxyDecryptionClientImplementation);
    343423}
    344424
    … …  
    351431    case GST_STATE_CHANGE_PAUSED_TO_READY:
    352432        GST_DEBUG_OBJECT(self, "PAUSED->READY");
    353         priv->cdmAttachmentCondition.notifyOne();
     433        priv->condition.notifyOne();
    354434        break;
    355435    default:
    … …  
    372452    if (gst_context_has_context_type(context, "drm-cdm-proxy")) {
    373453        const GValue* value = gst_structure_get_value(gst_context_get_structure(context), "cdm-proxy");
    374         LockHolder locker(priv->cdmAttachmentMutex);
     454        LockHolder locker(priv->mutex);
    375455        priv->cdmProxy = value ? reinterpret_cast<CDMProxy*>(g_value_get_pointer(value)) : nullptr;
    376456        GST_DEBUG_OBJECT(self, "received new CDMInstance %p", priv->cdmProxy.get());
  • releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.h

    r264219 r276708  
    2929#include <gst/gst.h>
    3030#include <wtf/RefPtr.h>
     31#include <wtf/WeakPtr.h>
    3132
    3233G_BEGIN_DECLS
    … …  
    4546
    4647GType webkit_media_common_encryption_decrypt_get_type(void);
     48
     49bool webKitMediaCommonEncryptionDecryptIsFlushing(WebKitMediaCommonEncryptionDecrypt*);
     50WeakPtr<WebCore::CDMProxyDecryptionClient> webKitMediaCommonEncryptionDecryptGetCDMProxyDecryptionClient(WebKitMediaCommonEncryptionDecrypt*);
    4751
    4852struct _WebKitMediaCommonEncryptionDecrypt {
  • releases/WebKitGTK/webkit-2.32/Source/WebCore/platform/graphics/gstreamer/eme/WebKitThunderDecryptorGStreamer.cpp

    r273311 r276708  
    157157    }
    158158
    159     CDMProxyThunder::DecryptionContext context;
     159    CDMProxyThunder::DecryptionContext context = { };
    160160    context.keyIDBuffer = keyIDBuffer;
    161161    context.ivBuffer = ivBuffer;
    … …  
    163163    context.numSubsamples = subsampleCount;
    164164    context.subsamplesBuffer = subsampleCount ? subsamplesBuffer : nullptr;
     165    context.cdmProxyDecryptionClient = webKitMediaCommonEncryptionDecryptGetCDMProxyDecryptionClient(self);
     166    bool result = priv->cdmProxy->decrypt(context);
    165167
    166     return priv->cdmProxy->decrypt(context);
     168    return result;
    167169}
    168170
Note: See TracChangeset for help on using the changeset viewer.