-
VMR9 다이렉트 쇼.GamePrograming/Direct3D 2010. 7. 15. 10:22
VMR9을 이용한 동영상 재생 클래스
DirectX9 VMR9(Video Mixing Renderer)을 사용한 동영상 재생 및 믹싱 클래스
Introduction
비디오 파일을 재생하기 위해 DirectShow Video Mixing Renderer9을 사용한 간단한 래퍼 클래스.
DirectX9 에서는 멀티미디어 응용프로그램에서 새로운 비디오 렌더러를 사용할 수 있다.
하지만, 이 렌더러(VMR9)는 호환성 문제 때문에 기본 렌더러로 사용되지 않는다.
Windows XP에서 기본 렌더러는 VMR7 이다. 이 렌더러는 하위버전 윈도우에 있던 것이다.가장 큰 차이점은 성능과 오버레이 믹싱 능력: VMR7은 DirectDraw를 사용하고, VMR9은 그래픽카드의 3D가속 기능을 지원하는 Direct3D를 기반으로 한다.
그 결과 최근 그래픽카드에서 향상된 성능, 더 나은 오버레이 믹싱, DirectX9을 지원하는 윈도우에서 호환성
그리고, de-interlacing & ProcAmp (contrast, saturation, etc.)과 같은 몇가지 새로운 기능을 사용할 수 있다.아무튼, VMR9이 매우 훌륭해 보이지만 윈도우 버전에 관계없이 기본 렌더러가 아니다.
그래서 VMR9을 수동으로 붙여야 하며 이 클래스를 만든 이유다.What you need...
데모를 실행하려면 DirectX9 runtime이 설치되어 있어야 하고, Direct3D와 호환되는 그래픽카드가 장착되어 있어야 한다.
빌드하려면 DirectX9 SDK를 깔아야 한다. 소스는 Visual C++ 6 SP5, Visual Studio .NET 2003 SP1에서 생성했다.Using the code
A first look
모든 DirectShow 그래프 관리 및 VMR 루틴은 클래스 하나에 포함되어 있다 :
CVMR9Graph.
[-] Collapse
class CVMR9Graph
{
// Constructor / destructor
public:
CVMR9Graph();
CVMR9Graph(HWND MediaWindow,
int NumberOfStream = 4);
virtual ~CVMR9Graph();
// Methods
public:
// Graph configuration
void SetNumberOfLayer(int nNumberOfLayer);
BOOL SetMediaWindow(HWND MediaWindow);
BOOL SetMediaFile(const char* pszFileName,
int nLayer = 0);
BOOL PreserveAspectRatio(BOOL bPreserve = TRUE);
IBaseFilter* AddFilter(const char* pszName,
const GUID& clsid);
// Graph control
BOOL PlayGraph();
BOOL StopGraph();
BOOL ResetGraph();
IMediaEvent* GetPtrMediaEvent();
IMediaControl* GetPtrMediaControl();
IMediaSeeking* GetPtrMediaSeeking();
IBasicAudio* GetPtrBasicAudio();
// Layer control
BOOL GetVideoRect(LPRECT pRect);
int GetAlphaLayer(int nLayer);
BOOL SetAlphaLayer(int nLayer, int nAlpha);
DWORD GetLayerZOrder(int nLayer);
BOOL SetLayerZOrder(int nLayer, DWORD dwZOrder);
BOOL SetLayerRect(int nLayer, RECT layerRect);
// Bitmap control
BOOL SetBitmap(const char* pszBitmapFileName,
int nAlpha, COLORREF cTransColor, RECT bitmapRect);
BOOL SetBitmapParams(int nAlpha,
COLORREF cTransColor, RECT bitmapRect);
// Reflected from window
BOOL Repaint();
BOOL Resize();
// helper
LPCTSTR GetLastError();
protected:
// [...]
};
편의를 위해 헤더에 DirectShow, Direct3D 헤더와 pragma 지시자로 lib를 포함하도록 했다.
Step 1 : Building a simple player
간단한 동영상 플레이어 만들기 아주 쉽다:
- 프로젝트에 VMR9Graph.h 와 VMR9Graph.cpp 파일을 포함한다,
- 응용프로그램에
CVMR9Graph
인스턴스를 추가, - 동영상 재생을 위한 윈도우를 만든다,
CVMR9Graph::SetMediaWindow(hMyVideoPlaybackHandle)
를 호출하여 동영상 재생 윈도우 설정,CVMR9Graph::SetMediaFile(0, pszPathToMyFile)을 호출하여 재생할 동영상 파일을 설정
,CVMR9Graph::RunGraph()를
호출하여 동영상을 재생한다.
이러면 동영상이 재생되지만 동영상 크기에 맞게 창이 조정되지는 않는다...
Step 2 : Forwarding events
응용프로그램에서 동영상 갱신이나 창크기를 그래프에게 전달해야 한다:
WM_SIZE
메시지 핸들러를 만들어CVMR9Graph::Resize()를 호출하고
,WM_PAINT
메시지 핸들러를 만들어CVMR9Graph::Repaint()를 호출한다.
CVMR9Graph::PreserveAspectRatio(FALSE)
를 호출하여 동영상 가로/세로 비율을 유지 여부를 지정할 수 있다.Step 3: Mixing video
여러개의 파일은 재생 레이어로 처리됐다. 각 레이어는 알파 블렌딩, 크기, 위치 같은 몇가지 속성을 지원한다.
여러 레이어 동영상은 크기가 큰 것을 기준으로 처리된다.
삽입된 각 레이어는 인덱스로 식별한다;
다음 예제는 동영상 파일 2개를 읽어서 첫번째 동영상의 알파값을 50%로 설정한다.
[-] Collapse
// load media files
myGraph.SetMediaFile(0, "C:\\Video1.avi");
myGraph.SetMediaFile(1, "C:\\Video2.mpg");
// set alpha value to video1
myGraph.SetAlphaLayer(0, 50);
데모 프로그램에서 알파값이 실시간으로 적용되는 것을 볼 수 있다.
Note 1: 나는 DivX 파일 2개를 믹싱할 수 없지만, DivX 하나와 다른 코덱은 가능하다... 왜 그런지 모르겠다... DirectShow 샘플도 같은 문제가 있다.
Note 2:
CVMR9Graph는 사운드 렌더러를 하나만 붙인다.
그래서 첫번째 동영상만 소리가 나온다. 사운드 렌더러를 추가하려면CVMR9Graph::AddFilter(_T"Another Sound Renderer", CLSID_DSoundRender)를 호출하면 된다
.Step 4 : Setting an overlay bitmap
CVMR9Graph에서 오버레이 비트맵은
Direct3D 서피스에 로딩된다. 비트맵 형식은 GIF, JPEG, PNG, BMP, DIB, TGA, or DDS format.오버레이 비트맵은 다음 파라메터와 함께
CVMR9Graph::SetBitmap()을 호출한다
:- 비트맵 파일의 경로,
- 알파값 (오버레이 비트맵은 최상위에 나타난다),
- 비트맵 투명 컬러키,
- 비트맵 크기와 위치.
오버레이 비트맵은 상당히 유용한 기능이다:
- 조그만 오버레이 표시기를 표현하거나,
- 동영상 영역을 오려낼 때 (비정형 스킨 윈도우를 만들어 재생하면 재밌을 듯...).
Last step: Go further away
클래스는 간결하고 재생 컨트롤은 최소화하려고 했는데 다음의 DirectShow 인터패이스를 추가할 수 있다.
IMediaEvent
: 그래프의 상태와 이벤트를 받는다.CVMR9Graph는 자동으로
WM_MEDIA_NOTIF
메시지를 재생창에 보낸다; 이때IMediaEvent::GetEvent()를 호출하여 이벤트 타입을 얻어오면 된다
.IMediaControl
: 재생, 일시정지 등의 기능을 제공한다.IMediaSeeking
: 재생 속도와 위치를 제어할 수 있다.IBasicAudio
: 사운드 볼륨과 밸런스를 제어할 수 있다.
Known issue
그래프가 동작중일 때,
CVMR9Graph::Stop()
이나CVMR9Graph::SetMediaFile()을 호출할 수 있지만
일부의 경우에 제대로 동작하지 않는다. 특히 비트맵 파일과 조합한 후...CVMR9Graph::ResetGraph()를 호출하면
그래프를 파괴하고 새 인스턴스를 생성한다.재생 창을 리사이징할 때 약간 깜박임이 있다... 왜냐하면 MFC window와 표준
OnEraseBackgnd()
구현 때문이다? -_-;;// TODO : some improvements
IVMRMonitorConfig9
인터페이스가 있지만 사용하지 않는다. 멀티 모니터에서 유용하다.
- 데브피아 오새롬(diebuster)님 글 펌 -