Cara Memainkan File Media Terproteksi

File media yang dilindungi adalah file media apa pun yang memiliki aturan terkait untuk menggunakan konten. Dalam beberapa kasus, file media yang dilindungi dienkripsi menggunakan beberapa bentuk enkripsi manajemen hak digital (DRM). Untuk memutar file media yang dilindungi, pemutaran harus terjadi di dalam jalur media terproteksi (PMP). Selain itu, pengguna mungkin harus memperoleh hak atas konten.

Istilah akuisisi hak mengacu pada tindakan apa pun yang harus dilakukan aplikasi sebelum pengguna dapat memutar konten. Contoh yang paling umum adalah mendapatkan lisensi DRM, tetapi Media Foundation mendefinisikan mekanisme generik yang dapat mendukung jenis akuisisi hak lainnya. Antarmuka IMFContentEnabler mendefinisikan mekanisme generik ini.

Akuisisi hak harus dilakukan di luar PMP, dari proses aplikasi. Sesi Media memberi tahu aplikasi melalui antarmuka IMFContentProtectionManager , yang diimplementasikan oleh aplikasi. Sesi Media menggunakan antarmuka IMFContentProtectionManager untuk meneruskan objek pengaktif konten ke aplikasi. Pengaktif konten mengimplementasikan antarmuka IMFContentEnabler . Aplikasi ini menggunakan antarmuka ini untuk memperoleh hak yang diperlukan.

Pengaktif konten mungkin mendukung akuisisi hak otomatis, dalam hal ini pengaktif konten mengimplementasikan seluruh proses, dan aplikasi hanya memantau status. Jika tidak, aplikasi harus menggunakan akuisisi hak non-senyap, yang merupakan proses di mana aplikasi mengirim data HTTP POST ke URL yang disediakan oleh pengaktif konten.

Untuk memutar media yang dilindungi, aplikasi mengikuti langkah yang sama yang diberikan dalam topik Cara Memutar File Media dengan Media Foundation, dengan langkah-langkah tambahan berikut:

  1. Kueri apakah sumber media berisi konten yang dilindungi. (Opsional.)
  2. Buat Sesi Media dalam proses PMP, bukan proses aplikasi.
  3. Lakukan akuisisi hak, jika diberi tahu untuk melakukannya oleh Sesi Media. Operasi ini dilakukan secara asinkron oleh aplikasi.
  4. Selesaikan operasi asinkron.

Kueri untuk Konten yang Dilindungi

Untuk mengkueri apakah sumber media berisi konten yang dilindungi, panggil fungsi MFRequireProtectedEnvironment pada deskriptor presentasi sumber media. Jika fungsi mengembalikan S_OK, Anda harus menggunakan PMP untuk memutar konten. Jika fungsi mengembalikan S_FALSE, PMP tidak diperlukan, dan Anda dapat membuat Sesi Media dalam proses aplikasi. Atau, Anda dapat menggunakan PMP untuk memutar kedua jenis konten, dilindungi, dan tidak terlindungi. Jika Anda melakukannya, Anda tidak perlu memanggil MFRequireProtectedEnvironment.

Untuk informasi selengkapnya tentang deskriptor presentasi, lihat Deskriptor Presentasi.

Membuat Sesi Media PMP

Untuk membuat Sesi Media di PMP, panggil MFCreatePMPMediaSession. Fungsi ini mirip dengan MFCreateMediaSession, tetapi alih-alih membuat Sesi Media dalam proses aplikasi, fungsi ini membuat Sesi Media dalam proses PMP. Aplikasi menerima penunjuk ke objek proksi untuk Sesi Media. Aplikasi ini memanggil metode IMFMediaSession pada objek proksi, seperti pada Sesi Media. Objek proksi meneruskan panggilan ke Sesi Media di seluruh batas proses.

Buat Sesi Media PMP sebagai berikut:

  1. Buat penyimpanan atribut baru dengan memanggil MFCreateAttributes.
  2. Atur atribut MF_SESSION_CONTENT_PROTECTION_MANAGER di penyimpanan atribut. Nilai atribut ini adalah penunjuk ke implementasi aplikasi IMFContentProtectionManager Anda. Panggil IMFAttributes::SetUnknown untuk mengatur atribut.
  3. Panggil MFCreatePMPMediaSession untuk membuat Sesi Media dalam proses PMP. Parameter pConfiguration adalah penunjuk ke antarmuka IMFAttributes dari penyimpanan atribut.
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).

Selanjutnya, buat topologi pemutaran dan antrekan di Sesi Media, seperti yang dijelaskan dalam Membuat Topologi Pemutaran.

Melakukan Akuisisi Hak

Jika pemutaran memerlukan akuisisi hak, Sesi Media memanggil IMFContentProtectionManager::BeginEnableContent. Parameter pEnablerActivate dari metode ini adalah penunjuk ke antarmuka IMFActivate . Gunakan antarmuka ini untuk membuat objek pengaktif konten, yang mengekspos antarmuka IMFContentEnabler . Kemudian gunakan pengaktif konten untuk melakukan langkah akuisisi hak.

Untuk membuat pengaktif konten, panggil IMFActivate::ActivateObject:

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

Kueri penunjuk IMFContentEnabler yang dikembalikan untuk antarmuka IMFMediaEventGenerator . Gunakan antarmuka ini untuk mendapatkan peristiwa dari objek pengaktif konten. Untuk informasi selengkapnya tentang peristiwa, lihat Generator Peristiwa Media.

Untuk mengetahui apakah pengaktif konten mendukung akuisisi otomatis, panggil IMFContentEnabler::IsAutomaticSupported. Jika metode ini mengembalikan nilai TRUE, aplikasi harus menggunakan akuisisi otomatis. Jika tidak, gunakan akuisisi non-senyap.

Metode BeginEnableContent bersifat asinkron. Aplikasi harus melakukan langkah akuisisi pada utas aplikasi. Salah satu pendekatannya adalah memposting pesan jendela privat ke jendela utama aplikasi, memberi tahu utas aplikasi untuk melakukan akuisisi. Saat operasi tertunda, aplikasi harus menyimpan penunjuk panggilan balik dan objek status yang diterimanya dalam parameter pCallback dan punkState dari BeginEnableContent. Ini akan digunakan untuk menyelesaikan operasi asinkron.

Akuisisi Otomatis

Untuk melakukan akuisisi otomatis, panggil IMFContentEnabler::AutomaticEnable. Metode ini asinkron. Ketika operasi selesai, pengaktif konten mengirimkan peristiwa MEEnablerCompleted . Kode status peristiwa menunjukkan apakah operasi berhasil. Jika kode status dari peristiwa MEEnablerCompleted NS_E_DRM_LICENSE_NOTACQUIRED, aplikasi harus mencoba menggunakan akuisisi non-senyap.

Saat operasi akuisisi sedang berlangsung, objek pengaktif mungkin mengirim peristiwa MEEnablerProgress untuk menunjukkan kemajuan operasi. Untuk membatalkan operasi, panggil IMFContentEnabler::Cancel.

Akuisisi Non-Senyap

Jika metode IsAutomaticSupported mengembalikan FALSE atau metode AutomaticEnable gagal dengan kode kesalahan NS_E_DRM_LICENSE_NOTACQUIRED, aplikasi harus melakukan akuisisi non-senyap seperti yang dijelaskan dalam langkah-langkah berikut:

  1. Panggil IMFContentEnabler::GetEnableURL untuk mendapatkan URL untuk akuisisi hak. Metode ini juga mengembalikan bendera yang menunjukkan apakah URL tepercaya.

  2. Hubungi IMFContentEnabler::GetEnableData untuk mendapatkan data HTTP POST.

  3. Panggil IMFContentEnabler::MonitorEnable. Metode ini menyebabkan pengaktif konten memantau kemajuan tindakan akuisisi hak.

  4. Kirimkan data ke URL akuisisi hak dengan menggunakan tindakan HTTP POST. Anda bisa menggunakan kontrol Internet Explorer atau WINDOWS Internet (WinINet) API.

Kode berikut menunjukkan langkah 1–3. Langkah 4 tergantung pada persyaratan khusus aplikasi Anda.

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

Ketika operasi selesai, pengaktif konten mengirimkan peristiwa MEEnablerCompleted .

Menyelesaikan Operasi Asinkron

Ketika akuisisi hak selesai, berhasil atau sebaliknya, aplikasi harus memberi tahu Sesi Media, dengan memanggil penunjuk panggilan balik yang diberikan dalam metode BeginEnableContent .

  1. Buat objek hasil asinkron dengan memanggil MFCreateAsyncResult.
  2. Panggil panggilan balik Sesi Media dengan memanggil MFInvokeCallback.
  3. Sesi Media akan memanggil IMFContentProtectionManager::EndEnableContent. Dalam implementasi metode ini, lepaskan pointer atau sumber daya apa pun yang Anda alokasikan di dalam BeginEnableContent. Mengembalikan HRESULT yang menunjukkan keberhasilan operasi secara keseluruhan. Jika akuisisi hak gagal atau pengguna membatalkan sebelum selesai, kembalikan kode kesalahan.

Kode berikut menunjukkan cara membuat hasil asinkron dan memanggil panggilan balik.

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

Sesi Media

Pemutaran Audio/Video