DirectShow DirectShow 의 사용법 DirectShow 의 기본 태스크 이벤트에의 응답   [목차열람] [주소복사] [슬롯비우기]
이벤트에의 응답
 
Microsoft DirectX 9.0

이벤트에의 응답

여기에서는, 필터 그래프로 발생하는 이벤트에 응답하는 방법을 해설한다.

이벤트 통지의 동작

DirectShow 애플리케이션의 실행중에 필터 그래프로 이벤트가 발생하는 일이 있다. 예를 들어, 필터에는 스트리밍 에러가 발생하는 일이 있다. 필터는 이벤트를 송신해 필터 그래프 매니저에 에러를 알린다. 이벤트는 이벤트 코드와 2 개의 이벤트 파라미터로부터 구성된다. 이벤트 코드는 이벤트의 타입을 나타낸다. 이벤트 파라미터는 추가 정보를 나타낸다. 파라미터의 의미는, 이벤트 코드에 따라서 다르다. 모든 이벤트 코드의 일람에 대해서는, 「이벤트 통지 코드」를 참조할것.

일부의 이벤트에 대해서는, 필터 그래프 매니저가 애플리케이션에 통지하지 않고 암묵중에 처리한다. 다른 이벤트는 애플리케이션의 큐에 들어간다. 처리가 필요한 이벤트는 애플리케이션에 따라서 다르다. 여기에서는, 일반적인 3 개의 이벤트를 채택한다.

이벤트 통지의 사용법

새로운 이벤트가 발생할 때 마다, 필터 그래프 매니저가 특정의 윈도우에 Windows 메시지를 송신하도록, 애플리케이션으로 지정할 수 있다. 따라서, 애플리케이션은 윈도우의 메시지 루프내에서 응답할 수 있다. 우선, 애플리케이션 윈도우에 송신되는 메시지를 정의한다. 애플리케이션에서는, WM_APP 로부터 0xBFFF 까지의 범위의 메시지 번호를 Private 메시지로서 사용할 수 있다.

#define WM_GRAPHNOTIFY  WM_APP + 1

다음에, 필터 그래프 매니저에 IMediaEventEx 인터페이스를 문의해IMediaEventEx::SetNotifyWindow 메서드를 호출한다.

IMediaEventEx *g_pEvent = NULL;
g_pGraph->QueryInterface(IID_IMediaEventEx, (void **) &g_pEvent);
g_pEvent->SetNotifyWindow((OAHWND) g_hwnd, WM_GRAPHNOTIFY, 0);

이 메서드는, 지정된 윈도우 (g_hwnd)를 메시지의 수신자로서 지정한다. 필터 그래프의 생성 후, 그래프를 실행하기 전에 메서드를 호출한다.

WM_GRAPHNOTIFY 는 보통의 Windows 메시지이다. 필터 그래프 매니저는, 새로운 이벤트를 이벤트 큐에 넣으면 지정된 애플리케이션 윈도우에 WM_GRAPHNOTIFY 메시지를 송신한다. 메시지의 lParam 파라미터는 SetNotifyWindow 의 3 번째의 파라미터에 동일하다. 이 파라미터를 사용하면, 메시지와 함께 인스턴스 데이터를 송신할 수 있다. 윈도우 메시지의 wParam 파라미터는 항상 0 이다.

애플리케이션의 WindowProc 함수에, WM_GRAPHNOTIFY 메시지용의 case 스테이트먼트를 추가한다.

case WM_GRAPHNOTIFY:
    HandleGraphEvent();
    break;

이벤트 핸들러 함수 중(안)에서 IMediaEvent::GetEvent 메서드를 호출해, 큐로부터 이벤트를 꺼낸다.

void HandleGraphEvent()
{
    // IMediaEventEx 포인터가 없는 경우는, 무시한다.
    if (g_pEvent == NULL)
    {
        return;
    }
    // 모든 이벤트를 얻어온다.
    long evCode, param1, param2;
    HRESULT hr;
    while (SUCCEEDED(g_pEvent->GetEvent(&evCode, &param1, &param2, 0)))
    {
        g_pEvent->FreeEventParams(evCode, param1, param2);
        switch (evCode)
        {
        case EC_COMPLETE:  // 실패에 끝난다.
        case EC_USERABORT: // 실패에 끝난다.
        case EC_ERRORABORT:
            CleanUp();
            PostQuitMessage(0);
            return;
        }
    } 
}

GetEvent 메서드는, 이벤트 코드와 2 개의 이벤트 파라미터를 꺼낸다. GetEvent 의 4 번째의 파라미터는 이벤트 발생까지의 대기 시간을 밀리 세컨드 단위로 지정한다. 애플리케이션에서는 WM_GRAPHNOTIFY 메시지에 응답해 이 메서드를 호출하기 (위해)때문에, 이벤트는 이미 큐에 들어가 있다. 따라서, 타임 아웃값은 0 으로 설정한다.

이벤트 통지와 메시지 루프는 어느쪽이나 비동기에 행해지기 (위해)때문에, 애플리케이션이 메시지에 응답 하면 와까지, 큐에는 복수의 이벤트가 들어가 있을 가능성이 있다. 또, 필터 그래프 매니저는, 이벤트가 무효가 되었을 경우에 큐로부터 이벤트를 삭제할 수 있다. 그 때문에, 큐가 하늘인 것을 나타내는 에러 코드가 돌려주어질 때까지 GetEvent 를 호출하는 것.

이 예로, 애플리케이션은 EC_COMPLETE, EC_USERABORT, 및 EC_ERRORABORT 에 응답해 애플리케이션 정의의 CleanUp 함수를 호출한다. 이 함수에 의해 애플리케이션은 정상적으로 종료한다. 예에서는, 2 개의 이벤트 파라미터를 무시하고 있다. 이벤트를 꺼내면 이벤트 파라미터에 관련하는 하늘의 리소스에 IMediaEvent::FreeEventParams 를 호출한다.

EC_COMPLETE 이벤트가 발생해도 필터 그래프는 정지하지 않는 점에 주의 해야 한다. 애플리케이션은 그래프를 정지하는지 포즈 할 수가 있다. 그래프를 정지 하면, 필터는 보관 유지하고 있는 리소스를 릴리즈 한다. 그래프를 포즈 하면, 필터는 리소스를 계속 보관 유지한다. 덧붙여 비디오 렌더러는 포즈 했을 때, 최신의 프레임의 정지화면상을 표시한다.

IMediaEventEx 포인터를 릴리즈 하기 전에, NULL 포인터를 사용해 SetNotifyWindow 를 호출해, 이벤트 통지를 취소한다.

// 그래프를 릴리즈 하기 전에 이벤트 통지를 무효로 한다.
g_pEvent->SetNotifyWindow(NULL, 0, 0);
g_pEvent->Release();
g_pEvent = NULL;

WM_GRAPHNOTIFY 메시지 핸들러로,GetEvent 를 호출하기 전에 IMediaEventEx 포인터를 체크한다.

if (g_pEvent == NULL) return;

이 체크에 의해, 애플리케이션이 포인터 릴리즈 후에 이벤트 통지를 받는 경우에 발생하는 에러를 회피할 수 있다.

참조

↑TOP