그래픽 드라이버가 COPP를 지원하는지 여부 테스트

[이 페이지와 연결된 기능인 DirectShow는 레거시 기능입니다. MediaPlayer, IMFMediaEngine 및 Media Foundation의 오디오/비디오 캡처로 대체되었습니다. 이러한 기능은 Windows 10 및 Windows 11 최적화되었습니다. 가능한 경우 새 코드가 DirectShow 대신 Media Foundation에서 MediaPlayer, IMFMediaEngine오디오/비디오 캡처를 사용하는 것이 좋습니다. 가능한 경우 레거시 API를 사용하는 기존 코드를 다시 작성하여 새 API를 사용하도록 제안합니다.]

COPP(Certified Output Protection Protocol)를 사용하면 애플리케이션이 비디오 카드 디스플레이 디바이스로 이동할 때 비디오 콘텐츠를 보호할 수 있습니다. 그래픽 드라이버가 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;
} 

인증된 출력 보호 프로토콜 사용