全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2128
推到 Plurk!
推到 Facebook!

Delphi中利用DirectX 8.0中DirectShow做VCD播放器

 
jackkcg
站務副站長


發表:891
回覆:1050
積分:848
註冊:2002-03-23

發送簡訊給我
#1 引用回覆 回覆 發表時間:2002-12-09 21:51:07 IP:61.64.xxx.xxx 未訂閱
此為轉貼資料 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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-10-21 13:02:17 IP:211.96.xxx.xxx 未訂閱
看到眼睛很累,所以就幫大大把這篇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

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-10-21 17:25:32 IP:61.221.xxx.xxx 未訂閱
多謝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
系統時間:2024-05-08 5:24:30
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!