1 /* ****************************************************************************** *\
2 
3 Copyright (C) 2012-2020 Intel Corporation.  All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 - Redistributions of source code must retain the above copyright notice,
8 this list of conditions and the following disclaimer.
9 - Redistributions in binary form must reproduce the above copyright notice,
10 this list of conditions and the following disclaimer in the documentation
11 and/or other materials provided with the distribution.
12 - Neither the name of Intel Corporation nor the names of its contributors
13 may be used to endorse or promote products derived from this software
14 without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 File Name: tracer_windows.cpp
28 
29 \* ****************************************************************************** */
30 
31 #if defined(_WIN32) || defined(_WIN64)
32 
33 #define MFX_DISPATCHER_LOG 1
34 
35 #include <windows.h>
36 #include <string.h>
37 #include <iostream>
38 #include "tracer.h"
39 #include "mfx_dispatcher.h"
40 #include "mfx_dispatcher_log.h"
41 #include "../tools/shared_mem_server.h"
42 
43 
44 //dump messages from dispatcher
45 class DispatcherLogRecorder : public IMsgHandler
46 {
47     static DispatcherLogRecorder m_Instance;
48 public:
get()49     static DispatcherLogRecorder& get(){return m_Instance;}
50     virtual void Write(int level, int opcode, const char * msg, va_list argptr);
51 };
52 
53 
54 class msdk_analyzer_sink : public IMsgHandler
55 {
56 
57 public:
msdk_analyzer_sink()58     msdk_analyzer_sink()
59     {
60         DispatchLog::get().AttachSink(DL_SINK_IMsgHandler, this);
61         DispatchLog::get().DetachSink(DL_SINK_PRINTF, NULL);
62     }
~msdk_analyzer_sink()63     ~msdk_analyzer_sink()
64     {
65         DispatchLog::get().DetachSink(DL_SINK_IMsgHandler, this);
66 
67     }
68 
Write(int level,int,const char * msg,va_list argptr)69     virtual void Write(int level, int /*opcode*/, const char * msg, va_list argptr)
70     {
71         char message_formated[1024];
72         if ((msg) && (argptr) && (level != DL_LOADED_LIBRARY))
73         {
74             vsprintf_s(message_formated, sizeof(message_formated)/sizeof(message_formated[0]), msg, argptr);
75 
76             //todo: eliminate this
77             if (message_formated[strnlen_s(message_formated, 1024)-1] == '\n')
78             {
79                 message_formated[strnlen_s(message_formated, 1024)-1] = 0;
80             }
81             Log::WriteLog(message_formated);
82         }
83     }
84 
85 };
86 
87 static char* g_mfxlib = NULL;
88 bool is_loaded;
89 
90 
91 
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpReserved)92 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
93 {
94     lpReserved;
95     hinstDLL;
96 
97     try{
98 
99         std::string slib = "";
100         switch( fdwReason ){
101             case DLL_PROCESS_ATTACH:
102                 slib = Config::GetParam("core", "lib");
103                 g_mfxlib = new char[MAX_PATH];
104                 strcpy_s(g_mfxlib, MAX_PATH, slib.c_str());
105                 if (!strcmp(g_mfxlib, "none"))
106                 {
107                     Log::useGUI = true;
108                     if (!is_loaded)
109                     {
110                         run_shared_memory_server();
111                     }
112 
113                 }
114                 tracer_init();
115                 Log::WriteLog(std::string("function: DLLMain() DLL_PROCESS_ATTACH +"));
116                 Log::WriteLog("mfx_tracer: lib=" + std::string(g_mfxlib));
117                 Log::WriteLog(std::string("function: DLLMain() DLL_PROCESS_ATTACH - \n\n"));
118                 break;
119             case DLL_THREAD_ATTACH:
120 
121                 break;
122             case DLL_THREAD_DETACH:
123 
124                 break;
125             case DLL_PROCESS_DETACH:
126                 Log::WriteLog(std::string("function: DLLMain() DLL_PROCESS_DETACH +"));
127                 //delete [] g_mfxlib;
128                 Log::WriteLog(std::string("function: DLLMain() DLL_PROCESS_DETACH - \n\n"));
129                 stop_shared_memory_server();
130                 break;
131         }
132     }
133     catch (std::exception& e){
134         std::cerr << "Exception: " << e.what() << '\n';
135     }
136     return TRUE;
137 }
138 
139 // external define from Dispatcher compiled with/MFX_DISPATCHER_EXPOSED_PREFIX
140 extern "C"
141 {
142     mfxStatus MFX_CDECL disp_MFXInitEx(mfxInitParam par, mfxSession *session);
143 }
144 
TracerInit(mfxInitParam par,mfxSession * session)145 mfxStatus TracerInit (mfxInitParam par, mfxSession *session)
146 {
147     DumpContext context;
148     context.context = DUMPCONTEXT_MFX;
149     if (!session) {
150         Log::WriteLog(context.dump("ver", par.Version));
151         Log::WriteLog(context.dump("session", NULL));
152         Log::WriteLog(context.dump_mfxStatus("status", MFX_ERR_NULL_PTR));
153         return MFX_ERR_NULL_PTR;
154     }
155 
156     mfxLoader* loader = (mfxLoader*)calloc(1, sizeof(mfxLoader));
157     if (!loader) {
158         Log::WriteLog(context.dump("ver", par.Version));
159         Log::WriteLog(context.dump("session", *session));
160         Log::WriteLog(context.dump_mfxStatus("status", MFX_ERR_MEMORY_ALLOC));
161         return MFX_ERR_MEMORY_ALLOC;
162      }
163 
164      Log::WriteLog("LoadLibrary: " + std::string(g_mfxlib));
165      HINSTANCE h_mfxdll = NULL;
166      h_mfxdll = LoadLibrary(g_mfxlib);
167      if (h_mfxdll == NULL){
168         //dispatcher
169         mfxStatus sts;
170         msdk_analyzer_sink sink;
171         is_loaded = true;
172         sts = disp_MFXInitEx(par, session);
173         is_loaded = false;
174         if (sts != MFX_ERR_NONE)
175         {
176             Log::WriteLog(context.dump("ver", par.Version));
177             Log::WriteLog(context.dump("session", *session));
178             Log::WriteLog(context.dump_mfxStatus("status", MFX_ERR_NOT_FOUND));
179             free(loader);
180             return MFX_ERR_NOT_FOUND;
181         }
182         char libModuleName[MAX_PATH];
183 
184         GetModuleFileName((HMODULE)(*(MFX_DISP_HANDLE**)(session))->hModule, libModuleName, MAX_PATH);
185         if (GetLastError() != 0)
186         {
187            Log::WriteLog("GetModuleFileName() reported  error! \n");
188            free(loader);
189            return MFX_ERR_NOT_FOUND;
190         }
191         h_mfxdll = LoadLibrary(libModuleName);
192     }
193     loader->dlhandle = h_mfxdll;
194 
195     //Loading functions table
196     int i;
197     mfxFunctionPointer proc;
198     for (i = 0; i < eFunctionsNum; ++i) {
199         proc = (mfxFunctionPointer)GetProcAddress((HINSTANCE)loader->dlhandle, g_mfxFuncTable[i].name);
200         if (!proc){
201             Sleep(100);
202             proc = (mfxFunctionPointer)GetProcAddress((HINSTANCE)loader->dlhandle, g_mfxFuncTable[i].name);
203         }
204         //if (!proc) break;
205         if(proc) loader->table[i] = proc;
206     }
207     // Initializing loaded library
208     mfxStatus mfx_res = (*(MFXInitPointer)loader->table[eMFXInit])(par.Implementation, &par.Version, &(loader->session));
209     if (MFX_ERR_NONE != mfx_res) {
210             FreeLibrary(h_mfxdll);
211             Log::WriteLog(context.dump("ver", par.Version));
212             Log::WriteLog(context.dump("session", *session));
213             Log::WriteLog(context.dump_mfxStatus("status", mfx_res));
214             free(loader);
215             return mfx_res;
216     }
217     *session = (mfxSession)loader;
218     return MFX_ERR_NONE;
219 }
220 
221 
MFXInit(mfxIMPL impl,mfxVersion * ver,mfxSession * session)222 mfxStatus MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSession *session)
223 {
224     if (is_loaded)
225     {
226         return MFX_ERR_ABORTED;
227     }
228     try{
229         DumpContext context;
230         context.context = DUMPCONTEXT_MFX;
231         Log::WriteLog(std::string("function: MFXInit(mfxIMPL impl=" + GetmfxIMPL(impl) + ", mfxVersion *ver=" + ToString(ver) + ", mfxSession *session=" + ToString(session) + ") +"));
232         mfxInitParam par = {};
233 
234         par.Implementation = impl;
235         if (ver)
236         {
237             par.Version = *ver;
238         }
239         else
240         {
241             par.Version.Major = DEFAULT_API_VERSION_MAJOR;
242             par.Version.Minor = DEFAULT_API_VERSION_MINOR;
243         }
244         par.ExternalThreads = 0;
245         Timer t;
246         mfxStatus sts = TracerInit(par, session);
247         std::string elapsed = TimeToString(t.GetTime());
248         Log::WriteLog(">> MFXInit called");
249 
250         Log::WriteLog(context.dump("impl", impl));
251         if (ver) Log::WriteLog(context.dump("ver", *ver));
252         if (session) Log::WriteLog(context.dump("session", *session));
253         Log::WriteLog(std::string("function: MFXInit(" + elapsed + ", " + context.dump_mfxStatus("status", sts) + ") - \n\n"));
254         return sts;
255     }
256     catch (std::exception& e){
257         std::cerr << "Exception: " << e.what() << '\n';
258         return MFX_ERR_ABORTED;
259     }
260 
261 }
262 
MFXClose(mfxSession session)263 mfxStatus MFXClose(mfxSession session)
264 {
265     try{
266         DumpContext context;
267         context.context = DUMPCONTEXT_MFX;
268         Log::WriteLog("function: MFXClose(mfxSession session=" + context.toString<mfxSession>(session) + ") +");
269         mfxLoader* loader = (mfxLoader*)session;
270 
271         if (!loader){
272             Log::WriteLog(context.dump("session", session));
273             Log::WriteLog(context.dump_mfxStatus("status", MFX_ERR_INVALID_HANDLE));
274             return MFX_ERR_INVALID_HANDLE;
275         }
276         Log::WriteLog(context.dump("session", session));
277         Timer t;
278         mfxStatus mfx_res = (*(MFXClosePointer)loader->table[eMFXClose])(loader->session);
279         std::string elapsed = TimeToString(t.GetTime());
280         Log::WriteLog(">> MFXClose called");
281 
282         FreeLibrary((HINSTANCE)loader->dlhandle);
283 
284         Log::WriteLog(context.dump("session", session));
285         Log::WriteLog("function: MFXClose(" + elapsed + ", " + context.dump_mfxStatus("status", mfx_res) + ") - \n\n");
286         return mfx_res;
287     }
288     catch (std::exception& e){
289         std::cerr << "Exception: " << e.what() << '\n';
290         return MFX_ERR_ABORTED;
291     }
292 }
293 
MFXInitEx(mfxInitParam par,mfxSession * session)294 mfxStatus MFXInitEx(mfxInitParam par, mfxSession *session)
295 {
296     if (is_loaded)
297     {
298         return MFX_ERR_ABORTED;
299     }
300     try{
301         DumpContext context;
302         context.context = DUMPCONTEXT_MFX;
303         Log::WriteLog(std::string("function: MFXInitEx(par.Implementation=" + GetmfxIMPL(par.Implementation) + " par.Versin="+ ToString(&par.Version) +", mfxSession *session=" + ToString(session) + ") +"));
304         Timer t;
305         mfxStatus sts = TracerInit(par, session);
306         std::string elapsed = TimeToString(t.GetTime());
307         Log::WriteLog(">> MFXInitEx called");
308         Log::WriteLog(context.dump("par", par));
309         Log::WriteLog(context.dump("session", *session));
310         Log::WriteLog(std::string("function: MFXInitEx(" + elapsed + ", " + context.dump_mfxStatus("status", sts) + ") - \n\n"));
311         return sts;
312     }
313     catch (std::exception& e){
314         std::cerr << "Exception: " << e.what() << '\n';
315         return MFX_ERR_ABORTED;
316     }
317 }
318 
319 
320 
321 #endif // #if defined(_WIN32) || defined(_WIN64)
322 
323 
324