線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:6252
推到 Plurk!
推到 Facebook!

DirectShow之介面實戰篇  (原作)u2m

 
cmf
尊榮會員


發表:84
回覆:918
積分:1032
註冊:2002-06-26

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-07-31 10:01:02 IP:61.218.xxx.xxx 未訂閱
DirectShow之介面實戰篇(一) u2m(原作) 現今自己編程做一個多媒體播放工具是一件很令人開心愉悅的事情,但如果使用MediaPlay控制項開發則會受到很多限制,自己的很多好的創意想法都無法或者很難實現,如果利用微軟的DirectX介面開發則可以充分的將作者的獨特想法付諸於實現,何樂而不為呢!!不過關於DirectShow介面的開發說明文檔實在是少之又少,僅有的一些不是英文的就是一些關於理論方面的,真正關於介面實戰編程而且是用Delphi開發工具實現的更是鳳毛麟角,使很多人都望而卻步。在這裏,我把我應用Directshow開發的心得以及我搜集到一些資料重新整理編輯出來公佈,希望對所有由此興趣的同仁有所幫助,就算達到了我的目的。廢話少說,進入正文。 既然是介面實戰篇,就先把一些常用的介面列出來,讓大家有一些基本的認識,都是用來做什麼的,什麼時候我們會需要用到此介面。 IFilterGraph : 過濾通道介面 IFilterGraph2 : 增強的IFilterGraph IGraphBuilder : 最為重用的COM介面,用於手動或者自動構造過濾通道Filter Graph Manager IMediaControl : 用來控制流媒體,例如流的啟動和停止暫停等,播放控制介面 IMediaEvent : 播放事件介面 ,該介面在Filter Graph發生一些事件時用來創建事件的標誌資訊 並傳送給應用程式 IMediaEventEx : 擴展播放事件介面 IMediaPosition : 播放的位置和速度控制介面(控制播放位置只能為設置時間控制方式) IMediaSeeking : 另一個播放的位置和播放速度控制介面,在位置選擇方面功能較強.設置播放格式, 多種控制播放方式. 常用的有:(1)TIME_FORMAT_MEDIA_TIME單位100納秒。 (2)TIME_FORMAT_FRAME按幀播放 IBasicAudio : 聲音控制介面 IBasicVideo : 圖像控制介面(串列傳輸速率,寬度,長度等資訊) IVideoWindow: 顯示視窗控制介面 (有關播放視窗的一切控制,包括caption顯示,視窗位置控制等) ISampleGrabber: 捕獲圖像介面(可用於抓圖控制) IVideoFrameStep :控制單幀播放的介面 好了,熟悉了應用DirectShow應用開發常用的介面後,我們就通過一個實例媒體播放器來熟悉掌握這些介面,實例的代碼雖然簡單,但五臟俱全,功能強大,同時也瞭解一下應用DirectShow開發一般常用的步驟。 未完待續
------
︿︿
cmf
尊榮會員


發表:84
回覆:918
積分:1032
註冊:2002-06-26

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-07-31 10:09:02 IP:61.218.xxx.xxx 未訂閱
DirectShow之介面實戰篇(二) 大體說來,一般使用DirectShow介面編程無非3個步驟,初始化介面,利用介面中的控制函數使用控制操作,最後釋放介面。(當然這裏假定你已經擁有了directshow.pas等必須單元,如果沒有的話請在網上查找或者向我索要)(注:以下變數沒有定義,需自己定義使用) (1) 初始化介面部分 首先,需要定義需要使用的介面變數 GraphBuilder: IGraphBuilder; MediaControl: IMediaControl; MediaSeeking: IMediaSeeking; MediaPosition: IMediaPosition; MediaEventEx: IMediaEvent; BasicAudio: IBasicAudio; BasicVideo: IBasicVideo; VideoWindow: IVideoWindow; SampleGrabber: ISampleGrabber; VideoFrameStep: IVideoFrameStep; (1)然後需要使用CoCreateInstance函數創建一個Filter Graph Manager 實例,CoCreateInstance(TGUID(CLSID_FilterGraph),nil, CLSCTX_INPROC_SERVER, TGUID(IID_IGraphBuilder),GraphBuilder) 因為需要抓圖使用IsampleGrabber介面,需要創建SampleGrabber實例, var Filter: IBaseFilter; CoCreateInstance(CLSID_SampleGrabber, nil, CLSCTX_INPROC_SERVER, IID_IBaseFilter, Filter); (2) 調用QueryInterface函數獲取來獲取指標,好以後操作控制 Filter.QueryInterface(IID_ISampleGrabber, SampleGrabber); GraphBuilder.AddFilter(Filter, 'Grabber'); GraphBuilder.QueryInterface(IID_IMediaControl, MediaControl); GraphBuilder.QueryInterface(IID_IMediaPosition, MediaPosition); GraphBuilder.QueryInterface(IID_IMediaSeeking, MediaSeeking); GraphBuilder.QueryInterface(IID_IMediaEventEx, MediaEventEx); GraphBuilder.QueryInterface(IID_IVideoFrameStep, VideoFrameStep); GraphBuilder.QueryInterface(IID_IBasicAudio, BasicAudio); GraphBuilder.QueryInterface(IID_IBasicVideo, BasicVideo); GraphBuilder.QueryInterface(IID_IVideoWindow, VideoWindow); 當然為了安全起見,可以對以上每個過程進行是否成功判斷,給出資訊,否則很有可能出現問題找不到頭緒。好了,一切準備成功,就可以進入第三步,開始我們的控制操作了。 (3)通過介面提供的函數開始控制 哦,差點忘記一件重要的事情,在上面調用QueryInterface之前,還有兩件重要的事情要做,第一,要建立一個Unicode(wide character)字串,保存檔案名。 var _wfile: array[0..MAX_PATH - 1] of wchar; MultiByteToWideChar(CP_ACP, 0, pChar(播放檔案名), -1, @_wfile, MAX_PATH); 然後需要成功RenderFile才可以控制操作GraphBuilder.RenderFile(_wfile, nil); 當然在顯示的時候要把顯示表單和控制項關連起來,這裏需要通過IvideoWindow介面方法,VideoWindow. put_Owner(Edit1.Handle); VideoWindow. put_WindowStyle(DSVIDEO_WINDOW_CHILD_STYLE); VideoWindow.SetWindowPosition(0,0, Edit1.ClientWidth, Edit1.ClientHeight); 得到圖像的一些必要資訊,使用IbasicVideo介面中的方法,一些變數自己定義, BasicVideo.GetVideoSize(VideoWidth, VideoHeight); BasicVideo.get_BitRate(VideoBitRate); BasicVideo.get_AvgTimePerFrame(PerFrame); 得到當前檔的總時間以及播放時間,需要使用ImediaSeeking介面方法, MediaSeeking.GetDuration(Duration);//得到總時間 MediaSeeking.GetCurrentPosition(CurrentPos);//得到當前播放時間 也可以通過IMediaSeeking::SetPositions方法設置開始和結束時間。 哦,這裏得到的單位好像是毫米級的,可以自己轉化為秒級的. 還有,如果想以後能夠單幀控制播放,在這裏也需要設定播放格式為按幀播放。 MediaSeeking.SetTimeFormat(Time_Format_Frame); 播放,停止,暫停等控制 這些需要使用ImediaControl介面的方法,控制起來很簡單,分別為 MediaControl.Play; MediaControl.Stop; MediaControl.Pause; 未完待續
------
︿︿
cmf
尊榮會員


發表:84
回覆:918
積分:1032
註冊:2002-06-26

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-07-31 10:13:43 IP:61.218.xxx.xxx 未訂閱
DirectShow之介面實戰篇(三) 播放速度的設定 需要使用ImediaPosition的方法。 MediaPosition.put_Rate(1);//正常 MediaPosition.put_Rate(0.25);//慢速 MediaPosition.put_Rate(2);//快速 單幀播放控制 需要使用IvideoFrameStep的方法 VideoFrameStep.Step(1, nil); 音量控制 需要使用IbasicAudio的方法 增加音量: BasicAudio.get_Volume (&volume);//得到音量 volume:= volume volumestep; BasicAudio.put_Volume (volume);//增加一定的音量的分貝 減小音量: BasicAudio.get_Volume (&volume); //得到音量 volume:= volume -volumestep; BasicAudio.putVolume (volume); //減小一定音量的分貝 顯示放大縮小控制 只需改變Edit1的大小,然後使用IvideoWindow介面方法即可 VideoWindow.SetWindowPosition(0, 0, Edit1.Width, Edit1.Height); 單幀捕獲,抓圖 其實很多介面都提供了此功能,但是我更傾向於使用IsampleGrabber介面來實現,相對來說,效率高些。 這個控制起來做的工作稍微多些,首先,在打開文件的時候 var MediaType: TAM_MEDIA_TYPE; ZeroMemory(@MediaType, SizeOf(TAM_MEDIA_TYPE)); MediaType.majortype := MEDIATYPE_Video;//視頻流 MediaType.subtype := MEDIASUBTYPE_RGB24;//24位圖像 MediaType.formattype := FORMAT_VideoInfo; SampleGrabber.SetMediaType(MediaType);//關聯介面 SampleGrabber.SetBufferSamples(True); 然後在抓圖按鈕事件中如下操作 var MediaType: TAM_MEDIA_TYPE; VideoInfoHeader: TVideoInfoHeader; BitmapInfo: TBitmapInfo; Bitmap: HBitmap; Buffer: Pointer; BufferSize: Integer; begin SampleGrabber.GetConnectedMediaType(MediaType); ZeroMemory(@VideoInfoHeader, SizeOf(TVideoInfoHeader)); CopyMemory(@VideoInfoHeader, MediaType.pbFormat, SizeOf(VideoInfoHeader)); ZeroMemory(@BitmapInfo, SizeOf(TBitmapInfo)); CopyMemory(@BitmapInfo, @VideoInfoHeader.bmiHeader, SizeOf(VideoInfoHeader.bmiHeader)); Bitmap:=CreateDIBSection(0, BitmapInfo, DIB_RGB_COLORS, Buffer, 0, 0); SampleGrabber.GetCurrentBuffer(BufferSize, Buffer); Image1.Picture.Bitmap.Handle:=Bitmap end; 即可。 在這裏,先總結這麼多,希望對大家有所幫助,這些只是DirectX的一個皮毛,它可以實現的功能十分強大,我也只是把我在實際中的遇到的問題總結出來供大家參考,後面的工作還很多,我想我會逐步的更深入的總結這方面的經驗發表出來與大家分享,好了,DirectShow介面施展篇到這裏該完結了,如果大家有補充或者想法,請發表出來以便我總結整理,謝謝大家。 完結
------
︿︿
系統時間:2024-05-06 22:22:11
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!