Skip to content

Commit 058a551

Browse files
marcin-mielczarczyk-redeocanha
authored andcommitted
RDKDEV-1148: Release CDM resources when not used
When HTMLMediaElement has been created in WPE and HTMLMediaElement::setMediaKeys() method was called to set DRM keys, CDMThunder implementation already allocates CDM resources and they're not released until HTMLMediaElement object is destructed. HTMLMediaElement destruction is non-deterministic and it's relying on Garbage Collector. In this case very often we observe that after WPE exit (WPE process is not closed, but some #boot address is being loaded), CDM resources are not released immediately and CDM can't be used by other applications like IP Player or Netflix. Proposed solution introduces following changes: 1) CDMPrivateThunder implementation doesn't occupy CDM resources permanently, as it only needs CDM resources to check if server certificate is supported so CDM resources can be acquired before check and released afterwards. The CDM resources are reallocated again if any code asks for the OpenCDMSystem instance again. 2) CDMInstanceThunder object's CDM resources are released on HTMLMediaElement::stop() to not wait for Garbage Collector See: #1580 Co-authored by: Enrique Ocaña González <eocanha@igalia.com> WARNING: While this commit is currently working for all the tested use cases, including reassigning one MediaKeys from one <video> to a different one, it's generally a bad idea to mess with the lifecycle of objects in this way. There can be some other unforeseen usage patterns that may create issues in the future. The proper solution to the problem would be to ensure that when the WebKitBrowser Thunder plugin is destroyed, all the JavaScript objects held by the WebProcess are properly garbage collected and therefore destroyed. This would release the OpenCDMSystem and other valuable external resources without requiring the preventive release hack done in this commit.
1 parent ef2fbfe commit 058a551

6 files changed

Lines changed: 33 additions & 6 deletions

File tree

Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ void MediaKeys::detachCDMClient(CDMClient& client)
161161
{
162162
ASSERT(m_cdmClients.contains(client));
163163
m_cdmClients.remove(client);
164+
if (m_cdmClients.computesEmpty())
165+
m_instance->releaseCDM();
164166
}
165167

166168
void MediaKeys::attemptToResumePlaybackOnClients()

Source/WebCore/html/HTMLMediaElement.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6097,6 +6097,12 @@ void HTMLMediaElement::stop()
60976097

60986098
if (m_mediaSession)
60996099
m_mediaSession->stopSession();
6100+
6101+
if (m_mediaKeys) {
6102+
m_mediaKeys->detachCDMClient(*this);
6103+
if (m_player)
6104+
m_player->cdmInstanceDetached(m_mediaKeys->cdmInstance());
6105+
}
61006106
}
61016107

61026108
void HTMLMediaElement::suspend(ReasonForSuspension reason)

Source/WebCore/platform/encryptedmedia/CDMInstance.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ class CDMInstance : public RefCounted<CDMInstance> {
107107
virtual void setStorageDirectory(const String&) = 0;
108108
virtual const String& keySystem() const = 0;
109109
virtual RefPtr<CDMInstanceSession> createSession() = 0;
110+
virtual void releaseCDM() { };
110111

111112
enum class HDCPStatus : uint8_t {
112113
Unknown,

Source/WebCore/platform/graphics/gstreamer/eme/CDMProxyThunder.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@ BoxPtr<OpenCDMSession> CDMProxyThunder::getDecryptionSession(DecryptionContext&
6464
BoxPtr<OpenCDMSession> keyValue = std::get<BoxPtr<OpenCDMSession>>(keyData);
6565

6666
if (!keyValue) {
67-
keyValue = adoptInBoxPtr(opencdm_get_system_session(&static_cast<const CDMInstanceThunder*>(instance())->thunderSystem(), keyID.data(),
68-
keyID.size(), s_licenseKeyResponseTimeout.millisecondsAs<uint32_t>()));
67+
keyValue = adoptInBoxPtr(opencdm_get_system_session(
68+
&const_cast<CDMInstanceThunder*>(static_cast<const CDMInstanceThunder*>(instance()))->thunderSystem(),
69+
keyID.data(), keyID.size(), s_licenseKeyResponseTimeout.millisecondsAs<uint32_t>()));
6970
ASSERT(keyValue);
7071
// takeValueIfDifferent takes and r-value ref of
7172
// KeyHandleValueVariant. We want to copy the BoxPtr when

Source/WebCore/platform/graphics/gstreamer/eme/CDMThunder.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ bool CDMFactoryThunder::supportsKeySystem(const String& keySystem)
141141

142142
CDMPrivateThunder::CDMPrivateThunder(const String& keySystem)
143143
: m_keySystem(keySystem)
144-
, m_thunderSystem(opencdm_create_system(keySystem.utf8().data()))
145144
{
146145
};
147146

@@ -204,7 +203,9 @@ void CDMPrivateThunder::loadAndInitialize()
204203

205204
bool CDMPrivateThunder::supportsServerCertificates() const
206205
{
207-
bool isSupported = opencdm_system_supports_server_certificate(m_thunderSystem.get());
206+
OpenCDMSystem *ocdmSystem = opencdm_create_system(m_keySystem.utf8().data());
207+
bool isSupported = opencdm_system_supports_server_certificate(ocdmSystem);
208+
opencdm_destruct_system(ocdmSystem);
208209
GST_DEBUG("server certificate supported %s", boolForPrinting(isSupported));
209210
return isSupported;
210211
}
@@ -258,6 +259,9 @@ void CDMInstanceThunder::initializeWithConfiguration(const CDMKeySystemConfigura
258259
void CDMInstanceThunder::setServerCertificate(Ref<SharedBuffer>&& certificate, SuccessCallback&& callback)
259260
{
260261
auto data = certificate->extractData();
262+
if (m_thunderSystem.get() == nullptr)
263+
m_thunderSystem.reset(opencdm_create_system(m_keySystem.utf8().data()));
264+
261265
OpenCDMError error = opencdm_system_set_server_certificate(m_thunderSystem.get(), const_cast<uint8_t*>(data.data()), data.size());
262266
callback(!error ? Succeeded : Failed);
263267
}
@@ -267,6 +271,19 @@ void CDMInstanceThunder::setStorageDirectory(const String& storageDirectory)
267271
FileSystem::makeAllDirectories(storageDirectory);
268272
}
269273

274+
void CDMInstanceThunder::releaseCDM()
275+
{
276+
m_thunderSystem.reset();
277+
}
278+
279+
OpenCDMSystem& CDMInstanceThunder::thunderSystem()
280+
{
281+
if (m_thunderSystem.get() == nullptr)
282+
m_thunderSystem.reset(opencdm_create_system(m_keySystem.utf8().data()));
283+
284+
return *m_thunderSystem.get();
285+
}
286+
270287
CDMInstanceSessionThunder::CDMInstanceSessionThunder(CDMInstanceThunder& instance)
271288
: CDMInstanceSessionProxy(instance)
272289
{

Source/WebCore/platform/graphics/gstreamer/eme/CDMThunder.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ class CDMPrivateThunder final : public CDMPrivate {
9999

100100
private:
101101
String m_keySystem;
102-
Thunder::UniqueThunderSystem m_thunderSystem;
103102
};
104103

105104
class CDMInstanceThunder final : public CDMInstanceProxy {
@@ -114,8 +113,9 @@ class CDMInstanceThunder final : public CDMInstanceProxy {
114113
void setStorageDirectory(const String&) final;
115114
const String& keySystem() const final { return m_keySystem; }
116115
RefPtr<CDMInstanceSession> createSession() final;
116+
void releaseCDM() final;
117117

118-
OpenCDMSystem& thunderSystem() const { return *m_thunderSystem.get(); };
118+
OpenCDMSystem& thunderSystem();
119119

120120
private:
121121
Thunder::UniqueThunderSystem m_thunderSystem;

0 commit comments

Comments
 (0)