Lendo DRM-Protected arquivos ASF no DirectShow
[O recurso associado a esta página, DirectShow, é um recurso herdado. Ele foi substituído por MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo na Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo no Media Foundation em vez de DirectShow, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]
Este tópico descreve como usar o DirectShow para reproduzir arquivos de mídia protegidos com o DRM (Gerenciamento de Direitos Digitais) do Windows Media.
Conceitos de DRM
Proteger um arquivo de mídia com o DRM do Windows Media envolve duas etapas distintas:
- O provedor de conteúdo empacota o arquivo, ou seja, criptografa o arquivo e anexa informações de licenciamento ao cabeçalho do arquivo ASF. As informações de licenciamento incluem uma URL em que o cliente pode obter a licença.
- O aplicativo cliente adquire uma licença para o conteúdo.
O empacotamento ocorre antes que o arquivo seja distribuído. A aquisição de licença ocorre quando o usuário tenta reproduzir ou copiar o arquivo. A aquisição de licença pode ser silenciosa ou não silenciosa. A aquisição silenciosa não requer nenhuma interação com o usuário. A aquisição não silenciosa requer que o aplicativo abra uma janela do navegador e exiba uma página da Web para o usuário. Nesse ponto, talvez o usuário precise fornecer algum tipo de informação ao provedor de conteúdo. No entanto, ambos os tipos de aquisição de licença exigem que o cliente envie uma solicitação HTTP a um servidor de licença.
Versões do DRM
Existem várias versões do DRM do Windows Media. Da perspectiva de um aplicativo cliente, eles podem ser agrupados em duas categorias: DRM versão 1 e DRM versão 7 ou posterior. (A segunda categoria inclui as versões 9 e 10 do DRM, bem como a versão 7.) O motivo para categorizar as versões do DRM dessa forma é que as licenças da versão 1 são tratadas de forma um pouco diferente das licenças da versão 7 ou posterior. Nesta documentação, o termo licença versão 7 significa a versão 7 ou posterior.
Também é importante distinguir o empacotamento DRM da licença DRM. Se o arquivo estiver empacotado usando o Windows Media Rights Manager versão 7 ou posterior, o cabeçalho DRM poderá conter uma URL de licença versão 1, além da URL de licença da versão 7. A URL de licença da versão 1 permite que jogadores mais antigos que não dão suporte à versão 7 obtenham uma licença para o conteúdo. No entanto, o inverso não é verdadeiro, portanto, um arquivo com o empacotamento da versão 1 não pode ter uma URL de licença versão 7.
Nível de segurança do aplicativo
Para reproduzir arquivos protegidos por DRM, o aplicativo cliente deve ser vinculado a uma biblioteca estática fornecida em formato binário pela Microsoft. Essa biblioteca, que identifica exclusivamente o aplicativo, às vezes é chamada de biblioteca stub. A biblioteca stub tem um nível de segurança atribuído, cujo valor é determinado pelo contrato de licença assinado quando você obteve a biblioteca stub.
O provedor de conteúdo define um nível de segurança mínimo necessário para adquirir a licença. Se o nível de segurança da biblioteca de stub for menor que o nível mínimo de segurança exigido pelo servidor de licença, o aplicativo não poderá obter a licença.
Individualização
Para aumentar a segurança, um aplicativo pode atualizar os componentes drm no computador do cliente. Essa atualização, chamada individualização, diferencia a cópia do aplicativo do usuário de todas as outras cópias do mesmo aplicativo. O cabeçalho DRM de um arquivo protegido pode especificar um nível mínimo de individualização. (Para obter mais informações, consulte a documentação de WMRMHeader.IndividualizedVersion no SDK do Windows Media Rights Manager.)
O Serviço de Individualização da Microsoft manipula informações do usuário. Portanto, antes de seu aplicativo ser individualizado, você deve exibir a Política de Privacidade da Microsoft ou fornecer um link para ele (consulte Política de Privacidade da Microsoft).
Fornecer o certificado de software
Para habilitar o aplicativo a usar a licença DRM, o aplicativo deve fornecer um certificado de software ou uma chave para o Gerenciador de Grafo de Filtro. Essa chave está contida em uma biblioteca estática individualizada para o aplicativo. Para obter informações sobre como obter a biblioteca individualizada, consulte Obtendo a biblioteca drm necessária na documentação do SDK do Formato de Mídia do Windows.
Para fornecer a chave de software, execute as seguintes etapas:
- Link para a biblioteca estática.
- Implemente a interface IServiceProvider .
- Consulte o Gerenciador de Grafo de Filtro para a interface IObjectWithSite .
- Chame IObjectWithSite::SetSite com um ponteiro para a implementação de IServiceProvider.
- O Gerenciador de Grafo de Filtro chamará IServiceProvider::QueryService, especificando IID_IWMReader para o identificador de serviço.
- Na implementação do QueryService, chame WMCreateCertificate para criar a chave de software.
O código a seguir mostra como implementar o método 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;
}
O código a seguir mostra como chamar SetSite no Gerenciador de Grafo de Filtro:
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;
}
Criando o gráfico de reprodução
Para reproduzir um arquivo ASF protegido por DRM, execute as seguintes etapas:
- Crie o Gerenciador de Grafo de Filtro e use a interface IMediaEventEx para registrar-se em eventos de grafo.
- Chame CoCreateInstance para criar uma nova instância do filtro leitor do ASF do WM .
- Chame IFilterGraph::AddFilter para adicionar o filtro ao grafo de filtro.
- Consulte o filtro para a interface IFileSourceFilter .
- Chame IFileSourceFilter::Load com a URL do arquivo.
- Manipular eventos de EC_WMT_EVENT .
- No primeiro evento EC_WMT_EVENT , consulte o filtro leitor asf do WM para a interface IServiceProvider .
- Chame IServiceProvider::QueryService para obter um ponteiro para a interface IWMDRMReader .
- Chame IGraphBuilder::Render para renderizar os pinos de saída do filtro leitor do ASF do WM .
Observação
Ao abrir um arquivo protegido por DRM, não chame IGraphBuilder::RenderFile para criar o grafo de filtro. O filtro leitor do ASF do WM não pode se conectar a nenhum outro filtro até que a licença DRM seja adquirida. Esta etapa exige que o aplicativo use a interface IWMDRMReader , que deve ser obtida do filtro, conforme descrito nas etapas 7 a 8. Portanto, você deve criar o filtro e adicioná-lo ao grafo
Observação
É importante registrar-se para eventos de grafo (etapa 1) antes de adicionar o filtro leitor do ASF do WM ao grafo (etapa 3), pois o aplicativo deve lidar com os eventos EC_WMT_EVENT . Os eventos são enviados quando Load é chamado (etapa 5).
O código a seguir mostra como criar o grafo:
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++ |
---|
|
No código anterior, a RenderOutputPins
função enumera os pinos de saída no filtro Leitor do ASF do WM e chama IGraphBuilder::Render para cada pin.
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;
}
O código a seguir mostra como obter um ponteiro para a interface IWMDRMReader do Leitor de ASF do WM:
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;
}
Tópicos relacionados