DirectShow의 이벤트 추적
[이 페이지와 연결된 기능인 DirectShow는 레거시 기능입니다. MediaPlayer, IMFMediaEngine 및 Media Foundation의 오디오/비디오 캡처로 대체되었습니다. 이러한 기능은 Windows 10 및 Windows 11 최적화되었습니다. 가능한 경우 새 코드에서 DirectShow 대신 MediaPlayer, IMFMediaEngine 및 오디오/비디오 캡처를 사용하는 것이 좋습니다. 가능한 경우 레거시 API를 사용하는 기존 코드를 다시 작성하여 새 API를 사용하도록 제안합니다.]
DirectShow는 계측 또는 디버깅을 위한 이벤트 로그를 만드는 데 사용할 수 있는 ETW(Windows용 이벤트 추적)를 지원합니다. ETW에 대한 자세한 내용은 Windows SDK 설명서를 참조하세요. DirectShow 애플리케이션에서 ETW 이벤트를 사용하려면 추적을 사용하도록 설정한 다음 추적 이벤트를 처리해야 합니다. 다음 단계를 사용합니다.
필요한 레지스트리 키 설정
사용자 컴퓨터에서 추적을 사용하도록 설정하려면 먼저 다음 레지스트리 키를 설정합니다.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectX
GlitchInstrumentation = 0x00000001 (REG_DWORD)
HKEY_LOCAL_MACHINE\SOFTWARE\DEBUG\Quartz.dll
PERFLOG = 0x00000001 (REG_DWORD)
이러한 키는 릴리스 및 디버그 이진 파일 모두에 적용됩니다.
애플리케이션에서 추적 사용
애플리케이션에서 추적을 사용하도록 설정하려면 다음 단계를 수행합니다.
- StartTrace를 호출하여 새 추적 세션을 시작합니다.
- EnableTrace를 호출하여 추적을 사용하도록 설정합니다. DirectShow에 대한 공급자 GUID가 GUID_DSHOW_CTL.
- 애플리케이션이 종료되기 전에 StopTrace 를 호출하여 추적 세션을 닫습니다.
이벤트 처리
이벤트를 처리하려면 다음 단계를 수행합니다.
- OpenTrace를 호출하여 처리할 추적을 엽니다.
- ProcessTrace를 호출하여 이벤트를 처리합니다.
- ProcessTrace 콜백에서 이벤트 GUID를 사용하여 이벤트 유형을 찾습니다. 이벤트 GUID는 이벤트 데이터에 사용되는 구조를 나타냅니다. 추적 이벤트 GUID를 참조하세요.
- CloseTrace를 호출하여 추적 핸들을 닫습니다.
예제 코드
다음 코드에서는 추적을 사용하도록 설정하는 도우미 클래스를 보여 줍니다. 이 코드는 세션이 완료된 후 처리할 수 있는 로그 파일에 이벤트를 작성하는 방법을 보여 줍니다. 이벤트를 실시간으로 처리할 수도 있습니다. 자세한 내용은 Windows SDK의 ETW 설명서를 참조하세요.
#include <wmistr.h>
#include <evntrace.h>
#include <perfstruct.h>
// Event classes. These are defined in dxmperf.h.
#ifndef DXMPERF_VIDEOREND
#define DXMPERF_VIDEOREND 0x00000001
#endif
#ifndef AUDIOBREAK_BIT
#define AUDIOBREAK_BIT 0x00000010
#endif
// This structure extends the EVENT_TRACE_PROPERTIES by adding fields
// for the name of the WMI session name and the log file.
struct PERFMON_LOGGERINFO
{
EVENT_TRACE_PROPERTIES TraceProperties;
WCHAR wcSessionName[ MAX_PATH ]; // Session name.
WCHAR wcLogFileName[ MAX_PATH ]; // Log file.
};
// Helper class for DirectShow event tracing.
class CTrace
{
public:
CTrace() : m_SessionLogger((TRACEHANDLE) INVALID_HANDLE_VALUE)
{
ZeroMemory(&m_LogInfo, sizeof(&m_LogInfo));
}
// Start: Starts a trace session.
HRESULT Start(WCHAR *wszLogFile)
{
const WCHAR* wszSessionName = L"PerfMon_DirectShow";
HRESULT hr = S_OK;
ULONG result;
ZeroMemory(&m_LogInfo, sizeof(m_LogInfo));
EVENT_TRACE_PROPERTIES& prop = m_LogInfo.TraceProperties;
prop.Wnode.BufferSize = sizeof(m_LogInfo); // Size of the structure.
prop.Wnode.Flags = WNODE_FLAG_TRACED_GUID; // Must be this value.
// Use the QPC (high resolution timer).
prop.Wnode.ClientContext = 1;
prop.Wnode.Guid = GUID_DSHOW_CTL; // Event provider GUID.
prop.LogFileMode =
EVENT_TRACE_FILE_MODE_CIRCULAR | EVENT_TRACE_USE_PAGED_MEMORY;
prop.EnableFlags =
EVENT_TRACE_FLAG_PROCESS; // Process events.
// Set the offset from the start of the structure to the log file name.
prop.LogFileNameOffset =
sizeof(m_LogInfo.TraceProperties) + sizeof(m_LogInfo.wcSessionName);
// Set the offset from the start of the structure to the session name.
prop.LoggerNameOffset = sizeof(m_LogInfo.TraceProperties);
// Copy the names into the structure.
StringCchCopy(m_LogInfo.wcSessionName, MAX_PATH, wszSessionName);
StringCchCopy(m_LogInfo.wcLogFileName, MAX_PATH, wszLogFile);
// Start the trace.
result = StartTrace(
&m_SessionLogger,
m_LogInfo.wcSessionName,
&m_LogInfo.TraceProperties
);
if (result == ERROR_SUCCESS)
{
result = EnableTrace(
TRUE, // Enable.
AUDIOBREAK_BIT | DXMPERF_VIDEOREND, // Event classes.
TRACE_LEVEL_VERBOSE, // Trace level.
&GUID_DSHOW_CTL, // Event provider.
m_SessionLogger // Session handle.
);
}
if (result != ERROR_SUCCESS)
{
hr = __HRESULT_FROM_WIN32(result);
}
return hr;
}
HRESULT Stop()
{
HRESULT hr = S_OK;
// Stop the trace.
if (m_SessionLogger != (TRACEHANDLE)INVALID_HANDLE_VALUE)
{
LONG result = 0;
result = EnableTrace(FALSE, 0, 0, &GUID_DSHOW_CTL, m_SessionLogger);
if (result == ERROR_SUCCESS)
{
result = StopTrace(
m_SessionLogger,
m_LogInfo.wcSessionName,
&m_LogInfo.TraceProperties);
}
m_SessionLogger = (TRACEHANDLE)INVALID_HANDLE_VALUE;
if (result != ERROR_SUCCESS)
{
hr = __HRESULT_FROM_WIN32(result);
}
}
return hr;
}
protected:
TRACEHANDLE m_SessionLogger;
PERFMON_LOGGERINFO m_LogInfo;
};
다음 코드는 이벤트 로그를 처리하는 방법을 보여줍니다.
// Callback for event processing.
VOID WINAPI EventCallback(PEVENT_TRACE pEvent)
{
PERFINFO_DSHOW_STREAMTRACE *pStreamTrace = NULL;
PERFINFO_DSHOW_AVREND *pVideoRender = NULL;
PERFINFO_DSHOW_AUDIOBREAK *pAudioBreak = NULL;
if (pEvent->Header.Guid == GUID_STREAMTRACE)
{
pStreamTrace = (PPERFINFO_DSHOW_STREAMTRACE)pEvent->MofData;
switch (pStreamTrace->id)
{
// TODO: Handle the event.
}
}
else if(pEvent->Header.Guid == GUID_VIDEOREND)
{
pVideoRender = (PPERFINFO_DSHOW_AVREND)pEvent->MofData;
// TODO: Handle the event.
}
else if(pEvent->Header.Guid == GUID_AUDIOBREAK)
{
pAudioBreak = (PPERFINFO_DSHOW_AUDIOBREAK)pEvent->MofData;
// TODO: Handle the event.
}
}
void ProcessTraceEvents(WCHAR *wszLogFile)
{
ULONG result = 0;
EVENT_TRACE_LOGFILE logfile;
ZeroMemory(&logfile, sizeof(logfile));
logfile.LogFileName = wszLogFile;
logfile.EventCallback = EventCallback;
TRACEHANDLE handle = OpenTrace(&logfile);
if (handle != (TRACEHANDLE)INVALID_HANDLE_VALUE)
{
result = ProcessTrace(&handle, 1, NULL, NULL);
CloseTrace(handle);
}
}
관련 항목