다음을 통해 공유


이벤트가 발생하는 경우 학습

[DirectShow 이 페이지와 연결된 기능은 레거시 기능입니다. MediaPlayer, IMFMediaEngine, Media Foundation 오디오/비디오 캡처대체되었습니다. 이러한 기능은 Windows 10 및 Windows 11에 최적화되었습니다. Microsoft는 가능하면 새로운 코드에서 MediaPlayer, IMFMediaEngineAudio/Video Capture를 DirectShow대신 Media Foundation 사용하는 것이 좋습니다. 가능한 경우 레거시 API를 사용하는 기존 코드를 다시 작성하여 새 API를 사용하도록 제안합니다.]

DirectShow 이벤트를 처리하려면 애플리케이션에서 큐에서 이벤트가 대기하는 시기를 확인하는 방법이 필요합니다. 필터 그래프 관리자는 다음 두 가지 방법을 제공합니다.

  • 창 알림: 필터 그래프 관리자는 새 이벤트가 있을 때마다 애플리케이션 창에 사용자 정의 Windows 메시지를 보냅니다.
  • 이벤트 신호: Filter Graph Manager는 큐에 DirectShow 이벤트가 있는 경우 Windows 이벤트를 알리고 큐가 비어 있으면 이벤트를 다시 설정합니다.

애플리케이션은 두 가지 기술 중 하나를 사용할 수 있습니다. 창 알림은 일반적으로 더 간단합니다.

창 알림

창 알림을 설정하려면 IMediaEventEx::SetNotifyWindow 메서드를 호출하고 프라이빗 메시지를 지정합니다. 애플리케이션은 WM_APP 0xBFFF 범위의 메시지 번호를 개인 메시지로 사용할 수 있습니다. Filter Graph Manager가 큐에 새 이벤트 알림을 배치할 때마다 지정된 창에 이 메시지를 게시합니다. 애플리케이션은 창의 메시지 루프 내에서 메시지에 응답합니다.

다음 코드 예제에서는 알림 창을 설정하는 방법을 보여줍니다.

#define WM_GRAPHNOTIFY WM_APP + 1   // Private message.
pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);

메시지는 일반 Windows 메시지이며 DirectShow 이벤트 알림 큐와 별도로 게시됩니다. 이 방법의 장점은 대부분의 애플리케이션이 이미 메시지 루프를 구현한다는 것입니다. 따라서 추가 작업 없이 DirectShow 이벤트 처리를 통합할 수 있습니다.

다음 코드 예제에서는 알림 메시지에 응답하는 방법에 대한 개요를 보여줍니다. 전체 예제를 보려면 이벤트에 응답하기을 참조하세요.

LRESULT CALLBACK WindowProc( HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
    switch (msg)
    {
        case WM_GRAPHNOTIFY:
            HandleEvent();  // Application-defined function.
            break;
        // Handle other Windows messages here too.
    }
    return (DefWindowProc(hwnd, msg, wParam, lParam));
}

이벤트 알림과 메시지 루프는 모두 비동기이므로 애플리케이션이 메시지에 응답할 때까지 큐에 둘 이상의 이벤트가 포함될 수 있습니다. 또한 이벤트가 유효하지 않은 경우 큐에서 이벤트를 지울 수 있습니다. 따라서 이벤트 처리 코드에서 오류 코드를 반환할 때까지 IAMMediaEvent::GetEvent 호출하여 큐가 비어 있음을 나타냅니다.

IMediaEventEx 포인터를 해제하기 전에 NULL 포인터로 SetNotifyWindow 호출하여 이벤트 알림을 취소합니다. 이벤트 처리 코드에서 GetEvent호출하기 전에 IMediaEventEx 포인터가 유효한지 확인합니다. 이러한 단계는 애플리케이션이 IMediaEventEx 포인터를 해제한 후 이벤트 알림을 받는 가능한 오류를 방지합니다.

이벤트 신호

Filter Graph Manager는 이벤트 큐의 상태를 반영하는 수동 재설정 이벤트를 유지합니다. 큐에 보류 중인 이벤트 알림이 포함된 경우 Filter Graph Manager는 수동 재설정 이벤트에 신호를 전송합니다. 큐가 비어 있으면 IMediaEvent::GetEvent 메서드를 호출하면 이벤트가 다시 설정됩니다. 애플리케이션은 이 이벤트를 사용하여 큐의 상태를 확인할 수 있습니다.

메모

여기서 용어는 혼동될 수 있습니다. 수동 재설정 이벤트는 Windows CreateEvent 함수에서 만든 이벤트의 유형입니다. DirectShow에서 정의한 이벤트와는 아무 상관이 없습니다.

 

IMediaEvent::GetEventHandle 메서드를 호출하여 수동 재설정 이벤트에 대한 핸들을 가져옵니다. WaitForMultipleObjects같은 함수를 호출하여 이벤트가 신호를 받을 때까지 기다립니다. 이벤트가 신호를 받으면 IMediaEvent::GetEvent 호출하여 DirectShow 이벤트를 가져옵니다.

다음 코드 예제에서는 이 방법을 보여 줍니다. 이벤트 핸들을 가져오고 이벤트가 신호를 받을 때까지 100밀리초 간격으로 기다립니다. 이벤트가 신호를 받으면 GetEvent 호출하고 이벤트 코드 및 이벤트 매개 변수를 콘솔 창에 출력합니다. 루프는 EC_COMPLETE 이벤트가 발생하면 종료되며 재생이 완료되었음을 나타냅니다.

HANDLE  hEvent; 
long    evCode, param1, param2;
BOOLEAN bDone = FALSE;
HRESULT hr = S_OK;
hr = pEvent->GetEventHandle((OAEVENT*)&hEvent);
if (FAILED(hr))
{
    /* Insert failure-handling code here. */
}

while(!bDone) 
{
    if (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 100))
    { 
        while (S_OK == pEvent->GetEvent(&evCode, &param1, &param2, 0)) 
        {
            printf("Event code: %#04x\n Params: %d, %d\n", evCode, param1, param2);
            pEvent->FreeEventParams(evCode, param1, param2);
            bDone = (EC_COMPLETE == evCode);
        }
    }
} 

필터 그래프는 적절한 경우 이벤트를 자동으로 설정하거나 다시 설정하므로 애플리케이션에서 설정하면 안 됩니다. 또한 필터 그래프를 해제하면 필터 그래프가 이벤트 핸들을 닫으므로 해당 지점 이후에는 이벤트 핸들을 사용하지 마세요.