Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

331 lines
8.1 KiB

  1. /*++
  2. Copyright 2000 Microsoft Corporation
  3. Module Name:
  4. dstrace.cpp
  5. Abstract:
  6. DShow performance monitor.
  7. Author:
  8. Arthur Zwiegincew (arthurz) 22-Sep-00
  9. Revision History:
  10. 22-Sep-00 - Created
  11. --*/
  12. #include <windows.h>
  13. #include <stdio.h>
  14. #include <wmistr.h>
  15. #include <evntrace.h>
  16. #include <initguid.h>
  17. #include <math.h>
  18. #define WMIPERF
  19. #include <perfstruct.h>
  20. GUID KmixerGuid =
  21. { 0xe5a43a19, 0x6de0, 0x44f8, 0xb0, 0xd7, 0x77, 0x2d, 0xbd, 0xe4, 0x6c, 0xc0 };
  22. GUID PortclsGuid =
  23. { 0x9d447297, 0xc576, 0x4015, 0x87, 0xb5, 0xa5, 0xa6, 0x98, 0xfd, 0x4d, 0xd1 };
  24. GUID UsbaudioGuid =
  25. { 0xd6464a84, 0xa358, 0x4013, 0xa1, 0xe8, 0x6e, 0x2f, 0xb4, 0x8a, 0xab, 0x93 };
  26. //
  27. // Video glitch threshold. When abs(PresentationTime - RenderTime) > this value,
  28. // we consider the event a glitch.
  29. //
  30. #define GLITCH_THRESHOLD 30 /* ms */ * 10000 /* 1 ms / 100 ns */
  31. //
  32. // Define our private ConsoleCtrlHandler() control type to indicate failed initialization.
  33. // We'll call with this constant directly. Used to centralize cleanup code.
  34. //
  35. #define CTRL_INITIALIZATION_ERROR 0xDeadBeef
  36. //
  37. // DSHOW WMI provider GUID.
  38. //
  39. GUID ControlGuid = GUID_DSHOW_CTL;
  40. //
  41. // Global state.
  42. //
  43. HANDLE MonitorThread;
  44. TRACEHANDLE LoggerHandle;
  45. TRACEHANDLE ConsumerHandle;
  46. EVENT_TRACE_LOGFILE Logfile;
  47. ////////////////////////////////////////////////////////////////////////////
  48. VOID
  49. TerminateLogging (
  50. VOID
  51. )
  52. {
  53. ULONG status;
  54. int i;
  55. struct EVENT_TRACE_INFO {
  56. EVENT_TRACE_PROPERTIES TraceProperties;
  57. char Logger[256];
  58. char LogFileName[256];
  59. } Info;
  60. ZeroMemory (&Info, sizeof (Info));
  61. Info.TraceProperties.LoggerNameOffset = sizeof (EVENT_TRACE_PROPERTIES);
  62. Info.TraceProperties.LogFileNameOffset = sizeof (EVENT_TRACE_PROPERTIES) + 256;
  63. Info.TraceProperties.Wnode.BufferSize = sizeof (Info);
  64. status = ControlTrace (0, "DSTrace", &Info.TraceProperties, EVENT_TRACE_CONTROL_QUERY);
  65. if (status != ERROR_SUCCESS) {
  66. printf ("QueryTrace failed=>%d\n", status);
  67. }
  68. status = ControlTraceA (LoggerHandle, NULL, &Info.TraceProperties, EVENT_TRACE_CONTROL_STOP);
  69. if (status != ERROR_SUCCESS) {
  70. printf ("StopTrace failed=>%d\n", status);
  71. }
  72. if (MonitorThread != NULL) {
  73. EnableTrace (FALSE, 0, 0, &ControlGuid, LoggerHandle);
  74. TerminateThread (MonitorThread, 0);
  75. }
  76. for (i = 0; i < 100; i += 1) {
  77. Sleep (50);
  78. status = CloseTrace (ConsumerHandle);
  79. if (status != ERROR_SUCCESS) {
  80. printf ("CloseTrace failed=>%d\n", status);
  81. }
  82. else {
  83. break;
  84. }
  85. }
  86. status = EnableTrace (FALSE, 0, 0, &ControlGuid, LoggerHandle);
  87. if (status != ERROR_SUCCESS) {
  88. printf ("EnableTrace failed=>%d\n", status);
  89. }
  90. }
  91. ////////////////////////////////////////////////////////////////////////////
  92. BOOL
  93. WINAPI
  94. ConsoleCtrlHandler (
  95. DWORD CtrlType
  96. )
  97. {
  98. static BOOL Exiting = FALSE;
  99. if (Exiting) {
  100. return TRUE;
  101. }
  102. Exiting = TRUE;
  103. if (CtrlType == CTRL_INITIALIZATION_ERROR) {
  104. printf ("Failed to initialize.");
  105. }
  106. else {
  107. printf ("Exiting.\n");
  108. }
  109. TerminateLogging();
  110. return TRUE;
  111. }
  112. ////////////////////////////////////////////////////////////////////////////
  113. VOID
  114. WINAPI
  115. EventCallback (
  116. IN PEVENT_TRACE Event
  117. )
  118. {
  119. PPERFINFO_DSHOW_AVREND PerfInfoAvRend;
  120. PPERFINFO_DSHOW_AUDIOGLITCH PerfInfoAudioGlitch;
  121. ULONG i;
  122. LONGLONG PresentationDelta;
  123. if (IsEqualGUID (Event->Header.Guid, GUID_VIDEOREND)) {
  124. printf (".");
  125. PerfInfoAvRend = (PPERFINFO_DSHOW_AVREND)Event->MofData;
  126. PresentationDelta = PerfInfoAvRend->dshowClock - PerfInfoAvRend->sampleTime;
  127. if (labs ((int)PresentationDelta) > GLITCH_THRESHOLD) {
  128. printf ("Video glitch on sample time %I64d; delta: %f\n",
  129. PerfInfoAvRend->sampleTime,
  130. (double)PresentationDelta / 10000.0L);
  131. }
  132. }
  133. else if (IsEqualGUID (Event->Header.Guid, GUID_DSOUNDGLITCH)) {
  134. PerfInfoAudioGlitch = (PPERFINFO_DSHOW_AUDIOGLITCH)Event->MofData;
  135. printf ("[DSound] Audio glitch type %d [time %d].\n",
  136. PerfInfoAudioGlitch->glitchType, GetTickCount());
  137. }
  138. else if (IsEqualGUID (Event->Header.Guid, KmixerGuid)) {
  139. PerfInfoAudioGlitch = (PPERFINFO_DSHOW_AUDIOGLITCH)Event->MofData;
  140. printf ("[KMixer] Audio glitch type %d [time %d].\n",
  141. PerfInfoAudioGlitch->glitchType, GetTickCount());
  142. }
  143. else if (IsEqualGUID (Event->Header.Guid, PortclsGuid)) {
  144. PerfInfoAudioGlitch = (PPERFINFO_DSHOW_AUDIOGLITCH)Event->MofData;
  145. printf ("[PortCls] Audio glitch type %d [time %d].\n",
  146. PerfInfoAudioGlitch->glitchType, GetTickCount());
  147. }
  148. else if (IsEqualGUID (Event->Header.Guid, UsbaudioGuid)) {
  149. PerfInfoAudioGlitch = (PPERFINFO_DSHOW_AUDIOGLITCH)Event->MofData;
  150. printf ("[UsbAudio] Audio glitch type %d [time %d].\n",
  151. PerfInfoAudioGlitch->glitchType, GetTickCount());
  152. }
  153. else {
  154. printf ("Other: GUID %08X-%08X-%08X-%08X\n",
  155. *((DWORD*)(&Event->Header.Guid)),
  156. *((DWORD*)(&Event->Header.Guid) + 1),
  157. *((DWORD*)(&Event->Header.Guid) + 2),
  158. *((DWORD*)(&Event->Header.Guid) + 3));
  159. }
  160. }
  161. ////////////////////////////////////////////////////////////////////////////
  162. ULONG
  163. WINAPI
  164. BufferCallback (
  165. PEVENT_TRACE_LOGFILE Log
  166. )
  167. {
  168. return TRUE;
  169. }
  170. ////////////////////////////////////////////////////////////////////////////
  171. DWORD
  172. WINAPI
  173. MonitorThreadProc (
  174. LPVOID Param
  175. )
  176. {
  177. struct EVENT_TRACE_INFO {
  178. EVENT_TRACE_PROPERTIES TraceProperties;
  179. char Logger[256];
  180. } Info;
  181. UNREFERENCED_PARAMETER (Param);
  182. ULONG status;
  183. //
  184. // Start the controller.
  185. //
  186. ZeroMemory (&Info, sizeof (Info));
  187. Info.TraceProperties.Wnode.BufferSize = sizeof (Info);
  188. Info.TraceProperties.Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  189. Info.TraceProperties.Wnode.Guid = ControlGuid;
  190. Info.TraceProperties.BufferSize = 4096;
  191. Info.TraceProperties.MinimumBuffers = 8;
  192. Info.TraceProperties.MaximumBuffers = 32;
  193. Info.TraceProperties.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  194. Info.TraceProperties.FlushTimer = 1;
  195. Info.TraceProperties.EnableFlags = 1;
  196. Info.TraceProperties.AgeLimit = 1;
  197. Info.TraceProperties.LoggerNameOffset = sizeof (Info.TraceProperties);
  198. strcpy (Info.Logger, "DSTrace");
  199. status = StartTrace (&LoggerHandle, "DSTrace", &Info.TraceProperties);
  200. if (status != ERROR_SUCCESS) {
  201. printf ("StartTrace failed=>%d\n", status);
  202. goto RETURN;
  203. }
  204. status = EnableTrace (TRUE, 0x1f, 0, &ControlGuid, LoggerHandle);
  205. if (status != ERROR_SUCCESS) {
  206. printf ("EnableTrace failed=>%d\n", status);
  207. goto RETURN;
  208. }
  209. //
  210. // Start the consumer.
  211. //
  212. ZeroMemory (&Logfile, sizeof (Logfile));
  213. Logfile.LoggerName = "DSTrace";
  214. Logfile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  215. Logfile.BufferCallback = BufferCallback;
  216. Logfile.EventCallback = EventCallback;
  217. ConsumerHandle = OpenTrace (&Logfile);
  218. if (ConsumerHandle == (TRACEHANDLE)INVALID_HANDLE_VALUE) {
  219. printf ("OpenTrace failed=>%d\n", GetLastError());
  220. goto RETURN;
  221. }
  222. printf ("Trace opened.\n");
  223. //
  224. // Consume. This call returns when logging is stopped.
  225. //
  226. status = ProcessTrace (&ConsumerHandle, 1, NULL, NULL);
  227. if (status != ERROR_SUCCESS) {
  228. printf ("ProcessTrace failed=>%d\n", status);
  229. return 0;
  230. }
  231. //
  232. // Clean up.
  233. //
  234. RETURN:
  235. ConsoleCtrlHandler (CTRL_INITIALIZATION_ERROR);
  236. return 0;
  237. }
  238. ////////////////////////////////////////////////////////////////////////////
  239. VOID
  240. __cdecl
  241. main (
  242. VOID
  243. )
  244. {
  245. ULONG status;
  246. status = SetConsoleCtrlHandler (ConsoleCtrlHandler, TRUE);
  247. if (!status) {
  248. printf ("Failed to initialize.");
  249. return;
  250. }
  251. //
  252. // Create the monitor thread and block.
  253. //
  254. MonitorThread = CreateThread (NULL, 0, MonitorThreadProc, 0, 0, NULL);
  255. if (MonitorThread == NULL) {
  256. return;
  257. }
  258. WaitForSingleObject (MonitorThread, INFINITE);
  259. }