L
LeeChange
Unregistered / Unconfirmed
GUEST, unregistred user!
本期将诞生我们的第一个DS程序,播放AVI文件。我们将发现用Delphi写一个这样的程序仅
需要几行代码(M$原文为用C++仅需要几行,但说什么也比用MediaPlayer控件写的多)。不过
他确实非常简单,类似与Hello World这样的东东。
用DS写播放器包括四步:
1.建立一个Filter graph builder的实例
2.再建立一个Filter graph
3.用Filter graph builder来指挥Filter graph运行
4.等他播完,退出。
为完成以上功能,要用到三个COM接口:
IGraphBuilder:构造Filter graph
IMediaControl:控制Filter graph中的媒体流
IMediaEvent:处理Fiter graph中产生的事件
Filter graph manager实现了上面所有的接口。
开始先调用CoInitialize来初始化COM library,再调用CoCreateInstance建立Filter graph
manager。
var
Graph: IGraphBuilder;
...
CoInitialize(nil);
CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, Graph);
这样,我们就得到了Filter graph builder的一个实例Graph,再通过他得到另外两个接口
var
MediaControl: IMediaControl;
MediaEvent: IMediaEvent;
...
Graph.QueryInterface(IID_IMediaControl, MediaControl);
Graph.QueryInterface(IID_IMediaEvent, MediaEvent);
接下来,就是程序的核心了:
var
evCode: Integer;
...
Graph.RenderFile('c:/program files/borland/delphi5/demos/coolstuf/speedis.avi',
nil);
MediaControl.Run;
MediaEvent.WaitForCompletion(INFINITE, evCode);
IGraphBuilder.RenderFile方法建立了一个能够播放文件的Filter Graph。第一个参数是文件
名,第二个参数必须为nil。
当Filter graph建立好后,就可以播放了。IMediaControl.Run让Graph运转起来。调用这个
方法后,整个graph就象一部机器运做起来。
IMediaEvent.WaitForCompletion可以理解为
repeat
do
Nothing
until 流已播完;
在实际运用中,我们应避免使用IFFINITE做为等待时间。这样我们将不知道要等多久,而在
这段时间内,可能还要做别的事情:比如说响应其他事件,喝点可乐什么的。
我们忽略的所有的错误信息,在现实中却不能这样做。象如果文件不存在,RenderFile会
返回一个错误代码:VFW_E_NOT_FOUND。
最后,要释放所有用到的接口。(具我对Delphi中接口管理的理解,Delphi应该自动销毁
接口,但我接受Macro Cantu的建议,手工销毁)
MediaEvent:=nil;
MediaControl:=nil;
Graph:=nil;
CoUninitialize;
Source Code:
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, DirectShow, ActiveX;
type
TMainForm = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
Graph: IGraphBuilder;
MediaControl: IMediaControl;
MediaEvent: IMediaEvent;
end;
var
MainForm: TMainForm;
implementation
{$R *.DFM}
{ TMainForm }
procedure TMainForm.FormCreate(Sender: TObject);
begin
CoInitialize(nil)
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
CoUninitialize
end;
procedure TMainForm.FormShow(Sender: TObject);
var
evCode: Integer;
begin
CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, Graph);
Graph.QueryInterface(IID_IMediaControl, MediaControl);
Graph.QueryInterface(IID_IMediaEvent, MediaEvent);
Graph.RenderFile('c:/program files/borland/delphi5/demos/coolstuf/speedis.avi',
nil);
MediaControl.Run;
MediaEvent.WaitForCompletion(INFINITE, evCode);
MediaEvent:=nil;
MediaControl:=nil;
Graph:=nil;
Close
end;
end.
需要几行代码(M$原文为用C++仅需要几行,但说什么也比用MediaPlayer控件写的多)。不过
他确实非常简单,类似与Hello World这样的东东。
用DS写播放器包括四步:
1.建立一个Filter graph builder的实例
2.再建立一个Filter graph
3.用Filter graph builder来指挥Filter graph运行
4.等他播完,退出。
为完成以上功能,要用到三个COM接口:
IGraphBuilder:构造Filter graph
IMediaControl:控制Filter graph中的媒体流
IMediaEvent:处理Fiter graph中产生的事件
Filter graph manager实现了上面所有的接口。
开始先调用CoInitialize来初始化COM library,再调用CoCreateInstance建立Filter graph
manager。
var
Graph: IGraphBuilder;
...
CoInitialize(nil);
CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, Graph);
这样,我们就得到了Filter graph builder的一个实例Graph,再通过他得到另外两个接口
var
MediaControl: IMediaControl;
MediaEvent: IMediaEvent;
...
Graph.QueryInterface(IID_IMediaControl, MediaControl);
Graph.QueryInterface(IID_IMediaEvent, MediaEvent);
接下来,就是程序的核心了:
var
evCode: Integer;
...
Graph.RenderFile('c:/program files/borland/delphi5/demos/coolstuf/speedis.avi',
nil);
MediaControl.Run;
MediaEvent.WaitForCompletion(INFINITE, evCode);
IGraphBuilder.RenderFile方法建立了一个能够播放文件的Filter Graph。第一个参数是文件
名,第二个参数必须为nil。
当Filter graph建立好后,就可以播放了。IMediaControl.Run让Graph运转起来。调用这个
方法后,整个graph就象一部机器运做起来。
IMediaEvent.WaitForCompletion可以理解为
repeat
do
Nothing
until 流已播完;
在实际运用中,我们应避免使用IFFINITE做为等待时间。这样我们将不知道要等多久,而在
这段时间内,可能还要做别的事情:比如说响应其他事件,喝点可乐什么的。
我们忽略的所有的错误信息,在现实中却不能这样做。象如果文件不存在,RenderFile会
返回一个错误代码:VFW_E_NOT_FOUND。
最后,要释放所有用到的接口。(具我对Delphi中接口管理的理解,Delphi应该自动销毁
接口,但我接受Macro Cantu的建议,手工销毁)
MediaEvent:=nil;
MediaControl:=nil;
Graph:=nil;
CoUninitialize;
Source Code:
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, DirectShow, ActiveX;
type
TMainForm = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
Graph: IGraphBuilder;
MediaControl: IMediaControl;
MediaEvent: IMediaEvent;
end;
var
MainForm: TMainForm;
implementation
{$R *.DFM}
{ TMainForm }
procedure TMainForm.FormCreate(Sender: TObject);
begin
CoInitialize(nil)
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
CoUninitialize
end;
procedure TMainForm.FormShow(Sender: TObject);
var
evCode: Integer;
begin
CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, Graph);
Graph.QueryInterface(IID_IMediaControl, MediaControl);
Graph.QueryInterface(IID_IMediaEvent, MediaEvent);
Graph.RenderFile('c:/program files/borland/delphi5/demos/coolstuf/speedis.avi',
nil);
MediaControl.Run;
MediaEvent.WaitForCompletion(INFINITE, evCode);
MediaEvent:=nil;
MediaControl:=nil;
Graph:=nil;
Close
end;
end.