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)之间的无限循环

AVStream ddk 翻译的更多相关文章

  1. HarmonyOS USB DDK助你轻松实现USB驱动开发

    HDF(Hardware Driver Foundation)驱动框架是HarmonyOS硬件生态开放的基础,为开发者提供了驱动加载.驱动服务管理和驱动消息机制等驱动能力,让开发者能精准且高效地开发驱 ...

  2. 《Django By Example》第五章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者@ucag注:大家好,我是新来的翻译, ...

  3. 《Django By Example》第四章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:祝大家新年快乐,这次带来<D ...

  4. [翻译]开发文档:android Bitmap的高效使用

    内容概述 本文内容来自开发文档"Traning > Displaying Bitmaps Efficiently",包括大尺寸Bitmap的高效加载,图片的异步加载和数据缓存 ...

  5. 【探索】机器指令翻译成 JavaScript

    前言 前些时候研究脚本混淆时,打算先学一些「程序流程」相关的概念.为了不因太枯燥而放弃,决定想一个有趣的案例,可以边探索边学. 于是想了一个话题:尝试将机器指令 1:1 翻译 成 JavaScript ...

  6. 《Django By Example》第三章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:第三章滚烫出炉,大家请不要吐槽文中 ...

  7. 《Django By Example》第二章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:翻译完第一章后,发现翻译第二章的速 ...

  8. 《Django By Example》第一章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:本人目前在杭州某家互联网公司工作, ...

  9. 【翻译】Awesome R资源大全中文版来了,全球最火的R工具包一网打尽,超过300+工具,还在等什么?

    0.前言 虽然很早就知道R被微软收购,也很早知道R在统计分析处理方面很强大,开始一直没有行动过...直到 直到12月初在微软技术大会,看到我软的工程师演示R的使用,我就震惊了,然后最近在网上到处了解和 ...

随机推荐

  1. OS模块的常用内置方法

    chdir 修改当前工作目录到指定目录 Change the current working directory to the specified path. chmod 修改一个文件的访问权限 Ch ...

  2. 安装与配置cacti 0.8.8b

    cacti安装与配置 一.安装所需要的软件 Apache    安装Apache文档 Mysql      安装Mysql文档 Php       安装PHP文档 Rrdtool    安装rrdto ...

  3. .net中关于Windows窗体程序和Web网站程序调用自己的服务

    在.NET Framework 4.0创建服务是中没有像3.5那样的选择新建-网站-ASP.NET Web服务模块,但在4.0中可以选择 新建-网站-ASP.NET空网站-选中项目右键添加新项- 选择 ...

  4. Python之Suds库调用WCF时复杂参数序列化

    今天主要做自动化测技术支持工作,最近一直在做接口自动化这块,前些天在研究将web页面模拟http进行接口自动化,这周杭州那边想测试WCF服务,所以这两天一直在探索.遇到的第一个问题就是服务参数传参序列 ...

  5. 使用.bat来执行Java程序基础

    将java程序做成可运行的jar后,又希望使用.bat文件来调用jar时,有几点需要注意的. 1.设置path和classpath .bat文件中扥的内容如下: @echo off set MY_HO ...

  6. DNA序列局部比对(Smith–Waterman algorithm)

    生物信息原理作业第三弹:DNA序列局部比对,利用Smith–Waterman算法,python3.6代码实现. 实例以及原理均来自https://en.wikipedia.org/wiki/Smith ...

  7. WPF中的Command事件绑定

    在项目中使用Command绑定能够使我们的代码更加的符合MVVM模式.不了解的同学可能不清楚,只有继承自ButtonBase类的元素才可以直接绑定Command(Button.CheckBox.Rad ...

  8. win7本地连接消失

    可能原因一 驱动程序错误: 右键"计算机"图标 - "属性" - 设备管理器现在在设备管理器下面找到"网络适配器",在下面的网卡驱动中发现有 ...

  9. 描述进程的PCB

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  10. Windows 桌面和文件夹的右键->打开命令行窗口

    Windows 桌面和文件夹的右键->打开命令行窗口 1.先按下shift,再点鼠标右键运行CMD,(不是管理员权限) 上图是我已经加了右键的,并且 系统设置了  ps代替cmd,所以是“在此处 ...