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


Чтение файлов ASF DRM-Protected в DirectShow

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует, чтобы новый код использовал MediaPlayer, IMFMediaEngine и аудио- и видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, использующий устаревшие API, чтобы по возможности использовать новые API.]

В этом разделе описывается использование DirectShow для воспроизведения файлов мультимедиа, защищенных с помощью Управления цифровыми правами Windows Media (DRM).

Основные понятия DRM

Защита файла мультимедиа с помощью WINDOWS Media DRM состоит из двух этапов:

  • Поставщик содержимого упаковывает файл, то есть шифрует файл и присоединяет сведения о лицензировании к заголовку ФАЙЛА ASF. Сведения о лицензировании содержат URL-адрес, по которому клиент может получить лицензию.
  • Клиентское приложение получает лицензию на содержимое.

Упаковка выполняется перед распространением файла. Получение лицензии происходит, когда пользователь пытается воспроизвести или скопировать файл. Получение лицензии может быть как автоматическим , так и не молчаливым. Автоматическое получение не требует взаимодействия с пользователем. Для автоматического приобретения приложение должно открыть окно браузера и отобразить веб-страницу для пользователя. На этом этапе пользователю может потребоваться предоставить поставщику содержимого какие-либо сведения. Однако оба типа получения лицензий требуют от клиента отправки HTTP-запроса на сервер лицензирования.

Версии DRM

Существует несколько версий WINDOWS Media DRM. С точки зрения клиентского приложения их можно сгруппировать в две категории: DRM версии 1 и DRM версии 7 или более поздней. (Вторая категория включает DRM версий 9 и 10, а также версии 7.) Причина такого классификации версий DRM заключается в том, что лицензии версии 1 обрабатываются несколько иначе, чем лицензии версии 7 или более поздних версий. В этой документации термин лицензия версии 7 означает версию 7 или более позднюю.

Кроме того, важно отличать упаковку DRM от лицензии DRM. Если файл упаковано с помощью Windows Media Rights Manager версии 7 или более поздней, заголовок DRM может содержать URL-адрес лицензии версии 1 в дополнение к URL-адресу лицензии версии 7. URL-адрес лицензии версии 1 позволяет старым игрокам, которые не поддерживают версию 7, получить лицензию на содержимое. Однако обратное не соответствует действительности, поэтому файл с упаковкой версии 1 не может иметь URL-адрес лицензии версии 7.

Уровень безопасности приложения

Для воспроизведения файлов, защищенных DRM, клиентское приложение должно быть связано со статической библиотекой, предоставляемой корпорацией Майкрософт в двоичной форме. Эту библиотеку, которая однозначно идентифицирует приложение, иногда называют библиотекой заглушки. Библиотеке заглушки назначен уровень безопасности, значение которого определяется лицензионным соглашением, подписанным при получении библиотеки заглушки.

Поставщик содержимого задает минимальный уровень безопасности, необходимый для получения лицензии. Если уровень безопасности библиотеки заглушки меньше минимального уровня безопасности, требуемого сервером лицензирования, приложение не может получить лицензию.

Индивидуализации

Чтобы повысить безопасность, приложение может обновить компоненты DRM на компьютере клиента. Это обновление, называемое индивидуализацией, отличает копию приложения пользователя от всех остальных копий того же приложения. Заголовок DRM защищенного файла может указывать минимальный уровень индивидуализации. (Дополнительные сведения см. в документации по WMRMHeader.IndividualizedVersion в пакете SDK windows Media Rights Manager.)

Служба индивидуализации Майкрософт обрабатывает сведения от пользователя. Поэтому перед индивидуализацией приложения необходимо отобразить Заявление о конфиденциальности Майкрософт или указать ссылку на него (см. заявление о конфиденциальности Майкрософт).

Укажите сертификат программного обеспечения

Чтобы разрешить приложению использовать лицензию DRM, приложение должно предоставить сертификат программного обеспечения или ключ для диспетчера фильтров Graph. Этот ключ содержится в статической библиотеке, которая индивидуализирована для приложения. Сведения о получении индивидуализированной библиотеки см. в разделе Получение обязательной библиотеки DRM в документации по пакету SDK для формата Windows Media.

Чтобы предоставить программный ключ, выполните следующие действия.

  1. Ссылка на статическую библиотеку.
  2. Реализуйте интерфейс IServiceProvider .
  3. Запросите к диспетчеру графов фильтров интерфейс IObjectWithSite .
  4. Вызовите IObjectWithSite::SetSite с указателем на реализацию IServiceProvider.
  5. Диспетчер графа фильтров вызовет IServiceProvider::QueryService, указав IID_IWMReader для идентификатора службы.
  6. В реализации QueryService вызовите WMCreateCertificate , чтобы создать программный ключ.

В следующем коде показано, как реализовать метод QueryService :

STDMETHODIMP Player::QueryService(REFIID siid, REFIID riid, void **ppv)
{
    if (ppv == NULL ) 
    { 
        return E_POINTER; 
    }

    if (siid == __uuidof(IWMReader) && riid == __uuidof(IUnknown))
    {
        IUnknown *punkCert;

        HRESULT hr = WMCreateCertificate(&punkCert);

        if (SUCCEEDED(hr))
        {
            *ppv = (void *) punkCert;
        }

        return hr;
    }
    return E_NOINTERFACE;
}

В следующем коде показано, как вызвать SetSite в диспетчере graph filter:

HRESULT Player::CreateFilterGraph()
{
    CComPtr<IObjectWithSite> pSite;

    HRESULT hr = pGraph.CoCreateInstance(CLSID_FilterGraph);

    if (FAILED(hr))
    {
        goto done;
    }

    // Register the application as a site (service).
    hr = pGraph->QueryInterface(&pSite);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pSite->SetSite(this);


done:
    return hr;
}

Создание графа воспроизведения

Чтобы воспроизвести ASF-файл с защитой DRM, выполните следующие действия.

  1. Создайте диспетчер фильтров графов и используйте интерфейс IMediaEventEx для регистрации событий графа.
  2. Вызовите CoCreateInstance , чтобы создать новый экземпляр фильтра читателя WM ASF .
  3. Вызовите метод IFilterGraph::AddFilter , чтобы добавить фильтр в граф фильтра.
  4. Запросите фильтр для интерфейса IFileSourceFilter .
  5. Вызовите IFileSourceFilter::Load с URL-адресом файла.
  6. Обработка событий EC_WMT_EVENT .
  7. В первом событии EC_WMT_EVENT запросите фильтр читателя WM ASF для интерфейса IServiceProvider .
  8. Вызовите IServiceProvider::QueryService , чтобы получить указатель на интерфейс IWMDRMReader .
  9. Вызовите IGraphBuilder::Render , чтобы отобразить выходные контакты фильтра средства чтения WM ASF .

Примечание

При открытии файла с защитой DRM не вызывайте IGraphBuilder::RenderFile для создания графа фильтра. Фильтр средства чтения WM ASF не может подключиться к другим фильтрам, пока не будет получена лицензия DRM. На этом шаге требуется, чтобы приложение использовало интерфейс IWMDRMReader , который должен быть получен из фильтра, как описано в шагах 7–8. Поэтому необходимо создать фильтр и добавить его в граф.

 

Примечание

Важно зарегистрироваться для событий графа (шаг 1) перед добавлением фильтра средства чтения WM ASF в граф (шаг 3), так как приложение должно обрабатывать события EC_WMT_EVENT . События отправляются при вызове load (шаг 5).

 

В следующем коде показано, как создать граф:

HRESULT Player::LoadMediaFile(PCWSTR pwszFile)
{


    BOOL bIsWindowsMediaFile = IsWindowsMediaFile(pwszFile);

    HRESULT hr = S_OK;

    // If this is the first time opening the file, create the
    // filter graph and add the WM ASF Reader filter.

    if (m_DRM.State() == DRM_INITIAL)
    {
        hr = CreateFilterGraph();
        if (FAILED(hr))
        {
            goto done;
        }

        // Use special handling for Windows Media files.
        if (bIsWindowsMediaFile)
        {
            // Add the ASF Reader filter to the graph.
            hr = m_pReader.CoCreateInstance(CLSID_WMAsfReader);
            if (FAILED(hr))
            {
                goto done;
            }

            hr = pGraph->AddFilter(m_pReader, NULL);
            if (FAILED(hr))
            {
                goto done;
            }

            hr = m_pReader->QueryInterface(&m_pFileSource);
            if (FAILED(hr))
            {
                goto done;
            }
        }
    }

    if (bIsWindowsMediaFile)
    {
            hr = m_pFileSource->Load(pwszFile, NULL);
C++
            if (FAILED(hr))            {                goto done;            }            hr = RenderOutputPins(pGraph, m_pReader);    }    else    {        // Not a Windows Media file, so just render the standard way.        hr = pGraph->RenderFile(pwszFile, NULL);    }done:    return hr;}

В предыдущем коде RenderOutputPins функция перечисляет выходные контакты в фильтре средства чтения WM ASF и вызывает IGraphBuilder::Render для каждого закрепления.

HRESULT RenderOutputPins(IGraphBuilder *pGraph, IBaseFilter *pFilter)
{
    CComPtr<IEnumPins>  pEnumPin = NULL;
    CComPtr<IPin>       pConnectedPin;
    CComPtr<IPin>       pPin;

    // Enumerate all pins on the filter
    HRESULT hr = pFilter->EnumPins(&pEnumPin);
    if (FAILED(hr))
    {
        goto done;
    }

    // Step through every pin, looking for the output pins.
    while (S_OK == (hr = pEnumPin->Next(1, &pPin, NULL)))
    {
        // Skip connected pins.
        hr = pPin->ConnectedTo(&pConnectedPin);
        if (hr == VFW_E_NOT_CONNECTED)
        {
            PIN_DIRECTION PinDirection;
            hr = pPin->QueryDirection(&PinDirection);

            if ((S_OK == hr) && (PinDirection == PINDIR_OUTPUT))
            {
                hr = pGraph->Render(pPin);
            }
        }

        pConnectedPin.Release();
        pPin.Release();

        // If there was an error, stop enumerating.
        if (FAILED(hr))
        {
            break;
        }
    }

done:
    return hr;
}

В следующем коде показано, как получить указатель на интерфейс IWMDRMReader из средства чтения WM ASF:

HRESULT DrmManager::Initialize(IBaseFilter *pFilter)
{


    CComPtr<IServiceProvider> pService;
    CComPtr<IWMDRMReader> pDrmReader;

    HRESULT hr = pFilter->QueryInterface(&pService);
    if (SUCCEEDED(hr))
    {
        hr = pService->QueryService(
            __uuidof(IWMDRMReader), IID_PPV_ARGS(&m_pDrmReader));
    }
    return hr;
}

Чтение ФАЙЛОВ ASF в DirectShow