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