Come riprodurre file multimediali protetti
Un file multimediale protetto è qualsiasi file multimediale associato a regole per l'uso del contenuto. In alcuni casi, un file multimediale protetto viene crittografato usando una qualche 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 consiste nell'ottenere una licenza DRM, ma Media Foundation definisce un meccanismo generico in grado di 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, dalla procedura di richiesta. La sessione multimediale 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 di diritti non invisibile all'utente, ovvero un processo in cui l'applicazione invia i 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:
- Verificare se l'origine multimediale contiene contenuti protetti. (Facoltativo.
- Creare la sessione multimediale nel processo PMP, anziché il processo dell'applicazione.
- Eseguire l'acquisizione dei diritti, se notificato dalla sessione multimediale. Questa operazione viene eseguita in modo asincrono dall'applicazione.
- Completare l'operazione asincrona.
Query per contenuto protetto
Per verificare se un'origine multimediale contiene contenuto protetto, chiamare la funzione MFRequireProtectedEnvironment sul descrittore di presentazione dell'origine multimediale. Se la funzione restituisce S_OK, è necessario usare 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 in 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 IMFMediaSession metodi 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:
- Creare un nuovo archivio attributi chiamando MFCreateAttributes.
- Impostare l'attributo MF_SESSION_CONTENT_PROTECTION_MANAGER nell'archivio attributi. Il valore di questo attributo è un puntatore all'implementazione della tua applicazione di IMFContentProtectionManager. Chiamare IMFAttributes::SetUnknown per impostare l'attributo.
- 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 di abilitazione del contenuto, 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 puntatoreIMFContentEnabler restituito per l'interfaccia IMFMediaEventGenerator. Usare questa interfaccia per ottenere eventi dall'oggetto di abilitazione del contenuto. Per altre informazioni sugli eventi, vedere Generatori di eventi multimediali.
Per verificare se l'abilitazione del contenuto supporta l'acquisizione automatica, è possibile chiamare IMFContentEnabler::IsAutomaticSupported. Se questo metodo restituisce il valore TRUE, l'applicazione deve usare l'acquisizione automatica. In caso contrario, usare l'acquisizione non silenziosa.
Il metodoBeginEnableContentè 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 stato che ha ricevuto nei parametri pCallback e punkState di BeginEnableContent. Questi 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 silenziosa.
Mentre l'operazione di acquisizione è in corso, l'oggetto enabler potrebbe inviare l'evento MEEnablerProgress per indicare lo stato dell'operazione. Per annullare l'operazione, chiamare IMFContentEnabler::Cancel.
Acquisizione non silenziosa
Se il metodoIsAutomaticSupportedrestituisce FALSE o il metodoAutomaticEnableha 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:
Chiamare IMFContentEnabler::GetEnableURL per ottenere l'URL per l'acquisizione dei diritti. Questo metodo restituisce anche un flag che indica se l'URL è attendibile.
Chiamare IMFContentEnabler::GetEnableData per ottenere i dati HTTP POST.
Chiama IMFContentEnabler::MonitorEnable. Questo metodo fa sì che l'enabler di contenuto monitori l'avanzamento dell'azione di acquisizione dei diritti.
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'enabler del contenuto invia un evento MEEnablerCompleted.
Completare l'operazione asincrona
Quando l'acquisizione dei diritti viene completata correttamente o diversamente, l'applicazione deve inviare una notifica alla sessione multimediale richiamando il puntatore di callback specificato nel metodo BeginEnableContent.
- Creare un oggetto risultato asincrono chiamando MFCreateAsyncResult.
- Richiamare il callback della sessione multimediale chiamando MFInvokeCallback.
- La sessione multimediale chiamerà IMFContentProtectionManager::EndEnableContent. Nell'implementazione di questo metodo rilasciare qualsiasi puntatore o risorsa allocata all'interno di BeginEnableContent. Restituisce un HRESULT che indica l'esito complessivo dell'operazione. Se l'acquisizione dei diritti non è riuscita o l'utente ha annullato prima del completamento, restituire 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);
Argomenti correlati