DirectShow 图形过滤(Filter)管理器介绍
Filter Graph Manager也是一个COM组件,它是DirectShow的控制中心,它控制Filter的运行。它有以下几个功能:
- 协调各个Filter的状态。Filter有运行,暂停,停止三种状态,在Filter Graph中,各个Filter的状态必须协调一到,否则会引起冲突。Filter Graph Manager互责协调各个Filter的状态。
- 提供一个参考时间,用以同步音频流和视频流。
- 提供一套用于建立Filter Graph的方法
- 与应用程序进行交互,它会将Filter Graph内部发生的事件,通过消息的方式通知应用程序。
这里对每一种功能都作了简要的描述。
- 状态改变(State changes):筛选器中的状态更改必须按特定顺序发生。因此,应用程序不会直接向过滤器发出状态更改命令。相反,它向过滤器图形管理器发出一个命令,后者将命令分发给每个过滤器。查找的工作方式与此类似:应用程序将醒询命令发送给过滤器图形管理器,后者将其分发给过滤器。
- 参考时钟(Reference clock)。图中的所有过滤器使用相同的时钟,称为参考时钟。基准时钟确保所有流都是同步的。应该呈现视频帧或音频样本的时间称为呈现时间。呈现时间是相对于基准时钟测量的。滤波器图管理器选择一个参考时钟,通常是声卡上的时钟或系统时钟。
- 图表事件(Graph events)。过滤器图管理器使用事件队列通知应用程序过滤器图中发生的事件。这种机制类似于Windows消息循环。
- 图形构建方法(Graph-building methods)。过滤器图管理器为应用程序提供了向图中添加过滤器、将过滤器连接到其他过滤器以及断开过滤器连接的方法。
DiretShow常用过滤器(filter)
- IGraphBuilder:为应用程序提供创建过滤器图表的方法。
- IMediaControl:提供控制过滤器图表中多媒体数据流的方法,包括运行、暂停和停止。
- IMediaEventEx:继承自IMediaEvent接口,处理过滤器图表的事件。
- IVideoWindow:用于设置多媒体播放器窗口的属性,应用程序可以用它来设置窗口的所有者、位置和尺寸等属性。
- IBasicAudio:用于控制音频流的音量和平衡。
- IBasicVideo:用于设置视频特性,如视频显示的目的区域和源区域。
- IMediaSeeking:提供搜索数据流位置和设置播放速率的方法。
- IMediaPosition:用于寻找数据流的位置。
- IVideoFrameStep:用于步进播放视频流,可使DirectShow应用程序,包括DVD播放器一次只播放一帧视频。
媒体类型(Media Type)
媒体类型使用结构体AM_MEDIA_TYPE表示:
媒体类型是描述数字媒体格式的一种通用的可扩展方式。两个过滤器相连时,必须使用一致的媒体类型,否则这两个过滤器就不能相连。媒体类型能识别上一级过滤器传送给下一级过滤器的数据类型,并对数据进行分类。
实际在很多应用程序中,用户根本不需要担心媒体类型的问题,DirectShow会处理好所有的细节。但有些应用程序需要对媒体类型进行操作。媒体类型一般可以有两种表示:AM_MEDIA_TYPE和CMediaType。前者是一个结构,后者是从这个结构继承过来的类。
typedef struct _AMMediaType {
GUID majortype;
GUID subtype;
BOOL bFixedSizeSamples;
BOOL bTemporalCompression;
ULONG lSampleSize;
GUID formattype;
IUnknown *pUnk;
ULONG cbFormat;
BYTE *pbFormat;
} AM_MEDIA_TYPE;
每个AM_MEDIA_TYPE由三部分组成:Major type、Subtype和Format type。这三个部分都使用GUID(全局唯一标识符)来唯一标示。
- Major type主要定性描述一种媒体类型,这种媒体类型可以是视频、音频、未解析的字节流或MIDI数据等等;
- Subtype进一步细化媒体类型,如果是视频的话可以进一步指定是RGB-24,还是RGB-32,或是UYVY等,如果是音频类型 ,可以是PCM音频,MPEG-1负载等。Subtype提供了比 Major type更多的信息,但它并没有定义有关格式的所有信息。例如,视频子类型没有定义图像大小或帧速率,这些其实是通过 format block来描述。
-Format block 详细描述格式的数据块。AM_MEDIA_TYPE结构的pbFormat成员指向格式块,用于描述此数据块。
pbFormat成员的类型为void*,因为格式块的布局根据媒体类型而变化。例如,PCM audio使用WAVEFORMATEX 。视频使用各种结构,包括VIDEOINFOHEADER和VIDEOINFOHEADER2。AM_MEDIA_TYPE结构体的formattype成员是一个GUID,用于指定格式块中包含的结构。每个格式结构都分配了一个GUID。cbFormat成员指定格式块的大小。在取消引用pbFormat指针之前,请始终检查这些值。
如果媒体类型的三个部分都指定了某个具体的GUID值,则称这个媒体类型是完全指定的;如果媒体类型的三个部分中有任何一个值是GUID_NULL,则称这个媒体类型是不完全指定的。GUID_NULL具有通配符的作用。
AM_MEDIA_TYPE也包含一些可选字段。这些可用于提供附加信息,但不要求过滤器使用它们:
- lSampleSize:如果此字段不为零,则定义每个采样(sample)的大小。如果为零,则表示采样大小可能因采样而异。
- bFixedSizeSamples:如果此布尔标志为TRUE,则表示lSampleSize中的值有效。否则,应该忽略lSampleSize。
- bTemporalCompression:如果此布尔标志为FALSE,则表示所有帧都是关键帧。
下面是一段媒体类型检查的示例代码:
HRESULT CheckMediaType(AM_MEDIA_TYPE *pmt)
{
if (pmt == NULL) return E_POINTER;
// Check the major type. We're looking for video.
if (pmt->majortype != MEDIATYPE_Video)
{
return VFW_E_INVALIDMEDIATYPE;
}
// Check the subtype. We're looking for 24-bit RGB.
if (pmt->subtype != MEDIASUBTYPE_RGB24)
{
return VFW_E_INVALIDMEDIATYPE;
}
// Check the format type and the size of the format block.
if ((pmt->formattype == FORMAT_VideoInfo) &&
(pmt->cbFormat >= sizeof(VIDEOINFOHEADER) &&
(pmt->pbFormat != NULL))
{
// Now it's safe to coerce the format block pointer to the
// correct structure, as defined by the formattype GUID.
VIDEOINFOHEADER *pVIH = (VIDEOINFOHEADER*)pmt->pbFormat;
// Examine pVIH (not shown). If it looks OK, return S_OK.
return S_OK;
}
return VFW_E_INVALIDMEDIATYPE;
}