DirectShow之介面實戰篇 (原作)u2m |
|
cmf
尊榮會員 發表:84 回覆:918 積分:1032 註冊:2002-06-26 發送簡訊給我 |
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 發送簡訊給我 |
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 發送簡訊給我 |
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介面施展篇到這裏該完結了,如果大家有補充或者想法,請發表出來以便我總結整理,謝謝大家。
完結
------
︿︿ |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |