Bagikan melalui


Membaca DRM-Protected File ASF di DirectShow

[Fitur yang terkait dengan halaman ini, DirectShow, adalah fitur warisan. Ini telah digantikan oleh MediaPlayer, IMFMediaEngine, dan Tangkapan Audio/Video di Media Foundation. Fitur-fitur tersebut telah dioptimalkan untuk Windows 10 dan Windows 11. Microsoft sangat menyarankan agar kode baru menggunakan MediaPlayer, IMFMediaEngine dan Audio/Video Capture di Media Foundation alih-alih DirectShow, jika memungkinkan. Microsoft menyarankan agar kode yang ada yang menggunakan API warisan ditulis ulang untuk menggunakan API baru jika memungkinkan.]

Topik ini menjelaskan cara menggunakan DirectShow untuk memutar file media yang dilindungi dengan Windows Media Digital Rights Management (DRM).

Konsep DRM

Melindungi file media dengan Windows Media DRM melibatkan dua langkah berbeda:

  • Penyedia konten mengemas file—yaitu, mengenkripsi file dan melampirkan informasi lisensi ke header file ASF. Informasi lisensi mencakup URL tempat klien dapat memperoleh lisensi.
  • Aplikasi klien memperoleh lisensi untuk konten tersebut.

Pengemasan terjadi sebelum file didistribusikan. Akuisisi lisensi terjadi ketika pengguna mencoba memutar atau menyalin file. Akuisisi lisensi mungkin diam atau tidak diam. Akuisisi senyap tidak memerlukan interaksi apa pun dengan pengguna. Akuisisi non-senyap mengharuskan aplikasi membuka jendela browser dan menampilkan halaman web kepada pengguna. Pada saat itu, pengguna mungkin perlu memberikan semacam informasi kepada penyedia konten. Namun, kedua jenis akuisisi lisensi mengharuskan klien untuk mengirimkan permintaan HTTP ke server lisensi.

Versi DRM

Ada beberapa versi Windows Media DRM. Dari perspektif aplikasi klien, mereka dapat dikelompokkan ke dalam dua kategori: DRM versi 1, dan DRM versi 7 atau yang lebih baru. (Kategori kedua mencakup DRM versi 9 dan 10, serta versi 7.) Alasan untuk mengategorikan versi DRM dengan cara ini adalah bahwa lisensi versi 1 ditangani agak berbeda dari lisensi versi 7 atau yang lebih baru. Dalam dokumentasi ini, istilah lisensi versi 7 berarti versi 7 atau yang lebih baru.

Penting juga untuk membedakan kemasan DRM dari lisensi DRM. Jika file dibungkus menggunakan Windows Media Rights Manager versi 7 atau yang lebih baru, header DRM dapat berisi URL lisensi versi 1 selain URL lisensi versi 7. URL lisensi versi 1 memungkinkan pemutar lama yang tidak mendukung versi 7 untuk mendapatkan lisensi konten. Namun, sebaliknya tidak benar, sehingga file dengan kemasan versi 1 tidak dapat memiliki URL lisensi versi 7.

Tingkat Keamanan Aplikasi

Untuk memutar file yang dilindungi DRM, aplikasi klien harus ditautkan ke pustaka statis yang disediakan dalam bentuk biner oleh Microsoft. Pustaka ini, yang secara unik mengidentifikasi aplikasi, terkadang disebut pustaka stub. Pustaka stub memiliki tingkat keamanan yang ditetapkan, nilainya ditentukan oleh perjanjian lisensi yang Anda tandatangani saat Anda mendapatkan pustaka stub.

Penyedia konten menetapkan tingkat keamanan minimum yang diperlukan untuk memperoleh lisensi. Jika tingkat keamanan pustaka stub Anda kurang dari tingkat keamanan minimum yang diperlukan oleh server lisensi, aplikasi tidak dapat memperoleh lisensi.

Individualisasi

Untuk meningkatkan keamanan, aplikasi dapat memperbarui komponen DRM di komputer klien. Pembaruan ini, yang disebut individualisasi, membedakan salinan aplikasi pengguna dari semua salinan lain dari aplikasi yang sama. Header DRM dari file yang dilindungi dapat menentukan dapat menentukan tingkat individualisasi minimum. (Untuk informasi selengkapnya, lihat dokumentasi untuk WMRMHeader.IndividualizedVersion di Windows Media Rights Manager SDK.)

Layanan Individualisasi Microsoft menangani informasi dari pengguna. Jadi sebelum aplikasi Anda individualisasi, Anda harus menampilkan Pernyataan Privasi Microsoft, atau menyediakan tautan ke aplikasi tersebut (lihat Pernyataan Privasi Microsoft).

Berikan Sertifikat Perangkat Lunak

Untuk mengaktifkan aplikasi untuk menggunakan lisensi DRM, aplikasi harus menyediakan sertifikat perangkat lunak atau kunci ke Filter Graph Manager. Kunci ini terkandung dalam pustaka statis yang disortir untuk aplikasi. Untuk informasi tentang mendapatkan pustaka individual, lihat Mendapatkan Pustaka DRM yang Diperlukan dalam dokumentasi Windows Media Format SDK.

Untuk menyediakan kunci perangkat lunak, lakukan langkah-langkah berikut:

  1. Tautkan ke pustaka statis.
  2. Terapkan antarmuka IServiceProvider .
  3. Kueri Filter Graph Manager untuk antarmuka IObjectWithSite .
  4. Panggil IObjectWithSite::SetSite dengan penunjuk ke implementasi IServiceProvider Anda.
  5. Filter Graph Manager akan memanggil IServiceProvider::QueryService, yang menentukan IID_IWMReader untuk pengidentifikasi layanan.
  6. Dalam implementasi QueryService Anda, panggil WMCreateCertificate untuk membuat kunci perangkat lunak.

Kode berikut menunjukkan cara mengimplementasikan metode QueryService :

STDMETHODIMP Player::QueryService(REFIID siid, REFIID riid, void **ppv)
{
    if (ppv == NULL ) 
    { 
        return E_POINTER; 
    }

    if (siid == __uuidof(IWMReader) && riid == __uuidof(IUnknown))
    {
        IUnknown *punkCert;

        HRESULT hr = WMCreateCertificate(&punkCert);

        if (SUCCEEDED(hr))
        {
            *ppv = (void *) punkCert;
        }

        return hr;
    }
    return E_NOINTERFACE;
}

Kode berikut menunjukkan cara memanggil SetSite di Filter Graph Manager:

HRESULT Player::CreateFilterGraph()
{
    CComPtr<IObjectWithSite> pSite;

    HRESULT hr = pGraph.CoCreateInstance(CLSID_FilterGraph);

    if (FAILED(hr))
    {
        goto done;
    }

    // Register the application as a site (service).
    hr = pGraph->QueryInterface(&pSite);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pSite->SetSite(this);


done:
    return hr;
}

Membangun Grafik Pemutaran

Untuk memutar file ASF yang dilindungi DRM, lakukan langkah-langkah berikut:

  1. Buat Filter Graph Manager dan gunakan antarmuka IMediaEventEx untuk mendaftar peristiwa grafik.
  2. Panggil CoCreateInstance untuk membuat instans baru filter Pembaca WM ASF .
  3. Panggil IFilterGraph::AddFilter untuk menambahkan filter ke grafik filter.
  4. Kueri filter untuk antarmuka IFileSourceFilter .
  5. Panggil IFileSourceFilter::Load dengan URL file.
  6. Menangani peristiwa EC_WMT_EVENT .
  7. Pada peristiwa EC_WMT_EVENT pertama, kueri filter Pembaca WM ASF untuk antarmuka IServiceProvider .
  8. Panggil IServiceProvider::QueryService untuk mendapatkan pointer ke antarmuka IWMDRMReader .
  9. Panggil IGraphBuilder::Render untuk merender pin output filter Pembaca WM ASF .

Catatan

Saat membuka file yang dilindungi DRM, jangan panggil IGraphBuilder::RenderFile untuk membuat grafik filter. Filter Pembaca WM ASF tidak dapat tersambung ke filter lain hingga lisensi DRM diperoleh. Langkah ini mengharuskan aplikasi untuk menggunakan antarmuka IWMDRMReader , yang harus diperoleh dari filter, seperti yang dijelaskan dalam langkah 7–8. Oleh karena itu, Anda harus membuat filter dan menambahkannya ke grafik

 

Catatan

Penting untuk mendaftar peristiwa grafik (langkah 1) sebelum menambahkan filter Pembaca WM ASF ke grafik (langkah 3), karena aplikasi harus menangani peristiwa EC_WMT_EVENT . Peristiwa dikirim ketika Muat dipanggil (langkah 5).

 

Kode berikut menunjukkan cara membuat grafik:

HRESULT Player::LoadMediaFile(PCWSTR pwszFile)
{


    BOOL bIsWindowsMediaFile = IsWindowsMediaFile(pwszFile);

    HRESULT hr = S_OK;

    // If this is the first time opening the file, create the
    // filter graph and add the WM ASF Reader filter.

    if (m_DRM.State() == DRM_INITIAL)
    {
        hr = CreateFilterGraph();
        if (FAILED(hr))
        {
            goto done;
        }

        // Use special handling for Windows Media files.
        if (bIsWindowsMediaFile)
        {
            // Add the ASF Reader filter to the graph.
            hr = m_pReader.CoCreateInstance(CLSID_WMAsfReader);
            if (FAILED(hr))
            {
                goto done;
            }

            hr = pGraph->AddFilter(m_pReader, NULL);
            if (FAILED(hr))
            {
                goto done;
            }

            hr = m_pReader->QueryInterface(&m_pFileSource);
            if (FAILED(hr))
            {
                goto done;
            }
        }
    }

    if (bIsWindowsMediaFile)
    {
            hr = m_pFileSource->Load(pwszFile, NULL);
C++
            if (FAILED(hr))            {                goto done;            }            hr = RenderOutputPins(pGraph, m_pReader);    }    else    {        // Not a Windows Media file, so just render the standard way.        hr = pGraph->RenderFile(pwszFile, NULL);    }done:    return hr;}

Dalam kode sebelumnya, RenderOutputPins fungsi menghitung pin output pada filter Pembaca WM ASF dan memanggil IGraphBuilder::Render untuk setiap pin.

HRESULT RenderOutputPins(IGraphBuilder *pGraph, IBaseFilter *pFilter)
{
    CComPtr<IEnumPins>  pEnumPin = NULL;
    CComPtr<IPin>       pConnectedPin;
    CComPtr<IPin>       pPin;

    // Enumerate all pins on the filter
    HRESULT hr = pFilter->EnumPins(&pEnumPin);
    if (FAILED(hr))
    {
        goto done;
    }

    // Step through every pin, looking for the output pins.
    while (S_OK == (hr = pEnumPin->Next(1, &pPin, NULL)))
    {
        // Skip connected pins.
        hr = pPin->ConnectedTo(&pConnectedPin);
        if (hr == VFW_E_NOT_CONNECTED)
        {
            PIN_DIRECTION PinDirection;
            hr = pPin->QueryDirection(&PinDirection);

            if ((S_OK == hr) && (PinDirection == PINDIR_OUTPUT))
            {
                hr = pGraph->Render(pPin);
            }
        }

        pConnectedPin.Release();
        pPin.Release();

        // If there was an error, stop enumerating.
        if (FAILED(hr))
        {
            break;
        }
    }

done:
    return hr;
}

Kode berikut menunjukkan cara mendapatkan penunjuk ke antarmuka IWMDRMReader dari Pembaca WM ASF:

HRESULT DrmManager::Initialize(IBaseFilter *pFilter)
{


    CComPtr<IServiceProvider> pService;
    CComPtr<IWMDRMReader> pDrmReader;

    HRESULT hr = pFilter->QueryInterface(&pService);
    if (SUCCEEDED(hr))
    {
        hr = pService->QueryService(
            __uuidof(IWMDRMReader), IID_PPV_ARGS(&m_pDrmReader));
    }
    return hr;
}

Membaca File ASF di DirectShow