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

DirectX.Capture 类库

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (222投票s)

2003年1月27日

公共领域

5分钟阅读

viewsIcon

4427508

downloadIcon

72304

一个用于将音视频捕获到 AVI 文件的 .NET 类库。

Sample Image - DirectXCapture.jpg

引言

本文介绍了一个在 .NET 中用于将音视频捕获到 AVI 文件的类库。此库的一些功能包括:

  • 列出并选择硬件设备
  • 访问常用的音频和视频设置(例如帧率、尺寸)
  • 支持音频和视频压缩编解码器
  • 支持视频预览
  • 支持电视调谐器
  • 支持交叉线和音频混音器
  • 检索设备能力
  • 显示驱动程序暴露的属性页
  • 包含 MSDN 风格的文档

Using the Code

Capture 类是此库的核心。下面是一个简单的示例

// Remember to add a reference to DirectX.Capture.dll
using DirectX.Capture

// Capture using the first video
// and audio devices available
Capture capture = new Capture( Filters.VideoInputDevices[0],
                               Filters.AudioInputDevices[0] );

// Start capturing
capture.Start();

// Stop capturing
capture.Stop();

请记住在您的项目中添加对 DirectX.Capture.dll 的引用。此 DLL 需要 DShowNET.dll,因此请确保它们在同一个目录中。添加引用后,Visual Studio .NET 应该会为您处理复制问题。

此示例将使用系统中安装的第一个视频和音频设备捕获视频和音频。要仅捕获视频,请将 null 作为第二个参数传递给构造函数。

该类被初始化为一个在 Windows temp 文件夹中的有效临时文件。要捕获到其他文件,请在开始捕获之前设置 Capture.Filename 属性。

第二个示例

下一个示例展示了如何更改视频和音频设置。诸如 Capture.FrameRateCapture.AudioSampleSize 等属性允许您以编程方式调整捕获。使用 Capture.VideoCapsCapture.AudioCaps 来确定这些属性的有效值。

Capture capture = new Capture( Filters.VideoInputDevices[0],
                               Filters.AudioInputDevices[1] );

capture.VideoCompressor = Filters.VideoCompressors[0];
capture.AudioCompressor = Filters.AudioCompressors[0];

capture.FrameRate = 29.997;                 // NTSC
capture.FrameSize = new Size( 640, 480 );   // 640x480
capture.AudioSamplingRate = 44100;          // 44.1 kHz
capture.AudioSampleSize = 16;               // 16-bit
capture.AudioChannels = 1;                  // Mono

capture.Filename = "C:\MyVideo.avi";

capture.Start();
...
capture.Stop();

上面的示例还展示了视频和音频压缩器的使用。在大多数情况下,您将希望使用压缩器。未压缩的视频每分钟可能轻易占用超过 1GB 的磁盘空间。尽可能早地设置 Capture.VideoCompressorCapture.AudioCompressor 属性。更改它们需要重建内部的 filter graph,这通常会导致其他大多数属性被重置为默认值。

幕后

此项目完全使用 DirectShow 进行视频捕获。一旦开始捕获,DirectShow 会启动另一个线程并自行处理视频和音频数据的检索/移动。这意味着您应该能够以 C 语言编写的应用程序相同的速度和质量进行捕获。

DirectShow 实现为一组 COM 组件,我们使用 .NET Interop 来访问它们。这方面开创性的工作由 NETMaster 在 DShowNET 项目 中完成。这个 Capture 库使用了 DShowNET 作为 interop 层,并只有少数几个扩展。这就是前面提到的 DShowNET.dll

坐落在这所有之上的就是 Capture 类库。任何 DirectShow 应用程序的核心是 filter graph 和 filter graph 管理器。有关详细概述,请参阅 MSDN 上的 Filter Graph 及其组件

最少的工作量

该库始终试图做到最少的工作量。问题是:DirectShow 非常灵活,但对于驱动程序开发人员来说,标准很少,而且我能测试的硬件有限。因此,该类试图避免执行任何可能不必要的工作,从而希望避免潜在的不兼容性。

一个例子是视频预览。您可以使用以下方法启动和停止预览:

// Start preview
capture.PreviewWindow = myPanelControl;

// Stop preview
capture.PreviewWindow = null;

希望这很容易使用。在内部,DirectShow 完成了大量工作:为 WDM 设备添加必需的上游过滤器,搜索预览引脚,使用 Overlay Manager 进行视频端口(硬件叠加),在没有独立预览引脚的情况下插入 SmartTee 过滤器,等等。该类没有在创建时立即渲染预览流,而是等到 PreviewWindow 属性被设置。

对于不需要预览的开发人员来说,这些工作都不会被执行。这意味着您的应用程序更有可能在更广泛的硬件上运行。对于需要预览的开发人员来说,这使得定位问题的原因并修复或优雅地处理它更加容易。

性能提示

Capture 类上的许多属性直接从底层 DirectShow COM 组件检索。如果您需要在代码块中反复引用某个属性,请复制该值并使用您的副本。

// AudioSampleSize is retrieved from DirectShow each iteration
for ( int c = 0; c < 32; c++ )
{
    if ( c == capture.AudioSampleSize )
        MessageBox.Show( "Found!" );
}

// A faster solution
int x = capture.AudioSampleSize;
for ( int c = 0; c < 32; c++ )
{
    if ( c == x )
        MessageBox.Show( "Found!" );
}

为什么该类不直接缓存该值?我们不知道过滤器(设备驱动程序)何时会更改此值,因此我们每次都必须检索该值。这意味着您将始终获得属性的真实值。

致谢

DirectShow interop 层由 NETMaster 在 DShowNET 项目中开发。MSDN 风格的文档是使用 nDoc 从源代码生成的。

故障排除

我使用 Asus v7700(NVidia GeForce2,参考驱动程序)和我的板载声卡对此进行了测试。我不能保证其他硬件会工作。但是,我预计大多数视频捕获卡和声卡都会工作。您可能会在电视调谐器卡和 DV 设备(Firewire 摄像机)上遇到问题,尽管这些问题应该可以解决。

可以尝试 DirectX SDK 中的 AMCap 示例(DX9\Samples\C++\DirectShow\Bin\AMCap.exe)或 Virtual VCR,一个免费的 DirectShow 捕获应用程序。

此类库使用 COM Interop 来访问 DirectShow 的全部功能,因此如果存在另一个应用程序能够成功使用某个硬件设备,那么应该可以修改此类库来使用该设备。请在下面的论坛中分享您的使用经验,无论好坏。

用户增强功能

以下增强功能已发布到讨论板:

感谢 fdaupias 和 dauboro 的贡献。我还没有时间发布包含这些增强功能的、经过测试的更新版本。如果有人想制作更新的下载 zip 文件,请发邮件给我,我将将其添加到此页面。请继续提供您的增强功能。

DirectX.Capture Wiki

此项目的 Wiki 在此。此 Wiki 任何人都可以编辑,无需注册。我希望此 Wiki 能让感兴趣的用户更容易地协作完成此项目。新版本、增强功能、技巧和窍门都可以发布在 Wiki 上。

© . All rights reserved.