DirectShow是Windows平台的流媒体框架。
CrossBar:a device might have multiple inputs,such as S-Video and composite video,The CrossBar filter enables the application to select the input.
CrossBar可以在多路输入之间切换输入。
device pin:设备引脚
filter通过设备引脚连接,但是数据不是通过引脚连接移动。
1. DirectShow介绍
头文件Dshow.h
依赖库:
- Strmiids.lib
- Quartz.lib 导出AMGetErrorText函数,不需要则可不添加
debug编译时,加d即可。
DirectShow包含在Windows SDK中。DirectShow包含在Windows XP SP2及以上版本的操作系统中。在Windows XP SP1及以前的操作系统版本可以通过DirectX SDK安装依赖库。
1.1 DirectShow术语
- Filter、Filter Graph、Filter Graph Manager
- Filter Pin
- Media Type、majortype、subtype、formattype
- Media Sample、Allocates内存分配器
- Data Flow
Filter与Filter Graph
Filter是DirectShow的基础组件,每个Filter执行一个特定的操作,例如:
- 读取文件
- 从视频采集设备中获取视频流
- 视频流解码
- 传递数据至显卡或声卡
Filter可以接收输入并生成输出。例如MJPEG解码Filter从视频流中取一帧,生成解码后的数据并输出。
每个Filter都有0或1个输入,可以有0或多个输出。输入端口称为Input PIN,输出端口称为Output PIN。
应该程序通过将Filter由输入PIN与输出PIN连接形成链来执行任务。一个Filter的输出就是链中下一个Filter的输入。一组连接的Filter被称为Filter Graph。
AVI视频文件播放的Filter Graph:
File Source Filter从硬盘中读取AVI视频文件;输出到AVI Splitter Filter解复用,分离出视频和音频,分别通过音频输出端口和视频输出端口输出;AVI Decompressor Filter从AVI Splitter Filter的视频输出端口获取视频流,并解压缩输出到Video Renderer Filter,使用GDI或DirectDraw显示到屏幕;Default DirectSound Device Filter从AVI Splitter Filter的音频输出端口读取音频数据,通过DirectSound 播放音频。
Filter Graph Manager
在上面的例子中,我们并不需要管理这个Filter Graph及其数据流,这些Filter是由Filter Graph Manager来控制的,例如:Run、Stop。如果需要更精确的控制,也可以通过COM接口直接访问Filter。Filter Graph Manager也会将实际通知传递给应用程序。
Filter Graph Manager还有另外一个作用,它提供了将Filter连接起来创建Filter Graph的方法。
编写一个DirectShow应用
任何一个DirectShow应用都需要执行以下3个任务:
- 创建一个Filter Graph Manager实例
- 使用Filter Graph Manager创建Filter Graph,将Filter连接起来
- 使用Filter Graph Manager控制Filter Graph运行及数据流,应用程序还需要响应来自Filter Graph Manager的事件
处理完成后,应用程序需要释放Filter Graph Manager和所有的Filter。
DirectShow是基于COM的,Filter Graph Manager和Filter都是COM对象。
DirectShow播放AVI文件
通过这个例子来展示DirectShow的魔力。
和上一节介绍的一样,创建一个DirectShow应用通常需要3步:
- 创建Filter Graph Manager实例
- 使用Filter Graph Manager实例创建一个Filter Graph
- 启动Filter Graph,使得数据通过链上的filter
因为DirectShow是基于COM的,所以首先需要初始化COM库:
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
// ... 初始化COM库异常
}
// some COM operation code ...
CoUninitialize();
现在正式开始DirectShow相关代码编写:
// 1. 创建Filter Graph Manager对象
IGraphBuilder *pGraph;
// 查找类标识为CLSID_FilterGraph的COM组件,使用改组件创建接口标识符为IID_IGraphBuilder的进程内组件对象pGraph
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
// 创建 Filter Graph
return;
}
/**
* 获取Filter Graph Manager的两个接口
* 1. IMediaControl 控制filter graph的启动和停止
* 2. IMediaEvent 从Filter Graph Manager获取事件,例如视频文件播放完毕事件
* */
IMediaControl *pControl;
IMediaEvent *pEvent;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// 2. 创建filter graph
hr = pGraph->RenderFile(L"1.avi", NULL);
// 3. Filter Graph Manager MediaControl Run
pControl->Run();
long evCode = 0;
// Filter Graph Manager MediaEvent Wait Event
pEvent->WaitForCompletion(INFINITE, &evCode);
pControl->Release();
pEvent->Release();
pGraph->Release();
如何将硬件设备添加到Filter Graph
所有的DirectShow Filter都是用户模式组件,如何将内核模式下的硬件添加到Filter Graph?必须通过用户模式的Filter封装设备。常见的硬件封装Filter有:
- Audio Capture Filter
- VFW Capture Filter
- TV Tuner Filter
- TV Audio Filter
- Analog Video Crossbar Filter
- KsPorxy Filter
KsProxy可以代表任意一个Windows Driver Model(WDM)流设备,硬件厂商可以以插件方式扩展KsProxy来支持自定义功能。新设备一般都支持WDM规范。支持WDM规范的视频采集设备比VFW设备拥有更强大的功能,增加了控制视频亮度、色度等功能。
WDM支持内核流,数据完全在内核模式下流动,无需切换到用户模式。
这些Filter将COM调用转化位设备驱动的调用,将信息传递只内核模式下的设备驱动,并将结果反馈给应用程序。将设备封装成Filter后,开发者可以像调用其他Filter一样调用设备Filter来控制设备。
2. DirectShow基础
2.1 视频渲染Video Rendering
DirectShow提供了以下几个Filter渲染视频:
- Video Renderer Filter:在所有支持DirectX的平台都可以使用,没有特殊的系统要求。它尽可能使用DirectDraw渲染视频,如果不成功则使用GDI。在Windows XP以前的系统中它是默认的渲染器。
- Video Mixing Renderer Filter 7(VMR-7):VMR-7在Windows XP上可用,它是XP的默认渲染器。VMR-7通常采用DirectDraw 7渲染。它提供了很多以前旧的Filter上没有的强大的特性,包括应用程序控制DirectShow表面渲染的插件模型。VMR代替了Video Renderer和Overlay Mixer。
- Video Mixing Renderer Filter 9(VMR-9):VMR-9是新版本的Video Mixing Renderer,采用了Direct3D 9做渲染。它在所有支持DirectX的平台上都可用。它不是默认的渲染器,因为它需要比Video Renderer Filter更高的系统权限。
- Overlay Mixer Filter:专门为DVD和广播视频设计。它也支持Video Port Extensions(VPEs),使MPEG-2硬件解码器或电视解调器能与显卡一起工作,将视频直接发送到显卡。
- Enhanced Video Renderer(EVP)Filter:从Windows Vista开始可用,与早期的视频渲染器相比它有更好的性能。
如何选择正确的视频渲染器:
Filter | Remarks |
---|---|
Enhanced Video Renderer(EVR) | 采用Direct3D 9,Windows Vista及之后版本操作系统可用 |
Video Mixing Renderer 9(VMR-9) | 采用Direct3D 9,Windows XP及之后版本操作系统可用 |
Video Mixing Renderer 7(VMR-7) | 采用DirectDraw,Windows XP及之后版本操作系统可用 |
Overlay Mixer | 通过DirectDraw支持overlay的硬件 |
Video Renderer Filter | 采用DirectDraw或GDI |
通常在Windows Vista及以后的操作系统版本中推荐使用EVR,在早期的Windows版本中首选VMR-9。Windows XP及以后版本的系统默认都是采用VMR-7。
有窗模式(Windowed Mode)和无窗模式(Windowless Mode)
Video Renderer Filter只支持有窗模式。VMR-7和VMR-9两者都支持,为了向后兼容它们默认是有窗模式,但是更推荐无窗模式。EVR只支持无窗模式。
- 创建Filter Graph Manager实例对象
- 创建VMR7/9实例对象并添加到Filter Graph Manager
- 获取VMR7/9配置接口,配置为无窗模式
- 获取窗口控制接口,设置视频显示的窗口句柄,并可设置视频显示的位置
2.2 响应Filter Graph事件
2. 查找设备
2.1 设备枚举器System Device Enumerator
要查找设备,通常都是根据根据类别使用设备枚举器来获取。