具体实施方式
综述
各种实施例涉及使用一协议的方法和系统,该协议通过在诸如运行受保护内容回放应用程序的计算机等设备,和相关联的显示设备的相关联的驱动程序,如图形驱动程序之间建立一安全通信信道,并在某些实施例中建立一安全数据信道,启用了媒体内容保护,这些显示设备诸如监视器、平板LCD、电视机等。各种实施例针对解决内容提供商和应用程序销售商发信号通知内容保护应当被应用到通过物理连接器输出到诸如显示设备等设备的数据的需求。
下文所描述的各种实施例提供了用于将命令从用户模式回放应用程序安全地传递到诸如图形驱动程序等驱动程序,并将状态信息从驱动程序安全地返回到用户模式应用程序的装置。在下文描述的实施例中,一旦建立了一安全通信信道,用户模式应用程序可指令相关联的驱动程序在计算机和显示设备之间的物理连接器上启用内容输出保护。安全信道会话的独占性可防止攻击者在内容从计算机发送到显示器时记录受保护的内容。
在以下的讨论中,各种实施例的描述针对两条单独但相关的线。具体地,在下文名为“用于建立从应用程序到下游组件的安全信道的协议”一节中,提供了一种创造性协议的描述。该协议旨在用于任一合适的系统,并不必要束缚到任何一个特定的系统或操作系统。在名为“Windows操作系统上协议的示例性实现”的一节中,在涉及Windows操作系统的实现的环境中提供了协议的描述。该描述旨在特别示出一个特定的实现以及与该特定实现相关联的一些设计考虑事项等等。
用于建立从应用程序到下游组件的安全信道的协议
在以下的描述中,描述了至少某些实施例,它们可用于提供从应用程序到各种下游组件的安全信令机制,使得应用程序可传递应当应用潜在数量的内容保护技术中的哪一种,以及应当如何向保护媒体内容输出应用那些内容保护技术中的至少一些。另外,并且基于启用并配置不同类型的内容保护的概念,至少某些实施例相对于用于保护媒体输出的内容保护技术的类型是不可预知的(agnostic)。这是有利的,因为所描述的系统和协议是自适应地灵活的,并可用于许多不同类型的现有和未来的内容保护技术,这可以从下文中了解。
作为其中可使用本创造性协议的一个典型系统的示例综述,考虑图2,它以消费者设备200的形式示出了一计算系统。消费者设备200可包括可用于呈现受保护媒体内容的任一合适类型的消费设备。这一设备的一个示例是个人计算机。其它类型的设备可包括个人视频记录器(PVR)设备、数码录像机(DVR)设备等等。
消费者设备200包括可从受保护的媒体内容源获得受保护媒体内容的回放应用程序202、便于处理受保护媒体内容的系统软件204、以及用于与硬件208(如,视频卡)接口的驱动程序软件206(或相关联的硬件的软件表示),硬件208通过某一类型的物理连接器210向相关联的输出设备212提供受保护的媒体内容,通过输出设备212可向用户呈现媒体内容。如上所述,输出设备的示例包括显示设备和扬声器。
为进行讨论的目的,至少在本节中,回放应用程序、系统软件、驱动程序软件和硬件的类型并不特定地相关,本领域的技术人员可以理解,有各种各样的不同类型的实体可构成回放应用程序和物理连接器之间的链。由此,本讨论并不限于任何一个特定类型的系统。
在所示并描述的实施例中,有各种不同类型的内容保护技术,它们可用于保护物理连接器210和输出设备212之间的媒体内容。例如,本领域的技术人员可以理解,各种内容保护类型可包括模拟内容保护(ACP)、复制生成管理系统-模拟(CGMS-A)以及高带宽数字内容保护(HDCP)。在附图中,这些各种类型的内容保护技术在214处示出。
依照此处所描述的实施例,在应用程序202和一个或多个下游组件之间建立一安全链路或信道。在所示的示例中,示出了两个不同的安全信道,尽管只需实现任一类型的一个信道。具体地,在一个实施例中,在应用程序202和驱动程序软件206之间建立安全通信信道216。在另一实施例中,在应用程序202和硬件208之间建立安全信道218。
在所示并描述的实施例中,信道216可主要用于应用程序和驱动程序之间的通信。这类通信可包括在应用程序和驱动程序之间传递命令、状态请求和相关联的状态。信道218不仅可用于这一类型的通信,也可用于向硬件提供实际的媒体数据,如音频和视频数据。
在本文档的上下文中,命令是一种指令,并可包括以下特征以及其它特征。首先,命令可改变或影响硬件208的配置。可选地或另外,命令可以是向硬件发出的要以某一特定方式处理媒体内容的信号。
状态请求可以有效地从硬件中检索两组信息。首先,状态请求可检索设计从应用程序发送到下游组件的任何命令的信息。例如,如果应用程序发送了执行某一任务的命令-例如设置特定类型的内容保护技术-相关联的状态请求可检索关于任务是否已被执行的信息。其次,状态请求可检索不必要与命令是否已发送相关联的信息。例如,状态请求可检索额外的硬件配置信息,它可能对特定的设备是固有的,例如使用的物理连接器的类型。这类状态请求也可用于确认特定物理连接器的硬件支持哪些内容保护技术。例如,物理连接器可以是DVI连接器,但是在图形硬件中可能没有HDCP支持。由此,应用程序然后可作出明智的选择,以播放视频数据的向下采样(down-sampled)或较低分辨率的版本,或者可能完全不播放视频数据。
建立安全信道
在所示并描述的实施例中,使用了单向信任模型和密钥传输协议来建立通信链的两个端点间的信任。本领域的技术人员可以理解,使用密钥传输具有许多优点。首先,使用密钥传输,创建熵的责任留给了建立信任的实体-此处为应用程序202。其次,密钥传输提供了完成所谓“通过”的能力。通过可允许内容数据在沿到图形硬件的链的一路上被加密。这进而可允许图形硬件解密内容数据、将内容数据解码成相关联的表面、然后将内容数据处理到显示器上,这是本领域技术人员所理解的,
使用信道216作为示例,使用例如公钥基础结构(PKI)技术在应用程序202和驱动程序206之间建立单向认证信道。更具体地,在本示例中,在应用程序202和驱动程序206之间建立了数据完整性密钥形式的通信密钥。一旦建立了通信密钥,可将命令和状态消息以未加密的形式传递,并且消息认证代码或MAC可用数据完整性密钥来创建。
作为示例,结合图3考虑以下内容。为建立与下游组件的信任,应用程序202首先调用驱动程序软件206,并从驱动程序软件接收一随机数rGH和与硬件208相关联的数字证书CertGH(图2)。当应用程序202接收数字证书CertGH时,应用程序处理该证书以验证数字证书上的签名是否由可信实体提供,并检索驱动程序软件206(在使用信道216的情况下)或图形硬件208(在使用信道218的情况下)的公钥(PGH)。公钥PGH现在可由应用程序用于加密数据,该数据智能由相关联的私钥来解密,该私钥由驱动程序软件或图形硬件保密。上述过程在应用程序和驱动程序软件之间建立了信任。
在建立信任之后,应用程序现在设置密钥传输。在本示例中,应用程序202将由驱动程序提供的随机数rGH、数据完整性密钥kDI(也称为会话密钥)、随机起始状态序列号(status_start)和随机起始命令序列号(command_start)串接、使用驱动程序软件的公钥PGH来加密值的串接、并将经加密的数据发送到驱动程序软件206。刚才所述的处理在应用程序和驱动程序软件间建立所用的会话密钥。随机起始状态序列号(status_start)和随机起始命令序列号(command_start)用于确保是否丢失了特定的消息,不论该消息是状态请求或报告的状态(在起始状态序列号的情况下)还是命令(在起始命令序列号的情况下),预期的消息接收器可确认这一事实。更具体地,每次当应用程序发送一条命令时,随机起始命令序列号被递增一。类似地,每次当发送一状态消息时,发送实体将起始状态序列号递增一。在接收端,消息接收器可通过简单地核查序列号是否按顺序出现来确认是否丢失了消息。如果有缺少的序列号,则相关联的消息丢失,并可采取适当的行动。以这一方式,使用随机起始序列号确保了消息的完整性和顺序。
在一个示例中,以下表中陈述的值和描述可用于上述过程。
值 |
描述 |
rGH |
由图形驱动程序生成的32位随机数。 |
CertGH |
图形硬件的可变长度数字证书。 |
PGH(rGH,kDI,status_start,command_start) |
来自图形驱动程序的32位随机数、128位随机数据完整性会话密钥、32位随机起始状态序列号和32位随机起始命令序列号的串接,用图形硬件的公钥来加密。该值的长度是2048位。 |
在过程的这一点上,在应用程序和驱动程序软件之间建立了安全信道。以下讨论描述了本创造性协议的两部分-命令协议和状态协议。
命令协议
协议的命令部分令系统的硬件,如硬件208(图2)能够由应用程序指令,以打开并在某些情况下配置特定的内容保护技术,如HDCP或CGMS-A。在所示并描述的实施例中,命令消息包含在一包封中,它具有两个段:数据段和消息认证代码或MAC段。
在所述并描述的实施例中,命令消息的数据段包含命令和相关联的命令序列号。消息认证代码或MAC段包含可以被认为是命令和相关联的命令序列号的加密钥的散列的内容。用于产生加密钥的散列的密钥是上述的数据完整性密钥kDI。
例如,考虑图4,其中应用程序202被示出为向驱动程序软件206发送以下形式的命令消息:
Command,MACkDI(Command)
其中,消息的“Command”部分不仅包括来自应用程序的相关联的命令,还包括了相关联的命令序列号。消息的“MACkDI(Command)”部分包括由应用程序计算的“Command”部分的MAC。当驱动程序软件206接收该命令消息时,驱动程序软件可在消息的命令部分使用协商的会话密钥kDI运行MAC算法。一旦在命令消息的命令部分上运行了MAC算法,驱动程序软件可将该值与命令消息中接收的MAC值进行比较。如果两个值的比较是有利的,则可建立命令消息的完整性。
在一个示例中,下表中陈述的值和描述可用于上述过程。
Command |
可变长度命令数据 |
MACkDI(Command) |
使用数据完整性会话密钥kDI的命令数据和命令序列号的128位MAC |
状态协议
在所示并描述的实施例中,状态消息包含在一包封内,它具有两个段:数据段和消息认证代码或MAC段。在本示例中,消息发送者使用会话密钥kDI和相关联的MAC算法来计算状态数据的MAC。
作为如何实现状态协议的一个示例,考虑图5。应用程序202以下列形式作出对状态信息的请求:
rAPP,Status Request
其中,rAPP是由应用程序生成的随机数,“Status Request”是对该状态信息的实际请求。响应于从应用程序接收状态请求,驱动程序软件206确认合适的任何状态信息,并将该状态信息连同适当的状态序列号一起提供给包封的数据段。另外,驱动程序软件也计算状态信息以及由应用程序提供的随机数的MAC。状态消息然后以下列形式被提供回应用程序:
rAPP,Status,MACkDI(rAPP,Status)
其中,“Status”不仅包括状态信息,还包括状态序列号。消息的MACkDI(rAPP,Status)部分包括由应用程序提供的随机数和状态信息的MAC。当应用程序接收状态信息时,它可通过在随机数和状态信息上运行MAC算法来计算随机数和状态信息的MAC,然后可将该值与消息的MACkDI(rAPP,Status)部分中的值进行比较。由此,应用程序可确认状态消息是真实的。应用程序然后可使用消息的内容来验证该消息是否以正确的顺序(通过序列号),以及该状态信息是否涉及先前由应用程序发送的状态请求(通过随机数rAPP)。
在一个示例中,下表中陈述的值和描述可用于上述过程。
值 |
描述 |
rAPP |
由应用程序生成的128位随机数 |
Status |
可变长度状态数据 |
MACkDI(rAPP,Status) |
使用数据完整性会话密钥kDI,对由应用程序提供的状态数据、状态序列号和随 |
示例性方法
图6示出了依照一个实施例的方法中的步骤。该方法可以结合任一合适的硬件、软件、固件或其组合来实现。另外,在某些软件实现中,本发明的各方面可以被实现为驻留在一个或多个计算机可读介质上,并可被执行来实现所描述的方法的计算机可读指令。在本示例中,所示的方法被分割成两部分-其中一部分被标记为“应用程序”,另一部分被标记为“下游组件”。这样做的目的是示出哪些实体执行要描述的动作。因此,出现在标签“应用程序”下的动作由应用程序执行,出现在标签“下游组件”下的动作由驻留在应用程序下游的组件执行。在一个实施例中,下游组件可包括驱动程序软件或处理媒体数据的相关联的硬件的软件表示。在另一实施例中,下游组件可包括硬件元件本身。
上文结合图2-5示出并描述了实现所描述的方法的一个示例性系统。可以理解并明白,也可以使用其它系统而不脱离本发明的精神和范围。
步骤600从一回放应用程序确定一与下游组件相关联的公钥。如何完成这一过程的示例已在上文给出。步骤602使用该公钥在回放应用程序和下游组件建立一安全信道。步骤600和602共同在回放应用程序和下游组件之间建立了信任。如何建立这一信任的一个示例已在上文结合图3描述。当然,也可以使用其它方法而不脱离本发明的精神和范围。
步骤604使用安全信道向下游组件发送命令消息。可使用任一合适的命令消息格式,其一个示例在上文结合图4给出。另外,可将任一合适和/或适当类型的命令从应用程序发送到下游组件。在一个实施例中,可发送的命令指示下游组件启用一种特定类型的内容保护技术,以保护要由系统处理的媒体内容或数据。
步骤606通过安全信道接收命令消息。这一步骤由向其发送命令消息的下游组件执行。步骤608然后验证命令消息的完整性。任一合适的方法可用于验证命令消息的完整性,其一个示例已结合图4给出。一旦验证了命令消息的完整性,步骤610实现包含在该命令消息中的相关联的命令。
步骤612使用安全信道向下游组件发送状态请求。可使用任一合适类型的状态请求结构,其一个示例已在上文结合图5给出。步骤614通过安全信道接收状态请求,步骤616作为响应准备状态消息,并使用安全信道将该状态消息发送到应用程序。可使用任一合适的状态消息结构,其一个示例已在上文结合图5给出。
步骤618通过安全信道接收状态消息,步骤620验证状态消息的完整性。可使用任一合适的方法来验证状态消息的完整性,其一个示例在上文给出。
在Windows操作系统上协议的示例性实现
系统综述
图7一般在700示出了可用于实现上述安全信道协议的系统。在以下的讨论中,本创造性协议被称为经证明的输出保护协议或“COPP”。在本示例中,使用MicrosoftDirectShow作为一个示例,它是流媒体的体系结构。如本领域的技术人员可以理解的,MicrosoftDirectShow提供了高质量的媒体流回放,并支持各种各样的格式,包括高级流格式(ASF)、运动图像专家组(MPEG)、音频-视频交错(AVI)、MPEG音频第3层(MP3)和WAV文件。
为达到流传送视频和音频数据所需的吞吐量,DirectShow使用MicrosoftDirectDraw和MicrosoftDirectSound来有效地向系统的声音和图形卡呈现数据。DirectDraw是DirectX的一个显示组件,它允许软件设计者直接操纵显示存储器、硬件位块传送器(blitter)、硬件覆盖和翻转表面,这是本领域的技术人员所理解的。DirectDraw提供了以直接的32位路径对设备专用显示功能的独立于设备的访问。64位路径也可存在于Windows的64位版本中。DirectDraw调用驱动程序中直接访问显卡的重要功能,而不会干涉Windows的图形设备接口(GDI)或与设备无关的位图(DIB)引擎。
在DirectShow中,同步是通过在加了时间标记的媒体样值中封装媒体数据来实现的。为处理各种不同的媒体源、格式和硬件设备,DirectShow使用一种模块化体系结构,其中,被称为过滤器的操作系统组件可被混合,并被匹配以提供对不同情形的支持。在所示的示例中,这些过滤器可以被集合成一过滤器图704,它由回放应用程序702使用以促使多媒体数据由硬件设备处理并呈现。
在这一特定的示例中,过滤器图704包括读取媒体内容的源过滤器706,以及解压内容的解码器708(如,WMV或MPEG-2解码器)。视频呈现组件710接收经解压的内容或数据,并理解要在其上呈现内容的硬件。在这一特定的示例中,有两种不同类型的呈现组件可以使用-VMR7(写入DirectX版本7 SDK中的视频混合呈现程序版本7)以及VMR9(写入DirectX版本9 SDK中的视频混合呈现程序版本9)组件。
在所示的示例中,提供了用户模式DirectDraw组件712,它是由DirectDraw应用程序加载并调用的系统提供的动态链接库(DLL)。该组件提供了硬件仿真、管理各种DirectDraw对象、并提供显示存储器和显示管理服务,这些都是本领域的技术人员所理解的。
另外,提供了内核模式DirectDraw组件714,它是win32k.sys的一个整体部分。内核模式组件714是由内核模式显示驱动程序加载的系统提供的图形引擎。该组件执行驱动程序的参数确认,由此能够容易地实现更多健壮的驱动程序。提供了DirectDraw图形驱动程序716,它通常由第三方硬件销售商实现。
在操作中,受保护的内容通常具有与其相关联的某一组政策。政策可规定在呈现相关联的内容时所使用的内容保护的类型和级别。例如,如果内容要通过DVI连接器来播放,则政策可规定必须启用HDCP,否则不能播放内容。
在本示例中,应用程序702知道与内容相关联的政策。实际上,源过滤器706可包括负责确定与内容相关联的政策,然后通知应用程序的组件。
用户模式应用程序接口(API)
一旦提取了政策并确认了政策含义,则系统700首先确认是否可以在这一特定系统中实施该政策。在这一特定示例中实现这一过程的方法是通过一用户模式应用程序接口(API),它被称为IAMCertifiedOutputProtection,由视频呈现组件710展示。依照一个实施例,IAMCertifiedOutputProtection接口由以下方法构成,这些方法由应用程序调用:
typedef struct_AMCOPPSignature{
BYTE Signature[256];
}AMCOPPSignature;
typedef struct_AMCOPPCommand{
GUID macKDI; // 16字节
GUID guidCommandID; // 16字节
DWORD dwSequence; // 4字节
DWORD cbSizeData; // 4字节
BYTE CommandData[4056];//4056字节(4056+4+4+16+16=4096)
}AMCOPPCommand,*LPAMCOPPCommand;
typedef struct_AMCOPPStatusInput{
GUID rApp; // 16字节
<dp n="d10"/>
GUID guidStatusRequestID;// 16字节
DWORD dwSequence; // 4字节
DWORD cbSizeData; // 4字节
BYTE StatusData[4056]; //4056字节(4056+4+4+16+16=4096)
}AMCOPPStatusInput,*LPAMCOPPStatusInput;
typedef struct_AMCOPPStatusOutput {
GUID macKDI; // 16字节
DWORD cbSizeData; // 4字节
BYTE COPPStatus[4076];//4076字节(4076+16+4=4096)
}AMCOPPStatusOutput,*LPAMCOPPStatusOutput;
IAMCertifiedoutputProtection
HRESULT KeyExchange(
[out] DWORD*pdwRandom 由图形驱动程序生成的32位随机数
[out] BYTE**VarLenCertGH, 图形硬件证书,由CoTaskMemFree释
放的存储器
[out] DWORD*pdwLengthCertGH); 图形硬件证书的长度
HRESULT SessionSequenceStart(
[in] AMCOPPSignature*pSig); 来自图形驱动程序的32位随机数、128位
随机数据安全会话密钥、128位随机数据
完整性会话密钥、32位随机起始状态序列
号和32位随机起始命令序列号的串接,由
图形硬件的公钥加密。该值的长度为2048
比特。
HRESULT ProtectionCommand(
[in] const AMCOPPCommand* 经加密的命令
cmd,
HRESULT ProtectionStatus(
[in] const AMCOPPStatusInput* 在其上请求状态的特征的描述
pInput,
[out] AMCOPPStatusOutput* 返回的状态信息
pOutput);
在上述示例中,AMCOPPCommand结构是应用程序用于向下游组件发送命令的数据结构,并可在诸如图4所示的交换中使用。AMCOPPStatusInput结构是应用程序用于作出状态请求的数据结构,并可在诸如图5的左侧所示的交换中使用。AMCOPPStatusOutput是图形驱动程序用于向应用程序提供回状态信息的数据结构,并可在诸如图5的右侧示出的交换中使用。
内核模式DDI(DX-VA)
DX-VA经证明的输出保护协议(COPP)提供了用于将命令从诸如回放应用程序702等用户模式应用程序传递到诸如图形驱动程序716等驱动程序,并用于将状态从驱动程序返回到用户模式应用程序的手段。如上所述,命令和状态所流过的信道是受到保护的。
在这一特定实现中,内容输出保护协议使用DX-VA COPP设备,它在下文中详细描述。在以下讨论中,使用以下术语:
●视频流:视频流是包括显示的视频帧的主要图像数据。来自视频流的像素总是不透明的,并不包含任何每像素字母数据。
●视频子流:视频子流是需要在显示组合的视频帧之前与视频流的样值复合的辅助图像数据的信道。视频子流的示例是NTSC被关闭的字母图像,DVD子图图像以及TAL图文电视图像。视频子流的另一特征是它们包含有限的颜色范围和每像素字母信息。
●视频会话:视频会话由视频流和可能的一个或多个视频子流构成,视频子流在连接到计算机的输出设备上显示之前与视频流组合。在任一特定的时刻在计算机上可能有若干视频会话是活动的,在单个进程内也可以有若干视频会话是活动的。
●DX-VA COPP设备:支持通过内容输出保护协议接收命令和状态请求的一种新DX-VA设备。
●连接器:图形硬件和显示设备之间的物理输出连接。
●保护类型:可应用于通过连接器传递的信号的保护类型;可向单个连接器应用一个以上保护类型。
●保护级别:应用于通过连接器传递的信号的保护级别。该值依赖于保护类型-某些保护类型,例如示例HDCP只有两种保护级别,为“开”和“关”。
设计综述
依照本实施例,为每一视频会话创建一被称为DX-VA COPP设备的单个组件。在图7的示例中,在驱动程序716内示出了两个示例性DX-VA COPP设备。DX-VACOPP设备表示COPP命令和状态请求的端点。另外,DX-VA COPP设备可虚拟化物理连接器的保护设置。单个物理连接器支持多个内容保护类型是可能的。例如,S-Video连接器可支持模拟内容保护以及CGMS-A Line20保护和CGMS-A Line21保护。在本文档中稍后给出的COPP示例设备驱动程序代码示出了如何可由驱动程序实现COPP设备的一个示例。
在所示并描述的实施例中每一DX-VA COPP设备被配置成当多个视频会话在计算机上活动时适当地运作。在此情况中,当不同的进程试图通过COPP配置输出显示适配器时,要求驱动程序716创建COPP DX-VA设备的多个实例。在本示例中,由驱动程序716创建了DX-VA COPP设备的两个实例。
局部和全局引用计数
对于支持内容保护的每一物理连接器,驱动程序716应当对每一类型和每一级别维护一全局引用计数。在所示并描述的实施例中,驱动程序716包括一全局状态组件,它维护该全局状态。
当为视频会话创建COPP DX-VA设备时,设备应当包含每一保护级别处的每一保护类型的局部引用计数。这由每一设备内的当前保护级别组件表示。保护类型的默认级别计数器应当被设为值1,该类型的所有其它保护级别计数器应当被设为值0。
当视频会话设置特定保护类型的新保护级别时,递减当前保护级别的引用计数,并递增新保护级别的引用计数。也可以对全局引用级别计数器作出相应的改变。
只要任一全局级别计数器改变,驱动程序应当调查该连接器的所有计数器,并确认保护级别被设为对应于其值大于0的最高级别计数器的级别。在本实例中,对一相关联的物理连接器,有两种不同的保护级别-级别A和级别B。注意,全局状态组件指示级别B保护被应用于物理连接器。由此,级别B是可应用于物理连接器的保护级别中的较高者。如果DX-VA COPP设备2终止,则全局状态组件将向物理连接器应用保护级别A。以下的示例性代码样例示出了如何完成这一过程。
尽管全局引用计数器大于0,然而内容保护应当被应用于输出连接器。一旦全局引用计数器达到0,则应当从输出连接器中移除内容保护。只要驱动程序接收DestroyDevice调用,全局引用计数器应当被递减设备局部引用计数器的当前级别。应当仅在该连接器的全局引用计数器达到0时才移除连接器保护。
应当注意,DestroyDevice可在设备仍具有大于0的局部引用计数器时被调用,其一个实例是如果用户模式被异常终止时。
视频会话初始化
在所示并描述的实施例中,视频会话与特定的物理输出连接器联系在一起。在显示驱动程序级,视频会话由以下步骤初始化:
●调用GetMoCompGuids以确定是否支持该输出连接器的DX-VA COPP。
●假定驱动程序不支持该输出连接器的DX-VA COPP设备,则调用CreateMoComp来创建DX-VA COPP设备。
●用DXVA_COPPGetCertificateLengthFnCode函数代码来调用RenderMoComp,以确定应当用于该会话的可变长度图形硬件证书的长度。
●用DXVA_COPPKeyExchangeFnCode函数代码来调用RenderMoComp,以将视频会话应用程序证书传递到驱动程序。驱动程序返回128位的私钥和其可变长度图形硬件证书的副本。
●最后,用DXVA_COPPSequenceStartFnCode函数代码来调用RenderMoComp,以指示用32位命令序列起始码和32位状态序列起始码开始了视频会话。
个别的DX-VA RenderMoComp函数代码在下文中给出。
处理设备丢失情况
以下情况将导致驱动程序中的DestroyMoComp入口点被调用,而仍对特定的视频会话启用输出内容保护:
●显示模式改变;
●向Windows桌面附加或撤除监视器;
●进入全屏DOS框;
●开始任何DDraw或D3D专有模式应用程序;
●快速用户切换;
●从Windows桌面添加或移除监视器;
●在WindowsXP专业版上锁定工作站或按下Alt-Ctrl-Del;
●通过“远程桌面连接”附加到工作站;
●进入省电模式,如“待机”或“休眠”:以及
●意外的应用程序终止,例如“页面错误”。
当出现这些情况时,驱动程序应当将全局保护级别计数递减被破坏的设备的当前局部保护级别计数。应当检查改变的全局保护级别,并且相应地调整应用到输出连接器的保护。
DX-VA命令
以下讨论描述了图形驱动程序所支持的若干命令或函数,尤其是个别的DX-VA COPP设备。
COPPOpenVideoSession
该函数初始化用于特定视频会话的COPP DX-VA设备。
HRESULT DXVA_COPPDeviceClass::COPPOpenVideoSession(
DWORD dwDeviceID
);
COPPPCloseVideoSession
该函数终止用于视频会话的COPP DX-VA设备。
HRESULT DXVA_COPPDeviceClass::COPPCloseVideoSession();
可能调用了该函数,而仍由视频会话应用输出保护。驱动程序应当撤消该DX-VA COPP设备的保护设置,并相应地调整全局保护设置。
COPPGetCertificateLength
这是新创建的COPP DX-VA设备将接收到的第一个函数调用。它由视频呈现组件710用于查询图形硬件所使用的证书的长度,以字节表示。驱动程序应当在DD-RENDERMOCOMPDATA结构的lpOutputData字段中返回正确的长度。
HRESULT DXVA_COPPDeviceClass::COPPGetCertificateLength(
[out] DWORD* pCertificateLength
);
COPPKeyExchange
这是新创建的COPP DX-VA设备将接收的第二个函数调用。驱动程序应当返回图形硬件的可变长度数字证书。DD_RENDERMOCOMPDATA结构的lpOutputData字段指向DXVA_COPPKeyExchangeOutput结构;DXVA_COPPVariableLengthData具有如前一COPPGetCertificateLength DXVA命令中所指示的证书所需的空间量。
typedef struct_DXVA_COPPSignature {
BYTE Signature[256];
} DXVA_COPPSignature,*LPDXVA_COPPSignature;
typedef struct_DXVA_COPPVariableLengthData {
DWORD Size;
BYTE Data[4];
} DXVA_COPPVariableLengthData,*LPDXVA_COPPVariableLengthData;
typedef struct_DXVA_COPPKeyExchangeOutput {
DWORD RandomNumber;
DXVA_COPPVariableLengthData Certificate;
} DXVA_COPPKeyExchangeOutput,*LPDXVA_COPPKeyExchangeOutput;
HRESULT DXVA_COPPDeviceClass::COPPKeyExchange(
[out] DWORD* pdwRandom,
[out] DXVA_COPPVariableLengthData* pGHCertificate
);
COPPSequenceStart
这是新创建的DX-VA COPP设备将接收的第三个函数调用。驱动程序将接收128位随机数据完整性会话密钥、32位随机起始状态序列号和32位随机起始命令序列号的串接,用图形硬件的公钥加密。如果在接收COPPKeyExchange函数调用前接收这一函数调用,或如果接收了后续的XOPPSequenceStart调用,则驱动程序应当返回E_UNEXPECTED。
HRESULT DXVA_COPPDeviceClass::COPPSequenceStart(
[in] DXVACOPPSignature* pSeqStartInfo
);
COPPCommand
COPP命令可包括来自视频会话的指令,以改变与DX-VA COPP设备相关联的物理连接器上的保护级别。如上所述,驱动程序应当能够支持多个视频会话,它们都通过同一物理连接器回放内容。
typedef struct_DXVACOPPCommand {
GUID macKDI; // 16字节
GUID guidCommandID; // 16字节
DWORD dwSequence; // 4字节
DWORD cbSizeData; // 4字节
BYTE CommandData[4056];//4056字节(4056+4+4+16+16=4096)
<dp n="d16"/>
} DXVA_COPPCommand,*LPDXVA_COPPCommand;
typedef struct_DXVA_COPPSetProtectionLevelCmdData {
DWORD ProtType;
DWORD ProtLevel;
} DXVA_COPPSetProtectionLevelCmdData;
DEFINE_GUID(DXVA_COPPSetProtectionLevel,
0xgbb9327c,0x4eb5,0x4727,0x9f,0x00,0xb4,0x2b,0x09,0x19,0xc0,0xda);
HRESULT DXVA_COPPDeviceClass::COPPCommand(
[in] DXVA_COPPCommand* pCommand
);
如果在接收COPPKeyExchange或COPPSequenceStart函数调用之前接收了该函数调用,驱动程序应当返回E_UNEXPECTED。同样,驱动程序应当确保传递到它的参数对使用的给定物理连接器是有效的。如果传递到COPPCommand的一个或多个参数是无效的,则驱动程序应当返回E_INVALIDARG。
下表列出了依照本实施例驱动程序可看见的DX-VA COPP命令集。
GUID |
CommandData参数的解释 |
描述 |
DXVA_COPPSetProtectionLevel9bb9327c-4eb5-4727-9f00b42b0919c0da |
DXVA_COPPSetProtectionLevelCmdDataProtType成员变量的有效值为:COPP_ProtectionType_ACPCOPP_ProtectionType_CGMSACOPP_ProtectionType_HDCP |
将指定的保护类型设为指定的保护级别。 |
定义的COPP命令
COPPQueryStatus
COPPQueryStatus是来自视频会话的请求,它检索关于所使用的物理连接器、可应用到通过物理连接器发送的内容的保护类型、以及物理连接器上活动的当前保护级别的信息。对于调用应用的顺序的相同的限制为:如果在此视频会话的COPPKeyExchange或COPPSequenceStart调用之前接收到此调用,则驱动程序应当返回E_UNEXPECTED。
typedef struct_DXVA_COPPStatusInput {
GUID rApp; // 16字节
GUID guidStatusRequestID;// 16字节
DWORD dwSequence; // 4字节
DWORD cbSizeData; // 4字节
BYTE StatusData[4056];//4056字节(4056+4+4+16+16=4096)
} DXVA_COPPStatusInput,*LPDXVA_COPPStatusInput;
<dp n="d17"/>
typedef struct_DXVA_COPPStatusOutput {
GUID macKDI; // 16字节
DWORD cbSizeData; // 4字节
BYTE COPPStatus[4076];// 4076字节(4076+16+4=4096)
} DXVA_COPPStatusOutput,*LPDXVA_COPPStatusOutput;
HRESULT DXVA_COPPDeviceClass::COPPQueryStatus(
[out] DXVA_COPPStatusInput* pInput,
[out] DXVA_COPPStatusOutput* pOutput
);
下表列出了依照本实施例驱动程序应当见到的一组DX-VA状态请求。
GUID |
输入数据 |
返回的数据 |
描述 |
DXVA_COPPQueryConnectorType81d0bfd5-6afe-48c2-99c0-95a08f97c5da |
无 |
rAPP(GUID 16字节)加上DWORD(4字节)COPP_ConnectorType_UnknownCOPP_ConnectorType_VGACOPP_ConnectorType_SVideoCOPP_ConnectorType_CompositeVideoCOPP_ConnectorType_ComponentVideoCOPP_ConnectorType_DVICOPP_ConnectorType_HDMICOPP_ConnectorType_LVDS |
返回标识视频会话当前正在使用的物理连接器类型的值。 |
DXVA_COPPQueryProtectionType38f2a801-9a6c-48bb-9107-b6696e6f1797 |
无 |
rAPP(GUID 16字节)加上DWORD(4字节)COPP_ProtectionType_UnknownCOPP_ProtectionType_NoneCOPP_ProtectionType_ACPCOPP_ProtectionType_CGMSACOPP_ProtectionType_HDCP |
返回物理连接器的可用保护机制。如果在物理连接器上支持多个保护类型,这些值可以被进行“或”运算。 |
DXVA_COPPQueryLocalProtectionLevelb2075857-3eda-4d5d-88db-748f8c1a0549 |
DWORD(4字节)-标识在其上需要状态的保护类型。COPP_ProtectionType_ACPCOPP_ProtectionType_CGMSACOPP_ProtectionType_HDCP |
rAPP(GUID 16字节)加上2×DWORD(8字节)第一个DWORD标识了指定的保护类型的保护级别,返回的实际值取决于该连接器的保护类型。第二个DWORD标识了计算机和显示设备之间的连接的完整性。返回的值可以是以下的任一个:COPP_LinkActiveCOPP_LinkLost |
返回为视频会话当前设置的保护级别 |
DXVA_COPPQueryGlobalProtectionLevel1957210a-7766-452a-b99a-d27aed54f03 |
DWORD(4字节)-标识在其上需要状态的保护类型。COPP_ProtectionT |
rAPP(GuID 16字节)加上2×DWORD(8字节)第一个DWORD标识了指定的保护类型的保护级别,返回的实际值取决于该连接器的保 |
返回对物理连接器当前设置的保护级别。 |
a |
ype_ACPCOPP_ProtectionType_CGMSACOPP_ProtectionType_HDCP |
护类型。第二个DWORD标识了计算机和显示设备之间的连接的完整性。返回的值可以是以下的任一个:COPP_LinkActiveCOPP_LinkLost |
|
定义的COPP状态请求
用户模式API的DDI映射
在这一特定的实现实例中,并且为了与Windows操作系统的DDI基础结构兼容,本文档中先前描述的API必须被“映射”到DirectDraw和DirectX VA现有的DDI。如本领域的技术人员所理解的,这些映射操作有助于避免对内核模式组件作出重大的改变。由此,本节和以下讨论描述了映射到现有的DirectDraw和DX-VADDI的COPP接口。
DX-VA DDI本身被分割成两个功能组:“DX-VA容器”和“DX-VA设备”。DX-VA容器DDI组的目的是确定显示硬件包含的各种DX-VA设备的数量和性能。因此,在本实现示例中,一个DX-VA驱动程序只能有一个容器,但是它可支持多个DX-VA设备。
本节的其余部分描述了如何将上述接口映射到DX-VA设备DDI。应当注意,与其它DX-VA DDI不同,COPP设备从不引用任何视频存储器表面。
从用户模式组件调用DDI
从用户模式组件,如视频呈现组件710(图7)使用DDI的步骤顺序如下:
1.调用GetMoCompGuids以获取驱动程序所支持的DX-VA设备。
2.调用CreateMoComp以为视频会话建立COPP设备,其中,COPP设备GUID定义如下:
DEFINE_GUID(DXVA_COPPDevice,
0xd2457add,0x8999,0x45ed,0x8a,0x8a,0xd1,0xaa,0x04,0x7b,0xa4,0xd5);
3.视频呈现组件然后用取决于所请求的COPP操作的类型的各种函数参数值调用COPP设备的RenderMoComp。
4.当视频呈现组件不再需要执行任何COPP操作时,它调用DestroyMoComp。
5.驱动程序释放COPP设备所使用的任何资源。
COPPOpenVideoSession
该方法直接映射到DD_MOTIONCOMPCALLBACKS结构的CreateMoComp方法,其中,GUID是COPP设备GUID,pUncompData指向不包含任何数据(全0)的结构,pData指向NULL。
应当理解和明白,如果驱动程序支持压缩视频的加速解码,则视频呈现组件将调用驱动程序来创建两个DX-VA设备-一个执行由DirectX VA视频解码规范定义的实际视频解码工作,另一个严格地用于遵循内容输出保护协议向输出连接器应用保护。
示例:将CreateMoComp映射到COPPOpenVideoSession
以下提供的示例代码示出了驱动程序应当如何将CreateMoComp DDI调用映射到COPPOpenVideoSession。示例代码仅示出了如何对COPP使用CreateMoComp函数。如果驱动程序支持其它DX-VA功能,如解码MPEG-2视频帧,则以下示例代码可被扩充以包括额外的DX-VA GUID的处理。
DWORD APIENTRY
CreateMoComp(
LPDDHAL_CREATEMOCOMPDATA lpData
)
{
AMTRACE((TEXT(″CreateMoComp″)));
if(!ValidDXVAGuid(lpData->lpGuid))
{
DbgLog((LOG_ERROR,1,
TEXT(″No formats supported for this GUID″)));
lpData->ddRVal=E_INVALIDARG;
return DDHAL_DRIVER_HANDLED;
}
if (*lpData->lpGuid==DXVA_COPPDevice)
{
DXVA_COPPDeviceClass* lpDev=
new DXVA_COPPDeviceClass(*lpData->lpGuid,DXVA_DeviceCOPP);
if (lpDev)
{
DWORD DevID=(DWORD)-1;
lpData->ddRVal=E_INVALIDARG;
if (DevID !=(DWORD)-1)
{
lpData->ddRVal=lpDev->COPPOpenVideoSession(DevID);
}
<dp n="d21"/>
if(lpData->ddRVal !=DD_OK)
{
delete lpDev;
lpDev=NULL;
}
}
else
{
lpData->ddRVal=E_OUTOFMEMORY;
}
lpData->lpMoComp->lpDriverReserved1=
(LPVOID)(DXVA_DeviceBaseClass*)lpDev;
return DDHAL_DRIVER_HANDLED;
}
lpData->ddRVal=DDERR_CURRENTLYNOTAVAIL;
return DDHAL_DRIVER_HANDLED;
}
示例:实现GetMoCompGuids
除CreateMoComp函数之外,驱动程序应当也实现DD_MOTIONCOMPCALLBACKS结构的GetMoCompGuids方法。以下示例代码示出了在驱动程序中实现这一功能的一个可能的方法。
DWORD g_dwDXVANumSupportedGUIDs=1;
const GUID* g_DXVASupportedGUIDs[1]= {
&DXVA_COPPDevice
};
DWORD APIENTRY
GetMoCompGuids(
PDD_GETMOCOMPGUIDSDATA lpData
)
{
DWORD dwNumToCopy;
if(lpData->lpGuids) {
dwNumToCopy=min(g_dwDXVANumSupportedGUIDs,
lpData->dwNumGuids);
for (DWORD i=0;i<dwNumToCopy;i++) {
lpData->lpGuids[i]=*g_DXVASupportedGUIDs[i];
}
}
else{
dwNumToCopy=g_dwDXVANumSupportedGUIDs;
}
lpData->dwNumGuids=dwNumToCopy;
lpData->ddRVal=DD_OK;
return DDHAL_DRIVER_HANDLED;
COPPGetCertificateLength
本发明直接映射到D_MOTIONCOMPCALLBACKS结构的RenderMoComp方法,其中:
●dwNumBuffers为0。
●lpBufferInfo为NULL。
●dwFunction被定义为DXVA_COPPGetCertificateLengthFnCode。
●lpInputData为NULL。
●lpOutputData指向单个DWORD。
注意,对于用于COPP的DX-VA设备,将调用RenderMoComp而不调用BeginMoCompFrame或EndMoCompFrame。
示例:将RenderMoComp映射到COPPGetCertificateLength
以下示例代码示出了驱动程序应当如何将RenderMoComp DDI调用映射到COPPGetCertificateLength调用。示例代码仅示出了如何对COPP控制使用RenderMoComp。如果驱动程序支持其它DX-VA功能,如解码MPEG-2视频流,则示例代码可被扩充以包括额外的DX-VA GUID的处理。
DWORD APIENTRY
RenderMoComp(
LPDDHAL_RENDERMOCOMPDATA lpData
)
{
AMTRACE((TEXT(″RenderMoComp″)));
DXVA_DeviceBaseClass* pDXVABase=
(DXVA_DeviceBaseClass*)lpData->lpMoComp->lpDriverReservedl;
if(pDXVABase==NULL) {
lpData->ddRVal=E_POINTER;
return DDHAL_DRIVER_HANDLED;
}
switch(pDXVABase->m_DeviceType) {
case DXVA_DeviceCOPP:
{
DXVA_COPPDeviceClass* pDXVACopp=
(DXVA_COPPDeviceClass*)lpData->lpMoComp->lpDriverReservedl;
switch(lpData->dwFunction)
{
case DXVA_COPPGetCertificateLengthFnCode:
{
if(lpData->dwOutputDataSize<sizeof(DWORD))
{
lpData->ddRVal=E_INVALIDARG;
}
else
{
lpData->ddRVal=pDXVACopp->COPPGetCertificateLength(
(DWORD*)lpData->lpOutputData);
<dp n="d23"/>
}
}
break;
COPPKeyExchange
该方法直接映射到D_MOTIONCOMPCALLBACKS结构的RenderMoComp方法,其中:
●dwNumBuffers为0。
●lpBufferInfo为NULL。
●dwFunction被定义为DXVA_COPPKeyExchangeFnCode。
●lpInputData为NULL。
●lpOutputData指向DXVA_COPPKeyExchangeOutput数据结构。
注意,对于用于COPP的DX-VA设备,将调用RenderMoComp而不调用BeginMoCompFrame或EndMoCompFrame。
示例:将RenderMoComp映射到COPPKeyExchange
以下示例代码示出了驱动程序应当如何将RenderMoComp DDI调用映射到COPPKeyExchange调用。示例代码仅示出了如何对COPP控制使用RenderMoComp。如果驱动程序支持其它DX-VA功能,如解码MPEG-2视频流,则示例代码可被扩充以包括额外的DX-VA GUID的处理。
case DXVA_COPPKeyExchangeFnCode:
{
DXVA_COPPKeyExchangeOutput* lpout=
(DXVA_COPPKeyExchangeOutput*)lpData->lpOutputData;
lpData->ddRVal=pDXVACopp->COPPKeyExchange(
&lpout->RandomNumber,
&lpout->Certificate);
}
break;
COPPSequenceStart
该方法直接映射到D_MOTIONCOMPCALLBACKS结构的RenderMoComp方法,其中:
●dwNumBuffers为0。
●lpBufferInfo为NULL。
●dwFunction被定义为DXVA_COPPSequenceStartFnCode。
●lpInputData指向DXVA_COPPSignature数据结构。
●lpOutputData为NULL。
注意,对于用于COPP的DX-VA设备,将调用RenderMoComp而不调用BeginMoCompFrame或EndMoCompFrame。
示例:将RenderMoComp映射到COPPSequenceStart
以下示例代码示出了驱动程序应当如何将RenderMoComp DDI调用映射到COPPSequenceStart调用。示例代码仅示出了如何对COPP控制使用RenderMoComp。如果驱动程序支持DX-VA其它功能,如解码MPEG-2视频流,则示例代码可被扩展以包括额外的DX-VA GUID的处理。
case DXVA_COPPSequenceStartFnCode:
{
DXVA_COPPSignature* lpin=
(DXVA_COPPSignature*)lpData->lpInputData;
lpData->ddRVal=pDXVACopp->COPPSequenceStart(lpin);
}
break;
COPPCommand
本方法直接映射到D_MOTIONCOMPCALLBACKS结构的RenderMoComp方法,其中:
●dwNumBuffers为0。
●lpBufferInfo为NULL。
●dwFunction被定义为DXVA_COPPCommandFnCode。
●lpInputData指向DXVA_COPPCommand数据结构。
●lpOutputData为NULL。
注意,对于用于COPP的DX-VA设备,将调用RenderMoComp而不调用
BeginMoCompFrame或EndMoCompFrame。
示例:将RenderMoComp映射到COPPCommand
以下示例代码示出了驱动程序应当如何将RenderMoComp DDI调用映射到COPPCommand调用。示例代码仅示出了如何对COPP控制使用RenderMoComp。如果驱动程序支持其它DX-VA功能,如解码MPEG-2视频流,则示例代码可被扩展以包括额外的DX-VA GUID的处理。
case DXVA_COPPCommandFnCode :
{
DXVA_COPPCommand* lpin=
(DXVA_COPPCommand*)lpData->lpInputData;
lpData->ddRVal=pDXVACopp->COPPCommand(lpin);
}
break;
COPPQueryStatus
本方法直接映射到D_MOTIONCOMPCALLBACKS结构的RenderMoComp方法,其中:
●dwNumBuffers为0。
●lpBufferInfo为NULL。
●dwFuncfion被定义为DXVA_COPPQueryStatusFnCode。
●lpInputData指向DXVA_COPPStatusInput数据结构。
●lpOutputData指向DXVA_COPPStatusOutput数据结构。
注意,对于用于COPP的DX-VA设备,将调用RenderMoComp而不调用BeginMoCompFrame或EndMoCompFrame。
示例:将RenderMoComp映射到COPPQueryStatus
以下示例代码示出了驱动程序应当如何将RenderMoComp DDI调用映射到COPPQueryStatus调用。示例代码仅示出了如何对COPP控制使用RenderMoComp。如果驱动程序支持其它DX-VA功能,如解码MPEG-2视频流,则示例代码可被扩展以包括额外的DX-VA GUID的处理。
case DXVA_COPPQueryStatusFnCode:
{
DXVA_COPPStatusInput* lpin=(DXVA_COPPStatusInput*
lpData->lpInputData;
DXVA_COPPStatusOutput* lpout=(DXVA_COPPStatusOutput*)
lpData->lpOutputData;
lpData->ddRVal=pDXVACopp->COPPQueryStatus(lpin,lpout);
}
break;
default:
lpDara->ddRVal=E_INVALIDARG;
break;
}
break;
}
}
return DDHAL_DRIVER_HANDLED;
}
COPPCloseVideoSession
本方法直接映射到D_MOTIONCOMPCALLBACKS结构的DestroyMoComp方法。
示例:将DestroyMoComp映射到COPPCloseVideoSesion
以下示例代码示出了驱动程序应当如何将DestroyMoComp DDI调用映射到COPPCloseVideoSession调用。示例代码仅示出了如何对COPP控制使用DestroyMoComp。如果驱动程序支持其它DX-VA功能,如解码MPEG-2视频流,则示例代码可被如下扩展以包括额外的DX-VA GUID的处理。
DWORD APIENTRY
DestroyMoComp(
LPDDHAL_DESTROYMOCOMPDATA lpData
)
{
AMTRACE((TEXT(″DestroyMoComp″)));
DXVA_DeviceBaseClass* pDXVABase=
(DXVA_DeviceBaseClass*)lpData->lpMoComp->lpDriverReservedl;
if(pDXVABase==NULL) {
lpData->ddRVal=E_POINTER;
return DDHAL_DRIVER_HANDLED;
}
switch (pDXVABase->m_DeviceType) {
case DXVA_DeviceContainer:
case DXVA_DeviceDecoder:
case DXVA_DeviceDeinterlacer:
case DXVA_DeviceProcAmpControl:
lpData->ddRVal=DDERR_CURRENTLYNOTAVAIL;
break;
case DXVA_DeviceCOPP:
{
<dp n="d27"/>
DXVA_COPPDeviceClass* pDXVADev=(DXVA_COPPDeviceClass*)pDXVABase;
lpData->ddRVal=pDXVADev->COPPCloseVideoSession();
delete pDXVADev;
}
break;
}
总结
上述各种实施例通过在诸如运行受保护内容回放应用程序的计算机等设备,和相关联的显示设备的诸如图形驱动程序等相关联的驱动程序之间建立一安全信道,并在某些实施例中建立安全数据信道,启用了媒体内容保护,相关联的显示设备如监视器、平板LCD、电视机等等。各种实施例通过使用物理地链接计算机及其显示设备的输出适配器作为受保护的视频路径的网关,解决了内容提供商和应用程序销售商发信号通知应当向媒体输出施加内容保护的需求。
各种实施例提供了安全地将命令从源用户模式回放应用程序传递到诸如图形驱动程序等驱动程序,并安全地将状态从驱动程序返回到用户模式应用程序的装置。所描述的实施例建立了一安全通信信道,并允许用户模式应用程序指令相关联的驱动程序在计算机和显示设备之间的连接器上启用内容输出保护。
尽管以对结构特征和/或方法步骤专用的语言描述了本发明,然而可以理解,所附权利要求书中定义的本发明不限于所描述的具体特征或步骤。相反,揭示了具体特征和步骤作为实现本发明的较佳形式。