Partager via


Lecture DRM-Protected fichiers ASF dans DirectShow

[La fonctionnalité associée à cette page, DirectShow, est une fonctionnalité héritée. Il a été remplacé par MediaPlayer, IMFMediaEngine et Audio/Video Capture dans Media Foundation. Ces fonctionnalités ont été optimisées pour Windows 10 et Windows 11. Microsoft recommande vivement au nouveau code d’utiliser MediaPlayer, IMFMediaEngine et La capture audio/vidéo dans Media Foundation au lieu de DirectShow, lorsque cela est possible. Microsoft suggère que le code existant qui utilise les API héritées soit réécrit pour utiliser les nouvelles API si possible.]

Cette rubrique explique comment utiliser DirectShow pour lire des fichiers multimédias protégés par la gestion des droits numériques (DRM) Windows Media.

DRM Concepts

La protection d’un fichier multimédia avec Windows Media DRM implique deux étapes distinctes :

  • Le fournisseur de contenu empaquette le fichier, c’est-à-dire chiffre le fichier et joint les informations de licence à l’en-tête du fichier ASF. Les informations de licence incluent une URL dans laquelle le client peut obtenir la licence.
  • L’application cliente acquiert une licence pour le contenu.

L’empaquetage se produit avant la distribution du fichier. L’acquisition de licence se produit lorsque l’utilisateur tente de lire ou de copier le fichier. L’acquisition de licence peut être silencieuse ou non. L’acquisition silencieuse ne nécessite aucune interaction avec l’utilisateur. L’acquisition non silencieuse nécessite que l’application ouvre une fenêtre de navigateur et affiche une page web pour l’utilisateur. À ce stade, l’utilisateur peut avoir besoin de fournir un type d’informations au fournisseur de contenu. Toutefois, les deux types d’acquisition de licences nécessitent que le client envoie une requête HTTP à un serveur de licences.

DRM Versions

Plusieurs versions de Windows Media DRM existent. Du point de vue d’une application cliente, ils peuvent être regroupés en deux catégories : DRM version 1 et DRM version 7 ou ultérieure. (La deuxième catégorie inclut les versions DRM 9 et 10, ainsi que la version 7.) La raison de la catégorisation des versions DRM de cette façon est que les licences version 1 sont gérées quelque peu différemment des licences de version 7 ou ultérieures. Dans cette documentation, le terme licence version 7 désigne la version 7 ou ultérieure.

Il est également important de distinguer l’empaquetage DRM de la licence DRM. Si le fichier est empaqueté à l’aide de Windows Media Rights Manager version 7 ou ultérieure, l’en-tête DRM peut contenir une URL de licence version 1 en plus de l’URL de licence version 7. L’URL de licence version 1 permet aux joueurs plus anciens qui ne prennent pas en charge la version 7 d’obtenir une licence pour le contenu. Toutefois, l’inverse n’étant pas vrai, un fichier avec empaquetage de version 1 ne peut pas avoir d’URL de licence de version 7.

Niveau de sécurité de l’application

Pour lire des fichiers protégés par DRM, l’application cliente doit être liée à une bibliothèque statique fournie sous forme binaire par Microsoft. Cette bibliothèque, qui identifie de manière unique l’application, est parfois appelée bibliothèque stub. La bibliothèque stub a un niveau de sécurité attribué, dont la valeur est déterminée par le contrat de licence que vous avez signé lorsque vous avez obtenu la bibliothèque stub.

Le fournisseur de contenu définit un niveau de sécurité minimal nécessaire pour acquérir la licence. Si le niveau de sécurité de votre bibliothèque stub est inférieur au niveau de sécurité minimal requis par le serveur de licences, l’application ne peut pas obtenir la licence.

Individualisation

Pour renforcer la sécurité, une application peut mettre à jour les composants DRM sur l’ordinateur du client. Cette mise à jour, appelée individualisation, différencie la copie de l’application par l’utilisateur de toutes les autres copies de la même application. L’en-tête DRM d’un fichier protégé peut spécifier un niveau d’individualisation minimal. (Pour plus d’informations, consultez la documentation relative à WMRMHeader.IndividualizedVersion dans le Kit de développement logiciel (SDK) Windows Media Rights Manager.)

Le service d’individualisation Microsoft gère les informations de l’utilisateur. Par conséquent, avant que votre application ne soit individualisée, vous devez afficher la Déclaration de confidentialité Microsoft ou fournir un lien vers celle-ci (voir Déclaration de confidentialité Microsoft).

Fournir le certificat logiciel

Pour permettre à l’application d’utiliser la licence DRM, l’application doit fournir un certificat logiciel ou une clé au Gestionnaire de graphes de filtre. Cette clé est contenue dans une bibliothèque statique qui est individualisée pour l’application. Pour plus d’informations sur l’obtention de la bibliothèque personnalisée, consultez Obtention de la bibliothèque DRM requise dans la documentation du Kit de développement logiciel (SDK) au format Windows Media.

Pour fournir la clé logicielle, procédez comme suit :

  1. Lien vers la bibliothèque statique.
  2. Implémentez l’interface IServiceProvider .
  3. Interrogez le Gestionnaire de graphes de filtre pour l’interface IObjectWithSite .
  4. Appelez IObjectWithSite::SetSite avec un pointeur vers votre implémentation d’IServiceProvider.
  5. Le Gestionnaire de graphes de filtre appelle IServiceProvider::QueryService, en spécifiant IID_IWMReader pour l’identificateur de service.
  6. Dans votre implémentation de QueryService, appelez WMCreateCertificate pour créer la clé logicielle.

Le code suivant montre comment implémenter la méthode 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;
}

Le code suivant montre comment appeler SetSite sur le Gestionnaire de graphes de filtre :

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

Génération du graphique de lecture

Pour lire un fichier ASF protégé par DRM, procédez comme suit :

  1. Créez le Gestionnaire de graphes de filtre et utilisez l’interface IMediaEventEx pour vous inscrire aux événements de graphe.
  2. Appelez CoCreateInstance pour créer un instance du filtre lecteur ASF WM.
  3. Appelez IFilterGraph::AddFilter pour ajouter le filtre au graphe de filtre.
  4. Interrogez le filtre pour l’interface IFileSourceFilter .
  5. Appelez IFileSourceFilter::Load avec l’URL du fichier.
  6. Gérer les événements EC_WMT_EVENT .
  7. Lors du premier événement EC_WMT_EVENT , interrogez le filtre lecteur ASF WM pour l’interface IServiceProvider .
  8. Appelez IServiceProvider::QueryService pour obtenir un pointeur vers l’interface IWMDRMReader .
  9. Appelez IGraphBuilder::Render pour afficher les broches de sortie du filtre lecteur WM ASF .

Notes

Lors de l’ouverture d’un fichier protégé par DRM, n’appelez pas IGraphBuilder::RenderFile pour créer le graphe de filtre. Le filtre WM ASF Reader ne peut pas se connecter à d’autres filtres tant que la licence DRM n’est pas acquise. Cette étape nécessite que l’application utilise l’interface IWMDRMReader , qui doit être obtenue à partir du filtre, comme décrit aux étapes 7 à 8. Par conséquent, vous devez créer le filtre et l’ajouter au graphique

 

Notes

Il est important de s’inscrire aux événements de graphe (étape 1) avant d’ajouter le filtre Lecteur ASF WM au graphique (étape 3), car l’application doit gérer les événements EC_WMT_EVENT . Les événements sont envoyés lorsque le chargement est appelé (étape 5).

 

Le code suivant montre comment générer le graphe :

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

Dans le code précédent, la RenderOutputPins fonction énumère les broches de sortie sur le filtre lecteur WM ASF et appelle IGraphBuilder::Render pour chaque broche.

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

Le code suivant montre comment obtenir un pointeur vers l’interface IWMDRMReader à partir du lecteur 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;
}

Lecture de fichiers ASF dans DirectShow