测试图形驱动程序是否支持 COPP

[与此页面关联的功能 DirectShow 是旧版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音频/视频捕获所取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能在 Media Foundation 中使用 MediaPlayerIMFMediaEngine音频/视频捕获 ,而不是 DirectShow。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]

经认证的输出保护协议 (COPP) 使应用程序能够在视频内容从视频卡传送到显示设备时对其进行保护。 如果图形驱动程序支持 COPP,则驱动程序持有由 Microsoft 签名的证书链,对驱动程序进行身份验证。 使用 COPP 强制实施内容保护的播放应用程序必须验证证书链,以确保驱动程序未被篡改。

但是,可能需要检查图形驱动程序是否支持 COPP,而无需验证证书。 例如,当数字媒体提供商 (DRM) 许可证颁发数字权限管理时,它可能需要检查用户是否具有启用了 COPP 的图形驱动程序。 提供商在颁发许可证时不需要强制实施 COPP;它只需要测试驱动程序是否支持 COPP。

以下代码演示如何测试驱动程序是否支持 COPP。 应用程序必须传入将用于测试驱动程序的视频文件的名称。 这是必需的,因为在连接筛选器之前,Microsoft® DirectShow® 中的视频混合呈现器筛选器不会初始化 COPP 会话。 此函数可以包含在客户端应用程序中,以检查驱动程序是否能够运行 COPP。

注意

如果用户的计算机有两个图形卡,则此函数会测试主要图形卡的驱动程序,但不测试辅助图形卡。

 

#include <dshow.h>
// Link to strmiids.lib

#define SAFE_RELEASE(p) if (NULL != (p)) { (p)->Release(); (p) = NULL; }
#define CHECK_HR(hr) if (FAILED(hr)) { goto done; }

enum COPPSupport 
{
    SUPPORTS_COPP,
    DOES_NOT_SUPPORT_COPP,
    CANNOT_DETERMINE_COPP_SUPPORT
};

//------------------------------------------------------------------------
// Name:        IsDriverCoppEnabled
// Description: Test whether the user's graphics driver supports
//              COPP.
// wszTestFile: Name of a video file to use for testing.
//
// If this method returns the value SUPPORTS_COPP, it does *not* guarantee 
// that the driver is a valid COPP-enabled driver. If you want to use COPP 
// to enforce video output protection, the application *must* validate 
// the certificate returned by the KeyExchange method. 
// 
// The purpose of this function is only to test whether the driver 
// claims to support COPP. 
//------------------------------------------------------------------------

COPPSupport IsDriverCoppEnabled(const WCHAR *wszTestFile)
{
    COPPSupport SupportResult = CANNOT_DETERMINE_COPP_SUPPORT; 

    IGraphBuilder *pGB = NULL;
    IBaseFilter *pRenderer = NULL;
    IAMCertifiedOutputProtection  *pCOPPDevice = NULL;
    BYTE *pbCertificate = NULL;
    GUID  RandomValue = GUID_NULL;
    ULONG cbCertificateLength = NULL;
    
    HRESULT hr = S_OK;

    CHECK_HR(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED));
   
    // Create the Filter Graph Manager.
    CHECK_HR(hr = CoCreateInstance(CLSID_FilterGraph, NULL, 
        CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGB));

    // Create the VMR-9. 
    hr = CoCreateInstance(CLSID_VideoMixingRenderer9,
        NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, 
        (void**)&pRenderer
        ));

    if (FAILED(hr))
    {
        // Try the VMR-7 instead.
        CHECK_HR(hr = CoCreateInstance(CLSID_VideoMixingRenderer,
                NULL, CLSCTX_INPROC, IID_IBaseFilter, 
                (void**)&pRenderer
                ));
    }

    // Add the VMR to the filter graph.
    CHECK_HR(hr = pGB->AddFilter(pRenderer, L"Video Renderer"));

    // Build a default playback graph.
    CHECK_HR(hr = pGB->RenderFile(wszTestFile, NULL));

    // Query for IAMCertifiedOutputProtection.
    CHECK_HR(hr = pRenderer->QueryInterface(IID_IAMCertifiedOutputProtection,
            (void**)&pCOPPDevice));

    // Get the driver's COPP certificate.
    hr = pCOPPDevice->KeyExchange(&RandomValue, &pbCertificate,
        &cbCertificateLength);

    if (SUCCEEDED(hr))
    {
        SupportResult = SUPPORTS_COPP;
    }
    else
    {
        SupportResult = DOES_NOT_SUPPORT_COPP;
    }

done:
    // Clean up.
    CoTaskMemFree(pbCertificate);
    SAFE_RELEASE(pCOPPDevice);
    SAFE_RELEASE(pRenderer);
    SAFE_RELEASE(pGB);
    CoUninitialize();

    return SupportResult;
} 

使用经过认证的输出保护协议