Udostępnij za pośrednictwem


Jak odtwarzać chronione pliki multimedialne

Chroniony plik multimedialny to dowolny plik multimedialny, który ma skojarzone reguły używania zawartości. W niektórych przypadkach chroniony plik multimedialny jest szyfrowany przy użyciu jakiejś formy szyfrowania praw cyfrowych (DRM). Aby odtworzyć chroniony plik multimedialny, odtwarzanie musi nastąpić wewnątrz ścieżki chronionego nośnika (PMP). Ponadto użytkownik może mieć możliwość uzyskania praw do zawartości.

Termin uzyskiwania praw odnosi się do każdej akcji, którą aplikacja musi wykonać, zanim użytkownik będzie mógł odtworzyć zawartość. Najczęstszym przykładem jest uzyskanie licencji DRM, ale Program Media Foundation definiuje ogólny mechanizm, który może obsługiwać inne typy pozyskiwania praw. Interfejs IMFContentEnabler definiuje ten ogólny mechanizm.

Uzyskiwanie praw musi odbywać się poza PMP, w ramach procesu aplikacyjnego. Sesja multimediów powiadamia aplikację za pośrednictwem interfejsu IMFContentProtectionManager, który jest implementowany przez aplikację. Sesja multimediów używa interfejsu IMFContentProtectionManager do przekazywania obiektu włączania zawartości do aplikacji. Osoby obsługujące zawartość implementują interfejs IMFContentEnabler. Aplikacja używa tego interfejsu do uzyskania niezbędnych praw.

Moduł zawartości może obsługiwać automatyczne pozyskiwanie praw, w którym to przypadku moduł zawartości implementuje cały proces, a aplikacja po prostu monitoruje stan. W przeciwnym razie aplikacja musi używać jawnego pozyskiwania praw, co jest procesem, w którym aplikacja wysyła dane HTTP POST do adresu URL dostarczonego przez udostępniającego treść.

Aby odtworzyć chronione nośniki, aplikacja wykonuje te same kroki opisane w temacie How to Play Media Files with Media Foundation, wykonując następujące dodatkowe czynności:

  1. Sprawdź, czy źródło multimediów zawiera chronioną zawartość. (Opcjonalnie).
  2. Utwórz sesję multimediów w procesie PMP zamiast procesu aplikacji.
  3. Wykonaj przejęcie praw, jeśli zostanie powiadomiony o tym przez sesję multimediów. Ta operacja jest wykonywana asynchronicznie przez aplikację.
  4. Ukończ operację asynchroniczną.

Zapytanie dotyczące chronionej zawartości

Aby zbadać, czy źródło multimediów zawiera chronioną zawartość, wywołaj funkcję MFRequireProtectedEnvironment w deskryptorze prezentacji źródła multimediów. Jeśli funkcja zwróci S_OK, musisz użyć protokołu PMP, aby odtworzyć zawartość. Jeśli funkcja zwróci S_FALSE, protokół PMP nie jest wymagany i można utworzyć sesję multimediów w procesie aplikacji. Alternatywnie można użyć protokołu PMP do odtwarzania obu typów zawartości, chronionych i niechronionych. Jeśli to zrobisz, nie musisz wywoływać MFRequireProtectedEnvironment.

Aby uzyskać więcej informacji na temat deskryptorów prezentacji, zobacz Deskryptory prezentacji.

Tworzenie sesji multimediów PMP

Aby utworzyć sesję multimediów w PMP, wywołaj MFCreatePMPMediaSession. Ta funkcja jest podobna do MFCreateMediaSession, ale zamiast tworzyć sesję multimediów w procesie aplikacji, tworzy sesję multimediów w procesie PMP. Aplikacja odbiera wskaźnik do obiektu proxy dla sesji medialnej. Aplikacja wywołuje metody IMFMediaSession na obiekcie proxy, tak jak zrobiłaby to na Sesji Mediów. Obiekt proxy przekazuje wywołania do Media Session przez granicę procesów.

Utwórz sesję medialną PMP w następujący sposób:

  1. Utwórz nowy magazyn atrybutów, wywołując MFCreateAttributes.
  2. Ustaw atrybut MF_SESSION_CONTENT_PROTECTION_MANAGER w magazynie atrybutów. Wartość tego atrybutu jest wskaźnikiem prowadzącym do implementacji w aplikacji IMFContentProtectionManager. Wywołaj IMFAttributes::SetUnknown, aby ustawić atrybut.
  3. Wywołaj MFCreatePMPMediaSession, aby utworzyć sesję multimediów w procesie PMP. Parametr pConfiguration jest wskaźnikiem do interfejsu IMFAttributes magazynu atrybutów.
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).

Następnie utwórz topologię odtwarzania i umieść ją w kolejce w Sesji Mediów zgodnie z opisem w Tworzenie topologii odtwarzania.

Uzyskiwanie praw

Jeśli odtwarzanie wymaga nabycia praw, sesja multimedialna wywołuje IMFContentProtectionManager::BeginEnableContent. Parametr pEnablerActivate tej metody jest wskaźnikiem do interfejsu IMFActivate. Użyj tego interfejsu, aby utworzyć obiekt włączania zawartości, który uwidacznia interfejs IMFContentEnabler. Następnie użyj włączania zawartości, aby wykonać krok pozyskiwania praw.

Aby stworzyć aktywator zawartości, wywołaj IMFActivate::ActivateObject:

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

Wykonaj zapytanie dotyczące zwróconego wskaźnika IMFContentEnabler dla interfejsuIMFMediaEventGenerator. Ten interfejs służy do pobierania zdarzeń z obiektu włączania zawartości. Aby uzyskać więcej informacji na temat zdarzeń, zobacz Media Event Generators.

Aby dowiedzieć się, czy moduł umożliwiający treści obsługuje automatyczne pozyskiwanie, wywołaj IMFContentEnabler::IsAutomaticSupported. Jeśli ta metoda zwraca wartość true, aplikacja powinna używać automatycznego pozyskiwania. W przeciwnym razie należy użyć pozyskiwania dyskretnego.

Metoda BeginEnableContent jest asynchroniczna. Aplikacja powinna wykonać krok pozyskiwania w wątku aplikacji. Jedną z metod jest przesłanie prywatnego komunikatu do okna głównego aplikacji, powiadamiając wątek aplikacji o dokonaniu akwizycji. Podczas trwania operacji aplikacja musi przechowywać wskaźnik wywołania zwrotnego oraz obiekt stanu, który otrzymała w parametrach pCallback i punkState funkcji BeginEnableContent. Zostaną one użyte do ukończenia operacji asynchronicznej.

Automatyczne pozyskiwanie

Aby przeprowadzić automatyczne pozyskiwanie, wywołaj IMFContentEnabler::AutomaticEnable. Ta metoda jest asynchroniczna. Po zakończeniu operacji aktywizator zawartości wysyła zdarzenie MEEnablerCompleted. Kod stanu zdarzenia wskazuje, czy operacja zakończyła się pomyślnie. Jeśli kod stanu ze zdarzenia MEEnablerCompleted jest NS_E_DRM_LICENSE_NOTACQUIRED, aplikacja powinna spróbować użyć niesilentnego pozyskiwania.

Podczas gdy operacja akwizycji jest w toku, obiekt uruchamiający może wysłać zdarzenie MEEnablerProgress, aby wskazać postęp operacji. Aby anulować operację, wywołaj metodę IMFContentEnabler::Cancel.

Nieciche pozyskiwanie

Jeśli metoda IsAutomaticSupported zwraca wartość FALSE lub wykonanie metody AutomaticEnable kończy się niepowodzeniem z kodem błędu NS_E_DRM_LICENSE_NOTACQUIRED, aplikacja powinna wykonać pozyskiwanie nieme zgodnie z opisem w poniższych krokach:

  1. Wywołaj IMFContentEnabler::GetEnableURL, aby uzyskać adres URL nabycia praw. Ta metoda zwraca również flagę wskazującą, czy adres URL jest zaufany.

  2. Wywołaj IMFContentEnabler::GetEnableData, aby pobrać dane HTTP POST.

  3. Wywołaj IMFContentEnabler::MonitorEnable. Ta metoda powoduje, że funkcja włączania zawartości monitoruje postęp akcji pozyskiwania praw.

  4. Prześlij dane do adresu URL pozyskiwania praw przy użyciu akcji HTTP POST. Możesz użyć kontrolki Internet Explorer lub interfejsów API Windows Internet (WinINet).

Poniższy kod przedstawia kroki od 1 do 3. Krok 4 zależy od konkretnych wymagań aplikacji.

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

Po zakończeniu operacji włącznik zawartości wysyła zdarzenie MEEnablerCompleted.

Ukończ operację asynchroniczną

Po pomyślnym lub innym zakończeniu pozyskiwania praw aplikacja musi powiadomić sesję multimediów, wywołując wskaźnik wywołania zwrotnego podany w metodzie BeginEnableContent.

  1. Utwórz obiekt wyniku asynchronicznego, wywołując MFCreateAsyncResult.
  2. Wywołaj funkcję zwrotną sesji multimediów, wywołując MFInvokeCallback.
  3. Sesja multimedialna wywoła IMFContentProtectionManager::EndEnableContent. W implementacji tej metody zwolnij wszystkie wskaźniki lub zasoby, które przydzieliłeś w BeginEnableContent. Zwróć HRESULT, który wskazuje ogólny sukces operacji. Jeśli przejęcie praw nie powiodło się lub użytkownik anulował przed jego ukończeniem, zwróć kod błędu.

Poniższy kod pokazuje, jak utworzyć wynik asynchroniczny i wywołać wywołanie zwrotne.

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

sesja multimedialna

odtwarzania audio/wideo