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)之间的无限循环
AVStream ddk 翻译的更多相关文章
- HarmonyOS USB DDK助你轻松实现USB驱动开发
HDF(Hardware Driver Foundation)驱动框架是HarmonyOS硬件生态开放的基础,为开发者提供了驱动加载.驱动服务管理和驱动消息机制等驱动能力,让开发者能精准且高效地开发驱 ...
- 《Django By Example》第五章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者@ucag注:大家好,我是新来的翻译, ...
- 《Django By Example》第四章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:祝大家新年快乐,这次带来<D ...
- [翻译]开发文档:android Bitmap的高效使用
内容概述 本文内容来自开发文档"Traning > Displaying Bitmaps Efficiently",包括大尺寸Bitmap的高效加载,图片的异步加载和数据缓存 ...
- 【探索】机器指令翻译成 JavaScript
前言 前些时候研究脚本混淆时,打算先学一些「程序流程」相关的概念.为了不因太枯燥而放弃,决定想一个有趣的案例,可以边探索边学. 于是想了一个话题:尝试将机器指令 1:1 翻译 成 JavaScript ...
- 《Django By Example》第三章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:第三章滚烫出炉,大家请不要吐槽文中 ...
- 《Django By Example》第二章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:翻译完第一章后,发现翻译第二章的速 ...
- 《Django By Example》第一章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:本人目前在杭州某家互联网公司工作, ...
- 【翻译】Awesome R资源大全中文版来了,全球最火的R工具包一网打尽,超过300+工具,还在等什么?
0.前言 虽然很早就知道R被微软收购,也很早知道R在统计分析处理方面很强大,开始一直没有行动过...直到 直到12月初在微软技术大会,看到我软的工程师演示R的使用,我就震惊了,然后最近在网上到处了解和 ...
随机推荐
- 洛谷 [P1403] 约数研究
本题的思想很好,正难则反 首先如果暴力枚举每个数的约数个数,一定会超时,那么我们就从约数的角度考虑,题目中问的是1~n的约数个数和,那么我们就枚举约数,看每个约数在1~n中出现过几次. #includ ...
- bzoj 4871: [Shoi2017]摧毁“树状图” [树形DP]
4871: [Shoi2017]摧毁"树状图" 题意:一颗无向树,选两条边不重复的路径,删去选择的点和路径剩下一些cc,求最多cc数. update 5.1 : 刚刚发现bzoj上 ...
- CF 208E. Blood Cousins [dsu on tree 倍增]
题意:给出一个森林,求和一个点有相同k级祖先的点有多少 倍增求父亲然后和上题一样还不用哈希了... #include <iostream> #include <cstdio> ...
- BZOJ 1845: [Cqoi2005] 三角形面积并 [计算几何 扫描线]
1845: [Cqoi2005] 三角形面积并 Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 1151 Solved: 313[Submit][Stat ...
- R语言-广义线性模型
使用场景:结果变量是类别型,二值变量和多分类变量,不满足正态分布 结果变量是计数型,并且他们的均值和方差都是相关的 解决方法:使用广义线性模型,它包含费正太因变量的分析 1.Logistics回归( ...
- tcp 网络编程
网络编程同时也是进程间的一种通信:服务器进程和应用进程间的通信. OSI:开放式系统互联 OSI 7层模型: ...
- mac攻略(4) -- 使用brew配置php7开发环境(mac+php+apache+mysql+redis)
[http://www.cnblogs.com/redirect/p/6131751.html] 网上有很多文章都是错误的,因为是copy别人的,作者没有自己亲测,不仅不能给新手提供帮助,还会产生严重 ...
- 获取登陆用户的ip
function getip(){ static $ip = null; if($ip !=null) return $ip; if(getenv('REMOTE_ADDR') ...
- asp.net core 一 Centos 环境部署
.netcore的运行环境,创建asp.net core 项目 CentOS 7 ,dotnet-sdk-2.0.0-2.0.0-1.x86_64 直接在liunx创建项目并运 ...
- sqlite不存在记录则插入数据
问题:如下图在Sqlite数据库中存在一张Student表,现需要向表中插入数据,如果不存在同名记录则插入,否则不进行插入操作. 解答:利用not exists语句,如下: insert into [ ...