Come riprodurre file multimediali protetti

Un file multimediale protetto è qualsiasi file multimediale associato alle regole per l'uso del contenuto. In alcuni casi, un file multimediale protetto viene crittografato usando una forma di crittografia DRM (Digital Rights Management). Per riprodurre un file multimediale protetto, la riproduzione deve essere eseguita all'interno del percorso multimediale protetto (PMP). Inoltre, l'utente potrebbe dover acquisire i diritti per il contenuto.

Il termine acquisizione dei diritti si riferisce a qualsiasi azione che l'applicazione deve eseguire prima che l'utente possa riprodurre il contenuto. L'esempio più comune è ottenere una licenza DRM, ma Media Foundation definisce un meccanismo generico che può supportare altri tipi di acquisizione dei diritti. L'interfaccia IMFContentEnabler definisce questo meccanismo generico.

L'acquisizione dei diritti deve essere eseguita al di fuori del PMP, dal processo dell'applicazione. La sessione multimediale invia una notifica all'applicazione tramite l'interfaccia IMFContentProtectionManager , implementata dall'applicazione. La sessione multimediale usa l'interfaccia IMFContentProtectionManager per inoltrare un oggetto di abilitazione del contenuto all'applicazione. Gli strumenti di abilitazione del contenuto implementano l'interfaccia IMFContentEnabler . L'applicazione usa questa interfaccia per acquisire i diritti necessari.

Un abilitatore di contenuto potrebbe supportare l'acquisizione automatica dei diritti, nel qual caso l'abilitazione del contenuto implementa l'intero processo e l'applicazione monitora semplicemente lo stato. In caso contrario, l'applicazione deve usare l'acquisizione dei diritti non invisibile all'utente, ovvero un processo in cui l'applicazione invia dati HTTP POST a un URL fornito dall'abilitatore del contenuto.

Per riprodurre supporti protetti, un'applicazione segue gli stessi passaggi descritti nell'argomento Come riprodurre file multimediali con Media Foundation, con i passaggi aggiuntivi seguenti:

  1. Eseguire una query per verificare se l'origine multimediale contiene contenuto protetto. Facoltativo.
  2. Creare la sessione multimediale nel processo PMP, anziché il processo dell'applicazione.
  3. Eseguire l'acquisizione dei diritti, se si riceve una notifica da parte della sessione multimediale. Questa operazione viene eseguita in modo asincrono dall'applicazione.
  4. Completare l'operazione asincrona.

Query per contenuto protetto

Per verificare se un'origine multimediale contiene contenuto protetto, chiamare la funzione MFRequireProtectedEnvironment nel descrittore di presentazione dell'origine multimediale. Se la funzione restituisce S_OK, è necessario usare il pmp per riprodurre il contenuto. Se la funzione restituisce S_FALSE, il pmp non è obbligatorio ed è possibile creare la sessione multimediale nel processo dell'applicazione. In alternativa, è possibile usare PMP per riprodurre entrambi i tipi di contenuto, protetti e non protetti. In tal caso, non è necessario chiamare MFRequireProtectedEnvironment.

Per altre informazioni sui descrittori di presentazione, vedere Descrittori di presentazione.

Creare la sessione multimediale PMP

Per creare la sessione multimediale nel PMP, chiamare MFCreatePMPMediaSession. Questa funzione è simile a MFCreateMediaSession, ma invece di creare la sessione multimediale nel processo dell'applicazione, crea la sessione multimediale nel processo PMP. L'applicazione riceve un puntatore a un oggetto proxy per la sessione multimediale. L'applicazione chiama metodi IMFMediaSession sull'oggetto proxy, proprio come nella sessione multimediale. L'oggetto proxy inoltra le chiamate alla sessione multimediale oltre il limite del processo.

Creare la sessione multimediale PMP come indicato di seguito:

  1. Creare un nuovo archivio attributi chiamando MFCreateAttributes.
  2. Impostare l'attributo MF_SESSION_CONTENT_PROTECTION_MANAGER nell'archivio attributi. Il valore di questo attributo è un puntatore all'implementazione dell'applicazione di IMFContentProtectionManager. Chiamare IMFAttributes::SetUnknown per impostare l'attributo.
  3. Chiamare MFCreatePMPMediaSession per creare la sessione multimediale nel processo PMP. Il parametro pConfiguration è un puntatore all'interfaccia IMFAttributes dell'archivio attributi.
IMFAttributes *pAttributes = NULL;
IMFMediaSession *pSession = NULL;

// Create the attribute store.
hr = MFCreateAttributes(&pAttributes, 1);

// Set the IMFContentProtectionManager pointer.
if (SUCCEEDED(hr))
{
    hr = pAttributes->SetUnknown(
        MF_SESSION_CONTENT_PROTECTION_MANAGER, 
        pCPM  // Your implementation of IMFContentProtectionManager.
        );
}

// Create the Media Session.
if (SUCCEEDED(hr))
{
    hr = MFCreatePMPMediaSession(
        0,
        pAttributes, 
        &pSession,
        NULL
    );
}

SAFE_RELEASE(pAttributes); // Release the attribute store.
// Use the Media Session to control playback (not shown).

Creare quindi una topologia di riproduzione e accodarla nella sessione multimediale, come descritto in Creazione di topologie di riproduzione.

Eseguire l'acquisizione dei diritti

Se la riproduzione richiede l'acquisizione dei diritti, la sessione multimediale chiama IMFContentProtectionManager::BeginEnableContent. Il parametro pEnablerActivate di questo metodo è un puntatore all'interfaccia IMFActivate . Utilizzare questa interfaccia per creare l'oggetto content enabler, che espone l'interfaccia IMFContentEnabler . Usare quindi l'abilitazione del contenuto per eseguire il passaggio di acquisizione dei diritti.

Per creare l'abilitazione del contenuto, chiamare IMFActivate::ActivateObject:

IMFContentEnabler *pEnabler = NULL;
hr = pEnablerActivate->ActivateObject(
    IID_IMFContentEnabler, 
    (void**)&pEnabler
    );

Eseguire una query sul puntatore IMFContentEnabler restituito per l'interfaccia IMFMediaEventGenerator . Usare questa interfaccia per ottenere eventi dall'oggetto abilitazione del contenuto. Per altre informazioni sugli eventi, vedere Media Event Generators.

Per determinare se l'abilitazione del contenuto supporta l'acquisizione automatica, chiamare IMFContentEnabler::IsAutomaticSupported. Se questo metodo restituisce il valore TRUE, l'applicazione deve usare l'acquisizione automatica. In caso contrario, usare l'acquisizione non invisibile all'utente.

Il metodo BeginEnableContent è asincrono. L'applicazione deve eseguire il passaggio di acquisizione nel thread dell'applicazione. Un approccio consiste nel pubblicare un messaggio di finestra privata nella finestra principale dell'applicazione, notificando al thread dell'applicazione di eseguire l'acquisizione. Mentre l'operazione è in sospeso, l'applicazione deve archiviare il puntatore di callback e l'oggetto di stato ricevuto nei parametri pCallback e punkState di BeginEnableContent. Verranno usati per completare l'operazione asincrona.

Acquisizione automatica

Per eseguire l'acquisizione automatica, chiamare IMFContentEnabler::AutomaticEnable. Questo metodo è asincrono. Al termine dell'operazione, l'abilitazione del contenuto invia un evento MEEnablerCompleted . Il codice di stato dell'evento indica se l'operazione è riuscita. Se il codice di stato dell'evento MEEnablerCompleted è NS_E_DRM_LICENSE_NOTACQUIRED, l'applicazione deve provare a usare l'acquisizione non invisibile all'utente.

Mentre l'operazione di acquisizione è in corso, l'oggetto enabler potrebbe inviare l'evento MEEnablerProgress per indicare lo stato di avanzamento dell'operazione. Per annullare l'operazione, chiamare IMFContentEnabler::Cancel.

Acquisizione non invisibile all'utente

Se il metodo IsAutomaticSupported restituisce FALSE o il metodo AutomaticEnable ha esito negativo con il codice di errore NS_E_DRM_LICENSE_NOTACQUIRED, l'applicazione deve eseguire l'acquisizione non invisibile all'utente, come descritto nei passaggi seguenti:

  1. Chiamare IMFContentEnabler::GetEnableURL per ottenere l'URL per l'acquisizione dei diritti. Questo metodo restituisce anche un flag che indica se l'URL è attendibile.

  2. Chiamare IMFContentEnabler::GetEnableData per ottenere i dati HTTP POST.

  3. Chiamare IMFContentEnabler::MonitorEnable. Questo metodo fa sì che l'abilitazione del contenuto monitori l'avanzamento dell'azione di acquisizione dei diritti.

  4. Inviare i dati all'URL di acquisizione dei diritti usando un'azione HTTP POST. È possibile usare il controllo Internet Explorer o le API Windows Internet (WinINet).

Il codice seguente illustra i passaggi da 1 a 3. Il passaggio 4 dipende dai requisiti specifici dell'applicazione.

WCHAR   *sURL = NULL;  // URL.
DWORD   cchURL = 0;    // Size of the URL in characters.

// Trust status of the URL.
MF_URL_TRUST_STATUS  trustStatus = MF_LICENSE_URL_UNTRUSTED;

BYTE    *pPostData = NULL;  // Buffer to hold HTTP POST data.
DWORD   cbPostDataSize = 0; // Size of the buffer, in bytes.

HRESULT hr = S_OK;

// Get the URL. 
hr = m_pEnabler->GetEnableURL(&sURL, &cchURL, &trustStatus);

if (SUCCEEDED(hr))
{
    if (trustStatus != MF_LICENSE_URL_TRUSTED)
    {
        // The URL is not trusted. Do not proceed.
        hr = E_FAIL;
    }
}

// Monitor the rights acquisition. 
if (SUCCEEDED(hr))
{
    hr = m_pEnabler->MonitorEnable();
}

// Get the HTTP POST data.
if (SUCCEEDED(hr))
{
    hr = m_pEnabler->GetEnableData(&pPostData, &cbPostDataSize);
}

// Open the URL and send the HTTP POST data. (Not shown.)

// Release the buffers.
CoTaskMemFree(pPostData);
CoTaskMemFree(sURL);

Al termine dell'operazione, l'abilitazione del contenuto invia un evento MEEnablerCompleted .

Completare l'operazione asincrona

Al termine dell'acquisizione dei diritti, l'applicazione deve inviare una notifica alla sessione multimediale richiamando il puntatore di callback specificato nel metodo BeginEnableContent .

  1. Creare un oggetto risultato asincrono chiamando MFCreateAsyncResult.
  2. Richiamare il callback della sessione multimediale chiamando MFInvokeCallback.
  3. La sessione multimediale chiamerà IMFContentProtectionManager::EndEnableContent. Nell'implementazione di questo metodo rilasciare qualsiasi puntatore o risorsa allocata all'interno di BeginEnableContent. Restituisce un valore HRESULT che indica l'esito positivo complessivo dell'operazione. Se l'acquisizione dei diritti non è riuscita o l'utente ha annullato prima del completamento, restituisce un codice di errore.

Il codice seguente illustra come creare il risultato asincrono e richiamare il callback.

IMFAsyncResult  *pResult = NULL;

// Create the asynchronous result object.
hr = MFCreateAsyncResult(NULL, pCallback, punkState, &pResult);

// Invoke the callback.
if (SUCCEEDED(hr))
{
    pResult->SetStatus(hrStatus);
    hr = MFInvokeCallback(pResult);
}
SAFE_RELEASE(pResult);

Sessione multimediale

Riproduzione di audio/video