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