Pelacakan Peristiwa di DirectShow
[Fitur yang terkait dengan halaman ini, DirectShow, adalah fitur warisan. Ini telah digantikan oleh MediaPlayer, IMFMediaEngine, dan Pengambilan Audio /Video di Media Foundation. Fitur-fitur tersebut telah dioptimalkan untuk Windows 10 dan Windows 11. Microsoft sangat menyarankan agar kode baru menggunakan MediaPlayer, IMFMediaEngine dan Pengambilan Audio/Video di Media Foundation alih-alih DirectShow, jika memungkinkan. Microsoft menyarankan agar kode yang ada yang menggunakan API warisan ditulis ulang untuk menggunakan API baru jika memungkinkan.]
DirectShow mendukung Pelacakan Peristiwa untuk Windows (ETW), yang dapat digunakan untuk membuat log peristiwa untuk instrumentasi atau penelusuran kesalahan. Untuk informasi selengkapnya tentang ETW, lihat dokumentasi Windows SDK. Untuk menggunakan peristiwa ETW dalam aplikasi DirectShow, Anda harus mengaktifkan pelacakan lalu memproses peristiwa pelacakan. Gunakan langkah-langkah berikut.
Atur Kunci Registri yang Diperlukan
Untuk mengaktifkan pelacakan pada komputer pengguna, pertama-tama atur kunci registri berikut:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectX
GlitchInstrumentation = 0x00000001 (REG_DWORD)
HKEY_LOCAL_MACHINE\SOFTWARE\DEBUG\Quartz.dll
PERFLOG = 0x00000001 (REG_DWORD)
Kunci ini berlaku untuk biner rilis dan debug.
Aktifkan Pelacakan di Aplikasi Anda
Untuk mengaktifkan pelacakan di aplikasi Anda, lakukan langkah-langkah berikut:
- Panggil StartTrace untuk memulai sesi pelacakan baru.
- Panggil EnableTrace untuk mengaktifkan pelacakan. GUID penyedia untuk DirectShow GUID_DSHOW_CTL.
- Sebelum aplikasi keluar, panggil StopTrace untuk menutup sesi pelacakan.
Memproses Peristiwa
Untuk memproses peristiwa, lakukan langkah-langkah berikut:
- Panggil OpenTrace untuk membuka jejak untuk diproses.
- Panggil ProcessTrace untuk memproses peristiwa.
- Di panggilan balik ProcessTrace, gunakan GUID peristiwa untuk menemukan jenis peristiwa. GUID peristiwa menunjukkan struktur yang digunakan untuk data peristiwa. Lihat GUID Peristiwa Pelacakan.
- Panggil CloseTrace untuk menutup handel pelacakan.
Kode Contoh
Kode berikut menunjukkan kelas pembantu yang memungkinkan pelacakan. Kode ini menunjukkan cara menulis peristiwa ke file log, yang dapat diproses setelah sesi selesai. Anda juga dapat memproses peristiwa secara real time. Untuk informasi selengkapnya, lihat dokumentasi ETW di Windows SDK.
#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;
};
Kode berikut menunjukkan cara memproses log peristiwa:
// 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);
}
}
Topik terkait