Multimedia Player with DirectShow Part 1
Zamrony P Juhara
15 September 2006 16:28:00 (1525 views)
First part of tutorial that explains how to use DirectShow, one of DirectX component, to create multimedia player with Delphi
Printer-friendly version
Introduction
DirectShow is one of DirectX component useful for multimedia streaming. This tutorial is first part of creating TV tuner application tutorial (inspired by question posted by mikroplus in Delphindo mailing list). Because creating TV Tuner with DirectShow needs knowledge about Directshow, so for first part, this tutorial discusses basic steps to create DirectShow application. To create simple application with DirectShow is not so hard.
What do dou need?
You need following softwares:
Brain.
DirectX version 8 or newer.
Delphi compiler. I use Delphi 7.
DirectX header conversion. You can download DirectX 9 header conversion or DirectX 8.1 header conversion. I use DirectX 8.1 header conversion.
COM Initialization
To initialize COM, we callCoInitialize(). For example:
CoInitialize(nil);
CoInitialize() is declared in Activex.pas unit.
Creating Filter Graph Manager.
DirectShow uses filter graph (or simply filter) to refer to software components that operate on multimedia data. Filter graph manager is manager of filters.
To create Filter Graph Manager, we can use CoCreateInstance() function, declared in activex.pas
Fore example:
var FFilterGraph:IGraphBuilder;
CoCreateInstance(CLSID_FilterGraph,nil,
CLSCTX_INPROC_SERVER,
IID_IGraphBuilder,
FFilterGraph);
CLSID_FilterGraph is classID for filter graph manager (declared in Directshow.pas unit), CLSCTX_INPROC_SERVER indicates that we use in-process COM server (DirectX is in-process COM server). IID_IGraphBuilder is interface ID for IGraphBuilder. IGraphiBuilder interface is interface of filter graph manager. If succeed, FFilterGraph will be filled with address of interface IGraphBuilder instance, otherwise it will be filled with nil.
Creating filter graph and add it to Filter graph manager.
DirectShow has many built-in filters, on of it is filter reader to read multimedia file. To read multimedia file and play it, IGraphBuilder has RenderFile() method useful for constructiong filter graph and add filter graph to filter graph manager automatically.
var FFilename:string;
wFilename:widestring;
begin
wFilename:=WideString(FFilename);
FFilterGraph.RenderFile(PWideChar(wFilename),nil);
end;
RenderFile() expects filename to be rendered. It should be type of PWideChar (2 byte per 1 character), therefore, if we use string, it must be typecasted to widestring. Second parameter is PlayList. This parameter is reserved and must be set to nil.
RenderFile doesn't clear existing filter graph. If we call RenderFile twice then all filter will be played simultaneous. This behaviour may not what we expected.
Removing filter graph from filter graph manager.
IGraphBuilder has RemoveFilter method to remove a filter from filter graph manager. For example:
FFilterGraph.RemoveFilter(aFilter);
Where aFilter is filter graph type of IBaseFilter that we want to delete. To get list of filters in filter graph manager, we use enumFilters().
FFilterGraph.EnumFilters(enum);
enum is type of IEnumFilters. This interface has method called Next to access next filter. For example
while (enum.Next(1,afilter,@totRead)=S_OK) do
begin
//do something with filter
end;
First parameter is number of filter we want to retrieve. In example above, we take filter one by one. afilter is filter type of IBaseFilter, totRead is address of variable that will filled with actual filter retrieved. According to Microsoft, afilter is array of IBaseFilter and its total element is equal to number of filter requested, but ub its declaration in DirectShow.pas, its type is IBaseFilter.
To remove all filter:
while (enum.Next(1,afilter,@totRead)=S_OK) do
begin
FFilterGraph.RemoveFilter(aFilter);
enum.Reset;
end;
After a filter is deleted, enum is no longer consistent with content of filter graph (out of sync). To make it consistent, we need to reset it.
Get other interfaces from filter graph manager.
Other interfaces we need is IMediaControl useful for controlling multimedia streaming process. IMediaSeeking is useful for seeking position in multimedia stream. IMediaEvent and IMediaEventEx.is used for event notification. To get those interfaces (except IMediaEventEx), we query from IGraphBuilder interface. For example:
var FMediaControl:IMediaControl;
aEvent:IMediaEvent;
FMediaEvent:IMediaEventEx;
FMediaSeek:IMediaSeek;
FFilterGraph.QueryInterface(IID_IMediaControl,FMediaControl);
FFilterGraph.QueryInterface(IID_IMediaEvent,aEvent);
aEvent.QueryInterface(IID_IMediaEventEx,FMediaEvent);
FFilterGraph.QueryInterface(IID_IMediaSeeking,FMediaSeek);
For IMediaEventEx, we don't quiery it from IGraphBuilder. IMediaEventEx is an extension of IMediaEvent and must be queried from IMediaEvent.
Sending DirectShow Event Notification Request.
To let us know what is currently going on, we need to tell DirectShow that we want to get notified. We use SetNotifyWindow() method of IMediaEventEx. For example:
FMediaEvent.SetNotifyWindow(aHandle,WM_MMNOTIFY,integer(self));
aHandle is window window that will receive WM_MMNOTIFY message. WM_MMNOTIFY is our own custom message we define. Custom message should be between WM_APP-WM_APP+$BFFF.
const WM_MMNOTIFY=WM_APP+$1234;
Don't forget to add messages.pas unit. Third parameter is our own data. This parameter will get passed to message handler via lParam of WM_MMNOTIFY. In above example, we send address of class instance.
Processing event
Create and event handler for WM_MMNOTIFY, for example:
procedure WM_MMNotify(var msg:TMessage);message WM_MMNOTIFY;
and in its implementation
procedure TfrmMediaPlayer.WM_MMNotify(var msg: TMessage);
var aplayer:TBasicPlayer;
evCode,param1,param2:integer;
begin
aplayer:=TBasicPlayer(msg.LParam);
aplayer.EventObj.GetEvent(evCode,param1,param2,0);
case evCode of
EC_COMPLETE:begin
//lakukan sesuatu
end;
end;
aplayer.EventObj.FreeEventParams(evCode,param1,param2);
end;
msg.lParam will hold address of class instance (see "Sending DirectShow Event Notification Request" above).
IMediaEventEx has GetEvent() useful to get code of event occured and its parameters. Because this function allocates memory for parameters of event, we must call FreeEventParams() to avoid memory leak. For complete event code, you can look at DirectX documentation. I use EC_COMPLETE very often. It tells us when data streaming is complete.
Controlling Data Streaming.
IMediaControl is used to control flow of multimedia data.
To start streaming, we use Run.
FMediaControl.Run;
To stop streaming, we use Stop, for example
FMediaControl.Stop;
To pause,
FMediaControl.Pause;
Seeking Position in Stream
We use IMediaSeeking to seek out position in multimedia stream. With IMediaSeeking, we can play stream from any position. From beginning of stream, from middle or else. Directshow uses two position terms for seeking, i.e, current position and stop position. Current position is current position of streaming, while stop position is position where streaming will be stopped. To get current position and stop position, we use GetPositions().
FMediaSeek.GetPositions(currentPos,
StopPos);
To set current position and stop position, we use SetPositions().
FMediaSeek.SetPositions(CurrentPos,
AM_SEEKING_AbsolutePositioning,
StopPos,
AM_SEEKING_AbsolutePositioning);
AMSEEKING_AbsolutePositioning is flag that indicates tha
没有合适的资源?快使用搜索试试~ 我知道了~
DirectSound有一个缓冲区对象IDirectSoundBuffer
共3个文件
txt:2个
zip:1个
4星 · 超过85%的资源 需积分: 10 39 下载量 50 浏览量
2010-05-24
16:49:37
上传
评论 1
收藏 34KB RAR 举报
温馨提示
DirectSound有一个缓冲区对象IDirectSoundBuffer,该对象表示一个包含数据的缓冲区,这些数据以PCM格式被存储,该对象不仅可以用于开始、停止或暂停声音的播放,还能够设置声音数据中诸如频率和格式等属性。 缓冲区分为主缓冲区和副缓冲区,主缓冲区中是听者将要听到的音频信号,一般是将副缓冲区中信号混音后的结果。而副缓冲区中存放着许多单独的声音信号,有的可以直接播放,有的要混音,有的循环播放。主缓冲区由DirectSound自动创建,而副缓冲区需由应用程序来创建。DirectSound将副缓冲区中的声音混合后,存入主缓冲区,再输出到相应播放设备。
资源推荐
资源详情
资源评论
收起资源包目录
DXShowPlay.rar (3个子文件)
Multimedia Player with DirectShow.zip 29KB
Multimedia Player with DirectShow.txt 18KB
www.pudn.com.txt 218B
共 3 条
- 1
tanshikao
- 粉丝: 1
- 资源: 8
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
前往页