libxcoder  5.4.0
ni_util.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_util.c
24  *
25  * \brief Utility definitions
26  ******************************************************************************/
27 
28 #if __linux__ || __APPLE__
29 #include <sys/ioctl.h>
30 #include <sys/stat.h>
31 #include <sys/ioctl.h>
32 #include <sys/mman.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #endif
38 
39 #include "ni_nvme.h"
40 #include "ni_util.h"
41 
42 typedef struct _ni_err_rc_txt_entry
43 {
45  const char *txt;
47 
48 static const ni_err_rc_txt_entry_t ni_err_rc_description[] = {
49  {NI_RETCODE_SUCCESS, "SUCCESS"},
50  {NI_RETCODE_FAILURE, "FAILURE"},
51  {NI_RETCODE_INVALID_PARAM, "INVALID_PARAM"},
52  {NI_RETCODE_ERROR_MEM_ALOC, "ERROR_MEM_ALOC"},
53  {NI_RETCODE_ERROR_NVME_CMD_FAILED, "ERROR_NVME_CMD_FAILED"},
54  {NI_RETCODE_ERROR_INVALID_SESSION, "ERROR_INVALID_SESSION"},
55  {NI_RETCODE_ERROR_RESOURCE_UNAVAILABLE, "ERROR_RESOURCE_UNAVAILABLE"},
56  {NI_RETCODE_PARAM_INVALID_NAME, "PARAM_INVALID_NAME"},
57  {NI_RETCODE_PARAM_INVALID_VALUE, "PARAM_INVALID_VALUE"},
58  {NI_RETCODE_PARAM_ERROR_FRATE, "PARAM_ERROR_FRATE"},
59  {NI_RETCODE_PARAM_ERROR_BRATE, "PARAM_ERROR_BRATE"},
60  {NI_RETCODE_PARAM_ERROR_TRATE, "PARAM_ERROR_TRATE"},
61  {NI_RETCODE_PARAM_ERROR_VBV_BUFFER_SIZE, "PARAM_ERROR_VBV_BUFFER_SIZE"},
62  {NI_RETCODE_PARAM_ERROR_INTRA_PERIOD, "PARAM_ERROR_INTRA_PERIOD"},
63  {NI_RETCODE_PARAM_ERROR_INTRA_QP, "PARAM_ERROR_INTRA_QP"},
64  {NI_RETCODE_PARAM_ERROR_GOP_PRESET, "PARAM_ERROR_GOP_PRESET"},
65  {NI_RETCODE_PARAM_ERROR_CU_SIZE_MODE, "PARAM_ERROR_CU_SIZE_MODE"},
66  {NI_RETCODE_PARAM_ERROR_MX_NUM_MERGE, "PARAM_ERROR_MX_NUM_MERGE"},
67  {NI_RETCODE_PARAM_ERROR_DY_MERGE_8X8_EN, "PARAM_ERROR_DY_MERGE_8X8_EN"},
68  {NI_RETCODE_PARAM_ERROR_DY_MERGE_16X16_EN, "PARAM_ERROR_DY_MERGE_16X16_EN"},
69  {NI_RETCODE_PARAM_ERROR_DY_MERGE_32X32_EN, "PARAM_ERROR_DY_MERGE_32X32_EN"},
70  {NI_RETCODE_PARAM_ERROR_CU_LVL_RC_EN, "PARAM_ERROR_CU_LVL_RC_EN"},
71  {NI_RETCODE_PARAM_ERROR_HVS_QP_EN, "PARAM_ERROR_HVS_QP_EN"},
72  {NI_RETCODE_PARAM_ERROR_HVS_QP_SCL, "PARAM_ERROR_HVS_QP_SCL"},
73  {NI_RETCODE_PARAM_ERROR_MN_QP, "PARAM_ERROR_MN_QP"},
74  {NI_RETCODE_PARAM_ERROR_MX_QP, "PARAM_ERROR_MX_QP"},
75  {NI_RETCODE_PARAM_ERROR_MX_DELTA_QP, "PARAM_ERROR_MX_DELTA_QP"},
76  {NI_RETCODE_PARAM_ERROR_CONF_WIN_TOP, "PARAM_ERROR_CONF_WIN_TOP"},
77  {NI_RETCODE_PARAM_ERROR_CONF_WIN_BOT, "PARAM_ERROR_CONF_WIN_BOT"},
78  {NI_RETCODE_PARAM_ERROR_CONF_WIN_L, "PARAM_ERROR_CONF_WIN_L"},
79  {NI_RETCODE_PARAM_ERROR_CONF_WIN_R, "PARAM_ERROR_CONF_WIN_R"},
80  {NI_RETCODE_PARAM_ERROR_USR_RMD_ENC_PARAM, "PARAM_ERROR_USR_RMD_ENC_PARAM"},
81  {NI_RETCODE_PARAM_ERROR_BRATE_LT_TRATE, "PARAM_ERROR_BRATE_LT_TRATE"},
82  {NI_RETCODE_PARAM_ERROR_RCENABLE, "PARAM_ERROR_RCENABLE"},
83  {NI_RETCODE_PARAM_ERROR_MAXNUMMERGE, "PARAM_ERROR_MAXNUMMERGE"},
84  {NI_RETCODE_PARAM_ERROR_CUSTOM_GOP, "PARAM_ERROR_CUSTOM_GOP"},
85  {NI_RETCODE_PARAM_ERROR_PIC_WIDTH, "PARAM_ERROR_PIC_WIDTH"},
86  {NI_RETCODE_PARAM_ERROR_PIC_HEIGHT, "PARAM_ERROR_PIC_HEIGHT"},
87  {NI_RETCODE_PARAM_ERROR_DECODING_REFRESH_TYPE, "PARAM_ERROR_DECODING_REFRESH_TYPE"},
88  {NI_RETCODE_PARAM_ERROR_CUSIZE_MODE_8X8_EN, "PARAM_ERROR_CUSIZE_MODE_8X8_EN"},
89  {NI_RETCODE_PARAM_ERROR_CUSIZE_MODE_16X16_EN, "PARAM_ERROR_CUSIZE_MODE_16X16_EN"},
90  {NI_RETCODE_PARAM_ERROR_CUSIZE_MODE_32X32_EN, "PARAM_ERROR_CUSIZE_MODE_32X32_EN"},
91  {NI_RETCODE_PARAM_ERROR_TOO_BIG, "PARAM_ERROR_TOO_BIG"},
92  {NI_RETCODE_PARAM_ERROR_TOO_SMALL, "PARAM_ERROR_TOO_SMALL"},
93  {NI_RETCODE_PARAM_ERROR_ZERO, "PARAM_ERROR_ZERO"},
94  {NI_RETCODE_PARAM_ERROR_OOR, "PARAM_ERROR_OOR"},
95  {NI_RETCODE_PARAM_ERROR_WIDTH_TOO_BIG, "PARAM_ERROR_WIDTH_TOO_BIG"},
96  {NI_RETCODE_PARAM_ERROR_WIDTH_TOO_SMALL, "PARAM_ERROR_WIDTH_TOO_SMALL"},
97  {NI_RETCODE_PARAM_ERROR_HEIGHT_TOO_BIG, "PARAM_ERROR_HEIGHT_TOO_BIG"},
98  {NI_RETCODE_PARAM_ERROR_HEIGHT_TOO_SMALL, "PARAM_ERROR_HEIGHT_TOO_SMALL"},
99  {NI_RETCODE_PARAM_ERROR_AREA_TOO_BIG, "PARAM_ERROR_AREA_TOO_BIG"},
100  {NI_RETCODE_ERROR_EXCEED_MAX_NUM_SESSIONS, "ERROR_EXCEED_MAX_NUM_SESSIONS"},
101  {NI_RETCODE_ERROR_GET_DEVICE_POOL, "ERROR_GET_DEVICE_POOL"},
102  {NI_RETCODE_ERROR_LOCK_DOWN_DEVICE, "ERROR_LOCK_DOWN_DEVICE"},
103  {NI_RETCODE_ERROR_UNLOCK_DEVICE, "ERROR_UNLOCK_DEVICE"},
104  {NI_RETCODE_ERROR_OPEN_DEVICE, "ERROR_OPEN_DEVICE"},
105  {NI_RETCODE_ERROR_INVALID_HANDLE, "ERROR_INVALID_HANDLE"},
106  {NI_RETCODE_ERROR_INVALID_ALLOCATION_METHOD, "ERROR_INVALID_ALLOCATION_METHOD"},
107  {NI_RETCODE_ERROR_VPU_RECOVERY, "ERROR_VPU_RECOVERY"},
108  {NI_RETCODE_ERROR_STREAM_ERROR, "ERROR_STREAM_ERROR"},
109 
110  {NI_RETCODE_PARAM_WARNING_DEPRECATED, "PARAM_WARNING_DEPRECATED"},
111  {NI_RETCODE_PARAM_ERROR_LOOK_AHEAD_DEPTH, "PARAM_ERROR_LOOK_AHEAD_DEPTH"},
112  {NI_RETCODE_PARAM_ERROR_FILLER, "PARAM_ERROR_FILLER"},
113  {NI_RETCODE_PARAM_ERROR_PICSKIP, "PARAM_ERROR_PICSKIP"},
114 
115  {NI_RETCODE_PARAM_WARN, "PARAM_WARN"},
116 
117  {NI_RETCODE_NVME_SC_WRITE_BUFFER_FULL, "NVME_SC_WRITE_BUFFER_FULL"},
118  {NI_RETCODE_NVME_SC_RESOURCE_UNAVAILABLE, "NVME_SC_RESOURCE_UNAVAILABLE"},
119  {NI_RETCODE_NVME_SC_RESOURCE_IS_EMPTY, "NVME_SC_RESOURCE_IS_EMPTY"},
120  {NI_RETCODE_NVME_SC_RESOURCE_NOT_FOUND, "NVME_SC_RESOURCE_NOT_FOUND"},
121  {NI_RETCODE_NVME_SC_REQUEST_NOT_COMPLETED, "NVME_SC_REQUEST_NOT_COMPLETED"},
122  {NI_RETCODE_NVME_SC_REQUEST_IN_PROGRESS, "NVME_SC_REQUEST_IN_PROGRESS"},
123  {NI_RETCODE_NVME_SC_INVALID_PARAMETER, "NVME_SC_INVALID_PARAMETER"},
124  {NI_RETCODE_NVME_SC_STREAM_ERROR, "NVME_SC_STREAM_ERROR"},
125  {NI_RETCODE_NVME_SC_INTERLACED_NOT_SUPPORTED, "NVME_SC_INTERLACED_NOT_SUPPORTED"},
126  {NI_RETCODE_NVME_SC_VPU_RECOVERY, "NVME_SC_VPU_RECOVERY"},
127  {NI_RETCODE_NVME_SC_VPU_RSRC_INSUFFICIENT, "NVME_SC_VPU_RSRC_INSUFFICIENT"},
128  {NI_RETCODE_NVME_SC_VPU_GENERAL_ERROR, "NVME_SC_VPU_GENERAL_ERROR"},
129 };
130 
131 /*!*****************************************************************************
132  * \brief Get time for logs with microsecond timestamps
133  *
134  * \param[in/out] p_tp timeval struct
135  * \param[in] p_tzp void *
136  *
137  * \return return 0 for success, -1 for error
138  ******************************************************************************/
139 int32_t ni_gettimeofday(struct timeval *p_tp, void *p_tzp)
140 {
141 #ifdef _WIN32
142  FILETIME file_time;
143  SYSTEMTIME system_time;
144  ULARGE_INTEGER ularge;
146  static const unsigned __int64 epoch =
147  ((unsigned __int64)116444736000000000ULL);
148 
149  // timezone information is stored outside the kernel so tzp isn't used
150  (void *)p_tzp;
152  // Note: this function is not a precision timer. See elapsed_time().
153  GetSystemTime(&system_time);
154  SystemTimeToFileTime(&system_time, &file_time);
155  ularge.LowPart = file_time.dwLowDateTime;
156  ularge.HighPart = file_time.dwHighDateTime;
157  // Surpress cppcheck
158  (void)ularge.LowPart;
159  (void)ularge.HighPart;
160  p_tp->tv_sec = (long)((ularge.QuadPart - epoch) / 10000000L);
161  p_tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
162 
163  return 0;
164 #else
165  return gettimeofday(p_tp, p_tzp);
166 #endif
167 }
168 
169 uint32_t ni_round_up(uint32_t number_to_round, uint32_t multiple)
170 {
171  if (0 == multiple)
172  {
173  return number_to_round;
174  }
175 
176  uint32_t remainder = number_to_round % multiple;
177  if (0 == remainder)
178  {
179  return number_to_round;
180  }
181 
182  return (number_to_round + multiple - remainder);
183 }
184 
185 /*!*****************************************************************************
186  * \brief Allocate aligned memory
187  *
188  * \param[in/out] memptr The address of the allocated memory will be a
189  * multiple of alignment, which must be a power of two
190  * and a multiple of sizeof(void *). If size is 0, then
191  * the value placed is either NULL, or a unique pointer
192  * value that can later be successfully passed to free.
193  * \param[in] alignment The alignment value of the allocated value.
194  * \param[in] size The allocated memory size.
195  *
196  * \return 0 for success, ENOMEM for error
197  ******************************************************************************/
198 int ni_posix_memalign(void **memptr, size_t alignment, size_t size)
199 {
200 #ifdef _WIN32
201  *memptr = _aligned_malloc(size, alignment);
202  if (NULL == *memptr)
203  {
204  return ENOMEM;
205  } else
206  {
207  ZeroMemory(*memptr, size);
208  return 0;
209  }
210 #else
211  return posix_memalign(memptr, alignment, size);
212 #endif
213 }
214 
215 #ifdef __linux__
216 /*!******************************************************************************
217  * \brief Get max io transfer size from the kernel
218  *
219  * \param
220  *
221  * \return
222  *******************************************************************************/
223 uint32_t ni_get_kernel_max_io_size(const char * p_dev)
224 {
225  FILE *p_file = NULL; /* file pointer*/
226  char file_name[KERNEL_NVME_FILE_NAME_MAX_SZ];
227  int max_segments = 0, min_io_size = 0, max_hw_sectors_kb = 0;
228  uint32_t io_size = DEFAULT_IO_TRANSFER_SIZE;
229  size_t len = 0;
230  int err = 0;
231 
232  memset(file_name, 0, KERNEL_NVME_FILE_NAME_MAX_SZ);
233 
234  if (!p_dev)
235  {
236  ni_log(NI_LOG_ERROR, "Invalid Arguments\n");
237  LRETURN;
238  }
239 
240  len = strlen(p_dev) - 5;
241  if (len < MIN_NVME_DEV_NAME_LEN)
242  {
243  ni_log(NI_LOG_DEBUG, "p_dev length is %zu\n", len);
244  LRETURN;
245  }
246 
247  // Get Max number of segments from /sys
248  memset(file_name, 0, sizeof(file_name));
249  ni_strcpy(file_name, KERNEL_NVME_FILE_NAME_MAX_SZ, SYS_PARAMS_PREFIX_PATH);
250 #if defined(_ANDROID) || defined(__OPENHARMONY__)
251  //start from 11 chars ahead to not copy the "/dev/block/" since we only need whats after it
252  ni_strncat(file_name, KERNEL_NVME_FILE_NAME_MAX_SZ, (char *)(p_dev + 11), sizeof(file_name) - SYS_PREFIX_SZ);
253 #else
254  //start from 5 chars ahead to not copy the "/dev/" since we only need whats after it
255  ni_strncat(file_name, KERNEL_NVME_FILE_NAME_MAX_SZ, (char *)(p_dev + 5), sizeof(file_name) - SYS_PREFIX_SZ);
256 #endif
257  ni_strncat(file_name, KERNEL_NVME_FILE_NAME_MAX_SZ, KERNEL_NVME_MAX_SEG_PATH,
258  sizeof(file_name) - SYS_PREFIX_SZ - len);
259  ni_log(NI_LOG_DEBUG, "file_name is %s\n", file_name);
260  ni_fopen(&p_file, file_name, "r");
261  if (!p_file)
262  {
263  ni_log(NI_LOG_ERROR, "file_name failed to open: %s\n", file_name);
264  LRETURN;
265  }
266 
267  err = ni_fscanf(p_file, "%d", &max_segments);
268  if (EOF == err)
269  {
270  ni_log(NI_LOG_ERROR, "fscanf failed on: %s max_segments\n", file_name);
271  LRETURN;
272  }
273 
274  fclose(p_file);
275  p_file = NULL;
276  // Get Max segment size from /sys
277  memset(file_name, 0, sizeof(file_name));
278  ni_strcpy(file_name, KERNEL_NVME_FILE_NAME_MAX_SZ, SYS_PARAMS_PREFIX_PATH);
279 #if defined(_ANDROID) || defined(__OPENHARMONY__)
280  //start from 11 chars ahead to not copy the "/dev/block/" since we only need whats after it
281  ni_strncat(file_name, KERNEL_NVME_FILE_NAME_MAX_SZ, (char *)(p_dev + 11), sizeof(file_name) - SYS_PREFIX_SZ);
282 #else
283  //start from 5 chars ahead to not copy the "/dev/" since we only need whats after it
284  ni_strncat(file_name, KERNEL_NVME_FILE_NAME_MAX_SZ, (char *)(p_dev + 5), sizeof(file_name) - SYS_PREFIX_SZ);
285 #endif
286  ni_strncat(file_name, KERNEL_NVME_FILE_NAME_MAX_SZ, KERNEL_NVME_MIN_IO_SZ_PATH,
287  sizeof(file_name) - SYS_PREFIX_SZ - len);
288  ni_log(NI_LOG_DEBUG, "file_name is %s\n", file_name);
289  ni_fopen(&p_file, file_name, "r");
290  if (!p_file)
291  {
292  ni_log(NI_LOG_ERROR, "file_name failed to open: %s\n", file_name);
293  LRETURN;
294  }
295 
296  err = ni_fscanf(p_file, "%d", &min_io_size);
297  if (EOF == err)
298  {
299  ni_log(NI_LOG_ERROR, "fscanf failed on: %s min_io_size\n", file_name);
300  LRETURN;
301  }
302 
303  fclose(p_file);
304  p_file = NULL;
305  //Now get max_hw_sectors_kb
306  memset(file_name, 0, sizeof(file_name));
307  ni_strcpy(file_name, KERNEL_NVME_FILE_NAME_MAX_SZ, SYS_PARAMS_PREFIX_PATH);
308 #if defined(_ANDROID) || defined(__OPENHARMONY__)
309  //start from 11 chars ahead to not copy the "/dev/block/" since we only need whats after it
310  ni_strncat(file_name, KERNEL_NVME_FILE_NAME_MAX_SZ, (char *)(p_dev + 11), sizeof(file_name) - SYS_PREFIX_SZ);
311 #else
312  //start from 5 chars ahead to not copy the "/dev/" since we only need whats after it
313  ni_strncat(file_name, KERNEL_NVME_FILE_NAME_MAX_SZ, (char *)(p_dev + 5), sizeof(file_name) - SYS_PREFIX_SZ);
314 #endif
315  ni_strncat(file_name, KERNEL_NVME_FILE_NAME_MAX_SZ, KERNEL_NVME_MAX_HW_SEC_KB_PATH,
316  sizeof(file_name) - SYS_PREFIX_SZ - len);
317  ni_log(NI_LOG_DEBUG, "file_name is %s\n", file_name);
318  ni_fopen(&p_file, file_name, "r");
319  if (!p_file)
320  {
321  ni_log(NI_LOG_ERROR, "file_name failed to open: %s\n", file_name);
322  LRETURN;
323  }
324 
325  err = ni_fscanf(p_file, "%d", &max_hw_sectors_kb);
326  if (EOF == err)
327  {
328  ni_log(NI_LOG_ERROR, "fscanf failed on: %s min_io_size\n", file_name);
329  LRETURN;
330  }
331 
332  if (ni_min(min_io_size * max_segments, max_hw_sectors_kb * 1024) >
333  MAX_IO_TRANSFER_SIZE)
334  {
335  io_size = MAX_IO_TRANSFER_SIZE;
336  //ni_log(NI_LOG_INFO, "max_io_size is set to: %d because its bigger than maximum limit of: %d\n",io_size, MAX_IO_TRANSFER_SIZE);
337  } else
338  {
339  io_size = ni_min(min_io_size * max_segments, max_hw_sectors_kb * 1024);
340  }
341 
342  // ni_log(NI_LOG_INFO, "\nMAX NVMe IO Size of %d was calculated for this platform and will
343  // be used unless overwritten by user settings\n",io_size);
344  fflush(stdout);
345 
346 END:
347 
348  if (p_file)
349  {
350  fclose(p_file);
351  }
352 
353  return io_size;
354 }
355 
356 #endif
357 
358 void ni_usleep(int64_t usec)
359 {
360 #ifdef _WIN32
361  if (usec < 5000) //this will be more accurate when less than 5000
362  {
363  LARGE_INTEGER StartCount;
364  LARGE_INTEGER StopCount;
365  LARGE_INTEGER Frequency;
366  QueryPerformanceCounter(&StartCount);
367  QueryPerformanceFrequency(&Frequency);
368  StopCount.QuadPart =
369  StartCount.QuadPart + usec * (Frequency.QuadPart / 1000000);
370  do
371  {
372  QueryPerformanceCounter(&StartCount);
373  } while (StartCount.QuadPart < StopCount.QuadPart);
374  } else
375  {
376  HANDLE timer = NULL;
377  LARGE_INTEGER ft = {0};
378  BOOL retval;
379 
380  ft.QuadPart = -(
381  10 *
382  usec); // Convert to 100 nanosecond interval, negative value indicates relative time
383 
384  timer = CreateWaitableTimer(NULL, TRUE, NULL);
385  if (NULL != timer)
386  {
387  retval = SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
388  if (retval)
389  {
390  WaitForSingleObject(timer, INFINITE);
391  }
392  CloseHandle(timer);
393  } else
394  {
395  ni_log(NI_LOG_ERROR, "failed to create waitable timer\n");
396  LARGE_INTEGER StartCount;
397  LARGE_INTEGER StopCount;
398  LARGE_INTEGER Frequency;
399  QueryPerformanceCounter(&StartCount);
400  QueryPerformanceFrequency(&Frequency);
401  StopCount.QuadPart =
402  StartCount.QuadPart + usec * (Frequency.QuadPart / 1000000);
403  do
404  {
405  QueryPerformanceCounter(&StartCount);
406  } while (StartCount.QuadPart < StopCount.QuadPart);
407  }
408  }
409 #else
410  if (usec < 0xFFFFFFFF) // to avoid overflow
411  {
412  usleep(usec);
413  } else
414  {
415  sleep(usec >> 32);
416  }
417 #endif
418 }
419 
420 char *ni_strtok(char *s, const char *delim, char **saveptr)
421 {
422  char *tok;
423 
424  if (!s && !(s = *saveptr))
425  return NULL;
426 
427  /* skip leading delimiters */
428  s += strspn(s, delim);
429 
430  /* s now points to the first non delimiter char, or to the end of the string */
431  if (!*s) {
432  *saveptr = NULL;
433  return NULL;
434  }
435  tok = s++;
436 
437  /* skip non delimiters */
438  s += strcspn(s, delim);
439  if (*s) {
440  *s = '\0';
441  *saveptr = s+1;
442  } else {
443  *saveptr = NULL;
444  }
445 
446  return tok;
447 }
448 
449 ni_retcode_t ni_strcpy(char *dest, size_t dmax, const char *src)
450 {
451 #if defined(_MSC_VER)
452  if(strcpy_s(dest, dmax, src))
453  return NI_RETCODE_FAILURE;
454  else
455  return NI_RETCODE_SUCCESS;
456 #else
457  if (!dest || !dmax || !src)
459 
460  if (dest == src)
461  return NI_RETCODE_SUCCESS;
462 
463  size_t orig_dmax;
464  char *orig_dest;
465  const char *overlap_bumper;
466  /* hold base of dest in case src was not copied */
467  orig_dmax = dmax;
468  orig_dest = dest;
469 
470  if (dest < src) {
471  overlap_bumper = src;
472  while (dmax > 0) {
473  if (dest == overlap_bumper) {
474  (void)orig_dmax;
475  *orig_dest = '\0';
476  return NI_RETCODE_FAILURE;
477  }
478  *dest = *src;
479  if (*dest == '\0') {
480  return NI_RETCODE_SUCCESS;
481  }
482  dmax--;
483  dest++;
484  src++;
485  }
486  } else {
487  overlap_bumper = dest;
488  while (dmax > 0) {
489  if (src == overlap_bumper) {
490  (void)orig_dmax;
491  *orig_dest = '\0';
492  return NI_RETCODE_FAILURE;
493  }
494  *dest = *src;
495  if (*dest == '\0') {
496  return NI_RETCODE_SUCCESS;
497  }
498  dmax--;
499  dest++;
500  src++;
501  }
502  }
503 
504  /*
505  * the entire src must have been copied, if not reset dest
506  * to null the string.
507  */
508  (void)orig_dmax;
509  *orig_dest = '\0';
510  return NI_RETCODE_FAILURE;
511 #endif
512 }
513 
514 ni_retcode_t ni_strncpy(char *dest, size_t dmax,
515  const char *src, size_t slen)
516 {
517 #if defined(_MSC_VER)
518  if(strncpy_s(dest, dmax, src, slen))
519  return NI_RETCODE_FAILURE;
520  else
521  return NI_RETCODE_SUCCESS;
522 #else
523  if (slen == 0 && dest && dmax) {
524  *dest = '\0';
525  return NI_RETCODE_SUCCESS;
526  }
527 
528  if (!dest || !dmax || !src)
530  size_t orig_dmax;
531  char *orig_dest;
532  const char *overlap_bumper;
533  /* hold base in case src was not copied */
534  orig_dmax = dmax;
535  orig_dest = dest;
536 
537  if (dest < src) {
538  overlap_bumper = src;
539 
540  while (dmax > 0) {
541  if (dest == overlap_bumper) {
542  (void)orig_dmax;
543  *orig_dest = '\0';
544  return NI_RETCODE_FAILURE;
545  }
546 
547  if (slen == 0) {
548  /*
549  * Copying truncated to slen chars. Note that the TR says to
550  * copy slen chars plus the NUL char. We zero the slack.
551  */
552 #ifdef SAFECLIB_STR_NULL_SLACK
553  if (dmax > 0x20)
554  memset(dest, 0, dmax);
555  else {
556  while (dmax) {
557  *dest = '\0';
558  dmax--;
559  dest++;
560  }
561  }
562 #else
563  *dest = '\0';
564 #endif
565  return NI_RETCODE_SUCCESS;
566  }
567 
568  *dest = *src;
569  if (*dest == '\0') {
570 #ifdef SAFECLIB_STR_NULL_SLACK
571  if (dmax > 0x20)
572  memset(dest, 0, dmax);
573  else {
574  while (dmax) {
575  *dest = '\0';
576  dmax--;
577  dest++;
578  }
579  }
580 #endif
581  return NI_RETCODE_SUCCESS;
582  }
583 
584  dmax--;
585  slen--;
586  dest++;
587  src++;
588  }
589  } else {
590  overlap_bumper = dest;
591 
592  while (dmax > 0) {
593  if (src == overlap_bumper) {
594  (void)orig_dmax;
595  *orig_dest = '\0';
596  return NI_RETCODE_FAILURE;
597  }
598 
599  if (slen == 0) {
600  /*
601  * Copying truncated to slen chars. Note that the TR says to
602  * copy slen chars plus the NUL char. We zero the slack.
603  */
604 #ifdef SAFECLIB_STR_NULL_SLACK
605  if (dmax > 0x20)
606  memset(dest, 0, dmax);
607  else {
608  while (dmax) {
609  *dest = '\0';
610  dmax--;
611  dest++;
612  }
613  }
614 #else
615  *dest = '\0';
616 #endif
617  return NI_RETCODE_SUCCESS;
618  }
619 
620  *dest = *src;
621  if (*dest == '\0') {
622 #ifdef SAFECLIB_STR_NULL_SLACK
623  if (dmax > 0x20)
624  memset(dest, 0, dmax);
625  else {
626  while (dmax) {
627  *dest = '\0';
628  dmax--;
629  dest++;
630  }
631  }
632 #endif
633  return NI_RETCODE_SUCCESS;
634  }
635 
636  dmax--;
637  slen--;
638  dest++;
639  src++;
640  }
641  }
642 
643  /*
644  * the entire src was not copied, so zero the string
645  */
646  (void)orig_dmax;
647  *orig_dest = '\0';
648  return NI_RETCODE_FAILURE;
649 #endif
650 }
651 
652 ni_retcode_t ni_strerror(char *dest, size_t dmax, int errnum)
653 {
654 #if defined(_MSC_VER)
655  if(strerror_s(dest, dmax, errnum))
656  return NI_RETCODE_FAILURE;
657  else
658  return NI_RETCODE_SUCCESS;
659 #else
660  if (!dest || !dmax || (dmax >= (size_t)(-1)))
662 #if 1
663  const char *tmpbuf = strerror(errnum);
664  ni_strcpy(dest, dmax, tmpbuf);
665 #else
666  /* strerrorlen_s is supported since c11 */
667  size_t len;
668  len = strerrorlen_s(errnum);
669  if (len < dmax) {
670  const char *tmpbuf = strerror(errnum);
671  ni_strcpy(dest, dmax, tmpbuf);
672  } else if (dmax > 3) { /* truncate */
673  const char *tmpbuf = strerror(errnum);
674  ni_strncpy(dest, dmax, tmpbuf, dmax - 4);
675  ni_strcat(dest, dmax, "...");
676  } else {
678  }
679 #endif
680 
681  return NI_RETCODE_SUCCESS;
682 #endif
683 }
684 
685 ni_retcode_t ni_strcat(char *dest, size_t dmax, const char *src)
686 {
687 #if defined(_MSC_VER)
688  if(strcat_s(dest, dmax, src))
689  return NI_RETCODE_FAILURE;
690  else
691  return NI_RETCODE_SUCCESS;
692 #else
693  if (!dest || !dmax || !src)
695 
696  size_t orig_dmax;
697  char *orig_dest;
698  const char *overlap_bumper;
699  /* hold base of dest in case src was not copied */
700  orig_dmax = dmax;
701  orig_dest = dest;
702 
703  if (dest < src) {
704  overlap_bumper = src;
705  /* Find the end of dest */
706  while (*dest != '\0') {
707  if (dest == overlap_bumper) {
708  (void)orig_dmax;
709  *orig_dest = '\0';
710  return NI_RETCODE_FAILURE;
711  }
712  dest++;
713  dmax--;
714  if (dmax == 0) {
715  (void)orig_dmax;
716  *orig_dest = '\0';
717  return NI_RETCODE_FAILURE;
718  }
719  }
720 
721  while (dmax > 0) {
722  if (dest == overlap_bumper) {
723  (void)orig_dmax;
724  *orig_dest = '\0';
725  return NI_RETCODE_FAILURE;
726  }
727 
728  *dest = *src;
729  if (*dest == '\0') {
730 #ifdef SAFECLIB_STR_NULL_SLACK
731  if (dmax > 0x20)
732  memset(dest, 0, dmax);
733  else {
734  while (dmax) {
735  *dest = '\0';
736  dmax--;
737  dest++;
738  }
739  }
740 #endif
741  return NI_RETCODE_SUCCESS;
742  }
743 
744  dmax--;
745  dest++;
746  src++;
747  }
748  } else {
749  overlap_bumper = dest;
750 
751  /* Find the end of dest */
752  while (*dest != '\0') {
753  /*
754  * NOTE: no need to check for overlap here since src comes first
755  * in memory and we're not incrementing src here.
756  */
757  dest++;
758  dmax--;
759  if (dmax == 0) {
760  (void)orig_dmax;
761  *orig_dest = '\0';
762  return NI_RETCODE_FAILURE;
763  }
764  }
765 
766  while (dmax > 0) {
767  if (src == overlap_bumper) {
768  (void)orig_dmax;
769  *orig_dest = '\0';
770  return NI_RETCODE_FAILURE;
771  }
772 
773  *dest = *src;
774  if (*dest == '\0') {
775  /* null slack to clear any data */
776 #ifdef SAFECLIB_STR_NULL_SLACK
777  if (dmax > 0x20)
778  memset(dest, 0, dmax);
779  else {
780  while (dmax) {
781  *dest = '\0';
782  dmax--;
783  dest++;
784  }
785  }
786 #endif
787  return NI_RETCODE_SUCCESS;
788  }
789 
790  dmax--;
791  dest++;
792  src++;
793  }
794  }
795 
796  /* the entire src was not copied, so null the string */
797  (void)orig_dmax;
798  *orig_dest = '\0';
799  return NI_RETCODE_FAILURE;
800 #endif
801 }
802 
803 ni_retcode_t ni_strncat(char *dest, size_t dmax,
804  const char *src, size_t slen)
805 {
806  size_t orig_dmax;
807  char *orig_dest;
808  const char *overlap_bumper;
809 
810  if (slen == 0 && !dest && !dmax) {
811  /* silent ok as in the msvcrt */
812  return NI_RETCODE_SUCCESS;
813  }
814  if (!dest || !dmax || !src)
816  else if (slen == 0) {
817  /* Special case, analog to msvcrt: when dest is big enough
818  return OK, but clear dest. */
819  (void)dmax;
820  *dest = '\0';
821  return NI_RETCODE_SUCCESS;
822  }
823 
824  /* hold base of dest in case src was not copied */
825  orig_dmax = dmax;
826  orig_dest = dest;
827 
828  if (dest < src) {
829  overlap_bumper = src;
830 
831  /* Find the end of dest */
832  while (*dest != '\0') {
833 
834  if (dest == overlap_bumper) {
835  (void)orig_dmax;
836  *orig_dest = '\0';
837  return NI_RETCODE_FAILURE;
838  }
839 
840  dest++;
841  dmax--;
842  if (dmax == 0) {
843  (void)orig_dmax;
844  *orig_dest = '\0';
845  return NI_RETCODE_FAILURE;
846  }
847  }
848 
849  while (dmax > 0) {
850  if (dest == overlap_bumper) {
851  (void)orig_dmax;
852  *orig_dest = '\0';
853  return NI_RETCODE_FAILURE;
854  }
855 
856  /*
857  * Copying truncated before the source null is encountered
858  */
859  if (slen == 0) {
860 #ifdef SAFECLIB_STR_NULL_SLACK
861  /* null remaining string */
862  if (dmax > 0x20)
863  memset(dest, 0, dmax);
864  else {
865  while (dmax) {
866  *dest = '\0';
867  dmax--;
868  dest++;
869  }
870  }
871 #else
872  *dest = '\0';
873 #endif
874  return NI_RETCODE_SUCCESS;
875  }
876 
877  *dest = *src;
878  if (*dest == '\0') {
879 #ifdef SAFECLIB_STR_NULL_SLACK
880  /* null slack to clear data */
881  if (dmax > 0x20)
882  memset(dest, 0, dmax);
883  else {
884  while (dmax) {
885  *dest = '\0';
886  dmax--;
887  dest++;
888  }
889  }
890 #endif
891  return NI_RETCODE_SUCCESS;
892  }
893 
894  dmax--;
895  slen--;
896  dest++;
897  src++;
898  }
899  } else {
900  overlap_bumper = dest;
901 
902  /* Find the end of dest */
903  while (*dest != '\0') {
904 
905  /*
906  * NOTE: no need to check for overlap here since src comes first
907  * in memory and we're not incrementing src here.
908  */
909  dest++;
910  dmax--;
911  if (dmax == 0) {
912  (void)orig_dmax;
913  *orig_dest = '\0';
914  return NI_RETCODE_FAILURE;
915  }
916  }
917 
918  while (dmax > 0) {
919  if (src == overlap_bumper) {
920  (void)orig_dmax;
921  *orig_dest = '\0';
922  return NI_RETCODE_FAILURE;
923  }
924 
925  /*
926  * Copying truncated
927  */
928  if (slen == 0) {
929 #ifdef SAFECLIB_STR_NULL_SLACK
930  /* null remaining string */
931  if (dmax > 0x20)
932  memset(dest, 0, dmax);
933  else {
934  while (dmax) {
935  *dest = '\0';
936  dmax--;
937  dest++;
938  }
939  }
940 #else
941  *dest = '\0';
942 #endif
943  return NI_RETCODE_SUCCESS;
944  }
945 
946  *dest = *src;
947  if (*dest == '\0') {
948 #ifdef SAFECLIB_STR_NULL_SLACK
949  /* null slack to clear any data */
950  if (dmax > 0x20)
951  memset(dest, 0, dmax);
952  else {
953  while (dmax) {
954  *dest = '\0';
955  dmax--;
956  dest++;
957  }
958  }
959 #endif
960  return NI_RETCODE_SUCCESS;
961  }
962 
963  dmax--;
964  slen--;
965  dest++;
966  src++;
967  }
968  }
969 
970  /*
971  * the entire src was not copied, so the string will be nulled.
972  */
973 
974  (void)orig_dmax;
975  *orig_dest = '\0';
976  return NI_RETCODE_FAILURE;
977 }
978 
979 ni_retcode_t ni_fopen(FILE **fp, const char *filename, const char *mode)
980 {
981 #if defined(_MSC_VER)
982  if(fopen_s(fp, filename, mode))
983  return NI_RETCODE_FAILURE;
984  else
985  return NI_RETCODE_SUCCESS;
986 #else
987  if (!fp || !filename || !mode)
989 
990  *fp = fopen(filename, mode);
991  if (!*fp) {
992  ni_log(NI_LOG_ERROR, "Failed to open file %s with mode %s\n", filename, mode);
993  return NI_RETCODE_FAILURE;
994  }
995  return NI_RETCODE_SUCCESS;
996 #endif
997 }
998 
999 struct tm* ni_localtime(struct tm *dest, const time_t *src)
1000 {
1001 #if defined(_MSC_VER)
1002  if (localtime_s(dest, src))
1003  return NULL;
1004  else
1005  return dest;
1006 #else
1007  if (!dest || !src)
1008  return NULL;
1009  if (*src < 0) {
1010  return NULL;
1011  }
1012  dest = localtime(src);
1013  return dest;
1014 #endif
1015 }
1016 
1017 int ni_fscanf(FILE *stream, const char *fmt, ...)
1018 {
1019  int ret;
1020 #if defined(_MSC_VER)
1021  va_list args;
1022  va_start(args, fmt);
1023  ret = vfscanf_s(stream, fmt, args);
1024  va_end(args);
1025 #else
1026  if (!stream || !fmt)
1027  return EOF;
1028  va_list args;
1029  va_start(args, fmt);
1030  ret = vfscanf(stream, fmt, args);
1031  va_end(args);
1032 #endif
1033  return ret;
1034 }
1035 
1036 int ni_vsprintf(char *dest, const size_t dmax, const char *fmt, va_list args)
1037 {
1038 #if defined(_MSC_VER)
1039  int ret = vsprintf_s(dest, dmax, fmt, args);
1040  return ret;
1041 #else
1042  if (!dest || !dmax || !fmt)
1043  return -1;
1044  // Use vsnprintf on Linux/macOS (which is safe if used correctly)
1045  int ret = vsnprintf(dest, dmax, fmt, args);
1046  if (ret < 0) {
1047  // Encoding error occurred
1048  return -1;
1049  } else if ((size_t)ret >= dmax) {
1050  // Buffer was too small (truncation occurred)
1051  char *overrun = dest + dmax - 1; // Point to the last character
1052  *overrun = '\0'; // Ensure null-termination
1053  return -1;
1054  }
1055  return ret;
1056 #endif
1057 }
1058 
1059 int ni_sprintf(char *dest, size_t dmax, const char *fmt, ...)
1060 {
1061  va_list args;
1062  va_start(args, fmt);
1063  int ret = ni_vsprintf(dest, dmax, fmt, args);
1064  va_end(args);
1065  return ret;
1066 }
1067 
1068 // memory buffer pool operations (one use is for decoder frame buffer pool)
1069 // expand buffer pool by a pre-defined size
1071 {
1072  int32_t i;
1073  for (i = 0; i < NI_DEC_FRAME_BUF_POOL_SIZE_EXPAND; i++)
1074  {
1075  if( NULL == ni_buf_pool_allocate_buffer(pool, pool->buf_size) )
1076  {
1077  ni_log(NI_LOG_FATAL, "FATAL: Failed to expand ni_buf_pool buffer: %p, "
1078  "current size: %u\n", pool, pool->number_of_buffers);
1079  return NULL;
1080  }
1081  }
1083  return pool->p_free_head;
1084 }
1085 
1086 // get a free memory buffer from the pool
1088 {
1089  ni_buf_t *buf = NULL;
1090 
1091  if (NULL == p_buffer_pool)
1092  {
1093  return NULL;
1094  }
1095 
1096  ni_pthread_mutex_lock(&p_buffer_pool->mutex);
1097  buf = p_buffer_pool->p_free_head;
1098 
1099  // find and return a free buffer
1100  if (NULL == buf)
1101  {
1102  ni_log(NI_LOG_INFO, "Expanding dec fme buffer_pool from %u to %u\n",
1103  p_buffer_pool->number_of_buffers,
1104  p_buffer_pool->number_of_buffers +
1106 
1107  buf = ni_buf_pool_expand(p_buffer_pool);
1108  if (NULL == buf)
1109  {
1110  ni_pthread_mutex_unlock(&p_buffer_pool->mutex);
1111  return NULL;
1112  }
1113  }
1114 
1115  // remove it from free list head; reconnect the linked list, the p_next
1116  // will become the new head now
1117  p_buffer_pool->p_free_head = buf->p_next_buffer;
1118 
1119  if (NULL != buf->p_next_buffer)
1120  {
1121  buf->p_next_buffer->p_previous_buffer = NULL;
1122  } else
1123  {
1124  p_buffer_pool->p_free_tail = NULL;
1125  }
1126 
1127  // add it to the used list tail
1128  buf->p_previous_buffer = p_buffer_pool->p_used_tail;
1129  buf->p_next_buffer = NULL;
1130 
1131  if (NULL != p_buffer_pool->p_used_tail)
1132  {
1133  p_buffer_pool->p_used_tail->p_next_buffer = buf;
1134  } else
1135  {
1136  p_buffer_pool->p_used_head = buf;
1137  }
1138 
1139  p_buffer_pool->p_used_tail = buf;
1140 
1141  ni_pthread_mutex_unlock(&p_buffer_pool->mutex);
1142 
1143  ni_log(NI_LOG_DEBUG, "%s ptr %p buf %p\n", __func__, buf->buf, buf);
1144  return buf;
1145 }
1146 
1147 // return a used memory buffer to the pool
1149 {
1150  // p_buffer_pool could be null in case of delayed buffer return after pool
1151  // has been freed
1152  if (!buf)
1153  {
1154  return;
1155  }
1156 
1157  ni_log(NI_LOG_DEBUG, "%s ptr %p buf %p\n", __func__, buf->buf, buf);
1158 
1159  if (!p_buffer_pool)
1160  {
1161  ni_log(NI_LOG_DEBUG, "%s: pool already freed, self destroy\n", __func__);
1162  ni_aligned_free(buf->buf);
1163  free(buf);
1164  return;
1165  }
1166 
1167  ni_pthread_mutex_lock(&p_buffer_pool->mutex);
1168 
1169  // remove buf from the used list
1170  if (NULL != buf->p_previous_buffer)
1171  {
1173  } else
1174  {
1175  p_buffer_pool->p_used_head = buf->p_next_buffer;
1176  }
1177 
1178  if (NULL != buf->p_next_buffer)
1179  {
1181  } else
1182  {
1183  p_buffer_pool->p_used_tail = buf->p_previous_buffer;
1184  }
1185 
1186  // put it on the tail of free buffers list
1187  buf->p_previous_buffer = p_buffer_pool->p_free_tail;
1188  buf->p_next_buffer = NULL;
1189 
1190  if (NULL != p_buffer_pool->p_free_tail)
1191  {
1192  p_buffer_pool->p_free_tail->p_next_buffer = buf;
1193  } else
1194  {
1195  p_buffer_pool->p_free_head = buf;
1196  }
1197 
1198  p_buffer_pool->p_free_tail = buf;
1199 
1200  ni_pthread_mutex_unlock(&p_buffer_pool->mutex);
1201 }
1202 
1203 // allocate a memory buffer and place it in the pool
1205  int buffer_size)
1206 {
1207  ni_buf_t *p_buffer = NULL;
1208  void *p_buf = NULL;
1209 
1210  if (NULL != p_buffer_pool &&
1211  (p_buffer = (ni_buf_t *)malloc(sizeof(ni_buf_t))) != NULL)
1212  {
1213  // init the struct
1214  memset(p_buffer, 0, sizeof(ni_buf_t));
1215 
1216  if (ni_posix_memalign(&p_buf, sysconf(_SC_PAGESIZE), buffer_size))
1217  {
1218  ni_aligned_free(p_buffer);
1219  return NULL;
1220  }
1221  ni_log(NI_LOG_DEBUG, "%s ptr %p buf %p\n", __func__, p_buf, p_buffer);
1222  p_buffer->buf = p_buf;
1223  p_buffer->pool = p_buffer_pool;
1224 
1225  // add buffer to the buf pool list
1226  p_buffer->p_prev = NULL;
1227  p_buffer->p_next = NULL;
1228  p_buffer->p_previous_buffer = p_buffer_pool->p_free_tail;
1229 
1230  if (p_buffer_pool->p_free_tail != NULL)
1231  {
1232  p_buffer_pool->p_free_tail->p_next_buffer = p_buffer;
1233  } else
1234  {
1235  p_buffer_pool->p_free_head = p_buffer;
1236  }
1237 
1238  p_buffer_pool->p_free_tail = p_buffer;
1239  }
1240 
1241  return p_buffer;
1242 }
1243 
1244 // decoder frame buffer pool init & free
1246  int32_t number_of_buffers,
1247  int width, int height,
1248  int height_align, int factor)
1249 {
1250  int32_t i;
1251  int width_aligned;
1252  int height_aligned;
1253 
1254  ni_log2(p_ctx, NI_LOG_TRACE, "%s: enter\n", __func__);
1255 
1256  if (QUADRA)
1257  {
1258  width_aligned = ((((width * factor) + 127) / 128) * 128) / factor;
1259  height_aligned = height;
1260  } else
1261  {
1262  width_aligned = ((width + 31) / 32) * 32;
1263  height_aligned = ((height + 7) / 8) * 8;
1264  if (height_align)
1265  {
1266  height_aligned = ((height + 15) / 16) * 16;
1267  }
1268  }
1269 
1270  int luma_size = width_aligned * height_aligned * factor;
1271  int chroma_b_size;
1272  int chroma_r_size;
1273  if (QUADRA)
1274  {
1275  int chroma_width_aligned =
1276  ((((width / 2 * factor) + 127) / 128) * 128) / factor;
1277  int chroma_height_aligned = height_aligned / 2;
1278  chroma_b_size = chroma_r_size =
1279  chroma_width_aligned * chroma_height_aligned * factor;
1280  } else
1281  {
1282  chroma_b_size = luma_size / 4;
1283  chroma_r_size = chroma_b_size;
1284  }
1285  uint32_t buffer_size = luma_size + chroma_b_size + chroma_r_size +
1287 
1288  // added 2 blocks of 512 bytes buffer space to handle any extra metadata
1289  // retrieval from fw
1290  buffer_size =
1291  ((buffer_size + (NI_MEM_PAGE_ALIGNMENT - 1)) / NI_MEM_PAGE_ALIGNMENT) *
1294 
1295  if (p_ctx->dec_fme_buf_pool != NULL)
1296  {
1297  ni_log2(p_ctx, NI_LOG_DEBUG,
1298  "Warning init dec_fme Buf pool already with size %u\n",
1300 
1301  if (buffer_size > p_ctx->dec_fme_buf_pool->buf_size)
1302  {
1304  "Warning resolution %dx%d memory buffer size %u "
1305  "> %u (existing buffer size), re-allocating !\n",
1306  width, height, buffer_size,
1307  p_ctx->dec_fme_buf_pool->buf_size);
1308 
1310  } else
1311  {
1313  "INFO resolution %dx%d memory buffer size %u <= "
1314  "%u (existing buffer size), continue !\n",
1315  width, height, buffer_size,
1316  p_ctx->dec_fme_buf_pool->buf_size);
1317  return 0;
1318  }
1319  }
1320 
1321  if ((p_ctx->dec_fme_buf_pool =
1322  (ni_buf_pool_t *)malloc(sizeof(ni_buf_pool_t))) == NULL)
1323  {
1324  ni_log2(p_ctx, NI_LOG_ERROR, "Error alloc for dec fme buf pool\n");
1325  return -1;
1326  }
1327 
1328  // init the struct
1329  memset(p_ctx->dec_fme_buf_pool, 0, sizeof(ni_buf_pool_t));
1331  p_ctx->dec_fme_buf_pool->number_of_buffers = number_of_buffers;
1332 
1333  ni_log2(p_ctx, NI_LOG_DEBUG,
1334  "ni_dec_fme_buffer_pool_initialize: entries %d entry size "
1335  "%d\n",
1336  number_of_buffers, buffer_size);
1337 
1338  p_ctx->dec_fme_buf_pool->buf_size = buffer_size;
1339  for (i = 0; i < number_of_buffers; i++)
1340  {
1341  if (NULL ==
1342  ni_buf_pool_allocate_buffer(p_ctx->dec_fme_buf_pool, buffer_size))
1343  {
1344  // release everything we have allocated so far and exit
1346  return -1;
1347  }
1348  }
1349 
1350  ni_log2(p_ctx, NI_LOG_TRACE, "%s: exit\n", __func__);
1351  return 0;
1352 }
1353 
1355 {
1356  ni_buf_t *buf, *p_next;
1357 
1358  if (p_buffer_pool)
1359  {
1360  ni_log(NI_LOG_TRACE, "%s: enter.\n", __func__);
1361 
1362  // mark used buf not returned at pool free time by setting pool ptr in used
1363  // buf to NULL, so they will self-destroy when time is due eventually
1364  ni_pthread_mutex_lock(&p_buffer_pool->mutex);
1365  buf = p_buffer_pool->p_used_head;
1366  if (buf)
1367  {
1368  while (buf)
1369  {
1370  p_next = buf->p_next_buffer;
1371  ni_log(NI_LOG_DEBUG, "Release ownership of ptr %p buf %p\n",
1372  buf->buf, buf);
1373  buf->pool = NULL;
1374  buf = p_next;
1375  }
1376  }
1377  ni_pthread_mutex_unlock(&p_buffer_pool->mutex);
1378 
1379  buf = p_buffer_pool->p_free_head;
1380  // free all the buffers in the free list
1381  int32_t count_free = 0;
1382  while (buf)
1383  {
1384  p_next = buf->p_next_buffer;
1385  ni_aligned_free(buf->buf);
1386  free(buf);
1387  buf = p_next;
1388  count_free++;
1389  }
1390  // NOLINTNEXTLINE(bugprone-branch-clone)
1391  if (count_free != p_buffer_pool->number_of_buffers)
1392  {
1393  ni_log(NI_LOG_DEBUG, "%s free %d != number_of_buffers %u\n",
1394  __func__, count_free, p_buffer_pool->number_of_buffers);
1395  } else
1396  {
1397  ni_log(NI_LOG_DEBUG, "%s all buffers freed: %d.\n", __func__,
1398  count_free);
1399  }
1400  free(p_buffer_pool);
1401  }
1402  else
1403  {
1404  ni_log(NI_LOG_INFO, "%s: NOT allocated\n", __func__);
1405  }
1406 }
1407 
1409 {
1410  ni_queue_node_t *buf, *p_next;
1411 
1412  ni_log(NI_LOG_TRACE, "%s: enter.\n", __func__);
1413 
1414  if (p_buffer_pool)
1415  {
1416  buf = p_buffer_pool->p_free_head;
1417  // free all the buffers in the free and used list
1418  int32_t count = 0;
1419  while (buf)
1420  {
1421  p_next = buf->p_next_buffer;
1422  free(buf);
1423  buf = p_next;
1424  count++;
1425  }
1426 
1427  buf = p_buffer_pool->p_used_head;
1428  while (buf)
1429  {
1430  p_next = buf->p_next_buffer;
1431  free(buf);
1432  buf = p_next;
1433  count++;
1434  }
1435 
1436  if (count != p_buffer_pool->number_of_buffers)
1437  {
1438  ni_log(NI_LOG_ERROR, "??? freed %d != number_of_buffers %u\n",
1439  count, p_buffer_pool->number_of_buffers);
1440  } else
1441  {
1442  ni_log(NI_LOG_DEBUG, "p_buffer_pool freed %d buffers.\n", count);
1443  }
1444  free(p_buffer_pool);
1445  }
1446  else
1447  {
1448  ni_log(NI_LOG_INFO, "%s: NOT allocated\n", __func__);
1449  }
1450 }
1451 
1453 {
1454  ni_queue_node_t *p_buffer = NULL;
1455 
1456  if (NULL != p_buffer_pool &&
1457  (p_buffer = (ni_queue_node_t *)malloc(sizeof(ni_queue_node_t))) != NULL)
1458  {
1459  //Inititalise the struct
1460  memset(p_buffer, 0, sizeof(ni_queue_node_t));
1461  // add buffer to the buf pool list
1462  p_buffer->p_prev = NULL;
1463  p_buffer->p_next = NULL;
1464  p_buffer->p_previous_buffer = p_buffer_pool->p_free_tail;
1465 
1466  if (p_buffer_pool->p_free_tail != NULL)
1467  {
1468  p_buffer_pool->p_free_tail->p_next_buffer = p_buffer;
1469  } else
1470  {
1471  p_buffer_pool->p_free_head = p_buffer;
1472  }
1473 
1474  p_buffer_pool->p_free_tail = p_buffer;
1475  }
1476 
1477  return p_buffer;
1478 }
1479 
1480 int32_t ni_buffer_pool_initialize(ni_session_context_t* p_ctx, int32_t number_of_buffers)
1481 {
1482  int i;
1483 
1484  ni_log2(p_ctx, NI_LOG_TRACE, "%s: enter\n", __func__);
1485 
1486  if (p_ctx->buffer_pool != NULL)
1487  {
1488  ni_log2(p_ctx, NI_LOG_DEBUG, "Warn init Buf pool already with size %u\n",
1489  p_ctx->buffer_pool->number_of_buffers);
1490  return -1;
1491  }
1492 
1493  if ((p_ctx->buffer_pool = (ni_queue_buffer_pool_t *)malloc(
1494  sizeof(ni_queue_buffer_pool_t))) == NULL)
1495  {
1496  ni_log(NI_LOG_ERROR, "Error alloc for pool\n");
1497  return -1;
1498  }
1499 
1500  //initialise the struct
1501  memset(p_ctx->buffer_pool, 0, sizeof(ni_queue_buffer_pool_t));
1502  p_ctx->buffer_pool->number_of_buffers = number_of_buffers;
1503  //p_buffer_pool->p_free_head = NULL;
1504  //p_buffer_pool->p_free_tail = NULL;
1505  //p_buffer_pool->p_used_head = NULL;
1506  //p_buffer_pool->p_used_tail = NULL;
1507 
1508  for (i = 0; i < number_of_buffers; i++)
1509  {
1510  if (NULL == ni_buffer_pool_allocate_buffer(p_ctx->buffer_pool))
1511  {
1512  //Release everything we have allocated so far and exit
1514  return -1;
1515  }
1516  }
1517 
1518  return 0;
1519 }
1520 
1522 {
1523  int i;
1524 
1525  for (i = 0; i < 200; i++)
1526  {
1527  if (NULL == ni_buffer_pool_allocate_buffer(pool))
1528  {
1530  "FATAL ERROR: Failed to allocate pool buffer for pool :%p\n",
1531  pool);
1532  return NULL;
1533  }
1534  }
1535  pool->number_of_buffers += 200;
1536  return pool->p_free_head;
1537 }
1538 
1540 {
1541  ni_queue_node_t *buf = NULL;
1542 
1543  if (NULL == p_buffer_pool)
1544  {
1545  return NULL;
1546  }
1547 
1548  // find and return a free buffer
1549  buf = p_buffer_pool->p_free_head;
1550  if (NULL == buf)
1551  {
1552  ni_log(NI_LOG_INFO, "Expanding p_buffer_pool from %u to %u \n",
1553  p_buffer_pool->number_of_buffers,
1554  p_buffer_pool->number_of_buffers + 200);
1555  buf = ni_buffer_pool_expand(p_buffer_pool);
1556  if (NULL == buf)
1557  {
1558  return NULL; //return null otherwise there will be null derefferencing later
1559  }
1560  }
1561 
1562  buf->checkout_timestamp = time(NULL);
1563  // remove it from free list head; reconnect the linked list, the p_next
1564  // will become the new head now
1565  p_buffer_pool->p_free_head = buf->p_next_buffer;
1566 
1567  if (NULL != buf->p_next_buffer)
1568  {
1569  buf->p_next_buffer->p_previous_buffer = NULL;
1570  } else
1571  {
1572  p_buffer_pool->p_free_tail = NULL;
1573  }
1574 
1575  // add it to the used list tail
1576  buf->p_previous_buffer = p_buffer_pool->p_used_tail;
1577  buf->p_next_buffer = NULL;
1578 
1579  if (NULL != p_buffer_pool->p_used_tail)
1580  {
1581  p_buffer_pool->p_used_tail->p_next_buffer = buf;
1582  } else
1583  {
1584  p_buffer_pool->p_used_head = buf;
1585  }
1586 
1587  p_buffer_pool->p_used_tail = buf;
1588 
1589  return buf;
1590 }
1591 
1593  ni_queue_buffer_pool_t *p_buffer_pool)
1594 {
1595  if (!buf || !p_buffer_pool)
1596  {
1597  return;
1598  }
1599 
1600  // remove buf from the used list
1601  if (NULL != buf->p_previous_buffer)
1602  {
1604  } else
1605  {
1606  p_buffer_pool->p_used_head = buf->p_next_buffer;
1607  }
1608 
1609  if (NULL != buf->p_next_buffer)
1610  {
1612  } else
1613  {
1614  p_buffer_pool->p_used_tail = buf->p_previous_buffer;
1615  }
1616 
1617  // put it on the tail of free buffers list
1618  buf->p_previous_buffer = p_buffer_pool->p_free_tail;
1619  buf->p_next_buffer = NULL;
1620 
1621  if (NULL != p_buffer_pool->p_free_tail)
1622  {
1623  p_buffer_pool->p_free_tail->p_next_buffer = buf;
1624  } else
1625  {
1626  p_buffer_pool->p_free_head = buf;
1627  }
1628 
1629  p_buffer_pool->p_free_tail = buf;
1630 }
1631 
1632 /*!******************************************************************************
1633  * \brief Get xcoder instance id
1634  *
1635  * \param
1636  *
1637  * \return
1638  *******************************************************************************/
1639 int32_t ni_get_frame_index(uint32_t *value)
1640 {
1641  ni_nvme_write_complete_dw0_t *p_value =
1643 
1644  return p_value->frame_index;
1645 }
1646 
1647 #ifdef _ANDROID
1648 /*!******************************************************************************
1649  * \brief use cmd to search nvme block file
1650  *
1651  * \param[in] p_dev Device name represented as c string. ex: "/dev/nvme0"
1652  * \param[in] search cmd
1653  * \param[in] cmd_ret length
1654  * \param[out] cmd_ret search result for nvme block file
1655  *
1656  * \return On success returns NI_RETCODE_SUCCESS
1657  * On failure returns NI_RETCODE_FAILURE
1658  * On failure returns NI_RETCODE_INVALID_PARAM
1659  *******************************************************************************/
1660 static ni_retcode_t ni_search_file(const char *p_dev, char *cmd, char *cmd_ret,
1661  int cmd_ret_len)
1662 {
1663  FILE *cmd_fp;
1665 
1666  if (access(p_dev, F_OK) == -1)
1667  {
1668  return NI_RETCODE_FAILURE;
1669  }
1670 
1671  // look for child block in sysfs mapping tree
1672  cmd_fp = popen(cmd, "r");
1673  if (!cmd_fp)
1674  {
1675  return NI_RETCODE_FAILURE;
1676  }
1677 
1678  if (fgets(cmd_ret, cmd_ret_len, cmd_fp) == 0)
1679  {
1681  }
1682 
1683  pclose(cmd_fp);
1684  return ret;
1685 }
1686 #endif
1687 /*!******************************************************************************
1688 * \brief Remove a string-pattern from a string in-place.
1689 *
1690 * \param[in,out] main_str Null terminated array of characters to operate upon in-place.
1691 * \param[in] pattern Null terminated array of characters to remove from main_str.
1692 * Supports special characters '#' and '+' for digit matching and
1693 * repeated matching respectively. Note, there is no way to \a escape
1694 * the special characters.
1695 * \b Example:
1696 * char a_str[10] = "aaa123qwe";
1697 * char b_str[5] = "a+#+";
1698 * remove_substring_pattern(a_str, b_str);
1699 * printf("%s\n", a_str);
1700 * \b Output:
1701 * qwe
1702 *
1703 * \return If characters removed, returns 1
1704 * If no characters removed, returns 0
1705 *******************************************************************************/
1706 NI_UNUSED static uint32_t remove_substring_pattern(char *main_str, const char *pattern)
1707 {
1708  uint32_t i, j; // for loop counters
1709  uint32_t match_length; // length of matching substring
1710  uint32_t matched_chr; // boolean flag for when match is found for a character in the pattern
1711  char char_match_pattern[11] = ""; // what characters to look for when evaluating a character in main_str
1712  uint32_t pattern_matched = 0; // boolean flag for when who pattern match is found
1713  uint32_t pattern_start = 0; // starting index in main_str of substring matching pattern
1714  const char digit_match_pattern[11] = "0123456789"; // set of numeric digits for expansion of special character '#'
1715 
1716  // do not accept zero length main_str or pattern
1717  if (!main_str || !pattern || !*main_str || !*pattern)
1718  {
1719  return 0;
1720  }
1721 
1722  // iterate over all characters in main_str looking for starting index of matching pattern
1723  for (i = 0; i < strlen(main_str) && !pattern_matched; i++)
1724  {
1725  pattern_matched = 0;
1726  match_length = 0;
1727  // iterate over the characters of the pattern
1728  for (j = 0; j < strlen(pattern); j++)
1729  {
1730  matched_chr = 0;
1731  // set which characters to look for, special cases for special control characters
1732  if (pattern[j] == '+')
1733  {
1734  // immediately fail as entering this branch means either the first character is a '+', or a '+" following a "+'
1735  return 0;
1736  }
1737  else if (pattern[j] == '#')
1738  {
1739  memcpy(char_match_pattern, digit_match_pattern, strlen(digit_match_pattern) + 1);
1740  }
1741  else
1742  {
1743  memcpy(char_match_pattern, pattern + j, 1);
1744  memset(char_match_pattern + 1, 0, 1);
1745  }
1746  // check if char is in match_pattern
1747  if (pattern[j+1] == '+')
1748  {
1749  while (main_str[i + match_length] && strchr(char_match_pattern, (int) main_str[i + match_length]))
1750  {
1751  match_length++;
1752  matched_chr = 1;
1753  }
1754  j++;
1755  }
1756  else if (main_str[i + match_length] && strchr(char_match_pattern, (int) main_str[i + match_length]))
1757  {
1758  match_length++;
1759  matched_chr = 1;
1760  }
1761  // if no matches were found, then this segment is not the sought pattern
1762  if (!matched_chr)
1763  {
1764  break;
1765  }
1766  // if all of pattern has been processed and matched, mark sucessful whole pattern match
1767  else if ((j + 1) >= strlen(pattern))
1768  {
1769  pattern_matched = 1;
1770  pattern_start = i;
1771  }
1772  }
1773  }
1774 
1775  // remove sub-string if its pattern was found in main_str
1776  if (pattern_matched)
1777  {
1778  uint32_t orig_main_str_len = (uint32_t)strlen(main_str);
1779  memmove(main_str + pattern_start, main_str + pattern_start + match_length,
1780  strlen(main_str + pattern_start + match_length));
1781  main_str[orig_main_str_len - match_length] = 0;
1782  return 1;
1783  }
1784  else
1785  {
1786  return 0;
1787  }
1788 }
1789 
1790 /*!******************************************************************************
1791  * \brief Find NVMe name space block from device name
1792  * If none is found, assume nvme multi-pathing is disabled and return /dev/nvmeXn1
1793  *
1794  * \param[in] p_dev Device name represented as c string. ex: "/dev/nvme0"
1795  * \param[in] out_buf Output buffer to put NVMe name space block. Must be at least length 21
1796  *
1797  * \return On success returns NI_RETCODE_SUCCESS
1798  * On failure returns NI_RETCODE_FAILURE
1799  *******************************************************************************/
1800 ni_retcode_t ni_find_blk_name(const char *p_dev, char *p_out_buf, int out_buf_len)
1801 {
1802  if (!p_dev || !p_out_buf)
1803  {
1804  return NI_RETCODE_INVALID_PARAM;
1805  }
1806 
1807 #ifdef _WIN32
1809  "Automatic namespaceID discovery not supported in Windows. Using "
1810  "guess.\n");
1811  snprintf(p_out_buf, out_buf_len, "%s", p_dev);
1812  return NI_RETCODE_SUCCESS;
1813 #elif __APPLE__
1814  /*
1815  Using smartctl /dev/rdisk4 -i | grep 'PCI Vendor' command check if output
1816  contains Quadra. Model number could be duplicated in other devices so
1817  should use PCI Vendor instead but smartctl is not preinstalled on mac
1818  snprintf(command, sizeof(command) - 1,
1819  "smartctl %s -i | grep 'PCI Vendor'", p_dev);
1820  */
1821  FILE *cmd_fp;
1822  char cmd_ret[60] = {0};
1823  char command[128] = {0};
1824  snprintf(command, sizeof(command) - 1,
1825  "diskutil info %s | grep 'Media Name'", p_dev);
1826  ni_log(NI_LOG_TRACE, "Using %s to find quadra device\n", command);
1827  cmd_fp = popen(command, "r");
1828  if (cmd_fp == NULL)
1829  {
1830  ni_log(NI_LOG_ERROR, "Failed to execute %s\n", command);
1831  return NI_RETCODE_FAILURE;
1832  }
1833  if (fgets(cmd_ret, sizeof(cmd_ret) - 1, cmd_fp) == NULL)
1834  {
1835  ni_log(NI_LOG_ERROR, "Failed to read %s output.\n", command);
1836  pclose(cmd_fp);
1837  return NI_RETCODE_FAILURE;
1838  }
1839  pclose(cmd_fp);
1840  ni_log(NI_LOG_TRACE, "Got '%s' from the command\n", cmd_ret);
1841  // if (strcasestr(cmd_ret, "0x1d82") != NULL)
1842  if (strcasestr(cmd_ret, "Quadra") != NULL)
1843  {
1844  snprintf(p_out_buf, out_buf_len, "%s", p_dev);
1845  return NI_RETCODE_SUCCESS;
1846  } else
1847  {
1848  //This is a soft error so trace level is fine
1849  ni_log(NI_LOG_TRACE, "%s is not a quadra device\n", p_dev);
1850  return NI_RETCODE_INVALID_PARAM;
1851  }
1852 #elif defined(XCODER_LINUX_VIRTIO_DRIVER_ENABLED)
1853  ni_log(NI_LOG_TRACE, "The device is already considered as a block divice in Linux virtual machine with VirtIO driver.\n");
1854  snprintf(p_out_buf, out_buf_len, "%s", p_dev);
1855  return NI_RETCODE_SUCCESS;
1856 #else
1857  ni_log(NI_LOG_DEBUG, "Set NVMe device name equal to NVMe block name\n");
1858  snprintf(p_out_buf, out_buf_len, "%s", p_dev);
1859  return NI_RETCODE_SUCCESS;
1860 #endif
1861 }
1862 
1863 /*!******************************************************************************
1864  * \brief check dev name
1865  *
1866  * \param[in] p_dev Device name represented as c string. ex: "/dev/nvmeXnY"
1867  *
1868  * \return On success returns NI_RETCODE_SUCCESS
1869  * On failure returns NI_RETCODE_FAILURE or NI_RETCODE_INVALID_PARAM
1870  *******************************************************************************/
1872 {
1873  if (!p_dev)
1874  {
1875  return NI_RETCODE_INVALID_PARAM;
1876  }
1877 
1878 #ifdef __APPLE__
1879  /*
1880  Using smartctl /dev/rdisk4 -i | grep 'PCI Vendor' command check if output
1881  contains Quadra. Model number could be duplicated in other devices so
1882  should use PCI Vendor instead but smartctl is not preinstalled on mac
1883  snprintf(command, sizeof(command) - 1,
1884  "smartctl %s -i | grep 'PCI Vendor'", p_dev);
1885  */
1886  FILE *cmd_fp;
1887  char cmd_ret[60] = {0};
1888  char command[128] = {0};
1889  snprintf(command, sizeof(command) - 1,
1890  "diskutil info %s | grep 'Media Name'", p_dev);
1891  ni_log(NI_LOG_TRACE, "Using %s to find quadra device\n", command);
1892  cmd_fp = popen(command, "r");
1893  if (cmd_fp == NULL)
1894  {
1895  ni_log(NI_LOG_ERROR, "Failed to execute %s\n", command);
1896  return NI_RETCODE_FAILURE;
1897  }
1898  if (fgets(cmd_ret, sizeof(cmd_ret) - 1, cmd_fp) == NULL)
1899  {
1900  ni_log(NI_LOG_ERROR, "Failed to read %s output.\n", command);
1901  pclose(cmd_fp);
1902  return NI_RETCODE_FAILURE;
1903  }
1904  pclose(cmd_fp);
1905  ni_log(NI_LOG_TRACE, "Got '%s' from the command\n", cmd_ret);
1906  // if (strcasestr(cmd_ret, "0x1d82") != NULL)
1907  if (strcasestr(cmd_ret, "Quadra") != NULL)
1908  {
1909  return NI_RETCODE_SUCCESS;
1910  } else
1911  {
1912  //This is a soft error so trace level is fine
1913  ni_log(NI_LOG_TRACE, "%s is not a quadra device\n", p_dev);
1914  return NI_RETCODE_INVALID_PARAM;
1915  }
1916 #endif
1917  return NI_RETCODE_SUCCESS;
1918 }
1919 
1920 /*!******************************************************************************
1921  * \brief Initialize timestamp handling
1922  *
1923  * \param
1924  *
1925  * \return
1926  *******************************************************************************/
1928 {
1929  ni_timestamp_table_t *ptemp;
1930 
1931  ni_log2(p_ctx, NI_LOG_TRACE, "%s: enter\n", __func__);
1932 
1933  if (*pp_table != NULL)
1934  {
1935  ni_log2(p_ctx, NI_LOG_DEBUG, "%s: previously allocated, reallocating now\n",
1936  __func__);
1937  ni_queue_free(&(*pp_table)->list, p_ctx->buffer_pool);
1938  free(*pp_table);
1939  }
1940  ni_log2(p_ctx, NI_LOG_DEBUG, "%s: Malloc\n", __func__);
1941  ptemp = (ni_timestamp_table_t *)malloc(sizeof(ni_timestamp_table_t));
1942  if (!ptemp)
1943  {
1945  }
1946 
1947  //initialise the struct
1948  memset(ptemp, 0, sizeof(ni_timestamp_table_t));
1949 
1950  ni_queue_init(p_ctx, &ptemp->list,
1951  name); //buffer_pool_initialize runs in here
1952 
1953  *pp_table = ptemp;
1954 
1955  ni_log2(p_ctx, NI_LOG_DEBUG, "%s: success\n", __func__);
1956 
1957  return NI_RETCODE_SUCCESS;
1958 }
1959 
1960 /*!******************************************************************************
1961  * \brief Clean up timestamp handling
1962  *
1963  * \param
1964  *
1965  * \return
1966  *******************************************************************************/
1968  ni_queue_buffer_pool_t *p_buffer_pool)
1969 {
1970  ni_log(NI_LOG_TRACE, "%s: enter\n", __func__);
1971 
1972  if (!p_table)
1973  {
1974  ni_log(NI_LOG_DEBUG, "%s: no pts table to free\n", __func__);
1975  return NI_RETCODE_SUCCESS;
1976  }
1977  ni_queue_free(&p_table->list, p_buffer_pool);
1978 
1979  free(p_table);
1980  ni_log(NI_LOG_DEBUG, "%s: success\n", __func__);
1981 
1982  return NI_RETCODE_SUCCESS;
1983 }
1984 
1985 /*!******************************************************************************
1986  * \brief Register timestamp in timestamp/frameoffset table
1987  *
1988  * \param
1989  *
1990  * \return
1991  *******************************************************************************/
1993  ni_timestamp_table_t *p_table,
1994  int64_t timestamp, uint64_t data_info)
1995 {
1997 
1998  err = ni_queue_push(p_buffer_pool, &p_table->list, data_info, timestamp);
1999 
2000  if (NI_RETCODE_SUCCESS == err) // NOLINT(bugprone-branch-clone)
2001  {
2002  ni_log(NI_LOG_DEBUG, "%s: success\n", __func__);
2003  } else
2004  {
2005  ni_log(NI_LOG_ERROR, "ERROR: %s: FAILED\n", __func__);
2006  }
2007 
2008  return err;
2009 }
2010 
2011 /*!******************************************************************************
2012  * \brief Retrieve timestamp from table based on frameoffset info
2013  *
2014  * \param
2015  *
2016  * \return
2017  *******************************************************************************/
2019  uint64_t frame_info, int64_t *p_timestamp,
2020  int32_t threshold, int32_t print,
2021  ni_queue_buffer_pool_t *p_buffer_pool)
2022 {
2024 
2025  ni_log(NI_LOG_DEBUG, "%s: getting timestamp with frame_info=%" PRId64 "\n",
2026  __func__, frame_info);
2027 
2028  err = ni_queue_pop(&p_table->list, frame_info, p_timestamp, threshold,
2029  print, p_buffer_pool);
2030  if (NI_RETCODE_SUCCESS != err)
2031  {
2032  ni_log(NI_LOG_ERROR, "%s: error getting timestamp\n", __func__);
2033  }
2034 
2036  "%s: timestamp=%" PRId64 ", frame_info=%" PRId64 ", err=%d\n",
2037  __func__, *p_timestamp, frame_info, err);
2038 
2039  return err;
2040 }
2041 
2043  ni_timestamp_table_t *p_table, uint64_t frame_info, int64_t *p_timestamp,
2044  int32_t threshold, int32_t print, ni_queue_buffer_pool_t *p_buffer_pool)
2045 {
2046  return ni_queue_pop_threshold(&p_table->list, frame_info, p_timestamp,
2047  threshold, print, p_buffer_pool);
2048 }
2049 
2051  ni_timestamp_table_t *dts_list,
2052  ni_queue_buffer_pool_t *p_buffer_pool)
2053 {
2054  if (!pts_list || !dts_list)
2055  {
2056  return;
2057  }
2058 
2059  // currently, only have dts list.
2060  // if pts list is added back, this should be modified.
2061  ni_queue_t *p_queue = &dts_list->list;
2062  ni_queue_node_t *p = p_queue->p_first;
2063  time_t now = time(NULL);
2064 
2065  while (p)
2066  {
2067  if (now - p->checkout_timestamp <= 30)
2068  {
2069  break;
2070  }
2071  if (p_queue->p_first == p_queue->p_last)
2072  {
2073  ni_buffer_pool_return_buffer(p_queue->p_first, p_buffer_pool);
2074  p = p_queue->p_first = p_queue->p_last = NULL;
2075  } else
2076  {
2077  p_queue->p_first = p->p_next;
2078  p->p_next->p_prev = NULL;
2079  ni_buffer_pool_return_buffer(p, p_buffer_pool);
2080 
2081  p = p_queue->p_first;
2082  }
2083  p_queue->count--;
2084  }
2085 }
2086 
2087 /*!******************************************************************************
2088  * \brief Retrieve timestamp from table based on frameoffset info
2089  *
2090  * \param
2091  *
2092  * \return
2093  *******************************************************************************/
2095  uint64_t frame_offset, int64_t *p_timestamp,
2096  int32_t threshold,
2097  ni_queue_buffer_pool_t *p_buffer_pool)
2098 {
2100 
2101  if (!p_table || !p_timestamp || !p_buffer_pool)
2102  {
2104  LRETURN;
2105  }
2106 
2107  ni_log(NI_LOG_DEBUG, "%s: getting timestamp with frame_offset=%" PRId64 "\n",
2108  __func__, frame_offset);
2109 
2110  err = ni_queue_pop(&p_table->list, frame_offset, p_timestamp, threshold, 0, p_buffer_pool);
2111  if( NI_RETCODE_SUCCESS != err)
2112  {
2113  ni_log(NI_LOG_ERROR, "%s: error getting timestamp\n", __func__);
2114  }
2115 
2117  "%s: timestamp=%" PRId64 ", frame_offset=%" PRId64 ", err=%d\n",
2118  __func__, *p_timestamp, frame_offset, err);
2119 
2120 END:
2121 
2122  return err;
2123 }
2124 
2125 /*!******************************************************************************
2126  * \brief Initialize xcoder queue
2127  *
2128  * \param
2129  *
2130  * \return
2131  *******************************************************************************/
2132 ni_retcode_t ni_queue_init(ni_session_context_t* p_ctx, ni_queue_t *p_queue, const char *name)
2133 {
2134  ni_log2(p_ctx, NI_LOG_TRACE, "%s: enter\n", __func__);
2135 
2136  if (!p_queue || !name)
2137  {
2138  return NI_RETCODE_INVALID_PARAM;
2139  }
2140  ni_strcpy(p_queue->name, sizeof(p_queue->name), name);
2142 
2143  p_queue->p_first = NULL;
2144  p_queue->p_last = NULL;
2145  p_queue->count = 0;
2146 
2147  ni_log2(p_ctx, NI_LOG_TRACE, "%s: exit\n", __func__);
2148 
2149  return NI_RETCODE_SUCCESS;
2150 }
2151 
2152 /*!******************************************************************************
2153  * \brief Push into xcoder queue
2154  *
2155  * \param
2156  *
2157  * \return
2158  *******************************************************************************/
2160  ni_queue_t *p_queue, uint64_t frame_info,
2161  int64_t timestamp)
2162 {
2164  ni_queue_node_t *temp = NULL;
2165 
2166  if (!p_queue)
2167  {
2168  ni_log(NI_LOG_ERROR, "%s: error, null pointer parameters passed\n",
2169  __func__);
2171  LRETURN;
2172  }
2173 
2174  temp = ni_buffer_pool_get_queue_buffer(p_buffer_pool);
2175 
2176  if (!temp)
2177  {
2178  ni_log(NI_LOG_ERROR, "%s: error, cannot allocate memory\n", __func__);
2180  LRETURN;
2181  }
2182 
2183  //ni_log(NI_LOG_TRACE, "%s enter: p_first=%"PRId64", p_last=%"PRId64", count=%d\n", __func__, p_queue->p_first, p_queue->p_last, p_queue->count);
2184 
2185  temp->timestamp = timestamp;
2186  temp->frame_info = frame_info;
2187 
2188  temp->p_next = NULL;
2189 
2190  if (!p_queue->p_first)
2191  {
2192  p_queue->p_first = p_queue->p_last = temp;
2193  p_queue->p_first->p_prev = NULL;
2194  p_queue->count++;
2195  } else
2196  {
2197  p_queue->p_last->p_next = temp;
2198  temp->p_prev = p_queue->p_last;
2199  p_queue->p_last = temp;
2200  p_queue->count++;
2201 
2202  // Assume the oldest one is useless when reaching this situation.
2203  if (p_queue->count > XCODER_MAX_NUM_QUEUE_ENTRIES)
2204  {
2206  "%s: queue overflow, remove oldest entry, count=%u\n",
2207  __func__, p_queue->count);
2208  //Remove oldest one
2209  temp = p_queue->p_first->p_next;
2210  // free(p_queue->p_first);
2211  ni_buffer_pool_return_buffer(p_queue->p_first, p_buffer_pool);
2212  p_queue->p_first = temp;
2213  p_queue->p_first->p_prev = NULL;
2214  p_queue->count--;
2215  }
2216  }
2217 
2218 END:
2219 
2220  return err;
2221 }
2222 
2223 /*!******************************************************************************
2224  * \brief Pop from the xcoder queue
2225  *
2226  * \param
2227  *
2228  * \return
2229  *******************************************************************************/
2230 ni_retcode_t ni_queue_pop(ni_queue_t *p_queue, uint64_t frame_info,
2231  int64_t *p_timestamp, int32_t threshold,
2232  int32_t print, ni_queue_buffer_pool_t *p_buffer_pool)
2233 {
2234  ni_queue_node_t *temp;
2235  ni_queue_node_t *temp_prev = NULL;
2236  int32_t found = 0;
2237  int32_t count = 0;
2239 
2240  if (!p_queue || !p_timestamp)
2241  {
2242  ni_log(NI_LOG_ERROR, "%s: error, null pointer parameters passed\n",
2243  __func__);
2244  retval = NI_RETCODE_INVALID_PARAM;
2245  LRETURN;
2246  }
2247 
2248  if (NULL == p_queue->p_first)
2249  {
2250  ni_log(NI_LOG_DEBUG, "%s: queue is empty...\n", __func__);
2251  retval = NI_RETCODE_FAILURE;
2252  LRETURN;
2253  }
2254 
2255  if (p_queue->p_first == p_queue->p_last)
2256  {
2258  *p_timestamp = p_queue->p_first->timestamp;
2259  // free(p_queue->p_first);
2260  ni_buffer_pool_return_buffer(p_queue->p_first, p_buffer_pool);
2261 
2262  p_queue->p_first = NULL;
2263  p_queue->p_last = NULL;
2264  p_queue->count--;
2265  ni_assert(p_queue->count == 0);
2266  found = 1;
2267  } else
2268  {
2269  temp = p_queue->p_first;
2270  while (temp && !found)
2271  {
2272  if (frame_info < temp->frame_info)
2273  {
2274  if (!temp->p_prev)
2275  {
2276  ni_log(NI_LOG_DEBUG, "First in ts list, return it\n");
2277  *p_timestamp = temp->timestamp;
2278 
2279  p_queue->p_first = temp->p_next;
2280  temp->p_next->p_prev = NULL;
2281 
2282  ni_buffer_pool_return_buffer(temp, p_buffer_pool);
2283  p_queue->count--;
2284  found = 1;
2285  break;
2286  }
2287 
2288  // retrieve from p_prev and delete p_prev !
2289  *p_timestamp = temp->p_prev->timestamp;
2290  temp = temp->p_prev;
2291  temp_prev = temp->p_prev;
2292 
2293  if (temp_prev)
2294  {
2295  temp_prev->p_next = temp->p_next;
2296  if (temp->p_next)
2297  {
2298  temp->p_next->p_prev = temp_prev;
2299  } else
2300  {
2301  p_queue->p_last = temp_prev;
2302  }
2303  } else
2304  {
2305  p_queue->p_first = temp->p_next;
2306  temp->p_next->p_prev = NULL;
2307  }
2308  //free(temp);
2309  ni_buffer_pool_return_buffer(temp, p_buffer_pool);
2310  p_queue->count--;
2311  found = 1;
2312  break;
2313  }
2314  temp = temp->p_next;
2315  count++;
2316  }
2317  }
2318 
2319  if (print)
2320  {
2321  ni_log(NI_LOG_DEBUG, "%s %s %d iterations ..\n", __func__,
2322  p_queue->name, count);
2323  }
2324 
2325  if (!found)
2326  {
2327  retval = NI_RETCODE_FAILURE;
2328  }
2329 
2330 END:
2331 
2332  return retval;
2333 }
2334 
2335 ni_retcode_t ni_queue_pop_threshold(ni_queue_t *p_queue, uint64_t frame_info,
2336  int64_t *p_timestamp, int32_t threshold,
2337  int32_t print,
2338  ni_queue_buffer_pool_t *p_buffer_pool)
2339 {
2340  ni_queue_node_t *temp;
2341  ni_queue_node_t *temp_prev = NULL;
2342  int32_t found = 0;
2343  int32_t count = 0;
2345 
2346  if (!p_queue || !p_timestamp)
2347  {
2348  ni_log(NI_LOG_ERROR, "%s: error, null pointer parameters passed\n",
2349  __func__);
2350  retval = NI_RETCODE_INVALID_PARAM;
2351  LRETURN;
2352  }
2353 
2354  if (p_queue->p_first == NULL)
2355  {
2356  ni_log(NI_LOG_DEBUG, "%s: queue is empty...\n", __func__);
2357  retval = NI_RETCODE_FAILURE;
2358  LRETURN;
2359  }
2360 
2361  if (p_queue->p_first == p_queue->p_last)
2362  {
2364  *p_timestamp = p_queue->p_first->timestamp;
2365  // free(p_queue->p_first);
2366  ni_buffer_pool_return_buffer(p_queue->p_first, p_buffer_pool);
2367 
2368  p_queue->p_first = NULL;
2369  p_queue->p_last = NULL;
2370  p_queue->count--;
2371  found = 1;
2372  } else
2373  {
2374  temp = p_queue->p_first;
2375  while ((temp) && (!found))
2376  {
2377  if (llabs((int)frame_info - (int)temp->frame_info) <= threshold)
2378  {
2379  *p_timestamp = temp->timestamp;
2380  if (temp_prev)
2381  {
2382  temp_prev->p_next = temp->p_next;
2383  if (temp->p_next)
2384  {
2385  temp->p_next->p_prev = temp_prev;
2386  } else
2387  {
2388  p_queue->p_last = temp_prev;
2389  }
2390  } else
2391  {
2392  p_queue->p_first = temp->p_next;
2393  temp->p_next->p_prev = NULL;
2394  }
2395  // free(temp);
2396  ni_buffer_pool_return_buffer(temp, p_buffer_pool);
2397  p_queue->count--;
2398  found = 1;
2399  break;
2400  }
2401  temp_prev = temp;
2402  temp = temp->p_next;
2403  count++;
2404  }
2405  }
2406 
2407  if (print)
2408  {
2409  ni_log(NI_LOG_DEBUG, "%s %s %d iterations ..\n", __func__,
2410  p_queue->name, count);
2411  }
2412 
2413  if (!found)
2414  {
2415  retval = NI_RETCODE_FAILURE;
2416  }
2417 
2418 END:
2419 
2420  return retval;
2421 }
2422 
2423 /*!******************************************************************************
2424  * \brief Free xcoder queue
2425  *
2426  * \param
2427  *
2428  * \return
2429  *******************************************************************************/
2431 {
2432  ni_queue_node_t *temp = NULL;
2433  ni_queue_node_t *temp_next;
2434  int32_t left = 0;
2435 
2436  if (!p_queue)
2437  {
2438  return NI_RETCODE_SUCCESS;
2439  }
2440 
2441  ni_log(NI_LOG_DEBUG, "Entries before clean up: \n");
2442  ni_queue_print(p_queue);
2443 
2444  temp = p_queue->p_first;
2445  while (temp)
2446  {
2447  temp_next = temp->p_next;
2448  //free(temp);
2449  ni_buffer_pool_return_buffer(temp, p_buffer_pool);
2450  temp = temp_next;
2451  left++;
2452  }
2453  ni_log(NI_LOG_DEBUG, "Entries cleaned up at ni_queue_free: %d, count: %u\n",
2454  left, p_queue->count);
2455 
2456  //ni_queue_print(p_queue);
2457 
2458  p_queue->count = 0;
2459 
2460  return NI_RETCODE_SUCCESS;
2461 }
2462 
2463 /*!******************************************************************************
2464  * \brief Print xcoder queue info
2465  *
2466  * \param
2467  *
2468  * \return
2469  *******************************************************************************/
2471 {
2472  ni_queue_node_t *temp = NULL;
2473  char buff[20] = {0};
2474 
2475  if (!p_queue)
2476  {
2477  return NI_RETCODE_SUCCESS;
2478  }
2479 
2480  ni_log(NI_LOG_DEBUG, "Queue [%s] Count: %u\n", p_queue->name,
2481  p_queue->count);
2482 
2483  ni_log(NI_LOG_DEBUG, "\nForward:\n");
2484 
2485  temp = p_queue->p_first;
2486 
2487  ni_log(NI_LOG_DEBUG, "%s enter: p_first=%p, p_last=%p, count=%u, temp=%p\n",
2488  __func__, p_queue->p_first, p_queue->p_last, p_queue->count, temp);
2489 
2490  // ni_log(NI_LOG_TRACE, "%s enter: p_first=%" PRId64 ", p_last=%" PRId64 ", count=%d, temp=%" PRId64 "\n", __func__, p_queue->p_first, p_queue->p_last, p_queue->count, temp);
2491 
2492  struct tm *ltime = NULL;
2493  struct tm temp_time;
2494  while (temp)
2495  {
2496  ltime = ni_localtime(&temp_time, &temp->checkout_timestamp);
2497  if (ltime)
2498  {
2499  strftime(buff, 20, "%Y-%m-%d %H:%M:%S", ltime);
2500  ni_log(NI_LOG_TRACE, " %s [%" PRId64 ", %" PRId64 "]", buff,
2501  temp->timestamp, temp->frame_info);
2502  }
2503  temp = temp->p_next;
2504  }
2505 
2506  ni_log(NI_LOG_DEBUG, "\nBackward:");
2507 
2508  temp = p_queue->p_last;
2509  while (temp)
2510  {
2511  ni_log(NI_LOG_TRACE, " [%" PRId64 ", %" PRId64 "]\n", temp->timestamp,
2512  temp->frame_info);
2513  temp = temp->p_prev;
2514  }
2515  ni_log(NI_LOG_DEBUG, "\n");
2516 
2517  return NI_RETCODE_SUCCESS;
2518 }
2519 
2520 /*!******************************************************************************
2521  * \brief Convert string to boolean
2522  *
2523  * \param
2524  *
2525  * \return
2526  *******************************************************************************/
2527 int32_t ni_atobool(const char *p_str, bool *b_error)
2528 {
2529  if (!strcmp(p_str, "1") || !strcmp(p_str, "true") || !strcmp(p_str, "yes"))
2530  {
2531  return 1;
2532  }
2533 
2534  if (!strcmp(p_str, "0") || !strcmp(p_str, "false") || !strcmp(p_str, "no"))
2535  {
2536  return 0;
2537  }
2538 
2539  *b_error = true;
2540  return 0;
2541 }
2542 
2543 /*!******************************************************************************
2544  * \brief Convert string to integer
2545  *
2546  * \param
2547  *
2548  * \return
2549  *******************************************************************************/
2550 int32_t ni_atoi(const char *p_str, bool *b_error)
2551 {
2552  char *end;
2553  int32_t v = strtol(p_str, &end, 0);
2554 
2555  if (end == p_str || *end != '\0')
2556  {
2557  *b_error = true;
2558  }
2559 
2560  return v;
2561 }
2562 
2563 /*!******************************************************************************
2564  * \brief Convert string to floating
2565  *
2566  * \param
2567  *
2568  * \return
2569  *******************************************************************************/
2570 double ni_atof(const char *p_str, bool *b_error)
2571 {
2572  char *end;
2573  double v = strtod(p_str, &end);
2574 
2575  if (end == p_str || *end != '\0')
2576  {
2577  *b_error = true;
2578  }
2579 
2580  return v;
2581 }
2582 
2583 /*!******************************************************************************
2584  * \brief Parse name
2585  *
2586  * \param
2587  *
2588  * \return
2589  *******************************************************************************/
2590 int32_t ni_parse_name(const char *arg, const char *const *names, bool *b_error)
2591 {
2592  int32_t i;
2593  for (i = 0; names[i]; i++)
2594  {
2595  if (!strcmp(arg, names[i]))
2596  {
2597  return i;
2598  }
2599  }
2600 
2601  return ni_atoi(arg, b_error);
2602 }
2603 
2604 /*!******************************************************************************
2605  * \brief Get system time for log
2606  *
2607  * \param
2608  *
2609  * \return
2610  *******************************************************************************/
2611 uint64_t ni_get_utime(void)
2612 {
2613  struct timeval tv;
2614  (void)ni_gettimeofday(&tv, NULL);
2615  return (tv.tv_sec * 1000000LL + tv.tv_usec);
2616 }
2617 
2618 uint64_t ni_gettime_ns(void)
2619 {
2620 #ifdef _WIN32
2621  LARGE_INTEGER frequency;
2622  LARGE_INTEGER count;
2623  uint64_t time_sec, time_nsec;
2624 
2625  // Get frequency firstly
2626  QueryPerformanceFrequency(&frequency);
2627 
2628  QueryPerformanceCounter(&count);
2629 
2630  time_sec = count.QuadPart / frequency.QuadPart;
2631  time_nsec = (count.QuadPart - time_sec * frequency.QuadPart) *
2632  1000000000LL / frequency.QuadPart;
2633 
2634  return (time_sec * 1000000000LL + time_nsec);
2635 #else
2636  struct timespec ts;
2637  clock_gettime(CLOCK_REALTIME, &ts);
2638  return ts.tv_sec * 1000000000LL + ts.tv_nsec;
2639 #endif
2640 }
2641 
2642 // Netint HW YUV420p data layout related utility functions
2643 
2644 /*!*****************************************************************************
2645  * \brief Get dimension information of Netint HW YUV420p frame to be sent
2646  * to encoder for encoding. Caller usually retrieves this info and
2647  * uses it in the call to ni_encoder_frame_buffer_alloc for buffer
2648  * allocation.
2649  *
2650  * \param[in] width source YUV frame width
2651  * \param[in] height source YUV frame height
2652  * \param[in] factor 1 for 8 bit, 2 for 10 bit
2653  * \param[in] is_semiplanar 1 for semiplanar frame, 0 otherwise
2654  * \param[out] plane_stride size (in bytes) of each plane width
2655  * \param[out] plane_height size of each plane height
2656  *
2657  * \return Y/Cb/Cr stride and height info
2658  *
2659  ******************************************************************************/
2660 void ni_get_hw_yuv420p_dim(int width, int height, int factor,
2661  int is_semiplanar,
2662  int plane_stride[NI_MAX_NUM_DATA_POINTERS],
2663  int plane_height[NI_MAX_NUM_DATA_POINTERS])
2664 {
2665  // strides are multiples of 128
2666  if (width < NI_MIN_WIDTH)
2667  {
2668  plane_stride[0] = ((NI_MIN_WIDTH * factor + 127) / 128) * 128;
2669  plane_stride[1] =
2670  (((NI_MIN_WIDTH / (is_semiplanar ? 1 : 2) * factor) + 127) /
2671  128) *
2672  128;
2673  plane_stride[2] = (is_semiplanar ? 0 : plane_stride[1]);
2674  } else
2675  {
2676  width = ((width + 1) / 2) * 2; // pad odd resolution
2677  plane_stride[0] = ((width * factor + 127) / 128) * 128;
2678  plane_stride[1] =
2679  (((width / (is_semiplanar ? 1 : 2) * factor) + 127) / 128) *
2680  128;
2681  plane_stride[2] = (is_semiplanar ? 0 : plane_stride[1]);
2682  }
2683 
2684  // height (in lines) just needs to be even number
2685  if (height < NI_MIN_HEIGHT)
2686  {
2687  plane_height[0] = NI_MIN_HEIGHT;
2688  } else
2689  {
2690  plane_height[0] = ((height + 1) / 2) * 2;
2691  }
2692  plane_height[1] = plane_height[2] = plane_height[0] / 2;
2693 }
2694 
2695 /*!*****************************************************************************
2696  * \brief Get dimension information of frame to be sent
2697  * to encoder for encoding. Caller usually retrieves this info and
2698  * uses it in the call to ni_encoder_frame_buffer_alloc for buffer
2699  * allocation.
2700  * The returned stride and height info will take alignment
2701  * requirements into account.
2702  *
2703  * \param[in] width source frame width
2704  * \param[in] height source frame height
2705  * \param[in] pix_fmt ni pixel format
2706  * \param[out] plane_stride size (in bytes) of each plane width
2707  * \param[out] plane_height size of each plane height
2708  *
2709  * \return stride and height info
2710  *
2711  ******************************************************************************/
2712 void ni_get_frame_dim(int width, int height,
2713  ni_pix_fmt_t pix_fmt,
2714  int plane_stride[NI_MAX_NUM_DATA_POINTERS],
2715  int plane_height[NI_MAX_NUM_DATA_POINTERS])
2716 {
2717  plane_height[0] = ((height + 1) / 2) * 2;
2718  plane_height[1] = plane_height[2] = plane_height[0] / 2;
2719 
2720  switch (pix_fmt)
2721  {
2722  /* 8-bit YUV420 planar */
2723  case NI_PIX_FMT_YUV420P:
2724  plane_stride[0] = NI_VPU_ALIGN128(width);
2725  plane_stride[1] = NI_VPU_ALIGN128((width / 2));
2726  plane_stride[2] = plane_stride[1];
2727  plane_stride[3] = 0;
2728  break;
2729  /* 10-bit YUV420 planar, little-endian, least significant bits */
2731  plane_stride[0] = NI_VPU_ALIGN128(width * 2);
2732  plane_stride[1] = NI_VPU_ALIGN128(width);
2733  plane_stride[2] = plane_stride[1];
2734  plane_stride[3] = 0;
2735  break;
2736  /* 8-bit YUV420 semi-planar */
2737  case NI_PIX_FMT_NV12:
2738  plane_stride[0] = NI_VPU_ALIGN128(width);
2739  plane_stride[1] = plane_stride[0];
2740  plane_stride[2] = 0;
2741  plane_stride[3] = 0;
2742  break;
2743  /* 8-bit yuv422 semi-planar */
2744  case NI_PIX_FMT_NV16:
2745  plane_stride[0] = NI_VPU_ALIGN64(width);
2746  plane_stride[1] = plane_stride[0];
2747  plane_stride[2] = 0;
2748  plane_stride[3] = 0;
2749  break;
2750  /*8-bit yuv422 planar */
2751  case NI_PIX_FMT_YUYV422:
2752  case NI_PIX_FMT_UYVY422:
2753  plane_stride[0] = NI_VPU_ALIGN16(width) * 2;
2754  plane_stride[1] = 0;
2755  plane_stride[2] = 0;
2756  plane_stride[3] = 0;
2757  break;
2758  /* 10-bit YUV420 semi-planar, little endian, most significant bits */
2759  case NI_PIX_FMT_P010LE:
2760  plane_stride[0] = NI_VPU_ALIGN128(width * 2);
2761  plane_stride[1] = plane_stride[0];
2762  plane_stride[2] = 0;
2763  plane_stride[3] = 0;
2764  break;
2765  /* 32-bit RGBA packed */
2766  case NI_PIX_FMT_ARGB:
2767  case NI_PIX_FMT_ABGR:
2768  case NI_PIX_FMT_RGBA:
2769  case NI_PIX_FMT_BGRA:
2770  case NI_PIX_FMT_BGR0:
2771  plane_height[1] = plane_height[2] = 0;
2772 
2773  plane_stride[0] = NI_VPU_ALIGN16(width) * 4;
2774  plane_stride[1] = 0;
2775  plane_stride[2] = 0;
2776  plane_stride[3] = 0;
2777  break;
2778  default:
2779  break;
2780  }
2781 
2782 }
2783 
2784 /*!*****************************************************************************
2785  * \brief Get dimension information of frame to be sent
2786  * to encoder for encoding. Caller usually retrieves this info and
2787  * uses it in the call to ni_encoder_frame_buffer_alloc for buffer
2788  * allocation.
2789  * The returned stride and height info will take into account both min
2790  * resolution and alignment requirements.
2791  *
2792  * \param[in] width source frame width
2793  * \param[in] height source frame height
2794  * \param[in] pix_fmt ni pixel format
2795  * \param[out] plane_stride size (in bytes) of each plane width
2796  * \param[out] plane_height size of each plane height
2797  *
2798  * \return stride and height info
2799  *
2800  ******************************************************************************/
2801 void ni_get_min_frame_dim(int width, int height,
2802  ni_pix_fmt_t pix_fmt,
2803  int plane_stride[NI_MAX_NUM_DATA_POINTERS],
2804  int plane_height[NI_MAX_NUM_DATA_POINTERS])
2805 {
2806 
2807  if (height < NI_MIN_HEIGHT)
2808  {
2809  height = NI_MIN_HEIGHT;
2810  }
2811  if (width < NI_MIN_WIDTH)
2812  {
2813  width = NI_MIN_WIDTH;
2814  }
2815  else
2816  {
2817  width = ((width + 1) / 2) * 2; // pad odd resolution
2818  }
2819 
2820  ni_get_frame_dim(width, height, pix_fmt, plane_stride, plane_height);
2821 
2823  "%s dst_stride %d/%d/%d height %d/%d/%d pix_fmt %d\n",
2824  __func__, plane_stride[0], plane_stride[1], plane_stride[2],
2825  plane_height[0], plane_height[1], plane_height[2], pix_fmt);
2826 }
2827 
2828 /*!*****************************************************************************
2829  * \brief Copy RGBA or YUV data to Netint HW frame layout to be sent
2830  * to encoder for encoding. Data buffer (dst) is usually allocated by
2831  * ni_encoder_frame_buffer_alloc.
2832  *
2833  * \param[out] p_dst pointers to which data is copied
2834  * \param[in] p_src pointers from which data is copied
2835  * \param[in] width source frame width
2836  * \param[in] height source frame height
2837  * \param[in] factor 1 for 8 bit, 2 for 10 bit
2838  * \param[in] is_semiplanar non-0 for semiplanar frame, 0 otherwise
2839  * \param[in] conf_win_right right offset of conformance window
2840  * \param[in] dst_stride size (in bytes) of each plane width in destination
2841  * \param[in] dst_height size of each plane height in destination
2842  * \param[in] src_stride size (in bytes) of each plane width in source
2843  * \param[in] src_height size of each plane height in source
2844  * \param[in] i index to plane to be copied
2845  *
2846  * \return copied data
2847  *
2848  ******************************************************************************/
2850  uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS],
2851  int frame_width, int frame_height, int factor,
2852  int is_semiplanar, int conf_win_right,
2853  int dst_stride[NI_MAX_NUM_DATA_POINTERS],
2854  int dst_height[NI_MAX_NUM_DATA_POINTERS],
2855  int src_stride[NI_MAX_NUM_DATA_POINTERS],
2856  int src_height[NI_MAX_NUM_DATA_POINTERS],
2857  int i)
2858 {
2859  if (i >= NI_MAX_NUM_DATA_POINTERS)
2860  {
2861  ni_log(NI_LOG_ERROR, "%s: error, invalid plane index %d\n", __func__,
2862  i);
2863  return;
2864  }
2865  if (p_dst[i] == p_src[i])
2866  {
2867  ni_log(NI_LOG_DEBUG, "%s: src and dst identical, return\n", __func__);
2868  return;
2869  }
2870 
2871  int height =
2872  (src_height[i] < dst_height[i] ? src_height[i] : dst_height[i]);
2873  uint8_t *dst = p_dst[i];
2874  const uint8_t *src = (const uint8_t *)p_src[i];
2875 
2876  // width padding length in bytes, if needed
2877  int pad_len_bytes;
2878 
2879  if (0 == i || is_semiplanar) // Y
2880  {
2881  pad_len_bytes = dst_stride[i] - frame_width * factor;
2882  }
2883  else
2884  {
2885  // U/V share the same padding length
2886  pad_len_bytes = dst_stride[i] - frame_width / 2 * factor;
2887  }
2888 
2889  if (0 == pad_len_bytes && conf_win_right > 0)
2890  {
2891  if (0 == i) // Y
2892  {
2893  pad_len_bytes = conf_win_right * factor;
2894  }
2895  else
2896  {
2897  // U/V share the same padding length
2898  pad_len_bytes = conf_win_right * factor / 2;
2899  }
2900  }
2901 
2903  "%s plane %d stride padding: %d pixel (%d bytes), copy height: "
2904  "%d.\n",
2905  __func__, i, pad_len_bytes / factor, pad_len_bytes,
2906  height);
2907 
2908  for (; height > 0; height--)
2909  {
2910  memcpy(dst, src,
2911  (src_stride[i] < dst_stride[i] ? src_stride[i] : dst_stride[i]));
2912  dst += dst_stride[i];
2913 
2914  // dst is now at the line end
2915  if (pad_len_bytes)
2916  {
2917  // repeat last pixel
2918  if (factor > 1)
2919  {
2920  // for 10 bit it's 2 bytes
2921  int j;
2922  uint8_t *tmp_dst = dst - pad_len_bytes;
2923  for (j = 0; j < pad_len_bytes / factor; j++)
2924  {
2925  memcpy(tmp_dst, dst - pad_len_bytes - factor, factor);
2926  tmp_dst += factor;
2927  }
2928  }
2929  else
2930  {
2931  memset(dst - pad_len_bytes, *(dst - pad_len_bytes - 1),
2932  pad_len_bytes);
2933  }
2934  }
2935  src += src_stride[i];
2936  }
2937 
2938  // height padding/cropping if needed
2939  int padding_height = dst_height[i] - src_height[i];
2940  if (padding_height > 0)
2941  {
2942  ni_log(NI_LOG_DEBUG, "%s plane %d padding height: %d\n", __func__,
2943  i, padding_height);
2944  src = dst - dst_stride[i];
2945  for (; padding_height > 0; padding_height--)
2946  {
2947  memcpy(dst, src, dst_stride[i]);
2948  dst += dst_stride[i];
2949  }
2950  }
2951 }
2952 /*!*****************************************************************************
2953  * \brief Copy YUV data to Netint HW YUV420p frame layout to be sent
2954  * to encoder for encoding. Data buffer (dst) is usually allocated by
2955  * ni_encoder_frame_buffer_alloc.
2956  *
2957  * \param[out] p_dst pointers of Y/Cb/Cr to which data is copied
2958  * \param[in] p_src pointers of Y/Cb/Cr from which data is copied
2959  * \param[in] width source YUV frame width
2960  * \param[in] height source YUV frame height
2961  * \param[in] factor 1 for 8 bit, 2 for 10 bit
2962  * \param[in] is_semiplanar non-0 for semiplanar frame, 0 otherwise
2963  * \param[in] conf_win_right right offset of conformance window
2964  * \param[in] dst_stride size (in bytes) of each plane width in destination
2965  * \param[in] dst_height size of each plane height in destination
2966  * \param[in] src_stride size (in bytes) of each plane width in source
2967  * \param[in] src_height size of each plane height in source
2968  *
2969  * \return Y/Cb/Cr data
2970  *
2971  ******************************************************************************/
2973  uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS],
2974  int frame_width, int frame_height, int factor,
2975  int is_semiplanar, int conf_win_right,
2976  int dst_stride[NI_MAX_NUM_DATA_POINTERS],
2977  int dst_height[NI_MAX_NUM_DATA_POINTERS],
2978  int src_stride[NI_MAX_NUM_DATA_POINTERS],
2979  int src_height[NI_MAX_NUM_DATA_POINTERS])
2980 {
2982  "%s dst_stride %d/%d/%d src_stride %d/%d/%d dst_height "
2983  "%d/%d/%d src_height %d/%d/%d\n",
2984  __func__, dst_stride[0], dst_stride[1], dst_stride[2], src_stride[0],
2985  src_stride[1], src_stride[2], dst_height[0], dst_height[1],
2986  dst_height[2], src_height[0], src_height[1], src_height[2]);
2987 
2988  int i;
2989 
2990  for (i = 0; i < NI_MAX_NUM_DATA_POINTERS - 1; i++)
2991  {
2992  ni_copy_plane_data(p_dst, p_src, frame_width, frame_height, factor,
2993  is_semiplanar, conf_win_right, dst_stride,
2994  dst_height, src_stride, src_height, i);
2995  }
2996 }
2997 
2998 /*!*****************************************************************************
2999  * \brief Copy RGBA or YUV data to Netint HW frame layout to be sent
3000  * to encoder for encoding. Data buffer (dst) is usually allocated by
3001  * ni_encoder_frame_buffer_alloc.
3002  *
3003  * \param[out] p_dst pointers to which data is copied
3004  * \param[in] p_src pointers from which data is copied
3005  * \param[in] width source frame width
3006  * \param[in] height source frame height
3007  * \param[in] factor 1 for 8 bit, 2 for 10 bit
3008  * \param[in] pix_fmt pixel format to distinguish between planar types and/or components
3009  * \param[in] conf_win_right right offset of conformance window
3010  * \param[in] dst_stride size (in bytes) of each plane width in destination
3011  * \param[in] dst_height size of each plane height in destination
3012  * \param[in] src_stride size (in bytes) of each plane width in source
3013  * \param[in] src_height size of each plane height in source
3014  *
3015  * \return copied data
3016  *
3017  ******************************************************************************/
3019  uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS],
3020  int frame_width, int frame_height,
3021  int factor, ni_pix_fmt_t pix_fmt,
3022  int conf_win_right,
3023  int dst_stride[NI_MAX_NUM_DATA_POINTERS],
3024  int dst_height[NI_MAX_NUM_DATA_POINTERS],
3025  int src_stride[NI_MAX_NUM_DATA_POINTERS],
3026  int src_height[NI_MAX_NUM_DATA_POINTERS])
3027 {
3029  "%s frame_width %d frame_height %d factor %d conf_win_right %d "
3030  "dst_stride %d/%d/%d src_stride %d/%d/%d dst_height "
3031  "%d/%d/%d src_height %d/%d/%d pix_fmt %d\n",
3032  __func__, frame_width, frame_height, factor, conf_win_right,
3033  dst_stride[0], dst_stride[1], dst_stride[2], src_stride[0],
3034  src_stride[1], src_stride[2], dst_height[0], dst_height[1],
3035  dst_height[2], src_height[0], src_height[1], src_height[2],
3036  pix_fmt);
3037 
3038  int is_rgba = 0;
3039  int is_semiplanar = 0;
3040  switch (pix_fmt)
3041  {
3042  case NI_PIX_FMT_NV12:
3043  case NI_PIX_FMT_P010LE:
3044  is_semiplanar = 1;
3045  break;
3046  case NI_PIX_FMT_ARGB:
3047  case NI_PIX_FMT_ABGR:
3048  case NI_PIX_FMT_RGBA:
3049  case NI_PIX_FMT_BGRA:
3050  is_rgba = 1;
3051  break;
3052  default:
3053  break;
3054  }
3055 
3056  if (is_rgba)
3057  {
3058  ni_copy_plane_data(p_dst, p_src,
3059  frame_width, frame_height, 4,
3060  is_semiplanar, conf_win_right,
3061  dst_stride, dst_height,
3062  src_stride, src_height,
3063  0); // just one plane for rgba
3064  }
3065  else
3066  {
3067  ni_copy_hw_yuv420p(p_dst, p_src, frame_width, frame_height, factor,
3068  is_semiplanar, conf_win_right, dst_stride,
3069  dst_height, src_stride, src_height);
3070  }
3071 }
3072 
3073 /*!*****************************************************************************
3074  * \brief Copy yuv444p data to yuv420p frame layout to be sent
3075  * to encoder for encoding. Data buffer (dst) is usually allocated by
3076  * ni_encoder_frame_buffer_alloc.
3077  *
3078  * \param[out] p_dst0 pointers of Y/Cb/Cr as yuv420p output0
3079  * \param[out] p_dst1 pointers of Y/Cb/Cr as yuv420p output1
3080  * \param[in] p_src pointers of Y/Cb/Cr as yuv444p intput
3081  * \param[in] width source YUV frame width
3082  * \param[in] height source YUV frame height
3083  * \param[in] factor 1 for 8 bit, 2 for 10 bit
3084  * \param[in] mode 0 for
3085  * out0 is Y+1/2V, with the original input as the out0, 1/4V
3086  * copy to data[1] 1/4V copy to data[2]
3087  * out1 is U+1/2V, U copy to data[0], 1/4V copy to data[1], 1/4V
3088  * copy to data[2]
3089  * mode 1 for
3090  * out0 is Y+1/2u+1/2v, with the original input as the output0,
3091  * 1/4U copy to data[1] 1/4V copy to data[2]
3092  * out1 is (1/2U+1/2V)+1/4U+1/4V, 1/2U & 1/2V copy to data[0],
3093  * 1/4U copy to data[1], 1/4V copy to data[2]
3094  *
3095  * \return Y/Cb/Cr data
3096  *
3097  ******************************************************************************/
3099  uint8_t *p_dst1[NI_MAX_NUM_DATA_POINTERS],
3100  uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS],
3101  int frame_width, int frame_height,
3102  int factor, int mode)
3103 {
3104  int i, j;
3105  int y_444p_linesize = frame_width * factor;
3106  int uv_444p_linesize = y_444p_linesize;
3107  int y_420p_linesize = NI_VPU_ALIGN128(y_444p_linesize);
3108  int uv_420p_linesize = NI_VPU_ALIGN128(uv_444p_linesize / 2);
3109 
3110  // return to avoid self copy
3111  if (p_dst0[0] == p_dst1[0] && p_dst0[1] == p_dst1[1] &&
3112  p_dst0[2] == p_dst1[2])
3113  {
3114  ni_log(NI_LOG_DEBUG, "%s: src and dst identical, return\n", __func__);
3115  return;
3116  }
3117 
3118  // Y component
3119  for (i = 0; i < frame_height; i++)
3120  {
3121  memcpy(&p_dst0[0][i * y_420p_linesize], &p_src[0][i * y_444p_linesize],
3122  y_444p_linesize);
3123  }
3124 
3125  if (mode == 0)
3126  {
3127  // out0 data[0]: Y data[1]: 0.25V data[2]: 0.25V
3128  // out1 data[0]: U data[1]: 0.25V data[2]: 0.25V
3129  // U component
3130  for (i = 0; i < frame_height; i++)
3131  {
3132  memcpy(&p_dst1[0][i * y_420p_linesize],
3133  &p_src[1][i * y_444p_linesize], y_444p_linesize);
3134  }
3135 
3136  for (i = 0; i < frame_height / 2; i++)
3137  {
3138  for (j = 0; j < frame_width * factor / 2; j += factor)
3139  {
3140  // V component
3141  // even line
3142  memcpy(&p_dst0[1][i * uv_420p_linesize + j],
3143  &p_src[2][2 * i * uv_444p_linesize + 2 * j],
3144  factor);
3145  memcpy(&p_dst0[2][i * uv_420p_linesize + j],
3146  &p_src[2][2 * i * uv_444p_linesize + (2 * j + factor)],
3147  factor);
3148  // odd line
3149  memcpy(&p_dst1[1][i * uv_420p_linesize + j],
3150  &p_src[2][(2 * i + 1) * uv_444p_linesize + 2 * j],
3151  factor);
3152  memcpy(&p_dst1[2][i * uv_420p_linesize + j],
3153  &p_src[2][(2 * i + 1) * uv_444p_linesize + (2 * j + factor)],
3154  factor);
3155  }
3156  }
3157  } else
3158  {
3159  // out0 data[0]: Y data[1]: 0.25U data[2]: 0.25V
3160  // out1 data[0]: 0.5U + 0.5V data[1]: 0.25U data[2]: 0.25V
3161  for (i = 0; i < frame_height / 2; i++)
3162  {
3163  for (j = 0; j < frame_width * factor / 2; j += factor)
3164  {
3165  // U component
3166  // even line 0.25U
3167  memcpy(&p_dst1[1][i * uv_420p_linesize + j],
3168  &p_src[1][2 * i * uv_444p_linesize + (2 * j + factor)],
3169  factor);
3170  // odd line 0.5U
3171  memcpy(&p_dst1[0][2 * i * uv_444p_linesize + 2 * j],
3172  &p_src[1][(2 * i + 1) * uv_444p_linesize + 2 * j],
3173  factor * 2);
3174  // even line 0.25U
3175  memcpy(&p_dst0[1][i * uv_420p_linesize + j],
3176  &p_src[1][2 * i * uv_444p_linesize + 2 * j],
3177  factor);
3178 
3179  // V component
3180  // even line 0.25V
3181  memcpy(&p_dst1[2][i * uv_420p_linesize + j],
3182  &p_src[2][2 * i * uv_444p_linesize + (2 * j + factor)],
3183  factor);
3184  // odd line 0.5V
3185  memcpy(&p_dst1[0][(2 * i + 1) * uv_444p_linesize + 2 * j],
3186  &p_src[2][(2 * i + 1) * uv_444p_linesize + 2 * j],
3187  factor * 2);
3188  // even line 0.25V
3189  memcpy(&p_dst0[2][i * uv_420p_linesize + j],
3190  &p_src[2][2 * i * uv_444p_linesize + 2 * j],
3191  factor);
3192  }
3193  }
3194  }
3195 }
3196 
3197 // NAL operations
3198 
3199 /*!*****************************************************************************
3200  * \brief Insert emulation prevention byte(s) as needed into the data buffer
3201  *
3202  * \param buf data buffer to be worked on - new byte(s) will be inserted
3203  * size number of bytes starting from buf to check
3204  *
3205  * \return the number of emulation prevention bytes inserted into buf, 0 if
3206  * none.
3207  *
3208  * Note: caller *MUST* ensure for newly inserted bytes, buf has enough free
3209  * space starting from buf + size
3210  ******************************************************************************/
3211 int ni_insert_emulation_prevent_bytes(uint8_t *buf, int size)
3212 {
3213  int insert_bytes = 0;
3214  uint8_t *buf_curr = buf;
3215  uint8_t *buf_end = buf + size - 1;
3216  int zeros = 0, insert_ep3_byte;
3217 
3218  ni_log(NI_LOG_TRACE, "%s: enter\n", __func__);
3219 
3220  for (; buf_curr <= buf_end; buf_curr++)
3221  {
3222  if (zeros == 2)
3223  {
3224  insert_ep3_byte = (*buf_curr <= 3);
3225  if (insert_ep3_byte)
3226  {
3227  // move bytes from curr to end 1 position to make space for ep3
3228  memmove(buf_curr + 1, buf_curr, buf_end - buf_curr + 1);
3229  *buf_curr = 0x3;
3230 
3231  buf_curr++;
3232  buf_end++;
3233  insert_bytes++;
3234  }
3235 
3236  zeros = 0;
3237  }
3238 
3239  if (!*buf_curr)
3240  {
3241  zeros++;
3242  } else
3243  {
3244  zeros = 0;
3245  }
3246  }
3247 
3248  ni_log(NI_LOG_TRACE, "%s: %d, exit\n", __func__, insert_bytes);
3249  return insert_bytes;
3250 }
3251 
3252 /*!*****************************************************************************
3253  * \brief Remove emulation prevention byte(s) as needed from the data buffer
3254  *
3255  * \param buf data buffer to be worked on - emu prevent byte(s) will be
3256  * removed from.
3257  * size number of bytes starting from buf to check
3258  *
3259  * \return the number of emulation prevention bytes removed from buf, 0 if
3260  * none.
3261  *
3262  * Note: buf will be modified if emu prevent byte(s) found and removed.
3263  ******************************************************************************/
3264 int ni_remove_emulation_prevent_bytes(uint8_t *buf, int size)
3265 {
3266  int remove_bytes = 0;
3267  uint8_t *buf_curr = buf;
3268  uint8_t *buf_end = buf + size - 1;
3269  int zeros = 0, remove_ep3_byte;
3270 
3271  ni_log(NI_LOG_TRACE, "%s: enter\n", __func__);
3272 
3273  for (; buf_curr < buf_end; buf_curr++)
3274  {
3275  if (zeros == 2)
3276  {
3277  remove_ep3_byte = (*buf_curr == 0x03 && *(buf_curr + 1) <= 3);
3278  if (remove_ep3_byte)
3279  {
3280  // move bytes after curr to end, 1 position forward to overwrite ep3
3281  memmove(buf_curr, buf_curr + 1, buf_end - buf_curr);
3282 
3283  // buf_curr unchanged
3284  buf_end--;
3285  remove_bytes++;
3286  }
3287 
3288  zeros = 0;
3289  }
3290 
3291  if (!*buf_curr)
3292  {
3293  zeros++;
3294  } else
3295  {
3296  zeros = 0;
3297  }
3298  }
3299 
3300  ni_log(NI_LOG_TRACE, "%s: %d, exit\n", __func__, remove_bytes);
3301  return remove_bytes;
3302 }
3303 
3304 /******************************************************************************
3305  *
3306  * Ai utils apis
3307  *
3308  ******************************************************************************/
3309 static uint32_t ni_ai_type_get_bytes(const uint32_t type)
3310 {
3311  switch (type)
3312  {
3315  return 1;
3320  return 2;
3324  return 4;
3328  return 8;
3329 
3330  default:
3331  return 0;
3332  }
3333 }
3334 
3335 static void ni_ai_integer_convert(const void *src, void *dest,
3336  ni_ai_buffer_format_e src_dtype,
3337  ni_ai_buffer_format_e dst_dtype)
3338 {
3339  unsigned char all_zeros[] = {0x00, 0x00, 0x00, 0x00,
3340  0x00, 0x00, 0x00, 0x00};
3341  unsigned char all_ones[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3342  uint32_t src_sz = ni_ai_type_get_bytes(src_dtype);
3343  uint32_t dest_sz = ni_ai_type_get_bytes(dst_dtype);
3344  unsigned char *buffer = all_zeros;
3345 
3346  if (((int8_t *)src)[src_sz - 1] & 0x80)
3347  {
3348  buffer = all_ones;
3349  }
3350  memcpy(buffer, src, src_sz);
3351  memcpy(dest, buffer, dest_sz);
3352 }
3353 
3354 static float ni_ai_int8_to_fp32(signed char val, signed char fixedPointPos)
3355 {
3356  float result = 0.0f;
3357 
3358  if (fixedPointPos > 0)
3359  {
3360  result = (float)val * (1.0f / ((float)(1 << fixedPointPos)));
3361  } else
3362  {
3363  result = (float)val * ((float)(1 << -fixedPointPos));
3364  }
3365 
3366  return result;
3367 }
3368 
3369 static float ni_ai_int16_to_fp32(int16_t val, signed char fixedPointPos)
3370 {
3371  float result = 0.0f;
3372 
3373  if (fixedPointPos > 0)
3374  {
3375  result = (float)val * (1.0f / ((float)(1 << fixedPointPos)));
3376  } else
3377  {
3378  result = (float)val * ((float)(1 << -fixedPointPos));
3379  }
3380 
3381  return result;
3382 }
3383 
3384 static float ni_ai_uint8_to_fp32(uint8_t val, int32_t zeroPoint, float scale)
3385 {
3386  float result = 0.0f;
3387 
3388  result = (float)(val - (uint8_t)zeroPoint) * scale;
3389 
3390  return result;
3391 }
3392 
3393 static float ni_ai_fp16_to_fp32(const short in)
3394 {
3395  typedef union
3396  {
3397  unsigned int u;
3398  float f;
3399  } _fp32_t;
3400 
3401  const _fp32_t magic = {(254 - 15) << 23};
3402  const _fp32_t infnan = {(127 + 16) << 23};
3403  _fp32_t o;
3404  // Non-sign bits
3405  o.u = (in & 0x7fff) << 13;
3406  o.f *= magic.f;
3407  if (o.f >= infnan.f)
3408  {
3409  o.u |= 255 << 23;
3410  }
3411  //Sign bit
3412  o.u |= (in & 0x8000) << 16;
3413  return o.f;
3414 }
3415 
3416 static float ni_ai_affine_to_fp32(int32_t val, int32_t zeroPoint, float scale)
3417 {
3418  float result = 0.0f;
3419  result = ((float)val - zeroPoint) * scale;
3420  return result;
3421 }
3422 
3423 static uint32_t ni_ai_get_tensor_size(int32_t *shape, uint32_t dim_num,
3424  int32_t type)
3425 {
3426  uint32_t sz;
3427  uint32_t i;
3428  sz = 0;
3429  if (NULL == shape || 0 == dim_num)
3430  {
3431  return sz;
3432  }
3433  sz = 1;
3434  for (i = 0; i < dim_num; i++)
3435  {
3436  sz *= shape[i];
3437  }
3438  sz *= ni_ai_type_get_bytes(type);
3439 
3440  return sz;
3441 }
3442 
3443 static uint32_t ni_ai_get_element_num(int32_t *sizes, uint32_t num_of_dims,
3444  int32_t data_format)
3445 {
3446  uint32_t num;
3447  uint32_t sz;
3448  uint32_t dsize;
3449 
3450  sz = ni_ai_get_tensor_size(sizes, num_of_dims, data_format);
3451  dsize = ni_ai_type_get_bytes(data_format);
3452  if (dsize)
3453  {
3454  num = (uint32_t)(sz / dsize);
3455  } else
3456  {
3457  num = 0;
3458  }
3459 
3460  return num;
3461 }
3462 
3463 static int32_t ni_ai_type_is_integer(const int32_t type)
3464 {
3465  int32_t ret = 0;
3466  switch (type)
3467  {
3474  ret = 1;
3475  break;
3476  default:
3477  break;
3478  }
3479 
3480  return ret;
3481 }
3482 
3483 static int32_t ni_ai_type_is_signed(const int32_t type)
3484 {
3485  int32_t ret = 0;
3486  switch (type)
3487  {
3494  ret = 1;
3495  break;
3496  default:
3497  break;
3498  }
3499 
3500  return ret;
3501 }
3502 
3503 static void ni_ai_type_get_range(int32_t type, double *max_range,
3504  double *min_range)
3505 {
3506  int32_t bits;
3507  double from, to;
3508  from = 0.0;
3509  to = 0.0;
3510  bits = ni_ai_type_get_bytes(type) * 8;
3511  if (ni_ai_type_is_integer(type))
3512  {
3513  if (ni_ai_type_is_signed(type))
3514  {
3515  from = (double)(-(1L << (bits - 1)));
3516  to = (double)((1UL << (bits - 1)) - 1);
3517  } else
3518  {
3519  from = 0.0;
3520  to = (double)((1UL << bits) - 1);
3521  }
3522  }
3523  if (NULL != max_range)
3524  {
3525  *max_range = to;
3526  }
3527  if (NULL != min_range)
3528  {
3529  *min_range = from;
3530  }
3531 }
3532 
3533 static inline double ni_abs(double x)
3534 {
3535  return x < 0 ? -x : x;
3536 }
3537 
3538 static double ni_ai_copy_sign(double number, double sign)
3539 {
3540  double value = ni_abs(number);
3541  return (sign > 0) ? value : (-value);
3542 }
3543 
3544 static inline int ni_ai_math_floorf(double x)
3545 {
3546  return x >= 0 ? (int)x : (int)x - 1;
3547 }
3548 
3549 static double ni_ai_rint(double x)
3550 {
3551 #define _EPSILON 1e-8
3552  double decimal;
3553  double inter;
3554  int intpart;
3555 
3556  intpart = (int)x;
3557  decimal = x - intpart;
3558  inter = (double)intpart;
3559 
3560  if (ni_abs((ni_abs(decimal) - 0.5f)) < _EPSILON)
3561  {
3562  inter += (int32_t)(inter) % 2;
3563  } else
3564  {
3565  return ni_ai_copy_sign(ni_ai_math_floorf(ni_abs(x) + 0.5f), x);
3566  }
3567 
3568  return inter;
3569 }
3570 
3571 static int32_t ni_ai_fp32_to_dfp(const float in, const signed char fl,
3572  const int32_t type)
3573 {
3574  int32_t data;
3575  double max_range;
3576  double min_range;
3577  ni_ai_type_get_range(type, &max_range, &min_range);
3578  if (fl > 0)
3579  {
3580  data = (int32_t)ni_ai_rint(in * (float)(1 << fl));
3581  } else
3582  {
3583  data = (int32_t)ni_ai_rint(in * (1.0f / (float)(1 << -fl)));
3584  }
3585  data = ni_min(data, (int32_t)max_range);
3586  data = ni_max(data, (int32_t)min_range);
3587 
3588  return data;
3589 }
3590 
3591 static int32_t ni_ai_fp32_to_affine(const float in, const float scale,
3592  const int zero_point, const int32_t type)
3593 {
3594  int32_t data;
3595  double max_range;
3596  double min_range;
3597  ni_ai_type_get_range(type, &max_range, &min_range);
3598  data = (int32_t)(ni_ai_rint(in / scale) + zero_point);
3599  data = ni_max((int32_t)min_range, ni_min((int32_t)max_range, data));
3600  return data;
3601 }
3602 
3603 static unsigned short ni_ai_fp32_to_bfp16_rtne(float in)
3604 {
3605  /*
3606  Convert a float point to bfloat16, with round-nearest-to-even as rounding method.
3607  */
3608  unsigned short out;
3609 
3610  uint32_t fp32;
3611  memcpy(&fp32, &in, sizeof(uint32_t));
3612 
3613  uint32_t lsb =
3614  (fp32 >> 16) & 1; /* Least significant bit of resulting bfloat. */
3615  uint32_t rounding_bias = 0x7fff + lsb;
3616 
3617  if ((float)0x7FC00000 == in)
3618  {
3619  out = 0x7fc0;
3620  } else
3621  {
3622  fp32 += rounding_bias;
3623  out = (unsigned short)(fp32 >> 16);
3624  }
3625 
3626  return out;
3627 }
3628 
3629 static unsigned short ni_ai_fp32_to_fp16(float in)
3630 {
3631  uint32_t fp32 = 0;
3632  uint32_t t1 = 0;
3633  uint32_t t2 = 0;
3634  uint32_t t3 = 0;
3635  uint32_t fp16 = 0u;
3636 
3637  memcpy((uint8_t *)&fp32, (uint8_t *)&in, sizeof(uint32_t));
3638 
3639  t1 = (fp32 & 0x80000000u) >> 16; /* sign bit. */
3640  t2 = (fp32 & 0x7F800000u) >> 13; /* Exponent bits */
3641  t3 = (fp32 & 0x007FE000u) >> 13; /* Mantissa bits, no rounding */
3642 
3643  if (t2 >= 0x023c00u)
3644  {
3645  fp16 = t1 | 0x7BFF; /* Don't round to infinity. */
3646  } else if (t2 <= 0x01c000u)
3647  {
3648  fp16 = t1;
3649  } else
3650  {
3651  t2 -= 0x01c000u;
3652  fp16 = t1 | t2 | t3;
3653  }
3654 
3655  return (unsigned short)fp16;
3656 }
3657 
3658 static void ni_ai_float32_to_dtype(float src, unsigned char *dst,
3659  const int32_t data_type,
3660  const int32_t quant_format,
3661  signed char fixed_point_pos, float tf_scale,
3662  int32_t tf_zerop)
3663 {
3664  switch (data_type)
3665  {
3667  memcpy(dst, &src, sizeof(float));
3668  break;
3670  *(int16_t *)dst = ni_ai_fp32_to_fp16(src);
3671  break;
3673  *(int16_t *)dst = ni_ai_fp32_to_bfp16_rtne(src);
3674  break;
3678  {
3679  int32_t dst_value = 0;
3680  switch (quant_format)
3681  {
3683  dst_value =
3684  ni_ai_fp32_to_dfp(src, fixed_point_pos, data_type);
3685  break;
3687  dst_value = ni_ai_fp32_to_affine(src, tf_scale, tf_zerop,
3688  data_type);
3689  break;
3691  dst_value = (int32_t)src;
3692  break;
3693  default:
3694  break;
3695  }
3696  ni_ai_integer_convert(&dst_value, dst, NI_AI_BUFFER_FORMAT_INT32,
3697  data_type);
3698  }
3699  break;
3700  default:;
3701  }
3702 }
3703 
3704 ni_retcode_t ni_network_layer_convert_output(float *dst, uint32_t dst_len,
3705  ni_packet_t *p_packet,
3706  ni_network_data_t *p_network,
3707  uint32_t layer)
3708 {
3709  uint8_t *data;
3710  uint32_t data_len;
3711  ni_network_layer_params_t *p_param;
3712 
3713  if (!p_network || !dst || dst_len == 0 || !p_packet || !p_packet->p_data)
3714  {
3715  return NI_RETCODE_INVALID_PARAM;
3716  }
3717 
3718  if (layer >= p_network->output_num)
3719  {
3720  return NI_RETCODE_INVALID_PARAM;
3721  }
3722 
3723  p_param = &p_network->linfo.out_param[layer];
3724  data = (uint8_t *)p_packet->p_data + p_network->outset[layer].offset;
3725  data_len = ni_ai_network_layer_size(p_param);
3726  return ni_network_convert_data_to_tensor(dst, dst_len, data, data_len,
3727  p_param);
3728 }
3729 
3731 {
3732  void *private;
3733  uint32_t total_num;
3734  uint32_t next_idx;
3735 };
3736 
3737 static int open_tensor_rsrc_file(struct tensor_rsrc *rsrc, void *data,
3738  uint32_t num)
3739 {
3740  FILE *f = NULL;
3741  ni_fopen(&f, (const char *)data, "r");
3742  rsrc->private = (void *)f;
3743  return rsrc->private ? 0 : -1;
3744 }
3745 
3746 static int get_tensor_rsrc_from_file(struct tensor_rsrc *rsrc, float *value)
3747 {
3748  FILE *fp = (FILE *)rsrc->private;
3749  float tensor;
3750 
3751  if (ni_fscanf(fp, "%f ", &tensor) == 1)
3752  {
3753  *value = tensor;
3754  return 0;
3755  }
3756 
3757  return -1;
3758 }
3759 
3760 static void close_tensor_rsrc_file(struct tensor_rsrc *rsrc)
3761 {
3762  FILE *fp = (FILE *)rsrc->private;
3763  fclose(fp);
3764 }
3765 
3766 static int open_tensor_rsrc_rawdata(struct tensor_rsrc *rsrc, void *data,
3767  uint32_t len)
3768 {
3769  rsrc->private = (void *)data;
3770  rsrc->total_num = len / sizeof(float);
3771  rsrc->next_idx = 0;
3772  return 0;
3773 }
3774 
3775 static int get_tensor_rsrc_from_rawdata(struct tensor_rsrc *rsrc, float *value)
3776 {
3777  float *tensors = (float *)rsrc->private;
3778 
3779  if (rsrc->next_idx < rsrc->total_num)
3780  {
3781  *value = tensors[rsrc->next_idx];
3782  rsrc->next_idx++;
3783  return 0;
3784  }
3785 
3786  return -1;
3787 }
3788 
3789 static void close_tensor_rsrc_rawdata(struct tensor_rsrc *rsrc)
3790 {
3791 }
3792 
3793 static ni_retcode_t ni_network_tensor_to_data(
3794  uint8_t *dst, uint32_t dst_len, void *tensor, uint32_t src_len,
3795  ni_network_layer_params_t *p_param,
3796  int (*open_tensor_rsrc)(struct tensor_rsrc *, void *, uint32_t),
3797  int (*get_tensor_rsrc)(struct tensor_rsrc *, float *),
3798  void (*close_tensor_rsrc)(struct tensor_rsrc *))
3799 {
3800  uint8_t *tensor_data;
3801  uint32_t i, sz;
3802  uint32_t stride;
3803  float fval;
3804  int32_t data_format;
3805  int32_t quant_format;
3806  int32_t fixed_point_pos;
3807  float tf_scale;
3808  int32_t tf_zerop;
3809  struct tensor_rsrc *rsrc;
3810 
3811  data_format = p_param->data_format;
3812  quant_format = p_param->quant_format;
3813  fixed_point_pos = p_param->quant_data.dfp.fixed_point_pos;
3814  tf_scale = p_param->quant_data.affine.scale;
3815  tf_zerop = p_param->quant_data.affine.zeroPoint;
3816 
3817  sz = ni_ai_get_element_num((int32_t *)p_param->sizes, p_param->num_of_dims,
3818  data_format);
3819  stride = ni_ai_type_get_bytes(data_format);
3820 
3821  if (sz * stride * sizeof(uint8_t) != dst_len)
3822  {
3823  return NI_RETCODE_INVALID_PARAM;
3824  }
3825 
3826  rsrc = (struct tensor_rsrc *)calloc(1, sizeof(struct tensor_rsrc));
3827  if (!rsrc)
3828  {
3829  return NI_RETCODE_FAILURE;
3830  }
3831 
3832  if (open_tensor_rsrc(rsrc, tensor, src_len) != 0)
3833  {
3834  free(rsrc);
3835  return NI_RETCODE_FAILURE;
3836  }
3837 
3838  memset(dst, 0, sz * stride * sizeof(uint8_t));
3839  tensor_data = dst;
3840  for (i = 0; i < sz; i++)
3841  {
3842  if (get_tensor_rsrc(rsrc, &fval) == 0)
3843  {
3844  ni_ai_float32_to_dtype(fval, &tensor_data[stride * i], data_format,
3845  quant_format, fixed_point_pos, tf_scale,
3846  tf_zerop);
3847  } else
3848  {
3849  break;
3850  }
3851  }
3852 
3853  close_tensor_rsrc(rsrc);
3854  free(rsrc);
3855  return NI_RETCODE_SUCCESS;
3856 }
3857 
3858 ni_retcode_t ni_network_layer_convert_tensor(uint8_t *dst, uint32_t dst_len,
3859  const char *tensor_file,
3860  ni_network_layer_params_t *p_param)
3861 {
3862  return ni_network_tensor_to_data(
3863  dst, dst_len, (void *)tensor_file, 0, p_param, open_tensor_rsrc_file,
3864  get_tensor_rsrc_from_file, close_tensor_rsrc_file);
3865 }
3866 
3868 ni_network_convert_tensor_to_data(uint8_t *dst, uint32_t dst_len, float *src,
3869  uint32_t src_len,
3870  ni_network_layer_params_t *p_param)
3871 {
3872  return ni_network_tensor_to_data(
3873  dst, dst_len, src, src_len, p_param, open_tensor_rsrc_rawdata,
3874  get_tensor_rsrc_from_rawdata, close_tensor_rsrc_rawdata);
3875 }
3876 
3878 ni_network_convert_data_to_tensor(float *dst, uint32_t dst_len, uint8_t *src,
3879  uint32_t src_len,
3880  ni_network_layer_params_t *p_param)
3881 {
3882  uint32_t i = 0;
3883  uint8_t *data;
3884  uint32_t ele_size;
3885  float *dst_float = dst;
3886  uint32_t type_size;
3887 
3888  if (!src || src_len == 0 || !dst || dst_len == 0 || !p_param)
3889  {
3890  return NI_RETCODE_INVALID_PARAM;
3891  }
3892 
3893  type_size = ni_ai_type_get_bytes(p_param->data_format);
3894 
3895  data = src;
3896 
3897  ele_size = 1;
3898  for (i = 0; i < p_param->num_of_dims; i++)
3899  {
3900  ele_size *= p_param->sizes[i];
3901  }
3902 
3903  if (dst_len != ele_size * sizeof(float))
3904  {
3905  return NI_RETCODE_INVALID_PARAM;
3906  }
3907 
3908  if (src_len != ni_ai_network_layer_size(p_param))
3909  {
3910  return NI_RETCODE_INVALID_PARAM;
3911  }
3912 
3913  if (p_param->data_format == NI_AI_BUFFER_FORMAT_INT8)
3914  {
3915  int32_t quant_format = p_param->quant_format;
3916 
3917  if (quant_format == NI_AI_BUFFER_QUANTIZE_DYNAMIC_FIXED_POINT)
3918  {
3919  uint8_t fix_pos = (uint8_t)p_param->quant_data.dfp.fixed_point_pos;
3920 
3921  for (i = 0; i < ele_size; i++, data += type_size)
3922  {
3923  dst_float[i] = ni_ai_int8_to_fp32(*data, fix_pos);
3924  }
3925  } else if (quant_format == NI_AI_BUFFER_QUANTIZE_TF_ASYMM)
3926  {
3927  int32_t zero_point = p_param->quant_data.affine.zeroPoint;
3928  float scale = p_param->quant_data.affine.scale;
3929 
3930  for (i = 0; i < ele_size; i++, data += type_size)
3931  {
3932  int32_t src_value = 0;
3933  ni_ai_integer_convert(data, &src_value,
3936  dst_float[i] =
3937  ni_ai_affine_to_fp32(src_value, zero_point, scale);
3938  }
3939  } else
3940  {
3941  for (i = 0; i < ele_size; i++, data += type_size)
3942  {
3943  void *float_data = (void *)data;
3944  dst_float[i] = *((float *)float_data);
3945  }
3946  }
3947  } else if (p_param->data_format == NI_AI_BUFFER_FORMAT_FP16)
3948  {
3949  for (i = 0; i < ele_size; i++, data += type_size)
3950  {
3951  dst_float[i] = ni_ai_fp16_to_fp32(*((short *)data));
3952  }
3953  } else if (p_param->data_format == NI_AI_BUFFER_FORMAT_UINT8)
3954  {
3955  int32_t zero_point = p_param->quant_data.affine.zeroPoint;
3956  float scale = p_param->quant_data.affine.scale;
3957 
3958  for (i = 0; i < ele_size; i++, data += type_size)
3959  {
3960  dst_float[i] = ni_ai_uint8_to_fp32(*data, zero_point, scale);
3961  }
3962  } else if (p_param->data_format == NI_AI_BUFFER_FORMAT_INT16)
3963  {
3964  uint8_t fix_pos = p_param->quant_data.dfp.fixed_point_pos;
3965 
3966  for (i = 0; i < ele_size; i++, data += type_size)
3967  {
3968  dst_float[i] = ni_ai_int16_to_fp32(*((short *)data), fix_pos);
3969  }
3970  } else if (p_param->data_format == NI_AI_BUFFER_FORMAT_FP32)
3971  {
3972  for (i = 0; i < ele_size; i++, data += type_size)
3973  {
3974  void *float_data = (void *)data;
3975  dst_float[i] = *((float *)float_data);
3976  }
3977  } else
3978  {
3979  return NI_RETCODE_INVALID_PARAM;
3980  }
3981 
3982  return NI_RETCODE_SUCCESS;
3983 }
3984 
3986 {
3987  return ni_ai_get_tensor_size((int32_t *)p_param->sizes,
3988  p_param->num_of_dims, p_param->data_format);
3989 }
3990 
3992 {
3993  uint32_t i, dims = 1;
3994 
3995  for (i = 0; i < p_param->num_of_dims; i++)
3996  {
3997  dims *= p_param->sizes[i];
3998  }
3999 
4000  return dims;
4001 }
4002 
4003 /* sha256 */
4004 // SHA256 outputs a 32 byte digest
4005 #define SHA256_BLOCK_SIZE 32
4006 
4007 typedef struct SHA256CTX
4008 {
4009  uint8_t aui8Data[64];
4010  uint32_t ui32DataLength;
4011  uint64_t ui64BitLength;
4012  uint32_t aui32State[8];
4013 } SHA256CTX;
4014 
4015 #define ROTLEFT(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
4016 #define ROTRIGHT(a, b) (((a) >> (b)) | ((a) << (32 - (b))))
4017 
4018 #define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
4019 #define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
4020 #define EP0(x) (ROTRIGHT(x, 2) ^ ROTRIGHT(x, 13) ^ ROTRIGHT(x, 22))
4021 #define EP1(x) (ROTRIGHT(x, 6) ^ ROTRIGHT(x, 11) ^ ROTRIGHT(x, 25))
4022 #define SIG0(x) (ROTRIGHT(x, 7) ^ ROTRIGHT(x, 18) ^ ((x) >> 3))
4023 #define SIG1(x) (ROTRIGHT(x, 17) ^ ROTRIGHT(x, 19) ^ ((x) >> 10))
4024 
4025 static const uint32_t ui32k[64] = {
4026  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
4027  0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
4028  0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
4029  0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
4030  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
4031  0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
4032  0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
4033  0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
4034  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
4035  0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
4036  0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
4037 
4038 void ni_SHA256Transform(SHA256CTX *psCtx, const uint8_t aui8Data[])
4039 {
4040  uint32_t ui32a, ui32b, ui32c, ui32d, ui32e, ui32f, ui32g, ui32h, ui32i,
4041  ui32j, ui32t1, ui32t2, ui32m[64];
4042 
4043  for (ui32i = 0, ui32j = 0; ui32i < 16; ++ui32i, ui32j += 4)
4044  ui32m[ui32i] = (aui8Data[ui32j] << 24) | (aui8Data[ui32j + 1] << 16) |
4045  (aui8Data[ui32j + 2] << 8) | (aui8Data[ui32j + 3]);
4046  for (; ui32i < 64; ++ui32i)
4047  ui32m[ui32i] = SIG1(ui32m[ui32i - 2]) + ui32m[ui32i - 7] +
4048  SIG0(ui32m[ui32i - 15]) + ui32m[ui32i - 16];
4049 
4050  ui32a = psCtx->aui32State[0];
4051  ui32b = psCtx->aui32State[1];
4052  ui32c = psCtx->aui32State[2];
4053  ui32d = psCtx->aui32State[3];
4054  ui32e = psCtx->aui32State[4];
4055  ui32f = psCtx->aui32State[5];
4056  ui32g = psCtx->aui32State[6];
4057  ui32h = psCtx->aui32State[7];
4058 
4059  for (ui32i = 0; ui32i < 64; ++ui32i)
4060  {
4061  ui32t1 = ui32h + EP1(ui32e) + CH(ui32e, ui32f, ui32g) + ui32k[ui32i] +
4062  ui32m[ui32i];
4063  ui32t2 = EP0(ui32a) + MAJ(ui32a, ui32b, ui32c);
4064  ui32h = ui32g;
4065  ui32g = ui32f;
4066  ui32f = ui32e;
4067  ui32e = ui32d + ui32t1;
4068  ui32d = ui32c;
4069  ui32c = ui32b;
4070  ui32b = ui32a;
4071  ui32a = ui32t1 + ui32t2;
4072  }
4073 
4074  psCtx->aui32State[0] += ui32a;
4075  psCtx->aui32State[1] += ui32b;
4076  psCtx->aui32State[2] += ui32c;
4077  psCtx->aui32State[3] += ui32d;
4078  psCtx->aui32State[4] += ui32e;
4079  psCtx->aui32State[5] += ui32f;
4080  psCtx->aui32State[6] += ui32g;
4081  psCtx->aui32State[7] += ui32h;
4082 }
4083 
4085 {
4086  psCtx->ui32DataLength = 0;
4087  psCtx->ui64BitLength = 0;
4088  psCtx->aui32State[0] = 0x6a09e667;
4089  psCtx->aui32State[1] = 0xbb67ae85;
4090  psCtx->aui32State[2] = 0x3c6ef372;
4091  psCtx->aui32State[3] = 0xa54ff53a;
4092  psCtx->aui32State[4] = 0x510e527f;
4093  psCtx->aui32State[5] = 0x9b05688c;
4094  psCtx->aui32State[6] = 0x1f83d9ab;
4095  psCtx->aui32State[7] = 0x5be0cd19;
4096 }
4097 
4098 void ni_SHA256Update(SHA256CTX *psCtx, const uint8_t aui8Data[],
4099  size_t ui32Length)
4100 {
4101  uint32_t ui32i;
4102 
4103  for (ui32i = 0; ui32i < ui32Length; ++ui32i)
4104  {
4105  psCtx->aui8Data[psCtx->ui32DataLength] = aui8Data[ui32i];
4106  psCtx->ui32DataLength++;
4107  if (psCtx->ui32DataLength == 64)
4108  {
4109  ni_SHA256Transform(psCtx, psCtx->aui8Data);
4110  psCtx->ui64BitLength += 512;
4111  psCtx->ui32DataLength = 0;
4112  }
4113  }
4114 }
4115 
4116 void ni_SHA256Final(SHA256CTX *psCtx, uint8_t aui8Hash[])
4117 {
4118  uint32_t ui32i;
4119 
4120  ui32i = psCtx->ui32DataLength;
4121 
4122  // Pad whatever data is left in the buffer.
4123  if (psCtx->ui32DataLength < 56)
4124  {
4125  psCtx->aui8Data[ui32i++] = 0x80;
4126  while (ui32i < 56)
4127  psCtx->aui8Data[ui32i++] = 0x00;
4128  } else
4129  {
4130  psCtx->aui8Data[ui32i++] = 0x80;
4131  while (ui32i < 64)
4132  psCtx->aui8Data[ui32i++] = 0x00;
4133  ni_SHA256Transform(psCtx, psCtx->aui8Data);
4134  memset(psCtx->aui8Data, 0, 56);
4135  }
4136 
4137  // Append to the padding the total message's length in bits and transform.
4138  psCtx->ui64BitLength += psCtx->ui32DataLength * 8;
4139  psCtx->aui8Data[63] = (uint8_t)psCtx->ui64BitLength;
4140  psCtx->aui8Data[62] = (uint8_t)(psCtx->ui64BitLength >> 8);
4141  psCtx->aui8Data[61] = (uint8_t)(psCtx->ui64BitLength >> 16);
4142  psCtx->aui8Data[60] = (uint8_t)(psCtx->ui64BitLength >> 24);
4143  psCtx->aui8Data[59] = (uint8_t)(psCtx->ui64BitLength >> 32);
4144  psCtx->aui8Data[58] = (uint8_t)(psCtx->ui64BitLength >> 40);
4145  psCtx->aui8Data[57] = (uint8_t)(psCtx->ui64BitLength >> 48);
4146  psCtx->aui8Data[56] = (uint8_t)(psCtx->ui64BitLength >> 56);
4147  ni_SHA256Transform(psCtx, psCtx->aui8Data);
4148 
4149  // Since this implementation uses little endian byte ordering and SHA uses big endian,
4150  // reverse all the bytes when copying the final state to the output hash.
4151  for (ui32i = 0; ui32i < 4; ++ui32i)
4152  {
4153  aui8Hash[ui32i] =
4154  (psCtx->aui32State[0] >> (24 - ui32i * 8)) & 0x000000ff;
4155  aui8Hash[ui32i + 4] =
4156  (psCtx->aui32State[1] >> (24 - ui32i * 8)) & 0x000000ff;
4157  aui8Hash[ui32i + 8] =
4158  (psCtx->aui32State[2] >> (24 - ui32i * 8)) & 0x000000ff;
4159  aui8Hash[ui32i + 12] =
4160  (psCtx->aui32State[3] >> (24 - ui32i * 8)) & 0x000000ff;
4161  aui8Hash[ui32i + 16] =
4162  (psCtx->aui32State[4] >> (24 - ui32i * 8)) & 0x000000ff;
4163  aui8Hash[ui32i + 20] =
4164  (psCtx->aui32State[5] >> (24 - ui32i * 8)) & 0x000000ff;
4165  aui8Hash[ui32i + 24] =
4166  (psCtx->aui32State[6] >> (24 - ui32i * 8)) & 0x000000ff;
4167  aui8Hash[ui32i + 28] =
4168  (psCtx->aui32State[7] >> (24 - ui32i * 8)) & 0x000000ff;
4169  }
4170 }
4171 
4172 void ni_calculate_sha256(const uint8_t aui8Data[], size_t ui32DataLength,
4173  uint8_t aui8Hash[])
4174 {
4175  // Create the context structure
4176  SHA256CTX sCtx;
4177 
4178  // Initialize the context
4179  ni_SHA256Init(&sCtx);
4180  // Update the context with data and data length
4181  ni_SHA256Update(&sCtx, aui8Data, ui32DataLength);
4182  // Finalize the result and put it into a hash buffer
4183  ni_SHA256Final(&sCtx, aui8Hash);
4184 }
4185 
4186 /*!*****************************************************************************
4187  * \brief Copy Descriptor data to Netint HW descriptor frame layout to be sent
4188  * to encoder for encoding. Data buffer (dst) is usually allocated by
4189  * ni_encoder_frame_buffer_alloc. Only necessary when metadata size in
4190  * source is insufficient
4191  *
4192  * \param[out] p_dst pointers of Y/Cb/Cr to which data is copied
4193  * \param[in] p_src pointers of Y/Cb/Cr from which data is copied
4194  *
4195  * \return descriptor data
4196  *
4197  ******************************************************************************/
4199  uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS])
4200 {
4201  // return to avoid self copy
4202  if (p_dst[0] == p_src[0] && p_dst[1] == p_src[1] && p_dst[2] == p_src[2] &&
4203  p_dst[3] == p_src[3])
4204  {
4205  ni_log(NI_LOG_DEBUG, "ni_copy_hw_yuv420p: src and dst identical, return\n");
4206  return;
4207  }
4208  niFrameSurface1_t *src_desc = (niFrameSurface1_t *)p_src[3];
4209  niFrameSurface1_t *dest_desc = (niFrameSurface1_t *)p_dst[3];
4210  memcpy(dest_desc, src_desc, sizeof(niFrameSurface1_t));
4211  ni_log(NI_LOG_DEBUG, "ni_copy_hw_descriptors dst FID Handle %d/%d src FID handle "
4212  "%d/%d\n",
4213  src_desc->ui16FrameIdx, src_desc->device_handle,
4214  dest_desc->ui16FrameIdx, dest_desc->device_handle);
4215 }
4216 
4217 /*!*****************************************************************************
4218  * \brief Get libxcoder API version
4219  *
4220  * \return char pointer to libxcoder API version
4221  ******************************************************************************/
4223 {
4224  static char* libxcoder_api_ver = LIBXCODER_API_VERSION;
4225  return libxcoder_api_ver;
4226 }
4227 
4228 #ifndef DEPRECATION_AS_ERROR
4229 /*!*****************************************************************************
4230  * \brief Get FW API version libxcoder is compatible with.
4231  * Deprecated in favour of `ni_fmt_fw_api_ver_str(&NI_XCODER_REVISION[NI_XCODER_REVISION_API_MAJOR_VER_IDX], &char_buf[0]);`
4232  *
4233  * \return char pointer to FW API version libxcoder is compatible with
4234  ******************************************************************************/
4236 {
4237  static char compat_fw_api_ver_str[5] = "";
4238  // init static array one byte at a time to avoid msvc compiler error C2099
4239  if (!compat_fw_api_ver_str[0])
4240  {
4241  compat_fw_api_ver_str[0] = \
4242  NI_XCODER_REVISION[NI_XCODER_REVISION_API_MAJOR_VER_IDX];
4243  compat_fw_api_ver_str[1] = '.';
4244  compat_fw_api_ver_str[2] = \
4245  NI_XCODER_REVISION[NI_XCODER_REVISION_API_MINOR_VER_IDX];
4247  compat_fw_api_ver_str[3] = \
4248  NI_XCODER_REVISION[NI_XCODER_REVISION_API_MINOR_VER_IDX+1];
4249  else
4250  compat_fw_api_ver_str[3] = 0;
4251  compat_fw_api_ver_str[4] = 0;
4252  }
4253  return &compat_fw_api_ver_str[0];
4254 }
4255 #endif
4256 
4257 /*!*****************************************************************************
4258  * \brief Get formatted FW API version string from unformatted FW API version
4259  * string
4260  *
4261  * \param[in] ver_str pointer to string containing FW API. Only up to 3
4262  * characters will be read
4263  * \param[out] fmt_str pointer to string buffer of at least size 5 to output
4264  * formated version string to
4265  *
4266  * \return none
4267  ******************************************************************************/
4268 void ni_fmt_fw_api_ver_str(const char ver_str[], char fmt_str[])
4269 {
4270  if (!ver_str || !fmt_str) {
4271  return;
4272  }
4273 
4274  fmt_str[0] = ver_str[0];
4275  fmt_str[1] = '.';
4276  fmt_str[2] = ver_str[1];
4277 
4278  if ((ver_str[0] < '6' || (ver_str[0] == '6' && ver_str[1] <= 'q')) ||
4279  (ver_str[2] == 0)) {
4280  fmt_str[3] = 0;
4281  } else {
4282  fmt_str[3] = ver_str[2];
4283  }
4284  fmt_str[4] = 0;
4285 }
4286 
4287 /*!*****************************************************************************
4288  * \brief Compare two 3 character strings containing a FW API version. Handle
4289  * comparision when FW API version format length changed from 2 to 3.
4290  *
4291  * \param[in] ver1 pointer to string containing FW API. Only up to 3
4292  * characters will be read
4293  * \param[in] ver2 pointer to string containing FW API. Only up to 3
4294  * characters will be read
4295  *
4296  * \return 0 if ver1 == ver2, 1 if ver1 > ver2, -1 if ver1 < ver2
4297  ******************************************************************************/
4298 int ni_cmp_fw_api_ver(const char ver1[], const char ver2[])
4299 {
4300  int index;
4301 
4302  index = 0;
4303 
4304  if (ver1[index] > ver2[index])
4305  return 1;
4306  else if (ver1[index] < ver2[index])
4307  return -1;
4308 
4309  index++;
4310 
4311  if (ver1[index] > ver2[index])
4312  return 1;
4313  else if (ver1[index] < ver2[index])
4314  return -1;
4315 
4316  if ((ver1[index - 1] < '6') || ((ver1[index - 1] == '6') && (ver1[index] <= 'q')))
4317  return 0;
4318 
4319  index++;
4320 
4321  if (ver1[index] > ver2[index])
4322  return 1;
4323  else if (ver1[index] < ver2[index])
4324  return -1;
4325 
4326  return 0;
4327 }
4328 
4329 /*!*****************************************************************************
4330  * \brief Get libxcoder SW release version
4331  *
4332  * \return char pointer to libxcoder SW release version
4333  ******************************************************************************/
4335 {
4336  static char release_ver_str[6] = "";
4337  // init static array one byte at a time to avoid compiler error C2099
4338  if (!release_ver_str[0])
4339  {
4340  release_ver_str[0] = NI_XCODER_REVISION[0];
4341  release_ver_str[1] = '.';
4342  release_ver_str[2] = NI_XCODER_REVISION[1];
4343  release_ver_str[3] = '.';
4344  release_ver_str[4] = NI_XCODER_REVISION[2];
4345  release_ver_str[5] = 0;
4346  }
4347  return &release_ver_str[0];
4348 }
4349 
4350 /*!*****************************************************************************
4351  * \brief Get text string for the provided error
4352  *
4353  * \return char pointer for the provided error
4354  ******************************************************************************/
4356 {
4357  int i;
4358  for (i = 0;
4359  i < sizeof(ni_err_rc_description) / sizeof(ni_err_rc_txt_entry_t); i++)
4360  {
4361  if (rc == ni_err_rc_description[i].rc)
4362  {
4363  return ni_err_rc_description[i].txt;
4364  }
4365  }
4366  return "rc not supported";
4367 }
4368 
4369 /*!*****************************************************************************
4370  * \brief retrieve key and value from 'key=value' pair
4371  *
4372  * \param[in] p_str pointer to string to extract pair from
4373  * \param[out] key pointer to key
4374  * \param[out] value pointer to value
4375  *
4376  * \return return 0 if successful, otherwise 1
4377  *
4378  ******************************************************************************/
4379 int ni_param_get_key_value(char *p_str, char *key, char *value)
4380 {
4381  if (!p_str || !key || !value)
4382  {
4383  return 1;
4384  }
4385 
4386  char *p = strchr(p_str, '=');
4387  if (!p)
4388  {
4389  return 1;
4390  } else
4391  {
4392  *p = '\0';
4393  key[0] = '\0';
4394  value[0] = '\0';
4395  int64_t key_len = p - p_str;
4396  ni_strncpy(key, 64, p_str, key_len);
4397  ni_strcpy(value, 64, p + 1);
4398  return 0;
4399  }
4400 }
4401 
4402 /*!*****************************************************************************
4403  * \brief retrieve encoder config parameter values from --xcoder-params
4404  *
4405  * \param[in] xcoderParams pointer to string containing xcoder params
4406  * \param[out] params pointer to xcoder params to fill out
4407  * \param[out] ctx pointer to session context
4408  *
4409  * \return return 0 if successful, -1 otherwise
4410  *
4411  ******************************************************************************/
4412 int ni_retrieve_xcoder_params(char xcoderParams[],
4413  ni_xcoder_params_t *params,
4414  ni_session_context_t *ctx)
4415 {
4416  char key[64], value[64];
4417  char *curr = xcoderParams, *colon_pos;
4418  int ret = 0;
4419 
4420  while (*curr)
4421  {
4422  colon_pos = strchr(curr, ':');
4423 
4424  if (colon_pos)
4425  {
4426  *colon_pos = '\0';
4427  }
4428 
4429  if (strlen(curr) > sizeof(key) + sizeof(value) - 1 ||
4430  ni_param_get_key_value(curr, key, value))
4431  {
4433  "Error: xcoder-params p_config key/value not "
4434  "retrieved: %s\n",
4435  curr);
4436  ret = -1;
4437  break;
4438  }
4439  ret = ni_encoder_params_set_value(params, key, value);
4440  switch (ret)
4441  {
4443  ni_log(NI_LOG_ERROR, "Error: unknown option: %s.\n", key);
4444  break;
4446  ni_log(NI_LOG_ERROR, "Error: invalid value for %s: %s.\n", key,
4447  value);
4448  break;
4449  default:
4450  break;
4451  }
4452 
4453  if (NI_RETCODE_SUCCESS != ret)
4454  {
4455  ni_log(NI_LOG_ERROR, "Error: config parsing failed %d: %s\n", ret,
4456  ni_get_rc_txt(ret));
4457  break;
4458  }
4459 
4460  if (colon_pos)
4461  {
4462  curr = colon_pos + 1;
4463  } else
4464  {
4465  curr += strlen(curr);
4466  }
4467  }
4469  // reuse decoder_low_delay for low delay encoding to store wait interval
4470  // in send/recv multi-thread mode.
4471  ctx->decoder_low_delay = params->low_delay_mode;
4472 
4473  return ret;
4474 }
4475 
4476 /*!*****************************************************************************
4477  * \brief Retrieve custom gop config values from --xcoder-gop
4478  *
4479  * \param[in] xcoderGop pointer to string containing xcoder gop
4480  * \param[out] params pointer to xcoder params to fill out
4481  * \param[out] ctx pointer to session context
4482  *
4483  * \return return 0 if successful, -1 otherwise
4484  *
4485  ******************************************************************************/
4486 int ni_retrieve_xcoder_gop(char xcoderGop[],
4487  ni_xcoder_params_t *params,
4488  ni_session_context_t *ctx)
4489 {
4490  char key[64], value[64];
4491  char *curr = xcoderGop, *colon_pos;
4492  int ret = 0;
4493 
4494  while (*curr)
4495  {
4496  colon_pos = strchr(curr, ':');
4497 
4498  if (colon_pos)
4499  {
4500  *colon_pos = '\0';
4501  }
4502 
4503  if (strlen(curr) > sizeof(key) + sizeof(value) - 1 ||
4504  ni_param_get_key_value(curr, key, value))
4505  {
4507  "Error: xcoder-params p_config key/value not "
4508  "retrieved: %s\n",
4509  curr);
4510  ret = -1;
4511  break;
4512  }
4513  ret = ni_encoder_gop_params_set_value(params, key, value);
4514  switch (ret)
4515  {
4517  ni_log(NI_LOG_ERROR, "Error: unknown option: %s.\n", key);
4518  break;
4520  ni_log(NI_LOG_ERROR, "Error: invalid value for %s: %s.\n", key,
4521  value);
4522  break;
4523  default:
4524  break;
4525  }
4526 
4527  if (NI_RETCODE_SUCCESS != ret)
4528  {
4529  ni_log(NI_LOG_ERROR, "Error: gop config parsing failed %d: %s\n", ret,
4530  ni_get_rc_txt(ret));
4531  break;
4532  }
4533 
4534  if (colon_pos)
4535  {
4536  curr = colon_pos + 1;
4537  } else
4538  {
4539  curr += strlen(curr);
4540  }
4541  }
4542 
4543  return ret;
4544 }
4545 
4546 /*!*****************************************************************************
4547  * \brief retrieve decoder config parameter values from --decoder-params
4548  *
4549  * \param[in] xcoderParams pointer to string containing xcoder params
4550  * \param[out] params pointer to xcoder params to fill out
4551  * \param[out] ctx pointer to session context
4552  *
4553  * \return return 0 if successful, -1 otherwise
4554  *
4555  ******************************************************************************/
4556 int ni_retrieve_decoder_params(char xcoderParams[],
4557  ni_xcoder_params_t *params,
4558  ni_session_context_t *ctx)
4559 {
4560  char key[64], value[64];
4561  char *curr = xcoderParams, *colon_pos;
4562  int ret = 0;
4563 
4564  while (*curr)
4565  {
4566  colon_pos = strchr(curr, ':');
4567 
4568  if (colon_pos)
4569  {
4570  *colon_pos = '\0';
4571  }
4572 
4573  if (strlen(curr) > sizeof(key) + sizeof(value) - 1 ||
4574  ni_param_get_key_value(curr, key, value))
4575  {
4577  "Error: decoder-params p_config key/value not "
4578  "retrieved: %s\n",
4579  curr);
4580  ret = -1;
4581  break;
4582  }
4583  ret = ni_decoder_params_set_value(params, key, value);
4584  switch (ret)
4585  {
4587  ni_log(NI_LOG_ERROR, "Error: unknown option: %s.\n", key);
4588  break;
4590  ni_log(NI_LOG_ERROR, "Error: invalid value for %s: %s.\n", key,
4591  value);
4592  break;
4593  default:
4594  break;
4595  }
4596 
4597  if (NI_RETCODE_SUCCESS != ret)
4598  {
4599  ni_log(NI_LOG_ERROR, "Error: config parsing failed %d: %s\n", ret,
4600  ni_get_rc_txt(ret));
4601  break;
4602  }
4603 
4604  if (colon_pos)
4605  {
4606  curr = colon_pos + 1;
4607  } else
4608  {
4609  curr += strlen(curr);
4610  }
4611  }
4614 
4615  return ret;
4616 }
4617 
4618 /*!*****************************************************************************
4619  * \brief initialize a mutex
4620  *
4621  * \param[in] thread mutex
4622  *
4623  * \return On success returns 0
4624  * On failure returns <0
4625  ******************************************************************************/
4626 int ni_pthread_mutex_init(ni_pthread_mutex_t *mutex)
4627 {
4628 #ifdef _WIN32
4629  bool rc = false;
4630  // error return zero
4631  rc = InitializeCriticalSectionEx(mutex, 0, CRITICAL_SECTION_NO_DEBUG_INFO);
4632  if (rc)
4633  {
4634  return 0;
4635  }
4636  else
4637  {
4638  return -1;
4639  }
4640 #else
4641  int rc;
4642  ni_pthread_mutexattr_t attr;
4643 
4644  rc = pthread_mutexattr_init(&attr);
4645  if (rc != 0)
4646  {
4647  return -1;
4648  }
4649 
4650  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
4651 
4652  return pthread_mutex_init(mutex, &attr);
4653 #endif
4654 }
4655 
4656 /*!*****************************************************************************
4657  * \brief destory a mutex
4658  *
4659  * \param[in] thread mutex
4660  *
4661  * \return On success returns 0
4662  * On failure returns <0
4663  ******************************************************************************/
4664 int ni_pthread_mutex_destroy(ni_pthread_mutex_t *mutex)
4665 {
4666 #ifdef _WIN32
4667  DeleteCriticalSection(mutex);
4668  return 0;
4669 #else
4670  return pthread_mutex_destroy(mutex);
4671 #endif
4672 }
4673 
4674 /*!*****************************************************************************
4675  * \brief thread mutex lock
4676  *
4677  * \param[in] thread mutex
4678  *
4679  * \return On success returns 0
4680  * On failure returns <0
4681  ******************************************************************************/
4682 int ni_pthread_mutex_lock(ni_pthread_mutex_t *mutex)
4683 {
4684  int rc = 0;
4685  if (mutex != NULL)
4686  {
4687 #ifdef _WIN32
4688  EnterCriticalSection(mutex);
4689 #else
4690  rc = pthread_mutex_lock(mutex);
4691 #endif
4692  } else
4693  {
4694  rc = -1;
4695  }
4696 
4697  return rc;
4698 }
4699 
4700 /*!*****************************************************************************
4701  * \brief thread mutex unlock
4702  *
4703  * \param[in] thread mutex
4704  *
4705  * \return On success returns 0
4706  * On failure returns <0
4707  ******************************************************************************/
4708 int ni_pthread_mutex_unlock(ni_pthread_mutex_t *mutex)
4709 {
4710  int rc = 0;
4711  if (mutex != NULL)
4712  {
4713 #ifdef _WIN32
4714  LeaveCriticalSection(mutex);
4715 #else
4716  rc = pthread_mutex_unlock(mutex);
4717 #endif
4718  } else
4719  {
4720  rc = -1;
4721  }
4722 
4723  return rc;
4724 }
4725 
4726 #ifdef _WIN32
4727 static unsigned __stdcall __thread_worker(void *arg)
4728 {
4729  ni_pthread_t *t = (ni_pthread_t *)arg;
4730  t->rc = t->start_routine(t->arg);
4731  return 0;
4732 }
4733 #endif
4734 
4735 /*!*****************************************************************************
4736  * \brief create a new thread
4737  *
4738  * \param[in] thread thread id
4739  * \param[in] attr attributes to the new thread
4740  * \param[in] start_routine entry of the thread routine
4741  * \param[in] arg sole argument of the routine
4742  *
4743  * \return On success returns 0
4744  * On failure returns <0
4745  ******************************************************************************/
4746 int ni_pthread_create(ni_pthread_t *thread, const ni_pthread_attr_t *attr,
4747  void *(*start_routine)(void *), void *arg)
4748 {
4749 #ifdef _WIN32
4750  thread->start_routine = start_routine;
4751  thread->arg = arg;
4752  thread->handle =
4753 #if HAVE_WINRT
4754  (void *)CreateThread(NULL, 0, win32thread_worker, thread, 0, NULL);
4755 #else
4756  (void *)_beginthreadex(NULL, 0, __thread_worker, thread, 0, NULL);
4757 #endif
4758  return !thread->handle;
4759 #else
4760  return pthread_create(thread, attr, start_routine, arg);
4761 #endif
4762 }
4763 
4764 /*!*****************************************************************************
4765  * \brief join with a terminated thread
4766  *
4767  * \param[in] thread thread id
4768  * \param[out] value_ptr return status
4769  *
4770  * \return On success returns 0
4771  * On failure returns <0
4772  ******************************************************************************/
4773 int ni_pthread_join(ni_pthread_t thread, void **value_ptr)
4774 {
4775 #ifdef _WIN32
4776  DWORD rc = WaitForSingleObject(thread.handle, INFINITE);
4777  if (rc != WAIT_OBJECT_0)
4778  {
4779  if (rc == WAIT_ABANDONED)
4780  return EINVAL;
4781  else
4782  return EDEADLK;
4783  }
4784  if (value_ptr)
4785  *value_ptr = thread.rc;
4786  CloseHandle(thread.handle);
4787  return 0;
4788 #else
4789  return pthread_join(thread, value_ptr);
4790 #endif
4791 }
4792 
4793 /*!*****************************************************************************
4794  * \brief initialize condition variables
4795  *
4796  * \param[in] cond condition variable
4797  * \param[in] attr attribute to the condvar
4798  *
4799  * \return On success returns 0
4800  * On failure returns <0
4801  ******************************************************************************/
4802 int ni_pthread_cond_init(ni_pthread_cond_t *cond,
4803  const ni_pthread_condattr_t *attr)
4804 {
4805 #ifdef _WIN32
4806  InitializeConditionVariable(cond);
4807  return 0;
4808 #else
4809  return pthread_cond_init(cond, attr);
4810 #endif
4811 }
4812 
4813 /*!*****************************************************************************
4814  * \brief destroy condition variables
4815  *
4816  * \param[in] cond condition variable
4817  *
4818  * \return On success returns 0
4819  * On failure returns <0
4820  ******************************************************************************/
4821 int ni_pthread_cond_destroy(ni_pthread_cond_t *cond)
4822 {
4823 #ifdef _WIN32
4824  /* native condition variables do not destroy */
4825  return 0;
4826 #else
4827  return pthread_cond_destroy(cond);
4828 #endif
4829 }
4830 
4831 /*!*****************************************************************************
4832  * \brief broadcast a condition
4833  *
4834  * \param[in] cond condition variable
4835  *
4836  * \return On success returns 0
4837  * On failure returns <0
4838  ******************************************************************************/
4839 int ni_pthread_cond_broadcast(ni_pthread_cond_t *cond)
4840 {
4841 #ifdef _WIN32
4842  WakeAllConditionVariable(cond);
4843  return 0;
4844 #else
4845  return pthread_cond_broadcast(cond);
4846 #endif
4847 }
4848 
4849 /*!*****************************************************************************
4850  * \brief wait on a condition
4851  *
4852  * \param[in] cond condition variable
4853  * \param[in] mutex mutex related to the condvar
4854  *
4855  * \return On success returns 0
4856  * On failure returns <0
4857  ******************************************************************************/
4858 int ni_pthread_cond_wait(ni_pthread_cond_t *cond, ni_pthread_mutex_t *mutex)
4859 {
4860 #ifdef _WIN32
4861  SleepConditionVariableCS(cond, mutex, INFINITE);
4862  return 0;
4863 #else
4864  return pthread_cond_wait(cond, mutex);
4865 #endif
4866 }
4867 
4868 /*!******************************************************************************
4869  * \brief signal a condition
4870  *
4871  * \param[in] cond condition variable
4872  *
4873  * \return On success returns 0
4874  * On failure returns <0
4875  *******************************************************************************/
4876 int ni_pthread_cond_signal(ni_pthread_cond_t *cond)
4877 {
4878 #ifdef _WIN32
4879  WakeConditionVariable(cond);
4880  return 0;
4881 #else
4882  return pthread_cond_signal(cond);
4883 #endif
4884 }
4885 
4886 /*!*****************************************************************************
4887  * \brief wait on a condition
4888  *
4889  * \param[in] cond condition variable
4890  * \param[in] mutex mutex related to the condvar
4891  * \param[in[ abstime abstract value of timeout
4892  *
4893  * \return On success returns 0
4894  * On failure returns <0
4895  ******************************************************************************/
4896 int ni_pthread_cond_timedwait(ni_pthread_cond_t *cond,
4897  ni_pthread_mutex_t *mutex,
4898  const struct timespec *abstime)
4899 {
4900 #ifdef _WIN32
4901  int64_t abs_ns = abstime->tv_sec * 1000000000LL + abstime->tv_nsec;
4902  DWORD t = (uint32_t)((abs_ns - ni_gettime_ns()) / 1000000);
4903 
4904  if (!SleepConditionVariableCS(cond, mutex, t))
4905  {
4906  DWORD err = GetLastError();
4907  if (err == ERROR_TIMEOUT)
4908  return ETIMEDOUT;
4909  else
4910  return EINVAL;
4911  }
4912  return 0;
4913 #else
4914  return pthread_cond_timedwait(cond, mutex, abstime);
4915 #endif
4916 }
4917 
4918 /*!*****************************************************************************
4919  * \brief examine and change mask of blocked signals
4920  *
4921  * \param[in] how behavior of this call, can be value of SIG_BLOCK,
4922  * SIG_UNBLOCK and SIG_SETMASK
4923  * \param[in] set current value of the signal mask. If NULL, the mask keeps
4924  * unchanged.
4925  * \param[in] old_set previous value of the signal mask, can be NULL.
4926  *
4927  * \return On success returns 0
4928  * On failure returns <0
4929  ******************************************************************************/
4930 int ni_pthread_sigmask(int how, const ni_sigset_t *set, ni_sigset_t *oldset)
4931 {
4932 #ifdef _WIN32
4933  return 0;
4934 #else
4935  return pthread_sigmask(how, set, oldset);
4936 #endif
4937 }
4938 
4939 /*!*****************************************************************************
4940  * \brief return error string according to error code from firmware
4941  *
4942  * \param[in] rc error code return from firmware
4943  *
4944  * \return error string
4945  ******************************************************************************/
4946 const char *ni_ai_errno_to_str(int rc)
4947 {
4948  switch (rc)
4949  {
4950  case NI_AI_STATUS_SUCCESS:
4951  return "Success";
4953  return "General Error";
4955  return "Not Initialized";
4957  return "Already Initialized";
4958  case NI_AI_STATUS_IO_BUSY:
4959  return "IO Busy";
4961  return "Resource Not Available";
4963  return "Create Network Failed";
4965  return "Input Buffer Full";
4967  return "Output Buffer Empty";
4969  return "Invalid Params";
4971  return "Error Start Network";
4973  return "Erorr Set Inout";
4975  return "Bad Option";
4977  return "Map Error";
4979  return "Context Not Available";
4981  return "Model Not Found";
4982  case NI_AI_STATUS_IO_ERROR:
4983  return "IO Error";
4985  return "Invalid Address";
4987  return "Out Of Memory";
4989  return "Bad Inout";
4991  return "Invalid Instance";
4993  return "IO Not Allowed";
4995  return "Network Not Ready";
4996  default:
4997  return "Other Error";
4998  }
4999 }
5000 /*!******************************************************************************
5001  * \brief decode the raw current obtained and determine power
5002  *
5003  * \param[in] current_value current value
5004  * \param[in] serial_number board SN
5005  *
5006  * \return On success returns power
5007  * On failure returns -1
5008  ********************************************************************************/
5009 uint32_t ni_decode_power_measurement(uint32_t current_data, const uint8_t *serial_number)
5010 {
5011  uint32_t power_mw;
5012  float current_ma,voltage_mv;
5013 
5014  if ((!serial_number) || (current_data == NI_INVALID_POWER))
5015  {
5016  return NI_INVALID_POWER;
5017  }
5018  char pcb_config[3];
5019  snprintf(pcb_config, sizeof(pcb_config), "%.2s", &serial_number[2]);
5020 
5021  float current_value = (float)current_data;
5022  voltage_mv = 12000.0f;
5023  if (strncmp(pcb_config, "A1", 2) == 0)
5024  {
5025  current_ma = (((current_value * 1000) / TPS25940_R_IMON) - TPS25940_IMON_OS) / TPS25940_GAIN_IMON;
5026  }
5027  else if ((strncmp(pcb_config, "A2", 2) == 0) || (strncmp(pcb_config, "A3", 2) == 0))
5028  {
5029  current_ma = ((current_value * MAX15162AAWE_C_IRATIO) / MAX15162AAWE_R_IMON);
5030  }
5031  else if ((strncmp(pcb_config, "AA", 2) == 0) || (strncmp(pcb_config, "AB", 2) == 0))
5032  {
5033  current_ma = (((current_value * 1000) / (TPS25946_R_IMON_T2A * TPS25946_GAIN_IMON)) * 1000);
5034  }
5035  else if (strncmp(pcb_config, "U0", 2) == 0)
5036  {
5037  current_ma = ((((current_value) * MAX17613B_R_ISET_TOTAL / MAX17613B_R_ISET_R2) *
5039  }
5040  else if ((strncmp(pcb_config, "U1", 2) == 0) || (strncmp(pcb_config, "U2", 2) == 0) || (strncmp(pcb_config, "U3", 2) == 0))
5041  {
5042  current_ma = ((1 * current_value * MAX15162AAWE_C_IRATIO) / MAX15162AAWE_R_IMON);
5043  }
5044  else if (strncmp(pcb_config, "UA", 2) == 0)
5045  {
5046  current_ma = (((current_value * 1000) / (TPS25946_R_IMON_T1U_UA * TPS25946_GAIN_IMON)) * 1000);
5047  }
5048  else if (strncmp(pcb_config, "S0", 2) == 0)
5049  {
5050  current_ma = (((current_value * 1000) / (TPS25946_R_IMON_T1S * TPS25946_GAIN_IMON)) * 1000);
5051  }
5052  else if ((strncmp(pcb_config, "M0", 2) == 0) || (strncmp(pcb_config, "M1", 2) == 0))
5053  {
5054  current_ma = ((((current_value * 1000) / (TPS25946_R_IMON_T1M * TPS25946_GAIN_IMON_T1M)) * 1000) * MCU_REF_VOLTAGE) / MCU_FSR_ADC;
5055  voltage_mv = 3300.0f;
5056  }
5057  else
5058  {
5059  return NI_INVALID_POWER;
5060  }
5061  power_mw = (uint32_t)((voltage_mv * current_ma) / 1000.0);
5062  return power_mw;
5063 }
5064 
5065 
5066 
5067 /*!******************************************************************************
5068  * \brief Check a device can be read by ni_device_capability_query()
5069  * by checking the size of the device using blockdev
5070  *
5071  * INFO OR ERROR logs will not be printed in this function
5072  *
5073  * \param[in] p_dev device path string. eg: "/dev/nvme1n2"
5074  * \param[in] size_needed The minimum required size
5075  *
5076  * \return
5077  * returns -1
5078  * when the device can not be read by ni_device_capability_query()
5079  *
5080  * returns 1
5081  * when the device can be read by ni_device_capability_query()
5082  *
5083  * returns 0 when the result can not be determined
5084  *
5085  *******************************************************************************/
5086 static int ni_device_size_precheck_blockdev(const char *p_dev, const uint64_t size_needed )
5087 {
5088 #ifndef __linux__
5089  (void) p_dev;
5090  (void) size_needed;
5091  return 0;
5092 #else
5093 
5094  int ret = 0;
5095 
5096  const char blockdev_command_dev[] = "blockdev --getsize64 %s 2>/dev/null";
5097  FILE *blockdev_file = NULL;
5098  char *blockdev_command = NULL;
5099  char blockdev_result [70] = {0};
5100 
5101  if (!p_dev)
5102  {
5103  return -1;
5104  }
5105 
5106  const size_t path_len = strlen(p_dev);
5107 
5108  blockdev_command = (char *)calloc(1, sizeof(blockdev_command_dev) + path_len);
5109  if (!blockdev_command)
5110  {
5111  LRETURN;
5112  }
5113 
5114  snprintf(blockdev_command, sizeof(blockdev_command_dev) + path_len, blockdev_command_dev, p_dev);
5115 
5116  ni_log2(NULL, NI_LOG_DEBUG, "%s() blockdev command %s\n", __func__, blockdev_command);
5117 
5118  blockdev_file = popen(blockdev_command, "r");
5119 
5120  if (!blockdev_file)
5121  {
5122  LRETURN;
5123  }
5124 
5125  if (fgets(blockdev_result, sizeof(blockdev_result), blockdev_file) == NULL)
5126  {
5127  LRETURN;
5128  }
5129 
5130  int status = pclose(blockdev_file);
5131  blockdev_file = NULL;
5132 
5133  if (status == 0) // no errors
5134  {
5135  if (*blockdev_result != '\0')
5136  {
5137  char *endptr = NULL;
5138  errno = 0;
5139  unsigned long long this_size = strtoull(blockdev_result, &endptr, 10);
5140 
5141  if (errno != 0 || endptr == blockdev_result)
5142  {
5143  ret = 0;
5144  }
5145  else if (this_size < size_needed)
5146  {
5147  ni_log2(NULL, NI_LOG_DEBUG, "%s() blockdev size check failed. size: %" PRIu64 "\n", __func__, this_size);
5148  ret = -1;
5149  }
5150  else
5151  {
5152  ret = 1;
5153  }
5154  }
5155  }
5156 
5157 END:
5158  if (blockdev_command)
5159  {
5160  free(blockdev_command);
5161  }
5162 
5163  if (blockdev_file)
5164  {
5165  pclose(blockdev_file);
5166  }
5167 
5168  return ret;
5169 
5170 #endif
5171 }
5172 
5173 /*!******************************************************************************
5174  * \brief Check a device can be read by ni_device_capability_query()
5175  * by checking the size of the device using lsblk
5176  *
5177  * INFO OR ERROR logs will not be printed in this function
5178  *
5179  * \param[in] p_dev Device path string. eg: "/dev/nvme1n2"
5180  * \param[in] size_needed The minimum required size
5181  *
5182  * \return
5183  * returns -1
5184  * when the device can not be read by ni_device_capability_query()
5185  *
5186  * returns 1
5187  * when the device can be read by ni_device_capability_query()
5188  *
5189  * returns 0 when the result can not be determined
5190  *
5191  *******************************************************************************/
5192 static int ni_device_size_precheck_lsblk(const char *p_dev, const uint64_t size_needed)
5193 {
5194 #ifndef __linux__
5195  (void) p_dev;
5196  (void) size_needed;
5197  return 0;
5198 #else
5199 
5200  int ret = 0;
5201  const char lsblk_command_dev[] = "lsblk -b -o SIZE %s 2>/dev/null";
5202  char *lsblk_command = NULL;
5203  FILE *lsblk_file = NULL;
5204  char lsblk_result [70] = {0};
5205  char *fgets_result = NULL;
5206 
5207  if (!p_dev)
5208  {
5209  return -1;
5210  }
5211 
5212  const size_t path_len = strlen(p_dev);
5213 
5214  lsblk_command = (char *)calloc(1, sizeof(lsblk_command_dev) + path_len);
5215  if (!lsblk_command)
5216  {
5217  LRETURN;
5218  }
5219 
5220  snprintf(lsblk_command, sizeof(lsblk_command_dev) + path_len, lsblk_command_dev, p_dev);
5221 
5222  ni_log2(NULL, NI_LOG_DEBUG, "%s() lsblk command %s\n", __func__, lsblk_command);
5223 
5224  lsblk_file = popen(lsblk_command, "r");
5225  if (!lsblk_file)
5226  {
5227  LRETURN;
5228  }
5229 
5230  fgets_result = fgets(lsblk_result, sizeof(lsblk_result), lsblk_file);//get the first line
5231  if (!fgets_result)
5232  {
5233  LRETURN;
5234  }
5235 
5236  memset(lsblk_result, 0, sizeof(lsblk_result));
5237 
5238  fgets_result = fgets(lsblk_result, sizeof(lsblk_result), lsblk_file);//get the next line
5239  if (fgets_result)
5240  {
5241  LRETURN;
5242  }
5243 
5244  int status = pclose(lsblk_file);
5245  lsblk_file = NULL;
5246 
5247  if (status == 0) // no errors
5248  {
5249  if (*lsblk_result != '\0')
5250  {
5251  char *endptr = NULL;
5252  errno = 0;
5253  unsigned long long this_size = strtoull(lsblk_result, &endptr, 10);
5254 
5255  if (errno != 0 || endptr == lsblk_result)
5256  {
5257  ret = 0;
5258  }
5259  else if (this_size < size_needed)
5260  {
5261  ni_log2(NULL, NI_LOG_DEBUG, "%s() lsblk size check failed. size: %" PRIu64 "\n", __func__, this_size);
5262  ret = -1;
5263  }
5264  else
5265  {
5266  ret = 1;
5267  }
5268  }
5269  }
5270 
5271 END:
5272  if (lsblk_command)
5273  {
5274  free(lsblk_command);
5275  }
5276 
5277  if (lsblk_file)
5278  {
5279  pclose(lsblk_file);
5280  }
5281 
5282  return ret;
5283 
5284 #endif
5285 }
5286 
5287 /*!******************************************************************************
5288  * \brief Check a device can be read by ni_device_capability_query()
5289  * by checking the vendor id
5290  *
5291  * INFO OR ERROR logs will not be printed in this function
5292  *
5293  * \param[in] p_dev device path string. eg: "/dev/nvme1n2"
5294  *
5295  * \return
5296  * returns -1
5297  * when the device can not be read by ni_device_capability_query()
5298  *
5299  * returns 1
5300  * when the device can be read by ni_device_capability_query()
5301  *
5302  * returns 0 when the result can not be determined
5303  *
5304  *******************************************************************************/
5305 static int ni_device_vendor_id_precheck(const char *p_dev)
5306 {
5307 #ifndef __linux__
5308  (void) p_dev;
5309  return 0;
5310 #else
5311 
5312  int ret = 0;
5313 
5314  if (!p_dev)
5315  {
5316  return -1;
5317  }
5318 
5319  const char *vendor_path_devs[] = {"/sys/class/block/%s/device/vendor", "/sys/class/block/%s/device/device/vendor"};
5320 
5321  const char *last_slash = strrchr(p_dev, '/');
5322  const char *device_name = (last_slash ? (last_slash + 1) : p_dev);
5323 
5324  const size_t path_len = strlen(p_dev);
5325 
5326  for (size_t i = 0; i < sizeof(vendor_path_devs)/sizeof(vendor_path_devs[0]) && ret == 0; ++i)
5327  {
5328  size_t template_len = strlen(vendor_path_devs[i]);
5329  char *vendor_path = (char *)calloc(1, template_len + path_len);
5330  if (!vendor_path)
5331  {
5332  continue;
5333  }
5334  snprintf(vendor_path, template_len + path_len, vendor_path_devs[i], device_name);
5335 
5336  int fd = open(vendor_path, O_RDONLY);
5337  if (fd >= 0)
5338  {
5339  char vendor_id[10] = {0};
5340  int read_size = read(fd, vendor_id, sizeof(vendor_id));
5341  if (read_size >= 4 && (size_t)read_size < sizeof(vendor_id))
5342  {
5343  char *find_1d82 = strstr(vendor_id, "1d82");
5344  if (find_1d82)
5345  {
5346  ret = 1;
5347  }
5348  else
5349  {
5350  ni_log2(NULL, NI_LOG_DEBUG, "%s() vendor check failed. vendor id: %s", vendor_id);
5351  ret = -1;
5352  }
5353  }
5354 
5355  close(fd);
5356  }
5357 
5358  free(vendor_path);
5359  }
5360 
5361  return ret;
5362 
5363 #endif
5364 }
5365 
5366 
5367 /*!******************************************************************************
5368  * \brief Check a device can be read by ni_device_capability_query()
5369  * by reading size from /sys/class/block/<devname>/size and
5370  * /sys/class/block/<devname>/queue/logical_block_size
5371  *
5372  * INFO OR ERROR logs will not be printed in this function
5373  *
5374  * \param[in] p_dev device path string. eg: "/dev/nvme1n2"
5375  * \param[in] size_needed The minimum required size
5376  *
5377  * \return
5378  * returns -1
5379  * when the device can not be read by ni_device_capability_query()
5380  *
5381  * returns 1
5382  * when the device can be read by ni_device_capability_query()
5383  *
5384  * returns 0 when the result can not be determined
5385  *
5386  *******************************************************************************/
5387 static int ni_device_size_precheck_system_information(const char *p_dev, const uint64_t size_needed)
5388 {
5389 #ifndef __linux__
5390  (void) p_dev;
5391  (void) size_needed;
5392  return 0;
5393 #else
5394 
5395  int ret = 0;
5396 
5397  if (!p_dev)
5398  {
5399  return -1;
5400  }
5401 
5402  const char block_path_dev[] = "/sys/class/block/%s/size";
5403  const char logical_block_size_path_dev[] = "/sys/class/block/%s/queue/logical_block_size";
5404 
5405  const char *last_slash = strrchr(p_dev, '/');
5406  const char *device_name = (last_slash ? (last_slash + 1) : p_dev);
5407 
5408  const size_t path_len = strlen(p_dev);
5409 
5410  int size_fd = -1;
5411  int logical_block_fd = -1;
5412 
5413  char *block_path = (char *)calloc(1, sizeof(block_path_dev) + path_len);
5414  char *logical_block_size_path = (char *)calloc(1, sizeof(logical_block_size_path_dev) + path_len);
5415 
5416  if (!block_path || !logical_block_size_path)
5417  {
5418  LRETURN;
5419  }
5420 
5421  snprintf(block_path, sizeof(block_path_dev) + path_len, block_path_dev, device_name);
5422  snprintf(logical_block_size_path, sizeof(logical_block_size_path_dev) + path_len, logical_block_size_path_dev, device_name);
5423 
5424  size_fd = open(block_path, O_RDONLY);
5425  logical_block_fd = open(logical_block_size_path, O_RDONLY);
5426 
5427  if (size_fd < 0 || logical_block_fd < 0)
5428  {
5429  LRETURN;
5430  }
5431 
5432  char this_size_str [20] = {0};
5433  char this_block_size_str [20] = {0};
5434 
5435  if (read(size_fd, this_size_str, sizeof(this_size_str)) <= 0 || read(logical_block_fd, this_block_size_str, sizeof(this_block_size_str)) <= 0)
5436  {
5437  ret = 0;
5438  }
5439  else
5440  {
5441  char *endptr1 = NULL;
5442  char *endptr2 = NULL;
5443  errno = 0;
5444  unsigned long long this_size = strtoull(this_size_str, &endptr1, 10);
5445  unsigned long long this_block_size = strtoull(this_block_size_str, &endptr2, 10);
5446 
5447  if (errno == 0 && endptr1 != this_size_str && endptr2 != this_block_size_str)
5448  {
5449  if (this_size * this_block_size >= size_needed)
5450  {
5451  ret = 1;
5452  }
5453  else
5454  {
5455  ni_log2(NULL, NI_LOG_DEBUG, "%s() read size check failed. size: %" PRIu64 "\n", __func__, this_size * this_block_size);
5456  ret = -1;
5457  }
5458  }
5459  }
5460 
5461 END:
5462  if (block_path)
5463  {
5464  free(block_path);
5465  }
5466  if (logical_block_size_path)
5467  {
5468  free(logical_block_size_path);
5469  }
5470 
5471  if (size_fd >= 0)
5472  {
5473  close(size_fd);
5474  }
5475  if (logical_block_fd >= 0)
5476  {
5477  close(logical_block_fd);
5478  }
5479 
5480  return ret;
5481 
5482 #endif
5483 }
5484 
5485 /*!******************************************************************************
5486  * \brief precheck a device can be read by ni_device_capability_query()
5487  * INFO OR ERROR logs will not be printed in this function
5488  * \param[in] p_dev device path string. eg: "/dev/nvme1n2"
5489  *
5490  * \return
5491  * returns NI_RETCODE_FAILURE
5492  * when the device can not be read by ni_device_capability_query()
5493  *
5494  * returns NI_RETCODE_SUCCESS when
5495  * 1. the device can not be read by ni_device_capability_query()
5496  * 2. the result can not be determined to prevent query failures due to
5497  * some reasons such as missing commands on the system
5498  *******************************************************************************/
5500 {
5501 #ifndef __linux__
5502  (void) p_dev;
5503  return 0;
5504 #else
5505  int ret = 0;
5506 
5507  const uint64_t SIZE_NEEDED = ((IDENTIFY_DEVICE_R) << (LBA_BIT_OFFSET)) + (NI_NVME_IDENTITY_CMD_DATA_SZ);
5508 
5509  if (!p_dev)
5510  {
5511  return NI_RETCODE_FAILURE;
5512  }
5513 
5514  const size_t path_len = strlen(p_dev);
5515 
5516  if (path_len > NI_MAX_DEVICE_NAME_LEN)
5517  {
5518  return NI_RETCODE_FAILURE;
5519  }
5520 
5521  ret = ni_device_size_precheck_blockdev(p_dev, SIZE_NEEDED);
5522  if (ret > 0)
5523  {
5524  return NI_RETCODE_SUCCESS;
5525  }
5526  if (ret < 0)
5527  {
5528  return NI_RETCODE_FAILURE;
5529  }
5530 
5531  ret = ni_device_size_precheck_lsblk(p_dev, SIZE_NEEDED);
5532  if (ret > 0)
5533  {
5534  return NI_RETCODE_SUCCESS;
5535  }
5536  if (ret < 0)
5537  {
5538  return NI_RETCODE_FAILURE;
5539  }
5540 
5541  ret = ni_device_vendor_id_precheck(p_dev);
5542  if (ret > 0)
5543  {
5544  return NI_RETCODE_SUCCESS;
5545  }
5546  if (ret < 0)
5547  {
5548  return NI_RETCODE_FAILURE;
5549  }
5550 
5551  ret = ni_device_size_precheck_system_information(p_dev, SIZE_NEEDED);
5552  if (ret > 0)
5553  {
5554  return NI_RETCODE_SUCCESS;
5555  }
5556  if (ret < 0)
5557  {
5558  return NI_RETCODE_FAILURE;
5559  }
5560 
5561  // Even if all previous prechecks cannot determine the result, still return SUCCESS
5562  // This is to prevent query failures due to some reasons such as missing commands on the system
5563  return (ret >= 0) ? NI_RETCODE_SUCCESS : NI_RETCODE_FAILURE;
5564 
5565 #endif
5566 }
NI_RETCODE_PARAM_ERROR_CONF_WIN_BOT
@ NI_RETCODE_PARAM_ERROR_CONF_WIN_BOT
Definition: ni_defs.h:481
NI_RETCODE_ERROR_VPU_RECOVERY
@ NI_RETCODE_ERROR_VPU_RECOVERY
Definition: ni_defs.h:529
NI_PIX_FMT_UYVY422
@ NI_PIX_FMT_UYVY422
Definition: ni_device_api.h:277
NI_LOG_FATAL
@ NI_LOG_FATAL
Definition: ni_log.h:61
NI_AI_STATUS_MODEL_NOT_FOUND
@ NI_AI_STATUS_MODEL_NOT_FOUND
Definition: ni_defs.h:619
ni_pthread_mutex_unlock
int ni_pthread_mutex_unlock(ni_pthread_mutex_t *mutex)
thread mutex unlock
Definition: ni_util.c:4708
NI_PIX_FMT_BGRA
@ NI_PIX_FMT_BGRA
Definition: ni_device_api.h:270
ni_get_compat_fw_api_ver
NI_DEPRECATED char * ni_get_compat_fw_api_ver(void)
Get FW API version libxcoder is compatible with. Deprecated in favour of ni_fmt_fw_api_ver_str(&NI_XC...
Definition: ni_util.c:4235
ni_pthread_cond_init
int ni_pthread_cond_init(ni_pthread_cond_t *cond, const ni_pthread_condattr_t *attr)
initialize condition variables
Definition: ni_util.c:4802
NI_UNUSED
#define NI_UNUSED
Definition: ni_defs.h:67
NI_AI_STATUS_ALREADY_INITIALIZED
@ NI_AI_STATUS_ALREADY_INITIALIZED
Definition: ni_defs.h:607
ni_encoder_params_set_value
ni_retcode_t ni_encoder_params_set_value(ni_xcoder_params_t *p_params, const char *name, const char *value)
Set value referenced by name in encoder parameters structure.
Definition: ni_device_api.c:5667
ni_strerror
ni_retcode_t ni_strerror(char *dest, size_t dmax, int errnum)
Definition: ni_util.c:652
_ni_network_data
Definition: ni_device_api.h:1376
_ni_session_context::decoder_low_delay
int decoder_low_delay
Definition: ni_device_api.h:1624
XCODER_MAX_NUM_QUEUE_ENTRIES
#define XCODER_MAX_NUM_QUEUE_ENTRIES
Definition: ni_util.h:107
ni_pix_fmt_t
ni_pix_fmt_t
Definition: ni_device_api.h:263
ni_strncat
ni_retcode_t ni_strncat(char *dest, size_t dmax, const char *src, size_t slen)
Definition: ni_util.c:803
_ni_queue_buffer_pool_t::p_free_head
ni_queue_node_t * p_free_head
Definition: ni_device_api.h:1320
NI_RETCODE_NVME_SC_VPU_GENERAL_ERROR
@ NI_RETCODE_NVME_SC_VPU_GENERAL_ERROR
Definition: ni_defs.h:564
_ni_buf_pool_t::p_free_tail
ni_buf_t * p_free_tail
Definition: ni_device_api.h:1301
ni_queue_init
ni_retcode_t ni_queue_init(ni_session_context_t *p_ctx, ni_queue_t *p_queue, const char *name)
Initialize xcoder queue.
Definition: ni_util.c:2132
NI_AI_STATUS_OUTPUT_BUFFER_EMPTY
@ NI_AI_STATUS_OUTPUT_BUFFER_EMPTY
Definition: ni_defs.h:612
NI_RETCODE_NVME_SC_RESOURCE_IS_EMPTY
@ NI_RETCODE_NVME_SC_RESOURCE_IS_EMPTY
Definition: ni_defs.h:551
NI_RETCODE_PARAM_ERROR_RCENABLE
@ NI_RETCODE_PARAM_ERROR_RCENABLE
Definition: ni_defs.h:490
NI_AI_BUFFER_QUANTIZE_NONE
@ NI_AI_BUFFER_QUANTIZE_NONE
Definition: ni_device_api.h:1848
ni_buffer_pool_allocate_buffer
ni_queue_node_t * ni_buffer_pool_allocate_buffer(ni_queue_buffer_pool_t *p_buffer_pool)
Definition: ni_util.c:1452
_ni_err_rc_txt_entry
Definition: ni_util.c:42
ni_atof
double ni_atof(const char *p_str, bool *b_error)
Convert string to floating.
Definition: ni_util.c:2570
NI_RETCODE_NVME_SC_RESOURCE_UNAVAILABLE
@ NI_RETCODE_NVME_SC_RESOURCE_UNAVAILABLE
Definition: ni_defs.h:550
ni_timestamp_register
ni_retcode_t ni_timestamp_register(ni_queue_buffer_pool_t *p_buffer_pool, ni_timestamp_table_t *p_table, int64_t timestamp, uint64_t data_info)
Register timestamp in timestamp/frameoffset table.
Definition: ni_util.c:1992
ni_retrieve_xcoder_gop
int ni_retrieve_xcoder_gop(char xcoderGop[], ni_xcoder_params_t *params, ni_session_context_t *ctx)
Retrieve custom gop config values from –xcoder-gop.
Definition: ni_util.c:4486
LBA_BIT_OFFSET
#define LBA_BIT_OFFSET
Definition: ni_nvme.h:625
_ni_buf_t::p_next_buffer
struct _ni_buf_t * p_next_buffer
Definition: ni_device_api.h:1292
NI_AI_BUFFER_FORMAT_INT16
@ NI_AI_BUFFER_FORMAT_INT16
Definition: ni_device_api.h:1828
NI_AI_BUFFER_QUANTIZE_TF_ASYMM
@ NI_AI_BUFFER_QUANTIZE_TF_ASYMM
Definition: ni_device_api.h:1853
BUFFER_POOL_SZ_PER_CONTEXT
#define BUFFER_POOL_SZ_PER_CONTEXT
Definition: ni_util.h:109
ni_get_frame_index
int32_t ni_get_frame_index(uint32_t *value)
Get xcoder instance id.
Definition: ni_util.c:1639
_ni_queue_buffer_pool_t::p_free_tail
ni_queue_node_t * p_free_tail
Definition: ni_device_api.h:1321
NI_AI_STATUS_NOT_INITIALIZED
@ NI_AI_STATUS_NOT_INITIALIZED
Definition: ni_defs.h:606
ni_strcpy
ni_retcode_t ni_strcpy(char *dest, size_t dmax, const char *src)
Definition: ni_util.c:449
_ni_queue_buffer_pool_t::p_used_tail
ni_queue_node_t * p_used_tail
Definition: ni_device_api.h:1323
NI_RETCODE_ERROR_GET_DEVICE_POOL
@ NI_RETCODE_ERROR_GET_DEVICE_POOL
Definition: ni_defs.h:520
ni_network_layer_convert_output
ni_retcode_t ni_network_layer_convert_output(float *dst, uint32_t dst_len, ni_packet_t *p_packet, ni_network_data_t *p_network, uint32_t layer)
Definition: ni_util.c:3704
_ni_buf_t::p_previous_buffer
struct _ni_buf_t * p_previous_buffer
Definition: ni_device_api.h:1291
NI_AI_STATUS_INPUT_BUFFER_FULL
@ NI_AI_STATUS_INPUT_BUFFER_FULL
Definition: ni_defs.h:611
MAJ
#define MAJ(x, y, z)
Definition: ni_util.c:4019
NI_PIX_FMT_YUV420P
@ NI_PIX_FMT_YUV420P
Definition: ni_device_api.h:265
_ni_network_layer_params_t::quant_data
union _ni_network_layer_params_t::@13 quant_data
NI_RETCODE_SUCCESS
@ NI_RETCODE_SUCCESS
Definition: ni_defs.h:441
MAX17613B_R_ISET_R2
#define MAX17613B_R_ISET_R2
Definition: ni_util.h:64
_ni_network_layer_params_t::num_of_dims
uint32_t num_of_dims
Definition: ni_device_api.h:1341
_ni_network_layer_params_t::data_format
int32_t data_format
Definition: ni_device_api.h:1344
NI_RETCODE_PARAM_ERROR_PIC_WIDTH
@ NI_RETCODE_PARAM_ERROR_PIC_WIDTH
Definition: ni_defs.h:494
_ni_err_rc_txt_entry::txt
const char * txt
Definition: ni_util.c:45
TPS25946_R_IMON_T2A
#define TPS25946_R_IMON_T2A
Definition: ni_util.h:53
TPS25940_R_IMON
#define TPS25940_R_IMON
Definition: ni_util.h:48
EP1
#define EP1(x)
Definition: ni_util.c:4021
_ni_queue_node_t::p_next_buffer
struct _ni_queue_node_t * p_next_buffer
Definition: ni_device_api.h:1314
_ni_queue_node_t::checkout_timestamp
time_t checkout_timestamp
Definition: ni_device_api.h:1310
ni_retrieve_xcoder_params
int ni_retrieve_xcoder_params(char xcoderParams[], ni_xcoder_params_t *params, ni_session_context_t *ctx)
retrieve encoder config parameter values from –xcoder-params
Definition: ni_util.c:4412
NI_AI_BUFFER_FORMAT_UINT32
@ NI_AI_BUFFER_FORMAT_UINT32
Definition: ni_device_api.h:1836
ni_gettime_ns
uint64_t ni_gettime_ns(void)
Definition: ni_util.c:2618
MCU_FSR_ADC
#define MCU_FSR_ADC
Definition: ni_util.h:67
NI_PIX_FMT_BGR0
@ NI_PIX_FMT_BGR0
Definition: ni_device_api.h:273
NI_XCODER_REVISION
#define NI_XCODER_REVISION
Definition: ni_defs.h:98
ni_pthread_cond_destroy
int ni_pthread_cond_destroy(ni_pthread_cond_t *cond)
destroy condition variables
Definition: ni_util.c:4821
ni_SHA256Transform
void ni_SHA256Transform(SHA256CTX *psCtx, const uint8_t aui8Data[])
Definition: ni_util.c:4038
ni_timestamp_get_with_threshold
ni_retcode_t ni_timestamp_get_with_threshold(ni_timestamp_table_t *p_table, uint64_t frame_info, int64_t *p_timestamp, int32_t threshold, int32_t print, ni_queue_buffer_pool_t *p_buffer_pool)
Definition: ni_util.c:2042
SHA256CTX::ui32DataLength
uint32_t ui32DataLength
Definition: ni_util.c:4010
NI_RETCODE_PARAM_ERROR_AREA_TOO_BIG
@ NI_RETCODE_PARAM_ERROR_AREA_TOO_BIG
Definition: ni_defs.h:516
NI_RETCODE_PARAM_ERROR_CUSIZE_MODE_32X32_EN
@ NI_RETCODE_PARAM_ERROR_CUSIZE_MODE_32X32_EN
Definition: ni_defs.h:502
_ni_queue_t::name
char name[32]
Definition: ni_device_api.h:1328
TPS25946_GAIN_IMON
#define TPS25946_GAIN_IMON
Definition: ni_util.h:51
_ni_network_data::outset
ni_network_layer_offset_t * outset
Definition: ni_device_api.h:1384
ni_parse_name
int32_t ni_parse_name(const char *arg, const char *const *names, bool *b_error)
Parse name.
Definition: ni_util.c:2590
NI_AI_STATUS_IO_BUSY
@ NI_AI_STATUS_IO_BUSY
Definition: ni_defs.h:608
NI_RETCODE_PARAM_ERROR_DY_MERGE_8X8_EN
@ NI_RETCODE_PARAM_ERROR_DY_MERGE_8X8_EN
Definition: ni_defs.h:466
_ni_buf_pool_t::mutex
ni_pthread_mutex_t mutex
Definition: ni_device_api.h:1297
NI_RETCODE_ERROR_STREAM_ERROR
@ NI_RETCODE_ERROR_STREAM_ERROR
Definition: ni_defs.h:538
tensor_rsrc::total_num
uint32_t total_num
Definition: ni_util.c:3733
ni_copy_hw_descriptors
void ni_copy_hw_descriptors(uint8_t *p_dst[NI_MAX_NUM_DATA_POINTERS], uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS])
Copy Descriptor data to Netint HW descriptor frame layout to be sent to encoder for encoding....
Definition: ni_util.c:4198
ni_pthread_cond_signal
int ni_pthread_cond_signal(ni_pthread_cond_t *cond)
signal a condition
Definition: ni_util.c:4876
NI_RETCODE_PARAM_ERROR_CONF_WIN_TOP
@ NI_RETCODE_PARAM_ERROR_CONF_WIN_TOP
Definition: ni_defs.h:479
NI_AI_STATUS_INVALID_INSTANCE
@ NI_AI_STATUS_INVALID_INSTANCE
Definition: ni_defs.h:624
ni_SHA256Init
void ni_SHA256Init(SHA256CTX *psCtx)
Definition: ni_util.c:4084
NI_AI_BUFFER_FORMAT_FP64
@ NI_AI_BUFFER_FORMAT_FP64
Definition: ni_device_api.h:1842
NI_RETCODE_PARAM_ERROR_CONF_WIN_L
@ NI_RETCODE_PARAM_ERROR_CONF_WIN_L
Definition: ni_defs.h:483
NI_RETCODE_INVALID_PARAM
@ NI_RETCODE_INVALID_PARAM
Definition: ni_defs.h:443
ni_buffer_pool_free
void ni_buffer_pool_free(ni_queue_buffer_pool_t *p_buffer_pool)
Definition: ni_util.c:1408
ni_ai_errno_to_str
const char * ni_ai_errno_to_str(int rc)
return error string according to error code from firmware
Definition: ni_util.c:4946
ni_queue_push
ni_retcode_t ni_queue_push(ni_queue_buffer_pool_t *p_buffer_pool, ni_queue_t *p_queue, uint64_t frame_info, int64_t timestamp)
Push into xcoder queue.
Definition: ni_util.c:2159
_ni_queue_node_t::frame_info
uint64_t frame_info
Definition: ni_device_api.h:1309
TPS25946_R_IMON_T1M
#define TPS25946_R_IMON_T1M
Definition: ni_util.h:56
ni_queue_print
ni_retcode_t ni_queue_print(ni_queue_t *p_queue)
Print xcoder queue info.
Definition: ni_util.c:2470
ni_copy_hw_yuv420p
void ni_copy_hw_yuv420p(uint8_t *p_dst[NI_MAX_NUM_DATA_POINTERS], uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS], int frame_width, int frame_height, int factor, int is_semiplanar, int conf_win_right, int dst_stride[NI_MAX_NUM_DATA_POINTERS], int dst_height[NI_MAX_NUM_DATA_POINTERS], int src_stride[NI_MAX_NUM_DATA_POINTERS], int src_height[NI_MAX_NUM_DATA_POINTERS])
Copy YUV data to Netint HW YUV420p frame layout to be sent to encoder for encoding....
Definition: ni_util.c:2972
ni_dec_fme_buffer_pool_free
void ni_dec_fme_buffer_pool_free(ni_buf_pool_t *p_buffer_pool)
Definition: ni_util.c:1354
_ni_network_layer_params_t
Definition: ni_device_api.h:1339
NI_RETCODE_PARAM_ERROR_MX_NUM_MERGE
@ NI_RETCODE_PARAM_ERROR_MX_NUM_MERGE
Definition: ni_defs.h:465
ni_pthread_cond_wait
int ni_pthread_cond_wait(ni_pthread_cond_t *cond, ni_pthread_mutex_t *mutex)
wait on a condition
Definition: ni_util.c:4858
ni_cmp_fw_api_ver
int ni_cmp_fw_api_ver(const char ver1[], const char ver2[])
Compare two 3 character strings containing a FW API version. Handle comparision when FW API version f...
Definition: ni_util.c:4298
NI_RETCODE_PARAM_ERROR_CU_LVL_RC_EN
@ NI_RETCODE_PARAM_ERROR_CU_LVL_RC_EN
Definition: ni_defs.h:469
_ni_queue_node_t::timestamp
uint64_t timestamp
Definition: ni_device_api.h:1308
NI_RETCODE_PARAM_ERROR_HEIGHT_TOO_BIG
@ NI_RETCODE_PARAM_ERROR_HEIGHT_TOO_BIG
Definition: ni_defs.h:512
_ni_timestamp_table_t::list
ni_queue_t list
Definition: ni_device_api.h:1336
NI_VPU_ALIGN64
#define NI_VPU_ALIGN64(_x)
Definition: ni_device_api.h:346
NI_RETCODE_PARAM_ERROR_MX_QP
@ NI_RETCODE_PARAM_ERROR_MX_QP
Definition: ni_defs.h:475
NI_RETCODE_ERROR_MEM_ALOC
@ NI_RETCODE_ERROR_MEM_ALOC
Definition: ni_defs.h:445
ni_retcode_t
ni_retcode_t
Definition: ni_defs.h:439
NI_RETCODE_PARAM_ERROR_DY_MERGE_32X32_EN
@ NI_RETCODE_PARAM_ERROR_DY_MERGE_32X32_EN
Definition: ni_defs.h:468
NI_FW_META_DATA_SZ
#define NI_FW_META_DATA_SZ
Definition: ni_defs.h:320
ni_pthread_join
int ni_pthread_join(ni_pthread_t thread, void **value_ptr)
join with a terminated thread
Definition: ni_util.c:4773
_ni_network_data::output_num
uint32_t output_num
Definition: ni_device_api.h:1379
ni_SHA256Final
void ni_SHA256Final(SHA256CTX *psCtx, uint8_t aui8Hash[])
Definition: ni_util.c:4116
SHA256CTX::ui64BitLength
uint64_t ui64BitLength
Definition: ni_util.c:4011
NI_RETCODE_PARAM_INVALID_VALUE
@ NI_RETCODE_PARAM_INVALID_VALUE
Definition: ni_defs.h:451
_ni_buf_pool_t::buf_size
uint32_t buf_size
Definition: ni_device_api.h:1299
NI_RETCODE_PARAM_ERROR_VBV_BUFFER_SIZE
@ NI_RETCODE_PARAM_ERROR_VBV_BUFFER_SIZE
Definition: ni_defs.h:458
SIG0
#define SIG0(x)
Definition: ni_util.c:4022
_ni_decoder_input_params_t::keep_alive_timeout
int keep_alive_timeout
Definition: ni_device_api.h:2580
NI_DEC_FRAME_BUF_POOL_SIZE_EXPAND
#define NI_DEC_FRAME_BUF_POOL_SIZE_EXPAND
Definition: ni_util.h:118
SHA256CTX
struct SHA256CTX SHA256CTX
_niFrameSurface1::ui16FrameIdx
uint16_t ui16FrameIdx
Definition: ni_device_api.h:2872
NI_AI_BUFFER_FORMAT_FP32
@ NI_AI_BUFFER_FORMAT_FP32
Definition: ni_device_api.h:1818
ni_get_libxcoder_api_ver
char * ni_get_libxcoder_api_ver(void)
Get libxcoder API version.
Definition: ni_util.c:4222
NI_LOG_INFO
@ NI_LOG_INFO
Definition: ni_log.h:63
ni_timestamp_scan_cleanup
void ni_timestamp_scan_cleanup(ni_timestamp_table_t *pts_list, ni_timestamp_table_t *dts_list, ni_queue_buffer_pool_t *p_buffer_pool)
Definition: ni_util.c:2050
NI_LOG_ERROR
@ NI_LOG_ERROR
Definition: ni_log.h:62
ni_buf_pool_get_buffer
ni_buf_t * ni_buf_pool_get_buffer(ni_buf_pool_t *p_buffer_pool)
Definition: ni_util.c:1087
NI_VPU_ALIGN16
#define NI_VPU_ALIGN16(_x)
Definition: ni_device_api.h:344
ni_buffer_pool_get_queue_buffer
ni_queue_node_t * ni_buffer_pool_get_queue_buffer(ni_queue_buffer_pool_t *p_buffer_pool)
Definition: ni_util.c:1539
_ni_network_data::linfo
ni_network_layer_info_t linfo
Definition: ni_device_api.h:1380
_ni_xcoder_params::cfg_enc_params
ni_encoder_cfg_params_t cfg_enc_params
Definition: ni_device_api.h:2841
ni_buf_pool_return_buffer
void ni_buf_pool_return_buffer(ni_buf_t *buf, ni_buf_pool_t *p_buffer_pool)
Definition: ni_util.c:1148
NI_PIX_FMT_NV12
@ NI_PIX_FMT_NV12
Definition: ni_device_api.h:267
_ni_network_layer_params_t::dfp
struct _ni_network_layer_params_t::@13::@14 dfp
ni_encoder_gop_params_set_value
ni_retcode_t ni_encoder_gop_params_set_value(ni_xcoder_params_t *p_params, const char *name, const char *value)
Set GOP parameter value referenced by name in encoder parameters structure.
Definition: ni_device_api.c:7357
tensor_rsrc::next_idx
uint32_t next_idx
Definition: ni_util.c:3734
NI_RETCODE_ERROR_UNLOCK_DEVICE
@ NI_RETCODE_ERROR_UNLOCK_DEVICE
Definition: ni_defs.h:523
NI_AI_BUFFER_FORMAT_INT64
@ NI_AI_BUFFER_FORMAT_INT64
Definition: ni_device_api.h:1838
MAX17613B_R_ISET_TOTAL
#define MAX17613B_R_ISET_TOTAL
Definition: ni_util.h:63
ni_err_rc_txt_entry_t
struct _ni_err_rc_txt_entry ni_err_rc_txt_entry_t
ni_buffer_pool_initialize
int32_t ni_buffer_pool_initialize(ni_session_context_t *p_ctx, int32_t number_of_buffers)
Definition: ni_util.c:1480
NI_RETCODE_PARAM_ERROR_DECODING_REFRESH_TYPE
@ NI_RETCODE_PARAM_ERROR_DECODING_REFRESH_TYPE
Definition: ni_defs.h:498
_ni_buf_t::pool
struct _ni_buf_pool_t * pool
Definition: ni_device_api.h:1288
NI_AI_STATUS_RESOURCE_NOT_AVAILABLE
@ NI_AI_STATUS_RESOURCE_NOT_AVAILABLE
Definition: ni_defs.h:609
NI_RETCODE_PARAM_ERROR_CUSIZE_MODE_16X16_EN
@ NI_RETCODE_PARAM_ERROR_CUSIZE_MODE_16X16_EN
Definition: ni_defs.h:501
ni_timestamp_init
ni_retcode_t ni_timestamp_init(ni_session_context_t *p_ctx, ni_timestamp_table_t **pp_table, const char *name)
Initialize timestamp handling.
Definition: ni_util.c:1927
ni_buf_pool_expand
ni_buf_t * ni_buf_pool_expand(ni_buf_pool_t *pool)
Definition: ni_util.c:1070
_ni_queue_t::p_first
ni_queue_node_t * p_first
Definition: ni_device_api.h:1330
ni_calculate_sha256
void ni_calculate_sha256(const uint8_t aui8Data[], size_t ui32DataLength, uint8_t aui8Hash[])
Definition: ni_util.c:4172
NI_RETCODE_ERROR_NVME_CMD_FAILED
@ NI_RETCODE_ERROR_NVME_CMD_FAILED
Definition: ni_defs.h:446
_ni_queue_node_t::p_next
struct _ni_queue_node_t * p_next
Definition: ni_device_api.h:1312
NI_AI_BUFFER_QUANTIZE_DYNAMIC_FIXED_POINT
@ NI_AI_BUFFER_QUANTIZE_DYNAMIC_FIXED_POINT
Definition: ni_device_api.h:1850
ni_network_convert_data_to_tensor
ni_retcode_t ni_network_convert_data_to_tensor(float *dst, uint32_t dst_len, uint8_t *src, uint32_t src_len, ni_network_layer_params_t *p_param)
Definition: ni_util.c:3878
ni_pthread_cond_timedwait
int ni_pthread_cond_timedwait(ni_pthread_cond_t *cond, ni_pthread_mutex_t *mutex, const struct timespec *abstime)
wait on a condition
Definition: ni_util.c:4896
ni_fscanf
int ni_fscanf(FILE *stream, const char *fmt,...)
Definition: ni_util.c:1017
NI_MEM_PAGE_ALIGNMENT
#define NI_MEM_PAGE_ALIGNMENT
Definition: ni_defs.h:263
NI_LOG_TRACE
@ NI_LOG_TRACE
Definition: ni_log.h:65
_ni_buf_t
Definition: ni_device_api.h:1285
ni_pthread_mutex_lock
int ni_pthread_mutex_lock(ni_pthread_mutex_t *mutex)
thread mutex lock
Definition: ni_util.c:4682
EP0
#define EP0(x)
Definition: ni_util.c:4020
NI_PIX_FMT_NV16
@ NI_PIX_FMT_NV16
Definition: ni_device_api.h:275
NI_RETCODE_PARAM_ERROR_FILLER
@ NI_RETCODE_PARAM_ERROR_FILLER
Definition: ni_defs.h:533
ni_ai_buffer_format_e
enum _ni_ai_buffer_format_e ni_ai_buffer_format_e
TPS25946_R_IMON_T1S
#define TPS25946_R_IMON_T1S
Definition: ni_util.h:55
_ni_nvme_write_complete_dw0_t::frame_index
uint32_t frame_index
Definition: ni_nvme.h:455
NI_RETCODE_ERROR_INVALID_ALLOCATION_METHOD
@ NI_RETCODE_ERROR_INVALID_ALLOCATION_METHOD
Definition: ni_defs.h:527
NI_AI_STATUS_CREATE_NETWORK_FAILED
@ NI_AI_STATUS_CREATE_NETWORK_FAILED
Definition: ni_defs.h:610
_ni_session_context::dec_fme_buf_pool
ni_buf_pool_t * dec_fme_buf_pool
Definition: ni_device_api.h:1589
ni_ai_network_layer_dims
uint32_t ni_ai_network_layer_dims(ni_network_layer_params_t *p_param)
Definition: ni_util.c:3991
NI_AI_BUFFER_FORMAT_FP16
@ NI_AI_BUFFER_FORMAT_FP16
Definition: ni_device_api.h:1820
_ni_packet::p_data
void * p_data
Definition: ni_device_api.h:2914
ni_decoder_params_set_value
ni_retcode_t ni_decoder_params_set_value(ni_xcoder_params_t *p_params, const char *name, char *value)
Set value referenced by name in decoder parameters structure.
Definition: ni_device_api.c:4907
ni_timestamp_done
ni_retcode_t ni_timestamp_done(ni_timestamp_table_t *p_table, ni_queue_buffer_pool_t *p_buffer_pool)
Clean up timestamp handling.
Definition: ni_util.c:1967
NI_RETCODE_NVME_SC_VPU_RECOVERY
@ NI_RETCODE_NVME_SC_VPU_RECOVERY
Definition: ni_defs.h:561
NI_PIX_FMT_YUV420P10LE
@ NI_PIX_FMT_YUV420P10LE
Definition: ni_device_api.h:266
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_XCODER_REVISION_API_MAJOR_VER_IDX
#define NI_XCODER_REVISION_API_MAJOR_VER_IDX
Definition: ni_defs.h:99
NI_AI_BUFFER_FORMAT_UINT8
@ NI_AI_BUFFER_FORMAT_UINT8
Definition: ni_device_api.h:1822
_ni_session_context::keep_alive_timeout
uint32_t keep_alive_timeout
Definition: ni_device_api.h:1551
NI_AI_STATUS_INVALID_ADDRESS
@ NI_AI_STATUS_INVALID_ADDRESS
Definition: ni_defs.h:621
NI_RETCODE_PARAM_ERROR_CUSIZE_MODE_8X8_EN
@ NI_RETCODE_PARAM_ERROR_CUSIZE_MODE_8X8_EN
Definition: ni_defs.h:500
NI_RETCODE_PARAM_ERROR_BRATE_LT_TRATE
@ NI_RETCODE_PARAM_ERROR_BRATE_LT_TRATE
Definition: ni_defs.h:489
NI_AI_BUFFER_FORMAT_INT32
@ NI_AI_BUFFER_FORMAT_INT32
Definition: ni_device_api.h:1834
ni_atobool
int32_t ni_atobool(const char *p_str, bool *b_error)
Convert string to boolean.
Definition: ni_util.c:2527
NI_RETCODE_PARAM_WARN
@ NI_RETCODE_PARAM_WARN
Definition: ni_defs.h:540
_ni_buf_pool_t::p_free_head
ni_buf_t * p_free_head
Definition: ni_device_api.h:1300
ni_fmt_fw_api_ver_str
void ni_fmt_fw_api_ver_str(const char ver_str[], char fmt_str[])
Get formatted FW API version string from unformatted FW API version string.
Definition: ni_util.c:4268
ni_usleep
void ni_usleep(int64_t usec)
Definition: ni_util.c:358
NI_RETCODE_PARAM_ERROR_MX_DELTA_QP
@ NI_RETCODE_PARAM_ERROR_MX_DELTA_QP
Definition: ni_defs.h:477
ni_buffer_pool_expand
ni_queue_node_t * ni_buffer_pool_expand(ni_queue_buffer_pool_t *pool)
Definition: ni_util.c:1521
ni_localtime
struct tm * ni_localtime(struct tm *dest, const time_t *src)
Definition: ni_util.c:999
LRETURN
#define LRETURN
Definition: ni_defs.h:337
NI_RETCODE_PARAM_WARNING_DEPRECATED
@ NI_RETCODE_PARAM_WARNING_DEPRECATED
Definition: ni_defs.h:530
_ni_session_context::buffer_pool
ni_queue_buffer_pool_t * buffer_pool
Definition: ni_device_api.h:1588
NI_VPU_ALIGN128
#define NI_VPU_ALIGN128(_x)
Definition: ni_device_api.h:347
TPS25946_GAIN_IMON_T1M
#define TPS25946_GAIN_IMON_T1M
Definition: ni_util.h:52
NI_RETCODE_PARAM_ERROR_HVS_QP_EN
@ NI_RETCODE_PARAM_ERROR_HVS_QP_EN
Definition: ni_defs.h:471
_ni_packet
Definition: ni_device_api.h:2902
_ni_buf_pool_t
Definition: ni_device_api.h:1295
ni_pthread_cond_broadcast
int ni_pthread_cond_broadcast(ni_pthread_cond_t *cond)
broadcast a condition
Definition: ni_util.c:4839
NI_AI_STATUS_IO_NOT_ALLOWED
@ NI_AI_STATUS_IO_NOT_ALLOWED
Definition: ni_defs.h:625
_ni_encoder_cfg_params::keep_alive_timeout
int keep_alive_timeout
Definition: ni_device_api.h:2440
_ni_queue_t::p_last
ni_queue_node_t * p_last
Definition: ni_device_api.h:1331
_ni_queue_t::count
uint32_t count
Definition: ni_device_api.h:1329
NI_RETCODE_NVME_SC_INTERLACED_NOT_SUPPORTED
@ NI_RETCODE_NVME_SC_INTERLACED_NOT_SUPPORTED
Definition: ni_defs.h:560
_ni_network_layer_params_t::sizes
uint32_t sizes[6]
Definition: ni_device_api.h:1342
_ni_buf_t::p_prev
struct _ni_buf_t * p_prev
Definition: ni_device_api.h:1289
_ni_network_layer_offset::offset
int32_t offset
Definition: ni_device_api.h:1373
ni_get_frame_dim
void ni_get_frame_dim(int width, int height, ni_pix_fmt_t pix_fmt, int plane_stride[NI_MAX_NUM_DATA_POINTERS], int plane_height[NI_MAX_NUM_DATA_POINTERS])
Get dimension information of frame to be sent to encoder for encoding. Caller usually retrieves this ...
Definition: ni_util.c:2712
NI_RETCODE_PARAM_ERROR_TOO_BIG
@ NI_RETCODE_PARAM_ERROR_TOO_BIG
Definition: ni_defs.h:503
CH
#define CH(x, y, z)
Definition: ni_util.c:4018
ni_pthread_create
int ni_pthread_create(ni_pthread_t *thread, const ni_pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
create a new thread
Definition: ni_util.c:4746
_ni_buf_t::p_next
struct _ni_buf_t * p_next
Definition: ni_device_api.h:1290
NI_RETCODE_PARAM_ERROR_MAXNUMMERGE
@ NI_RETCODE_PARAM_ERROR_MAXNUMMERGE
Definition: ni_defs.h:491
ni_atoi
int32_t ni_atoi(const char *p_str, bool *b_error)
Convert string to integer.
Definition: ni_util.c:2550
ni_copy_plane_data
void ni_copy_plane_data(uint8_t *p_dst[NI_MAX_NUM_DATA_POINTERS], uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS], int frame_width, int frame_height, int factor, int is_semiplanar, int conf_win_right, int dst_stride[NI_MAX_NUM_DATA_POINTERS], int dst_height[NI_MAX_NUM_DATA_POINTERS], int src_stride[NI_MAX_NUM_DATA_POINTERS], int src_height[NI_MAX_NUM_DATA_POINTERS], int i)
Copy RGBA or YUV data to Netint HW frame layout to be sent to encoder for encoding....
Definition: ni_util.c:2849
ni_buf_pool_allocate_buffer
ni_buf_t * ni_buf_pool_allocate_buffer(ni_buf_pool_t *p_buffer_pool, int buffer_size)
Definition: ni_util.c:1204
SIG1
#define SIG1(x)
Definition: ni_util.c:4023
ni_dec_fme_buffer_pool_initialize
int32_t ni_dec_fme_buffer_pool_initialize(ni_session_context_t *p_ctx, int32_t number_of_buffers, int width, int height, int height_align, int factor)
Definition: ni_util.c:1245
TPS25946_R_IMON_T1U_UA
#define TPS25946_R_IMON_T1U_UA
Definition: ni_util.h:54
NI_RETCODE_PARAM_ERROR_CONF_WIN_R
@ NI_RETCODE_PARAM_ERROR_CONF_WIN_R
Definition: ni_defs.h:485
SHA256CTX
Definition: ni_util.c:4007
TPS25940_GAIN_IMON
#define TPS25940_GAIN_IMON
Definition: ni_util.h:47
NI_RETCODE_PARAM_ERROR_WIDTH_TOO_BIG
@ NI_RETCODE_PARAM_ERROR_WIDTH_TOO_BIG
Definition: ni_defs.h:508
NI_RETCODE_PARAM_ERROR_HVS_QP_SCL
@ NI_RETCODE_PARAM_ERROR_HVS_QP_SCL
Definition: ni_defs.h:472
_ni_queue_buffer_pool_t
Definition: ni_device_api.h:1317
NI_RETCODE_PARAM_ERROR_LOOK_AHEAD_DEPTH
@ NI_RETCODE_PARAM_ERROR_LOOK_AHEAD_DEPTH
Definition: ni_defs.h:531
ni_param_get_key_value
int ni_param_get_key_value(char *p_str, char *key, char *value)
retrieve key and value from 'key=value' pair
Definition: ni_util.c:4379
_ni_session_context
Definition: ni_device_api.h:1434
SHA256CTX::aui8Data
uint8_t aui8Data[64]
Definition: ni_util.c:4009
NI_PIX_FMT_P010LE
@ NI_PIX_FMT_P010LE
Definition: ni_device_api.h:268
_niFrameSurface1
Definition: ni_device_api.h:2870
NI_RETCODE_NVME_SC_STREAM_ERROR
@ NI_RETCODE_NVME_SC_STREAM_ERROR
Definition: ni_defs.h:559
NI_MAX_NUM_DATA_POINTERS
#define NI_MAX_NUM_DATA_POINTERS
Definition: ni_defs.h:244
NI_MAX_DEVICE_NAME_LEN
#define NI_MAX_DEVICE_NAME_LEN
Definition: ni_defs.h:236
TPS25940_IMON_OS
#define TPS25940_IMON_OS
Definition: ni_util.h:46
ni_pthread_mutex_init
int ni_pthread_mutex_init(ni_pthread_mutex_t *mutex)
initialize a mutex
Definition: ni_util.c:4626
NI_AI_STATUS_ERROR_START_NETWORK
@ NI_AI_STATUS_ERROR_START_NETWORK
Definition: ni_defs.h:614
ni_pthread_sigmask
int ni_pthread_sigmask(int how, const ni_sigset_t *set, ni_sigset_t *oldset)
examine and change mask of blocked signals
Definition: ni_util.c:4930
NI_PIX_FMT_YUYV422
@ NI_PIX_FMT_YUYV422
Definition: ni_device_api.h:276
NI_PIX_FMT_RGBA
@ NI_PIX_FMT_RGBA
Definition: ni_device_api.h:269
NI_DEPRECATED
#define NI_DEPRECATED
Definition: ni_defs.h:80
NI_AI_STATUS_MAP_ERROR
@ NI_AI_STATUS_MAP_ERROR
Definition: ni_defs.h:617
tensor_rsrc::private
void * private
Definition: ni_util.c:3732
ni_SHA256Update
void ni_SHA256Update(SHA256CTX *psCtx, const uint8_t aui8Data[], size_t ui32Length)
Definition: ni_util.c:4098
ni_network_convert_tensor_to_data
ni_retcode_t ni_network_convert_tensor_to_data(uint8_t *dst, uint32_t dst_len, float *src, uint32_t src_len, ni_network_layer_params_t *p_param)
Definition: ni_util.c:3868
NI_RETCODE_PARAM_ERROR_USR_RMD_ENC_PARAM
@ NI_RETCODE_PARAM_ERROR_USR_RMD_ENC_PARAM
Definition: ni_defs.h:487
NI_RETCODE_NVME_SC_INVALID_PARAMETER
@ NI_RETCODE_NVME_SC_INVALID_PARAMETER
Definition: ni_defs.h:558
NI_RETCODE_ERROR_INVALID_SESSION
@ NI_RETCODE_ERROR_INVALID_SESSION
Definition: ni_defs.h:447
NI_PIX_FMT_ABGR
@ NI_PIX_FMT_ABGR
Definition: ni_device_api.h:272
ni_strtok
char * ni_strtok(char *s, const char *delim, char **saveptr)
Definition: ni_util.c:420
NI_PIX_FMT_ARGB
@ NI_PIX_FMT_ARGB
Definition: ni_device_api.h:271
ni_quadra_card_identify_precheck
ni_retcode_t ni_quadra_card_identify_precheck(const char *p_dev)
precheck a device can be read by ni_device_capability_query() INFO OR ERROR logs will not be printed ...
Definition: ni_util.c:5499
_ni_xcoder_params
Definition: ni_device_api.h:2787
NI_RETCODE_PARAM_ERROR_WIDTH_TOO_SMALL
@ NI_RETCODE_PARAM_ERROR_WIDTH_TOO_SMALL
Definition: ni_defs.h:510
NI_AI_STATUS_INVALID_PARAMS
@ NI_AI_STATUS_INVALID_PARAMS
Definition: ni_defs.h:613
ni_find_blk_name
ni_retcode_t ni_find_blk_name(const char *p_dev, char *p_out_buf, int out_buf_len)
Find NVMe name space block from device name If none is found, assume nvme multi-pathing is disabled a...
Definition: ni_util.c:1800
ni_timestamp_get_v2
ni_retcode_t ni_timestamp_get_v2(ni_timestamp_table_t *p_table, uint64_t frame_offset, int64_t *p_timestamp, int32_t threshold, ni_queue_buffer_pool_t *p_buffer_pool)
Retrieve timestamp from table based on frameoffset info.
Definition: ni_util.c:2094
ni_get_min_frame_dim
void ni_get_min_frame_dim(int width, int height, ni_pix_fmt_t pix_fmt, int plane_stride[NI_MAX_NUM_DATA_POINTERS], int plane_height[NI_MAX_NUM_DATA_POINTERS])
Get dimension information of frame to be sent to encoder for encoding. Caller usually retrieves this ...
Definition: ni_util.c:2801
NI_RETCODE_NVME_SC_VPU_RSRC_INSUFFICIENT
@ NI_RETCODE_NVME_SC_VPU_RSRC_INSUFFICIENT
Definition: ni_defs.h:562
NI_AI_STATUS_BAD_OPTION
@ NI_AI_STATUS_BAD_OPTION
Definition: ni_defs.h:616
ni_copy_frame_data
void ni_copy_frame_data(uint8_t *p_dst[NI_MAX_NUM_DATA_POINTERS], uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS], int frame_width, int frame_height, int factor, ni_pix_fmt_t pix_fmt, int conf_win_right, int dst_stride[NI_MAX_NUM_DATA_POINTERS], int dst_height[NI_MAX_NUM_DATA_POINTERS], int src_stride[NI_MAX_NUM_DATA_POINTERS], int src_height[NI_MAX_NUM_DATA_POINTERS])
Copy RGBA or YUV data to Netint HW frame layout to be sent to encoder for encoding....
Definition: ni_util.c:3018
ni_sprintf
int ni_sprintf(char *dest, size_t dmax, const char *fmt,...)
Definition: ni_util.c:1059
ni_posix_memalign
int ni_posix_memalign(void **memptr, size_t alignment, size_t size)
Allocate aligned memory.
Definition: ni_util.c:198
NI_INVALID_POWER
#define NI_INVALID_POWER
Definition: ni_util.h:44
NI_RETCODE_PARAM_ERROR_PIC_HEIGHT
@ NI_RETCODE_PARAM_ERROR_PIC_HEIGHT
Definition: ni_defs.h:496
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_RETCODE_PARAM_ERROR_BRATE
@ NI_RETCODE_PARAM_ERROR_BRATE
Definition: ni_defs.h:454
_ni_network_layer_params_t::quant_format
int32_t quant_format
Definition: ni_device_api.h:1346
NI_RETCODE_NVME_SC_RESOURCE_NOT_FOUND
@ NI_RETCODE_NVME_SC_RESOURCE_NOT_FOUND
Definition: ni_defs.h:553
ni_nvme.h
Private definitions for interfacing with NETINT video processing devices over NVMe.
ni_strncpy
ni_retcode_t ni_strncpy(char *dest, size_t dmax, const char *src, size_t slen)
Definition: ni_util.c:514
tensor_rsrc
Definition: ni_util.c:3730
NI_AI_STATUS_GENERIC_ERROR
@ NI_AI_STATUS_GENERIC_ERROR
Definition: ni_defs.h:605
_ni_queue_node_t
Definition: ni_device_api.h:1306
ni_decode_power_measurement
uint32_t ni_decode_power_measurement(uint32_t current_data, const uint8_t *serial_number)
decode the raw current obtained and determine power
Definition: ni_util.c:5009
NI_RETCODE_PARAM_ERROR_CUSTOM_GOP
@ NI_RETCODE_PARAM_ERROR_CUSTOM_GOP
Definition: ni_defs.h:492
NI_RETCODE_PARAM_INVALID_NAME
@ NI_RETCODE_PARAM_INVALID_NAME
Definition: ni_defs.h:450
NI_AI_STATUS_BAD_INOUT
@ NI_AI_STATUS_BAD_INOUT
Definition: ni_defs.h:623
ni_insert_emulation_prevent_bytes
int ni_insert_emulation_prevent_bytes(uint8_t *buf, int size)
Insert emulation prevention byte(s) as needed into the data buffer.
Definition: ni_util.c:3211
ni_get_hw_yuv420p_dim
void ni_get_hw_yuv420p_dim(int width, int height, int factor, int is_semiplanar, int plane_stride[NI_MAX_NUM_DATA_POINTERS], int plane_height[NI_MAX_NUM_DATA_POINTERS])
Get dimension information of Netint HW YUV420p frame to be sent to encoder for encoding....
Definition: ni_util.c:2660
ni_buffer_pool_return_buffer
void ni_buffer_pool_return_buffer(ni_queue_node_t *buf, ni_queue_buffer_pool_t *p_buffer_pool)
Definition: ni_util.c:1592
END
#define END
Definition: ni_defs.h:338
NI_XCODER_REVISION_API_MINOR_VER_IDX
#define NI_XCODER_REVISION_API_MINOR_VER_IDX
Definition: ni_defs.h:100
ni_pthread_mutex_destroy
int ni_pthread_mutex_destroy(ni_pthread_mutex_t *mutex)
destory a mutex
Definition: ni_util.c:4664
LIBXCODER_API_VERSION
#define LIBXCODER_API_VERSION
Definition: ni_defs.h:115
NI_MAX_SEI_DATA
#define NI_MAX_SEI_DATA
Definition: ni_device_api.h:439
ni_queue_free
ni_retcode_t ni_queue_free(ni_queue_t *p_queue, ni_queue_buffer_pool_t *p_buffer_pool)
Free xcoder queue.
Definition: ni_util.c:2430
ni_get_libxcoder_release_ver
char * ni_get_libxcoder_release_ver(void)
Get libxcoder SW release version.
Definition: ni_util.c:4334
NI_AI_BUFFER_FORMAT_BFP16
@ NI_AI_BUFFER_FORMAT_BFP16
Definition: ni_device_api.h:1832
_ni_buf_pool_t::p_used_head
ni_buf_t * p_used_head
Definition: ni_device_api.h:1302
NI_NVME_IDENTITY_CMD_DATA_SZ
#define NI_NVME_IDENTITY_CMD_DATA_SZ
Definition: ni_nvme.h:38
_niFrameSurface1::device_handle
int32_t device_handle
Definition: ni_device_api.h:2877
_ni_network_layer_info::out_param
ni_network_layer_params_t * out_param
Definition: ni_device_api.h:1368
ni_gettimeofday
int32_t ni_gettimeofday(struct timeval *p_tp, void *p_tzp)
Get time for logs with microsecond timestamps.
Definition: ni_util.c:139
_ni_network_layer_params_t::affine
struct _ni_network_layer_params_t::@13::@15 affine
NI_RETCODE_ERROR_EXCEED_MAX_NUM_SESSIONS
@ NI_RETCODE_ERROR_EXCEED_MAX_NUM_SESSIONS
Definition: ni_defs.h:518
_ni_queue_buffer_pool_t::p_used_head
ni_queue_node_t * p_used_head
Definition: ni_device_api.h:1322
_ni_timestamp_table_t
Definition: ni_device_api.h:1334
NI_MIN_HEIGHT
#define NI_MIN_HEIGHT
Definition: ni_device_api.h:128
ni_get_rc_txt
const char * ni_get_rc_txt(ni_retcode_t rc)
Get text string for the provided error.
Definition: ni_util.c:4355
NI_RETCODE_FAILURE
@ NI_RETCODE_FAILURE
Definition: ni_defs.h:442
ni_strcat
ni_retcode_t ni_strcat(char *dest, size_t dmax, const char *src)
Definition: ni_util.c:685
_ni_buf_t::buf
void * buf
Definition: ni_device_api.h:1287
NI_RETCODE_PARAM_ERROR_GOP_PRESET
@ NI_RETCODE_PARAM_ERROR_GOP_PRESET
Definition: ni_defs.h:462
NI_RETCODE_PARAM_ERROR_HEIGHT_TOO_SMALL
@ NI_RETCODE_PARAM_ERROR_HEIGHT_TOO_SMALL
Definition: ni_defs.h:514
_ni_buf_pool_t::number_of_buffers
uint32_t number_of_buffers
Definition: ni_device_api.h:1298
MAX15162AAWE_C_IRATIO
#define MAX15162AAWE_C_IRATIO
Definition: ni_util.h:59
MAX17613B_C_IRATIO
#define MAX17613B_C_IRATIO
Definition: ni_util.h:65
_ni_queue_buffer_pool_t::number_of_buffers
uint32_t number_of_buffers
Definition: ni_device_api.h:1319
NI_RETCODE_PARAM_ERROR_FRATE
@ NI_RETCODE_PARAM_ERROR_FRATE
Definition: ni_defs.h:452
NI_RETCODE_PARAM_ERROR_CU_SIZE_MODE
@ NI_RETCODE_PARAM_ERROR_CU_SIZE_MODE
Definition: ni_defs.h:464
ni_network_layer_convert_tensor
ni_retcode_t ni_network_layer_convert_tensor(uint8_t *dst, uint32_t dst_len, const char *tensor_file, ni_network_layer_params_t *p_param)
Definition: ni_util.c:3858
NI_RETCODE_PARAM_ERROR_TOO_SMALL
@ NI_RETCODE_PARAM_ERROR_TOO_SMALL
Definition: ni_defs.h:504
ni_util.h
Utility definitions.
ni_remove_emulation_prevent_bytes
int ni_remove_emulation_prevent_bytes(uint8_t *buf, int size)
Remove emulation prevention byte(s) as needed from the data buffer.
Definition: ni_util.c:3264
NI_AI_STATUS_IO_ERROR
@ NI_AI_STATUS_IO_ERROR
Definition: ni_defs.h:620
NI_RETCODE_PARAM_ERROR_DY_MERGE_16X16_EN
@ NI_RETCODE_PARAM_ERROR_DY_MERGE_16X16_EN
Definition: ni_defs.h:467
ni_queue_pop_threshold
ni_retcode_t ni_queue_pop_threshold(ni_queue_t *p_queue, uint64_t frame_info, int64_t *p_timestamp, int32_t threshold, int32_t print, ni_queue_buffer_pool_t *p_buffer_pool)
Definition: ni_util.c:2335
MCU_REF_VOLTAGE
#define MCU_REF_VOLTAGE
Definition: ni_util.h:68
NI_RETCODE_ERROR_INVALID_HANDLE
@ NI_RETCODE_ERROR_INVALID_HANDLE
Definition: ni_defs.h:525
_ni_nvme_write_complete_dw0_t
Definition: ni_nvme.h:452
NI_RETCODE_PARAM_ERROR_INTRA_QP
@ NI_RETCODE_PARAM_ERROR_INTRA_QP
Definition: ni_defs.h:461
NI_AI_STATUS_NETWORK_NOT_READY
@ NI_AI_STATUS_NETWORK_NOT_READY
Definition: ni_defs.h:626
_ni_buf_pool_t::p_used_tail
ni_buf_t * p_used_tail
Definition: ni_device_api.h:1303
NI_RETCODE_NVME_SC_WRITE_BUFFER_FULL
@ NI_RETCODE_NVME_SC_WRITE_BUFFER_FULL
Definition: ni_defs.h:548
NI_AI_STATUS_SUCCESS
@ NI_AI_STATUS_SUCCESS
Definition: ni_defs.h:604
ni_aligned_free
#define ni_aligned_free(p_memptr)
Definition: ni_util.h:399
_ni_decoder_input_params_t::decoder_low_delay
int decoder_low_delay
Definition: ni_device_api.h:2582
_ni_xcoder_params::low_delay_mode
int low_delay_mode
Definition: ni_device_api.h:2807
NI_RETCODE_PARAM_ERROR_ZERO
@ NI_RETCODE_PARAM_ERROR_ZERO
Definition: ni_defs.h:506
NI_AI_STATUS_ERROR_SET_INOUT
@ NI_AI_STATUS_ERROR_SET_INOUT
Definition: ni_defs.h:615
NI_AI_STATUS_CONTEXT_NOT_AVAILABLE
@ NI_AI_STATUS_CONTEXT_NOT_AVAILABLE
Definition: ni_defs.h:618
ni_check_dev_name
ni_retcode_t ni_check_dev_name(const char *p_dev)
check dev name
Definition: ni_util.c:1871
ni_round_up
uint32_t ni_round_up(uint32_t number_to_round, uint32_t multiple)
Definition: ni_util.c:169
NI_AI_BUFFER_FORMAT_INT8
@ NI_AI_BUFFER_FORMAT_INT8
Definition: ni_device_api.h:1824
_ni_queue_t
Definition: ni_device_api.h:1326
NI_RETCODE_PARAM_ERROR_OOR
@ NI_RETCODE_PARAM_ERROR_OOR
Definition: ni_defs.h:507
NI_AI_BUFFER_FORMAT_UINT16
@ NI_AI_BUFFER_FORMAT_UINT16
Definition: ni_device_api.h:1826
NI_MIN_WIDTH
#define NI_MIN_WIDTH
Definition: ni_device_api.h:126
_ni_queue_node_t::p_previous_buffer
struct _ni_queue_node_t * p_previous_buffer
Definition: ni_device_api.h:1313
_EPSILON
#define _EPSILON
NI_RETCODE_NVME_SC_REQUEST_NOT_COMPLETED
@ NI_RETCODE_NVME_SC_REQUEST_NOT_COMPLETED
Definition: ni_defs.h:555
QUADRA
#define QUADRA
Definition: ni_defs.h:123
ni_ai_network_layer_size
uint32_t ni_ai_network_layer_size(ni_network_layer_params_t *p_param)
Definition: ni_util.c:3985
ni_retrieve_decoder_params
int ni_retrieve_decoder_params(char xcoderParams[], ni_xcoder_params_t *params, ni_session_context_t *ctx)
retrieve decoder config parameter values from –decoder-params
Definition: ni_util.c:4556
ni_get_utime
uint64_t ni_get_utime(void)
Get system time for log.
Definition: ni_util.c:2611
ni_queue_pop
ni_retcode_t ni_queue_pop(ni_queue_t *p_queue, uint64_t frame_info, int64_t *p_timestamp, int32_t threshold, int32_t print, ni_queue_buffer_pool_t *p_buffer_pool)
Pop from the xcoder queue.
Definition: ni_util.c:2230
ni_vsprintf
int ni_vsprintf(char *dest, const size_t dmax, const char *fmt, va_list args)
Definition: ni_util.c:1036
NI_AI_BUFFER_FORMAT_UINT64
@ NI_AI_BUFFER_FORMAT_UINT64
Definition: ni_device_api.h:1840
NI_RETCODE_NVME_SC_REQUEST_IN_PROGRESS
@ NI_RETCODE_NVME_SC_REQUEST_IN_PROGRESS
Definition: ni_defs.h:556
NI_LOG_DEBUG
@ NI_LOG_DEBUG
Definition: ni_log.h:64
_ni_xcoder_params::dec_input_params
ni_decoder_input_params_t dec_input_params
Definition: ni_device_api.h:2842
ni_copy_yuv_444p_to_420p
void ni_copy_yuv_444p_to_420p(uint8_t *p_dst0[NI_MAX_NUM_DATA_POINTERS], uint8_t *p_dst1[NI_MAX_NUM_DATA_POINTERS], uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS], int frame_width, int frame_height, int factor, int mode)
Copy yuv444p data to yuv420p frame layout to be sent to encoder for encoding. Data buffer (dst) is us...
Definition: ni_util.c:3098
NI_RETCODE_PARAM_ERROR_PICSKIP
@ NI_RETCODE_PARAM_ERROR_PICSKIP
Definition: ni_defs.h:534
MAX15162AAWE_R_IMON
#define MAX15162AAWE_R_IMON
Definition: ni_util.h:60
SHA256CTX::aui32State
uint32_t aui32State[8]
Definition: ni_util.c:4012
ni_fopen
ni_retcode_t ni_fopen(FILE **fp, const char *filename, const char *mode)
Definition: ni_util.c:979
_ni_err_rc_txt_entry::rc
ni_retcode_t rc
Definition: ni_util.c:44
NI_RETCODE_PARAM_ERROR_TRATE
@ NI_RETCODE_PARAM_ERROR_TRATE
Definition: ni_defs.h:456
NI_RETCODE_ERROR_RESOURCE_UNAVAILABLE
@ NI_RETCODE_ERROR_RESOURCE_UNAVAILABLE
Definition: ni_defs.h:448
NI_RETCODE_PARAM_ERROR_MN_QP
@ NI_RETCODE_PARAM_ERROR_MN_QP
Definition: ni_defs.h:473
NI_AI_STATUS_OUT_OF_MEMORY
@ NI_AI_STATUS_OUT_OF_MEMORY
Definition: ni_defs.h:622
ni_timestamp_get
ni_retcode_t ni_timestamp_get(ni_timestamp_table_t *p_table, uint64_t frame_info, int64_t *p_timestamp, int32_t threshold, int32_t print, ni_queue_buffer_pool_t *p_buffer_pool)
Retrieve timestamp from table based on frameoffset info.
Definition: ni_util.c:2018
NI_RETCODE_ERROR_LOCK_DOWN_DEVICE
@ NI_RETCODE_ERROR_LOCK_DOWN_DEVICE
Definition: ni_defs.h:521
IDENTIFY_DEVICE_R
#define IDENTIFY_DEVICE_R
Definition: ni_nvme.h:687
ni_assert
#define ni_assert(expression)
Definition: ni_defs.h:341
NI_RETCODE_ERROR_OPEN_DEVICE
@ NI_RETCODE_ERROR_OPEN_DEVICE
Definition: ni_defs.h:524
_ni_queue_node_t::p_prev
struct _ni_queue_node_t * p_prev
Definition: ni_device_api.h:1311
NI_RETCODE_PARAM_ERROR_INTRA_PERIOD
@ NI_RETCODE_PARAM_ERROR_INTRA_PERIOD
Definition: ni_defs.h:459