Comment lire des fichiers multimédias protégés
Un fichier multimédia protégé est tout fichier multimédia associé à des règles d’utilisation du contenu. Dans certains cas, un fichier multimédia protégé est chiffré à l’aide d’une forme de chiffrement de gestion des droits numériques (DRM). Pour lire un fichier multimédia protégé, la lecture doit se produire à l’intérieur du chemin d’accès multimédia protégé (PMP). En outre, l’utilisateur peut avoir à acquérir des droits sur le contenu.
Le terme acquisition de droits fait référence à toute action que l’application doit effectuer avant que l’utilisateur puisse lire le contenu. L’exemple le plus courant est l’obtention d’une licence DRM, mais Media Foundation définit un mécanisme générique qui peut prendre en charge d’autres types d’acquisition de droits. L’interface IMFContentEnabler définit ce mécanisme générique.
L’acquisition des droits doit être effectuée en dehors du PMP, à partir du processus de demande. La session multimédia notifie l’application via l’interface IMFContentProtectionManager , qui est implémentée par l’application. La session multimédia utilise l’interface IMFContentProtectionManager pour transférer un objet d’activation de contenu à l’application. Les enablers de contenu implémentent l’interface IMFContentEnabler . L’application utilise cette interface pour acquérir les droits nécessaires.
Un enabler de contenu peut prendre en charge l’acquisition automatique de droits, auquel cas l’enabler de contenu implémente l’ensemble du processus, et l’application surveille simplement l’status. Sinon, l’application doit utiliser l’acquisition de droits non silencieux, qui est un processus où l’application envoie des données HTTP POST à une URL fournie par l’enableur de contenu.
Pour lire des fichiers multimédias protégés, une application suit les mêmes étapes que celles décrites dans la rubrique Comment lire des fichiers multimédias avec Media Foundation, avec les étapes supplémentaires suivantes :
- Vérifiez si la source multimédia contient du contenu protégé. (Facultatif.)
- Créez la session multimédia dans le processus PMP, au lieu du processus d’application.
- Effectuez l’acquisition des droits, si la session multimédia en est informée. Cette opération est effectuée de manière asynchrone par l’application.
- Terminez l’opération asynchrone.
Requête pour le contenu protégé
Pour savoir si une source multimédia contient du contenu protégé, appelez la fonction MFRequireProtectedEnvironment sur le descripteur de présentation de la source multimédia. Si la fonction retourne S_OK, vous devez utiliser le PMP pour lire le contenu. Si la fonction retourne S_FALSE, le PMP n’est pas requis et vous pouvez créer la session multimédia dans le processus d’application. Vous pouvez également utiliser le PMP pour lire les deux types de contenu, protégé et non protégé. Dans ce cas, vous n’avez pas besoin d’appeler MFRequireProtectedEnvironment.
Pour plus d’informations sur les descripteurs de présentation, consultez Descripteurs de présentation.
Créer la session multimédia PMP
Pour créer la session multimédia dans le PMP, appelez MFCreatePMPMediaSession. Cette fonction est similaire à MFCreateMediaSession, mais au lieu de créer la session multimédia dans le processus de l’application, elle crée la session multimédia dans le processus PMP. L’application reçoit un pointeur vers un objet proxy pour la session multimédia. L’application appelle les méthodes IMFMediaSession sur l’objet proxy, comme elle le ferait sur la session multimédia. L’objet proxy transfère les appels à la session multimédia au-delà de la limite de processus.
Créez la session multimédia PMP comme suit :
- Créez un magasin d’attributs en appelant MFCreateAttributes.
- Définissez l’attribut MF_SESSION_CONTENT_PROTECTION_MANAGER sur le magasin d’attributs. La valeur de cet attribut est un pointeur vers l’implémentation d’IMFContentProtectionManager de votre application. Appelez IMFAttributes::SetUnknown pour définir l’attribut.
- Appelez MFCreatePMPMediaSession pour créer la session multimédia dans le processus PMP. Le paramètre pConfiguration est un pointeur vers l’interface IMFAttributes du magasin d’attributs.
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).
Ensuite, créez une topologie de lecture et mettez-la en file d’attente sur la session multimédia, comme décrit dans Création de topologies de lecture.
Effectuer l’acquisition de droits
Si la lecture nécessite l’acquisition de droits, la session multimédia appelle IMFContentProtectionManager::BeginEnableContent. Le paramètre pEnablerActivate de cette méthode est un pointeur vers l’interface IMFActivate . Utilisez cette interface pour créer l’objet d’activation de contenu, qui expose l’interface IMFContentEnabler . Utilisez ensuite l’enabler de contenu pour effectuer l’étape d’acquisition des droits.
Pour créer l’activateur de contenu, appelez IMFActivate::ActivateObject :
IMFContentEnabler *pEnabler = NULL;
hr = pEnablerActivate->ActivateObject(
IID_IMFContentEnabler,
(void**)&pEnabler
);
Interrogez le pointeur IMFContentEnabler retourné pour l’interface IMFMediaEventGenerator . Utilisez cette interface pour obtenir des événements à partir de l’objet d’activation de contenu. Pour plus d’informations sur les événements, consultez Générateurs d’événements multimédias.
Pour savoir si l’enabler de contenu prend en charge l’acquisition automatique, appelez IMFContentEnabler::IsAutomaticSupported. Si cette méthode retourne la valeur TRUE, l’application doit utiliser l’acquisition automatique. Sinon, utilisez l’acquisition non silencieuse.
La méthode BeginEnableContent est asynchrone. L’application doit effectuer l’étape d’acquisition sur le thread de l’application. Une approche consiste à publier un message de fenêtre privée dans la fenêtre main de l’application, en informant le thread d’application d’effectuer l’acquisition. Pendant que l’opération est en attente, l’application doit stocker le pointeur de rappel et l’objet d’état qu’elle a reçus dans les paramètres pCallback et punkState de BeginEnableContent. Celles-ci seront utilisées pour terminer l’opération asynchrone.
Acquisition automatique
Pour effectuer une acquisition automatique, appelez IMFContentEnabler::AutomaticEnable. Cette méthode est asynchrone. Une fois l’opération terminée, l’enabler de contenu envoie un événement MEEnablerCompleted . Le code status de l’événement indique si l’opération a réussi. Si le code status de l’événement MEEnablerCompleted est NS_E_DRM_LICENSE_NOTACQUIRED, l’application doit essayer d’utiliser l’acquisition sans assistance.
Pendant que l’opération d’acquisition est en cours, l’objet enabler peut envoyer l’événement MEEnablerProgress pour indiquer la progression de l’opération. Pour annuler l’opération, appelez IMFContentEnabler::Cancel.
Acquisition non silencieuse
Si la méthode IsAutomaticSupported retourne FALSE ou si la méthode AutomaticEnable échoue avec le code d’erreur NS_E_DRM_LICENSE_NOTACQUIRED, l’application doit effectuer une acquisition sans assistance, comme décrit dans les étapes suivantes :
Appelez IMFContentEnabler::GetEnableURL pour obtenir l’URL de l’acquisition des droits. Cette méthode retourne également un indicateur indiquant si l’URL est approuvée.
Appelez IMFContentEnabler::GetEnableData pour obtenir les données HTTP POST.
Appelez IMFContentEnabler::MonitorEnable. Cette méthode permet à l’enabler de contenu de surveiller la progression de l’action d’acquisition de droits.
Envoyez les données à l’URL d’acquisition des droits à l’aide d’une action HTTP POST. Vous pouvez utiliser le contrôle Internet Explorer ou les API Internet Windows (WinINet).
Le code suivant montre les étapes 1 à 3. L’étape 4 dépend des exigences particulières de votre application.
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);
Une fois l’opération terminée, l’enabler de contenu envoie un événement MEEnablerCompleted .
Terminer l’opération asynchrone
Lorsque l’acquisition des droits est terminée, avec succès ou autrement, l’application doit notifier la session multimédia, en appelant le pointeur de rappel fourni dans la méthode BeginEnableContent .
- Créez un objet de résultat asynchrone en appelant MFCreateAsyncResult.
- Appelez le rappel de la session multimédia en appelant MFInvokeCallback.
- La session multimédia appelleRA IMFContentProtectionManager::EndEnableContent. Dans votre implémentation de cette méthode, libérez tous les pointeurs ou ressources que vous avez alloués dans BeginEnableContent. Retourne un HRESULT qui indique la réussite globale de l’opération. Si l’acquisition des droits a échoué ou si l’utilisateur a annulé avant qu’elle ne soit terminée, retournez un code d’erreur.
Le code suivant montre comment créer le résultat asynchrone et appeler le rappel.
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);
Rubriques connexes