libxcoder  5.2.0
ni_log.c
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * Copyright (C) 2022 NETINT Technologies
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18  * SOFTWARE.
19  *
20  ******************************************************************************/
21 
22 /*!*****************************************************************************
23  * \file ni_log.c
24  *
25  * \brief Logging definitions
26  ******************************************************************************/
27 
28 #include <string.h>
29 #include <stdio.h>
30 #include <stdint.h>
31 #include <time.h>
32 #include <inttypes.h>
33 #ifdef _WIN32
34 #include <windows.h>
35 #else
36 #include <sys/time.h>
37 #endif
38 #include "ni_log.h"
39 #include "ni_defs.h"
40 #include "ni_device_api.h"
41 #include "ni_util.h"
42 
43 
44 static ni_log_level_t ni_log_level = NI_LOG_INFO;
45 static void (*ni_log_callback)(int, const char*, va_list) =
47 
48 #ifdef _WIN32
49 static ni_pthread_mutex_t ni_log2_mutex;
50 static int ni_log2_mutex_initialized = 0;
51 INIT_ONCE g_InitOnce_ni_log2_mutex = INIT_ONCE_STATIC_INIT;
52 #else
53 static ni_pthread_mutex_t ni_log2_mutex = PTHREAD_MUTEX_INITIALIZER;
54 //pthread
55 #endif
56 static int ni_log2_print_with_mutex = 0;
57 
58 #define NI_LOG2_SESSION_ID_TIMESTAMP_FMT "[SID=%x, TS=" "%" PRIu64 "]"
59 #define NI_LOG2_TIMESTAMP_FMT "[TS=" "%" PRIu64 "]"
60 #define NI_LOG2_SESSION_ID_FMT "[SID=%x]"
61 #define NI_LOG2_E2EID_FMT "|%s|"
62 #define NI_LOG2_FMT_FMT "%s"
63 #define NI_LOG2_SPACE " "
64 
65 #define NI_LOG2_PRINT_BUFF_SIZE 512
66 
67 #ifdef _ANDROID
68 #include <android/log.h>
69 
70 static char ni_log_tag[128] = "libxcoder";
71 
72 #define ALOGV(fmt, ...) \
73  __android_log_vprint(ANDROID_LOG_VERBOSE, ni_log_tag, fmt, ##__VA_ARGS__)
74 #define ALOGD(fmt, ...) \
75  __android_log_vprint(ANDROID_LOG_DEBUG, ni_log_tag, fmt, ##__VA_ARGS__)
76 #define ALOGI(fmt, ...) \
77  __android_log_vprint(ANDROID_LOG_INFO, ni_log_tag, fmt, ##__VA_ARGS__)
78 #define ALOGW(fmt, ...) \
79  __android_log_vprint(ANDROID_LOG_WARN, ni_log_tag, fmt, ##__VA_ARGS__)
80 #define ALOGE(fmt, ...) \
81  __android_log_vprint(ANDROID_LOG_ERROR, ni_log_tag, fmt, ##__VA_ARGS__)
82 #endif
83 
84 
85 /*!*****************************************************************************
86  * \brief Get time for logs with microsecond timestamps
87  *
88  * \param[in/out] p_tp timeval struct
89  * \param[in] p_tzp timezone struct
90  *
91  * \return return 0 for success, -1 for error
92  ******************************************************************************/
93 int32_t ni_log_gettimeofday(struct timeval *p_tp, struct timezone *p_tzp)
94 {
95 #ifdef _WIN32
96  FILETIME file_time;
97  SYSTEMTIME system_time;
98  ULARGE_INTEGER ularge;
100  static const unsigned __int64 epoch =
101  ((unsigned __int64)116444736000000000ULL);
102 
103  // timezone information is stored outside the kernel so tzp isn't used
104  (void)p_tzp;
106  // Note: this function is not a precision timer. See elapsed_time().
107  GetSystemTime(&system_time);
108  SystemTimeToFileTime(&system_time, &file_time);
109  ularge.LowPart = file_time.dwLowDateTime;
110  ularge.HighPart = file_time.dwHighDateTime;
111  // Surpress cppcheck
112  (void)ularge.LowPart;
113  (void)ularge.HighPart;
114  p_tp->tv_sec = (long)((ularge.QuadPart - epoch) / 10000000L);
115  p_tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
116 
117  return 0;
118 #else
119  return gettimeofday(p_tp, p_tzp);
120 #endif
121 }
122 
123 /*!*****************************************************************************
124  * \brief Default ni_log() callback
125  *
126  * \param[in] level log level
127  * \param[in] fmt printf format specifier
128  * \param[in] vl variadric args list
129  *
130  * \return
131  * \note This function doesn't automatically append a newline to the end of
132  * the log message.
133  ******************************************************************************/
134 void ni_log_default_callback(int level, const char* fmt, va_list vl)
135 {
136  if (level <= ni_log_level)
137  {
138 #ifndef _ANDROID
139 #ifdef NI_LOG_TRACE_TIMESTAMPS
140  if (level == NI_LOG_TRACE)
141  {
142  struct timeval tv;
143  ni_log_gettimeofday(&tv, NULL);
144  fprintf(stderr, "[%" PRIu64 "] ", (uint64_t) (tv.tv_sec * 1000000LL + tv.tv_usec));
145  }
146 #endif
147 #endif
148 
149 #ifdef _ANDROID
150  if (level >= NI_LOG_DEBUG)
151  ALOGD(fmt, vl);
152  else if (level == NI_LOG_INFO)
153  ALOGI(fmt, vl);
154  else
155  ALOGE(fmt, vl);
156 #else
157  vfprintf(stderr, fmt, vl);
158 #endif
159  }
160 }
161 
162 /*!*****************************************************************************
163  * \brief Set ni_log() callback
164  *
165  * \param[in] callback
166  *
167  * \return
168  ******************************************************************************/
169 void ni_log_set_callback(void (*log_callback)(int, const char*, va_list))
170 {
171  ni_log_callback = log_callback;
172 }
173 
174 /*!*****************************************************************************
175  * \brief print log message using ni_log_callback
176  *
177  * \param[in] level log level
178  * \param[in] format printf format specifier
179  * \param[in] ... additional arguments
180  *
181  * \return
182  ******************************************************************************/
183 void ni_log(ni_log_level_t level, const char *fmt, ...)
184 {
185  va_list vl;
186 
187  va_start(vl, fmt);
188  if (ni_log_callback)
189  {
190  ni_log_callback(level, fmt, vl);
191  }
192  va_end(vl);
193 }
194 
195 /*!*****************************************************************************
196  * \brief Set ni_log_level
197  *
198  * \param level log level
199  *
200  * \return
201  ******************************************************************************/
203 {
204  ni_log_level = level;
205 }
206 
207 /*!*****************************************************************************
208  * \brief Get ni_log_level
209  *
210  * \return ni_log_level
211  ******************************************************************************/
213 {
214  return ni_log_level;
215 }
216 
217 /*!*****************************************************************************
218  * \brief Convert ffmpeg log level integer to appropriate ni_log_level_t
219  *
220  * \param fflog_level integer representation of FFmpeg log level
221  *
222  * \return ni_log_level
223  ******************************************************************************/
225 {
226  ni_log_level_t converted_ni_log_level = NI_LOG_ERROR;
227  if (fflog_level <= -8)
228  {
229  converted_ni_log_level = NI_LOG_NONE;
230  }
231  else if (fflog_level <= 8)
232  {
233  converted_ni_log_level = NI_LOG_FATAL;
234  }
235  else if (fflog_level <= 16)
236  {
237  converted_ni_log_level = NI_LOG_ERROR;
238  }
239  else if (fflog_level <= 32)
240  {
241  converted_ni_log_level = NI_LOG_INFO;
242  }
243  else if (fflog_level <= 48)
244  {
245  converted_ni_log_level = NI_LOG_DEBUG;
246  }
247  else
248  {
249  converted_ni_log_level = NI_LOG_TRACE;
250  }
251  return converted_ni_log_level;
252 }
253 
254 
255 /*!*****************************************************************************
256  * \brief Convert terminal arg string to ni_log_level_t
257  *
258  * \param log_str character pointer of log level arg in terminal
259  *
260  * \return ni_log_level
261  ******************************************************************************/
263 {
264 #ifdef _WIN32
265  int (*strcicmp) (const char*, const char *) = &_stricmp;
266 #else
267  int (*strcicmp) (const char*, const char *) = &strcasecmp;
268 #endif
269 
270  if (!(*strcicmp)(arg_str, "none"))
271  {
272  return NI_LOG_NONE;
273  } else if (!(*strcicmp)(arg_str, "fatal"))
274  {
275  return NI_LOG_FATAL;
276  } else if (!(*strcicmp)(arg_str, "error"))
277  {
278  return NI_LOG_ERROR;
279  } else if (!(*strcicmp)(arg_str, "info"))
280  {
281  return NI_LOG_INFO;
282  } else if (!(*strcicmp)(arg_str, "debug"))
283  {
284  return NI_LOG_DEBUG;
285  } else if (!(*strcicmp)(arg_str, "trace"))
286  {
287  return NI_LOG_TRACE;
288  } else {
289  return NI_LOG_INVALID;
290  }
291 }
292 
293 #ifdef _ANDROID
294 /*!******************************************************************************
295  * \brief Set ni_log_tag
296  *
297  * \param log tag
298  *
299  * \return
300  *******************************************************************************/
301 void ni_log_set_log_tag(const char *log_tag)
302 {
303  strcpy(ni_log_tag, log_tag);
304  ni_log_tag[strlen(log_tag)] = '\0';
305 }
306 #endif
307 
309 {
310  struct timeval tv;
311  ni_log_gettimeofday(&tv, NULL);
312  return (uint64_t) (tv.tv_sec * 1000000LL + tv.tv_usec);
313 }
314 
315 #ifdef _WIN32
316 static BOOL CALLBACK ni_log2_init_mutex_once_callback(PINIT_ONCE InitOnce,
317  PVOID Parameter,
318  PVOID *Context)
319 {
320  ni_pthread_mutex_init(&ni_log2_mutex);
321  ni_log2_mutex_initialized = 1;
322  return true;
323 }
324 #endif
325 
326 void ni_log2_with_mutex(int on)
327 {
328 #ifdef _WIN32
329  if(!ni_log2_mutex_initialized && on)
330  {
331  InitOnceExecuteOnce(&g_InitOnce_ni_log2_mutex, ni_log2_init_mutex_once_callback, NULL, NULL);
332  }
333 #endif
334  ni_log2_print_with_mutex = on;
335 }
336 
337 void ni_log2(const void *p_context, ni_log_level_t level, const char *fmt, ...)
338 {
339  const ni_session_context_t *p_session_context = (const ni_session_context_t *)p_context;
340 
341  if(level > ni_log_level)
342  {
343  return;
344  }
345 
346  if(ni_log2_print_with_mutex)
347  {
348  ni_pthread_mutex_lock(&ni_log2_mutex);
349 
350  if(p_session_context && level == NI_LOG_ERROR)
351  {
353  p_session_context->session_id, ni_log_get_utime(), p_session_context->E2EID);
354  }
355  else if(p_session_context)
356  {
358  p_session_context->session_id, p_session_context->E2EID);
359  }
360  else if (level == NI_LOG_ERROR)
361  {
363  ni_log_get_utime());
364  }
365 
366  va_list vl;
367  va_start(vl, fmt);
368  if (ni_log_callback)
369  {
370  ni_log_callback(level, fmt, vl);
371  }
372  va_end(vl);
373 
374  ni_pthread_mutex_unlock(&ni_log2_mutex);
375  }
376  else
377  {
378  if(!p_session_context && level != NI_LOG_ERROR)
379  {
380  va_list vl;
381  va_start(vl, fmt);
382  if (ni_log_callback)
383  {
384  ni_log_callback(level, fmt, vl);
385  }
386  va_end(vl);
387 
388  return;
389  }
390 
391  char printbuf[NI_LOG2_PRINT_BUFF_SIZE];
392  // int used_size = 0;
393  // size_t free_size = NI_LOG2_PRINT_BUFF_SIZE;
394  int this_used_size = 0;
395 
396  if(p_session_context && level == NI_LOG_ERROR)
397  {
398  this_used_size = snprintf(printbuf, NI_LOG2_PRINT_BUFF_SIZE,
400  p_session_context->session_id, ni_log_get_utime(), p_session_context->E2EID, fmt);
401  }
402  else if(p_session_context)
403  {
404  this_used_size = snprintf(printbuf, NI_LOG2_PRINT_BUFF_SIZE,
406  p_session_context->session_id, p_session_context->E2EID, fmt);
407  }
408  else if (level == NI_LOG_ERROR)
409  {
410  this_used_size = snprintf(printbuf, NI_LOG2_PRINT_BUFF_SIZE,
412  ni_log_get_utime(), fmt);
413  }
414 
415  if(this_used_size < 0)
416  {
417  ni_log(NI_LOG_ERROR,"ni_log2: an error occurd in snprintf\n");
418 
419  va_list vl;
420  va_start(vl, fmt);
421  if (ni_log_callback)
422  {
423  ni_log_callback(level, fmt, vl);
424  }
425  va_end(vl);
426 
427  return;
428  }
429 
430  if(this_used_size >= NI_LOG2_PRINT_BUFF_SIZE)
431  {
432  ni_log(NI_LOG_ERROR,"ni_log2: too many characters for output\n");
433 
434  va_list vl;
435  va_start(vl, fmt);
436  if (ni_log_callback)
437  {
438  ni_log_callback(level, fmt, vl);
439  }
440  va_end(vl);
441 
442  return;
443  }
444 
445  va_list vl;
446  va_start(vl, fmt);
447  if (ni_log_callback)
448  {
449  ni_log_callback(level, printbuf, vl);
450  }
451  va_end(vl);
452 
453  }
454 }
ni_log_default_callback
void ni_log_default_callback(int level, const char *fmt, va_list vl)
Default ni_log() callback.
Definition: ni_log.c:134
NI_LOG_FATAL
@ NI_LOG_FATAL
Definition: ni_log.h:59
ni_pthread_mutex_unlock
int ni_pthread_mutex_unlock(ni_pthread_mutex_t *mutex)
thread mutex unlock
Definition: ni_util.c:4083
ni_log_level_t
ni_log_level_t
Definition: ni_log.h:55
ff_to_ni_log_level
ni_log_level_t ff_to_ni_log_level(int fflog_level)
Convert ffmpeg log level integer to appropriate ni_log_level_t.
Definition: ni_log.c:224
NI_LOG2_SESSION_ID_TIMESTAMP_FMT
#define NI_LOG2_SESSION_ID_TIMESTAMP_FMT
Definition: ni_log.c:58
_ni_session_context::session_id
uint32_t session_id
Definition: ni_device_api.h:1480
ni_log_set_level
void ni_log_set_level(ni_log_level_t level)
Set ni_log_level.
Definition: ni_log.c:202
ni_log_get_level
ni_log_level_t ni_log_get_level(void)
Get ni_log_level.
Definition: ni_log.c:212
NI_LOG2_SPACE
#define NI_LOG2_SPACE
Definition: ni_log.c:63
NI_LOG2_PRINT_BUFF_SIZE
#define NI_LOG2_PRINT_BUFF_SIZE
Definition: ni_log.c:65
ni_log_gettimeofday
int32_t ni_log_gettimeofday(struct timeval *p_tp, struct timezone *p_tzp)
Get time for logs with microsecond timestamps.
Definition: ni_log.c:93
ni_log.h
Logging definitions.
NI_LOG2_FMT_FMT
#define NI_LOG2_FMT_FMT
Definition: ni_log.c:62
NI_LOG_INFO
@ NI_LOG_INFO
Definition: ni_log.h:61
arg_to_ni_log_level
ni_log_level_t arg_to_ni_log_level(const char *arg_str)
Convert terminal arg string to ni_log_level_t.
Definition: ni_log.c:262
ni_log2_with_mutex
void ni_log2_with_mutex(int on)
set whether to use a lock or not in ni_log2
Definition: ni_log.c:326
NI_LOG_ERROR
@ NI_LOG_ERROR
Definition: ni_log.h:60
ni_defs.h
Common NETINT definitions used by all modules.
NI_LOG_TRACE
@ NI_LOG_TRACE
Definition: ni_log.h:63
ni_pthread_mutex_lock
int ni_pthread_mutex_lock(ni_pthread_mutex_t *mutex)
thread mutex lock
Definition: ni_util.c:4057
ni_log
void ni_log(ni_log_level_t level, const char *fmt,...)
print log message using ni_log_callback
Definition: ni_log.c:183
NI_LOG_INVALID
@ NI_LOG_INVALID
Definition: ni_log.h:57
_ni_session_context::E2EID
char E2EID[128]
Definition: ni_device_api.h:1703
ni_log_set_callback
void ni_log_set_callback(void(*log_callback)(int, const char *, va_list))
Set ni_log() callback.
Definition: ni_log.c:169
_ni_session_context
Definition: ni_device_api.h:1408
ni_pthread_mutex_init
int ni_pthread_mutex_init(ni_pthread_mutex_t *mutex)
initialize a mutex
Definition: ni_util.c:4001
NI_LOG2_TIMESTAMP_FMT
#define NI_LOG2_TIMESTAMP_FMT
Definition: ni_log.c:59
ni_log2
void ni_log2(const void *p_context, ni_log_level_t level, const char *fmt,...)
print log message and additional information using ni_log_callback,
Definition: ni_log.c:337
NI_LOG2_E2EID_FMT
#define NI_LOG2_E2EID_FMT
Definition: ni_log.c:61
NI_LOG2_SESSION_ID_FMT
#define NI_LOG2_SESSION_ID_FMT
Definition: ni_log.c:60
ni_device_api.h
Public definitions for operating NETINT video processing devices for video processing.
NI_LOG_NONE
@ NI_LOG_NONE
Definition: ni_log.h:58
ni_util.h
Utility definitions.
ni_log_get_utime
uint64_t ni_log_get_utime()
Get time for logs with microsecond timestamps.
Definition: ni_log.c:308
NI_LOG_DEBUG
@ NI_LOG_DEBUG
Definition: ni_log.h:62