widevine-rdk is the common OCDM (Open Content Decryption Module) MediaSession implementation for the Widevine DRM system. It operates as a dynamically loaded DRM backend plugin within the WPEFramework/Thunder OCDM framework, bridging the platform-neutral OCDM interface with the vendor-supplied Widevine CDM library. The component handles the complete lifecycle of a protected media session: device provisioning, license acquisition, key status tracking, and the decryption of encrypted audio and video samples passed down from the RDK middleware playback pipeline.

At the device level, widevine-rdk enables playback of Widevine-protected content on RDK devices by managing DRM session state on behalf of media pipeline components. It abstracts the details of the Widevine protocol from upper layers, exposing a standard CDMi interface that the OCDM plugin consumes. Secure Video Path (SVP) integration is provided through the gst-svp-ext library, routing decrypted video samples directly into hardware-protected memory regions.

At the module level, widevine-rdk provides three coordinated units of functionality: a media system manager that owns the single CDM instance and the map of active sessions, a per-session media key session that drives the license request and decryption workflows, and a host-services implementation that supplies the CDM library with storage, clock, and timer services sourced from the WPEFramework core.

```mermaid
flowchart LR

%% Styles
classDef Apps stroke:#00B9F1,fill:#E6F7FD,stroke-width:2px;
classDef RDKMW stroke:#75D701,fill:#F1FFE6,stroke-width:2px;
classDef VL stroke:#808080,fill:#F2F2F2,stroke-width:2px;

%% Apps Layer
    subgraph Apps["Apps & Runtimes"]
        FBApps["Firebolt Apps"]
        WPE_RT["WPE Runtime"]
    end

%% Middleware
    subgraph RDKMW["RDK Core Middleware"]
        Rialto["Rialto / Media Pipeline"]
        Thunder["WPEFramework (Thunder)"]
        OCDM["OCDM Plugin"]
        WV["widevine-rdk\n(OCDM DRM Backend)"]
        Thunder --> OCDM
        OCDM --> WV
    end

%% Vendor Layer
    subgraph VL["Vendor Layer"]
        WVCDM["Widevine CDM Library\n(widevine_ce_cdm_shared)"]
        SVP["gst-svp-ext\n(SVP Platform Library)"]
    end

    Apps -->|Firebolt APIs| Thunder
    Rialto -->|CDMi decrypt calls| OCDM
    WV -->|widevine::Cdm APIs| WVCDM
    WV -->|SVP context / secure buffer APIs| SVP
    WV -->|"Provisioning HTTP(S)"| Cloud["Provisioning Server"]
```

Key Features & Responsibilities:


Design

The component is designed as a shared library (.drm extension) loaded at runtime by the WPEFramework OCDM plugin. It implements the CDMi IMediaKeys interface in the Widevine class and the IMediaKeySession interface in MediaKeySession, with both classes residing in the CDMi namespace. A single Widevine instance owns the widevine::Cdm object and a session map (std::map<std::string, MediaKeySession*>) keyed by session ID. Each entry in the session map corresponds to one active decryption context.

The initialization path in Widevine::Initialize() reads a JSON configuration block provided by the OCDM plugin, extracts product/company/model/device identifiers (with fallback to /etc/device.properties via the ReadFromPropertiesFile() helper), enriches client identity with build_info (__DATE__) and arch_name (from uname() on Linux), derives a wv.storage base path from shell->PersistentPath(), creates the directory via Core::Directory::CreatePath(), and calls _host.SetBasePath() to configure persistent DRM artifact storage. It then optionally pre-loads a DRM certificate (now deprecated; file-backed storage supersedes this) and calls widevine::Cdm::initialize() followed by widevine::Cdm::create(). The resulting CDM handle is retained for the lifetime of the plugin instance.

Northbound interaction with WPEFramework/Thunder is entirely through the CDMi interface. The OCDM plugin calls CreateMediaKeySession() to obtain an IMediaKeySession, then drives the license exchange by calling Run(), Update(), and Decrypt() on that session. JSON-RPC routing is handled entirely by the OCDM plugin layer; this component exposes only the CDMi interface.

Southbound, the component calls into the Widevine CDM library (widevine_ce_cdm_shared) for all DRM operations and into gst-svp-ext for SVP secure memory management. Network communication with the provisioning server is performed directly from MediaSession.cpp using libcurl, with a write callback aggregating the HTTP response body into a std::string.

Runtime storage for DRM artifacts is handled in two ways: the keybox path is passed to the CDM via an environment variable (WIDEVINE_KEYBOX_PATH), and all other DRM files (certificates, usage tables, etc.) are stored under <PersistentPath>/wv.storage/. The HostImplementation uses a write-through cache (std::map<std::string, std::string>) backed by that directory: reads consult the cache first and fall back to disk (populating the cache on a hit); writes update both cache and disk. Bulk and wildcard deletions (fnmatch-based) are supported against the on-disk store. PreloadFile() is still present but is deprecated; file-backed storage is the authoritative mechanism.

```mermaid
graph LR

    subgraph WidevineDRM ["widevine-rdk (.drm plugin)"]

        subgraph MediaSystemLayer ["Media System"]
            MS["Widevine\n(IMediaKeys)"]
            SM["SessionMap"]
            AL["_adminLock"]
            MS --> SM
            MS --> AL
        end

        subgraph SessionLayer ["Media Key Session"]
            MKS["MediaKeySession\n(IMediaKeySession)"]
            GL["g_lock"]
            SVPCtx["SVP Context"]
            MKS --> GL
            MKS --> SVPCtx
        end

        subgraph HostLayer ["Host Services"]
            HI["HostImplementation\n(IStorage + IClock + ITimer)"]
            FS["StorageMap"]
            TM["TimerType Thread"]
            HI --> FS
            HI --> TM
        end

        subgraph ExtLayer ["External Dependencies"]
            WV_CDM["Widevine CDM Library"]
            SVP_LIB["gst-svp-ext"]
            PROV_SRV["Provisioning Server"]
        end

        MS -->|creates| MKS
        MS -->|owns| HI
        MS -->|Cdm init / create| WV_CDM
        MKS -->|CDM operations| WV_CDM
        MKS -->|SVP buffer ops| SVP_LIB
        MKS -->|provisioning GET| PROV_SRV
        HI -->|storage / timer callbacks| WV_CDM
    end
```

Threading Model

Platform and Integration Requirements


Component State Flow

Initialization to Active State

The component is initialized when the WPEFramework OCDM plugin loads the .drm shared library and calls through the GetSystemFactory() entry point. The factory returns a Widevine instance. On Initialize(), the component reads the JSON configuration, sets up client device identity, initializes the SVP platform, creates the Widevine CDM instance, and sets the YouTube certificate scope parameter.

The component transitions through the following states: Initializing (parse JSON config, read device.properties) → CDMSetup (call widevine::Cdm::initialize() and widevine::Cdm::create()) → Active (handle CreateMediaKeySession, Decrypt, CDM event callbacks) → Shutdown (session map cleared, CDM instance deleted in destructor).

```mermaid
sequenceDiagram
    participant OCDMPlugin as OCDM Plugin
    participant WV as Widevine (MediaSystem)
    participant HI as HostImplementation
    participant CDM as Widevine CDM Library
    participant SVP as gst-svp-ext

    OCDMPlugin->>WV: GetSystemFactory() → Widevine instance
    OCDMPlugin->>WV: Initialize(shell, configline)

    WV->>WV: Parse JSON config (certificate, keybox, product, company, model, device)
    WV->>WV: Read /etc/device.properties via ReadFromPropertiesFile()
    WV->>WV: Set client_info.build_info (__DATE__) and arch_name (uname)
    WV->>SVP: svpPlatformInitializeWidevine()
    SVP-->>WV: SVP platform ready

    WV->>HI: SetBasePath(<PersistentPath>/wv.storage)
    WV->>HI: PreloadFile(cert.bin, certificate data) [deprecated]
    WV->>CDM: widevine::Cdm::initialize(kOpaqueHandle, client_info, &_host, ...)
    CDM-->>WV: kSuccess

    WV->>CDM: widevine::Cdm::create(this, &_host, false)
    CDM-->>WV: Cdm* instance

    WV->>CDM: setAppParameter("youtube_cert_scope", COBALT_CERT_SCOPE)
    CDM-->>WV: kSuccess

    WV-->>OCDMPlugin: Initialize() complete

    loop Runtime
        OCDMPlugin->>WV: CreateMediaKeySession(...)
        WV-->>OCDMPlugin: IMediaKeySession*
    end

    OCDMPlugin->>WV: Destructor / plugin unload
    WV->>WV: Delete all sessions, delete _cdm
```

Runtime State Changes

Once active, state changes within a session are driven by license exchange outcomes and CDM callbacks.

State Change Triggers:

Context Switching Scenarios:


Call Flows

Initialization Call Flow

```mermaid
sequenceDiagram
    participant OCDMPlugin as OCDM Plugin
    participant WV as Widevine
    participant CFG as JSON Config
    participant HI as HostImplementation
    participant CDM as Widevine CDM Library

    OCDMPlugin->>WV: Initialize(shell, configline)
    WV->>CFG: config.FromString(configline)
    CFG-->>WV: certificate, keybox, product, company, model, device

    WV->>WV: Derive basePath from shell->PersistentPath() + "/wv.storage"
    WV->>WV: Core::Directory(basePath).CreatePath()
    WV->>HI: SetBasePath(basePath)
    HI-->>WV: Disk-backed storage configured

    WV->>HI: PreloadFile("cert.bin", certificate data) [deprecated]
    HI-->>WV: File seeded in cache

    WV->>CDM: widevine::Cdm::initialize(kOpaqueHandle, client_info, &_host, ...)
    CDM-->>WV: kSuccess

    WV->>CDM: widevine::Cdm::create(this, &_host, false)
    CDM-->>WV: _cdm instance

    WV->>CDM: _cdm->setAppParameter("youtube_cert_scope", scope_value)
    CDM-->>WV: kSuccess

    WV-->>OCDMPlugin: Initialization complete
```

Request Processing Call Flow

The most representative call flow is the license acquisition sequence: a new session is created, a license request is generated by the CDM, forwarded to the license server by the caller, and the response is applied back to the session.

```mermaid
sequenceDiagram
    participant Pipeline as Media Pipeline (Rialto)
    participant OCDMPlugin as OCDM Plugin
    participant WV as Widevine
    participant MKS as MediaKeySession
    participant CDM as Widevine CDM Library
    participant LicSrv as License Server

    Pipeline->>OCDMPlugin: Open DRM session (init data, license type)
    OCDMPlugin->>WV: CreateMediaKeySession(licenseType, initDataType, initData, CDMData)
    WV->>MKS: new MediaKeySession(cdm, licenseType)
    MKS->>CDM: createSession(licenseType, &sessionId)
    CDM-->>MKS: sessionId (or kNeedsDeviceCertificate → provisioning)
    WV->>MKS: Init(licenseType, initDataType, initData, CDMData)
    MKS-->>WV: CDMi_SUCCESS
    WV-->>OCDMPlugin: IMediaKeySession*

    OCDMPlugin->>MKS: Run(callback)
    MKS->>CDM: generateRequest(sessionId, initDataType, initData)
    CDM-->>MKS: onMessage(kLicenseRequest, licenseRequestMessage)
    MKS->>OCDMPlugin: OnKeyMessage(message, destUrl)
    OCDMPlugin->>LicSrv: POST license request
    LicSrv-->>OCDMPlugin: License response

    OCDMPlugin->>MKS: Update(licenseResponse)
    MKS->>CDM: update(sessionId, keyResponse)
    CDM-->>MKS: onKeyStatusChange()
    MKS->>OCDMPlugin: OnKeyStatusUpdate("KeyUsable", keyId, keyIdLen)
    MKS->>OCDMPlugin: OnKeyStatusesUpdated()
```

Internal Modules

Module / ClassDescriptionKey Files
WidevineImplements IMediaKeys, widevine::Cdm::IEventListener, and IMediaSystemMetrics. Owns the widevine::Cdm instance, the session map, and the HostImplementation. Routes CDM event callbacks to the appropriate MediaKeySession under _adminLock. Registered with the CDMi system factory for MIME types video/webm, video/mp4, audio/webm, audio/mp4.MediaSystem.cpp
MediaKeySessionImplements IMediaKeySession. Manages the per-session lifecycle: initialization, license request generation, license response processing, key status reporting, and sample decryption. Holds the SVP context and secure buffer state when USE_SVP is active. Serializes CDM operations with g_lock.MediaSession.cpp, MediaSession.h
HostImplementationImplements widevine::Cdm::IStorage, widevine::Cdm::IClock, widevine::Cdm::ITimer, and (for version 18) widevine::Cdm::ILogger. Provides the CDM library with a write-through cache backed by persistent disk storage under <PersistentPath>/wv.storage/ (configured via SetBasePath()), a millisecond timestamp from WPEFramework::Core::Time::Now(), and timer scheduling via WPEFramework::Core::TimerType. PreloadFile() is retained for backward compatibility but is deprecated. Supports bulk and wildcard file removal via fnmatch.HostImplementation.cpp, HostImplementation.h
PolicyCompile-time constants used by MediaKeySession: the license server URL (kLicenseServer), an optional embedded default server certificate (kDefaultServerCertificate), and CENC init data constants. An additional production provisioning service certificate (kCpProductionServiceCertificate) is defined in MediaSession.cpp for use during the provisioning flow.Policy.h, MediaSession.cpp
ModuleWPEFramework module declaration required for integration with the plugin framework.Module.cpp, Module.h

Component Interactions

Interaction Matrix

Target Component / LayerInteraction PurposeKey APIs / Topics
WPEFramework OCDM Plugin

OCDM PluginNorthbound CDMi interface — session creation, decryption, server certificate, metricsCDMi::IMediaKeys, CDMi::IMediaKeySession, CDMi::IMediaSystemMetrics, CDMi::IMediaKeySessionCallback::OnKeyMessage, OnKeyStatusUpdate, OnKeyStatusesUpdated, OnError
Vendor Libraries

widevine_ce_cdm_sharedAll DRM operations: CDM lifecycle, session management, decryptionwidevine::Cdm::initialize(), widevine::Cdm::create(), createSession(), generateRequest(), update(), load(), remove(), close(), decrypt(), getKeyStatuses(), setServiceCertificate(), setAppParameter(), setVideoResolution(), getMetrics(), getProvisioningRequest(), handleProvisioningResponse()
gst-svp-extSecure Video Path — secure memory allocation, token generation, context managementsvpPlatformInitializeWidevine(), gst_svp_ext_get_context(), gst_svp_ext_free_context(), svp_allocate_secure_buffers(), svp_release_secure_buffers(), svp_buffer_alloc_token(), svp_buffer_to_token(), svp_buffer_free_token(), svpIsDynamicSVPEncEnabled(), gst_svp_has_header(), gst_svp_header_get_start_of_data(), gst_svp_header_get_field(), gst_svp_header_set_field()
External Systems

Provisioning ServerDevice provisioning over HTTP(S)curl_easy_perform() with WV_PROV_SERVER_URL + "&signedRequest=" + request (HTTP GET carrying signed provisioning request)
/etc/device.propertiesDevice identity fallback for CDM client infoFile read: OPERATOR_NAME, MODEL_NUM, COBALT_CERT_SCOPE (and DEVICE_NAME on non-Linux builds only)

Events Published

Event NameTopicTrigger ConditionSubscriber
Key messageIMediaKeySessionCallback::OnKeyMessageCDM calls onMessage() with kLicenseRequest, kLicenseRenewal, or kLicenseReleaseOCDM Plugin
Key status updateIMediaKeySessionCallback::OnKeyStatusUpdateAfter Update() processes a license response (MediaKeySession::onKeyStatusChange()), or when CDM calls onRemoveComplete()OCDM Plugin
Key statuses updatedIMediaKeySessionCallback::OnKeyStatusesUpdatedAfter all per-key OnKeyStatusUpdate calls are dispatchedOCDM Plugin
Unknown key statusIMediaKeySessionCallback::OnKeyStatusUpdateCDM returns a key status value not mapped to a known string; reported as "UnknownError"OCDM Plugin
ErrorIMediaKeySessionCallback::OnErrorgenerateRequest() fails; or CDM update()/load()/remove() returns a non-success statusOCDM Plugin

IPC Flow Patterns

Primary Request / Response Flow:

The OCDM plugin dispatches calls synchronously to the Widevine CDMi interface. The component delegates to the CDM library and returns the result.

```mermaid
sequenceDiagram
    participant Pipeline as Media Pipeline
    participant OCDMPlugin as OCDM Plugin
    participant WV as widevine-rdk
    participant CDM as Widevine CDM Library

    Pipeline->>OCDMPlugin: Decrypt sample
    OCDMPlugin->>WV: IMediaKeySession::Decrypt(inData, sampleInfo)
    WV->>CDM: m_cdm->decrypt(sessionId, decryptionBatch)
    CDM-->>WV: kSuccess / error status
    WV-->>OCDMPlugin: CDMi_SUCCESS / CDMi_S_FALSE
    OCDMPlugin-->>Pipeline: Decrypted sample (or error)
```

Event Notification Flow:

CDM library callbacks (onMessage, onRemoveComplete, onDeferredComplete) arrive on CDM-internal threads. The Widevine class routes them under _adminLock to the corresponding session. Key status updates after a license exchange are dispatched directly from MediaKeySession::Update().

```mermaid
sequenceDiagram
    participant CDM as Widevine CDM Library
    participant WV as Widevine (MediaSystem)
    participant MKS as MediaKeySession
    participant CB as IMediaKeySessionCallback (OCDM Plugin)

    Note over CDM,WV: License message callback (CDM-internal thread)
    CDM->>WV: onMessage(session_id, kLicenseRequest, message)
    WV->>WV: _adminLock.Lock()
    WV->>MKS: onMessage(messageType, message)
    MKS->>CB: OnKeyMessage(message, destUrl)
    WV->>WV: _adminLock.Unlock()

    Note over MKS,CB: Key status update (caller thread, after Update())
    MKS->>CDM: m_cdm->update(sessionId, keyResponse)
    MKS->>CDM: getKeyStatuses(sessionId, &map)
    CDM-->>MKS: KeyStatusMap
    loop For each key in map
        MKS->>CB: OnKeyStatusUpdate(statusString, keyId, keyIdLen)
    end
    MKS->>CB: OnKeyStatusesUpdated()
```

Implementation Details

Major HAL APIs Integration

APIPurposeImplementation File
widevine::Cdm::initialize()One-time CDM library initialization with client identity and host service interfacesMediaSystem.cpp
widevine::Cdm::create()Creates a CDM instance that manages key sessionsMediaSystem.cpp
m_cdm->createSession()Opens a new Widevine key session of the specified type (temporary, persistent)MediaSession.cpp
m_cdm->generateRequest()Generates a license request message for a given initialization data type and dataMediaSession.cpp
m_cdm->update()Provides a license server response to the CDM to install keysMediaSession.cpp
m_cdm->decrypt()Decrypts an encrypted sample using the installed keysMediaSession.cpp
m_cdm->getKeyStatuses()Retrieves the current status of all keys in a sessionMediaSession.cpp
m_cdm->load()Loads a persistent license session from storageMediaSession.cpp
m_cdm->remove()Removes a persistent license from storageMediaSession.cpp
m_cdm->close()Closes and releases a key sessionMediaSession.cpp
m_cdm->setServiceCertificate()Sets a service certificate for encrypted license requestsMediaSystem.cpp, MediaSession.cpp
m_cdm->setAppParameter()Sets CDM application-level parameters (e.g., YouTube cert scope)MediaSystem.cpp
m_cdm->setVideoResolution()Notifies the CDM of the current video resolution for output protectionMediaSession.cpp
m_cdm->getMetrics()Retrieves CDM telemetry metricsMediaSystem.cpp
m_cdm->getProvisioningRequest()Generates a device provisioning request when no device certificate is presentMediaSession.cpp
m_cdm->handleProvisioningResponse()Processes the provisioning server response to install a device certificateMediaSession.cpp
_host.SetBasePath()Configures the root directory (<PersistentPath>/wv.storage/) for disk-backed DRM artifact storageMediaSystem.cpp
svpPlatformInitializeWidevine()Initializes the SVP platform subsystem for WidevineMediaSystem.cpp
gst_svp_ext_get_context()Obtains an SVP context handle for the current sessionMediaSession.cpp
svp_allocate_secure_buffers()Allocates a hardware-protected secure memory region for a decrypted sampleMediaSession.cpp
svp_buffer_to_token()Converts a secure buffer descriptor to an opaque token for downstream useMediaSession.cpp
svp_release_secure_buffers()Releases a previously allocated secure memory regionMediaSession.cpp

Key Implementation Logic


Configuration

Key Configuration Files

Configuration FilePurposeOverride Mechanism
OCDM plugin JSON config (Thunder config)Supplies certificate path, keybox path, product/company/model/device identity strings to Widevine::Initialize()Set via WPEFramework plugin configuration; parsed using Core::JSON::Container
/etc/device.propertiesFallback source for OPERATOR_NAME, MODEL_NUM, COBALT_CERT_SCOPE (and DEVICE_NAME on non-Linux builds) when not set in JSON configWrite to file; values are read on each Initialize() call

Key Configuration Parameters

ParameterTypeDefaultDescription
certificatestringFilesystem path to a pre-loaded DRM certificate file (cert.bin). Loaded into file-backed host storage (with an in-memory cache) before CDM initialization.
keyboxstringFilesystem path to the Widevine keybox. Set as the WIDEVINE_KEYBOX_PATH environment variable for the CDM library.
productstring"WPEFramework"Product name reported to the CDM as client_info.product_name.
companystringvalue of OPERATOR_NAME in device.propertiesCompany name reported to the CDM as client_info.company_name.
modelstringvalue of MODEL_NUM in device.propertiesModel name reported to the CDM as client_info.model_name.
build_info (auto)string__DATE__ (compile-time)Build date set automatically in client_info.build_info; not configurable at runtime.
arch_name (auto, Linux only)stringuname().machineCPU architecture populated from uname() into client_info.arch_name on Linux builds; not configurable at runtime.
devicestring"Linux"Device name reported to the CDM as client_info.device_name.
WIDEVINE_VERSION (build-time)intv16 code path (implicit if undefined)Selects the Widevine CDM API version (16, 17, or 18). Set via the CMake variable CMAKE_WIDEVINE_VERSION (which then defines -DWIDEVINE_VERSION=<n>). If not defined, the preprocessor treats it as 0 and the build compiles the <17 (v16) code path; define it explicitly for Widevine CDM versions 17 or 18. In Yocto builds, this is typically derived from distro features (widevine_v18 → 18, widevine_v17 → 17, otherwise v16).
WV_PROV_SERVER_URL_STRING (build-time)stringMandatory provisioning server base URL (must include a query parameter). Set via the CMake variable WV_PROV_SERVER_URL_STRING (which then defines -DWV_PROV_SERVER_URL="<url>"). The string &signedRequest= and the request body are appended at runtime.

Runtime Configuration

The CDM session's stream metadata can be updated at runtime through MediaKeySession::SetParameter():

# Set media type (drives SVP stream type selection)
SetParameter("mediaType", "video/mp4")

# Set video resolution (forwarded to CDM for output protection)
SetParameter("RESOLUTION", "1920,1080")

# Set SVP RPC ID for gst-svp-ext context binding
SetParameter("rpcId", "<hex_id>")

Configuration Persistence

The keybox path is communicated to the CDM library via the WIDEVINE_KEYBOX_PATH environment variable; the CDM library manages keybox reading and persistence. All other DRM artifacts (certificates, usage tables, etc.) are persisted by HostImplementation to <PersistentPath>/wv.storage/ on disk and survive process restarts. PreloadFile() can still seed the in-memory cache before CDM initialization but is deprecated; the file-backed store is now the primary mechanism. Configuration changes applied through SetParameter() are session-scoped and apply for the duration of the active session.