PlayReady の Encrypted Media Extension

このセクションでは、以前の Windows 8.1 バージョンから Windows 10 バージョンへの変更をサポートするように PlayReady Web アプリを変更する方法について説明します。

Internet Explorer で PlayReady メディア要素を使用すると、開発者は、コンテンツ プロバイダーによって定義されたアクセス 規則を適用しながら、ユーザーに PlayReady コンテンツを提供できる Web アプリを作成できます。 このセクションでは、HTML5 と JavaScript のみを使用して、PlayReady メディア要素を既存の Web アプリに追加する方法について説明します。

PlayReady Encrypted Media Extension の新機能

このセクションでは、Windows 10 で PlayReady コンテンツ保護を有効にするために PlayReady Encrypted Media Extension (EME) に加えられた変更の一覧を示します。

次の一覧では、Windows 10 用 PlayReady Encrypted Media Extension に加えられた新機能と変更について説明します。

  • ハードウェア デジタル著作権管理 (DRM) を追加しました。

    ハードウェア ベースのコンテンツ保護のサポートにより、複数のデバイス プラットフォームで高解像度 (HD) コンテンツと Ultra High Definition (UHD) コンテンツを安全に再生できます。 キー マテリアル (秘密キー、コンテンツ キー、これらのキーを派生またはロック解除するために使われるその他のキー マテリアルを含みます)、および暗号化解除された圧縮および非圧縮ビデオ サンプルは、ハードウェア セキュリティを利用して保護されます。

  • 非永続的ライセンスのプロアクティブな取得を提供します。

  • 1 つのメッセージで複数のライセンスの取得を提供します。

    Windows 8.1 と同様に、複数のキー識別子 (KeyID) を持つ PlayReady オブジェクトを使用するか、複数の KeyID で 暗号化解除モデル データ (CDMData) を使用できます。

    Note

    Windows 10 では、CDMData の <KeyID> で複数のキー識別子がサポートされています。

  • リアルタイム有効期限のサポート、または期間限定ライセンス (LDL) を追加しました。

    ライセンスに対してリアルタイムの有効期限を設定する機能を提供します。

  • HDCP Type 1 (バージョン 2.2) ポリシーのサポートを追加しました。

  • Miracast が出力として暗黙的になりました。

  • セキュリティで保護された停止を追加しました。

    セキュア ストップは、PlayReady デバイスが、特定のコンテンツに対してメディア再生が停止したメディア ストリーミング サービスに自信を持ってアサートするための手段を提供します。

  • オーディオとビデオのライセンスの分離を追加しました。

    別々のトラックは、ビデオがオーディオとしてデコードされることを防ぎます。より堅牢なコンテンツ保護を実現します。 新しい標準では、オーディオ トラックとビジュアル トラックに個別のキーが必要です。

  • MaxResDecode を追加しました。

    この機能は、(ライセンスではなく) より能力の高いキーを所有している場合でも、コンテンツの再生を最大解像度に制限するために追加されました。 複数のストリーム サイズが 1 つのキーでエンコードされる場合をサポートします。

PlayReady での暗号化されたメディア拡張機能のサポート

このセクションでは、PlayReady でサポートされる W3C Encrypted Media Extension のバージョンについて説明します。

PlayReady for Web Apps は現在、2013 年 5 月 10 日の W3C Encrypted Media Extension (EME) ドラフトにバインド。 このサポートは、今後のバージョンの Windows で更新された EME 仕様に変更される予定です。

ハードウェア DRM を使用する

このセクションでは、Web アプリで PlayReady ハードウェア DRM を使用する方法と、保護されたコンテンツでサポートされていない場合にハードウェア DRM を無効にする方法について説明します。

PlayReady ハードウェア DRM を使用するには、JavaScript Web アプリで isTypeSupported EME メソッドを使用し、 com.microsoft.playready.hardware の主要なシステム識別子を使用して、ブラウザーから PlayReady ハードウェア DRM のサポートを照会する必要があります。

場合によっては、一部のコンテンツがハードウェア DRM でサポートされていません。 カクテル コンテンツはハードウェア DRM ではサポートされません。カクテル コンテンツを再生する場合は、ハードウェア DRM をオプトアウトする必要があります。 一部のハードウェア DRM は HEVC をサポートし、一部はサポートしません。HEVC コンテンツを再生する必要があり、ハードウェア DRM でサポートされていない場合は、オプトアウトすることもできます。

Note

HEVC コンテンツがサポートされているかどうかを確認するには、 com.microsoft.playreadyをインスタンス化した後、 PlayReadyStatics.CheckSupportedHardware メソッドを使用します。

Web アプリにセキュア ストップを追加する

このセクションでは、Web アプリにセキュア ストップを追加する方法について説明します。

セキュア ストップは、PlayReady デバイスが、特定のコンテンツに対してメディア再生が停止したメディア ストリーミング サービスに自信を持ってアサートするための手段を提供します。 この機能により、メディア ストリーミング サービスは、特定のアカウントの異なるデバイスに対する使用制限の正確な適用とレポートを提供します。

セキュリティで保護された停止チャレンジを送信する主なシナリオは 2 つあります。

  • コンテンツの終了に達したためにメディア プレゼンテーションが停止したとき、またはユーザーが中央のどこかでメディア プレゼンテーションを停止したとき。
  • 前のセッションが予期せず終了したとき (システムやアプリのクラッシュなど)。 アプリは、起動時またはシャットダウン時に、未処理のセキュア ストップ セッションに対してクエリを実行し、他のメディア再生とは別にチャレンジを送信する必要があります。

次の手順では、さまざまなシナリオでセキュア ストップを設定する方法について説明します。

プレゼンテーションの通常の終了に対してセキュア ストップを設定するには:

  1. 再生を開始する前に、 onEnded イベントを登録します。
  2. onEnded イベント ハンドラーは、ビデオ/オーディオ要素オブジェクトからremoveAttribute("src")を呼び出してソースを NULL に設定する必要があります。これはメディア基盤がトポロジを破棄し、復号化を破棄し、停止状態を設定します。
  3. ハンドラー内でセキュアストップ CDM セッションを開始して、この時点で再生が停止したことを通知するセキュアストップチャレンジをサーバーに送信することもできますが、後で実行することもできます。

ユーザーがページから移動するか、タブまたはブラウザーを閉じた場合にセキュア ストップを設定するには:

  • 停止状態を記録するためにアプリアクションは必要ありません。記録されます。

カスタム ページ コントロールまたはユーザー アクション (カスタム ナビゲーション ボタン、現在のプレゼンテーションが完了する前に新しいプレゼンテーションを開始するなど) の安全な停止を設定するには:

  • カスタム ユーザー アクションが発生した場合、アプリはソースを NULL に設定する必要があります。これによって メディア基盤がトポロジの破棄、復号化の破棄、停止状態の設定をトリガーします。

次の例は、Web アプリで Secure Stop を使用する方法を示しています。

// JavaScript source code

var g_prkey = null;
var g_keySession = null;
var g_fUseSpecificSecureStopSessionID = false;
var g_encodedMeteringCert = 'Base64 encoded of your metering cert (aka publisher cert)';

// Note: g_encodedLASessionId is the CDM session ID of the proactive or reactive license acquisition 
//       that we want to initiate the secure stop process.
var g_encodedLASessionId = null;

function main()
{
    ...

    g_prkey = new MSMediaKeys("com.microsoft.playready");

    ...

    // add 'onended' event handler to the video element
    // Assume 'myvideo' is the ID of the video element
    var videoElement = document.getElementById("myvideo");
    videoElement.onended = function (e) { 

        //
        // Calling removeAttribute("src") will set the source to null
        // which will trigger the MF to tear down the topology, destroy the
        // decryptor(s) and set the stop state.  This is required in order
        // to set the stop state.
        //
        videoElement.removeAttribute("src");
        videoElement.load();

        onEndOfStream();
    };
}

function onEndOfStream()
{
    ...

    createSecureStopCDMSession();

    ...    
}

function createSecureStopCDMSession()
{
    try{    
        var targetMediaCodec = "video/mp4";
        var customData = "my custom data";

        var encodedSessionId = g_encodedLASessionId;
        if( !g_fUseSpecificSecureStopSessionID )
        {
            // Use "*" (wildcard) as the session ID to include all secure stop sessions
            // TODO: base64 encode "*" and place encoded result to encodedSessionId
        }

        var int8ArrayCDMdata = formatSecureStopCDMData( encodedSessionId, customData,  g_encodedMeteringCert );
        var emptyArrayofInitData = new Uint8Array();

        g_keySession = g_prkey.createSession(targetMediaCodec, emptyArrayofInitData, int8ArrayCDMdata);

        addPlayreadyKeyEventHandler();

    } catch( e )
    {
        // TODO: Handle exception
    }
}

function addPlayreadyKeyEventHandler()
{
    // add 'keymessage' eventhandler   
    g_keySession.addEventListener('mskeymessage', function (event) {

        // TODO: Get the keyMessage from event.message.buffer which contains the secure stop challenge
        //       The keyMessage format for the secure stop is similar to LA as below:
        //
        //            <PlayReadyKeyMessage type="SecureStop" >
        //              <SecureStop version="1.0" >
        //                <Challenge encoding="base64encoded">
        //                    secure stop challenge
        //                </Challenge>
        //                <HttpHeaders>
        //                    <HttpHeader>
        //                      <name>Content-Type</name>
        //                         <value>"content type data"</value>
        //                    </HttpHeader>
        //                    <HttpHeader>
        //                         <name>SOAPAction</name>
        //                         <value>soap action</value>
        //                     </HttpHeader>
        //                    ....
        //                </HttpHeaders>
        //              </SecureStop>
        //            </PlayReadyKeyMessage>
                
        // TODO: send the secure stop challenge to a server that handles the secure stop challenge

        // TODO: Receive and response and call event.target.Update() to process the response
    });
    
    // add 'keyerror' eventhandler
    g_keySession.addEventListener('mskeyerror', function (event) {
        var session = event.target;
        
        ...

        session.close();
    });
    
    // add 'keyadded' eventhandler
    g_keySession.addEventListener('mskeyadded', function (event) {
        
        var session = event.target;

        ...

        session.close();             
    });
}

/**
* desc@ formatSecureStopCDMData
*   generate playready CDMData
*   CDMData is in xml format:
*   <PlayReadyCDMData type="SecureStop">
*     <SecureStop version="1.0">
*       <SessionID>B64 encoded session ID</SessionID>
*       <CustomData>B64 encoded custom data</CustomData>
*       <ServerCert>B64 encoded server cert</ServerCert>
*     </SecureCert>
* </PlayReadyCDMData>        
*/
function formatSecureStopCDMData(encodedSessionId, customData, encodedPublisherCert) 
{
    var encodedCustomData = null;

    // TODO: base64 encode the custom data and place the encoded result to encodedCustomData

    var CDMDataStr = "<PlayReadyCDMData type=\"SecureStop\">" +
                     "<SecureStop version=\"1.0\" >" +
                     "<SessionID>" + encodedSessionId + "</SessionID>" +
                     "<CustomData>" + encodedCustomData + "</CustomData>" +
                     "<ServerCert>" + encodedPublisherCert + "</ServerCert>" +
                     "</SecureStop></PlayReadyCDMData>";
    
    var int8ArrayCDMdata = null

    // TODO: Convert CDMDataStr to Uint8 byte array and palce the converted result to int8ArrayCDMdata

    return int8ArrayCDMdata;
}

Note

前のセキュア ストップのデータの <SessionID>B64 encoded session ID</SessionID> は、アスタリスク (*) にすることができます。これは、記録されたすべてのセキュア ストップ セッション用のワイルドカードです。 つまり、SessionID タグは特定のセッションにするか、すべてのセキュア ストップ セッションを選択するワイルドカード (*) にすることができます。

暗号化メディア拡張機能のプログラミングに関する考慮事項

このセクションでは、Windows 10 用 PlayReady 対応 Web アプリを作成するときに考慮する必要があるプログラミング上の考慮事項を示します。

アプリによって作成されたMSMediaKeysMSMediaKeySession オブジェクトは、アプリが閉じるまで存続する必要があります。 これらのオブジェクトを確実に有効に保つ方法の 1 つは、グローバル変数として割り当てることです (変数はスコープ外になり、関数内でローカル変数として宣言されている場合はガベージ コレクションの対象になります)。 次の例では、変数 g_msMediaKeysg_mediaKeySession をグローバル変数として割り当てています。これらの変数は、関数内で MSMediaKeys オブジェクトと MSMediaKeySession オブジェクトに割り当てられます。

var g_msMediaKeys;
var g_mediaKeySession;

function foo() {
  ...
  g_msMediaKeys = new MSMediaKeys("com.microsoft.playready");
  ...
  g_mediaKeySession = g_msMediaKeys.createSession("video/mp4", intiData, null);
  g_mediaKeySession.addEventListener(this.KEYMESSAGE_EVENT, function (e) 
  {
    ...
    downloadPlayReadyKey(url, keyMessage, function (data) 
    {
      g_mediaKeySession.update(data);
    });
  });
  g_mediaKeySession.addEventListener(this.KEYADDED_EVENT, function () 
  {
    ...
    g_mediaKeySession.close();
    g_mediaKeySession = null;
  });
}

詳細については、 サンプル アプリケーションを参照してください。

関連項目