DirectShow.NET
DirectShow用于DVD和文件播放、捕获以及采样器
摘要
这段实验性代码展示了如何在.NET和C#中使用DirectShow。这包括简单的媒体播放、播放DVD光盘、将视频流捕获到磁盘以及采样图像捕获器。
请注意,本文档不能替代阅读详细的DirectShow SDK文档!我**不会**解释DirectShow,只会解释一些使用的.NET互操作技术!
DirectShow
DirectShow是一个标准化的Microsoft Win32 API,允许您的应用程序使用任何兼容的电影或视频设备。DirectShow随DirectX 8.1(b)版本提供,支持Windows 98/ME/2000,并包含在XP中。请安装最新版本,本文档仅支持8.1。
再次强调,我不会描述任何DirectShow接口,您必须通过安装C++ SDK、阅读SDK文档并理解SDK示例来了解它们!DirectShow通过COM组件和接口暴露,分为以下两个“级别”:
- DirectShow **自定义接口** - 主要面向C++程序员。
- DirectShow **VB组件** - 专为VB6设计,提供类型库。
.NET互操作
虽然使用带有类型库的VB6组件在.NET中很容易,但无法直接访问自定义的DirectShow接口。我们必须使用以下方法之一进行互操作:
- 使用“C++托管扩展”,例如DirectX.NET所做的那样。
- 将所有接口从IDL重写为例如C#!
- 只使用一种(托管)语言(C#)。
- 大多数DirectShow接口并不复杂。
- 用于简单播放/捕获的DirectShow方法不是时间关键型的。
- 我们可以直接使用(已文档化的)接口,不受限制,没有“包装类”。
- 重写接口的初始工作量很大。
- 您必须理解互操作才能正确使用它。
- 不够.NET/面向对象。
// ======== IDL of ICaptureGraphBuilder2 (AXExtend.idl) ====== [ object, uuid(93E5A4E0-2D50-11d2-ABFA-00A0C9C6E38D), pointer_default(unique) ] interface ICaptureGraphBuilder2 : IUnknown { // Use this filtergraph HRESULT SetFiltergraph( [in] IGraphBuilder *pfg ); // what filtergraph are you using? // *ppfg->Release() when you're done with it HRESULT GetFiltergraph( [out] IGraphBuilder **ppfg); .......使用C#中的互操作属性将被翻译为
// ======== C# version of ICaptureGraphBuilder2 (DsExtend.cs) ======
[ComVisible(true), ComImport,
Guid("93E5A4E0-2D50-11d2-ABFA-00A0C9C6E38D"),
InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]
public interface ICaptureGraphBuilder2
{
[PreserveSig]
int SetFiltergraph( [In] IGraphBuilder pfg );
[PreserveSig]
int GetFiltergraph( [Out] out IGraphBuilder ppfg );
....
一旦我们在C#中有了所有这些接口定义,我们就可以像在C++中一样开始调用DirectShow了。
// ======== C++ code to create the COM instance of Filter Graph ======== JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGB)); // Have the graph builder construct its the...我们将
// appropriate graph automatically JIF(pGB->RenderFile(wFile, NULL)); // QueryInterface for DirectShow interfaces JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)); ....
CoCreateInstance
替换为Activator.CreateInstance
,而QueryInterface
在C#中只是一个简单的**转换**。// ======== C# code to create the COM instance of Filter Graph ========
Type comtype = null;
object comobj = null;
try {
comtype = Type.GetTypeFromCLSID( Clsid.FilterGraph );
if( comtype == null )
throw new NotSupportedException(
"DirectX (8.1 or higher) not installed?" );
comobj = Activator.CreateInstance( comtype );
graphBuilder = (IGraphBuilder) comobj; comobj = null;
int hr = graphBuilder.RenderFile( clipFile, null );
if( hr < 0 )
Marshal.ThrowExceptionForHR( hr );
mediaCtrl = (IMediaControl) graphBuilder;
....
项目结构
下载包含了所有这些C#源代码。
\DirectShow\ \DShowNET\ // the DirectShow interface definitions : \DsBugWO.cs // workaround for a bug \DsControl.cs // ported from control.odl \DsCore.cs // ported from axcore.idl \DsDevice.cs // device enumerator, helper functions \DsDVD.cs // DVD interfaces from dvdif.idl \DsExtend.cs // ported from axextend.idl \DsUtils.cs // utility classes, SDK Common sources \DsUuids.cs // UUIDs and CLSIDs from uuids.h \QEdit.cs // grabber interfaces from qedit.idl \CaptureNET\ // video stream capture sample \DVDPlayerNET\ // DVD player sample \PlayWndNET\ // simple media file playback \SampleGrabberNET\ // picture grabber
播放
下载中包含的第一个示例是PlayWndNET。它可以播放DirectShow已知的视频和音频文件格式,如avi、mpg、wav、mid等。
DVD播放器
对于下一个示例DVDPlayerNET,您必须安装第三方DVD编解码器,如WinDVD或PowerDVD。然后,C#示例使用DirectShow DVD接口观看电影。它还支持菜单导航。
抓取图像
提供的最复杂的示例是SampleGrabberNET。它在一个预览窗口中显示来自捕获设备(如DV摄像机、网络摄像头或电视卡)的实时视频流。通过按“Grab”(抓取)工具栏按钮,您可以将静态图像捕获到24位RGB位图文件中!
该示例还支持电视卡的IAMTVTuner
接口,因此您可以切换电视调谐器频道。
捕获
最后一个示例CaptureNET可用于将实时视频流捕获到磁盘。请注意,少数设置只能在启动时设置一次,并且立即开始写入AVI文件。
限制
- 实验性!请勿用于生产质量的代码。
- 这些示例仅提供部分且非常基本的功能。
- 我在Windows XP上进行了大部分测试,在Windows ME上进行了一些测试。
- 仅在非常有限的设备和少数媒体格式上进行了测试。
我使用了Logitech QuickCam、Sony DV摄像机、Hauppauge WinTV PCI和WinDVD。 - 从制造商那里获取最新的驱动程序(WDM)。
- 如果在对话框中选择了不受支持的设置,某些设备可能会失败。
- 此代码**无助于**解决任何DirectShow/WDM配置问题。
- 需要>128MB内存,>400MHz CPU,快速且大容量的硬盘。