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

DirectShow.NET

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (190投票s)

2002年7月22日

公共领域

3分钟阅读

viewsIcon

4418114

downloadIcon

34003

DirectShow用于DVD和文件播放、捕获以及采样器

Sample Image - directshownet.jpg

免责声明:使用DirectShow和.NET Framework 1.0的实验性代码

摘要

这段实验性代码展示了如何在.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设计,提供类型库。
您可以使用VB6的DirectShow播放组件,如本CodeProject文章所述:C#中的DirectShow MediaPlayer(Daniel Strigl)

.NET互操作

虽然使用带有类型库的VB6组件在.NET中很容易,但无法直接访问自定义的DirectShow接口。我们必须使用以下方法之一进行互操作:

  • 使用“C++托管扩展”,例如DirectX.NET所做的那样。
  • 将所有接口从IDL重写为例如C#!
出于以下原因,我选择了第二种策略:
  • 只使用一种(托管)语言(C#)。
  • 大多数DirectShow接口并不复杂。
  • 用于简单播放/捕获的DirectShow方法不是时间关键型的。
  • 我们可以直接使用(已文档化的)接口,不受限制,没有“包装类”。
当然,这也有一些缺点:
  • 重写接口的初始工作量很大。
  • 您必须理解互操作才能正确使用它。
  • 不够.NET/面向对象。
一个典型的在C#中重写IDL接口的例子如下:
// ======== 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等。

DirectShow playback

DVD播放器

对于下一个示例DVDPlayerNET,您必须安装第三方DVD编解码器,如WinDVD或PowerDVD。然后,C#示例使用DirectShow DVD接口观看电影。它还支持菜单导航。

DirectShow DVD

抓取图像

提供的最复杂的示例是SampleGrabberNET。它在一个预览窗口中显示来自捕获设备(如DV摄像机、网络摄像头或电视卡)的实时视频流。通过按“Grab”(抓取)工具栏按钮,您可以将静态图像捕获到24位RGB位图文件中!

DirectShow picture grabber

该示例还支持电视卡的IAMTVTuner接口,因此您可以切换电视调谐器频道。

捕获

最后一个示例CaptureNET可用于将实时视频流捕获到磁盘。请注意,少数设置只能在启动时设置一次,并且立即开始写入AVI文件。

DirectShow Capturing

限制

  • 实验性!请勿用于生产质量的代码。
  • 这些示例仅提供部分且非常基本的功能。
  • 我在Windows XP上进行了大部分测试,在Windows ME上进行了一些测试。
  • 仅在非常有限的设备和少数媒体格式上进行了测试。
    我使用了Logitech QuickCam、Sony DV摄像机、Hauppauge WinTV PCI和WinDVD。
  • 从制造商那里获取最新的驱动程序(WDM)。
  • 如果在对话框中选择了不受支持的设置,某些设备可能会失败。
  • 此代码**无助于**解决任何DirectShow/WDM配置问题。
  • 需要>128MB内存,>400MHz CPU,快速且大容量的硬盘。
© . All rights reserved.