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


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

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

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

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

Защита файла мультимедиа с помощью DRM Windows Media включает в себя два различных шага:

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

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

Версии DRM

Существуют несколько версий DRM Windows Media. С точки зрения клиентского приложения их можно сгруппировать в две категории: 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, приложение должно предоставить сертификат программного обеспечения или ключ диспетчеру графов фильтра. Этот ключ содержится в статической библиотеке, которая индивидуализирована для приложения. Сведения о получении отдельной библиотеки см. в разделе Получение требуемой библиотеки 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 в диспетчере графов фильтров:

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;
}

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

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

  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 Reader для интерфейса IServiceProvider.
  8. Вызовите IServiceProvider::QueryService, чтобы получить указатель на интерфейс IWMDRMReader.
  9. Вызовите IGraphBuilder::Render для отрисовки выходных выводов фильтра WM ASF Reader.

Заметка

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

 

Заметка

Важно зарегистрировать события графа (шаг 1) перед добавлением фильтра WM ASF Reader в граф (шаг 3), так как приложение должно обрабатывать события EC_WMT_EVENT. События отправляются, когда вызывается загрузка (шаг 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