Compartir a través de


Leer DRM-Protected archivos ASF en DirectShow

[La característica asociada a esta página, DirectShow, es una característica heredada. Se ha reemplazado por MediaPlayer, IMFMediaEngine y Captura de audio/vídeo en Media Foundation. Esas características se han optimizado para Windows 10 y Windows 11. Microsoft recomienda encarecidamente que el nuevo código use MediaPlayer, IMFMediaEngine y Audio/Video Capture en Media Foundation en lugar de DirectShow, siempre que sea posible. Microsoft sugiere que el código existente que usa las API heredadas se reescriba para usar las nuevas API si es posible.

En este tema se describe cómo usar DirectShow para reproducir archivos multimedia protegidos con Windows Media Digital Rights Management (DRM).

Conceptos de DRM

La protección de un archivo multimedia con DRM de Windows Media implica dos pasos distintos:

  • El proveedor de contenido empaqueta el archivo, es decir, cifra el archivo y adjunta información de licencia al encabezado de archivo ASF. La información de licencia incluye una dirección URL en la que el cliente puede obtener la licencia.
  • La aplicación cliente adquiere una licencia para el contenido.

El empaquetado se produce antes de que se distribuya el archivo. La adquisición de licencias se produce cuando el usuario intenta reproducir o copiar el archivo. La adquisición de licencias puede ser silenciosa o no silenciosa. La adquisición silenciosa no requiere ninguna interacción con el usuario. La adquisición no silenciosa requiere que la aplicación abra una ventana del explorador y muestre una página web al usuario. En ese momento, es posible que el usuario tenga que proporcionar algún tipo de información al proveedor de contenido. Sin embargo, ambos tipos de adquisición de licencias requieren que el cliente envíe una solicitud HTTP a un servidor de licencias.

Versiones de DRM

Existen varias versiones de DRM de Windows Media. Desde la perspectiva de una aplicación cliente, se pueden agrupar en dos categorías: DRM versión 1 y DRM versión 7 o posterior. (La segunda categoría incluye las versiones 9 y 10 de DRM, así como la versión 7). El motivo para clasificar las versiones de DRM de esta manera es que las licencias de la versión 1 se controlan de forma ligeramente diferente a las licencias de la versión 7 o posteriores. En esta documentación, el término licencia de la versión 7 significa la versión 7 o posterior.

También es importante distinguir el empaquetado drm de la licencia DRM. Si el archivo se empaqueta con Windows Media Rights Manager versión 7 o posterior, el encabezado DRM puede contener una dirección URL de licencia de la versión 1 además de la dirección URL de licencia de la versión 7. La dirección URL de licencia de la versión 1 permite a los jugadores anteriores que no admiten la versión 7 obtener una licencia para el contenido. Sin embargo, el contrario no es true, por lo que un archivo con empaquetado de la versión 1 no puede tener una dirección URL de licencia de la versión 7.

Nivel de seguridad de la aplicación

Para reproducir archivos protegidos con DRM, la aplicación cliente debe estar vinculada a una biblioteca estática proporcionada en formato binario por Microsoft. Esta biblioteca, que identifica de forma única la aplicación, a veces se denomina biblioteca de código auxiliar. La biblioteca de código auxiliar tiene un nivel de seguridad asignado, cuyo valor viene determinado por el contrato de licencia que firmó al obtener la biblioteca de código auxiliar.

El proveedor de contenido establece un nivel de seguridad mínimo necesario para adquirir la licencia. Si el nivel de seguridad de la biblioteca de código auxiliar es menor que el nivel de seguridad mínimo requerido por el servidor de licencias, la aplicación no puede obtener la licencia.

Individualización

Para aumentar la seguridad, una aplicación puede actualizar los componentes drm en el equipo del cliente. Esta actualización, denominada individualización, diferencia la copia del usuario de la aplicación de todas las demás copias de la misma aplicación. El encabezado DRM de un archivo protegido puede especificar un nivel de individualización mínimo. (Para obtener más información, consulte la documentación de WMRMHeader.IndividualizedVersion en el SDK de Windows Media Rights Manager).

Microsoft Individualization Service controla la información del usuario. Por lo tanto, antes de que la aplicación se individualice, debe mostrar la Declaración de privacidad de Microsoft o proporcionar un vínculo a ella (consulte Declaración de privacidad de Microsoft).

Proporcionar el certificado de software

Para permitir que la aplicación use la licencia DRM, la aplicación debe proporcionar un certificado de software o una clave al Administrador de gráficos de filtros. Esta clave se encuentra en una biblioteca estática que se individualiza para la aplicación. Para obtener información sobre cómo obtener la biblioteca individualizada, consulte Obtención de la biblioteca DRM necesaria en la documentación del SDK de Windows Media Format.

Para proporcionar la clave de software, realice los pasos siguientes:

  1. Vínculo a la biblioteca estática.
  2. Implemente la interfaz IServiceProvider .
  3. Consulte el Administrador de gráficos de filtros para la interfaz IObjectWithSite .
  4. Llame a IObjectWithSite::SetSite con un puntero a la implementación de IServiceProvider.
  5. El Administrador de gráficos de filtros llamará a IServiceProvider::QueryService, especificando IID_IWMReader para el identificador de servicio.
  6. En la implementación de QueryService, llame a WMCreateCertificate para crear la clave de software.

El código siguiente muestra cómo implementar el 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;
}

En el código siguiente se muestra cómo llamar a SetSite en filter Graph Manager:

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

Creación del gráfico de reproducción

Para reproducir un archivo ASF protegido con DRM, realice los pasos siguientes:

  1. Cree el Administrador de gráficos de filtros y use la interfaz IMediaEventEx para registrarse en eventos de grafos.
  2. Llame a CoCreateInstance para crear una nueva instancia del filtro Lector ASF de WM .
  3. Llame a IFilterGraph::AddFilter para agregar el filtro al gráfico de filtros.
  4. Consulte el filtro para la interfaz IFileSourceFilter .
  5. Llame a IFileSourceFilter::Load con la dirección URL del archivo.
  6. Controlar eventos de EC_WMT_EVENT .
  7. En el primer evento de EC_WMT_EVENT , consulte el filtro Lector ASF de WM para la interfaz IServiceProvider .
  8. Llame a IServiceProvider::QueryService para obtener un puntero a la interfaz IWMDRMReader .
  9. Llame a IGraphBuilder::Render para representar los pines de salida del filtro lector de ASF de WM .

Nota:

Al abrir un archivo protegido con DRM, no llame a IGraphBuilder::RenderFile para crear el gráfico de filtros. El filtro lector de ASF de WM no puede conectarse a ningún otro filtro hasta que se adquiera la licencia DRM. Este paso requiere que la aplicación use la interfaz IWMDRMReader , que se debe obtener del filtro, como se describe en los pasos 7–8. Por lo tanto, debe crear el filtro y agregarlo al gráfico.

 

Nota:

Es importante registrarse para los eventos de grafo (paso 1) antes de agregar el filtro lector asf de WM al gráfico (paso 3), ya que la aplicación debe controlar los eventos de EC_WMT_EVENT . Los eventos se envían cuando se llama a Load (paso 5).

 

En el código siguiente se muestra cómo compilar el 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++
            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;}

En el código anterior, la RenderOutputPins función enumera las patillas de salida en el filtro Lector ASF de WM y llama a IGraphBuilder::Render para cada patilla.

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

En el código siguiente se muestra cómo obtener un puntero a la interfaz IWMDRMReader del lector DE ASF 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;
}

Leer archivos ASF en DirectShow