AVStream ddk 翻译

1.       AVStream概览

AVStream是一款微软提供的多媒体类驱动程序,它既支持单独的视频流媒体,也支持音频视频集成的流媒体。微软把AVStream作为操作系统的一部分,在驱动程序ks.sys中导出。硬件供应商只需要编写运行在Ks.sys下层的小驱动程序(minidriver)。

以前的音频类驱动程序是微软提供的音频端口驱动程序(audio port class driver)。音频供应商应该编写运行在portcls.sys下层的小驱动程序(minidriver)。

微软仅为已经存在的小驱动程序(minidrivers)提供流媒体类驱动(stream class driver)支持。

AVStream通过以下几点向供应商提供意义重大的优点:

l          小驱动(minidriver)程序员可以编写更少的代码。

l          为音频和视频小驱动程序(minidrivers)提供统一的内核流媒体类模型。

l          供应商可以使用COM对象加入新的接口,而不需要对已存在的小驱动程序(minidriver)的二进制文件做任何修改。

在AVStream驱动模型中,供应商提供小驱动程序(minidriver)与微软提供的类驱动程序交互,如下图所示:

2.       AVStream小驱动程序(minidriver)示例

DDK包含两个AVStream小驱动程序(minidriver)示例:Avshws和Avssamp。Avshws是一个为仿真硬件如何通过AVStream实现DMA而编写的pin-centric捕获驱动程序。Avssamp是一个filter-centric捕获驱动程序,没有实现DMA。

这些例子演示了本文档中描述的许多概念,而且可以被驱动开发者修改成自己需要的类型。这些例子相关的说明文件(Readme file)可以在DDK中找到,位于这些示例相同的路径中。DDK中未包含这些说明文件。

3.       AVStream头文件

所有内核流媒体和AVStream需要引用的材料,包括结构体,函数都在头文件Ks.h中生命。为了访问微软提供的KS和AVStream类驱动程序支持,小驱动程序必需包含这个头文件。

4.       AVStream对象层次图

AVStream小驱动程序(minidriver)可以通过对象层次图导出许多不同类型的filter,比如,下图就是一个。

5.       AVStream描述符

AVStream 小驱动程序(minidriver)在调用KsInitializeDriver例程时,通过提供一个嵌套的描述符结构来描述自己和自己支持的filter类型。每个关键组件-设备,filter类厂和pin类厂都有一个相关的描述符。

在设备描述符中,FilterDescriptors成员指向KSFILTER_DESCRIPTOR结构体数组,这个数组描述了这个设备可以创建的filter类型。AVStream的客户可以调用KsCreateFilterFactory例程来动态添加filter类厂。

KSFILTER_DESCRIPTOR表明该filter支持多少类型的pin, filter注册在哪个分类下面,以及filter的拓扑结构。在每个filter描述符中,小驱动程序(minidriver)提供了一个指向KSPIN_DESCRIPTOR_EX结构体数组的指针。每个这样的pin描述符描述一类这个filter可以实例化的pin。你可以调用KsFilterCreatePinFactory例程创建另外的pin类厂。

典型的AVStream小驱动程序(minidriver)把描述符作为静态变量布置在源文件中,然后调用KsInitializeDriver例程完成创建任务。

也存在其他类型的描述符,比如,节点描述符KSNODE_DESCRIPTOR,它描述一个给定节点的拓扑结构。

6.       AVStream派遣表

AVStream派遣表,KSDEVICE_DISPATCH, 是一套函数指针,指向派遣例程。小驱动程序(minidriver)可以通过提供回调例程完成驱动指定任务的方式,扩展AVStream提供的功能。

这些小驱动程序(minidriver)提供的例程接收事件的通知消息,并可以扩展或者修改AVStream提供的默认事件处理。

KSFILTER_DISPATCH和KSPIN_DISPATCH结构体都提供一个叫做Process的派遣例程。使用这个派遣例程区分filter-centric filter和pin-centric filter。要指定一个filter-centric filter,在filtre派遣表中指定一个指向process派遣回调例程的指针。pin-centric filter在每个pin描述符表中,提供一个process派遣例程。

你可以注册filter,向它发送创建,删除,数据处理和重启等通知。你可以注册pin,向它发送诸如创建,关闭,数据处理,重启,设置数据格式,以及状态改变等事件的通知。要注册通知对象,在相关的派遣结构中指定一个指向供应商提供的派遣例程的指针。

7.       初始化AVStream小驱动程序(minidriver)

AVStream小驱动程序(minidriver)自己不处理设备的初始化,而是在DriverEntry例程中调用KsInitializeDriver例程完成初始化。KsInitializeDriver例程初始化驱动程序对象,除此以外还负责初始化IRP派遣例程,PnP 添加设备和卸载设备事件派遣例程。

在调用KsInitializeDriver时,小驱动程序(minidriver)传递一个需要初始化的指向驱动程序对象的指针,一个指向注册表路径的指针和一个可选的设备描述符对象。如果小驱动程序(minidriver)不传递设备描述符对象,AVStream在调用AddDevice例程时创建具有指定特征的设备对象。

设备描述符对象包含一个指向KSDEVICE_DISPATCH结构的指针和一个filter描述符数组。为小驱动程序(minidriver)支持的每一类filter提供一个KSFILTER_DESCRIPTOR。当小驱动程序(minidriver)调用KsInitializeDriver时,AVStream为每一类小驱动程序(minidriver)导出的filter创建一个filter类厂对象。当接收到相应filter创建的IRP后,由该类filter类厂分别实例化该filter。每个filter描述符包含一个指向KSPIN_DECRIPTION_EX对象数组的指针。

当某个filter的给定pin上建立连接时,AVStream pin类厂创建一个pin对象。注意每个filter必需至少导出一个pin。小驱动程序(minidriver)使用KSPIN_DESCRIPTOR_EX的成员InstanceNecessary来确定创建这种类型pin的数目对于filter的正常运行是否必要。同样的,小驱动程序(minidriver)也可以使用KSPIN_DESCRIPTOR_EX结构体的成员InstancePossible来确定创建这种类型pin的数目是否超过最大数目。

AVStream支持两种处理类型:filter-centric processing 和 pin-centric processing. 当布置好描述符后,就要决定使用哪种处理类型了。

安装AVStream小驱动程序(minidriver)

AVStream小驱动程序(minidriver)必须存在一个inf文件(系统使用该文件来安装驱动程序)。AVStream的inf文件基于普通inf文件的格式。牢记以下AVStream驱动程序指南。

如果你为父设备编写小驱动程序(minidriver),inf文件的AddReg一节应该包含:

[ParentName.AddReg]
HKR,"ENUM\[DeviceName]",pnpid,,"[string]"

如果你为子设备编写minidriver,inf文件的AddReg一节应该包含:

[Manufacturer]
...=ChildName
[ChildName]
...=ChildName.Device,AVStream\[string]
注意在流媒体类驱动中,上面的"AVStream"应该替换成"Stream"。

对于所有的AVStream小驱动程序(minidriver), 指定filter应用串必须和KSFILTER_DESCRIPTOR结构中ReferenceGuid成员匹配。

8.       Pin-Centric Processing

当编写AVStream小驱动程序(minidriver)时,你的filter可以使用两种处理范例的一种:pin-centric processing or filter-centric processing。

pin-centric processing指当新的数据帧到达pin队列时,AVStream调用小驱动程序(minidriver)的pin process派遣例程。

filter-centric processing指当每个实例化的pin上存在有效的数据帧时,AVStream调用小驱动程序(minidriver)的filter process派遣例程。注意这种定义指定了默认的行为;小驱动程序(minidriver)可以通过设置KSPIN_DESCRIPTOR_EX结构体中的flags成员来修改这种默认行为。

一般来讲,软件filter使用filter-centric processing,硬件filter使用pin-centric processing。比如,支持变换和呈现数据的硬件可以把数据路由到pin-centric filter。相反的情况很少。

想要得到pin-centric filter,小驱动程序(minidriver)就要在每个KSPIN_DISPATCH结构中提供一个指向AVStrMiniPinProcess回调例程的指针。不要在KSFILTER_DISPATCH结构中指定AVStrMiniPinProcess回调例程的指针。

如果小驱动程序(minidriver)不修改KSPIN_DESCRIPTOR_EX中的flags设置,AVStream将在以下三种情况下调用供应商提供的AVStrMiniPinProcess回调例程:

l          该pin进入最小处理状态,队列中必需已经存在数据帧,而且pin必需从欠最小处理状态至少转化成最小处理状态。

l          新数据帧到达。Pin至少处于最小处理状态,而且在leading edge和之前没有数据帧。

l          小驱动程序(minidriver)明确调用KsPinAttemptProcessing例程。

默认情况下,暂停就时最小处理状态。

另外,如果pin的与门是关闭的,AVStream不调用pin的处理派遣例程。例如,如果你使用KsGateXxx例程添加另外的off输入到该pin的与门,你的处理派遣例程将不被调用。

当AVStream调用AVStrMiniPinProcess例程时,它提供一个指向存在有效数据pin的指针。随后小驱动程序(minidriver)通过调用KsPinGetLeadingEdgeStreamPointer例程请求leading edge指针。小驱动程序(minidriver)将使用流媒体指针(stream pointer)API管理流媒体数据。

当AVStream调用AVStrMiniPinProcess例程时,通过设置KSPIN_DESCRIPTOR_EX结构中的相关标记(flags),使用pin-centric processing的小驱动程序(minidriver)可以备修改。

如果小驱动程序(minidriver)通过调用KsPinAcquireProcessingMutex例程持有处理互斥量(processing mutex),处理尝试可能会失败。如果小驱动程序(minidriver)使用KsGate*调用直接管理门,问题可能同样会出现。

9.       Filter-Centric Processing

10.  AVStream中的事件处理

AVStream filter和pin通过在结构体KSFILTER_DESCRIPTOR或者KSPIN_DESCRIPTOR_EX的AutomationTable成员中提供一个KSAUTOMATION_TABLE类型的结构体,描述它们支持的属性,事件和方法。

要支持事件,AVStream小驱动程序(minidriver)就要在自动操作表中提供一个KSEVENT_SET类型的数组。每个KSEVENT_SET结构包含一个KSEVENT_ITEM数组。每个KSEVENT_ITEM结构描述了小驱动程序(minidriver)如何支持指定的事件。

通过在KSEVENT_ITEM结构中提供AVStrMiniAddEvent和AVStrMiniRemoveEvent处理函数,Minidriver可以自定义事件的行为。

当AVStream接收到一个事件使能请求后,它便产生一个KSEVENT_ENTRY结构。如果小驱动程序(minidriver)已经提供了一个AVStrAddEvent处理函数,AVStream会在调用AVStrAddEvent的时传递一个指向KSEVENT_ENTRY结构的指针。

如果没有提供AVStrAddEvent处理函数,AVStream默认情况下会添加一个事件到对象列表。小驱动程序(minidriver)不会接收到KSEVENT_ENTRY的指针。Minidriver可以调用KsFilterGenerateEvent或者KsPinGenerateEvents触发一个事件。

11.  用户模式中方法和事件代码实例

这部分代码展示了如何在用户模式的KsProxy插件程序中使用方法和事件。

在你的minidriver中提供了对给定方法支持后,你可以通过调用IksControl::KsMethod方法达到调用底层方法的目的,下面是例子代码:

PVOID MethodBuffer; // Your method arguments buffer
ULONG MethodBufferSize; // Your method buffer size

KSMETHOD Method;
ULONG BytesReturned;

Method.Set = KSMETHODSETID_MyMethodSet;
Method.Id = KSMETHOD_MyMethodId;
Method.Flags = KSMETHOD_TYPE_SEND;

HRESULT hr = 
pIKsControl -> KsMethod (
    &Method,
        sizeof (Method),
    MethodBuffer,
    &MethodBufferSize,
    &BytesReturned);

在内核模式自动操作表中,你可以是用KSMETHOD_ITEM的Flags成员指定该缓冲区是否是可读写的,是否是可映射或者可拷贝的。

要注册一个minidriver支持的事件,使用一下示例代码:

HANDLE EventHandle; // Your event handle.

KSEVENT Event;
KSEVENTDATA EventData;

Event.Set = KSEVENTSETID_MyEventSet;
Event.Id = KSEVENT_MyEventId;
Event.Flags = KSEVENT_TYPE_ENABLE;

EventData.NotificationType = KSEVENTF_EVENT_HANDLE;
EventData.EventHandle.Event = EventHandle;
EventData.EventHandle.Reserved [0] = 0;
EventData.EventHandle.Reserved [1] = 0;

ULONG BytesReturned;

HRESULT hr =
pIKsControl -> KsEvent (
    &Event,
        sizeof (Event),
    &EventData,
        sizeof (EventData),
    &BytesReturned);

在上面的示例中,通知将持续除非minidriver让该事件失效。要让你的事件失效。调用KsControl::KsEvent。如果你只想在事件第一次发生时被通知,设置Event.Flags为KSEVENT_TYPE_ONESHOT。

12.  AVStream子设备

这部分适用于Microsoft Windows Server 2003和安装了DirectX 9.0及以后版本的早期操作系统。对于你的设备,AVStream可以作为一个总线枚举器运行,Enum分支下的键,AVStream都为你创建一个子设备。要这样做,在注册表中设备键下放置一个Enum子键。

特别是在驱动程序的inf文件的AddReg部分,供应商为每个Enum下的子项REG_SZ类型的pnpid值。AVStream使用这个串值为每个单独的设备构造一个PnP硬件ID。

在DirectX 9.0以前的发行版本中,AVStream创建一个形如"AVStream\<pnpid>"子设备硬件ID。

例如,供应商在inf文件的AddReg部分指定一下设置:

[MyTVDevice.AddReg]
HKR,"ENUM\CrossbarDevice",pnpid,,"MyCrossbar"
HKR,"ENUM\TunerDevice",pnpid,,"MyTuner"

因此,AVStream使用下面的设备ID创建两个子设备。

AVStream\MyCrossbar,AVStream\MyTuner

为了解决两个子设备指定相同的pnpid这种可能的冲突。DirectX 9.0及以后的版本改变了每个子设备的ID报告机制。对于每个通过父设备报告的硬件ID,AVStream为每个子设备创建一个形如下面的ID:

AVStream\<pnpid>#<modified parent hardware ID>

修改过的父硬件ID为父硬件ID中使用 “#”代替所有的反斜线”\”。

如果最终的串太长,AVStream以MAX_DEVICE_ID_LEN终止ID串,包含一个NULL。在Windows Server 2003,这个限制在头文件cfgmgr32.h中被设置为200个字符。

例如父设备报告一下的设备ID:

PCI\VEN_XXXX&DEV_YYYY&SUBSYS_ZZZZZZZZ&REV_VV
PCI\VEN_XXXX&DEV_YYYY&SUBSYS_ZZZZZZZZ

对于pnpid键值为MyCrossbar的设备,AVStream创建一下的子设备硬件ID:

AVStream\MyCrossbar#PCI#VEN_XXXX&DEV_YYYY&SUBSYS_ZZZZZZZZ&REV_VV
AVStream\MyCrossbar#PCI#VEN_XXXX&DEV_YYYY&SUBSYS_ZZZZZZZZ

对于父设备报告的兼容ID,AVStream使用相同的处理方法。AVStream为子设备创建兼容ID形如下面ID:

AVStream\<pnpid>#<modified parent compatible ID>

兼容ID名称修改机制个长度限制法则与硬件ID是一样的。

例如,父设备报告了一下兼容ID:

PCI\VEN_XXXX&DEV_YYYY&REV_VV
PCI\VEN_XXXX&DEV_YYYY
PCI\VEN_XXXX&CC_ZZZZZZ
PCI\VEN_XXXX&CC_ZZZZ
PCI\VEN_XXXX
PCI\CC_ZZZZZZ
PCI\CC_ZZZZ

MyCrossbar子设备将通过AVStream报告如下的兼容ID:

AVStream\MyCrossbar#PCI#VEN_XXXX&DEV_YYYY&REV_VV
AVStream\MyCrossbar#PCI#VEN_XXXX&DEV_YYYY
AVStream\MyCrossbar#PCI#VEN_XXXX&CC_ZZZZZZ
AVStream\MyCrossbar#PCI#VEN_XXXX&CC_ZZZZ
AVStream\MyCrossbar#PCI#VEN_XXXX
AVStream\MyCrossbar#PCI#CC_ZZZZZZ
AVStream\MyCrossbar#PCI#CC_ZZZZ
AVStream\MyCrossbar

13.   在AVStream中重启处理

如果下列任何一种情况为真,AVStream将停止处理。

l          在pin-centric环境中,当前该pin上没有有效的数据。

l          在filter-centric环境中,至少存在一个pin,该pin的KSPIN_DECRIPTOR_EX的flags没有设置KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING标记,没有数据等待处理。默认情况下,没有设置这个标记。

l          不管数据真是否有效,小驱动程序(minidriver)的处理派遣回调例程返回STATUS_PENDING。注意处理派遣例程可以是AVStrMiniFilterProcess也可以是AVStrMiniPinProcess,依赖于小驱动程序(minidriver)实现的pin-centric processing或者filter-centric processing。

当新数据到达空队列时,AVStream开始处理。因此,如果当相关的队列装满,小驱动程序(minidriver)的处理派遣例程返回为STATUS_PENDING时,小驱动程序(minidriver)将不会被调用重新处理。如果小驱动程序(minidriver)设置STATUS_PENDING,minidriver必需调用KsPinAttemptProcessing或者KsFilterAttemptProcessing重新开始处理。

如果小驱动程序(minidriver)没有真正的处理数据,不要在处理派遣例程中返回STATUS_PENDING。这会引起AVStream马上再次调用小驱动程序(minidriver),导致在AVStream和小驱动程序(minidriver)之间的无限循环

时间: 2024-10-21 01:27:49

AVStream ddk 翻译的相关文章

在GlassFish应用服务器上创建并运行你的第一个Restful Web Service【翻译】

前言 本人一直开发Android应用,目前Android就业形势恶劣,甚至会一路下滑,因此决定学习服务器开发.采用的语言是java,IDE是Intellij,在下载Intellij的同时看到官网很多优秀的guide文章,于是按照guide成功完成了一个RESTful的demo.官方文档非常简洁,给我带来了很大的帮助,于是翻译之,希望对其他不愿意看原文的人有所帮助.由于水平有限,读者发现错误请指正,谢谢. 原文地址: https://www.jetbrains.com/help/idea/2016

Java 7 Concurrency Cookbook 翻译 序言

在日常的Java代码开发过程中,很难免地有对多线程的需求,掌握java多线程和并发的机制也是Java程序员写出更健壮和高效代码的基础.笔者找寻国内已出版的关于Java多线程和并发的的中文书籍和翻译书籍,大家一致推荐的是<Java Concurrency in Practice>,笔者暂时还没有看英文原版,笔者看的是它的翻译版<Java并发编程实战>,笔者读起来感觉并不通畅,不知道是翻译的问题还是原版本来就写得不够流畅,同时感觉知识的深度也超过了入门的需求. 笔者在机缘巧合之下,发现

[翻译] ORMLite document -- How to Use Part (二)

前言 此文档翻译于第一次学习 ORMLite 框架,如果发现当中有什么不对的地方,请指正.若翻译与原文档出现任何的不相符,请以原文档为准.原则上建议学习原英文文档. ---------------------------------------------------------------------------------------------- 二.如何使用 2.7 表的创建 ORMLite 提供了一些工具类为您存储在数据库中的类创建 table 和 schema. 2.7.1 Tabl

Reveal常用技巧(翻译来自Reveal官网blog)

翻译来自官网:http://revealapp.com/blog/reveal-common-tips-cn.html 以下基于Reveal 1.6. 用于快速上手的内置应用 刚刚下载Reveal,啥都还没配置呢,想先随便玩玩看,怎么办? 我们花了不少时间开发这个复杂程度类似与实际场景的Sample应用──Soundstagram(音频分享版的Instagram, ¯\_(ツ)_/¯),就是为了让大家能最快速地上手Reveal,尝试它的各种强大功能. 在 Help 菜单项中,点击 Inspect

qt 国际化(翻译时会触发changeEvent)

1. 修改工程文件 .pro ,加入翻译源文件 hello_world.ts: TRANSLATIONS += \        Resource/translations/hello_world.ts 写代码时需要注意下面两点:  2. 源码用 utf-8 字符集3. 源码中需要翻译的字符串必须用英文(不能有中文或其它语言),则需要用 tr()  函数.  例如: QMessageBox::information(this,tr("Information"),tr("Hel

还在吐槽翻译的外版书质量差吗?谈谈我个人的理解

很难想象哪个学习计算机技术的人是没看过这方面书籍的,如果只是在网上看看技术贴,那样得来的知识绝对是离散的,不系统的.而要真正学好一门学问(比如一门计算机语言或者一门技术),一本好书的作用是不言而喻的.很多人抱怨国人在技术图书方面抄来抄去,不求甚解,虽然出版图书者甚众,但最终成为精品者却凤毛麟角.于是,更多读者热衷于外版书.但显然,并非所有国人的外语水平都足以在阅读原版书籍时毫无障碍.那么退而求其次,寻求翻译版就成为一种看似不得已的选择. 不幸的是,网上对于翻译版书籍的吐槽可以说从未消停.我也看过

VLD 1.0 ReadMe翻译尝试

近期想学习下VLD的实现,打算从最简单的V1.0版本看起.以下是V1.0版本自己尝试翻译下,最新的2.x版本似乎强大了很多. 简介 Visual C++提供了内置的内存检测机制,但其充其量只满足了最小定位需求.VLD工具定位为内置内存泄漏的替代,提供了如下特性: 泄漏内存块的全调用栈回溯,包括文件及其行号: 泄漏内存完整转储(hex和ascii格式): 可定制的泄漏报告等级(报告的详细程度可配置) 相对于Purify和BoundsChecher工具其是免费的,而其他免费工具,往往需要入侵式代码.

如何调用有道翻译API(Java,HTTP)

申请Key 首先如图进入有道翻译,在下方点击"有道翻译API". 紧接着来调用数据接口,按提示完成下列输入框. 如下图所示,已经申请成功了. 下图是官方给的示例,可以有xml和json.jsonp等三种数据格式. 代码(Java) public class TestPost { public static void main(String[] args) { new ReadByPost().start(); } } class ReadByPost extends Thread{ @

Android studio project文件结构翻译

Android studio project文件结构翻译 个人翻译,用作备忘. 链接地址:https://developer.android.com/tools/projects/index.html#ApplicationModules Android Project Files Studio的项目文件和设置,设置的作用范围包含所有的module. 以以下的demo为例. .git:git版本控制的文件存放目录. .gradle:gradle执行一些编译所生成的目录 Idea: 由Intell