370 likes | 633 Views
DirectShow Multimedia Programming. 한국외국어대학교 정보통신공학과 조 정 원 mailto:sweop@hanmail.net 지도교수 : 홍진표 교수님. 인터페이스 레퍼런스. 인터페이스 레퍼런스를 사용하기 위한 원칙 IGraphBuilder *pGB 가 선언되어 있으며 , 필터그래프 매니저 객체로 초기화 되어 있다 . HRESUL hr 과 HWND hWnd 도 선언되어 있다 . 모두 PID 인터페이스 이므로 필터그래프 매니저로부터 얻어온다 .
E N D
DirectShow Multimedia Programming 한국외국어대학교 정보통신공학과 조 정 원 mailto:sweop@hanmail.net 지도교수 : 홍진표 교수님
인터페이스 레퍼런스 • 인터페이스 레퍼런스를 사용하기 위한 원칙 • IGraphBuilder *pGB가 선언되어 있으며, 필터그래프 매니저 객체로 초기화 되어 있다. • HRESUL hr과 HWND hWnd도 선언되어 있다. • 모두 PID 인터페이스 이므로 필터그래프 매니저로부터 얻어온다. • 상속한 인터페이스를 함께 표시하되 공용으로 사용되는 Iunknown이나 Idispatch 인터페이스는 생략한다.
StopWhenReady() IMediaSeeking *pMS; JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); if(pMS != NULL) {……………………..} //미디어 검색처리 IMediaControl *pMC; JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)); if(pMC != NULL) hr = pMC->StopWhenReady(); • 매개변수는 없으며 ‘화면 표시’는 정지 상태에서 미디어를 검색할 때 뒷부분에 넣어주면 정지 상태에서 검색에 따라 비디오 창의 화면을 변경시킬 수 있다.
GetState() OAFilterState fs; Hr = pMC->GetState(0, &fs); if(hr == S_OK) { switch(fs) { case State_Stopped: break; //정지 상태 case State_Paused: break; // 일시 정지 상태 case State_Running: break; // 재생 상태 } } else if (hr == VFW_S_STATE_INTERMEDIATE) {} // 상태 전환 진행 중 else if (hr == VFW_S_CANT_CUE) {} // 일시 정지 상태이지만 버퍼링을 수행할 수 없음 • 매개변수 • LONG msTimeout : 밀리초 단위로 타임아웃을 설정 • OAFilterState fs : 필터그래프의 현재 상태를 가져 온다.
CheckCapabilities() DWORD dwCapabilities = AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanSeekForwards | AM_SEEKING_CanSeekBackwards; IMediaSeeking *pMS; JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); if(pMS != NULL) hr = pMS->CheckCapabilities(&dwCapabilities); if (hr == S_OK) { } // 모두 지원된다 else if (hr == S_FALSE) { // 일부만 지원하기 때문에 리턴값으로 확인 if (dwCapabilities & AM_SEEKING_CanSeekAbsolute) { } if (dwCapabilities & AM_SEEKING_CanSeekForwards) { } if (dwCapabilities & AM_SEEKING_CanSeekBackwards) { } } • 매개변수 • DWORD *pCapabilities : AM_SEEKING_SEEKING_CAPABILITIES 열거형 변수 값을 전달하고 결과를 받아온다. • 능력 확인 : 특정 검색 능력을 지원하는지 확인한다.
GetCapabilities() DWORD dwCapabilities; IMediaSeeking *pMS; JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); if(pMS != NULL) hr = pMS->GetCapabilities(); if (dwCapabilities & AM_SEEKING_CanSeekAbsolute) { } if (dwCapabilities & AM_SEEKING_CanSeekForwards) { } if (dwCapabilities & AM_SEEKING_CanSeekBackwards) { } if (dwCapabilities & AM_SEEKING_CanGetCurrentPos) { } if (dwCapabilities & AM_SEEKING_CanGetStopPos) { } if (dwCapabilities & AM_SEEKING_CanGetDuration) { } if (dwCapabilities & AM_SEEKING_CanPlayBackwards) { } if (dwCapabilities & AM_SEEKING_CanDoSegments) { } if (dwCapabilities & AM_SEEKING_Source) { } • 매개변수 • DWORD *pCapabilities : 열거형 변수 값을 얻어온다. • 능력 열거 : 모든 검색 능력을 열거한다.
IsFormatSupported() IMediaSeeking *pMS; JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); if(pMS != NULL) hr = pMS->IsFormatSupported(&TIME_FORMAT_FRAME); if(hr == S_OK) { } // 프레임 시간 형식이 지원됨 if(hr == S_FALSE) { } // 프레임 시간 형식은 지원되지 않음 • 매개 변수 • Const GUID *pFormat : 확인하려는 시간 형식을 직접 전달한다. • 시간 형식 : 특정한 시간 형식이 지원되는지 확인하기 위해 GUID를 직접 전달한다.
GetTimeFormat() GUID guid; IMediaSeeking *pMS; JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); if(pMS != NULL) hr = pMS->GetTimeFormat(); if (guid == TIME_FORMAT_NONE) { } else if (guid == TIME_FORMAT_FRAME) { } else if (guid == TIME_FORMAT_SAMPLE) { } else if (guid == TIME_FORMAT_FIELD) { } else if (guid == TIME_FORMAT_BYTE) { } else if (guid == TIME_FORMAT_MEDIA_TIME) { } • 매개 변수 • GUID *pFormat : 시간 형식의 GUID 값을 얻어온다. • 현재 시간 형식 : 현재 사용하고 있는 시간 형식을 얻어온다.
GetDuration() LONGLONG IIDuration; IMediaSeeking *pMS; JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); if(pMS != NULL) { if(pMS->CheckCapabilities(AM_SEEKING_CanGetDuration) == S_OK) hr = pMS->GetDuration(&Iiduration); } if (hr == S_OK) { } // 전체 재생시간은 IIDuration이다. • 매개변수 • LONGLONG *pDuration : 전체 재생 시간을 얻어온다. • 전체 재생 시간 : 스트림의 전체 재생 시간을 얻어온다.
GetPositions() LONGLONG IICurrent, IIStop; DWORD dwCapabilities = AM_SEEKING_CanGetStopPos | AM_SEEKING_CanGetCurrentPos; IMediaSeeking *pMS; JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); if(pMS != NULL) { if (pMS->CheckCapabilities(&dwCapabilities) == S_OK) hr = pMS->GetPositions(&IICurrent, &IIStop); } if (hr == S_OK) { } // 현재 위치는 IICurrent, 정지 위치는 IIIStop 시간에 해당된다. • 매개변수 • LONGLONG *pCurrent : 현재 위치의 시간 값을 얻어온다. • LONGLONG *pStop : 정지 위치의 시간 값을 얻어온다. • 위치 얻기 : 현재 위치와 재생이 정지될 위치를 얻는다.
SetPositions() (1) • 현재 위치와 재생이 정지될 위치를 설정한다. • 위치는 시간으로 표현되는데 이때 시간 값은 현재 설정되어 있는 시간 형식에 따른다. • 필터그래프와 상태와 관계없이 언제라도 호출하여 위치를 변경할 수 있다. • 매개변수 • LONGLONG *pCurrent : 현재 위치를 지정하고 리턴 값을 받아온다. • DWORD dwCurrentFlags : 현재 위치 지정과 관련되 플래그를 설정한다. • LONGLONG *pStop : 재생이 정지될 위치를 지정하고 리턴 값을 받아온다. • DWORD dwStopFlags :정지 위치 지정과 관련된 플래그를 설정한다.
SetPositions() (2) LONGLONG IICurrent = UNITS, IIStop = UNITS*10; DWORD dwCapabilities = AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanSeekForwards | AM_SEEKING_CanSeekBackwards; IMediaSeeking *pMS; JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); if(pMS != NULL) { if (pMS->CheckCapabilities(&dwCapabilities) == S_OK) hr = pMS->SetPositions(&IICurrent, AM_SEEKING_AbsolutePositioning, &IIStop, AM_SEEKING_AbsolutePositioning); } if (hr == S_OK) { } // 1초부터 10초까지 재생 구간으로 설정 되었다. • 재생 구간 변경 : 현재 위치 및 정지 위치를 변경한다.
SetPositions() (3) LONGLONG IICurrent; // 정지 위치는 변경하지 않고 현재 위치만 이동시킨다. DWORD dwCapabilities = AM_SEEKING_CanSeekAbsolute | AM_SEEKING_CanSeekForwards | AM_SEEKING_CanSeekBackwards | AM_SEEKING_CanGetCurrentPos; IMediaSeeking *pMS; JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); if(pMS != NULL) { if (pMS->CheckCapabilities(&dwCapabilities) == S_OK) hr = pMS->GetCurrentPositions(&IICurrent); IICurrent += UNITS; // 1초 앞으로 이동 hr = pMS->SetPositions(&IICurrent, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); } if (hr == S_OK) { } // 앞쪽으로 1초 이동하였다.(상대 위치 사용) if(pMS != NULL) { if (pMS->CheckCapabilities(&dwCapabilities) == S_OK) hr = pMS->GetCurrentPositions(&IICurrent); IICurrent -= UNITS; // 1초 뒤로 이동 hr = pMS->SetPositions(&IICurrent, AM_SEEKING_RelativePositioning, NULL, AM_SEEKING_NoPositioning); } if (hr == S_OK) { } // 뒤쪽으로 1초 이동하였다.(상대 위치 사용)
WindowStyle IVideoWindow *pVW; JIF(pGB->QueryInterface(IID_IVedeoWindow, (void **)&pVW)); if(pVW != NULL) { long IStyleGet; hr = pVW->get_WindowStyle(&IStyleGet); long IStylePut = WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; hr = pVW->put_WindowStyle(IStylePut); } • 매개변수 • long WindowStyle : 비디오 창의 스타일을 입력하거나 얻어온다. • 스타일 : 현재 비디오 창의 스타일을 다룬다.
WindowStyleEx IVideoWindow *pVW; JIF(pGB->QueryInterface(IID_IVedeoWindow, (void **)&pVW)); if(pVW != NULL) { long IStyleExGet; hr = pVW->get_WindowStyleEx(&IStyleExGet); long IStyleExPut = WS_EX_TOPMOST; hr = pVW->put_WindowStyleEx(IStyleExPut); } • 매개변수 • long WindowStyleEx : 비디오 창의 확장 스타일을 입력하거나 얻어온다. • 확장 스타일 : 현재 비디오 창의 확장 스타일을 다룬다.
Owner IVideoWindow *pVW; JIF(pGB->QueryInterface(IID_IVedeoWindow, (void **)&pVW)); if(pVW != NULL) { OAHWND hwndGet; hr = pVW->get_Owner(&hwndGet); OAHWND hwndPut = m_hWnd; hr = pVW->put_Owner(&hwndPut); } • 매개변수 • OAHWND Drain : 비디오 창의 부모창을 입력하거나 얻어온다. • 부모 창 : 현재 비디오 창의 부모 창을 다룬다.
MessageDrain IVideoWindow *pVW; JIF(pGB->QueryInterface(IID_IVedeoWindow, (void **)&pVW)); if(pVW != NULL) { OAHWND hwndGet; hr = pVW->get_MessageDrain(&bstrGet); OAHWND hwndPut = m_hWnd; hr = pVW->put_MessageDrain(bstrPut); } • 매개변수 • OAHWND Drain : 비디오 창의 메시지 전달 창을 입력하거나 얻어온다. • 부모 창 : 현재 비디오 창의 메시지 전달 창을 다룬다.
FullScreenMode IVideoWindow *pVW; JIF(pGB->QueryInterface(IID_IVedeoWindow, (void **)&pVW)); if(pVW != NULL) { long IFullScreenGet; hr = pVW->get_FullScreenMode(&IFullScreenGet); long IFullScreenPut = OATRUE; hr = pVW->put_FullScreenMode(IFullScreenPut); // 전체 화면 모드 설정 long IFullScreenPut = OAFALSE; hr = pVW->put_FullScreenMode(IFullScreenPut); // 전체 화면 모드 해제 } • 매개변수 • long FullScreenMode: 비디오 창의 전체화면 모드를 입력하거나 얻어온다. • 전체화면 모드 : 현재 비디오 창의 전체 화면 모드를 다룬다.
SetWindowForeground() IVideoWindow *pVW; JIF(pGB->QueryInterface(IID_IVedeoWindow, (void **)&pVW)); if(pVW != NULL) { hr = pVW->SetWindowForeground(OATRUE); // 초점 설정 hr = pVW->SetWindowForeground(OAFALSE); // 초점 해제 } • 매개변수 • BSTR strCaption: 비디오 창이 초점(focus)을 받을 것인지 입력한다. • 화면 앞 이동 : 비디오 창을 화면 앞으로 끌어온다.
Get/SetWindowPosition() IVideoWindow *pVW; JIF(pGB->QueryInterface(IID_IVedeoWindow, (void **)&pVW)); if(pVW != NULL) { long ILeft, ITop, IWidth, IHeight; hr = pVW->GetWindowPosition(&ILeft, &ITop, &IWidth, &IHeight); hr = pVW->SetWindowPosition(10, 5, 320, 240); } • 매개변수 • long Left : 비디오 창의 X좌표 Top : 비디오 창의 Y좌표 • long Width : 비디오 창의 폭 Height : 비디오 창의 높이 • 위치와 크기 지정 : 비디오 창의 위치와 크기를 결정한다.
GetEventHandle() UINT MyEventProc(LPVOID pParam) { MediaEventEx *pME; JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)); if(pME != NULL) { OAEVENT hEvent; hr = pME->GetEventHandle((HANDLE)&hEvent, INFINITE); HandleGraphEvent(); // 이벤트 처리 함수 } } • 매개변수 • OAEVENT *hEvent : 이벤트 핸들을 얻어온다. • 수동 이벤트 처리 : 직접 이벤트가 발생되었는지 확인한다. • 이러한 수옫 처리에서는 대개 다른 처리를 함께 수행하기 위해 별도의 스레드가 필요하다.
GetEvent () long Ievent, lParam1, lParam2; Long ITimeOut = 0; MediaEventEx *pME; JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)); while(SUCCEED(pME->GetEvent(&Ievent, &lParam1, &lParam2, ITimeOut))) { switch(IEvent) { } hr = pME->FreeEventParams(IEvent, lParam1, lParam2); } • 매개변수 • long *IEventCode : 발생한 이벤트 코드를 얻어온다. • long *IParam1,2 : 이벤트 코드의 첫, 두 번째 매개변수 • long msTimeout : 타임아웃 간격를 설정한다. INFINITE이면 무한히 기다린다. • 이벤트 꺼내오기 : 이벤트 큐에서 이벤트를 하나 꺼내온다.
WaitForCompletion() MediaEventEx *pME; JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)); if(pME != NULL) { long IEvent; hr = pME->WaitForCompletion(INFINITE ,IEvent); switch(IEvent) { case EC_COMPLETE : // 재생 완료 case EC_ERRORABORT : // 오류 발생 중지 case EC_USERABORT : // 사용자 중지 } } • 매개변수 • long msTimeout : 타임아웃 간격을 설정한다. • long *pEventCode : 발생한 이벤트 코드를 얻어온다. • 이벤트 기다림 : 재생 등이 중지될 때까지 기다린다.
SetNotifyWindow() #define WM_GRAPHNOTIFY WM_APP+1 MediaEventEx *pME; JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)); if(pME != NULL) { hr = pME->SetNotifyWindow(m_hWnd, WM_GRAPHNOTIFY, 0); /* 자동 이벤트 처리 : 이벤트가 발생하면 그 사실을 메시지 창에 알려준다. */ hr = pME->SetNotifyWindow(NULL, WM_GRAPHNOTIFY, 0); /* 처리 해제 : 창이 종료된 후에도 메시지를 전달하려고 하면 오류가 발생하기 때문에 창을 종료할 때 꼭 처리해야 한다. */ } • 매개변수 • OAHWND hwnd : 이벤트 발생 메시지를 처리할 창 핸들을 입력한다. NULL이면 메시지를 전달하지 않는다. • long Imsg : 이벤트 발생 메시지의 두 번째 매개변수로 전달될 값을 입력한다. • lONG IInstanceData : 이벤트가 발생하면 그 사실을 메시지 창에 알려준다.
AvgTimePerFrame[R] IBasicVideo *pBV; JIF(pGB->QueryInterface(IID_IBasicVideo, (void **)&pBV)); if(pBV != NULL) { REFTIME timeAvgTimePerFrame; hr = pBV->get_AvgTimePerFrame(&timeAvgTimePerFrame); } • 매개변수 • REFTIME *pAvgTimePerFrame : 프레임당 평균 시간을 얻는다. • 프레임 평균 시간 : 현재 비디오 스트림의 프레임당 평균 시간을 얻는다.
BitRate [R] IBasicVideo *pBV; JIF(pGB->QueryInterface(IID_IBasicVideo, (void **)&pBV)); if(pBV != NULL) { long IBitRate; hr = pBV->get_BitRate(&IBitRate); } • 매개변수 • long *pBitRate : 비트율을 얻어온다. • 비트율 : 현재 비디오 스트림의 비트율을 얻는다.
GetVideoSize() IBasicVideo *pBV; JIF(pGB->QueryInterface(IID_IBasicVideo, (void **)&pBV)); if(pBV != NULL) { long Iwidth, IHeight; hr = pBV->GetVideoSize(&Iwidth, &IHeight); } • 매개변수 • long *pWidth, *pHeight : 본래 비디오의 폭, 높이 • 본래 비디오 크기 : 본래 비디오 크기를 얻어온다.
Volume IBasicAudio *pBA; JIF(pGB->QueryInterface(IID_IBasicAudio, (void **)&pBA)); if(pBA != NULL) { long IVolume; hr = pBV->get_Volume(&Ivolume); hr = pBV->put_Volume(-10000); // 소리 없앰(-100dB) hr = pBV->put_Volume(0); // 소리의 최대 크기(0dB) } • 매개변수 • long Ivolume : 볼륨 크기를 다룬다. -10,000 부터 0사이 값을 갖는다. • 볼륨 크기 : 현재 오디오의 볼륨 크기를 다룬다.
Balance IBasicAudio *pBA; JIF(pGB->QueryInterface(IID_IBasicAudio, (void **)&pBA)); if(pBA != NULL) { long IBalance; hr = pBV->get_Balance(&IBalance); // 왼쪽에서만 소리남(왼쪽 0dB ,오른쪽 -100dB) hr = pBV->put_Balance(-10000); // 가운데에서 소리남(왼쪽 -50dB ,오른쪽 -50dB) hr = pBV->put_Balance(0); // 오른쪽에서만 소리남(왼쪽 -100dB ,오른쪽 0dB) hr = pBV->put_Balance(10000); } • 매개변수 • long *pBalance : 좌우 균형을 다룬다. -10,000부터 10,000사이 값을 갖는다. • 좌우 균형 : 현재 오디오의 좌우 균형을 다룬다.
Reference • DirecthShow 멀티미디어 프로그래밍, 한빛미디어 • MSDN