1.1 Summary of Kernel Streaming Concepts
1.1.1 Kernel Streaming Client Interface:
Ks以一系列file object向应用程序表现driver的不同功能。应用程序传下I/O和request给file object去控制驱动的不同功能。
Ks dirver 的file object有如下不同成员:
1. Filters
Ks filter封装设备的功能单元。一个driver可以支持相同filter的多个实例。一个多功能设备的driver可以支持多个不同类型的ks filter。不要混淆KS filters 和 filter drivers,每一种ks driver,不管是function或filter driver,都可创建有一个或多个ks filter file object.
2. Pins
Pin表现设备上的I/O通道,应用程序可以连接pin,可以将pin相互连接,可以请求一个它支持的数据类型的pin。
3. Clocks
驱动支持板上时钟,以file object表现时钟,应用程序可申请计时器,也可请求在某时刻通报时间。
4. Allocators
驱动支持定制内存管理接口,例如板上内存管理以file object表现接口,应用程序可用File boject来分配和处理内存。
Ks file object分层次的组织起来,应用程序用IRP_MJ_CREATE显示driver上的ks filter,再依次用IRP_MJ_CREATE显示filter上的pin,clock和内存分配器。
Ks结构为driver和应用程序提供相互作用的可扩展的机制。Ks对象支持如下不同的概念:
1. Properties
Ks对象支持properties。应用程序可以通过请求对象来确定它所支持的properties类型。可获得或设置此properties。例如音频驱动pins可提供properties允许应用程序获得或设置设备音量。
2. Events
Ks对象可定义它支持的一步时间类型。应用程序通过请求对象来确定它支持的事件,也可请求通报事件发生的时间。例如,应用程序可请求时钟对象在某特定时间通报它。
3. Methods
象COM对象一样,ks对象支持Methods。例如,分配器对象支持Methods来分配和处理内存。
微软定义一系列标准的properties, events, and methods,应用程序和驱动可以支持这些设置来协作处理标准的多媒体类型。驱动可支持定制系列的properties, events, and methods,设备用它们和其特有的功能相合。
应用程序通过系列的IRP_MJ_DEVICE_CONTROL来与ks object联系,并指定和说明IO_STACK_LOCATION中IRP里的驱动和ks对象成员。
• IOCTL_KS_READ_STREAM
Clients use this to read data from a pin.
• IOCTL_KS_WRITE_STREAM
Clients use this to read data from a pin.
• IOCTL_KS_PROPERTY
Clients use this IOCTL to get or set properties, or to determine the properties supported by a KS object.
• IOCTL_KS_ENABLE_EVENT
Clients use this IOCTL to request notification of an event type, or to determine the events supported by a KS object.
• IOCTL_KS_DISABLE_EVENT
Clients use this IOCTL to rescind a previous request notification.
• IOCTL_KS_METHOD
Clients use this IOCTL to execute a method on a KS object.
驱动不用直接支持这些I/O请求。微软用class driver来处理这些复杂的请求。祥看:
Kernel Streaming Driver Implementation
1.1.2 Kernel Streaming Driver Implementation
为简化内核流驱动开发,微软提供两个class driver来处理内核流的工作。
audio port class driver支持系统总线的内部音频卡,如ISA或PCI。
stream class driver 支持其他类型的内核流驱动,包括DVD设备,video capture devices, 和 external sound devices.
每一个class driver提供一个接口来支持内核流对象及其I/O请求。驱动提供一个关于它所支持的ks对象描述,class driver很容易的处理所创建的file Object,并接收IOCTL_KS_XXX请求。
对每一个独立的多媒体术领域,微软都定义了驱动所支持的标准的内核流定义。Audio, video capture and DVD devices 在如下文件中:
WDM Audio Driver Design Guide
Video Capture Minidriver Design Guide
DVD Driver Model Design Notes
1.2 KS Properties, Events, and Methods
每一个KS对象都支持内在的操作允许应用程序获得和设置对象状态,执行对象methods,和注册通告事件的回调线程。驱动支持每一种操作类——properties, methods, and events——以标准的方式。
• Set
功能相似的操作都一起封装在一个set中。每一个property, event,或method set都以一个GUID来标识。微软为标准的技术操作定义GUIDs,去冬可以定义自己特定操作的GUIDs。
• Identifier
每一个操作都用一个set里的ID号来描述。
• Operation-specific identification data
特定的操作需要额外的数据来详细描述。例如,音频设备上的pins支持KSPROPSETID_Audio property set。一个音频pin可能支持多个不同的音频通道。应用程序获得或设置特定的KSPROPSETID_Audio properties必须说明请求所申请的音频通道。当前,微软定义的需要额外数据的ks操作为property sets。
通用操作的标准GUIDs 和 identifiers在头文件ks.h中,多媒体技术的特殊class的标准GUIDs 和 identifiers在头文件ksmedia.h中。
应用程序传下I/O请求去获得和设置properties, 处理 methods, 和登记或不登记 event 通告。对每一个I/O请求,应用程序传下两个buffer:
• Instance Specification. 应用程序为I/O请求指定操作实例。每个操作实例以一个和ader开始,header描述operation set, operation ID, and operation flags,接着是操作特定的标识数据。下表说明了header的结构:
Operation type Instance specification header
Property KSPROPERTY
Event KSEVENT
Method KSMETHOD
处理操作需要扩展的数据结构,驱动使用以实例头为第一个成员的扩展数据结构。例如,KSPROPSETID_Pin property set里用KSP_PIN结构来指定Property实例。适当的扩展数据结构备份于每一个独自的property set。
• Operation data. 应用程序为操作指定一个数据buffer。Property请求用此buffer来获得或设置property。Method 请求的method input or output也用此buffer。 Event notification requests 用此 property 来确定所请求的事件通告的类型。.
1.2.1 KS Properties
应用程序用IOCTL_KS_PROPERTY请求来获得或设置property sets。KSPROPERTY里的Flags成员指定操作类型:KSPROPERTY_TYPE_GET为获取请求,KSPROPERTY_TYPE_SET为设置请求。
当应用程序发出一个获取property请求,驱动返回应用程序传下的数据buffer里的property。当应用程序发出一个设置property请求,驱动用buffer里的数据来指定新的property值。
Flags成员其余的值允许应用程序请求property的其它信息。例如:
KSPROPERTY_TYPE_SETSUPPORT
如果应用程序制定此flag,驱动不返回数据buffer里的数据。但如果他支持property设置它返回STATUS_SUCCESS,否则它返回错误码。
KSPROPERTY_TYPE_BASICSUPPORT
如果应用程序制定此flag,驱动返回STATUS_SUCCESS如果它支持property,否则它返回错误码。在数据buffer,驱动传下property的信息,例如property只读,只写或读写。
KSPROPERTY_TYPE_DEFAULTVALUES
如果应用程序制定此flag,驱动用数据buffer返回它的值的类型描述,包括它允许的范围和错误值。
typedef struct {
GUID Set;
ULONG Id;
ULONG Flags;
} KSIDENTIFIER;
typedef KSIDENTIFIER KSPROPERTY;
1.2.2 KS Events
驱动的应用程序可以要求当特定条件发生时通告。例如,应用程序可以确定当码流的时间戳在某特定时刻到达时要做的特定处理。
为请求时间通告,应用程序递交一个IOCTL_KS_ENABLE_EVENT请求,在请求的数据buffer中,,应用程序传下KSEVENTDATA结构来说明当事件发生时驱动如何通告。
应用程序可以通过IOCTL_KS_DISABLE_EVENT请求来取消一个事件,为识别事件,应用程序传下源数据buffer,此地址不需要指向源数据区,驱动仅用其来识别哪个事件通告无效。
一个事件类型可能需要额外的时间通告参数。例如,时钟的 事件是在某特定时间触发。注册说明此事件的应用程序需要说明初发此事件的时间戳。所有额外的数据参数都在数据buffer的KSEVENTDATA结构之后。支持此事件类型的驱动用一个数据扩展结构,第一个成员为KSEVENTDATA,用来保存通告数据。此数据类型分别与各自事件设置讨论。
应用程序可为事件通告中KSEVENT的成员Flags指定不同的选项。
1.KSEVENT_TYPE_ENABLE
事件每次发生时驱动通告应用程序,直到应用程序明确地指定取消此通告。2.KSEVENT_TYPE_ONESHOT
驱动在事件第一次发生时通告,应用程序无需取消此通告,再此后的事件中将不会得到通告。
3.KSEVENT_TYPE_ENABLEBUFFERED
驱动排队事件而不是通告应用程序。应用程序传下第二个请求IOCTL_KS_ENABLE_EVENT 来接收事件通告队列。
应用程序也可用KSEVENT_TYPE_SETSUPPORT和 KSEVENT_TYPE_BASICSUPPORT两个flags来查明一个KS对象支持的事件设置或是一个特殊的事件。
1.2.3 KS Methods
应用程序用IOCTL_KS_METHOD来请求执行一个KS对象中的method。KSMETHOD中的成员Flags指定一个操作中数据buffer的有效性。KS_METHOD_TYPE_NONE说明buffer不能读或写。KS_METHOD_TYPE_READ 和 KS_METHOD_TYPE_WRITE说明buffer只读或只写。KS_METHOD_TYPE_MODIFY说明其既能读又能写。
应用程序也可指定KS_METHOD_TYPE_SETSUPPORT用IOCTL_KS_METHOD来查询驱动是否支持method设置。或指定KS_METHOD_TYPE_BASICSUPPORT来查询一个特殊method的设置。
1.3 KS Filters, Pins and Node Topology
此节介绍pins的基本知识和交互。
1.3.1 Pin Connections
为与KS驱动交互,应用程序在驱动上示例一个KS Filter。应用程序一般通过微软的DirectShow来示例一个KS filter。一个驱动可以支持多种类型的filters,或同一种filter的多种实例。特别是驱动可以支持多种类型的filter如果他具有多媒体类型的功能。当一个应用程序示例一个KS filter时,驱动创建一个file object。应用程序所有后来发送的内核流I/O请求都给filter,或是它所创建的其他子file object。
每一个KS filter可以同时支持几个不同类型的数据流。为创建一个数据流,应用程序示例一个filter上的pin。Filter把它作为一个filter的file object的子file object一样描述每一个pin。应用程序通过发送一个IRP_MJ_CREATE请求给filter来示例一个pin。
Pin的不同类型决定其如何使用:
1.IRP source vs. IRP sink
IRP接收pin响应IOCTL_KS_READ_STREAM和IOCTL_KS_WRITE_STREAM请求,IRP源pin传出他们。应用程序可以直接给一个IRP接收pin发送I/O请求。当应用程序示例一个IRP源pin时,另一方面它指定与IRP源pin相连接的IRP接收pin。一旦连接建立,IRP源pin直接与IRP接收pin读或写数据。而不再被应用程序干涉。
2.Data source vs. data sink
数据源pin提供数据而数据接收pin吸收数据。数据源pin仅可与数据接收pin连接。必须注意数据source或sink是独立于IRP sink或IRP sink的。例如,应用程序可以连接一个数据source,IRP接收pin到一个数据sink,IRP源pin。IRP源pin发送IOCTL_KS_READ_STREAM请求来从IRP接收pin获取数据。
为在Ks filters之间建立连接,应用程序可动态的组合成一个数据可以流通的filter graph。例如,应用程序可以动态的在音频数据格式间加载一个filter来转换,将其配制成两个不同格式设备之间的桥接。
当应用程序处理I/O请求时,一般它对从设备要发送或接收的数据格式有特殊的要求。例如,应用程序可以选择是否接收DVD机的音频或视频数据。到此,KS filters提供几个不同的pin factories。在它的创建请求中,应用程序指定一个pin factory,且filter为连接创建一个类型的pin。Filter可以从一个相同的factory中创建一个或多个pins。
为提供执行时pin factories和其性能信息,KS filters支持KSPROPSETID_Pin性能设定。应用程序用KSPROPERTY_PIN_CTYPES性能设定来确定filter支持的pin factories的数目。
KSPROPSETID_Pin性能设定的其他成员允许应用程序查明每一个pin factory的个体properties。应用程序可以查询pin factory的如下properties:
1.Communication direction
(KSPROPERTY_PIN_COMMUNICATION) 此特性指明pin factory例示的pin上IRP的流向。Pins可以是IRP sources, IRP sinks, both, or neither。
2.Dataflow direction
(KSPROPERTY_PIN_DATAFLOW) 此特性指明pin factory例示的pin上数据的流向。Pins可以是IRP sources, IRP sinks, both, or neither。
3.Data formats
(KSPROPERTY_PIN_DATARANGES, KSPROPERTY_PIN_CONSTRAINEDDATARANGES, and KSPROPERTY_PIN_DATAINTERSECTION) pins支持特定的数据格式。这些properties指明pin factory例示的pin支持的数据格式。详情参考KS Data Formats and Data Ranges。
4.Medium
(KSPROPERTY_PIN_MEDIUMS) 设备可支持定制的旁路IRP处理多媒体信息。例如,一个DVD设备可直接写视频卡,而旁路CPU。KS filter用一个GUID来描述此媒体的媒体设置,识别媒体的ID 号。应用程序用此特性来请求pin factory例示pin支持的所有媒体。当连接到pin时应用程序指明实际所用的媒体。
5.Interface
(KSPROPERTY_PIN_INTERFACES). pin factory例示的pin可请求特定的properties, events, and methods设置。KS filter接口property来指明pin factory的要求。一个GUID指定的每一个接口描述接口设置,和接口设置里识别接口的ID号。。
6.Category
(KSPROPERTY_PIN_CATEGORY). KS filter 用此 property 来指明pin factory例示的pin的标准函数种类。
7.Name
(KSPROPERTY_PIN_NAME). KS filter可为它的每一个注册pin factories提供名字。
1.3.2 Pin Internal Topology
KS filter也支持内部连接。例如,考虑一个有一个数据接收pin和数据源pin的简单filter。它从数据接收pin上接收数据,在内部进行处理,然后写道数据源pin上。在下图中,pin用粗线表示,内部,filter将数据接收pin连接到内部处理单元,一个node,它最终会连接到一个数据源pin上。
Figure 1.1 Diagram of a Simple KS Filter.
一个复杂的设备可能组合或是分离pin之间的数据流。例如,考虑一个音频混频器它支持几个pin实例接收数据流。混频器将它们组合到一个流中并写到数据源pin上。如图所示:
Figure 1.2 Diagram of a Mixer.
每一个输入pin可以看为连接到中心混频器结点的输出pin上。而混频器接,也可看为KS filter上将一个输入pin连接到一个输出pin上结点。图示描述了filter上pins的内部关系。一个更为复杂的设备可以支持几个不同的节点,它们通过filter处理不同的数据流传输。
KS filter可以通过KSPROPSETID_Topology property set来报告pins之间的的内部连接,和内部节点。
1. The KSPROPERTY_TOPOLOGY_NODES property 提供一组GUIDs来描述节点的类型。微软在ksmedia.h头中定义了型如KSNODETYPE_XXX的标准接点设置。在其余的特性设置请求中,应用程序用此序列中的zero-based index来指向一个节点。
2.The KSPROPERTY_TOPOLOGY_CONNECTIONS property 提供一组KSTOPOLOGY_CONNECTION结构来描述pins和节点之间的连接。
3.在上面的混频器例子中,KSTOPOLOGY_CONNECTION 结构组可以如下描述:
// FromNode, FromNodePin, ToNode, ToNodePin,
{
{ KSFILTER_NODE, 0, 0, 0 },
{ 0, 1, KSFILTER_NODE, 1 }
}
4.KS filter将内部节点上的连接描述为pins。实际上pins表现为KSFILTER_NODE节点上的连接。
1.3.3 Reading and Writing on Pins
应用程序通过聚散来执行节点上的读写。当应用程序发送IOCTL_KS_READ_STREAM或 IOCTL_KS_WRITE_STREAM请求时,它传下一个KSSTREAM_HEADER结构序列为操作描述数据buffer。
KSSTREAM_HEADER结构序列中的每一个入口描述了聚散序列里的一个入口。成员 Data 保存了数据buffer的实际地址。而成员FrameExtent指明了大小。一般的,每一个入口指明基于时间的数据流中一个单独的帧。驱动可以在成员PresentationTime中包含一个现在的时间戳,在成员Duration中包含一个期限。
KS驱动和应用程序可以动态的协商数据格式。当流的数据格式改变的时,驱动在KSSTREAM_HEADER的成员OptionsFlag中指明KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY标志。在相应的数据buffer中,驱动自动传输在结构KSDATAFORMAT里描述的的新数据格式。更多的信息参阅KS Data Format Negotiation。
驱动和应用程序也可在KSSTREAM_HEADER中的成员OptionsFlag里说明流的状态信息。例如,KSSTREAM_HEADER_OPTIONS_ENDOFSTREAM指明当前帧尾最后一个。参考KSSTREAM_HEADER描述得更多可能的标志。
驱动可以请求扩展的流头结构来描述每一个帧。此结构的第一个成员必须是KSSTREAM_HEADER。例如,视频流请求KS_FRAME_INFO结构来描述视频流的每一个帧。
1.4 KS Data Formats and Data Ranges
下面节将介绍基本的数据格式和数据范围:指定数据格式和范围,和协商数据格式。
1.4.1 Specifying a KS Data Format or Data Range
为支持多种多媒体数据格式,每一个pin持有一个当前的数据格式。数据格式用一个,二个或是三个GUIDs来指定,加上每一种数据格式的一些额外的特殊参数。
每一个数据格式都有一个主要格式GUID。在主要数据格式中,数据格式可以请求一个从格式GUID和一个特殊的GUID。一个特殊的数据格式也可请求额外信息来完全确定一个数据格式。例如,主格式KSDATAFORMAT_TYPE_VIDEO需要请求源视频流的播放区长度和宽度来完全确定。
应用程序和驱动都用KSDATAFORMAT结构来描述数据格式。在内存的一个可变大小的格式制定数据block后面,此结构指定三个GUIDs来说明基本的格式类型。
一般的,Pins会支持数据格式的范围。例如,一个pin可支持主格式KSDATAFORMAT_TYPE_VIDEO,但对于源视频窗口会有一个长度和宽度的范围制的限制。驱动用KSDATARANGE结构来指明一个数据格式范围(驱动可以支持几个不同的范围)。KSDATARANGE的格式独立部分一个是KSDATAFORMAT的复制——驱动可以为主格式从格式或特别格式指定一个特殊的GUID,或是驱动指明一个wildcard(通配符)来匹配所有的格式,从格式或是所有的特殊格式。
KSDATARANGE的标准成员也在内存的一个可变大小的格式制定数据block后面。此block独立于用结构KSDATAFORMAT描述的数据格式设定block,即使同样的主格式,从格式和特殊格式。例如,指定一个视频窗口区长和宽值的范围比指定单一的长宽值需要更多的信息,所以对同一种数据格式类型,数据范围结构KSDATAFORMAT_TYPE_VIDEO的安排与数据格式结构不同。
因此,,每一种数据格式有两个与其关联的数据结构——一个指定数据格式,另一个指定数据格式的范围。每一个数据格式的文件需同时包括数据格式结构和数据格式范围结构。
注意,由于KSDATAFORMAT 和 KSDATARANGE有相同的标准头,所以跟随的可变大小数据block必须不同。例如,一个视频捕捉设备用结构KS_DATAFORMAT_VIDEOINFOHEADER来描述视频数据格式,而结构KS_DATARANGE_VIDEO描饰数据格式的范围。
1.4.2 KS Data Format Negotiation
应用程序和KS filter可协商数据流的数据格式。应用程序可以用四种不同的properties来请求filter上一个给定pin factory所例示的pins支持的数据格式。
1.KSPROPERTY_PIN_DATARANGES. KS filter报告pin factory所例示的pins所支持的所有数据范围。这包括pin曾经支持的所有数据格式。
2.KSPROPERTY_PIN_CONSTRAINEDDATARANGES. KS filter报告pin factory所例示的pins所支持的所有数据范围。给出当前内核驱动的状态。
3.KSPROPERTY_PIN_PROPOSEDATAFORMAT. 应用程序可用此property查询pin factory所例示的pins是否支持一个特殊的数据格式。如果pins支持此数据格式,KS filter将返回STATUS_SUCCESS,否则将返回错误代码。
4.KSPROPERTY_PIN_DATAINTERSECTION. 应用程序用此property提供一个数据格式范围。如果存在,KS filter将返回pin factory所例示的pins支持的数据范围中的一个单独的格式。
一旦一个pin被例示,应用程序可以去定一个当前的数据格式或是通过KSPROPSETID_Connection property请求改变数据格式。例如,应用程序可用请求KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT来确定一个pin是否支持一个给定的数据格式,这样应用程序可用请求KSPROPERTY_CONNECTION_DATAFORMAT来实际改变数据格式。
1.5 KS Clocks
KS驱动用时钟对象来描述时间计数。时钟对象可以描述板上硬件的实际时钟,或描述数据流的当前时间戳。
时钟支持KSPROPSETID_Clock参数设定。在一个给定的实例中,时钟提供两个有可能不同的时间戳。物理时钟的物理时间——或是系统时间或是在板上的硬件时钟。时钟的物理时间只能向前。时钟的描述时间表是数据流的时间戳。例如,一个时钟可以描述一个支持环绕的音频流的当前时间。描述时间可能是倒退的,可能是重制的任意值。
应用程序可用KSPROPERTY_CLOCK_PHYSICALTIMEproperty来确定当前时钟上的的物理时间,而用KSPROPERTY_CLOCK_TIME来确定当前的描述时间。对任意那个请求,驱动在其数据buffer的LONGLONG里以100ns为单位返回当前的时间。时钟不用请求支持100ns的分辨率。应用程序可以通过KSPROPERTY_CLOCK_RESOLUTION property来确定实际的时间分辨率。
应用程序可以请求当时钟到达特定的时间戳时进行通告,或接收时钟流逝一段固定时间的周期性通告。为此,应用程序注册KSEVENT_CLOCK_POSITION_MARK来请求达到一定时间戳时通告,而用KSEVENT_CLOCK_INTERVAL_MARK来请求周期通告。
数据流与时钟,即流的主时钟同步输入输出。驱动可以将它们的流与其它的驱动创建的时钟同步,多个不同的流可以与同一个时钟同步。应用程序可通过KSPROPERTY_STREAM_MASTERCLOCK property确定一个pin上的主时钟。应用程序也可用此property为pin设置主时钟。
1.6 KS Allocators
分配符是一个为I/O请求分配数据buffer的KS对象。KS驱动为pin提供一个分配符用来对I/O的输入输出最优化。
驱动原则上可谓外来的buffer类型提供分配符,如视频卡的板上RAM,但是很多驱动使用默认的分配符。默认的分配符分配系统内存。驱动可以指明帧大小,帧的最大数目和队列要求。默认分配符尽量满足要求,并可以重用丢弃帧来优化。
支持分配符的驱动响应KSPROPERTY_CONNECTION_ALLOCATORFRAMING property。此property的数据buffer为一个KSALLOCATOR_FRAMING结构。驱动利用此结构的数据buffer来指明要求。这些限制包括:固定的帧大小,精确的正常帧上限范围,队列,或是类型池。支持默认分配符的驱动将成员RequirementsFlag为设置为KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY标志。