保護されたメディア ファイルを再生する方法

保護されたメディア ファイルは、コンテンツを使用するための規則が関連付けられているすべてのメディア ファイルです。 場合によっては、保護されたメディア ファイルが何らかの形式のデジタル著作権管理 (DRM) 暗号化を使用して暗号化されます。 保護されたメディア ファイルを再生するには、保護されたメディア パス (PMP) 内で再生を行う必要があります。 さらに、ユーザーはコンテンツに対する権限を取得する必要がある場合があります。

権利の取得という用語は、ユーザーがコンテンツを再生する前にアプリケーションが実行する必要があるアクションを指します。 最も一般的な例は DRM ライセンスの取得ですが、Media Foundation では、他の種類の権利取得をサポートできる汎用的なメカニズムが定義されています。 IMFContentEnabler インターフェイスは、この汎用メカニズムを定義します。

権利の取得は、アプリケーション プロセスから PMP の外部で行う必要があります。 メディア セッションは、アプリケーションによって実装される IMFContentProtectionManager インターフェイスを介してアプリケーションに通知します。 メディア セッションでは、 IMFContentProtectionManager インターフェイスを使用して、コンテンツ イネーブラー オブジェクトをアプリケーションに転送します。 コンテンツ イネーブラーは、 IMFContentEnabler インターフェイスを 実装します。 アプリケーションはこのインターフェイスを使用して、必要な権限を取得します。

コンテンツ イネーブラーは、自動権利取得をサポートする場合があります。この場合、コンテンツ イネーブラーはプロセス全体を実装し、アプリケーションは単に状態を監視します。 それ以外の場合、アプリケーションは非サイレント権限の取得を使用する必要があります。これは、アプリケーションがコンテンツ イネーブラーによって提供される URL に HTTP POST データを送信するプロセスです。

保護されたメディアを再生するには、Media Foundation でメディア ファイルを再生する方法に関するトピックで説明されているのと同じ手順に従い、次の追加手順を実行します。

  1. メディア ソースに保護されたコンテンツが含まれているかどうかをクエリします。 (省略可能)
  2. アプリケーション プロセスではなく、PMP プロセスでメディア セッションを作成します。
  3. メディア セッションによって通知された場合は、権利の取得を実行します。 この操作は、アプリケーションによって非同期的に実行されます。
  4. 非同期操作を完了します。

保護されたコンテンツのクエリ

メディア ソースに保護されたコンテンツが含まれているかどうかを照会するには、メディア ソースのプレゼンテーション記述子で MFRequireProtectedEnvironment 関数を呼び出します。 関数がS_OKを返す場合は、PMP を使用してコンテンツを再生する必要があります。 関数がS_FALSEを返す場合、PMP は不要であり、アプリケーション プロセスでメディア セッションを作成できます。 または、PMP を使用して、保護されたコンテンツと保護されていないコンテンツの両方を再生することもできます。 その場合は、 MFRequireProtectedEnvironment を呼び出す必要はありません。

プレゼンテーション記述子の詳細については、「 プレゼンテーション記述子」を参照してください。

PMP メディア セッションを作成する

PMP でメディア セッションを作成するには、 MFCreatePMPMediaSession を呼び出します。 この関数は MFCreateMediaSession に似ていますが、アプリケーションのプロセスでメディア セッションを作成する代わりに、PMP プロセスでメディア セッションを作成します。 アプリケーションは、メディア セッションのプロキシ オブジェクトへのポインターを受け取ります。 アプリケーションは、メディア セッションと同様に、プロキシ オブジェクトで IMFMediaSession メソッドを呼び出します。 プロキシ オブジェクトは、プロセス境界を越えてメディア セッションへの呼び出しを転送します。

次のように PMP メディア セッションを作成します。

  1. MFCreateAttributes を呼び出して、新しい属性ストアを作成します。
  2. 属性ストアに MF_SESSION_CONTENT_PROTECTION_MANAGER 属性を設定します。 この属性の値は、アプリケーションによる IMFContentProtectionManager の実装へのポインターです。 IMFAttributes::SetUnknown を呼び出して、 属性を設定します。
  3. MFCreatePMPMediaSession を呼び出して、PMP プロセスでメディア セッションを作成します。 pConfiguration パラメーターは、属性ストアの IMFAttributes インターフェイスへのポインターです。
IMFAttributes *pAttributes = NULL;
IMFMediaSession *pSession = NULL;

// Create the attribute store.
hr = MFCreateAttributes(&pAttributes, 1);

// Set the IMFContentProtectionManager pointer.
if (SUCCEEDED(hr))
{
    hr = pAttributes->SetUnknown(
        MF_SESSION_CONTENT_PROTECTION_MANAGER, 
        pCPM  // Your implementation of IMFContentProtectionManager.
        );
}

// Create the Media Session.
if (SUCCEEDED(hr))
{
    hr = MFCreatePMPMediaSession(
        0,
        pAttributes, 
        &pSession,
        NULL
    );
}

SAFE_RELEASE(pAttributes); // Release the attribute store.
// Use the Media Session to control playback (not shown).

次に、「再生トポロジの作成」で説明されているように、 再生トポロジを作成し、メディア セッションでキューに入れます。

権利取得の実行

再生に権限の取得が必要な場合、メディア セッションは IMFContentProtectionManager::BeginEnableContent を呼び出します。 このメソッドの pEnablerActivate パラメーターは、 IMFActivate インターフェイスへのポインターです。 このインターフェイスを使用して、 IMFContentEnabler インターフェイスを公開するコンテンツ イネーブラー オブジェクトを作成します。 次に、コンテンツ イネーブラーを使用して、権利取得手順を実行します。

コンテンツ イネーブラーを作成するには、 IMFActivate::ActivateObject を呼び出します。

IMFContentEnabler *pEnabler = NULL;
hr = pEnablerActivate->ActivateObject(
    IID_IMFContentEnabler, 
    (void**)&pEnabler
    );

返された IMFContentEnabler ポインターに対して 、IMFMediaEventGenerator インターフェイスのクエリを実行します。 コンテンツ イネーブラー オブジェクトからイベントを取得するには、このインターフェイスを使用します。 イベントの詳細については、「 Media Event Generators」を参照してください。

コンテンツ イネーブラーが自動取得をサポートしているかどうかを確認するには、 IMFContentEnabler::IsAutomaticSupported を呼び出します。 このメソッドが 値 TRUE を返す場合、アプリケーションは自動取得を使用する必要があります。 それ以外の場合は、サイレントではない取得を使用します。

BeginEnableContent メソッドは非同期です。 アプリケーションは、アプリケーションのスレッドで取得手順を実行する必要があります。 1 つの方法は、プライベート ウィンドウ メッセージをアプリケーションのメイン ウィンドウに投稿し、取得を実行するようにアプリケーション スレッドに通知することです。 操作が保留中の間、アプリケーションは、BeginEnableContentpCallback パラメーターと punkState パラメーターで受け取ったコールバック ポインターと状態オブジェクトを格納する必要があります。 これらは非同期操作を完了するために使用されます。

自動取得

自動取得を実行するには、 IMFContentEnabler::AutomaticEnable を呼び出します。 このメソッドは非同期です。 操作が完了すると、コンテンツ イネーブラーは MEEnablerCompleted イベントを送信します。 イベントの状態コードは、操作が成功したかどうかを示します。 MEEnablerCompleted イベントの状態コードがNS_E_DRM_LICENSE_NOTACQUIRED場合、アプリケーションは非サイレント取得の使用を試みる必要があります。

取得操作の進行中に、enabler オブジェクトから MEEnablerProgress イベントが送信され、操作の進行状況が示される場合があります。 操作を取り消すには、 IMFContentEnabler::Cancel を呼び出します。

非サイレント取得

IsAutomaticSupported メソッドが FALSE を返す場合、または AutomaticEnable メソッドがエラー コード NS_E_DRM_LICENSE_NOTACQUIREDで失敗した場合、アプリケーションは次の手順で説明するように、非サイレント取得を実行する必要があります。

  1. IMFContentEnabler::GetEnableURL を呼び出して、権利取得の URL を取得します。 このメソッドは、URL が信頼されているかどうかを示すフラグも返します。

  2. IMFContentEnabler::GetEnableData を呼び出して HTTP POST データを取得します。

  3. IMFContentEnabler::MonitorEnable を呼び出します。 このメソッドにより、コンテンツ イネーブラーは権利取得アクションの進行状況を監視します。

  4. HTTP POST アクションを使用して、権限取得 URL にデータを送信します。 インターネット エクスプローラー コントロールまたは Windows インターネット (WinINet) API を使用できます。

次のコードは、手順 1 から 3 を示しています。 手順 4 は、アプリケーションの特定の要件によって異なります。

WCHAR   *sURL = NULL;  // URL.
DWORD   cchURL = 0;    // Size of the URL in characters.

// Trust status of the URL.
MF_URL_TRUST_STATUS  trustStatus = MF_LICENSE_URL_UNTRUSTED;

BYTE    *pPostData = NULL;  // Buffer to hold HTTP POST data.
DWORD   cbPostDataSize = 0; // Size of the buffer, in bytes.

HRESULT hr = S_OK;

// Get the URL. 
hr = m_pEnabler->GetEnableURL(&sURL, &cchURL, &trustStatus);

if (SUCCEEDED(hr))
{
    if (trustStatus != MF_LICENSE_URL_TRUSTED)
    {
        // The URL is not trusted. Do not proceed.
        hr = E_FAIL;
    }
}

// Monitor the rights acquisition. 
if (SUCCEEDED(hr))
{
    hr = m_pEnabler->MonitorEnable();
}

// Get the HTTP POST data.
if (SUCCEEDED(hr))
{
    hr = m_pEnabler->GetEnableData(&pPostData, &cbPostDataSize);
}

// Open the URL and send the HTTP POST data. (Not shown.)

// Release the buffers.
CoTaskMemFree(pPostData);
CoTaskMemFree(sURL);

操作が完了すると、コンテンツ イネーブラーは MEEnablerCompleted イベントを送信します。

非同期操作を完了する

権限の取得が正常に完了した場合、またはそれ以外の場合は、 BeginEnableContent メソッドで指定されたコールバック ポインターを呼び出して、アプリケーションがメディア セッションに通知する必要があります。

  1. MFCreateAsyncResult を呼び出して非同期の結果オブジェクトを作成します。
  2. MFInvokeCallback を呼び出して、メディア セッションのコールバックを呼び出します。
  3. メディア セッションでは、 IMFContentProtectionManager::EndEnableContent が呼び出されます。 このメソッドの実装では、 BeginEnableContent 内で割り当てたポインターまたはリソースを解放します。 操作の全体的な成功を示す HRESULT を返します。 権限の取得に失敗した場合、またはユーザーが完了する前に取り消した場合は、エラー コードを返します。

次のコードは、非同期の結果を作成し、コールバックを呼び出す方法を示しています。

IMFAsyncResult  *pResult = NULL;

// Create the asynchronous result object.
hr = MFCreateAsyncResult(NULL, pCallback, punkState, &pResult);

// Invoke the callback.
if (SUCCEEDED(hr))
{
    pResult->SetStatus(hrStatus);
    hr = MFInvokeCallback(pResult);
}
SAFE_RELEASE(pResult);

メディア セッション

オーディオ/ビデオの再生