65.9K
CodeProject 正在变化。 阅读更多。
Home

CAviCap 和 CFrameGrabber - AVICap 窗口的包装器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (53投票s)

1999年12月9日

viewsIcon

649993

downloadIcon

19013

AVICap 包装器, 以简化实时视频处理和单帧捕获

  • 下载演示项目 - 77 Kb
  • 下载源代码文件 - 17 Kb

    引言

    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" 包含了所有必要的函数描述。

    在您的应用程序中使用此类:

    1. 创建 CAviCap 类对象。
    2. 调用 Create 成员函数来创建一个 AVICap 窗口。请注意,如果您创建的是不可见窗口,StartPreview 方法将不起作用,因为 AVICap 会禁用隐藏/最小化捕获窗口的控制计时器。如果您需要不可见的捕获窗口,则必须使用 GrabOneFrame 成员函数来控制捕获。
    3. 调用 GetDriversList 方法以获取可用驱动程序的列表。
    4. 调用 ConnectWithDriver 方法。根据 m_DoQuickConnection 标志,连接将带有/不带有驱动程序参数测试进行。通常,这种测试可能非常慢,并且可能导致与 VfW 1.1 不完全兼容的驱动程序“冻结”。我认为,最好的方法是在软件设置/安装时测试一次驱动程序。

      注意:某些驱动程序在测试期间可能会弹出消息框。此外,驱动程序对话框中的“公共格式”列表可能与您使用 EnumValidFrameSize 方法获得的列表有很大差异。这是一个非常奇怪的事实,但有时可能非常有用。

    5. 使用 SetFrameSizeSetBitResolutionSetFormat 方法设置所需的帧大小和颜色分辨率。
    6. 使用 SetFrameCallBack 安装您自己的回调函数,如果您需要直接访问图像数据。捕获驱动程序将在捕获到新帧时调用您的函数,响应内部计时器事件或 GrabOneFrame 成员函数的调用。驱动程序将 VIDEOHDR 结构指针传递给回调函数。结构成员 lpData 指向图像数据缓冲区。
    7. 使用 StartPreview 以间隔(由 SetPreviewRate 定义)进行顺序捕获,或者通过调用 GrabOneFrame 成员函数来控制捕获。

      有关其他方法用法的详细信息,请参阅演示项目“AviCapTest”。

    CFrameGrabber 类实现。

    这个简单的封装类用于单帧捕获。尽管该类不支持 AVICap 窗口的许多功能,如文件流、预览、回调通知,但它可以用于大多数应用程序任务。

    在您的应用程序中使用此类:

    1. 创建 CFrameGrabber 类对象。
    2. 调用 Create 成员函数来创建一个 AVICap 窗口。默认情况下,将创建不可见的子窗口,并建立与默认捕获驱动程序的连接。如果找不到捕获驱动程序,函数将返回“FALSE”。
    3. 如果窗口成功创建,则对象即可使用。
    4. 调用 GetDIB 成员函数来捕获设备无关位图(DIB)。也可以调用 GetImageBitsBuffer,它返回图像缓冲区指针。为了获取新图像,请在至少 20 毫秒后调用这些函数。
    5. 您可以使用 GetImageSizeGetImageBitsResolution 成员函数确定当前的帧大小和位分辨率。
    6. VideoFormatDialogVideoSourceDialog 允许调用标准的驱动程序对话框。

    演示程序

    在公共工作区文件中包含两个演示程序。项目已在 MSVC++ 5.0 和 6.0 中编译和测试。AviCapTest.exe 使用 CAviCap 类进行捕获,FrameGrabberTest.exe 基于 FrameGrabber 类。这些演示程序连接到计算机上安装的默认捕获驱动程序。此外,AviCapTest 还对驱动程序进行了全面测试。这些类的一些“标准”和“增强”命令组合在菜单中。两个项目还包括简单的图像处理示例。

  • © . All rights reserved.