1 // Copyright (c) 2012-2019 Intel Corporation
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20
21 #if defined(MFX_DISPATCHER_LOG)
22
23 #include "mfx_dispatcher_log.h"
24 #include "mfxstructures.h"
25 #include <windows.h>
26 #if defined(DISPATCHER_LOG_REGISTER_EVENT_PROVIDER)
27 #include <evntprov.h>
28 #include <winmeta.h>
29 #endif
30 #include <stdarg.h>
31 #include <algorithm>
32 #include <string>
33 #include <sstream>
34
35 struct CodeStringTable
36 {
37 int code;
38 const char *string;
39 } LevelStrings []=
40 {
41 {DL_INFO, "INFO: "},
42 {DL_WRN, "WARNING:"},
43 {DL_ERROR, "ERROR: "}
44 };
45
46 #define DEFINE_CODE(code)\
47 {code, #code}
48
49 static CodeStringTable StringsOfImpl[] = {
50 DEFINE_CODE(MFX_IMPL_AUTO),
51 DEFINE_CODE(MFX_IMPL_SOFTWARE),
52 DEFINE_CODE(MFX_IMPL_HARDWARE),
53 DEFINE_CODE(MFX_IMPL_AUTO_ANY),
54 DEFINE_CODE(MFX_IMPL_HARDWARE_ANY),
55 DEFINE_CODE(MFX_IMPL_HARDWARE2),
56 DEFINE_CODE(MFX_IMPL_HARDWARE3),
57 DEFINE_CODE(MFX_IMPL_HARDWARE4),
58
59 DEFINE_CODE(MFX_IMPL_UNSUPPORTED)
60 };
61
62 static CodeStringTable StringsOfImplVIA[] = {
63 DEFINE_CODE(MFX_IMPL_VIA_ANY),
64 DEFINE_CODE(MFX_IMPL_VIA_D3D9),
65 DEFINE_CODE(MFX_IMPL_VIA_D3D11),
66 };
67
68 static CodeStringTable StringsOfStatus[] =
69 {
70 DEFINE_CODE(MFX_ERR_NONE ),
71 DEFINE_CODE(MFX_ERR_UNKNOWN ),
72 DEFINE_CODE(MFX_ERR_NULL_PTR ),
73 DEFINE_CODE(MFX_ERR_UNSUPPORTED ),
74 DEFINE_CODE(MFX_ERR_MEMORY_ALLOC ),
75 DEFINE_CODE(MFX_ERR_NOT_ENOUGH_BUFFER ),
76 DEFINE_CODE(MFX_ERR_INVALID_HANDLE ),
77 DEFINE_CODE(MFX_ERR_LOCK_MEMORY ),
78 DEFINE_CODE(MFX_ERR_NOT_INITIALIZED ),
79 DEFINE_CODE(MFX_ERR_NOT_FOUND ),
80 DEFINE_CODE(MFX_ERR_MORE_DATA ),
81 DEFINE_CODE(MFX_ERR_MORE_SURFACE ),
82 DEFINE_CODE(MFX_ERR_ABORTED ),
83 DEFINE_CODE(MFX_ERR_DEVICE_LOST ),
84 DEFINE_CODE(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM),
85 DEFINE_CODE(MFX_ERR_INVALID_VIDEO_PARAM ),
86 DEFINE_CODE(MFX_ERR_UNDEFINED_BEHAVIOR ),
87 DEFINE_CODE(MFX_ERR_DEVICE_FAILED ),
88 DEFINE_CODE(MFX_WRN_IN_EXECUTION ),
89 DEFINE_CODE(MFX_WRN_DEVICE_BUSY ),
90 DEFINE_CODE(MFX_WRN_VIDEO_PARAM_CHANGED ),
91 DEFINE_CODE(MFX_WRN_PARTIAL_ACCELERATION ),
92 DEFINE_CODE(MFX_WRN_INCOMPATIBLE_VIDEO_PARAM),
93 DEFINE_CODE(MFX_WRN_VALUE_NOT_CHANGED ),
94 DEFINE_CODE(MFX_WRN_OUT_OF_RANGE ),
95
96 };
97
98 #define CODE_TO_STRING(code, array)\
99 CodeToString(code, array, sizeof(array)/sizeof(array[0]))
100
CodeToString(int code,CodeStringTable array[],int len)101 const char* CodeToString(int code, CodeStringTable array[], int len )
102 {
103 for (int i = 0 ; i < len; i++)
104 {
105 if (array[i].code == code)
106 return array[i].string;
107 }
108 return "undef";
109 }
110
DispatcherLog_GetMFXImplString(int impl)111 std::string DispatcherLog_GetMFXImplString(int impl)
112 {
113 std::string str1 = CODE_TO_STRING(impl & ~(-MFX_IMPL_VIA_ANY), StringsOfImpl);
114 std::string str2 = CODE_TO_STRING(impl & (-MFX_IMPL_VIA_ANY), StringsOfImplVIA);
115
116 return str1 + (str2 == "undef" ? "" : "|"+str2);
117 }
118
DispatcherLog_GetMFXStatusString(int sts)119 const char *DispatcherLog_GetMFXStatusString(int sts)
120 {
121 return CODE_TO_STRING(sts, StringsOfStatus);
122 }
123
124 //////////////////////////////////////////////////////////////////////////
125
126
Write(const char * str,...)127 void DispatcherLogBracketsHelper::Write(const char * str, ...)
128 {
129 va_list argsptr;
130 va_start(argsptr, str);
131 DispatchLog::get().Write(m_level, m_opcode, str, argsptr);
132 va_end(argsptr);
133 }
134
Write(const char * str,...)135 void DispatchLogBlockHelper::Write(const char * str, ...)
136 {
137 va_list argsptr;
138 va_start(argsptr, str);
139 DispatchLog::get().Write(m_level, DL_EVENT_START, str, argsptr);
140 va_end(argsptr);
141 }
142
~DispatchLogBlockHelper()143 DispatchLogBlockHelper::~DispatchLogBlockHelper()
144 {
145 DispatchLog::get().Write(m_level, DL_EVENT_STOP, NULL, NULL);
146 }
147
148 //////////////////////////////////////////////////////////////////////////
149
DispatchLog()150 DispatchLog::DispatchLog()
151 : m_DispatcherLogSink(DL_SINK_PRINTF)
152 {
153
154 }
155
SetSink(int nSink,IMsgHandler * pHandler)156 void DispatchLog::SetSink(int nSink, IMsgHandler * pHandler)
157 {
158 DetachAllSinks();
159 AttachSink(nSink, pHandler);
160 }
161
AttachSink(int nsink,IMsgHandler * pHandler)162 void DispatchLog::AttachSink(int nsink, IMsgHandler *pHandler)
163 {
164 m_DispatcherLogSink |= nsink;
165 if (NULL != pHandler)
166 m_Recepients.push_back(pHandler);
167 }
168
DetachSink(int nsink,IMsgHandler * pHandler)169 void DispatchLog::DetachSink(int nsink, IMsgHandler *pHandler)
170 {
171 if (nsink & DL_SINK_IMsgHandler)
172 {
173 m_Recepients.remove(pHandler);
174 }
175
176 m_DispatcherLogSink &= ~nsink;
177 }
178
ExchangeSink(int nsink,IMsgHandler * oldHdl,IMsgHandler * newHdl)179 void DispatchLog::ExchangeSink(int nsink, IMsgHandler *oldHdl, IMsgHandler *newHdl)
180 {
181 if (nsink & DL_SINK_IMsgHandler)
182 {
183 std::list<IMsgHandler*> :: iterator it = std::find(m_Recepients.begin(), m_Recepients.end(), oldHdl);
184
185 //cannot exchange in that case
186 if (m_Recepients.end() == it)
187 return;
188
189 *it = newHdl;
190 }
191 }
192
193
DetachAllSinks()194 void DispatchLog::DetachAllSinks()
195 {
196 m_Recepients.clear();
197 m_DispatcherLogSink = DL_SINK_NULL;
198 }
199
Write(int level,int opcode,const char * msg,va_list argptr)200 void DispatchLog::Write(int level, int opcode, const char * msg, va_list argptr)
201 {
202 int sinkTable[] =
203 {
204 DL_SINK_PRINTF,
205 DL_SINK_IMsgHandler,
206 };
207
208 for (size_t i = 0; i < sizeof(sinkTable) / sizeof(sinkTable[0]); i++)
209 {
210 switch(m_DispatcherLogSink & sinkTable[i])
211 {
212 case DL_SINK_NULL:
213 break;
214
215 case DL_SINK_PRINTF:
216 {
217 char msg_formated[8048] = {0};
218
219 if (NULL != msg && level != DL_LOADED_LIBRARY)
220 {
221 #if _MSC_VER >= 1400
222 vsprintf_s(msg_formated, sizeof(msg_formated)/sizeof(msg_formated[0]), msg, argptr);
223 #else
224 vsnprintf(msg_formated, sizeof(msg_formated)/sizeof(msg_formated[0]), msg, argptr);
225 #endif
226 //TODO: improve this , add opcode handling
227 printf("%s %s", CODE_TO_STRING(level, LevelStrings), msg_formated);
228 }
229 break;
230 }
231
232 case DL_SINK_IMsgHandler:
233 {
234 std::list<IMsgHandler*>::iterator it;
235
236 for (it = m_Recepients.begin(); it != m_Recepients.end(); ++it)
237 {
238 (*it)->Write(level, opcode, msg, argptr);
239 }
240 break;
241 }
242 }
243 }
244 }
245
246 #if defined(DISPATCHER_LOG_REGISTER_EVENT_PROVIDER)
247 class ETWHandler : public IMsgHandler
248 {
249 public:
ETWHandler(const wchar_t * guid_str)250 ETWHandler(const wchar_t * guid_str)
251 : m_bUseFormatter(DISPATCHER_LOG_USE_FORMATING)
252 , m_EventHandle()
253 , m_bProviderEnable()
254 {
255 GUID rguid = GUID_NULL;
256 if (FAILED(CLSIDFromString(guid_str, &rguid)))
257 {
258 return;
259 }
260
261 EventRegister(&rguid, NULL, NULL, &m_EventHandle);
262
263 m_bProviderEnable = 0 != EventProviderEnabled(m_EventHandle, 1,0);
264 }
265
~ETWHandler()266 ~ETWHandler()
267 {
268 if (m_EventHandle)
269 {
270 EventUnregister(m_EventHandle);
271 }
272 }
273
Write(int level,int opcode,const char * msg,va_list argptr)274 virtual void Write(int level, int opcode, const char * msg, va_list argptr)
275 {
276 //event not registered
277 if (0==m_EventHandle)
278 {
279 return;
280 }
281 if (!m_bProviderEnable)
282 {
283 return;
284 }
285 if (level == DL_LOADED_LIBRARY)
286 {
287 return;
288 }
289
290 char msg_formated[1024];
291 EVENT_DESCRIPTOR descriptor;
292 EVENT_DATA_DESCRIPTOR data_descriptor;
293
294 EventDescZero(&descriptor);
295
296 descriptor.Opcode = (UCHAR)opcode;
297 descriptor.Level = (UCHAR)level;
298
299 if (m_bUseFormatter)
300 {
301 if (NULL != msg)
302 {
303 #if _MSC_VER >= 1400
304 vsprintf_s(msg_formated, sizeof (msg_formated) / sizeof (msg_formated[0]), msg, argptr);
305 #else
306 vsnprintf(msg_formated, sizeof (msg_formated) / sizeof (msg_formated[0]), msg, argptr);
307 #endif
308 EventDataDescCreate(&data_descriptor, msg_formated, (ULONG)(strlen(msg_formated) + 1));
309 }else
310 {
311 EventDataDescCreate(&data_descriptor, NULL, 0);
312 }
313 }else
314 {
315 //TODO: non formated events supports under zbb
316 }
317
318 EventWrite(m_EventHandle, &descriptor, 1, &data_descriptor);
319 }
320
321 protected:
322
323 //we may not use formatter in some cases described in dispatch_log macro
324 //it significantly increases performance by eliminating any vsprintf operations
325 bool m_bUseFormatter;
326 //consumer is attached, dispatcher trace to reduce formating overhead
327 //submits event only if consumer attached
328 bool m_bProviderEnable;
329 REGHANDLE m_EventHandle;
330 };
331 //
332
333
GetSink(const wchar_t * sguid)334 IMsgHandler *ETWHandlerFactory::GetSink(const wchar_t* sguid)
335 {
336 _storage_type::iterator it;
337 it = m_storage.find(sguid);
338 if (it == m_storage.end())
339 {
340 ETWHandler * handler = new ETWHandler(sguid);
341 _storage_type::_Pairib it_bool = m_storage.insert(_storage_type::value_type(sguid, handler));
342 it = it_bool.first;
343 }
344
345 return it->second;
346 }
347
~ETWHandlerFactory()348 ETWHandlerFactory::~ETWHandlerFactory()
349 {
350 for each(_storage_type::value_type val in m_storage)
351 {
352 delete val.second;
353 }
354 }
355
356 class EventRegistrator : public IMsgHandler
357 {
358 const wchar_t * m_sguid;
359 public:
EventRegistrator(const wchar_t * sguid=DISPATCHER_LOG_EVENT_GUID)360 EventRegistrator(const wchar_t* sguid = DISPATCHER_LOG_EVENT_GUID)
361 :m_sguid(sguid)
362 {
363 DispatchLog::get().AttachSink( DL_SINK_IMsgHandler
364 , this);
365 }
366
Write(int level,int opcode,const char * msg,va_list argptr)367 virtual void Write(int level, int opcode, const char * msg, va_list argptr)
368 {
369 //we cannot call attach sink since we may have been called from iteration
370 //we axchanging preserve that placeholding
371 IMsgHandler * pSink = NULL;
372 DispatchLog::get().ExchangeSink(DL_SINK_IMsgHandler,
373 this,
374 pSink = ETWHandlerFactory::get().GetSink(m_sguid));
375 //need to call only once here all next calls will be done inside dispatcherlog
376 if (NULL != pSink)
377 {
378 pSink->Write(level, opcode, msg, argptr);
379 }
380 }
381 };
382 #endif
383
384 template <class TSink>
385 class SinkRegistrator
386 {
387 };
388
389 #if defined(DISPATCHER_LOG_REGISTER_EVENT_PROVIDER)
390 template <>
391 class SinkRegistrator<ETWHandlerFactory>
392 {
393 public:
SinkRegistrator(const wchar_t * sguid=DISPATCHER_LOG_EVENT_GUID)394 SinkRegistrator(const wchar_t* sguid = DISPATCHER_LOG_EVENT_GUID)
395 {
396 DispatchLog::get().AttachSink( DL_SINK_IMsgHandler
397 , ETWHandlerFactory::get().GetSink(sguid));
398 }
399 };
400 #endif
401
402 #if defined(DISPATCHER_LOG_REGISTER_FILE_WRITER)
403 template <>
404 class SinkRegistrator<FileSink>
405 {
406 public:
SinkRegistrator()407 SinkRegistrator()
408 {
409 DispatchLog::get().AttachSink( DL_SINK_IMsgHandler, &FileSink::get(DISPACTHER_LOG_FW_PATH));
410 }
411 };
412
Write(int level,int,const char * msg,va_list argptr)413 void FileSink::Write(int level, int /*opcode*/, const char * msg, va_list argptr)
414 {
415 if (NULL != m_hdl && NULL != msg)
416 {
417 fprintf(m_hdl, "%s", CODE_TO_STRING(level, LevelStrings));
418 vfprintf(m_hdl, msg, argptr);
419 }
420 }
421 #endif
422
423 //////////////////////////////////////////////////////////////////////////
424 //singletons initialization section
425
426
427 #ifdef DISPATCHER_LOG_REGISTER_EVENT_PROVIDER
428 static SinkRegistrator<ETWHandlerFactory> g_registrator1;
429 #endif
430
431
432 #ifdef DISPATCHER_LOG_REGISTER_FILE_WRITER
433 static SinkRegistrator<FileSink> g_registrator2;
434 #endif
435
436
437 #endif//(MFX_DISPATCHER_LOG)