下载源程序:【北方网通】 【电信或网通】
【下载说明】
1、单击上面这个地址,打开下载页面。
2、点普通下载--等待30秒--点“下载”按钮--保存
这个实验性的代码展示了怎么在C#中使用DirectShow技术。它包含一个简单的媒体播放器、DVD播放器、抓取视频画面至硬盘和简单的截屏工具。
备注,这篇文章不会节省你详细阅读DirectShowSDK文档的时间。在这里,我不会解释什么是DirectShow,仅仅是使用了.NET的互操作技术。
DirectShow是一个微软Win32 API的标准,是为了能够在你的程序中使用兼容的视频或音频设备而开发的。DirectShow在xp、windows 98/me/2000上都可以使用,目前的DirectX版本是8.1b。请安装最新的版本,这篇文章的代码仅适用于8.1版本。
· 下载DirectX
再次强调下,我不会描述任何DirectShow接口,通过安装C++版本的SDK、阅读SDK文档和理解SDK实例,你会了解到它们。
· MSDN上的DirectX SDK
· MSDN上的DirectShow文档
DirectShow是作为COM组件和接口来使用的,它们包括两个分类:
· DirectShow自定义接口 –主要是为C++编程者
· DirectShow VB组件 –为VB6设计,提供一个类库
在.NET里面,你也可以使用DirectShow的VB6组件。
在.NET里面,使用VB6组件是很方便的。况且没有直接的方法去使用自定义DirectShow接口。我们需要使用以下几种互操作方法:
· Use 'Managed Extensions for C++', as done e.g.by DirectX.NET
· 使用“C++的托管扩展”,比如DirectX.NET
· Rewrite all the interfaces from IDL to e.g. C#!
· 从IDL重新写所有的接口,比如使用C#写。
I chose the second strategyfor this reasons :
由于这些原因,我选择了第二条策略:
· 仅用一种语言,比如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));
....
我们使用Activator.CreateInstance来替换CoCreateInstance,QueryInterface在C#中仅仅是一个简单的cast操作。
// ======== 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。它可以播放一个视频或音频格式的文件,像AVI、MPG、WAV、MID等等。
下一个例子是DVDPlayerNET,你必须安装一个第三方的DVD编码器,比如WinDVD或者PowerDVD。然后,这个C#例子使用DirectShow的DVD接口来播放电影。它也支持导航菜单。
最复杂的一个例子就是SampleGrabberNET了。它可以显示一个实时的视频流,比如DV摄像头、WEB摄像头或者TV卡。通过点击工具栏上面的“Grab”按钮,你可以抓取一个静态图片,保存成24位的RGB位图。
这个实例也支持TV卡的IAMTVTuner接口,因此,你可以选择电视的频道。
最后一个例子是CaptureNET,它可以被用来将一个实时的视频流保存到硬盘上。备注,一旦启动之后,有较少的参数可以调整,并且立即开始捕捉,并写入到一个AVI文件中。
受限的地方
· 实验阶段!在量产代码中,请不要使用。
· 例子仅仅提供部分非常基础的功能。
· 我在xp上做了很多的测试,但是很少在me上测试。
· 仅仅在少数的设备上测试过少数的媒体格式。我使用了Logitech QuickCam、Sony DV camcorder、Hauppauge WinTV PCI和WinDVD.
· Get the latest driver(WDM) from manufacturer.
· 从制造商那里获取最新的驱动。
· 如果你在对话框上选择了不支持的设置的话,某些设备可能会不能正常使用。
· 这些代码不会帮助你饿任何DirectShow或WDM配置问题。
· 使用大于128MB的内存,大于400MHz的处理器,快而大的硬盘
【更多阅读】