Поделиться через


Воспроизведение защищенных файлов мультимедиа

Защищенный файл мультимедиа — это любой файл мультимедиа, имеющий связанные правила для использования содержимого. В некоторых случаях защищенный файл мультимедиа шифруется с помощью шифрования цифрового управления правами (DRM). Чтобы воспроизвести защищенный файл мультимедиа, воспроизведение должно происходить внутри защищенного пути носителя (PMP). Кроме того, пользователю может потребоваться получить права на содержимое.

Термин получения прав ссылается на любое действие, которое приложение должно выполнить, прежде чем пользователь сможет воспроизвести содержимое. Наиболее распространенным примером является получение лицензии DRM, но Media Foundation определяет универсальный механизм, который может поддерживать другие типы приобретения прав. Интерфейс IMFContentEnabler определяет этот универсальный механизм.

Получение прав должно выполняться вне PMP, в ходе процесса подачи заявки. Сеанс мультимедиа уведомляет приложение через интерфейс IMFContentProtectionManager, который реализуется приложением. Медиа-сеанс использует интерфейс IMFContentProtectionManager для пересылки объекта активации контента в приложение. Контентные активаторы реализуют интерфейс IMFContentEnabler. Приложение использует этот интерфейс для получения необходимых прав.

Средство включения содержимого может поддерживать автоматическое получение прав, в этом случае средство включения содержимого реализует весь процесс, а приложение просто отслеживает состояние. В противном случае приложение должно использовать получение неумоляемых прав, что является процессом, в котором приложение отправляет данные HTTP POST в URL-адрес, предоставленный включенной функцией содержимого.

Чтобы воспроизвести защищенный носитель, приложение выполняет те же действия, описанные в разделе Воспроизведение файлов мультимедиа с помощью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 в хранилище атрибутов. Значение этого атрибута — это указатель на реализацию МВФContentProtectionManagerприложения. Вызовите 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. Используйте этот интерфейс для получения событий из объекта средства включения содержимого. Дополнительные сведения о событиях см. в разделе Генераторы событий мультимедиа.

Чтобы узнать, поддерживает ли модуль включения содержимого автоматическое приобретение, вызовите IMFContentEnabler::IsAutomaticSupported. Если этот метод возвращает значение TRUE, приложение должно использовать автоматическое приобретение. В противном случае используйте явные приобретения.

Метод BeginEnableContent является асинхронным. Приложение должно осуществить шаг приобретения в потоке приложения. Одним из способов является публикация сообщения частного окна в главном окне приложения, уведомляя поток приложения о получении. Пока операция находится в ожидании, приложение должно хранить указатель обратного вызова и объект состояния, полученные в параметрах pCallback и punkState функции BeginEnableContent. Они будут использоваться для выполнения асинхронной операции.

Автоматическое приобретение

Чтобы выполнить автоматическое включение, вызовите IMFContentEnabler::AutomaticEnable. Этот метод является асинхронным. После завершения операции включение содержимого отправляет событие MEEnablerCompleted. Код состояния события указывает, выполнена ли операция успешно. Если код состояния в событии MEEnablerCompleted равен NS_E_DRM_LICENSE_NOTACQUIRED, приложению следует попытаться использовать небеззвучное приобретение.

В процессе выполнения операции приобретения объект активатора может отправлять событие 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. Отправьте данные в URL-адрес приобретения прав с помощью действия HTTP POST. Вы можете использовать элемент управления Internet Explorer или API Windows Internet (WinINet).

В следующем коде показаны шаги 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. Сеанс мультимедиа вызовет IMF ContentProtectionManager::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);

мультимедийная сессия

воспроизведение звука и видео