이 예는 MSDN에 나온 샘플 DirectShow어플리케이션이다.
앞에서 말했던 DirectShow 어플리케이션 작성의 4가지 스텝을 다시 기억해 보자.
-
필터그래프 매니저의 인스턴스 생성
-
매니저를 이용해서 필터 그래프 생성
-
매니저를 이용해서 필터그래프에서 데이터를 처리하도록 함
-
사용이 끝나면 리소스 반환
1. 인스턴스 생성
앞에서 이야기했듯이 매니저나 필터 모두 COM객체이기 때문에, 우선 COM라이브러리를 초기화 해야 한다. 이 작업은 CoInitialize를 호출함으로써 이루어진다.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr)) {
// 에러처리 코드(간단하게 하기 위해 생략)
}
에러처리는 생략했으며, 필요한 분은 COM책을 들여다 보시면 다 있다. (참고로, MSDN에 따르면, DirectShow는 free-threading model이기 때문에, COINIT_MULTITHREADED옵션을 사용해도 된다고 한다. 이때는 CoINitializeEx를 사용하라.)
이제 필터그래프매니저를 생성해야 한다. COM에서는 객체 생성을 위해 CoCreateInstance를 사용한다.
IGraphBuilder *pGraph;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
CLSID_FilterGraph는 필터그래프매니저의 클래스ID이다.(뭔소린지 모르는 분은 COM책을 보시라. 앞으로 설명할 내용에서 나오는 용어들도 마찬가지). 또한, 이 예제에서는 inprocess DLL로 사용하기 때문에, CLSCTX_INPROC_SERVER로 실행 컨택스트를 정해준다. IID_IGraphBuilder는 우리가 사용할 인터페이스 ID이다. 이 인터페이스는 그래프 생성시 사용할 메소드들이 정의되어 있다. pGraph의 주소를 void**로 넘겨주는것은 CoCreateInstance함수가 그렇게 정의되어 있기 때문이다. CoCreateInstance함수는 pGraph에다 생성된 COM객체의 인터페이스에 대한 포인터를 넘겨주게 된다.
이제 IGraphBuilder인터페이스를 얻었고, 다른 두개의 인터페이스를 얻을 차례이다.
- IMediaControl은 스트리밍을 콘트롤한다. 그래프의 작동을 시작하고, 중지하는 메소드를 포함하고 있다.
- IMediaEvent는 필터그래프매니저에서 발생하는 이벤트를 얻기 위한 메소드를 제공한다.
두 인터페이스 모두 IGraphBuilder에다 QueryInterface를 해서 얻는다.
IMediaControl *pControl;
IMediaEvent *pEvent;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
2. 그래프 생성
이제 필터그래프를 만들수 있게 되었다. 파일을 플레이하기 위한 필터그래프는 다음 메소드를 호출해서 할 수 있다.
hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);
IGraphBuilder::RenderFile 메소드는 지정한 파일을 읽을 수 있는 필터그래프를 생성한다. 첫번째 파라미터는 wide character타입이다. 따라서, L"C:\\Example.avi"을 사용했다. 두번째 파라미터는 항상 NULL이어야 한다.
이 메소드는 파일이 없거나, 파일의 포맷을 알아낼 수 없을 경우 실패한다.
메소드에서 성공하게 되면, 그래프 생성이 완료된 것이고, 파일의 플레이를 시작할 수 있게 된 것이다.
3. 그래프 동작
필터그래프 생성후, IMediaControl::Run을 호출하면 그래프가 동작하게 된다. 즉, 파일을 플레이하게 된다는 것이다. 다음과 같이 호출한다.
hr = pControl->Run();
필터 그래프가 동작하게 되면, 데이터가 필터 그래프를 통해 흘러서 비디오와 오디오가 렌더링되게 된다. 이때 비디오/오디오의 플레이는 독립된 쓰레드로 진행된다.
플레이의 완료까지 기다리려면 IMediaEvent::WaitForCompletion메소드를 호출함으로써 기다릴 수 있다.
long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);
이 메소드는 플레이가 종료되거나, 지정한 시간이 지날 될 때까지 블럭되며, 이벤트를 evCode에 넘겨주게 된다. 어플리케이션은 이벤트코드를 보고 어떤 이유로 WaitForCompletion이 리턴했는지를 알수 있다.
4. 리소스 해제
사용이 끝난 COM객체는 release해주고, COM라이브러리도 반환해야 한다. 다음과 같다.
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
전체 소스는 첨부파일에 있다.
* 링크 및 실행 방법
다음 파일은 항상 인클루두 해야 한다.
Dshow.h
링크시에는 다음을 참조해 필요한 라이브러리는 함께 링크해야 한다.
Strmiids.lib : 모든 DirectShow 어플리케이션에 필요.
Quartz.lib : AMGetErrorText 메서드의 호출에 필요.
Strmbase.lib :DirectShow의 base classes를 사용할 경우만 필요
dshow.h를 사용하기 위해서는 platform SDK를 깔아야 하며, directX SDK도 함께 깔아야 한다.
두 파일은 모두 MS의 다운로드 페이지나 naver자료실에서 다운로드 받을 수 있다.
출처 -http://mrwebi.tistory.com/33
댓글 없음:
댓글 쓰기