Condividi tramite


Lettura dei file ASF DRM-Protected in DirectShow

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stato sostituito da MediaPlayer, IMFMediaEnginee Acquisizione audio/video in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice utilizzi MediaPlayer, IMFMediaEngine e Acquisizione audio/video in Media Foundation anziché usare DirectShow, dove possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

Questo argomento descrive come usare DirectShow per riprodurre file multimediali protetti con Windows Media Digital Rights Management (DRM).

Concetti relativi a DRM

La protezione di un file multimediale con DRM di Windows Media prevede due passaggi distinti:

  • Il provider di contenuti crea un pacchetto del file, ovvero crittografa il file e allega informazioni sulle licenze all'intestazione del file ASF. Le informazioni sulle licenze includono un URL in cui il client può ottenere la licenza.
  • L'applicazione client acquisisce una licenza per il contenuto.

La creazione di pacchetti avviene prima della distribuzione del file. L'acquisizione della licenza si verifica quando l'utente tenta di riprodurre o copiare il file. L'acquisizione della licenza può essere silenziosa o non silenziosa. L'acquisizione silenziosa non richiede alcuna interazione con l'utente. L'acquisizione non invisibile all'utente richiede all'applicazione di aprire una finestra del browser e visualizzare una pagina Web. A questo punto, l'utente potrebbe dover fornire alcune informazioni al provider di contenuti. Tuttavia, entrambi i tipi di acquisizione di licenze richiedono al client di inviare una richiesta HTTP a un server licenze.

Versioni DRM

Esistono diverse versioni di Windows Media DRM. Dal punto di vista di un'applicazione client, possono essere raggruppati in due categorie: DRM versione 1 e DRM versione 7 o successiva. La seconda categoria include DRM versioni 9 e 10, nonché la versione 7. Il motivo della categorizzazione delle versioni DRM in questo modo è che le licenze della versione 1 vengono gestite in modo leggermente diverso rispetto alle licenze 7 o successive. In questa documentazione il termine licenza versione 7 indica la versione 7 o successiva.

È anche importante distinguere la creazione di pacchetti DRM dalla licenza DRM. Se il file viene incluso in un pacchetto con Windows Media Rights Manager versione 7 o successiva, l'intestazione DRM può contenere un URL di licenza versione 1 oltre all'URL della licenza della versione 7. L'URL della licenza versione 1 consente ai lettori meno recenti che non supportano la versione 7 di ottenere una licenza per il contenuto. Tuttavia, il contrario non è vero, quindi un file con pacchetto versione 1 non può avere un URL di licenza versione 7.

Livello di sicurezza delle applicazioni

Per riprodurre file protetti da DRM, l'applicazione client deve essere collegata a una libreria statica fornita in formato binario da Microsoft. Questa libreria, che identifica in modo univoco l'applicazione, è talvolta denominata libreria stub. La libreria stub ha un livello di sicurezza assegnato, il cui valore è determinato dal contratto di licenza firmato quando è stata ottenuta la libreria stub.

Il provider di contenuti imposta un livello di sicurezza minimo necessario per acquisire la licenza. Se il livello di sicurezza della libreria stub è inferiore al livello di sicurezza minimo richiesto dal server licenze, l'applicazione non può ottenere la licenza.

Individualizzazione

Per aumentare la sicurezza, un'applicazione può aggiornare i componenti DRM nel computer del client. Questo aggiornamento, denominato individualizzazione, differenzia la copia dell'utente dell'applicazione da tutte le altre copie della stessa applicazione. L'intestazione DRM di un file protetto può specificare un livello di individualizzazione minimo. Per altre informazioni, vedere la documentazione per WMRMHeader.IndividualizedVersion in Windows Media Rights Manager SDK.

Il servizio di individualizzazione Microsoft gestisce le informazioni dell'utente. Pertanto, prima dell'individualizzazione dell'applicazione, è necessario visualizzare l'Informativa sulla privacy di Microsoft o fornire un collegamento (vedere Informativa sulla privacy di Microsoft).

Specificare il certificato software

Per consentire all'applicazione di usare la licenza DRM, l'applicazione deve fornire un certificato software o chiave a Filter Graph Manager. Questa chiave è contenuta in una libreria statica individualizzata per l'applicazione. Per informazioni su come ottenere la libreria individualizzata, vedere Ottenere la libreria DRM necessaria nella documentazione di Windows Media Format SDK.

Per fornire la chiave software, seguire questa procedura:

  1. Collegamento alla libreria statica.
  2. Implementare l'interfaccia IServiceProvider.
  3. Eseguire una query su Filter Graph Manager per l'interfacciaIObjectWithSite.
  4. Chiamare IObjectWithSite::SetSite con un puntatore alla tua implementazione di IServiceProvider.
  5. Filter Graph Manager chiamerà IServiceProvider::QueryService, specificando IID_IWMReader per l'identificatore del servizio.
  6. Nell'implementazione di QueryServicechiamare WMCreateCertificate per creare la chiave software.

Il codice seguente illustra come implementare il metodo 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;
}

Il codice seguente illustra come chiamare SetSite in 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;
}

Creazione del grafico di riproduzione

Per riprodurre un file ASF protetto da DRM, seguire questa procedura:

  1. Creare il di Filter Graph Manager e usare l'interfacciaIMediaEventExper eseguire la registrazione per gli eventi del grafo.
  2. Chiamare CoCreateInstance per creare una nuova istanza del filtro WM ASF Reader .
  3. Chiamare IFilterGraph::AddFilter per aggiungere il filtro al grafico del filtro.
  4. Eseguire una query sul filtro per l'interfaccia IFileSourceFilter.
  5. Chiamare IFileSourceFilter::Load con l'URL del file.
  6. Gestire gli eventi EC_WMT_EVENT.
  7. Nel primo evento EC_WMT_EVENT eseguire una query sul filtro lettore ASF WM per l'interfaccia IServiceProvider.
  8. Chiamare IServiceProvider::QueryService per ottenere un puntatore all'interfaccia IWMDRMReader.
  9. Chiamare IGraphBuilder::Render per eseguire il rendering dei pin di output del filtro WM ASF Reader .

Nota

Quando si apre un file protetto da DRM, non chiamare IGraphBuilder::RenderFile per creare il grafico del filtro. Il filtro lettore ASF WM non può connettersi ad altri filtri finché non viene acquisita la licenza DRM. Questo passaggio richiede all'applicazione di usare l'interfacciaIWMDRMReader, che deve essere ottenuta dal filtro, come descritto nei passaggi da 7 a 8. Pertanto, è necessario creare il filtro e aggiungerlo al grafico

 

Nota

È importante eseguire la registrazione per gli eventi del grafo (passaggio 1) prima di aggiungere il filtro lettore ASF WM al grafico (passaggio 3), perché l'applicazione deve gestire gli eventi EC_WMT_EVENT. Gli eventi vengono inviati quando viene chiamato Load (passaggio 5).

 

Il codice seguente illustra come compilare il grafico:

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

Nel codice precedente, la funzione RenderOutputPins enumera i pin di uscita sul filtro WM ASF Reader e chiama IGraphBuilder::Render per ogni 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;
}

Il codice seguente mostra come ottenere un puntatore all'interfaccia IWMDRMReader dal lettore 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;
}

La lettura dei file ASF in DirectShow