文章目录
基于AVStream框架的虚拟摄像头开发实现
在前面文章中,我们分析过虚拟摄像头有两种实现方式:
- 基于DirectShow框架的虚拟摄像头实现。
- 基于驱动的虚拟摄像头实现。
并且在前面文章中分析了基于DirectShow框架的方案(可以参见基于DirectShow框架的虚拟摄像头开发实现),在这里我们分析基于AVStream驱动框架的摄像头方案,该方案可以做到稳定性好,兼容几乎所有的应用软件。
1. AVStream技术概览
AVStream是用来取代Kernel Stream的音视频开发的一种新框架,其大致架构如下:
如上图我们可以发现其都是基于KS框架来扩展的,扩展基于Port Class的驱动框架(用来开发音频驱动),基于AVStream的驱动框架(用来开发视频驱动)。这个框架有两个比较明显的优势:
- 开发更加便捷和简单。
- 为音视频的处理提供了统一的内核流处理模型。
在AVStream框架中,都是基于对象来进行抽象和管理,整个对象形成一个类似树状的结构,框架如下:
如上图中所示:
- 对于一个AVStream驱动的设备,使用AVStream Device对象作为整个结构的树根。
- AVStream Device对象可以设置多个AVStream Filter Factory对象,用来创建过滤器。
- 对于一个过滤器可以可以包含多个AVStream Pin Factory。
- AVStream Pin Factory可以用来创建引脚实例。
AVStream的主要工作就是组织这些对象,让其协同工作。
2. 描述符
通过上面我们可以看到整个AVStream的核心工作原理是各自的对象来实现的,AVStream框架已经为我们做好了所有的处理流程(例如IRP数据的处理),我们只需要定义这些对象即可。在AVStream框架中,使用描述符来定义各自的对象,可以分为三种描述符:
- 设备描述符。
- 过滤器描述符。
- 引脚描述符。
设备描述符包括设备的信息,例如设备的PNP回调函数,以及设备中默认的过滤器描述符,其定义如下:
typedef struct _KSDEVICE_DESCRIPTOR {
const KSDEVICE_DISPATCH *Dispatch;
ULONG FilterDescriptorsCount;
const KSFILTER_DESCRIPTOR const * * FilterDescriptors;
ULONG Version;
ULONG Flags;
PVOID Alignment;
} KSDEVICE_DESCRIPTOR, *PKSDEVICE_DESCRIPTOR;
KSFILTER_DESCRIPTOR
表示过滤器描述符,描述了过滤器工厂的特性,框架使用该特性创建过滤器,该结构定义如下:
typedef struct _KSFILTER_DESCRIPTOR {
const KSFILTER_DISPATCH *Dispatch;
const KSAUTOMATION_TABLE *AutomationTable;
ULONG Version;
ULONG Flags;
const GUID *ReferenceGuid;
ULONG PinDescriptorsCount;
ULONG PinDescriptorSize;
const KSPIN_DESCRIPTOR_EX *PinDescriptors;
ULONG CategoriesCount;
const GUID *Categories;
ULONG NodeDescriptorsCount;
ULONG NodeDescriptorSize;
const KSNODE_DESCRIPTOR *NodeDescriptors;
ULONG ConnectionsCount;
const KSTOPOLOGY_CONNECTION *Connections;
const KSCOMPONENTID *ComponentId;
} KSFILTER_DESCRIPTOR, *PKSFILTER_DESCRIPTOR;
KSPIN_DESCRIPTOR_EX
表示引脚的描述符,引脚描述符定义了引脚工厂的特性,框架使用这些特性来创建引脚实例,该结构定义如下:
typedef struct _KSPIN_DESCRIPTOR_EX {
const KSPIN_DISPATCH *Dispatch;
const KSAUTOMATION_TABLE *AutomationTable;
KSPIN_DESCRIPTOR PinDescriptor;
ULONG Flags;
ULONG InstancesPossible;
ULONG InstancesNecessary;
const KSALLOCATOR_FRAMING_EX *AllocatorFraming;
PFNKSINTERSECTHANDLEREX IntersectHandler;
} KSPIN_DESCRIPTOR_EX, *PKSPIN_DESCRIPTOR_EX;
通过这几个描述符,我们就定义了整个驱动的对象属性信息,AVStream框架就可以通过这些属性创建各自的设备对象,过滤器工厂,过滤器实例,引脚工厂,引脚实例等结构。
3. 分发表
在AVStrem架构中框架已经替我们做好了大部分的事情了,但是我们怎么和框架进行交互呢?这个就是分发表的作用,在每个描述符中都有一个KSXXX_DISPATCH
定义着各种回调函数。
KSDEVICE_DISPATCH
表示设备创建和PNP处理相关的回调接口,定义如下:
typedef struct _KSDEVICE_DISPATCH {
PFNKSDEVICECREATE Add;
PFNKSDEVICEPNPSTART Start;
PFNKSDEVICE PostStart;
PFNKSDEVICEIRP Q