[Delphi] DirectShow 강좌
DirectShow를 이용한 동영상 플레이 시키는 방법을 소개합니다.
Delphi XE 이상에서 컴파일 가능합니다.
준비(폼디자인)
1. 먼저 VCL Forms Application 을 생성합니다.
프로젝트를 저장하고 폼위에 Panel 컴포넌트를 올립니다.
Screen 으로 사용할 패널입니다.
Screen Panel의 Caption 을 지우고
Align 프로퍼티를 alClient 로 설정합니다.
그리고 Panel 을 하나 더 올립니다. 버튼올릴 패널입니다.
Caption 을 지우고 Align 프로퍼티를 alBotton으로 설정합니다.
프로젝트를 저장하고 폼위에 Panel 컴포넌트를 올립니다.
Screen 으로 사용할 패널입니다.
Screen Panel의 Caption 을 지우고
Align 프로퍼티를 alClient 로 설정합니다.
그리고 Panel 을 하나 더 올립니다. 버튼올릴 패널입니다.
Caption 을 지우고 Align 프로퍼티를 alBotton으로 설정합니다.
코딩
2. uses 절에 Winapi.DirectShow9, Winapi.ActiveX 를 추가합니다.
3. private 절에 동영상 플레이어에서 사용할 기본 개체를 선언합니다.
FilterGraph: IGraphBuilder; //필터그래프의 인터페이스 중의 하나.
MediaControl: IMediaControl; // 미디어 제어 인터페이스 Play, Stop, Pause.
VideoWindow: IVideoWindow; // 영상 제어 인터페이스
4. Form Create 이벤트에서
CoInitialize(nil); //COM을 초기화한다
6. 폼위에 버튼을 올린 후 Click 이벤트에 변수 선언을 한 후
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | var WFileName : Array[0..255] of WideChar; PFileName : PWideChar; begin StringToWideChar('재생할 파일경로+파일명',WFileName,255); PFileName := @WFileName[0]; // 동영상 파일을 Render 하기 if FilterGraph.RenderFile(PFileName,nil) = S_OK then begin // 영상을 플레이할 패널 지정 Screen = Panel VideoWindow.put_Owner(Screen.Handle); VideoWindow.put_WindowStyle(WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN); VideoWindow.SetWindowPosition(0,0,Screen.Width,Screen.Height); VideoWindow.put_MessageDrain(Screen.Handle); MediaControl.Run; end; end; | cs |
이제 Panel 위에 재생하려는 영상이 플레이 됩니다.
7. Form Close 이벤트에
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // 중지 if Assigned(MediaControl) then MediaControl.Stop; // 비디오 윈도우 해제 If Assigned(VideoWindow) then Begin VideoWindow.put_Visible(false); VideoWindow.put_Owner(0); End; // DirectShow 인터페이스 해제 FilterGraph := nil; MediaControl := nil; VideoWindow := nil; CoUninitialize; //COM을 셧다운시킨다. | cs |
이렇게 코딩합니다.
이렇게 하면 Panel 위에 선택한 동영상이 재생됩니다.
추가기능
8. 열기 버튼 클릭했을때 파일 선택창 나오도록 하기
with TOpenDialog.Create(Self) do
try
Filter := 'Media Files(*.avi;*.mpg;*.wmv;*.mp4)|*.avi;*.mpg;*.wmv;*.mp4;|All Files(*.*)|*.*;';
Title := 'Open Media Files..';
if Execute then begin
LoadMedia(FileName);
end;
finally
Free;
end;
9. 미디어 불러오는 코드 프로시져로 변경
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | procedure TfrmMain.LoadMedia(filename: String); var WFileName : Array[0..255] of WideChar; PFileName : PWideChar; begin StringToWideChar(filename,WFileName,255); PFileName := @WFileName[0]; // 동영상 파일을 Render 하기 if FilterGraph.RenderFile(PFileName,nil) = S_OK then begin // 영상을 플레이할 패널 지정 Screen = Panel VideoWindow.put_Owner(Screen.Handle); VideoWindow.put_WindowStyle(WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN); VideoWindow.SetWindowPosition(0,0,Screen.Width,Screen.Height); VideoWindow.put_MessageDrain(Screen.Handle); MediaControl.Run; // 재생/일시정지 버튼 상태 btnPlayPause.Caption := ''일시정지''; end; end; | cs |
10. 재생/일시정지 토클 버튼 추가
화면에 버튼 컴포넌트를 추가한 후 OnClick 이벤트에
1 2 3 4 5 6 7 8 | if btnPlayPause.Caption = '일시정지' then begin MediaControl.Pause; btnPlayPause.Caption := '재생' end else begin MediaControl.Run; btnPlayPause.Caption := '일시정지' end; | cs |
11. 영상을 재생한 후 프로그램을 크기를 바꾸보면 처음 재생했던 패널 크기로만 영상이 재생되는걸
알수 있습니다. 패널 OnResize 이벤트에
if Assigned(VideoWindow) then
VideoWindow.SetWindowPosition(0, 0, screen.Width, screen.Height);
위와 같이 코딩을 하면 패널 크기가 바뀔때마다 화면 크기를 변경해 줍니다.
이젠 위 화면 같이 트랙바와 라벨컴포넌트를 이용해
타임라인 제어와 재생시간 표시를 해보겠습니다.
12. 트랙바 컨트롤을 화면에 추가합니다.
강좌 9. 에서 만든 LoadMedia 함수에 총재생시간을 구해서 트랙바의 MAX 값과 Min 값을 세팅해줍니다.
//총 재생 시간 구하기
MediaPosition.get_Duration(MediaLength);
TrackBar1.Max := trunc(MediaLength);
TrackBar1.Min := 0;
13. 트랙바 OnChange 이벤트에 아래와 같이 코딩해줍니다.
1 2 3 4 5 6 7 | If Assigned(MediaPosition) then Begin // LockTrack 은 Boolean 형의 전역변수임 if not LockTrack then begin // 미디어의 위치를 트랙바위치로 지정 MediaPosition.put_CurrentPosition(TrackBar1.Position); end; End; | cs |
14. 타이머 컴포넌트를 하나 추가하고 OnTimer 이벤트에
1 2 3 4 5 6 7 8 9 10 11 12 | var CurPos : Double; begin If Assigned(MediaPosition) then Begin MediaPosition.get_CurrentPosition(CurPos); Label1.Caption := Format('%s', [SecondToTimeStr(CurPos)]); LockTrack := true; TrackBar1.Position := trunc(CurPos); LockTrack := false; End; end; | cs |
LockTrack 전역변수를 사용하는 이유는 타이머 이벤트에서 트랙바 포지션을 바꿀때 OnChange 이벤트를 타지 않게 하기 위해서
15. SecontToTimeStr 함수 만들기
1 2 3 4 5 6 7 8 9 10 | function TfrmMain.SecondToTimeStr(Sec: Double): string; var H, M, S: Integer; begin H := Trunc(Sec) div 3600; M := (Trunc(Sec) - H * 3600) div 60; S := Trunc(Sec) - H * 3600 - M * 60; Result := Format('%d:%d:%d', [H, M, S]); end; // 현재 값을 받아서 시:분:초 로 표시 | cs |
이상입니다. 실제 구현한 소스코드는 아래 github에 공개해 놓았습니다.
기초적인 소스니 필요하신 분은 이용하시길 바라요!!!
그리고 동영상 플레이어 강좌지만 파일 열기에서 mp3를 선택하면 mp3가 플레이 됩니다. ㅎㅎ
댓글
댓글 쓰기