Delphi中利用DirectX 8.0中DirectShow做VCD播放器 |
|
jackkcg
站務副站長 發表:891 回覆:1050 積分:848 註冊:2002-03-23 發送簡訊給我 |
此為轉貼資料 Delphi中利用DirectX 8.0中DirectShow做VCD播放器
www.Alltips.Com 2001-11-24 極限技術網 Microsoft公司發佈了 DirectX 8.0,較之以前的版本,版本進行了大幅度修改,使DirectShow成爲DirectX中的一部分,對DirectShow而言,新的DirectShow 媒體物件,全面支援*.AVI ,*.WAV,*.MPG,*.MP3 ,*.ASF以及DVD等格式的多媒體文件及多媒體流的高質量的播放及捕獲。
用DirectShow 編寫VCD播放器,可以說主要包括四步:
1.初始化COM物件,建立一個Filter graph builder的實例
2.再建立一個Filter graph,從文件中讀取流,並進行將流解壓後送到顯卡和音效卡,Filter得到輸入,産生輸出。對於一個MPEG-1的視頻解碼的Filter來說,他的輸入是壓縮過的MPEG1流,輸出是解壓後的RGB視頻流。
3.用Filter graph builder來指揮Filter graph運行
4.釋放COM物件,退出。
爲完成以上功能,主要要用到三個COM介面:
IGraphBuilder用來構造Filter graph;
IMediaControl用來:控制Filter graph中的媒體流;
tu
IMediaEvent用來處理Fiter graph中産生的事件,其中Filter graph manager實現了上面所有的介面,並且我們只需要發送簡單的命令,如:run、pause、stop等,就可以控制媒體的播放。採用以上介面就可以輕鬆實現VCD的播
圖1
放了,圖1爲筆者編寫的播放器介面,除以上介面外,增加了IBasicAudio介面控制聲音;VideoWindow介面控制播放表單的位置等屬性。
程式源代碼如下: unit Unit1;interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Ole2, DirectShow, ComCtrls, mmsystem;type TForm1 = class(TForm) Panel1: TPanel; PlayFile: TButton; FilePause: TButton; FileStop: TButton; OpenFileDialog: TOpenDialog; Button1: TButton; frame: TTrackBar; Timer1: TTimer; volumeban: TTrackBar; volume: TTrackBar; procedure PlayFileClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure Button1Click(Sender: TObject); procedure volumebanChange(Sender: TObject); procedure frameChange(Sender: TObject); procedure volumeChange(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure FilePauseClick(Sender: TObject); procedure FileStopClick(Sender: TObject); private procedure CloseDxcom; { Private declarations } public { Public declarations } end;function InitDxcom: boolean;var Form1: TForm1; g_pGraphBuilder: IGraphBuilder = nil; g_pMediaControl: IMediaControl = nil; // 播放狀態設置. g_pMediaSeeking: IMediaSeeking = nil; // 播放位置. g_pAudioControl: IBasicAudio = nil; // 音量/平衡設置. g_pVideoWindow: IVideoWindow = nil; //設置播放表單. PLAYING: boolean = false; //判斷是否正在播放implementation{$R *.DFM}function Initdxcom: boolean;begin Result := false; // 初始化COM介面 if failed(CoInitialize(nil)) then exit; // 創建DirectShow Graph if failed(CoCreateInstance(OLE2.TGUID(CLSID_FilterGraph), nil, CLSCTX_INPROC, OLE2.TGUID(IID_IGraphBuilder), g_pGraphBuilder)) then exit; // 獲取IMediaControl 介面 if failed(g_pGraphBuilder.QueryInterface(IID_IMediaControl, g_pMediaControl)) then exit; // 獲取IMediaSeeking 介面 if failed(g_pGraphBuilder.QueryInterface(IID_IMediaSeeking, g_pMediaSeeking)) then exit; // 獲取IBasicAudio 介面 if failed(g_pGraphBuilder.QueryInterface(IID_IBasicAudio, g_pAudioControl)) then exit; // 獲取IVideowindow 介面 if failed(g_pGraphBuilder.QueryInterface(IID_IVideoWindow, g_pVideoWindow)) then exit; // 所有介面獲取成功 Result := true;end;procedure tform1.CloseDxcom;begin // 停止播放 if Assigned(g_pMediaControl) then g_pMediaControl.Stop; // 釋放所有用到的介面。 if Assigned(g_pAudioControl) then g_pAudioControl := nil; if Assigned(g_pMediaSeeking) then g_pMediaSeeking := nil; if Assigned(g_pMediaControl) then g_pMediaControl := nil; if Assigned(g_pVideoWindow) then g_pVideoWindow := nil; if Assigned(g_pGraphBuilder) then g_pGraphBuilder := nil; CoUninitialize;end;procedure TForm1.PlayFileClick(Sender: TObject);begin g_pVideoWindow.put_Owner(panel1.handle); //設置播放表單 g_pVideoWindow.put_windowstyle(WS_CHILD or WS_Clipsiblings); //參數類型見WINDOWS API g_pVideoWindow.SetWindowposition(0, 0, panel1.width, panel1.height); //播放的圖像爲整個panel1的ClientRect//g_pAudioControl.put_Volume(VOLUME_FULL);//設置爲最大音量 g_pMediaControl.run; timer1.enabled := true; PLAYING := true;end;procedure TForm1.FormCreate(Sender: TObject);begin if Initdxcom() = false then showmessage('初始化DIRECTX SHOW介面出錯');end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);begin CloseDxcom;end;procedure TForm1.Button1Click(Sender: TObject);var s: string; _hr: Hresult; wFile: array[0..(Max_path * 2) - 1] of char;begin if OpenFileDialog.execute then //獲取指定視頻文件 begin s := OpenFileDialog.filename; MultiByteToWideChar(CP_ACP, 0, pchar(s), -1, @wFile, MAX_PATH); //轉換格式 _hr := g_pGraphBuilder.renderfile(@wfile, nil); // 建立了一個能夠播放文件的Filter Graph。第一個參數是檔案名,第二個參數必須爲nil if failed(_hr) then showmessage('打開文件錯誤'); end;end;procedure TForm1.volumebanChange(Sender: TObject);begin if not PLAYING then exit; g_pAudioControl.put_Balance(volumeban.Position * 100); //左右聲道音量平衡設置end;procedure TForm1.frameChange(Sender: TObject);var _stop: LONGLONG; _newpos: longlong;begin if not PLAYING then exit; // 獲得當前播放幀數 g_pMediaSeeking.GetStopPosition(_stop); _newpos := (_stop * frame.position) div 100; // 範圍檢查 if _newpos < 0 then _newpos := 0; if _newpos > _stop then _newpos := _stop; // 設置新播放幀數位置 g_pMediaSeeking.SetPositions( _newpos, AM_SEEKING_AbsolutePositioning, _newpos, AM_SEEKING_NoPositioning);end;procedure TForm1.volumeChange(Sender: TObject);begin if not PLAYING then exit; g_pAudioControl.put_Volume((volume.Position -100) * 100);end;procedure TForm1.Timer1Timer(Sender: TObject);var _current, _stop: LONGLONG;begin if not PLAYING then exit; g_pMediaSeeking.GetPositions(_current, _stop); //獲得當前位置 if _stop < > 0 then frame.Position := Trunc((_current * 100) / _stop); if _current = _stop then frame.Position := 0;end;procedure TForm1.FilePauseClick(Sender: TObject);begin g_pMediaControl.pause;//timer1.enabled:=true;end;procedure TForm1.FileStopClick(Sender: TObject);begin g_pMediaControl.stop; timer1.enabled := false; g_pVideoWindow.put_visible(false); g_pVideoWindow.put_Owner(0)end;end.
至此,該播放器就可以工作了,當然該播放器不僅可以播放VCD,MP3、AVI等文件也可以播放。
我們也可以利用IMediaSeeking的SetPositions作出Delphi中Tmediaplayer元件中的前進、到帶
等功能,而且利用IMediaSeeking的SetRate方法可以實現變速播放等功能,詳情請讀者參考微軟
公司的MSDN或DirectX8.0 SDK文檔。以上是我一點心得,如有錯誤或不足,請讀者批評改正! 發表人 - jackkcg 於 2002/12/09 21:52:42
------
********************************************************** 哈哈&兵燹 最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知 K.表Knowlege 知識,就是本站的標語:Open our mind |
japhenchen
高階會員 發表:51 回覆:444 積分:184 註冊:2003-07-23 發送簡訊給我 |
看到眼睛很累,所以就幫大大把這篇code排一下,讓後來的人能夠看懂一些
unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Ole2, DirectShow, ComCtrls, mmsystem; type TForm1 = class(TForm) Panel1: TPanel; PlayFile: TButton; FilePause: TButton; FileStop: TButton; OpenFileDialog: TOpenDialog; Button1: TButton; frame: TTrackBar; Timer1: TTimer; volumeban: TTrackBar; volume: TTrackBar; procedure PlayFileClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure Button1Click(Sender: TObject); procedure volumebanChange(Sender: TObject); procedure frameChange(Sender: TObject); procedure volumeChange(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure FilePauseClick(Sender: TObject); procedure FileStopClick(Sender: TObject); private procedure CloseDxcom; { Private declarations } public { Public declarations } end; function InitDxcom: boolean; var Form1: TForm1; g_pGraphBuilder: IGraphBuilder = nil; g_pMediaControl: IMediaControl = nil; // 播放狀態設置. g_pMediaSeeking: IMediaSeeking = nil; // 播放位置. g_pAudioControl: IBasicAudio = nil; // 音量/平衡設置. g_pVideoWindow: IVideoWindow = nil; //設置播放表單. PLAYING: boolean = false; //判斷是否正在播放 implementation {$R *.DFM} function Initdxcom: boolean; begin Result := false; // 初始化COM介面 if failed(CoInitialize(nil)) then exit; // 創建DirectShow Graph if failed(CoCreateInstance(OLE2.TGUID(CLSID_FilterGraph), nil, CLSCTX_INPROC, OLE2.TGUID(IID_IGraphBuilder), g_pGraphBuilder)) then exit; // 獲取IMediaControl 介面 if failed(g_pGraphBuilder.QueryInterface(IID_IMediaControl, g_pMediaControl)) then exit; // 獲取IMediaSeeking 介面 if failed(g_pGraphBuilder.QueryInterface(IID_IMediaSeeking, g_pMediaSeeking)) then exit; // 獲取IBasicAudio 介面 if failed(g_pGraphBuilder.QueryInterface(IID_IBasicAudio, g_pAudioControl)) then exit; // 獲取IVideowindow 介面 if failed(g_pGraphBuilder.QueryInterface(IID_IVideoWindow, g_pVideoWindow)) then exit; // 所有介面獲取成功 Result := true; end; procedure tform1.CloseDxcom; begin // 停止播放 if Assigned(g_pMediaControl) then g_pMediaControl.Stop; // 釋放所有用到的介面。 if Assigned(g_pAudioControl) then g_pAudioControl := nil; if Assigned(g_pMediaSeeking) then g_pMediaSeeking := nil; if Assigned(g_pMediaControl) then g_pMediaControl := nil; if Assigned(g_pVideoWindow) then g_pVideoWindow := nil; if Assigned(g_pGraphBuilder) then g_pGraphBuilder := nil; CoUninitialize; end; procedure TForm1.PlayFileClick(Sender: TObject); begin g_pVideoWindow.put_Owner(panel1.handle); //設置播放表單 g_pVideoWindow.put_windowstyle(WS_CHILD or WS_Clipsiblings); //參數類型見WINDOWS API g_pVideoWindow.SetWindowposition(0, 0, panel1.width, panel1.height); //播放的圖像?整個panel1的ClientRect// g_pAudioControl.put_Volume(VOLUME_FULL); //設置?最大音量 g_pMediaControl.run; timer1.enabled := true; PLAYING := true; end; procedure TForm1.FormCreate(Sender: TObject); begin if Initdxcom() = false then showmessage('初始化DIRECTX SHOW介面出錯'); end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin CloseDxcom; end; procedure TForm1.Button1Click(Sender: TObject); var s: string; _hr: Hresult; wFile: array[0..(Max_path * 2) - 1] of char; begin if OpenFileDialog.execute then begin //獲取指定視頻文件 s := OpenFileDialog.filename; MultiByteToWideChar(CP_ACP, 0, pchar(s), -1, @wFile, MAX_PATH); //轉換格式 _hr := g_pGraphBuilder.renderfile(@wfile, nil); // 建立了一個能夠播放文件的Filter Graph。第一個參數是檔案名,第二個參數必須?nil if failed(_hr) then showmessage('打開文件錯誤'); end; end; procedure TForm1.volumebanChange(Sender: TObject); begin if not PLAYING then exit; g_pAudioControl.put_Balance(volumeban.Position * 100); //左右聲道音量平衡設置 end; procedure TForm1.frameChange(Sender: TObject); var _stop: LONGLONG; _newpos: longlong; begin if not PLAYING then exit; g_pMediaSeeking.GetStopPosition(_stop); // 獲得當前播放幀數 _newpos := (_stop * frame.position) div 100; if _newpos < 0 then _newpos := 0; // 範圍檢查 if _newpos > _stop then _newpos := _stop; // 設置新播放幀數位置 g_pMediaSeeking.SetPositions( _newpos, AM_SEEKING_AbsolutePositioning, _newpos, AM_SEEKING_NoPositioning); end; procedure TForm1.volumeChange(Sender: TObject); begin if not PLAYING then exit; g_pAudioControl.put_Volume((volume.Position -100) * 100); end; procedure TForm1.Timer1Timer(Sender: TObject); var _current, _stop: LONGLONG; begin if not PLAYING then exit; g_pMediaSeeking.GetPositions(_current, _stop); //獲得當前位置 if _stop < > 0 then frame.Position := Trunc((_current * 100) / _stop); if _current = _stop then frame.Position := 0; end; procedure TForm1.FilePauseClick(Sender: TObject); begin g_pMediaControl.pause; //timer1.enabled:=true; end; procedure TForm1.FileStopClick(Sender: TObject); begin g_pMediaControl.stop; timer1.enabled := false; g_pVideoWindow.put_visible(false); g_pVideoWindow.put_Owner(0)end; end.我不懂,不懂,不懂....所以我才來ktop學工夫 |
jackkcg
站務副站長 發表:891 回覆:1050 積分:848 註冊:2002-03-23 發送簡訊給我 |
多謝japhenchen 兄的整理 哈哈
真正是太好了 *********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind to make knowledge together!
希望能大家敞開心胸,將知識寶庫結合一起
------
********************************************************** 哈哈&兵燹 最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知 K.表Knowlege 知識,就是本站的標語:Open our mind |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |