// Copyright (c) 2012-2020 Intel Corporation // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #if !defined(__MFX_DISPATCHER_LOG_H) #define __MFX_DISPATCHER_LOG_H ////////////////////////////////////////////////////////////////////////// //dispatcher log (DL) level #define DL_INFO 1 #define DL_WRN 2 #define DL_ERROR 4 #define DL_LOADED_LIBRARY 8 ////////////////////////////////////////////////////////////////////////// //opcodes used only in events enum { DL_EVENT_START = 1, DL_EVENT_STOP, DL_EVENT_MSG }; ////////////////////////////////////////////////////////////////////////// #define DL_SINK_NULL 0 #define DL_SINK_PRINTF 1 #define DL_SINK_IMsgHandler 2 #define MFXFOURCCTYPE() "%c%c%c%c" #define ZERO_OR_SPACE(value) ((0==(value)) ? '0' : (value)) #define MFXU32TOFOURCC(mfxu32)\ ZERO_OR_SPACE((char)(mfxu32 & 0xFF)), \ ZERO_OR_SPACE((char)((mfxu32 >> 8) & 0xFF)),\ ZERO_OR_SPACE((char)((mfxu32 >> 16) & 0xFF)),\ ZERO_OR_SPACE((char)((mfxu32 >> 24) & 0xFF)) #define MFXGUIDTYPE() "%X-%X-%X-%X-%X-%X-%X-%X-%X-%X-%X-%X-%X-%X-%X-%X" #define MFXGUIDTOHEX(guid)\ (guid)->Data[0],\ (guid)->Data[1],\ (guid)->Data[2],\ (guid)->Data[3],\ (guid)->Data[4],\ (guid)->Data[5],\ (guid)->Data[6],\ (guid)->Data[7],\ (guid)->Data[8],\ (guid)->Data[9],\ (guid)->Data[10],\ (guid)->Data[11],\ (guid)->Data[12],\ (guid)->Data[13],\ (guid)->Data[14],\ (guid)->Data[15] #if defined(MFX_DISPATCHER_LOG) //---------------------------setup section------------------------ //using of formating instead of variadic macro with NULL end, //leads to more flexibility in format, however constructing string //with vsprintf_s is a time wasting #define DISPATCHER_LOG_USE_FORMATING 1 //creates unique object, event guid registration, factories on heap //heap reduce stack allocation and reduce reservation time at startup //is a vital if mediasdk wont use #define DISPATCHER_LOG_HEAP_SINGLETONES // guid for all dispatcher events #define DISPATCHER_LOG_EVENT_GUID L"{EB0538CC-4FEE-484d-ACEE-1182E9F37A57}" //puts a sink into listeners list //#define DISPATCHER_LOG_REGISTER_EVENT_PROVIDER //puts a sink into listeners list //#define DISPATCHER_LOG_REGISTER_FILE_WRITER #define DISPACTHER_LOG_FW_PATH "c:\\dispatcher.log" #include #include //callback interface for intercept logging messages class IMsgHandler { public: virtual ~IMsgHandler(){} virtual void Write(int level, int opcode, const char * msg, va_list argptr) = 0; }; #if DISPATCHER_LOG_USE_FORMATING #define DISPATCHER_LOG(lvl, opcode, str)\ {\ DispatcherLogBracketsHelper wrt(lvl,opcode);\ wrt.Write str;\ } #else #define DISPATCHER_LOG_VA_ARGS(...) wrt.Write(__VA_ARGS__, NULL) //WARNING: don't use types that occupy more that 4 bytes in memory //WARNING: don't use %s in format specifier #define DISPATCHER_LOG(lvl, opcode, str) \ {\ DispatcherLogBracketsHelper wrt(lvl, opcode);\ DISPATCHER_LOG_VA_ARGS str;\ } #endif//DISPATCHER_LOG_USE_FORMATING #define DISPATCHER_LOG_OPERATION(operation) operation #define __name_from_line( name, line ) name ## line #define _name_from_line( name , line) __name_from_line( name, line ) #define name_from_line( name ) _name_from_line( name, __LINE__) #define DISPATCHER_LOG_AUTO(lvl, msg)\ DispatchLogBlockHelper name_from_line(__auto_log_)(lvl); name_from_line(__auto_log_).Write msg; #include #include #include #include template class DSSingleTone { public: template inline static T & get(TParam1 par1) { T * pstored; if (NULL == (pstored = store_or_load())) { return *store_or_load(new T(par1)); } return *pstored; } inline static T & get() { T * pstored; if (NULL == (pstored = store_or_load())) { return *store_or_load(new T()); } return *pstored; } private: //if obj == NULL, then it load //if obj != NULL then it store obj inline static T * store_or_load(T * obj = NULL) { static std::unique_ptr instance; if (NULL != obj) { instance.reset(obj); } return instance.get(); } }; class DispatchLog : public DSSingleTone { friend class DSSingleTone; std::listm_Recepients; int m_DispatcherLogSink; public: //sets current sink void SetSink(int nsink, IMsgHandler *pHandler); void AttachSink(int nsink, IMsgHandler *pHandler); void DetachSink(int nsink, IMsgHandler *pHandler); void ExchangeSink(int nsink, IMsgHandler *pOld, IMsgHandler *pNew); void DetachAllSinks(); void Write(int level, int opcode, const char * msg, va_list argptr); protected: DispatchLog(); }; //allows to push arguments on the stack without declaring them as function parameters struct DispatcherLogBracketsHelper { int m_level; int m_opcode; DispatcherLogBracketsHelper(int level, int opcode) :m_level(level) ,m_opcode(opcode) { } void Write(const char * str, ...); } ; //auto log on ctor dtor struct DispatchLogBlockHelper { int m_level; void Write(const char * str, ...); DispatchLogBlockHelper (int level) : m_level(level) { } ~DispatchLogBlockHelper(); }; //----utility sinks----- #if defined(DISPATCHER_LOG_REGISTER_EVENT_PROVIDER) class ETWHandlerFactory : public DSSingleTone { friend class DSSingleTone; typedef std::map _storage_type; _storage_type m_storage; public: ~ETWHandlerFactory(); IMsgHandler *GetSink(const wchar_t* sguid = DISPATCHER_LOG_EVENT_GUID); protected: ETWHandlerFactory(){} }; #endif #if defined(DISPATCHER_LOG_REGISTER_FILE_WRITER) class FileSink : public DSSingleTone , public IMsgHandler { friend class DSSingleTone; public: virtual void Write(int level, int opcode, const char * msg, va_list argptr); FileSink() : m_hdl(NULL) { } ~FileSink() { if (NULL != m_hdl) fclose(m_hdl); } private: FILE * m_hdl; FileSink(const std::string & log_file) { fopen_s(&m_hdl, log_file.c_str(), "a"); } }; #endif //-----utility functions //since they are not called outside of macro we can define them here std::string DispatcherLog_GetMFXImplString(int impl); const char *DispatcherLog_GetMFXStatusString(int sts); #else // !defined(MFX_DISPATCHER_LOG) #define DISPATCHER_LOG(level, opcode, message) #define DISPATCHER_LOG_AUTO(level, message) #define DISPATCHER_LOG_OPERATION(operation) #endif// !defined(MFX_DISPATCHER_LOG) #define DISPATCHER_LOG_INFO(msg) DISPATCHER_LOG(DL_INFO, DL_EVENT_MSG, msg) #define DISPATCHER_LOG_WRN(msg) DISPATCHER_LOG(DL_WRN, DL_EVENT_MSG, msg) #define DISPATCHER_LOG_ERROR(msg) DISPATCHER_LOG(DL_ERROR, DL_EVENT_MSG, msg) #define DISPATCHER_LOG_LIBRARY(msg) DISPATCHER_LOG(DL_LOADED_LIBRARY, DL_EVENT_MSG, msg) #define DISPATCHER_LOG_BLOCK(msg) DISPATCHER_LOG_AUTO(DL_INFO, msg) #endif // !defined(__MFX_DISPATCHER_LOG_H)