Supporting Encrypted Media Extensions with Microsoft PlayReady DRM in web browsers

[ This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation ]

The World Wide Web Consortium (W3C) Encrypted Media Extensions (EME) to HTML5 introduce the ability for websites to play Digital Rights Management (DRM) protected content without the use of plug-ins. Internet Explorer 11 on Windows 8.1 supports EME in combination with Microsoft PlayReady DRM. This guide describes how other browsers can similarly enable Microsoft PlayReady DRM playback on Windows 8.1.

This information applies to the following operating systems:

  • Windows 8.1

Introduction

DRM in browsers

Browsers have been able to play DRM protected content for some time, most commonly by supporting a DRM enabled version of Adobe Flash or Microsoft Silverlight. These components were provided as browser plug-ins. They, and their underlying media platforms, served to standardize the media pipelines and provided playback for end users at no charge for the plug-in.

Plug-ins can limit which devices are compatible with web content, and this has encouraged expansions of HTML that allow browsers to directly support rich features with reduced need for plug-in components. A previous example was the addition of progressive playback of media content added in HTML5. This allowed browsers to play media files directly without the need for any media player plug-in. And now new specifications have defined HTML features that allow adaptive streaming playback of DRM protected media.

With the release in Windows 8.1, IE11 supports premium streaming extensions to HTML. These new extensions allow Internet Explorer to play premium video content from a variety of sources, and under a broad range of network and system constraints, without the use of browser plug-ins. The Windows 8.1 design uses Microsoft PlayReady DRM, and works in both the traditional desktop and new experience desktop browser versions.

Two W3C web specifications support this new capability in IE11 on Windows 8.1:

  • Media Source Extensions: This specification defines extensions to the HTMLMediaElement that support adaptive streaming. It allows JavaScript to dynamically construct streams for audio and video elements by appending segments to media sourceBuffer. JavaScript can achieve adaptive streaming by adjusting the quality level of these appended segments in response to a range of networking or media rendering bottlenecks.
  • Encrypted Media Extensions: This specification defines extensions to the HTMLMediaElement that support content protection systems. It allows the protection technologies supported by the browser to be identified, and defines methods for key exchanges that support playback of DRM protected media.

The combination of adaptive streaming and DRM playback capabilities in web browsers will allow premium media consumption experiences supported entirely by JavaScript issued from web servers, and potentially hosted by interoperable browser solutions that work on devices of all kinds.

IE11 supports Media Source Extensions and Encrypted Media Extensions for Microsoft PlayReady DRM. The purpose of this guide is to provide information that will allow other browsers to implement similar capability in browsers running on Windows 8.1.

Microsoft PlayReady DRM

Microsoft PlayReady is a Digital Rights Management (DRM) system that provides support for devices and computers. It supports this in several ways:

  • Microsoft PlayReady Porting Kit: Provides a readily deployable implementation and source code that allows Microsoft PlayReady client support on any device, regardless of operating system.
  • Microsoft PlayReady License Servers: Used to host license services necessary to issue licenses for DRM protected content playback.

There is also a Microsoft PlayReady PC software development kit (SDK) that provides a Windows desktop runtime for traditional Windows applications that have DRM capabilities. This SDK is still active, but is not the method used by IE11 to implement Microsoft PlayReady support.

With the new app model first released in Windows 8, a Microsoft PlayReady AppX Framework was also released. It supports app downloads from the Windows Store, and is staged along with other pre-installed apps so that it is part of the first run experience on Windows 8 and later powered systems.

IE11 in Windows 8.1 takes advantage of the staged Microsoft PlayReady framework. Though not a Windows component (it is developed and compiled in separate processes), it is available in all media enabled Windows SKUs and thus is available for new experience browsers running on Windows 8.1.

Encrypted Media Extensions CDM

The Encrypted Media Extensions (EME) specification defines a Content Decryption Model (CDM) that translate generic EME APIs into specific data exchanges that a specific DRM solution may require. This allows EME to be generalized, leaving the system specific aspects to the CDM.

The Microsoft PlayReady framework used by Windows 8.1 apps includes CDM functionality. And the Microsoft PlayReady Porting Kit for devices includes CDM interface support as well. Using the framework for Windows 8.1 systems and the CDM enabled porting kit for other devices allows Microsoft PlayReady to support browsers running on a wide variety of systems and devices.

The goal of this guide is to describe in detail just the Windows 8.1 aspect of this CDM support.

Implementation

Overview

Historically, apps that built on the Microsoft PlayReady SDK for Windows were responsible for licensing the technology, satisfying rigorous media pipeline requirements to ensure the media was protected once in decrypted form, and also had financial obligations associated with their Microsoft PlayReady license. The Microsoft PlayReady framework developed for Windows 8 (and now extended with EME/CDM support for Windows 8.1) offered strong advantages for apps that chose to use it:

  • The technology was already licensed: As such, no separate license was necessary. The apps would build on publicly documented APIs and ship Microsoft PlayReady enabled systems with no additional licensing.
  • The media pipeline was secured: The Microsoft PlayReady framework uses Microsoft Media Foundation implemented media services, and this pipeline was built and certified to meet DRM needs. Apps were free to use this pipeline with no additional certification (or re-certification on design changes) required.

The EME implementation in IE11 uses updated Media Foundation APIs built specifically for EME support. This is the implementation recommended for other browsers (both desktop and new experience) running on Windows 8.1 (and forward).

Technology Description
Implement browser MSE/EME APIs using MF New Media Foundation APIs map directly to APIs described in the W3C MSE and EME standards.
Attach the IMFMediaSourceExtension Object With MSE APIs mapped to their MF equivalents, the browser must attach an IMFMediaSourceExtension object to an element.
PlayReady AppX Framework The AppX Framework would normally be registered based on a dependency declared in an app manifest. For new experience desktop browsers, this is done automatically at first user login.
Support In Private Internet Explorer separates the Microsoft PlayReady license store for In Private use and deletes it when the In Private session is ended. This removes licenses that may have been stored during the In Private session.
Support Tab Suspension Tab Suspension separate tabs on new experience browsers into separate processes, and allows power management features in Microsoft WindowsWindows to manage which tabs remain active in background and which are suspended to improve the browser power profile. Tab Suspension has specific implementation requirements that browsers must meet to insure media experiences work properly.

 

Media Foundation APIs

To support Microsoft PlayReady EME, browsers must implement MSE and EME APIs onto their Media Foundation equivalents. Media Foundation APIs have been mapped directly to EME as shown in the following diagram:

The APIs mappings allow Microsoft Win32 Classic Windows applications to build directly on MSE/EME features, and allow third party browsers to implement them as well. The specific Media Foundation MediaEngine APIs that correspond to EME interfaces are listed in the following table:

The following table shows the APIs Mapping from MSE in JavaScript to Media Foundation MediaEngine in C++.

JavaScript (MSE) MFMediaEngine C++

[Constructor]

IMFMediaEngineClassFactoryEx::CreateMediaSourceExtension

MediaSource

IMFMediaSourceExtension

MediaSource.sourceBuffers

IMFMediaSourceExtension::GetSourceBuffers

MediaSource.activeSourceBuffers

IMFMediaSourceExtension::GetActiveSourceBuffers

MediaSource.readyState

IMFMediaSourceExtension::GetReadyState

MediaSource.duration

IMFMediaSourceExtension::GetDuration

IMFMediaSourceExtension::SetDuration

MediaSource.addSourceBuffer

IMFMediaSourceExtension::AddSourceBuffer

MediaSource.removeSourceBuffer

IMFMediaSourceExtension::RemoveSourceBuffer

MediaSource.endOfStream

IMFMediaSourceExtension::SetEndOfStream

MediaSource.isTypeSupported

IMFMediaSourceExtension::IsTypeSupported

SourceBuffer

IMFSourceBuffer

SourceBuffer.updating

IMFSourceBuffer::GetUpdating

SourceBuffer.buffered

IMFSourceBuffer::GetBuffered

SourceBuffer.timestampOffset

IMFSourceBuffer::GetTimeStampOffset

IMFSourceBuffer::SetTimeStampOffset

SourceBuffer.audioTracks

No equivalent in Media Foundation

SourceBuffer.appendWindowStart;

IMFSourceBuffer::GetAppendWindowStart

IMFSourceBuffer::SetAppendWindowStart

SourceBuffer.appendWindowEnd

IMFSourceBuffer::GetAppendWindowEnd

IMFSourceBuffer::SetAppendWindowEnd

SourceBuffer.appendBuffer(ArrayBuffer data)

IMFSourceBuffer::Append

SourceBuffer.appendBufferArrayBufferView data)

IMFSourceBuffer::Append

SourceBuffer.appendStream

IMFSourceBuffer::AppendByteStream

SourceBuffer.abort

IMFSourceBuffer::Abort

SourceBuffer.remove

IMFSourceBuffer::Remove

SourceBufferList

IMFSourceBufferList

SourceBufferList.length

IMFSourceBufferList::GetLength

getter SourceBuffer

IMFSourceBufferList::GetSourceBuffer

VideoPlaybackQuality

IMFMEdiaEngineEx::GetStatistics

VideoPlaybackQuality.creationTime

No Media Foundation equivalent

VideoPlaybackQuality.totalVideoFrames

MF_MEDIA_ENGINE_STATISTIC_FRAMES_RENDERED + MF_MEDIA_ENGINE_STATISTIC_FRAMES_DROPPED

These flags are defined in MF_MEDIA_ENGINE_STATISTIC

VideoPlaybackQuality.droppedVideoFrames

MF_MEDIA_ENGINE_STATISTIC_FRAMES_DROPPED

This flag is defined in MF_MEDIA_ENGINE_STATISTIC.

VideoPlaybackQuality.totalFrameDelay

MF_MEDIA_ENGINE_STATISTIC_TOTAL_FRAME_DELAY

This flag is defined in MF_MEDIA_ENGINE_STATISTIC.

DOMString URL.createObjectURL(MediaSource mediaSource)

No equivalent in Media Foundation

HTMLVideoElement .getVideoPlaybackQuality

See VideoPlaybackQuality notes above

AudioTrack.kind

No Media Foundation equivalent

AudioTrack.language

IMFMediaEngineEx::GetStreamAttribute

Note, pass MF_SD_LANGUAGE as the value for the guidMFAttribute parameter.

AudioTrack.sourceBuffer

IMFMediaSourceExtension::GetSourceBuffer

Events by target

MediaSource.sourceopen

IMFMediaSourceExtensionNotify

MediaSource.sourceended

IMFMediaSourceExtensionNotify::OnSourceEnded

MediaSource.sourceclose

IMFMediaSourceExtensionNotify::OnSourceClose

SourceBuffer.updatestart

IMFSourceBufferNotify::OnUpdateStart

SourceBuffer.update

IMFSourceBufferNotify::OnUpdate

SourceBuffer.updateend

IMFSourceBufferNotif::OnUpdateEnd

SourceBuffer.error

IMFSourceBufferNotify::OnError

SourceBuffer.abort

IMFSourceBufferNotify::OnAbort

SourceBufferList.addsourcebuffer

IMFBufferListNotify::OnAddSourceBuffer

SourceBufferList.removesourcebuffer

IMFBufferListNotify::OnRemoveSourceBuffer

 

The following table shows the APIs Mapping from EME in JavaScript to Media Foundation MediaEngine in C++.

JavaScript (MSE) MFMediaEngine C++

HTMLMediaElement.msKeys

IMFMediaEngineEME::get_Keys

HTMLMediaElement.msSetMediaKeys

IMFMediaEngineEME::SetMediaKeys

onmsneedkey

[Constructor]

IMFMediaEngineClassFactory2::CreateMediaKeys2

MSMediaKeys

IMFMediaKeys

MSMediaKeys.keySystem

IMFMediaKeys::get_KeySystem

MSMediaKeys.createSession

IMFMediaKeys::CreateSession

MSMediaKeys.isTypeSupported

IMFMediaEngineClassFactoryEx::IsTypeSupported

IMFMediaKeys::GetSuspendNotify

IMFMediaKeys::Shutdown

MediaKeySession

IMFMediaKeySession

MediaKeySession.error

IMFMediaKeySession::GetError

MediaKeySession.keySystem

IMFMediaKeySession::get_KeySystem

MediaKeySession.sessionId

IMFMediaKeySession::get_SessionId

MediaKeySession.update

IMFMediaKeySession::Update

MediaKeySession.close

IMFMediaKeySession::Close

HTMLSourceElement.keySystem

IMFMediaEngineSrcElementsEx::GetKeySystem

Event interface additions

MediaKeyMessageEvent

Equates to IMFMediaKeySessionNotify

MediaKeyMessageEvent.message

MediaKeyMessageEvent.destinationURL

MediaKeyNeededEvent

Equates to IMFMediaEngineNeedKeyNotify

MediaKeyNeededEvent.initData

Events

keyadded

IMFMediaKeySessionNotify::KeyAdded

keyerror

IMFMediaKeySessionNotify::KeyError

keymessage

IMFMediaKeySessionNotify::KeyMessage

msneedkey

IMFMediaEngineNeedKeyNotify::NeedKey

 

IMFMediaSourceExtension Object

With MSE APIs mapped to their Media Foundation equivalents, the browser must attach an IMFMediaSourceExtension object to an element. One approach to doing this is:

  1. Implement URL.createObjectURL (MediaSource mediaSource) per the W3C MSE standard.

  2. When a MediaSource object URL is set as a media element's source, pass the URL to Media Foundation through the IMFMediaEngine::SetSource method.

  3. When creating an instance of the media engine, pass in an object that implements IMFMediaEngineExtension by setting the MF_MEDIA_ENGINE_EXTENSION attribute on the IMFAttributes store that is passed to IMFMediaEngineClassFactory::CreateInstance.

  4. Implement IMFMediaEngineExtension such that calling BeginCreateObject with type=MF_OBJECT_MEDIASOURCE along with a MediaSource URL causes the associated IMFMediaSourceExtension instance to be asynchronously returned via the provided callback.

PlayReady AppX Framework

Four frameworks will be staged in Windows 8.1. There are pairs for x86 and amd64 variants. In addition, compatibility with Windows 8 Windows Store app required a specific version be maintained for them (under the family name Microsoft.Media.PlayReadyClient), and a new version provided with the added EME features.

The AppX PackageManager tracks app dependencies on AppX Frameworks. These are normally declared in the app manifest, but new experience browsers are built as desktop apps and don’t have a manifest option. They must take an explicit reference on the framework to notify the Package Manager that the framework has a desktop app that needs the framework installed. That insures that the Package Manager will keep the framework active even if all Windows 8 Windows Store app that need it have been removed.

AppX Frameworks are normally restricted to use by Windows Store app only. In Windows 8.1, the Microsoft PlayReady app package can be used by desktop or new experience desktop browsers. This happens automatically if the browser implements EME with Media Foundation APIs.

InPrivate browsing

IE11 deletes Microsoft PlayReady licenses acquired during In Private browsing sessions. This practice is recommended for other browsers that implement EME.

The new Microsoft PlayReady framework allows the app to specify the license store location (also called Hased Data Store or HDS) for any session. This default HDS is also specific to the app using the framework, so that licenses stored in it are isolated by app. The default HDS also includes Indiv data and any persistent licenses that may be acquired. For this reason, Microsoft recommends that it not be deleted.

IE11 uses the default HDS for normal EME sessions, and specifies a separate HDS for In Private browsing using the Microsoft PlayReady HDS path feature. That allows the In Private HDS to be deleted with no impact on Indiv data or persistent licenses.

Browsers can do the same thing using the optional cdmStorePath parameter of IMFMediaEngineClassFactory2::CreateMediaKeys2 to specify the directory path the Microsoft PlayReady CDM.

HRESULT CreateMediaKeys2(  
        [annotation("_In_")] BSTR keySystem,  
        [annotation("_In_")] BSTR defaultCdmStorePath,  
        [annotation("_In_opt_")] BSTR inprivateCdmStorePath,  
        [annotation("_COM_Outptr_")] IMFMediaKeys **ppKeys  
        );

Windows Internet Explorer deletes the entire cdmStorePath directory when the In Private session ends. This means that any persistent licenses stored during In Private are deleted.

Tab suspension

IE11 implements tab suspension to help minimize power consumption when users are using the browser.

Tab Suspension allows browser tabs to be separately managed for background operation. Using tab suspension, Windows can manage demands on CPU when browsers have many tabs open.

Some key systems require notification before being suspended, including Microsoft PlayReady. Before suspending a tab, browsers should perform the following steps for each unique key system running in the tab:

  1. Create a new Media Keys instance for the key system in the frame process.

  2. Call IMFMediaKeys::GetSuspendNotify to retrieve the key system’s suspend handler. The key system may return the HRESULTE_NOTIMPL when it does not need a suspend handler.

  3. Before suspending the tab, call IMFCdmSuspendNotify::Begin. If the suspend handler returns anything other than S_OK, abort the tab suspension and try again in a few minutes.

  4. After suspending the tab, call IMFCdmSuspendNotify::End.

  5. Release the suspend handler and media keys created by the frame process.