CAviCap 和 CFrameGrabber - AVICap 窗口的包装器






4.86/5 (53投票s)
1999年12月9日

649993

19013
AVICap 包装器,
引言
AVICap 窗口类为应用程序提供了一个基于消息的接口,用于访问视频和波形音频采集硬件,以及控制将视频流捕获到磁盘的过程。不幸的是,它有一些严重的限制。
- 格式、源和视频标准的所有设置操作都在驱动程序的对话框中完成。
- 程序控制复杂,且无法保证结果的准确性。
- 捕获条件与 AVICap 窗口的 WM_VISIBLE 标志密切相关。
- 不支持窗口拉伸。
- 大多数捕获驱动程序都有内部缓冲区队列(fifo),因此当用户应用程序需要捕获单个帧时,它们无法提供令人满意的时序精度。它们只是从缓冲区队列返回最后一个帧。
总之,AVICap 窗口对于控制将视频流捕获到磁盘的过程来说足够好,但在大多数情况下对于实时视频处理却毫无用处。为了解决这个问题,我编写了一个 AVICap 窗口的封装类,以便与实时视频协同工作。这个类最初在 CodeGuru 上进行了描述。之后,我收到了大量关于 AviCap 类实现和用法的提问。我意识到,对于那些不熟悉 VfW 技巧的程序员来说,CAviCap 类并不那么容易理解,因此也不那么有用。在这篇文章中,我将尝试回答关于 CAviCap 实现的最常见问题。此外,我还将介绍一个新的 AVIcap 窗口封装类。这个类有一个非常简单的接口,面向刚开始接触 VfW 的程序员。
视频捕获软件组件
Avicap32.dll 导出了 capCreateCaptureWindow
函数,用于创建 AVICap 窗口。由于捕获驱动程序本质上是 16 位 DLL,Avicap32.dll 不会间接调用捕获驱动程序。它将驱动程序的调用转换为 16 位的 Avicap.dll 和 mmsystem.dll,这些 DLL 负责处理捕获驱动程序。Windows 98 还包含一个软件层,可以将 VfW 1.1 接口转换为 WDM 视频捕获接口。这个转换软件仅适用于 Windows 98 中外部总线(USB 和 1394)上的视频捕获设备。有关 Windows 98 上 USB 和 WDM 的更多信息,请参阅 http://support.microsoft.com/support/kb/articles/Q192/1/12.ASP。
另一种捕获方式是使用 DirectShow 接口。它封装了标准的 AviCap 窗口,并为 USB 设备提供了独立的 WDM 驱动程序接口。有关更多信息,请参阅 DirectShow SDK。
CAviCap 类实现。
CAviCap
类提供了 AVICap 窗口类的功能,以及用于管理窗口的成员,但排除了流式操作。在内部,这个类是通过 MFC 常用的方式(“动态子类化”)实现的。大多数公共方法都是 WM_CAP_XXXX 消息的辅助函数,但有少数方法为程序员提供了增强的控制。文件 "cavicap.h" 包含了所有必要的函数描述。
在您的应用程序中使用此类:
- 创建
CAviCap
类对象。 - 调用
Create
成员函数来创建一个 AVICap 窗口。请注意,如果您创建的是不可见窗口,StartPreview
方法将不起作用,因为 AVICap 会禁用隐藏/最小化捕获窗口的控制计时器。如果您需要不可见的捕获窗口,则必须使用GrabOneFrame
成员函数来控制捕获。 - 调用
GetDriversList
方法以获取可用驱动程序的列表。 - 调用
ConnectWithDriver
方法。根据m_DoQuickConnection
标志,连接将带有/不带有驱动程序参数测试进行。通常,这种测试可能非常慢,并且可能导致与 VfW 1.1 不完全兼容的驱动程序“冻结”。我认为,最好的方法是在软件设置/安装时测试一次驱动程序。注意:某些驱动程序在测试期间可能会弹出消息框。此外,驱动程序对话框中的“公共格式”列表可能与您使用
EnumValidFrameSize
方法获得的列表有很大差异。这是一个非常奇怪的事实,但有时可能非常有用。 - 使用
SetFrameSize
和SetBitResolution
或SetFormat
方法设置所需的帧大小和颜色分辨率。 - 使用
SetFrameCallBack
安装您自己的回调函数,如果您需要直接访问图像数据。捕获驱动程序将在捕获到新帧时调用您的函数,响应内部计时器事件或GrabOneFrame
成员函数的调用。驱动程序将VIDEOHDR
结构指针传递给回调函数。结构成员lpData
指向图像数据缓冲区。
- 使用
StartPreview
以间隔(由SetPreviewRate
定义)进行顺序捕获,或者通过调用GrabOneFrame
成员函数来控制捕获。有关其他方法用法的详细信息,请参阅演示项目“AviCapTest”。
CFrameGrabber 类实现。
这个简单的封装类用于单帧捕获。尽管该类不支持 AVICap 窗口的许多功能,如文件流、预览、回调通知,但它可以用于大多数应用程序任务。
在您的应用程序中使用此类:
- 创建
CFrameGrabber
类对象。 - 调用
Create
成员函数来创建一个 AVICap 窗口。默认情况下,将创建不可见的子窗口,并建立与默认捕获驱动程序的连接。如果找不到捕获驱动程序,函数将返回“FALSE”。 - 如果窗口成功创建,则对象即可使用。
- 调用
GetDIB
成员函数来捕获设备无关位图(DIB
)。也可以调用GetImageBitsBuffer
,它返回图像缓冲区指针。为了获取新图像,请在至少 20 毫秒后调用这些函数。 - 您可以使用
GetImageSize
和GetImageBitsResolution
成员函数确定当前的帧大小和位分辨率。 VideoFormatDialog
和VideoSourceDialog
允许调用标准的驱动程序对话框。
演示程序
在公共工作区文件中包含两个演示程序。项目已在 MSVC++ 5.0 和 6.0 中编译和测试。AviCapTest.exe 使用 CAviCap
类进行捕获,FrameGrabberTest.exe 基于 FrameGrabber
类。这些演示程序连接到计算机上安装的默认捕获驱动程序。此外,AviCapTest 还对驱动程序进行了全面测试。这些类的一些“标准”和“增强”命令组合在菜单中。两个项目还包括简单的图像处理示例。