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