libxcoder 5.8.0
Loading...
Searching...
No Matches
ni_rsrc_api.cpp
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_rsrc_api.cpp
24 *
25 * \brief Public definitions for managing NETINT video processing devices
26 ******************************************************************************/
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <fcntl.h>
31#include <string.h>
32#include <errno.h>
33#include <ctype.h>
34
35#if __linux__ || __APPLE__
36#include <unistd.h>
37#include <fcntl.h> /* For O_* constants */
38#include <dirent.h>
39#include <sys/mman.h>
40#include <sys/types.h>
41#include <sys/stat.h> /* For mode constants */
42#include <regex.h>
43#endif
44
45#if __APPLE__
46#include <sys/syslimits.h>
47#endif
48
49#include "ni_rsrc_api.h"
50#include "ni_rsrc_priv.h"
51#include "ni_util.h"
52
53namespace {
54const char *ni_codec_format_str[] = {"H.264", "H.265", "VP9", "JPEG",
55 "AV1"};
56const char *ni_dec_name_str[] = {"h264_ni_quadra_dec", "h265_ni_quadra_dec",
57 "vp9_ni_quadra_dec", "jpeg_ni_quadra_dec"};
58const char *ni_enc_name_str[] = {"h264_ni_quadra_enc", "h265_ni_quadra_enc", "empty",
59 "jpeg_ni_quadra_enc", "av1_ni_quadra_enc"};
60
61// return true if string key is found in array of strings, false otherwise
62bool is_str_in_str_array(const char key[],
63 char arr[][NI_MAX_DEVICE_NAME_LEN],
64 int array_size)
65{
66 int i;
67
68 for (i = 0; i < array_size; i++)
69 {
70 if (0 == strcmp(key, arr[i]))
71 {
72 return true;
73 }
74 }
75 return false;
76}
77} // namespace
78
79#ifndef DEPRECATION_AS_ERROR
83NI_DEPRECATED ni_device_handle_t g_dev_handle = NI_INVALID_DEVICE_HANDLE;
84#endif
85
87{
88 if (!p_device)
89 {
90 ni_log(NI_LOG_INFO, "WARNING: NULL parameter passed in!\n");
91 return;
92 }
93
94 ni_device_info_t *p_dev_info = NULL;
95 for (int xcoder_index_1 = 0;
96 xcoder_index_1 < p_device->xcoder_cnt[NI_DEVICE_TYPE_ENCODER];
97 xcoder_index_1++)
98 {
99 p_dev_info = &p_device->xcoders[NI_DEVICE_TYPE_ENCODER][xcoder_index_1];
100 ni_log(NI_LOG_INFO, "Device #%d:\n", xcoder_index_1);
101 ni_log(NI_LOG_INFO, " Serial number: %.*s\n",
102 (int)sizeof(p_dev_info->serial_number),
103 p_dev_info->serial_number);
104 ni_log(NI_LOG_INFO, " Model number: %.*s\n",
105 (int)sizeof(p_dev_info->model_number),
106 p_dev_info->model_number);
107 ni_log(NI_LOG_INFO, " Last ran firmware loader version: %.8s\n",
108 p_dev_info->fl_ver_last_ran);
109 ni_log(NI_LOG_INFO, " NOR flash firmware loader version: %.8s\n",
110 p_dev_info->fl_ver_nor_flash);
111 ni_log(NI_LOG_INFO, " Current firmware revision: %.8s\n",
112 p_dev_info->fw_rev);
113 ni_log(NI_LOG_INFO, " NOR flash firmware revision: %.8s\n",
114 p_dev_info->fw_rev_nor_flash);
115 ni_log(NI_LOG_INFO, " F/W & S/W compatibility: %s\n",
116 p_dev_info->fw_ver_compat_warning ?
117 "no, possible missing features" : "yes");
118 ni_log(NI_LOG_INFO, " F/W branch: %s\n",
119 p_dev_info->fw_branch_name);
120 ni_log(NI_LOG_INFO, " F/W commit time: %s\n",
121 p_dev_info->fw_commit_time);
122 ni_log(NI_LOG_INFO, " F/W commit hash: %s\n",
123 p_dev_info->fw_commit_hash);
124 ni_log(NI_LOG_INFO, " F/W build time: %s\n",
125 p_dev_info->fw_build_time);
126 ni_log(NI_LOG_INFO, " F/W build id: %s\n",p_dev_info->fw_build_id);
127 ni_log(NI_LOG_INFO, " DeviceID: %s\n", p_dev_info->dev_name);
128 ni_log(NI_LOG_INFO, " PixelFormats: yuv420p, yuv420p10le, nv12, p010le"
129 ", ni_quadra\n");
130
131 for (size_t dev_type = NI_DEVICE_TYPE_DECODER;
132 dev_type != NI_DEVICE_TYPE_XCODER_MAX; dev_type++)
133 {
134 for (int xcoder_index_2 = 0;
135 xcoder_index_2 < p_device->xcoder_cnt[NI_DEVICE_TYPE_ENCODER];
136 xcoder_index_2++)
137 {
138 if (strcmp(p_dev_info->dev_name,
139 p_device->xcoders[dev_type][xcoder_index_2].dev_name)
140 == 0 && p_dev_info->module_id >= 0)
141 {
142 ni_rsrc_print_device_info(&(p_device->xcoders[dev_type]
143 [xcoder_index_2]));
144 }
145 }
146 }
147 }
148}
149
150/*!*****************************************************************************
151 * \brief Scan and refresh all resources on the host, taking into account
152 * hot-plugged and pulled out cards.
153 *
154 * \param[in] should_match_rev 0: transcoder firmware revision matching the
155 * library's version is NOT required for placing
156 * the transcoder into resource pool; 1: otherwise
157 *
158 * \return
159 * NI_RETCODE_SUCCESS on success
160 * NI_RETCODE_FAILURE on failure
161 *
162 ******************************************************************************/
163ni_retcode_t ni_rsrc_refresh(int should_match_rev)
164{
165 char xcoder_dev_names[NI_MAX_DEVICE_CNT][NI_MAX_DEVICE_NAME_LEN] = {0};
166 int xcoder_dev_count = 0;
167 char curr_dev_names[NI_MAX_DEVICE_CNT][NI_MAX_DEVICE_NAME_LEN] = {0};
168 int curr_dev_count = 0;
169 int i = 0;
170 ni_device_t *saved_coders = NULL;
171 char **xcoder_refresh_dev_names = NULL;
172 int xcoder_refresh_dev_count = 0;
173 saved_coders = (ni_device_t *)malloc(sizeof(ni_device_t));
174 if (!saved_coders)
175 {
176 char errmsg[NI_ERRNO_LEN] = {0};
178 ni_log(NI_LOG_ERROR, "ERROR %s() failed to malloc memory: %s\n",
179 __func__, errmsg);
180 return NI_RETCODE_FAILURE;
181 }
182 memset(saved_coders, 0, sizeof(ni_device_t));
183
184 // retrieve saved info from resource pool at start up
185 if (NI_RETCODE_SUCCESS ==
188 saved_coders->xcoders[NI_DEVICE_TYPE_ENCODER],
189 &(saved_coders->xcoder_cnt[NI_DEVICE_TYPE_ENCODER])))
190 {
191 for (i = 0; i < saved_coders->xcoder_cnt[NI_DEVICE_TYPE_ENCODER];
192 i++)
193 {
194 ni_strcpy(xcoder_dev_names[i], sizeof(xcoder_dev_names[i]),
195 saved_coders->xcoders[NI_DEVICE_TYPE_ENCODER][i]
196 .dev_name);
197 }
198 xcoder_dev_count =
199 saved_coders->xcoder_cnt[NI_DEVICE_TYPE_ENCODER];
200#ifdef XCODER_311
201 ni_log(NI_LOG_DEBUG,"%d devices retrieved from current pool at start up\n",
202 xcoder_dev_count);
203#else
204 ni_log(NI_LOG_INFO,"%d devices retrieved from current pool at start up\n",
205 xcoder_dev_count);
206#endif
207
208 } else
209 {
210 ni_log(NI_LOG_ERROR, "Error retrieving from current pool at start "
211 "up\n");
212 }
213 free(saved_coders);
214
215 if (xcoder_dev_count > 0)
216 {
217 xcoder_refresh_dev_names = (char **)malloc(xcoder_dev_count *
218 sizeof(char *));
219 for (i = 0; i < xcoder_dev_count; i++)
220 {
221 xcoder_refresh_dev_names[i] = (char *)malloc(NI_MAX_DEVICE_NAME_LEN);
222 ni_strcpy(xcoder_refresh_dev_names[i], NI_MAX_DEVICE_NAME_LEN, xcoder_dev_names[i]);
223 }
224 xcoder_refresh_dev_count = xcoder_dev_count;
225 }
226 curr_dev_count =
228 xcoder_refresh_dev_names, xcoder_refresh_dev_count);
229 if (0 == curr_dev_count)
230 {
231 ni_log(NI_LOG_ERROR, "No devices found on the host\n");
232 }
233 int devices_removed = 0;
234 int devices_added = 0;
235 // remove from resource pool any device that is not available now
236 for (i = 0; i < xcoder_dev_count; i++)
237 {
238 if (!is_str_in_str_array(xcoder_dev_names[i], curr_dev_names,
239 curr_dev_count))
240 {
242 "\n\n%d. %s NOT in current scanned list, removing !\n", i,
243 xcoder_dev_names[i]);
244 if (NI_RETCODE_SUCCESS ==
245 ni_rsrc_remove_device(xcoder_dev_names[i]))
246 {
247 ni_log(NI_LOG_INFO, "%s deleted successfully !\n",
248 xcoder_dev_names[i]);
249 devices_removed++;
250 } else
251 {
252 ni_log(NI_LOG_ERROR, "%s failed to delete !\n",
253 xcoder_dev_names[i]);
254 }
255 }
256 }
257
258 // and add into resource pool any newly discoved ones
259 for (i = 0; i < curr_dev_count; i++)
260 {
261 if (!is_str_in_str_array(curr_dev_names[i], xcoder_dev_names,
262 xcoder_dev_count))
263 {
264 ni_log(NI_LOG_INFO, "\n\n%s NOT in previous list, adding !\n",
265 curr_dev_names[i]);
266 if (NI_RETCODE_SUCCESS ==
267 ni_rsrc_add_device(curr_dev_names[i], should_match_rev))
268 {
269 devices_added++;
270 ni_log(NI_LOG_INFO, "%s added successfully !\n", curr_dev_names[i]);
271 } else
272 {
273 ni_log(NI_LOG_ERROR, "%s failed to add !\n", curr_dev_names[i]);
274 }
275 }
276 }
277
278 if (devices_added != devices_removed)
279 {
280 ni_log(NI_LOG_ERROR, "Total devices added %d removed %d\n",devices_added,
281 devices_removed);
282 for (i = 0; i < xcoder_dev_count; i++)
283 {
284 ni_log(NI_LOG_ERROR, "Previous device %s\n", xcoder_dev_names[i]);
285 }
286 for (i = 0; i < curr_dev_count; i++)
287 {
288 ni_log(NI_LOG_ERROR, "Current device %s\n", curr_dev_names[i]);
289 }
290 }
291 if (xcoder_refresh_dev_names) {
292 for (i = 0; i < xcoder_refresh_dev_count; i++)
293 free(xcoder_refresh_dev_names[i]);
294 free(reinterpret_cast<void*>(xcoder_refresh_dev_names));
295 xcoder_refresh_dev_names = NULL;
296 }
297 return NI_RETCODE_SUCCESS;
298}
299
300#ifdef _ANDROID
301
302#include <utils/Mutex.h>
303#include "ni_rsrc_api_android.h"
304
305android::sp<INidec> service = NULL;
306static android::Mutex gLock;
307
308/*!*****************************************************************************
309 * \brief Init android net.int.SharedBuffer service for binder using.
310 *
311 * \param none
312 *
313 * \return service (= 0) if get service , < 0 otherwise
314 *
315 ******************************************************************************/
317{
318 android::Mutex::Autolock _l(gLock);
319 if (service == NULL)
320 {
321 service = INidec::tryGetService();
322 if (service == nullptr)
323 {
324 ni_log(NI_LOG_ERROR, "Failed to get Netint service, maybe it's not launched\n");
325 return -2;
326 }
327 }
328 return 0;
329}
330
331#endif
332
333#ifdef _WIN32
334
335#ifndef DEPRECATION_AS_ERROR
336/*!******************************************************************************
337 * \brief Scans system for all NVMe devices and returns the system device
338 * names to the user which were identified as NETINT transcoder deivices.
339 * Names are suitable for OpenFile api usage afterwards
340 * This function had been replaced by ni_rsrc_get_local_device_list2
341 * This function can't be callback with multi thread
342 *
343 *
344 * \param[out] ni_devices List of device names identified as NETINT NVMe transcoders
345 * \param[in] max_handles Max number of device names to return
346 *
347 * \return Number of devices found if successful operation completed
348 * 0 if no NETINT NVMe transcoder devices were found
349 * NI_RETCODE_ERROR_MEM_ALOC if memory allocation failed
350 *******************************************************************************/
352 char ni_devices[][NI_MAX_DEVICE_NAME_LEN],
353 int max_handles
354)
355{
356 if ((ni_devices == NULL)||(max_handles == 0))
357 {
358 ni_log(NI_LOG_ERROR, "Error with input parameters\n");
359 return 0;
360 }
361 return ni_rsrc_enumerate_devices(ni_devices, max_handles);
362}
363#endif
364
365/*!*****************************************************************************
366 * \brief Scans system for all NVMe devices and returns the system device
367 * names to the user which were identified as NETINT transcoder
368 * devices. Names are suitable for resource management API usage
369 * afterwards
370 * This function had replaced ni_rsrc_get_local_device_list
371 * This function can be callback with multi thread
372 *
373 * \param[out] ni_devices List of device names identified as NETINT NVMe
374 * transcoders
375 * \param[in] max_handles Max number of device names to return
376 * \param[in] xcoder_refresh_dev_names Xcoder fresh device name
377 * \param[in] xcoder_refresh_dev_count Xcoder fresh device number count
378 *
379 * \return Number of devices found. 0 if unsucessful.
380 ******************************************************************************/
382 int max_handles, char **xcoder_refresh_dev_names,
383 int xcoder_refresh_dev_count)
384{
385 if ((ni_devices == NULL)||(max_handles == 0))
386 {
387 ni_log(NI_LOG_ERROR, "Error with input parameters\n");
388 return 0;
389 }
390 return ni_rsrc_enumerate_devices(ni_devices, max_handles);
391}
392
393/*!******************************************************************************
394 * \brief
395 *
396 * \param
397 *
398 * \return
399 *******************************************************************************/
401{
402 ni_device_queue_t* p_device_queue = NULL;
403 ni_device_pool_t* p_device_pool = NULL;
404 HANDLE map_file_handle = NULL;
405 HANDLE mutex_handle = NULL;
406
407 //Create a mutex for protecting the memory area
408 mutex_handle = CreateMutexA(NULL, // default security attributes
409 FALSE, // initially owned
410 CODERS_LCK_NAME // unnamed mutex
411 );
412
413 if (NULL == mutex_handle)
414 {
415 ni_log(NI_LOG_ERROR, "CreateMutex %s failed: %d\n", CODERS_LCK_NAME,
416 NI_ERRNO);
417 return NULL;
418 }
419
420 if (WAIT_ABANDONED == WaitForSingleObject(mutex_handle, INFINITE))
421 {
422 ni_log(NI_LOG_ERROR, "ERROR: Failed to obtain mutex: %p\n", mutex_handle);
423 }
424
425 map_file_handle = OpenFileMappingA(
426 FILE_MAP_ALL_ACCESS, // read/write access
427 FALSE, // do not inherit the name
428 CODERS_SHM_NAME // name of mapping object
429 );
430
431 if (NULL == map_file_handle)
432 {
433 ReleaseMutex(mutex_handle);
434 CloseHandle(mutex_handle);
435 ni_log(NI_LOG_ERROR, "Could not open file mapping object %s, error: %d\n",
437 return NULL;
438 }
439
440 p_device_queue = ( ni_device_queue_t*)MapViewOfFile(
441 map_file_handle, // handle to map object
442 FILE_MAP_ALL_ACCESS, // read/write permission
443 0,
444 0,
445 sizeof(ni_device_queue_t)
446 );
447
448 if (NULL == p_device_queue)
449 {
450 ReleaseMutex(mutex_handle);
451 CloseHandle(mutex_handle);
452 CloseHandle(map_file_handle);
453 return NULL;
454 }
455
456 p_device_pool = (ni_device_pool_t *)malloc(sizeof(ni_device_pool_t));
457 if (NULL == p_device_pool)
458 {
459 char errmsg[NI_ERRNO_LEN] = {0};
461 ni_log(NI_LOG_ERROR, "ERROR %s() malloc() ni_device_pool_t: %s\n", __func__,
462 errmsg);
463 UnmapViewOfFile(p_device_queue);
464 }
465 else
466 {
467 p_device_pool->lock = mutex_handle;
468 p_device_pool->p_device_queue = p_device_queue;
469 }
470
471 ReleaseMutex(mutex_handle);
472 CloseHandle(map_file_handle);
473 return p_device_pool;
474}
475
476/*!******************************************************************************
477 * \brief Initialize and create all resources required to work with NETINT NVMe
478 * transcoder devices. This is a high level API function which is used
479 * mostly with user application like FFmpeg that relies on those resources.
480 * In case of custom application integration, revised functionality might
481 * be necessary utilizing coresponding API functions.
482 *
483 * \param[in] should_match_rev 0: transcoder firmware revision matching the
484 * library's version is NOT required for placing
485 * the transcoder into resource pool; 1: otherwise
486 * timeout_seconds -1: No timeout amount, loop until init success
487 * or fail; else: timeout will fail init once reached
488 *
489 * \return
490 * NI_RETCODE_SUCCESS on success
491 * NI_RETCODE_FAILURE on failure
492 *
493 *******************************************************************************/
494int ni_rsrc_init(int should_match_rev, int timeout_seconds)
495{
496 char device_names[NI_MAX_DEVICE_CNT][NI_MAX_DEVICE_NAME_LEN] = { 0 };
497 char api_version[5];
498 int number_of_devices = 0;
499 uint32_t runtime = 0;
500 while (0 == number_of_devices)
501 {
502 number_of_devices = ni_rsrc_get_local_device_list2(device_names, NI_MAX_DEVICE_CNT,
503 NULL, 0);
504
505 if (NI_RETCODE_ERROR_MEM_ALOC == number_of_devices)
506 {
507 ni_log(NI_LOG_FATAL, "FATAL: memory allocation failed\n");
508 return NI_RETCODE_FAILURE;
509 }
510 else if (0 == number_of_devices)
511 {
512 ni_log(NI_LOG_INFO, "Quadra devices not ready\n");
514 {
515 ni_log(NI_LOG_ERROR, "User requested to stop checking\n");
516 return NI_RETCODE_FAILURE;
517 }
518 if (timeout_seconds == 0) {
519 ni_log(NI_LOG_ERROR, "Quadra devices not ready "
520 "and exit without wait\n");
522 }
523 runtime += 1;
524 Sleep(1 * 1000);
525 if (runtime >= (uint32_t)timeout_seconds)
526 {
527 ni_log(NI_LOG_ERROR, "Timeout reached at %d seconds! Failing\n",
528 runtime);
530 }
531 }
532 }
533
535 api_version);
536 ni_log(NI_LOG_INFO, "Compatible FW API version: %s\n", api_version);
537
538 return ni_rsrc_init_priv(should_match_rev, number_of_devices, device_names);
539}
540
541
542/*!******************************************************************************
543* \brief Allocates and returns a pointer to ni_device_context_t struct
544* based on provided device_type and guid.
545* To be used for load update and codec query.
546*
547* \param[in] device_type NI_DEVICE_TYPE_DECODER or NI_DEVICE_TYPE_ENCODER
548* \param[in] guid GUID of the encoder or decoder device
549*
550* \return pointer to ni_device_context_t if found, NULL otherwise
551*
552* Note: The returned ni_device_context_t content is not supposed to be used by
553* caller directly: should only be passed to API in the subsequent
554* calls; also after its use, the context should be released by
555* calling ni_rsrc_free_device_context.
556*******************************************************************************/
558{
559 char shm_name[32] = { 0 };
560 char lck_name[32] = { 0 };
561 ni_device_context_t* p_device_context = NULL;
562 ni_device_info_t* p_device_queue = NULL;
563 HANDLE map_file_handle = NULL;
564 HANDLE mutex_handle = NULL;
565
567 ni_rsrc_get_shm_name(device_type, guid, shm_name, sizeof(shm_name));
568 ni_rsrc_get_lock_name(device_type, guid, lck_name, sizeof(lck_name));
569 //Create a mutex for protecting the memory area
570 mutex_handle = CreateMutexA(NULL, // default security attributes
571 FALSE, // initially owned
572 lck_name); // unnamed mutex
573
574 if (NULL == mutex_handle)
575 {
576 ni_log(NI_LOG_ERROR, "CreateMutex error: %d\n", NI_ERRNO);
577 p_device_context = NULL;
578 LRETURN;
579 }
580
581 if (WAIT_ABANDONED == WaitForSingleObject(mutex_handle, INFINITE))
582 {
583 ni_log(NI_LOG_ERROR, "ERROR: ni_rsrc_get_device_context() failed to "
584 "obtain mutex: %p\n", mutex_handle);
585 }
586
587 map_file_handle = OpenFileMappingA(
588 FILE_MAP_ALL_ACCESS, // read/write access
589 FALSE, // do not inherit the name
590 shm_name
591 ); // name of mapping object
592
593 if (NULL == map_file_handle)
594 {
595 ni_log(NI_LOG_ERROR, "Could not open file mapping object %s, error: %d.\n",
596 shm_name, NI_ERRNO);
597 p_device_context = NULL;
598 LRETURN;
599 }
600
601 p_device_queue = (ni_device_info_t*)MapViewOfFile(
602 map_file_handle, // handle to map object
603 FILE_MAP_ALL_ACCESS, // read/write permission
604 0,
605 0,
606 sizeof(ni_device_info_t)
607 );
608
609 if (NULL == p_device_queue)
610 {
611 ni_log(NI_LOG_ERROR, "Could not map view of file, p_last error (%d).\n",
612 NI_ERRNO);
614 p_device_context = NULL;
615 LRETURN;
616 }
617
618 p_device_context = (ni_device_context_t *)malloc(sizeof(ni_device_context_t));
619 if (NULL == p_device_context)
620 {
621 char errmsg[NI_ERRNO_LEN] = {0};
623 ni_log(NI_LOG_ERROR, "ERROR %s() malloc() ni_device_context_t: %s\n",
624 __func__, errmsg);
625 p_device_context = NULL;
626 LRETURN;
627 }
628
629 ni_strncpy(p_device_context->shm_name, NI_MAX_DEVICE_NAME_LEN, shm_name, (NI_MAX_DEVICE_NAME_LEN-1));
630 p_device_context->lock = mutex_handle;
631 p_device_context->p_device_info = p_device_queue;
632
633END:
634
635 if (NULL == p_device_context)
636 {
637 if (NULL != p_device_queue)
638 {
639 UnmapViewOfFile(p_device_queue);
640 }
641 if (NULL != mutex_handle)
642 {
643 ReleaseMutex(mutex_handle);
644 CloseHandle(mutex_handle);
645 }
646
647 if (NULL != map_file_handle)
648 {
649 CloseHandle(map_file_handle);
650 }
651 } else
652 {
653 ReleaseMutex(mutex_handle);
654 CloseHandle(map_file_handle);
655 }
656
657 return p_device_context;
658}
659
660#elif __linux__ || __APPLE__
661#if __APPLE__
662#define DEV_NAME_PREFIX "rdisk"
663#elif defined(XCODER_LINUX_VIRTIO_DRIVER_ENABLED)
664#define DEV_NAME_PREFIX "vd"
665#else
666#define DEV_NAME_PREFIX "nvme"
667#endif
668
669#ifndef DEPRECATION_AS_ERROR
670/*!*****************************************************************************
671 * \brief Scans system for all NVMe devices and returns the system device
672 * names to the user which were identified as NETINT transcoder
673 * devices. Names are suitable for resource management API usage
674 * afterwards
675 * This function had been replaced by ni_rsrc_get_local_device_list2
676 * This function can't be callback with multi thread
677 *
678 * \param[out] ni_devices List of device names identified as NETINT NVMe
679 * transcoders
680 * \param[in] max_handles Max number of device names to return
681 *
682 * \return Number of devices found. 0 if unsucessful.
683 ******************************************************************************/
685 int max_handles)
686{
687 /* list all XCoder devices under /dev/.. */
688#if defined(_ANDROID) || defined(__OPENHARMONY__)
689#define ANDROID_MAX_DIR_NUM 2
690 int android_dir_num = 0;
691 const char* dir_name_array[ANDROID_MAX_DIR_NUM];
692 dir_name_array[0] = "/dev";
693 dir_name_array[1] = "/dev/block";
694#else
695 const char* dir_name = "/dev";
696#endif
697 int i, xcoder_device_cnt = 0;
698 DIR* FD;
699 struct dirent* in_file;
700 ni_device_info_t device_info;
701 ni_device_capability_t device_capabilites;
702 ni_device_handle_t dev_handle = NI_INVALID_DEVICE_HANDLE;
703 ni_retcode_t rc;
704 g_device_in_ctxt = false;
705
706 if ((ni_devices == NULL)||(max_handles == 0))
707 {
708 ni_log(NI_LOG_ERROR, "ERROR: bad input parameters\n");
709 return 0;
710 }
711
712 int nvme_dev_cnt = 0;
713 char nvme_devices[200][NI_MAX_DEVICE_NAME_LEN];
714
715 regex_t regex;
716 // GNU ERE not support /d, use [0-9] or [[:digit:]] instead
717#if __APPLE__
718 const char *pattern = "^rdisk[0-9]+$";
719#elif defined(XCODER_LINUX_VIRTIO_DRIVER_ENABLED)
720 const char *pattern = "^vd[a-z]$";
721#else
722 const char *pattern = "^nvme[0-9]+(c[0-9]+)?n[0-9]+$";
723#endif
724 // Compile the regular expression
725 if(regcomp(&regex, pattern, REG_EXTENDED | REG_NOSUB)) {
726 ni_log(NI_LOG_ERROR, "Could not compile regex\n");
727 return 0;
728 }
729
730#if defined(_ANDROID) || defined(__OPENHARMONY__)
731 //find XCoder devices in folders of dir_name_array until find in one folder
732 //or not find in any folders
733 while(xcoder_device_cnt == 0 && android_dir_num < ANDROID_MAX_DIR_NUM)
734 {
735 const char *dir_name = dir_name_array[android_dir_num];
736 ++android_dir_num;
737
738 nvme_dev_cnt = 0;
739 g_device_in_ctxt = false;
740 dev_handle = NI_INVALID_DEVICE_HANDLE;
741 // g_dev_handle = NI_INVALID_DEVICE_HANDLE;
742 size_t size_of_nvme_devices_x = sizeof(nvme_devices)/sizeof(nvme_devices[0]);
743 for(size_t dimx = 0; dimx < size_of_nvme_devices_x; ++dimx)
744 {
745 memset(nvme_devices[dimx], 0, sizeof(nvme_devices[0]));
746 }
747 //}//while brace below will end this
748#endif
749
750 FD = opendir(dir_name);
751 if (NULL == FD)
752 {
753
754#if defined(_ANDROID) || defined(__OPENHARMONY__)
755 ni_log(NI_LOG_INFO, "Failed to open directory %s\n", dir_name);
756 if(android_dir_num < ANDROID_MAX_DIR_NUM)
757 {
758 continue;
759 }
760 regfree(&regex);
761 return 0;
762#else
763 ni_log(NI_LOG_ERROR, "ERROR: failed to open directory %s\n", dir_name);
764 regfree(&regex);
765 return 0;
766#endif
767 }
768
769 /* collect all the available NVMe devices and sort */
770 while ((in_file = readdir(FD))) // NOLINT(concurrency-mt-unsafe) - thread-local FD, no shared DIR*
771 {
773 if (!strcmp(in_file->d_name, ".") || !strcmp(in_file->d_name, ".."))
774 {
775 continue;
776 }
777
778 /* pick only those files with name nvmeX where X consists of 1-n
779 digits */
780 if (!strncmp(in_file->d_name, DEV_NAME_PREFIX, strlen(DEV_NAME_PREFIX)))
781 {
782 if (nvme_dev_cnt < 200)
783 {
784 const int write_len = snprintf(nvme_devices[nvme_dev_cnt],
785 NI_MAX_DEVICE_NAME_LEN - 6, "%s/%s",
786 dir_name, in_file->d_name);
787 if (write_len < 0 || write_len >= (NI_MAX_DEVICE_NAME_LEN - 6))
788 {
790 "ERROR: failed to copy device %d name %s\n",
791 nvme_dev_cnt, in_file->d_name);
792 }
793 nvme_dev_cnt++;
794 }
795 int skip_this = 0;
796 skip_this = regexec(&regex, in_file->d_name, 0, NULL, 0);
797 ni_log(NI_LOG_TRACE, "name: %s skip %d\n", in_file->d_name, skip_this);
798
799 if (!skip_this)
800 {
801 memset(&device_info, 0, sizeof(ni_device_info_t));
802 if (snprintf(device_info.dev_name, NI_MAX_DEVICE_NAME_LEN - 6,
803 "%s/%s", dir_name, in_file->d_name) < 0)
804 {
806 "ERROR: failed an snprintf() in "
807 "ni_rsrc_get_local_device_list()\n");
808 continue;
809 }
810 ni_strncpy(device_info.blk_name, NI_MAX_DEVICE_NAME_LEN, device_info.dev_name,
812 memset(&device_capabilites, 0, sizeof(ni_device_capability_t));
813
814 g_device_in_ctxt = false;
815 for (int j = 0; j < g_xcoder_refresh_dev_count; j++)
816 {
817 if (0 ==
818 strcmp(device_info.dev_name,
820 {
821 g_device_in_ctxt = true;
822 break;
823 }
824 }
826 {
827 continue;
828 }
830 {
831 continue;
832 }
833 dev_handle = ni_device_open2(device_info.dev_name, NI_DEVICE_READ_ONLY);
834
835 if (NI_INVALID_DEVICE_HANDLE != dev_handle)
836 {
837 g_dev_handle = dev_handle;
838 rc = ni_device_capability_query(dev_handle,
839 &device_capabilites);
840 if (NI_RETCODE_SUCCESS == rc)
841 {
842 if (is_supported_xcoder(
843 device_capabilites.device_is_xcoder))
844 {
845 ni_devices[xcoder_device_cnt][0] = '\0';
846 ni_strcat(ni_devices[xcoder_device_cnt], NI_MAX_DEVICE_NAME_LEN,
847 device_info.dev_name);
848 xcoder_device_cnt++;
849 }
850 }
851 g_dev_handle = NI_INVALID_DEVICE_HANDLE;
852
853 ni_device_close(dev_handle);
854 }
855 }
856 }
857 if ((NI_MAX_DEVICE_CNT <= xcoder_device_cnt) ||
858 (max_handles <= xcoder_device_cnt))
859 {
861 "Disregarding some Netint devices on system over "
862 "limit of NI_MAX_DEVICE_CNT(%d) or max_handles(%d)\n",
863 NI_MAX_DEVICE_CNT, max_handles);
864 break;
865 }
866 }
867 closedir(FD);
868
869#if defined(_ANDROID) || defined(__OPENHARMONY__)
870 }//while brace
871#endif
872
873 regfree(&regex);
874
875 qsort(ni_devices, xcoder_device_cnt, (size_t)NI_MAX_DEVICE_NAME_LEN,
877 if (0 == xcoder_device_cnt)
878 {
879 ni_log(NI_LOG_INFO, "Found %d NVMe devices on system, none of them xcoder\n", nvme_dev_cnt);
880 for (i = 0; i < nvme_dev_cnt; i++)
881 {
882 ni_log(NI_LOG_INFO, "NVMe device %d: %s\n", i, nvme_devices[i]);
883 }
884 }
885 g_device_in_ctxt = false;
886 g_dev_handle = NI_INVALID_DEVICE_HANDLE;
887
888 return xcoder_device_cnt;
889}
890#endif
891
892/*!*****************************************************************************
893 * \brief Scans system for all NVMe devices and returns the system device
894 * names to the user which were identified as NETINT transcoder
895 * devices. Names are suitable for resource management API usage
896 * afterwards
897 * This function had replaced ni_rsrc_get_local_device_list
898 * This function can be callback with multi thread
899 *
900 * \param[out] ni_devices List of device names identified as NETINT NVMe
901 * transcoders
902 * \param[in] max_handles Max number of device names to return
903 * \param[in] xcoder_refresh_dev_names Xcoder fresh device name
904 * \param[in] xcoder_refresh_dev_count Xcoder fresh device number count
905 *
906 * \return Number of devices found. 0 if unsucessful.
907 ******************************************************************************/
909 int max_handles, char **xcoder_refresh_dev_names,
910 int xcoder_refresh_dev_count)
911{
912 /* list all XCoder devices under /dev/.. */
913#ifdef _ANDROID
914#define ANDROID_MAX_DIR_NUM 2
915 int android_dir_num = 0;
916 const char* dir_name_array[ANDROID_MAX_DIR_NUM];
917 dir_name_array[0] = "/dev";
918 dir_name_array[1] = "/dev/block";
919#else
920 const char* dir_name = "/dev";
921#endif
922 int i, xcoder_device_cnt = 0;
923 DIR* FD;
924 struct dirent* in_file;
925 ni_device_info_t device_info;
926 ni_device_capability_t device_capabilites;
927 ni_device_handle_t dev_handle = NI_INVALID_DEVICE_HANDLE;
928 ni_retcode_t rc;
929 bool device_in_ctxt = false;
930
931 if ((ni_devices == NULL)||(max_handles == 0))
932 {
933 ni_log(NI_LOG_ERROR, "ERROR: bad input parameters\n");
934 return 0;
935 }
936
937 int nvme_dev_cnt = 0;
938 char nvme_devices[200][NI_MAX_DEVICE_NAME_LEN];
939
940 regex_t regex;
941 // GNU ERE not support /d, use [0-9] or [[:digit:]] instead
942#if __APPLE__
943 const char *pattern = "^rdisk[0-9]+$";
944#elif defined(XCODER_LINUX_VIRTIO_DRIVER_ENABLED)
945 const char *pattern = "^vd[a-z]$";
946#else
947 const char *pattern = "^nvme[0-9]+(c[0-9]+)?n[0-9]+$";
948#endif
949 // Compile the regular expression
950 if(regcomp(&regex, pattern, REG_EXTENDED | REG_NOSUB)) {
951 ni_log(NI_LOG_ERROR, "Could not compile regex\n");
952 return 0;
953 }
954
955#ifdef _ANDROID
956 //find XCoder devices in folders of dir_name_array until find in one folder
957 //or not find in any folders
958 while(xcoder_device_cnt == 0 && android_dir_num < ANDROID_MAX_DIR_NUM)
959 {
960 const char *dir_name = dir_name_array[android_dir_num];
961 ++android_dir_num;
962
963 nvme_dev_cnt = 0;
964 device_in_ctxt = false;
965 dev_handle = NI_INVALID_DEVICE_HANDLE;
966 // g_dev_handle = NI_INVALID_DEVICE_HANDLE;
967 size_t size_of_nvme_devices_x = sizeof(nvme_devices)/sizeof(nvme_devices[0]);
968 for(size_t dimx = 0; dimx < size_of_nvme_devices_x; ++dimx)
969 {
970 memset(nvme_devices[dimx], 0, sizeof(nvme_devices[0]));
971 }
972 //}//while brace below will end this
973#endif
974
975 FD = opendir(dir_name);
976 if (NULL == FD)
977 {
978
979#ifdef _ANDROID
980 ni_log(NI_LOG_INFO, "Failed to open directory %s\n", dir_name);
981 if(android_dir_num < ANDROID_MAX_DIR_NUM)
982 {
983 continue;
984 }
985 regfree(&regex);
986 return 0;
987#else
988 ni_log(NI_LOG_ERROR, "ERROR: failed to open directory %s\n", dir_name);
989 regfree(&regex);
990 return 0;
991#endif
992 }
993
994 /* collect all the available NVMe devices and sort */
995 while ((in_file = readdir(FD))) // NOLINT(concurrency-mt-unsafe) - thread-local FD, no shared DIR*
996 {
998 if (!strcmp(in_file->d_name, ".") || !strcmp(in_file->d_name, ".."))
999 {
1000 continue;
1001 }
1002
1003 /* pick only those files with name nvmeX where X consists of 1-n
1004 digits */
1005 if (!strncmp(in_file->d_name, DEV_NAME_PREFIX, strlen(DEV_NAME_PREFIX)))
1006 {
1007 if (nvme_dev_cnt < 200)
1008 {
1009 const int write_len = snprintf(nvme_devices[nvme_dev_cnt],
1010 NI_MAX_DEVICE_NAME_LEN - 6, "%s/%s",
1011 dir_name, in_file->d_name);
1012 if (write_len < 0 || write_len >= (NI_MAX_DEVICE_NAME_LEN - 6))
1013 {
1015 "ERROR: failed to copy device %d name %s\n",
1016 nvme_dev_cnt, in_file->d_name);
1017 }
1018 nvme_dev_cnt++;
1019 }
1020 int skip_this = 0;
1021 skip_this = regexec(&regex, in_file->d_name, 0, NULL, 0);
1022 ni_log(NI_LOG_TRACE, "name: %s skip %d\n", in_file->d_name, skip_this);
1023
1024 if (!skip_this)
1025 {
1026 memset(&device_info, 0, sizeof(ni_device_info_t));
1027 if (snprintf(device_info.dev_name, NI_MAX_DEVICE_NAME_LEN - 6,
1028 "%s/%s", dir_name, in_file->d_name) < 0)
1029 {
1031 "ERROR: failed an snprintf() in "
1032 "ni_rsrc_get_local_device_list2()\n");
1033 continue;
1034 }
1035 ni_strncpy(device_info.blk_name, NI_MAX_DEVICE_NAME_LEN, device_info.dev_name,
1037 memset(&device_capabilites, 0, sizeof(ni_device_capability_t));
1038
1039 device_in_ctxt = false;
1040 for (int j = 0; j < xcoder_refresh_dev_count; j++)
1041 {
1042 if (0 ==
1043 strcmp(device_info.dev_name,
1044 xcoder_refresh_dev_names[j]))
1045 {
1046 device_in_ctxt = true;
1047 break;
1048 }
1049 }
1050 if (NI_RETCODE_SUCCESS != ni_check_dev_name(device_info.dev_name))
1051 {
1052 continue;
1053 }
1055 {
1056 continue;
1057 }
1058 dev_handle = ni_device_open2(device_info.dev_name, NI_DEVICE_READ_ONLY);
1059
1060 if (NI_INVALID_DEVICE_HANDLE != dev_handle)
1061 {
1062 rc = ni_device_capability_query2(dev_handle,
1063 &device_capabilites, device_in_ctxt);
1064 if (NI_RETCODE_SUCCESS == rc)
1065 {
1066 if (is_supported_xcoder(
1067 device_capabilites.device_is_xcoder))
1068 {
1069 ni_devices[xcoder_device_cnt][0] = '\0';
1070 ni_strcat(ni_devices[xcoder_device_cnt], NI_MAX_DEVICE_NAME_LEN,
1071 device_info.dev_name);
1072 xcoder_device_cnt++;
1073 }
1074 }
1075
1076 ni_device_close(dev_handle);
1077 }
1078 }
1079 }
1080 if ((NI_MAX_DEVICE_CNT <= xcoder_device_cnt) ||
1081 (max_handles <= xcoder_device_cnt))
1082 {
1084 "Disregarding some Netint devices on system over "
1085 "limit of NI_MAX_DEVICE_CNT(%d) or max_handles(%d)\n",
1086 NI_MAX_DEVICE_CNT, max_handles);
1087 break;
1088 }
1089 }
1090 closedir(FD);
1091
1092#ifdef _ANDROID
1093 }//while brace
1094#endif
1095
1096 regfree(&regex);
1097
1098 qsort(ni_devices, xcoder_device_cnt, (size_t)NI_MAX_DEVICE_NAME_LEN,
1100 if (0 == xcoder_device_cnt)
1101 {
1102 ni_log(NI_LOG_INFO, "Found %d NVMe devices on system, none of them xcoder\n", nvme_dev_cnt);
1103 for (i = 0; i < nvme_dev_cnt; i++)
1104 {
1105 ni_log(NI_LOG_INFO, "NVMe device %d: %s\n", i, nvme_devices[i]);
1106 }
1107 }
1108
1109 return xcoder_device_cnt;
1110}
1111
1112/*!*****************************************************************************
1113 * \brief Create and return the allocated ni_device_pool_t struct
1114 *
1115 * \param None
1116 *
1117 * \return Pointer to ni_device_pool_t struct on success, or NULL on failure
1118 *******************************************************************************/
1120{
1121 int shm_fd = -1;
1122 ni_rsrc_shm_state state = NI_RSRC_SHM_IS_INVALID;
1123 const int flags = O_RDWR | O_CLOEXEC;
1124 const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
1125 ni_device_queue_t* p_device_queue = NULL;
1126 ni_lock_handle_t lock;
1127 ni_device_pool_t* p_device_pool = NULL;
1128
1129 if (ni_rsrc_try_get_shm_lock(CODERS_LCK_NAME,
1130 flags, mode, (int *)&lock) < 0) {
1131 ni_log(NI_LOG_ERROR, "%s: Failed to get lock\n", __func__);
1132 return NULL;
1133 }
1134
1135 if (ni_rsrc_open_shm(CODERS_SHM_NAME,
1136 sizeof(ni_device_queue_t),
1137 &state,
1138 (int *)&shm_fd) < 0) {
1139 ni_log(NI_LOG_ERROR, "%s: Failed to ni_rsrc_open_shm\n", __func__);
1140 LRETURN;
1141 }
1142
1143 if ((ni_rsrc_mmap_shm(CODERS_SHM_NAME,
1144 shm_fd,
1145 sizeof(ni_device_queue_t),
1146 (void **)&p_device_queue)) < 0) {
1147 ni_log(NI_LOG_ERROR, "%s(): Failed to ni_rsrc_mmap_shm\n", __func__);
1148 LRETURN;
1149 }
1150
1151 p_device_pool = (ni_device_pool_t *)malloc(sizeof(ni_device_pool_t));
1152 if (! p_device_pool) {
1153 char errmsg[NI_ERRNO_LEN] = {0};
1155 ni_log(NI_LOG_ERROR, "ERROR %s() malloc() ni_device_pool_t: %s\n",
1156 __func__, errmsg);
1157 ni_rsrc_munmap_shm((void *)p_device_queue, sizeof(ni_device_queue_t));
1158 } else {
1159 p_device_pool->lock = lock;
1160 p_device_pool->p_device_queue = p_device_queue;
1161 }
1162
1163END:
1164 lockf(lock, F_ULOCK, 0);
1165
1166 if (NULL == p_device_pool) {
1167 close(lock);
1168 }
1169
1170#ifndef __OPENHARMONY__
1171 if (shm_fd >= 0) {
1172 close(shm_fd);
1173 }
1174#endif
1175
1176 return p_device_pool;
1177}
1178
1179/*!******************************************************************************
1180 * \brief Initialize and create all resources required to work with NETINT NVMe
1181 * transcoder devices. This is a high level API function which is used
1182 * mostly with user application like FFmpeg that relies on those resources.
1183 * In case of custom application integration, revised functionality might
1184 * be necessary utilizing corresponding API functions.
1185 *
1186 * \param[in] should_match_rev 0: transcoder firmware revision matching the
1187 * library's version is NOT required for placing
1188 * the transcoder into resource pool; 1: otherwise
1189 * timeout_seconds -1: No timeout amount, loop until init success
1190 * or fail; else: timeout will fail init once reached
1191 *
1192 * \return
1193 * NI_RETCODE_SUCCESS on success
1194 * NI_RETCODE_FAILURE on failure
1195 *
1196 *******************************************************************************/
1197int ni_rsrc_init(int should_match_rev, int timeout_seconds)
1198{
1199 char device_names[NI_MAX_DEVICE_CNT][NI_MAX_DEVICE_NAME_LEN];
1200 char api_version[5];
1201 int number_of_devices;
1202 uint32_t runtime;
1203 const int limit_depth = 3;
1204 int ret;
1205
1206 runtime = 0;
1207 while (1)
1208 {
1209 number_of_devices = ni_rsrc_get_local_device_list2(device_names,
1211 NULL, 0);
1212 if (number_of_devices > 0)
1213 {
1214 break;
1215 }
1216 else
1217 {
1218 ni_log(NI_LOG_INFO, "Quadra devices not ready\n");
1220 {
1221 ni_log(NI_LOG_ERROR, "User requested to stop checking\n");
1222 return 1;
1223 }
1224 if (timeout_seconds == 0) {
1225 ni_log(NI_LOG_ERROR, "Quadra devices not ready "
1226 "and exit without wait\n");
1228 }
1229 ni_usleep(1000000);
1230 runtime += 1;
1231 /* timeout_seconds == -1 means wait indefinitely; skip timeout check */
1232 if (timeout_seconds != -1 && runtime >= (uint32_t)timeout_seconds)
1233 {
1235 "Timeout exceeded/reached after %u seconds!\n",
1236 runtime);
1238 }
1239 }
1240 }
1241
1243 api_version);
1244 ni_log(NI_LOG_INFO, "Compatible FW API version: %s\n", api_version);
1245
1246 ret = ni_rsrc_init_priv(should_match_rev, number_of_devices, device_names, limit_depth);
1247
1248 if (ret == NI_RETCODE_SUCCESS)
1249 {
1251 }
1252
1253 if (ret == NI_RETCODE_SUCCESS)
1254 {
1255 ret = ni_rsrc_refresh(should_match_rev);
1256 }
1257 return ret;
1258}
1259
1260/*!******************************************************************************
1261* \brief Allocates and returns a pointer to ni_device_context_t struct
1262* based on provided device_type and guid.
1263* To be used for load update and codec query.
1264*
1265 * \param[in] device_type NI_DEVICE_TYPE_DECODER or NI_DEVICE_TYPE_ENCODER
1266 * \param[in] guid GUID of the encoder or decoder device
1267*
1268* \return pointer to ni_device_context_t if found, NULL otherwise
1269*
1270* Note: The returned ni_device_context_t content is not supposed to be used by
1271* caller directly: should only be passed to API in the subsequent
1272* calls; also after its use, the context should be released by
1273* calling ni_rsrc_free_device_context.
1274*******************************************************************************/
1276{
1278 int shm_fd = -1;
1279 ni_rsrc_shm_state state = NI_RSRC_SHM_IS_INVALID;
1280 int lock;
1281 const int flags = O_RDWR | O_CLOEXEC;
1282 const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
1283 char shm_name[32] = { 0 };
1284 char lck_name[32] = { 0 };
1285 ni_device_context_t *p_device_context = NULL;
1286 ni_device_info_t *p_device_queue = NULL;
1287
1288 ni_rsrc_get_shm_name(device_type, guid, shm_name, sizeof(shm_name));
1289 ni_rsrc_get_lock_name(device_type, guid, lck_name, sizeof(lck_name));
1290
1291 if (ni_rsrc_try_get_shm_lock(lck_name, flags, mode, &lock) < 0) {
1292 ni_log(NI_LOG_ERROR, "%s: Failed to get lock\n", __func__);
1293 return NULL;
1294 }
1295
1296 if (ni_rsrc_open_shm(shm_name,
1297 sizeof(ni_device_info_t),
1298 &state,
1299 (int *)&shm_fd) < 0) {
1300 ni_log(NI_LOG_ERROR, "%s: Failed to ni_rsrc_open_shm\n", __func__);
1301 LRETURN;
1302 }
1303
1304 if ((ni_rsrc_mmap_shm(shm_name,
1305 shm_fd,
1306 sizeof(ni_device_info_t),
1307 (void **)&p_device_queue)) < 0) {
1308 ni_log(NI_LOG_ERROR, "%s(): Failed to ni_rsrc_mmap_shm\n", __func__);
1309 LRETURN;
1310 }
1311
1312 p_device_context = (ni_device_context_t *)malloc(sizeof(ni_device_context_t));
1313 if (!p_device_context) {
1314 char errmsg[NI_ERRNO_LEN] = {0};
1316 ni_log(NI_LOG_ERROR, "ERROR %s() malloc() ni_device_context_t: %s\n",
1317 __func__, errmsg);
1318 ni_rsrc_munmap_shm((void *)p_device_queue, sizeof(ni_device_info_t));
1319 LRETURN;
1320 }
1321
1322 ni_strncpy(p_device_context->shm_name, NI_MAX_DEVICE_NAME_LEN, shm_name, (NI_MAX_DEVICE_NAME_LEN-1));
1323 p_device_context->lock = lock;
1324 p_device_context->p_device_info = p_device_queue;
1325
1326END:
1327 lockf(lock, F_ULOCK, 0);
1328
1329#ifndef __OPENHARMONY__
1330 if (shm_fd >= 0) {
1331 close(shm_fd);
1332 }
1333#endif
1334
1335 return p_device_context;
1336}
1337#endif
1338
1339/*!******************************************************************************
1340 * \brief Free previously allocated device context
1341 *
1342 * \param p_device_context Pointer to previously allocated device context
1343 *
1344 * \return None
1345 *******************************************************************************/
1347{
1348 if (p_device_context)
1349 {
1350#ifdef _WIN32
1351 UnmapViewOfFile(p_device_context->p_device_info);
1352 ReleaseMutex(p_device_context->lock);
1353#elif __linux__ || __APPLE__
1354 close(p_device_context->lock);
1355 ni_rsrc_munmap_shm((void *)p_device_context->p_device_info, sizeof(ni_device_info_t));
1356 ni_log(NI_LOG_DEBUG, "in %s do munmap for %s\n", __func__, p_device_context->shm_name);
1357#endif
1358 free(p_device_context);
1359 }
1360}
1361
1362/*!******************************************************************************
1363* \brief List device(s) based on device type with full information
1364* including s/w instances on the system.
1365*
1366* \param[in] device_type NI_DEVICE_TYPE_DECODER or NI_DEVICE_TYPE_ENCODER
1367* \param[out] p_device The device information returned.
1368* \param[out] p_device_count The number of ni_device_info_t structs returned.
1369*
1370* \return
1371* NI_RETCODE_SUCCESS
1372* NI_RETCODE_FAILURE
1373*
1374* Note: Caller is responsible for allocating memory for "p_device".
1375*******************************************************************************/
1377 ni_device_info_t *p_device_info, int * p_device_count)
1378{
1379 int i, count;
1380 ni_device_queue_t *p_device_queue = NULL;
1381 ni_device_pool_t *p_device_pool = NULL;
1382 ni_device_context_t *p_device_context = NULL;
1384 bool b_release_pool_mtx = false;
1385
1386 if ( (NULL == p_device_info) || (NULL == p_device_count) )
1387 {
1388 retval = NI_RETCODE_FAILURE;
1389 LRETURN;
1390 }
1391
1392 p_device_pool = ni_rsrc_get_device_pool();
1393 if (NULL == p_device_pool)
1394 {
1395 retval = NI_RETCODE_FAILURE;
1396 LRETURN;
1397 }
1398
1399#ifdef _WIN32
1400 if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE)) // no time-out interval)
1401 {
1402 ni_log(NI_LOG_ERROR, "ERROR: ni_rsrc_list_devices() failed to obtain "
1403 "mutex: %p\n", p_device_pool->lock);
1404 retval = NI_RETCODE_FAILURE;
1405 LRETURN;
1406 }
1407#elif __linux__ || __APPLE__
1408 lockf(p_device_pool->lock, F_LOCK, 0);
1409#endif
1410
1411 b_release_pool_mtx = true;
1412
1413 p_device_queue = p_device_pool->p_device_queue;
1414 count = (int)p_device_queue->xcoder_cnt[device_type];
1415
1416 *p_device_count=0;
1417 for (i = 0; i < count; i++)
1418 {
1419 int guid = -1;
1420 guid = p_device_queue->xcoders[device_type][i];
1421 p_device_context = ni_rsrc_get_device_context(device_type, guid);
1422 if (p_device_context)
1423 {
1424#ifdef _WIN32
1425 if (WAIT_ABANDONED == WaitForSingleObject(p_device_context->lock, INFINITE)) // no time-out interval) //we got the mutex
1426 {
1427 ni_log(NI_LOG_ERROR, "ERROR: ni_rsrc_list_devices() failed to obtain "
1428 "mutex: %p\n", p_device_context->lock);
1429 ReleaseMutex(p_device_pool->lock);
1430 retval = NI_RETCODE_FAILURE;
1431 LRETURN;
1432 }
1433
1434 memcpy(&p_device_info[i], p_device_context->p_device_info, sizeof(ni_device_info_t));
1435 ReleaseMutex(p_device_context->lock);
1436#elif __linux__ || __APPLE__
1437 lockf(p_device_context->lock, F_LOCK, 0);
1438 memcpy(&p_device_info[i], p_device_context->p_device_info, sizeof(ni_device_info_t));
1439 lockf(p_device_context->lock, F_ULOCK, 0);
1440#endif
1441
1442 ni_rsrc_free_device_context(p_device_context);
1443
1444 (*p_device_count)++;
1445 }
1446 else
1447 {
1448 ni_log(NI_LOG_ERROR, "ERROR: cannot find decoder guid: %d\n", guid);
1449 }
1450 }
1451
1452END:
1453
1454 if (b_release_pool_mtx)
1455 {
1456#ifdef _WIN32
1457 ReleaseMutex(p_device_pool->lock);
1458#elif __linux__ || __APPLE__
1459 lockf(p_device_pool->lock, F_ULOCK, 0);
1460#endif
1461 }
1462
1463 ni_rsrc_free_device_pool(p_device_pool);
1464
1465 return retval;
1466}
1467
1468/*!******************************************************************************
1469* \brief List all devices with full information including s/w instances
1470* on the system.
1471
1472* \param[out] p_device The device information returned.
1473*
1474* \return
1475* NI_RETCODE_SUCCESS
1476* NI_RETCODE_INVALID_PARAM
1477* NI_RETCODE_FAILURE
1478*
1479* Note: Caller is responsible for allocating memory for "p_device".
1480*******************************************************************************/
1482{
1483 int k = 0;
1485
1486 if (NULL == p_device)
1487 {
1488 retval = NI_RETCODE_INVALID_PARAM;
1489 LRETURN;
1490 }
1491
1492 for (k = 0; k < NI_DEVICE_TYPE_XCODER_MAX; k++)
1493 {
1494 retval = ni_rsrc_list_devices((ni_device_type_t)k, p_device->xcoders[k],
1495 &(p_device->xcoder_cnt[k]));
1496 if (NI_RETCODE_FAILURE == retval)
1497 {
1498 ni_log(NI_LOG_ERROR, "ERROR: could not retrieve info for %d type "
1499 "devices\n", k);
1500 LRETURN;
1501 }
1502 }
1503
1504END:
1505
1506 return retval;
1507}
1508
1509/*!******************************************************************************
1510* \brief Grabs information for every initialized and uninitialized
1511* device.
1512
1513* \param list_uninitialized Flag to determine if uninitialized devices
1514* should be grabbed.
1515*
1516* \return
1517* NI_RETCODE_SUCCESS
1518* NI_RETCODE_INVALID_PARAM
1519* NI_RETCODE_FAILURE
1520*
1521* Note: Caller is responsible for allocating memory for "p_device".
1522*******************************************************************************/
1523ni_retcode_t ni_rsrc_list_all_devices2(ni_device_t* p_device, bool list_uninitialized)
1524{
1526 if (!p_device)
1527 {
1528 retval = NI_RETCODE_INVALID_PARAM;
1529 return retval;
1530 }
1531
1532 /* Grab initialized devices. */
1533
1534 const ni_log_level_t log_level = ni_log_get_level();
1535
1536 if (list_uninitialized)
1537 {
1539 }
1540
1541 ni_rsrc_list_all_devices(p_device);
1542
1543 if (!list_uninitialized)
1544 {
1545 return retval;
1546 }
1547
1548 ni_log_set_level(log_level);
1549
1550 /* Store device names of initialized devices. */
1551
1552 ni_device_info_t *p_dev_info;
1553 char initialized_dev_names[NI_MAX_DEVICE_CNT][NI_MAX_DEVICE_NAME_LEN] = {0};
1554
1555 for (int dev_index = 0;
1556 dev_index < p_device->xcoder_cnt[NI_DEVICE_TYPE_ENCODER]; dev_index++)
1557 {
1558 p_dev_info = &p_device->xcoders[NI_DEVICE_TYPE_ENCODER][dev_index];
1559 ni_strcpy(initialized_dev_names[dev_index], NI_MAX_DEVICE_NAME_LEN, p_dev_info->dev_name);
1560 }
1561
1562 /* Retrieve uninitialized devices. */
1563
1564 char dev_names[NI_MAX_DEVICE_CNT][NI_MAX_DEVICE_NAME_LEN] = {0};
1565 const int dev_count = ni_rsrc_get_local_device_list2(dev_names, NI_MAX_DEVICE_CNT,
1566 NULL, 0);
1567
1568 ni_device_capability_t capability;
1569 ni_device_handle_t fd;
1570
1571 for (int dev_index = 0; dev_index < dev_count; dev_index++)
1572 {
1573 if (is_str_in_str_array(dev_names[dev_index],
1574 initialized_dev_names, NI_MAX_DEVICE_CNT))
1575 {
1576 continue;
1577 }
1578
1579 fd = ni_device_open2(dev_names[dev_index], NI_DEVICE_READ_ONLY);
1580 if (NI_INVALID_DEVICE_HANDLE == fd)
1581 {
1582 ni_log(NI_LOG_ERROR, "Failed to open device: %s\n",
1583 dev_names[dev_index]);
1584 return NI_RETCODE_FAILURE;
1585 }
1586
1587 retval = ni_device_capability_query2(fd, &capability, false);
1588 if (NI_RETCODE_SUCCESS != retval)
1589 {
1590 ni_device_close(fd);
1591 ni_log(NI_LOG_ERROR, "Failed to query device capability: %s\n",
1592 dev_names[dev_index]);
1593 return retval;
1594 }
1595
1596 for (int dev_type = 0; dev_type < NI_DEVICE_TYPE_XCODER_MAX; dev_type++)
1597 {
1598 p_device->xcoder_cnt[dev_type]++;
1599
1600 p_dev_info = &p_device->xcoders[dev_type][dev_index];
1601 memcpy(p_dev_info->serial_number, capability.serial_number,
1602 sizeof(capability.serial_number));
1603 memcpy(p_dev_info->model_number, capability.model_number,
1604 sizeof(capability.model_number));
1605 memcpy(p_dev_info->fw_rev, capability.fw_rev,
1606 sizeof(capability.fw_rev));
1607 p_dev_info->fw_ver_compat_warning = ni_rsrc_is_fw_compat(capability.fw_rev) >= 2 ? 1 : 0;
1608 memcpy(p_dev_info->fw_branch_name, capability.fw_branch_name,
1609 sizeof(capability.fw_branch_name));
1610 memcpy(p_dev_info->fw_commit_time, capability.fw_commit_time,
1611 sizeof(capability.fw_commit_time));
1612 memcpy(p_dev_info->fw_commit_hash, capability.fw_commit_hash,
1613 sizeof(capability.fw_commit_hash));
1614 memcpy(p_dev_info->fw_build_time, capability.fw_build_time,
1615 sizeof(capability.fw_build_time));
1616 memcpy(p_dev_info->fw_build_id, capability.fw_build_id,
1617 sizeof(capability.fw_build_id));
1618 ni_strcpy(p_dev_info->dev_name, NI_MAX_DEVICE_NAME_LEN, dev_names[dev_index]);
1619 memcpy(p_dev_info->blk_name, p_dev_info->dev_name,
1620 sizeof(p_dev_info->dev_name));
1621 p_dev_info->device_type = (ni_device_type_t)dev_type;
1622 p_dev_info->module_id = -1; /* special value to indicate device is
1623 not initialized */
1624
1625 ni_query_fl_fw_versions(fd, p_dev_info);
1626 /* load FW flavour for an uninitialized card */
1627 ni_device_extra_info_t extra_info = {0};
1628 p_dev_info->fw_flavour =
1629 (ni_query_extra_info(fd, &extra_info, capability.fw_rev) == NI_RETCODE_SUCCESS)
1630 ? extra_info.fw_flavour : (uint8_t)'-';
1631 }
1632
1633 ni_device_close(fd);
1634 }
1635
1636 return retval;
1637}
1638
1639
1641{
1642 int i;
1643
1644 if (!p_device_info)
1645 {
1646 ni_log(NI_LOG_ERROR, "ERROR: Cannot print device info!\n");
1647 } else
1648 {
1649 ni_log(NI_LOG_INFO, " %s #%d\n",
1651 p_device_info->module_id);
1652 ni_log(NI_LOG_INFO, " H/W ID: %d\n", p_device_info->hw_id);
1653 ni_log(NI_LOG_INFO, " MaxNumInstances: %d\n",
1654 p_device_info->max_instance_cnt);
1655
1656 if (NI_DEVICE_TYPE_SCALER == p_device_info->device_type)
1657 {
1658 ni_log(NI_LOG_INFO, " Capabilities:\n");
1660 " Operations: Crop (ni_quadra_crop), Scale (ni_quadra_scale), Pad "
1661 "(ni_quadra_pad), Overlay (ni_quadra_overlay)\n"
1662 " Drawbox (ni_quadra_drawbox), Rotate (ni_quadra_rotate), XStack (ni_quadra_xstack)\n");
1663 } else if (NI_DEVICE_TYPE_AI == p_device_info->device_type)
1664 {
1665 ni_log(NI_LOG_INFO, " Capabilities:\n");
1666 ni_log(
1668 " Operations: ROI (ni_quadra_roi), Background Replace (ni_quadra_bg)\n");
1669 } else if (NI_DEVICE_TYPE_DECODER == p_device_info->device_type ||
1670 NI_DEVICE_TYPE_ENCODER == p_device_info->device_type)
1671 {
1672 ni_log(NI_LOG_INFO, " Max4KFps: %d\n", p_device_info->max_fps_4k);
1673 for (i = 0; i < EN_CODEC_MAX; i++)
1674 {
1675 if (EN_INVALID != p_device_info->dev_cap[i].supports_codec)
1676 {
1677 ni_log(NI_LOG_INFO, " %s ",
1678 ni_codec_format_str[p_device_info->dev_cap[i]
1679 .supports_codec]);
1680 ni_log(NI_LOG_INFO, "(%s) Capabilities:\n",
1682 p_device_info->device_type ?
1683 ni_dec_name_str[p_device_info->dev_cap[i]
1684 .supports_codec] :
1685 ni_enc_name_str[p_device_info->dev_cap[i]
1686 .supports_codec]);
1687 ni_log(NI_LOG_INFO, " MaxResolution: %dx%d\n",
1688 p_device_info->dev_cap[i].max_res_width,
1689 p_device_info->dev_cap[i].max_res_height);
1690 ni_log(NI_LOG_INFO, " MinResolution: %dx%d\n",
1691 p_device_info->dev_cap[i].min_res_width,
1692 p_device_info->dev_cap[i].min_res_height);
1693
1694 // no profile for JPEG encode, or level for JPEG
1695 if (! (NI_DEVICE_TYPE_ENCODER == p_device_info->device_type &&
1696 EN_JPEG == p_device_info->dev_cap[i].supports_codec))
1697 {
1698 ni_log(NI_LOG_INFO, " Profiles: %s\n",
1699 p_device_info->dev_cap[i].profiles_supported);
1700 }
1701 if (EN_JPEG != p_device_info->dev_cap[i].supports_codec)
1702 {
1703 ni_log(NI_LOG_INFO, " Level: %s\n",
1704 p_device_info->dev_cap[i].level);
1705 }
1706 }
1707 }
1708 }
1709 }
1710}
1711
1712/*!*****************************************************************************
1713* \brief Print detailed capability information of all devices
1714* on the system.
1715
1716* \param none
1717*
1718* \return none
1719*
1720*******************************************************************************/
1722{
1723 ni_device_t *device = NULL;
1724 device = (ni_device_t *)malloc(sizeof(ni_device_t));
1725 if (!device)
1726 {
1727 char errmsg[NI_ERRNO_LEN] = {0};
1729 ni_log(NI_LOG_ERROR, "ERROR %s() failed to malloc memory: %s\n",
1730 __func__, errmsg);
1731 return;
1732 }
1733 memset(device, 0, sizeof(ni_device_t));
1734
1736 {
1737 free(device);
1738 return;
1739 }
1740
1741 print_device(device);
1742 free(device);
1743}
1744
1745/*!*****************************************************************************
1746* \brief Prints detailed capability information for all initialized
1747* devices and general information about uninitialized devices.
1748
1749* \param list_uninitialized Flag to determine if uninitialized devices
1750* should be grabbed.
1751*
1752* \return none
1753*
1754*******************************************************************************/
1755void ni_rsrc_print_all_devices_capability2(bool list_uninitialized)
1756{
1757 ni_device_t *device = NULL;
1758 device = (ni_device_t *)malloc(sizeof(ni_device_t));
1759 if (!device)
1760 {
1761 char errmsg[NI_ERRNO_LEN] = {0};
1763 ni_log(NI_LOG_ERROR, "ERROR %s() failed to malloc memory: %s\n",
1764 __func__, errmsg);
1765 return;
1766 }
1767 memset(device, 0, sizeof(ni_device_t));
1768
1769 if (NI_RETCODE_SUCCESS != ni_rsrc_list_all_devices2(device, list_uninitialized))
1770 {
1771 free(device);
1772 return;
1773 }
1774
1775 print_device(device);
1776 free(device);
1777}
1778
1779/*!******************************************************************************
1780* \brief Query a specific device with detailed information on the system
1781
1782* \param[in] device_type NI_DEVICE_TYPE_DECODER or NI_DEVICE_TYPE_ENCODER
1783* \param[in] guid unique device(decoder or encoder) id
1784*
1785* \return
1786* pointer to ni_device_info_t if found
1787* NULL otherwise
1788*
1789* Note: Caller is responsible for releasing memory that was allocated for the
1790* returned pointer
1791*******************************************************************************/
1793{
1794 ni_device_info_t *p_device_info = NULL;
1795 ni_device_context_t* p_device_context = NULL;
1796
1797 p_device_context = ni_rsrc_get_device_context(device_type, guid);
1798 if (NULL == p_device_context)
1799 {
1800 LRETURN;
1801 }
1802
1803 p_device_info = (ni_device_info_t *)malloc(sizeof(ni_device_info_t));
1804 if (NULL == p_device_info)
1805 {
1806 LRETURN;
1807 }
1808
1809#ifdef _WIN32
1810 if (WAIT_ABANDONED == WaitForSingleObject(p_device_context->lock, INFINITE)) // no time-out interval) //we got the mutex
1811 {
1812 ni_log(NI_LOG_ERROR, "ERROR: ni_rsrc_get_device_info() failed to obtain "
1813 "mutex: %p\n", p_device_context->lock);
1814 free(p_device_info);
1815 LRETURN;
1816 }
1817
1818 memcpy(p_device_info, p_device_context->p_device_info, sizeof(ni_device_info_t));
1819 ReleaseMutex(p_device_context->lock);
1820#elif __linux
1821 lockf(p_device_context->lock, F_LOCK, 0);
1822
1823 memcpy(p_device_info, p_device_context->p_device_info, sizeof(ni_device_info_t));
1824
1825 lockf(p_device_context->lock, F_ULOCK, 0);
1826#endif
1827
1828END:
1829
1830 ni_rsrc_free_device_context(p_device_context);
1831
1832 return p_device_info;
1833}
1834
1835/*!****************************************************************************
1836* \brief Get GUID of the device by block device name and type
1837*
1838* \param[in] blk_name device's block name
1839* \param[in] type device type
1840*
1841* \return device GUID (>= 0) if found, NI_RETCODE_FAILURE (-1) otherwise
1842*******************************************************************************/
1843int ni_rsrc_get_device_by_block_name(const char *blk_name,
1844 ni_device_type_t device_type)
1845{
1846 int i;
1847 int guid = NI_RETCODE_FAILURE, tmp_id;
1848 ni_device_pool_t *p_device_pool = NULL;
1849 ni_device_context_t *p_device_context = NULL;
1850 int num_coders = 0;
1851
1852 //uploader shares instance with encoder
1853 if(device_type == NI_DEVICE_TYPE_UPLOAD)
1854 {
1855 device_type = NI_DEVICE_TYPE_ENCODER;
1856 }
1857
1858 p_device_pool = ni_rsrc_get_device_pool();
1859 if (!p_device_pool)
1860 {
1861 ni_log(NI_LOG_ERROR, "ERROR: cannot get p_device_pool\n");
1862 return guid;
1863 }
1864
1865#ifdef _WIN32
1866 // no time-out interval (we got the mutex)
1867 if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE))
1868 {
1869 ni_log(NI_LOG_ERROR, "ERROR: %s failed to obtain mutex: %p\n",
1870 __FUNCTION__, p_device_pool->lock);
1871 ni_rsrc_free_device_pool(p_device_pool);
1872 return NI_RETCODE_FAILURE;
1873 }
1874#elif __linux__ || __APPLE__
1875 lockf(p_device_pool->lock, F_LOCK, 0);
1876#endif
1877
1878 num_coders = (int)p_device_pool->p_device_queue->xcoder_cnt[device_type];
1879
1880 for (i = 0; i < num_coders; i++)
1881 {
1882 tmp_id = p_device_pool->p_device_queue->xcoders[device_type][i];
1883 p_device_context = ni_rsrc_get_device_context(device_type, tmp_id);
1884
1885 if (p_device_context &&
1886 0 == strcmp(p_device_context->p_device_info->dev_name, blk_name))
1887 {
1888 guid = p_device_context->p_device_info->module_id;
1889 ni_rsrc_free_device_context(p_device_context);
1890 break;
1891 }
1892
1893 ni_rsrc_free_device_context(p_device_context);
1894 }
1895
1896#ifdef _WIN32
1897 ReleaseMutex(p_device_pool->lock);
1898#elif __linux__ || __APPLE__
1899 lockf(p_device_pool->lock, F_ULOCK, 0);
1900#endif
1901
1902 ni_rsrc_free_device_pool(p_device_pool);
1903
1904 ni_log(NI_LOG_DEBUG, "%s %s got guid: %d\n", __FUNCTION__, blk_name, guid);
1905
1906 return guid;
1907}
1908
1909/*!*****************************************************************************
1910* \brief Update the load value and s/w instances info of a specific decoder or
1911* encoder. This is used by resource management daemon to update periodically.
1912*
1913* \param[in] p_ctxt The device context returned by ni_rsrc_get_device_context
1914* \param[in] p_load The latest load value to update
1915* \param[in] sw_instance_cnt Number of s/w instances
1916* \param[in] sw_instance_info Info of s/w instances
1917*
1918* \return
1919* NI_RETCODE_SUCCESS
1920* NI_RETCODE_FAILURE
1921*******************************************************************************/
1922int ni_rsrc_update_device_load(ni_device_context_t *p_device_context, int load,
1923 int sw_instance_cnt, const ni_sw_instance_info_t sw_instance_info[])
1924{
1925 int i;
1926 if (!p_device_context || !sw_instance_info)
1927 {
1928 ni_log(NI_LOG_ERROR, "ERROR: %s() invalid input pointers\n", __func__);
1929 return NI_RETCODE_FAILURE;
1930 }
1931
1932#ifdef _WIN32
1933 if (WAIT_ABANDONED == WaitForSingleObject(p_device_context->lock, INFINITE)) // no time-out interval) //we got the mutex
1934 {
1935 ni_log(NI_LOG_ERROR, "ERROR: %s() failed to obtain mutex: %p\n",
1936 __func__, p_device_context->lock);
1937 return NI_RETCODE_FAILURE;
1938 }
1939#elif __linux__ || __APPLE__
1940 lockf(p_device_context->lock, F_LOCK, 0);
1941#endif
1942
1943 p_device_context->p_device_info->load = load;
1944 p_device_context->p_device_info->active_num_inst = sw_instance_cnt;
1945 for (i = 0; i < sw_instance_cnt; i++)
1946 {
1947 p_device_context->p_device_info->sw_instance[i] = sw_instance_info[i];
1948 }
1949
1950#ifdef _WIN32
1951 ReleaseMutex(p_device_context->lock);
1952#elif __linux__ || __APPLE__
1953 lockf(p_device_context->lock, F_ULOCK, 0);
1954#endif
1955
1956 return NI_RETCODE_SUCCESS;
1957}
1958
1959/*!*****************************************************************************
1960* \brief Allocate resources for decoding/encoding, by designating explicitly
1961* the device to use. do not track the load on the host side
1962*
1963* \param[in] device_type NI_DEVICE_TYPE_DECODER or NI_DEVICE_TYPE_ENCODER
1964* \param[in] guid unique device (decoder or encoder) module id
1965* \return pointer to ni_device_context_t if found, NULL otherwise
1966*
1967* Note: only need to specify the device type and guid and codec type
1968*
1969*
1970* Note: the returned ni_device_context_t content is not supposed to be used by
1971* caller directly: should only be passed to API in the subsequent
1972* calls; also after its use, the context should be released by
1973* calling ni_rsrc_free_device_context.
1974*******************************************************************************/
1976(
1977 ni_device_type_t device_type,
1978 int guid
1979)
1980{
1981 ni_device_context_t *p_device_context = ni_rsrc_get_device_context(device_type, guid);
1982
1983 return p_device_context;
1984}
1985
1986
1987/*!*****************************************************************************
1988* \brief Release resources allocated for decoding/encoding.
1989* function This *must* be called at the end of transcoding
1990* with previously assigned load value by allocate* functions.
1991*
1992* \param[in/out] p_ctxt the device context
1993* \param[in] load the load value returned by allocate* functions
1994*
1995* \return None
1996*******************************************************************************/
1998 uint64_t load)
1999{
2000
2001#if 1
2002 (void) p_device_context;
2003 (void) load;
2004 return;
2005
2006#else
2007 if (!p_device_context)
2008 {
2009 ni_log(NI_LOG_ERROR, "ERROR: %s() invalid input pointers\n", __func__);
2010 return;
2011 }
2012
2013#ifdef _WIN32
2014 if (WAIT_ABANDONED == WaitForSingleObject(p_device_context->lock, INFINITE)) // no time-out interval) //we got the mutex
2015 {
2016 ni_log(NI_LOG_ERROR, "ERROR: %s() failed to obtain mutex: %p\n",
2017 __func__, p_device_context->lock);
2018 }
2019#elif __linux__ || __APPLE__
2020 lockf(p_device_context->lock, F_LOCK, 0);
2021#endif
2022
2023 if (p_device_context->p_device_info->xcode_load_pixel < load)
2024 {
2025 ni_log(NI_LOG_INFO, "Warning: releasing resource load %lu > current load %lu\n", load,
2026 p_device_context->p_device_info->xcode_load_pixel);
2027 }
2028 else
2029 {
2030 p_device_context->p_device_info->xcode_load_pixel -= load;
2031 // Remove as the value is getting from the FW
2032 // p_device_context->p_device_info->model_load = (int)((double)(p_device_context->p_device_info->xcode_load_pixel) * 100 / total_cap);
2033#if __linux__ || __APPLE__
2034 if (msync((void *)p_device_context->p_device_info, sizeof(ni_device_info_t), MS_SYNC | MS_INVALIDATE))
2035 {
2036 char errmsg[NI_ERRNO_LEN] = {0};
2038 ni_log(NI_LOG_ERROR, "ERROR %s() msync() p_device_context->"
2039 "p_device_info: %s\n", __func__, errmsg);
2040 }
2041#endif
2042 }
2043
2044#ifdef _WIN32
2045 ReleaseMutex(p_device_context->lock);
2046#elif __linux__ || __APPLE__
2047 lockf(p_device_context->lock, F_ULOCK, 0);
2048#endif
2049
2050#endif
2051}
2052
2053/*!*****************************************************************************
2054* \brief check the NetInt h/w device in resource pool on the host.
2055*
2056* \param[in] guid the global unique device index in resource pool
2057* device_type NI_DEVICE_TYPE_DECODER or NI_DEVICE_TYPE_ENCODER
2058*
2059* \return
2060* NI_RETCODE_SUCCESS
2061*******************************************************************************/
2063{
2064 ni_device_pool_t *p_device_pool = NULL;
2065 ni_device_context_t *p_device_ctx = NULL;
2066 ni_session_context_t *p_session_ctx = NULL;
2067 ni_xcoder_params_t *p_api_param = NULL;
2068 bool b_release_pool_mtx = false;
2070 int retry_cnt = 0;
2071
2072 if (guid < 0)
2073 {
2074 ni_log(NI_LOG_ERROR, "ERROR invalid guid:%d\n", guid);
2076 }
2077
2078 if (!IS_XCODER_DEVICE_TYPE(device_type))
2079 {
2080 ni_log(NI_LOG_ERROR, "ERROR: Unknown device type:%d\n", device_type);
2082 }
2083
2084 p_session_ctx = ni_device_session_context_alloc_init();
2085 p_api_param = (ni_xcoder_params_t *)calloc(1, sizeof(ni_xcoder_params_t));
2086 if (!p_session_ctx || !p_api_param)
2087 {
2089 LRETURN;
2090 }
2092 p_session_ctx->src_bit_depth = 8;
2093 p_session_ctx->hw_id = guid;
2094
2095 if (NI_DEVICE_TYPE_DECODER == device_type)
2096 {
2097 if (ni_decoder_init_default_params(p_api_param, 30, 1, NI_MIN_BITRATE,
2100 {
2101 ni_log(NI_LOG_ERROR, "ERROR: set decoder default params error\n");
2102 retval = NI_RETCODE_INVALID_PARAM;
2103 LRETURN;
2104 }
2105 } else if (NI_DEVICE_TYPE_ENCODER == device_type)
2106 {
2108 p_api_param, 30, 1, NI_MIN_BITRATE, XCODER_MIN_ENC_PIC_WIDTH,
2110 {
2111 ni_log(NI_LOG_ERROR, "ERROR: set encoder default params error\n");
2112 retval = NI_RETCODE_INVALID_PARAM;
2113 LRETURN;
2114 }
2115 } else if (NI_DEVICE_TYPE_SCALER == device_type)
2116 {
2117 p_session_ctx->device_type = NI_DEVICE_TYPE_SCALER;
2119 } else
2120 {
2121 p_session_ctx->device_type = NI_DEVICE_TYPE_AI;
2122 }
2123 p_session_ctx->p_session_config = p_api_param;
2124
2125 p_device_pool = ni_rsrc_get_device_pool();
2126 if (!p_device_pool)
2127 {
2128 ni_log(NI_LOG_ERROR, "ERROR: get device poll failed\n");
2130 LRETURN;
2131 }
2132
2133#ifdef _WIN32
2134 if (WAIT_ABANDONED ==
2135 WaitForSingleObject(p_device_pool->lock,
2136 INFINITE)) // no time-out interval)
2137 {
2139 "ERROR: ni_rsrc_list_devices() failed to obtain mutex: %p\n",
2140 p_device_pool->lock);
2141 retval = NI_RETCODE_FAILURE;
2142 LRETURN;
2143 }
2144#elif __linux__
2145 lockf(p_device_pool->lock, F_LOCK, 0);
2146#endif
2147 b_release_pool_mtx = true;
2148
2149 // get device context
2150 p_device_ctx = ni_rsrc_get_device_context(device_type, guid);
2151 if (p_device_ctx)
2152 {
2153 p_session_ctx->device_handle = ni_device_open2(
2155 p_session_ctx->blk_io_handle = p_session_ctx->device_handle;
2156 if (NI_INVALID_DEVICE_HANDLE == p_session_ctx->device_handle)
2157 {
2158 ni_log(NI_LOG_ERROR, "open device failed: %d\n", errno);
2160 } else
2161 {
2162#ifdef _WIN32
2163 p_session_ctx->event_handle = ni_create_event();
2164 if (NI_INVALID_EVENT_HANDLE == p_session_ctx->event_handle)
2165 {
2166 ni_log(NI_LOG_INFO, "Error create envent:%d\n", GetLastError());
2167 retval = NI_RETCODE_FAILURE;
2168 LRETURN;
2169 }
2170#endif
2171 retval = ni_device_session_query(p_session_ctx, device_type);
2172 if (NI_RETCODE_SUCCESS != retval)
2173 {
2175 "guid %d. %s is not avaiable, type: %d, retval:%d\n",
2176 guid, p_device_ctx->p_device_info->dev_name,
2177 device_type, retval);
2178 retval = NI_RETCODE_FAILURE;
2179 } else
2180 {
2181 while (1)
2182 {
2183 retry_cnt++;
2184 retval = ni_device_session_open(p_session_ctx, device_type);
2185 ni_device_session_close(p_session_ctx, 0, device_type);
2186 if (retval == NI_RETCODE_SUCCESS)
2187 {
2188 ni_log(NI_LOG_INFO, "guid %d. %s is avaiable\n",
2189 guid, p_device_ctx->p_device_info->dev_name);
2190 break;
2191 } else if (
2192 retry_cnt < 10 &&
2193 retval ==
2194 NI_RETCODE_ERROR_VPU_RECOVERY) // max 2 seconds
2195 {
2197 "vpu recovery happened on guid %d. %s, retry "
2198 "cnt:%d\n",
2199 guid, p_device_ctx->p_device_info->dev_name,
2200 retry_cnt);
2201#ifndef _WIN32
2202 ni_usleep(200000); // 200 ms
2203#endif
2204 continue;
2205 } else
2206 {
2208 "session open error guid %d. %s, type: %d, "
2209 "retval:%d\n",
2210 guid, p_device_ctx->p_device_info->dev_name,
2211 device_type, retval);
2212 retval = NI_RETCODE_FAILURE;
2213 break;
2214 }
2215 }
2216 }
2217 }
2218 } else
2219 {
2221 "Error get device resource: guid %d, device_ctx %p\n", guid,
2222 p_device_ctx);
2223 retval = NI_RETCODE_FAILURE;
2224 }
2225
2226END:
2227
2228 if (b_release_pool_mtx)
2229 {
2230#ifdef _WIN32
2231 ReleaseMutex(p_device_pool->lock);
2232#elif __linux__
2233 lockf(p_device_pool->lock, F_ULOCK, 0);
2234#endif
2235 }
2236
2237 if (p_session_ctx)
2238 {
2239 ni_close_event(p_session_ctx->event_handle);
2240 ni_device_close(p_session_ctx->device_handle);
2241 }
2242
2243 ni_rsrc_free_device_context(p_device_ctx);
2244 ni_device_session_context_free(p_session_ctx);
2245 free(p_api_param);
2246 ni_rsrc_free_device_pool(p_device_pool);
2247
2248 return retval;
2249}
2250
2251/*!*****************************************************************************
2252* \brief Remove an NetInt h/w device from resource pool on the host.
2253*
2254* \param[in] p_dev the NVMe device name
2255*
2256* \return
2257* NI_RETCODE_SUCCESS
2258* NI_RETCODE_FAILURE
2259*******************************************************************************/
2260int ni_rsrc_remove_device(const char* dev)
2261{
2262#if __linux__ || __APPLE__
2263 char lck_name[32];
2264#endif
2265 int return_value = NI_RETCODE_SUCCESS;
2266 int32_t guid;
2267 int32_t guids[NI_MAX_DEVICE_CNT];
2268 unsigned int guid_index_i, guid_index_j, ui_device_type;
2269#ifdef _WIN32
2270 DWORD rValue;
2271#endif
2272 ni_device_context_t *p_device_context;
2273 ni_device_pool_t *p_device_pool = NULL;
2274 ni_device_queue_t *p_device_queue;
2275 ni_device_type_t device_type;
2276 char errmsg[NI_ERRNO_LEN] = {0};
2277
2278 if (!dev)
2279 {
2280 ni_log(NI_LOG_ERROR, "ERROR: %s() dev is NULL\n", __FUNCTION__);
2281 return_value = NI_RETCODE_INVALID_PARAM;
2282 LRETURN;
2283 }
2284
2285 p_device_pool = ni_rsrc_get_device_pool();
2286 if (!p_device_pool)
2287 {
2288 return_value = NI_RETCODE_FAILURE;
2289 LRETURN;
2290 }
2291
2292#ifdef _WIN32
2293 rValue = WaitForSingleObject(p_device_pool->lock, INFINITE);
2294 if (rValue != WAIT_OBJECT_0)
2295 {
2297 "ERROR: %s() Failed to obtain mutex %p\n",
2298 __FUNCTION__,
2299 p_device_pool->lock);
2300 return_value = NI_RETCODE_FAILURE;
2301 LRETURN;
2302 }
2303#elif __linux__ || __APPLE__
2304 lockf(p_device_pool->lock, F_LOCK, 0);
2305#endif
2306
2307 p_device_queue = p_device_pool->p_device_queue;
2308 for (guid_index_i = 0; guid_index_i < NI_MAX_DEVICE_CNT; guid_index_i++)
2309 {
2310 for (ui_device_type = NI_DEVICE_TYPE_DECODER;
2311 ui_device_type < NI_DEVICE_TYPE_XCODER_MAX;
2312 ui_device_type++)
2313 {
2314 guid = p_device_queue->xcoders[ui_device_type][guid_index_i];
2315 if (guid == -1)
2316 {
2317 continue;
2318 }
2319 device_type = (ni_device_type_t)ui_device_type;
2320 p_device_context = ni_rsrc_get_device_context(device_type, guid);
2321 if (!p_device_context)
2322 {
2324 "ERROR: %s() Failed to obtain device context for "
2325 "%s with GUID %u! Undefined behavior!\n",
2326 __func__,
2327 GET_XCODER_DEVICE_TYPE_STR(device_type),
2328 guid);
2329 return_value = NI_RETCODE_FAILURE;
2330 continue;
2331 }
2332
2333 if (strncmp(dev,
2334 p_device_context->p_device_info->dev_name,
2336 {
2337 if (strncmp(dev, p_device_context->p_device_info->dev_name, strlen(dev)) == 0)
2338 {
2340 "ERROR: %s() Devicename format mismatch %s %s\n",
2341 __func__,dev,p_device_context->p_device_info->dev_name);
2342 return_value = NI_RETCODE_FAILURE;
2343 }
2344 continue;
2345 }
2346
2347#ifdef _WIN32
2348 CloseHandle(p_device_context->lock);
2349#elif __linux__ || __APPLE__
2350 if (!ni_rsrc_remove_shm(p_device_context->shm_name, sizeof(ni_device_info_t)))
2351 {
2353 "%s %s %s deleted\n",
2354 dev,
2355 GET_XCODER_DEVICE_TYPE_STR(device_type),
2356 p_device_context->shm_name);
2357 }
2358 else
2359 {
2362 "ERROR: %s(): %s %s %s failed to delete %s\n",
2363 __FUNCTION__,
2364 dev,
2365 GET_XCODER_DEVICE_TYPE_STR(device_type),
2366 p_device_context->shm_name,
2367 errmsg);
2368 return_value = NI_RETCODE_FAILURE;
2369 }
2370#endif
2371
2372 ni_rsrc_free_device_context(p_device_context);
2373
2374#if __linux__ || __APPLE__
2375 ni_rsrc_get_lock_name(device_type, guid, lck_name, 32);
2376 if (!unlink(lck_name))
2377 {
2379 "%s %s %s deleted\n",
2380 dev,
2381 GET_XCODER_DEVICE_TYPE_STR(device_type),
2382 lck_name);
2383 }
2384 else
2385 {
2388 "ERROR: %s(): %s %s %s failed to delete %s\n",
2389 __FUNCTION__,
2390 dev,
2391 GET_XCODER_DEVICE_TYPE_STR(device_type),
2392 lck_name,
2393 errmsg);
2394 return_value = NI_RETCODE_FAILURE;
2395 }
2396#endif
2397
2398 if (return_value != NI_RETCODE_SUCCESS)
2399 {
2400 continue;
2401 }
2402
2403 p_device_queue->xcoders[ui_device_type][guid_index_i] = -1;
2404 p_device_queue->xcoder_cnt[ui_device_type]--;
2405 }
2406 }
2407
2408 // Take p_device_queue->xcoder_cnt[ui_device_type] to contain the value 2.
2409 // p_device_queue->xcoders[ui_device_type] could be [0, -1, 2, ...]
2410 // p_device_queue->xcoders[ui_device_type] should be [0, 2, -1, ...]
2411 for (ui_device_type = NI_DEVICE_TYPE_DECODER;
2412 ui_device_type < NI_DEVICE_TYPE_XCODER_MAX;
2413 ui_device_type++)
2414 {
2415 memset(guids, -1, sizeof(guids));
2416 guid_index_j = 0;
2417 for (guid_index_i = 0; guid_index_i < NI_MAX_DEVICE_CNT; guid_index_i++)
2418 {
2419 guid = p_device_queue->xcoders[ui_device_type][guid_index_i];
2420 if (guid != -1)
2421 {
2422 guids[guid_index_j] = guid;
2423 guid_index_j++;
2424 if (guid_index_j == p_device_queue->xcoder_cnt[ui_device_type])
2425 {
2426 break;
2427 }
2428 }
2429 }
2430 memcpy(p_device_queue->xcoders[ui_device_type], guids, sizeof(guids));
2431 }
2432
2433#if __linux__ || __APPLE__
2434#ifndef _ANDROID
2435 if (!msync((void *)p_device_queue,
2436 sizeof(ni_device_queue_t),
2437 MS_SYNC|MS_INVALIDATE))
2438 {
2439 ni_log(NI_LOG_INFO, "%s deleted\n", dev);
2440 }
2441 else
2442 {
2445 "ERROR: %s(): msync() failed to delete %s: %s\n",
2446 __FUNCTION__,
2447 dev,
2448 errmsg);
2449 return_value = NI_RETCODE_FAILURE;
2450 }
2451#endif
2452#endif
2453
2454#ifdef _WIN32
2455 ReleaseMutex(p_device_pool->lock);
2456#elif __linux__ || __APPLE__
2457 lockf(p_device_pool->lock, F_ULOCK, 0);
2458#endif
2459
2460end:
2461 ni_rsrc_free_device_pool(p_device_pool);
2462
2463 return return_value;
2464}
2465
2466/*!*****************************************************************************
2467* \brief Remove all NetInt h/w devices from resource pool on the host.
2468*
2469* \param none
2470*
2471* \return
2472* NI_RETCODE_SUCCESS
2473* NI_RETCODE_FAILURE
2474*******************************************************************************/
2476{
2477 char xcoder_dev_names[NI_MAX_DEVICE_CNT][NI_MAX_DEVICE_NAME_LEN] = {0};
2478 int xcoder_dev_count = 0;
2479 int i = 0;
2480 ni_device_t *saved_coders = NULL;
2481 saved_coders = (ni_device_t *)malloc(sizeof(ni_device_t));
2482 if (!saved_coders)
2483 {
2484 char errmsg[NI_ERRNO_LEN] = {0};
2486 ni_log(NI_LOG_ERROR, "ERROR %s() failed to malloc memory: %s\n",
2487 __func__, errmsg);
2488 return NI_RETCODE_FAILURE;
2489 }
2490 memset(saved_coders, 0, sizeof(ni_device_t));
2491
2492 // retrieve saved info from resource pool at start up
2493 if (NI_RETCODE_SUCCESS ==
2496 saved_coders->xcoders[NI_DEVICE_TYPE_ENCODER],
2497 &(saved_coders->xcoder_cnt[NI_DEVICE_TYPE_ENCODER])))
2498 {
2499 for (i = 0; i < saved_coders->xcoder_cnt[NI_DEVICE_TYPE_ENCODER];
2500 i++)
2501 {
2502 ni_strcpy(xcoder_dev_names[i], NI_MAX_DEVICE_NAME_LEN,
2503 saved_coders->xcoders[NI_DEVICE_TYPE_ENCODER][i]
2504 .dev_name);
2505 ni_log(NI_LOG_INFO, "device %d %s retrieved\n", i,
2506 xcoder_dev_names[i]);
2507 }
2508 xcoder_dev_count =
2509 saved_coders->xcoder_cnt[NI_DEVICE_TYPE_ENCODER];
2510#ifdef XCODER_311
2512 "%d devices retrieved from current pool at start up\n",
2513 xcoder_dev_count);
2514#else
2516 "%d devices retrieved from current pool at start up\n",
2517 xcoder_dev_count);
2518#endif
2519 } else
2520 {
2521 ni_log(NI_LOG_ERROR, "Error retrieving from current pool at start "
2522 "up\n");
2523 }
2524 free(saved_coders);
2525
2526 // remove from resource pool all devices
2527 for (i = 0; i < xcoder_dev_count; i++)
2528 {
2529 ni_log(NI_LOG_INFO, "removing device %d %s !\n", i,
2530 xcoder_dev_names[i]);
2531 if (NI_RETCODE_SUCCESS ==
2532 ni_rsrc_remove_device(xcoder_dev_names[i]))
2533 {
2534 ni_log(NI_LOG_INFO, "%s deleted successfully !\n",
2535 xcoder_dev_names[i]);
2536 } else
2537 {
2538 ni_log(NI_LOG_ERROR, "%s failed to delete !\n",
2539 xcoder_dev_names[i]);
2540 }
2541 }
2542
2543#if __linux__ || __APPLE__
2544 if (!ni_rsrc_remove_shm(CODERS_SHM_NAME, sizeof(ni_device_queue_t)))
2545 {
2546 ni_log(NI_LOG_INFO, "%s deleted.\n", CODERS_SHM_NAME);
2547 }
2548 else
2549 {
2550 ni_log(NI_LOG_ERROR, "%s failed to delete !\n", CODERS_SHM_NAME);
2551 }
2552
2553 for (i = 0; i < NI_DEVICE_TYPE_XCODER_MAX; i++)
2554 {
2555 if (0 == unlink(XCODERS_RETRY_LCK_NAME[i]))
2556 {
2557 ni_log(NI_LOG_INFO, "%d %s deleted.\n",
2558 i, XCODERS_RETRY_LCK_NAME[i]);
2559 }
2560 else
2561 {
2562 ni_log(NI_LOG_ERROR, "%d %s failed to delete !\n",
2563 i, XCODERS_RETRY_LCK_NAME[i]);
2564 }
2565 }
2566
2567 if (0 == unlink(CODERS_LCK_NAME))
2568 {
2569 ni_log(NI_LOG_INFO, "%s deleted.\n", CODERS_LCK_NAME);
2570 }
2571 else
2572 {
2573 ni_log(NI_LOG_ERROR, "%s failed to delete !\n", CODERS_LCK_NAME);
2574 }
2575#endif
2576
2577 return NI_RETCODE_SUCCESS;
2578}
2579
2580/*!*****************************************************************************
2581* \brief Add an NetInt h/w device into resource pool on the host.
2582*
2583* \param[in] p_dev Device name represented as C string. ex "/dev/nvme0"
2584* \param[in] should_match_rev 0: transcoder firmware revision matching the
2585* library's version is NOT required for placing
2586* the transcoder into resource pool; 1: otherwise
2587*
2588* \return
2589* NI_RETCODE_SUCCESS
2590* NI_RETCODE_INVALID_PARAM
2591* NI_RETCODE_FAILURE
2592*******************************************************************************/
2593int ni_rsrc_add_device(const char* dev, int should_match_rev)
2594{
2595 uint32_t i, existing_number_of_devices;
2596
2597 ni_device_type_t device_type;
2598 ni_device_context_t *device_context;
2599 ni_device_pool_t *device_pool;
2600 ni_device_queue_t *device_queue;
2601 ni_retcode_t retcode;
2602
2603 if (!dev)
2604 {
2605 ni_log(NI_LOG_ERROR, "ERROR: %s(): dev is NULL\n", __FUNCTION__);
2607 }
2608
2609 device_pool = ni_rsrc_get_device_pool();
2610 if (!device_pool)
2611 {
2612 return NI_RETCODE_SUCCESS;
2613 }
2614
2615#ifdef _WIN32
2616 if (WAIT_ABANDONED == WaitForSingleObject(device_pool->lock, INFINITE))
2617 {
2619 "ERROR: %s(): Failed to obtain lock %p\n",
2620 __FUNCTION__,
2621 device_pool->lock);
2622 return NI_RETCODE_FAILURE;
2623 }
2624#elif __linux__ || __APPLE__
2625 lockf(device_pool->lock, F_LOCK, 0);
2626#endif
2627
2628 retcode = NI_RETCODE_SUCCESS;
2629
2630 device_type = NI_DEVICE_TYPE_ENCODER;
2631 device_queue = device_pool->p_device_queue;
2632 existing_number_of_devices = device_queue->xcoder_cnt[device_type];
2633
2634 if (existing_number_of_devices == NI_MAX_DEVICE_CNT)
2635 {
2637 "ERROR: %s(): Limit of NI_MAX_DEVICE_CNT(%d) existing Quadra "
2638 "devices previously reached. Not adding %s.\n",
2639 __FUNCTION__,
2641 dev);
2642 retcode = NI_RETCODE_FAILURE;
2643 LRETURN;
2644 }
2645
2646 for (i = 0; i < existing_number_of_devices; i++)
2647 {
2648 device_context =
2649 ni_rsrc_get_device_context(device_type,
2650 device_queue->xcoders[device_type][i]);
2651 if (device_context && !strncmp(device_context->p_device_info->dev_name,
2652 dev,
2654 {
2655 retcode = NI_RETCODE_FAILURE;
2657 "ERROR: %s(): %s already exists in resource pool\n",
2658 __FUNCTION__,
2659 dev);
2660 ni_rsrc_free_device_context(device_context);
2661 LRETURN;
2662 }
2663 ni_rsrc_free_device_context(device_context);
2664 }
2665
2666 if (!add_to_shared_memory(dev,
2667 true,
2668 should_match_rev,
2669 device_queue))
2670 {
2671 retcode = NI_RETCODE_FAILURE;
2672 }
2673
2674end:
2675#ifdef _WIN32
2676 ReleaseMutex(device_pool->lock);
2677#elif __linux__ || __APPLE__
2678 lockf(device_pool->lock, F_ULOCK, 0);
2679#endif
2680 ni_rsrc_free_device_pool(device_pool);
2681 return retcode;
2682}
2683
2684/*!*****************************************************************************
2685* \brief Free all resources taken by the device pool
2686*
2687* \param[in] p_device_pool Poiner to a device pool struct
2688*
2689* \return None
2690*******************************************************************************/
2692{
2693 if (p_device_pool)
2694 {
2695 if (NI_INVALID_LOCK_HANDLE != p_device_pool->lock)
2696 {
2697#ifdef _WIN32
2698 CloseHandle(p_device_pool->lock);
2699#elif __linux__ || __APPLE__
2700 close(p_device_pool->lock);
2701#endif
2702 }
2703#ifdef _WIN32
2704 UnmapViewOfFile(p_device_pool->p_device_queue);
2705#else
2706 ni_rsrc_munmap_shm((void *)p_device_pool->p_device_queue, sizeof(ni_device_queue_t));
2707 ni_log(NI_LOG_DEBUG, "in %s do munmap for %s\n", __func__, CODERS_SHM_NAME);
2708#endif
2709
2710 free(p_device_pool);
2711 }
2712}
2713
2714/*!*****************************************************************************
2715 * \brief lock a file lock and open a session on a device
2716 *
2717 * \param device_type
2718 * \param lock
2719 *
2720 * \return None
2721 *******************************************************************************/
2722int ni_rsrc_lock_and_open(int device_type, ni_lock_handle_t* lock)
2723{
2724
2725 int count = 0;
2727 char errmsg[NI_ERRNO_LEN] = {0};
2728#ifdef _WIN32
2729 *lock = CreateMutexA(NULL, FALSE, XCODERS_RETRY_LCK_NAME[device_type]);
2730
2731 if (NULL == *lock)
2732 {
2734 ni_log(NI_LOG_ERROR, "ERROR: %s() CreateMutex() %s failed: %s\n",
2735 __func__, XCODERS_RETRY_LCK_NAME[device_type],
2736 errmsg);
2738 }
2739#else
2740 do
2741 {
2742 // the retry lock files should be created in ni_rsrc_init
2743 *lock =
2744 open(XCODERS_RETRY_LCK_NAME[device_type], O_RDWR | O_CLOEXEC);
2745
2746 if (*lock < 0)
2747 {
2749 ni_log(NI_LOG_ERROR, "Can not lock down the file lock. Error: %s\n", errmsg);
2751 }
2752 }
2753 while (0);
2754#endif
2755 // Now the lock is free so we lock it down
2756 count = 0;
2757 do
2758 {
2759 //sleep 10ms if the file lock is locked by other FFmpeg process
2760 if (count>=1)
2761 {
2762 //sleep 10ms if the file lock is locked by other FFmpeg process
2764 }
2765#ifdef _WIN32
2766 DWORD ret = WaitForSingleObject(*lock, 1); // time-out 1ms
2767 if (WAIT_OBJECT_0 == ret)
2768 {
2769 status = NI_RETCODE_SUCCESS;
2770 } else if (WAIT_TIMEOUT != ret)
2771 {
2773 ni_log(NI_LOG_ERROR, "ERROR: %s() failed to obtain mutex: %s\n",
2774 __func__, errmsg);
2775 }
2776#else
2777 status = lockf(*lock, F_LOCK, 0);
2778#endif
2779 if (status != 0)
2780 {
2781 count++;
2782 if (count > MAX_LOCK_RETRY)
2783 {
2784 ni_log(NI_LOG_ERROR, "Can not put down the lock after 6s");
2785#ifdef _WIN32
2786 CloseHandle(*lock);
2787#else
2788 close(*lock);
2789#endif
2791 }
2792 }
2793 }
2794 while (status != 0);
2795
2796 return NI_RETCODE_SUCCESS;
2797}
2798
2799/*!*****************************************************************************
2800 * \brief unlock a file lock
2801 *
2802 * \param device_type
2803 * \param lock
2804 *
2805 * \return None
2806 *******************************************************************************/
2807int ni_rsrc_unlock(int device_type, ni_lock_handle_t lock)
2808{
2809 (void)device_type;
2810 if (lock == NI_INVALID_LOCK_HANDLE)
2811 {
2812 return NI_RETCODE_FAILURE;
2813 }
2814
2815 int count = 0;
2816 bool unlocked = false;
2817 do
2818 {
2819 if (count >= 1)
2820 {
2822 }
2823#ifdef _WIN32
2824 unlocked = (ReleaseMutex(lock) != 0);
2825#else
2826 unlocked = (lockf(lock, F_ULOCK, 0) == 0);
2827#endif
2828 count++;
2829 if (count > MAX_LOCK_RETRY)
2830 {
2831 ni_log(NI_LOG_ERROR, "Can not unlock the lock after 6s");
2832#ifdef _WIN32
2833 CloseHandle(lock);
2834#else
2835 close(lock);
2836#endif
2838 }
2839 } while (!unlocked);
2840
2841#ifdef _WIN32
2842 CloseHandle(lock);
2843#else
2844 close(lock);
2845#endif //_WIN32 defined
2846 return NI_RETCODE_SUCCESS;
2847}
2848
2849/*!*****************************************************************************
2850* \brief check if device FW revision is compatible with SW API
2851*
2852* \param fw_rev
2853*
2854* \return 1 for full compatibility, 2 for partial, 0 for none
2855*******************************************************************************/
2856int ni_rsrc_is_fw_compat(uint8_t fw_rev[8])
2857{
2858 if ((uint8_t)fw_rev[NI_XCODER_REVISION_API_MAJOR_VER_IDX] ==
2862 } else {
2863 return 0;
2864 }
2865}
2866
2867
2868/*!******************************************************************************
2869 * \brief get linux numa_node
2870 *
2871 * \param[in] char *device_name
2872 *
2873 * \return int atoi(cmd_ret)
2874 *******************************************************************************/
2875int ni_rsrc_get_numa_node(char *device_name)
2876{
2877#ifndef __linux__
2878 return -1;
2879#else
2880 int ret = -1;
2881 FILE *cmd_fp;
2882 char *ptr = NULL;
2883 char cmd[128] = {0};
2884 char cmd_ret[64] = {0};
2885
2886 if(!device_name)
2887 {
2888 return ret;
2889 }
2890 ptr = device_name + 5;
2891 (void)snprintf(cmd, sizeof(cmd) - 1, "cat /sys/block/%s/device/*/numa_node",ptr);
2892 cmd_fp = popen(cmd, "r"); // NOLINT(cert-env33-c) - constant command string, required for device detection
2893 if (!cmd_fp)
2894 {
2895 return ret;
2896 }
2897 if (fgets(cmd_ret, sizeof(cmd_ret)/sizeof(cmd_ret[0]), cmd_fp) == NULL)
2898 {
2899 goto get_numa_node_ret;
2900 }
2901 {
2902 int32_t tmp_numa;
2903 if (ni_strtoi(cmd_ret, &tmp_numa) != NI_RETCODE_SUCCESS)
2904 {
2905 ni_log(NI_LOG_ERROR, "%s: invalid numa node value '%s'\n",
2906 __func__, cmd_ret);
2907 goto get_numa_node_ret;
2908 }
2909 ret = (int)tmp_numa;
2910 }
2911
2912get_numa_node_ret:
2913 pclose(cmd_fp);
2914 return ret;
2915#endif
2916}
2917
2918namespace {
2919int int_cmp(const void *a, const void *b)
2920{
2921 const int *ia = (const int *)a;
2922 const int *ib = (const int *)b;
2923 return (*ia == *ib) ? 0 : ((*ia > *ib) ? 1 : -1);
2924 /* integer comparison: returns negative if b > a , 0 if a == b,and positive if a > b */
2925}
2926
2927int ni_hw_device_info_quadra_threshold_param_t_compare(const void *pl, const void *pr)
2928{
2931 if(!ll || !rr)
2932 {
2933 return 0;
2934 }
2935 return (ll->device_type == rr->device_type) ? 0 : ((ll->device_type > rr->device_type) ? 1 : -1);
2936}
2937
2938
2939/*!*********************************************************************************************
2940* \brief Calculate decoder load used in ni_check_hw_info()
2941* The computing method is from firmware for 770.
2942* This function is used for ni_check_hw_info()
2943*
2944* \param decoder_param
2945*
2946* \return task decoder load
2947***********************************************************************************************/
2948int check_hw_info_decoder_need_load(ni_hw_device_info_quadra_decoder_param_t *decoder_param)
2949{
2950 int factor_8_10 = 1;
2951 const uint32_t resolution = decoder_param->h * decoder_param->w;
2952 if(decoder_param->bit_8_10 == 10)
2953 {
2954 factor_8_10 = 2;
2955 }
2956 return resolution >= 1920*1080 ?
2957 (int)(((uint64_t)(resolution)*(uint64_t)(decoder_param->fps)*(uint64_t)(factor_8_10)*100)/1440/1920/1080) :
2958 (int)((uint64_t)(resolution)*(uint64_t)(decoder_param->fps)*(uint64_t)(factor_8_10)*100/2880/1280/720);
2959}
2960
2961/*!**************************************************************************************
2962* \brief Calculate encoder load used in ni_check_hw_info()
2963* The computing method is from firmware->ModelLoadSet
2964* This function is used for ni_check_hw_info()
2965*
2966* \param encoder_param
2967*
2968* \return task encoder load
2969****************************************************************************************/
2970int check_hw_info_encoder_need_load(ni_hw_device_info_quadra_encoder_param_t *encoder_param)
2971{
2972 double factor = 1.0;
2973 double factor_codec = 1.0;
2974 double factor_rdoq = 1.0;
2975 double factor_rdoLevel = 1.0;
2976 double factor_lookahead = 1.0;
2977 double factor_8_10_bit = 1.0;
2978 double factor_720p = 1.0;
2979
2980 const int resolution = (int)(encoder_param->w * encoder_param->h);
2981
2982
2983 if(encoder_param->code_format == 3)//STD_JPGE
2984 {
2985 factor_codec = 0.67;
2986 }
2987 else{
2988 if((encoder_param->code_format == 0 || encoder_param->code_format == 1) &&
2989 encoder_param->ui8enableRdoQuant)//264 or 265
2990 {
2991 factor_rdoq = 1.32;
2992 }
2993
2994 if((encoder_param->code_format == 1 || encoder_param->code_format ==2) &&
2995 encoder_param->rdoLevel > 1)
2996 {
2997 factor_rdoLevel = (encoder_param->rdoLevel == 2) ? 1.91 : 3.28;
2998 }
2999
3000 if(encoder_param->lookaheadDepth != 0)
3001 {
3002 factor_lookahead = (double)(encoder_param->lookaheadDepth * 0.0014 + 1.012);
3003 }
3004 }
3005
3006 if(encoder_param->bit_8_10 == 10)
3007 {
3008 factor_8_10_bit = 2;
3009 }
3010
3011 factor_720p = 1.125;//consider h and w
3012 factor = factor_codec * factor_8_10_bit * factor_rdoq * factor_rdoLevel
3013 * factor_lookahead * factor_720p;
3014
3015 //ENC_TOTAL_BIT_VOLUME_1_SEC (3840 * 2160 * 60ULL)
3016 //PERF_MODEL_LOAD_PERCENT = ((ENC_TOTAL_BIT_VOLUME_1_SEC / 100) * ENCODER_MULTICORE_NUM)
3017 //encoedr_need_load = sample_model_load/PERF_MODEL_LOAD_PERCENT
3018 return (int)(
3019 ((uint32_t)((uint32_t)factor*encoder_param->fps * resolution)) /
3020 ((3840ULL * 2160 * 60) / 100 * 4));
3021}
3022
3023/*!*****************************************************************************
3024* \brief Calculate shared memeory uasge buffer scale
3025* The computing method is from MemUsageCalculation_SR
3026* This function is used for ni_check_hw_info()
3027*
3028* \param h
3029* \param w
3030* \param bit_8_10
3031* \param rgba
3032*
3033* \return task shared memeory uasge buffer scale
3034********************************************************************************/
3035int check_hw_info_shared_mem_calculate_b_scale(int h,int w,int bit_8_10,int rgba)
3036{
3037 const int stride = 128;
3038 const int estimated_yuv_size = rgba ?
3039 w * h * 4 :
3040 bit_8_10 == 8 ?
3041 ( ((w + stride - 1)/stride)*stride + ((w/2 + stride - 1)/stride)*stride ) * h:
3042 ( ((w * 2 + stride - 1)/stride)*stride + ((w + stride - 1)/stride)*stride ) * h;
3043 const int b_unit = 1601536;//Bin_Unit_Size
3044 const int b_scale = (estimated_yuv_size + b_unit -1) / b_unit;
3045 return b_scale;
3046}
3047
3048/*!*****************************************************************************
3049* \brief Calculate encoder shared memory usage
3050* The computing method is from MemUsageCalculation_SR
3051* This function is used for ni_check_hw_info()
3052*
3053* \param encoder_param
3054*
3055* \return task encoder shared memeory uasge
3056********************************************************************************/
3057int check_hw_info_encoder_shared_mem_usage(const ni_hw_device_info_quadra_encoder_param_t *encoder_param)
3058{
3059 // const int p_1080 = 2073600;
3060 // const int p_1440 = 3686400;
3061 // const int p_4k = 8294400;
3062
3063 if(!encoder_param)
3064 {
3065 return 0;
3066 }
3067
3068 //cppcheck do not allow this
3069 // const int v32_ofCores = 0;
3070
3071 // int encoder_shared_mem_usage = 0;
3072
3073 // int v32_ofCores_calculate = ((v32_ofCores>0)?v32_ofCores:1)-1;
3074 //cppcheck do not allow this
3075
3076 const int v32_ofCores_calculate = 0;
3077
3078 const int b_counts = (int)(v32_ofCores_calculate +
3079 ((encoder_param->lookaheadDepth > 0) ? encoder_param->lookaheadDepth + 8/2 + v32_ofCores_calculate : 0 )+
3080 8 +
3081 (encoder_param->uploader ? 1 : 0) * 3 +
3082 1) * 1;
3083 const int b_scale = check_hw_info_shared_mem_calculate_b_scale((int)encoder_param->h, (int)encoder_param->w,
3084 (int)encoder_param->bit_8_10, (int)encoder_param->rgba);
3085 return b_scale * b_counts;
3086
3087}
3088
3089/*!*****************************************************************************
3090* \brief Calculate decoder shared memory usage
3091* The computing method is from MemUsageCalculation_SR
3092* This function is used for ni_check_hw_info()
3093*
3094* \param decoder_param
3095* \param estimated_max_dpb
3096*
3097* \return task decoder shared memeory uasge
3098********************************************************************************/
3099int check_hw_info_decoder_shared_mem_usage(const ni_hw_device_info_quadra_decoder_param_t *decoder_param,int estimated_max_dpb)
3100{
3101 // const int p_1080 = 2073600;
3102 // const int p_1440 = 3686400;
3103 // const int p_4k = 8294400;
3104
3105 if(!decoder_param)
3106 {
3107 return 0;
3108 }
3109 const int hw_frame = decoder_param->hw_frame;
3110
3111 const int v30_xlsx = 0;
3112 const int b_counts = 1 * (v30_xlsx +
3113 (hw_frame ? 0 : 1)*3 +
3114 estimated_max_dpb);
3115 const int b_scale = check_hw_info_shared_mem_calculate_b_scale((int)decoder_param->h, (int)decoder_param->w,
3116 (int)decoder_param->bit_8_10, (int)decoder_param->rgba);
3117 return b_scale * b_counts;
3118}
3119
3120/*!*****************************************************************************
3121* \brief Calculate scaler shared memory usage
3122* The computing method is from MemUsageCalculation_SR
3123* This function is used for ni_check_hw_info()
3124*
3125* \param scaler_param
3126* \param estimated_max_dpb
3127*
3128* \return task scaler shared memeory uasge
3129********************************************************************************/
3130int check_hw_info_scaler_shared_mem_usage(const ni_hw_device_info_quadra_scaler_param_t *scaler_param,int estimated_max_dpb)
3131{
3132 // const int p_1080 = 2073600;
3133 // const int p_1440 = 3686400;
3134 // const int p_4k = 8294400;
3135
3136
3137 if(!scaler_param)
3138 {
3139 return 0;
3140 }
3141 // const int hw_frame = 1;
3142 //cppcheck do not allow this
3143
3144 const int v30_xlsx = 0;
3145 const int b_counts = 1 * (v30_xlsx +
3146 0/* (hw_frame ? 0 : 1)*3 */ +
3147 estimated_max_dpb);
3148 const int b_scale = check_hw_info_shared_mem_calculate_b_scale((int)scaler_param->h, (int)scaler_param->w,
3149 (int)scaler_param->bit_8_10, (int)scaler_param->rgba);
3150 return b_scale * b_counts;
3151}
3152
3153
3154/*!*************************************************************************************************
3155* \brief Remove unsupported card in ni_check_hw_info() by memroy
3156* This function is used for ni_check_hw_info()
3157*
3158* \param[in] card_remove
3159* \param[in] ni_card_info
3160* \param[in] card_num
3161* \param[in] coder_param
3162* \param[in] mode mode == 0->decoder, mode == 1->encoder, mode == 2->scaler, mode > 3->all
3163*
3164* \return NONE
3165****************************************************************************************************/
3166void check_hw_info_remove_card_with_memory(int *card_remove, const ni_hw_device_info_quadra_t *ni_card_info, int card_num, const ni_hw_device_info_quadra_coder_param_t *coder_param,int mode)
3167{
3168 const int total = 2456;//buffer count summary
3169 int task_mem_usage = 0;
3170 int task_mem_precentage = 0;
3171 int i;
3172
3173 if(!ni_card_info)
3174 {
3175 ni_log(NI_LOG_ERROR, "card_info is NULL mark all cards as removed\n");
3176 for(i = 0; i < card_num; ++i)
3177 {
3178 card_remove[i] = 1;
3179 }
3180 return;
3181 }
3182
3183 if(mode == 0)
3184 {
3185 task_mem_usage = check_hw_info_decoder_shared_mem_usage(coder_param->decoder_param,16);
3186 }
3187 else if(mode == 1)
3188 {
3189 task_mem_usage = check_hw_info_encoder_shared_mem_usage(coder_param->encoder_param);
3190 }
3191 else if(mode == 2)
3192 {
3193 task_mem_usage = check_hw_info_scaler_shared_mem_usage(coder_param->scaler_param,16);
3194 }
3195 else if(mode > 3)
3196 {
3197 const int decoder_shared_mem_usage = check_hw_info_decoder_shared_mem_usage(coder_param->decoder_param,16);
3198 const int encoder_shared_mem_usage = check_hw_info_encoder_shared_mem_usage(coder_param->encoder_param);
3199 const int scaler_shared_mem_usage = check_hw_info_scaler_shared_mem_usage(coder_param->scaler_param,16);
3200 task_mem_usage = decoder_shared_mem_usage + ((encoder_shared_mem_usage > scaler_shared_mem_usage) ?
3201 encoder_shared_mem_usage : scaler_shared_mem_usage);
3202 }
3203 else
3204 {
3205 ni_log(NI_LOG_ERROR, "parameter:mode is out of range\n");
3206 task_mem_usage = check_hw_info_decoder_shared_mem_usage(coder_param->decoder_param,16) +
3207 check_hw_info_encoder_shared_mem_usage(coder_param->encoder_param)+
3208 check_hw_info_scaler_shared_mem_usage(coder_param->scaler_param,16);
3209 }
3210
3211 task_mem_precentage = 100 * task_mem_usage / total;
3212
3213 if(task_mem_precentage > 90)
3214 {
3215 //calculate mem usage is an estimated num , maybe too big
3216 task_mem_precentage = 90;
3217 }
3218
3219 for(i = 0;i<card_num;++i)
3220 {
3221 if(card_remove[i] == 1)
3222 {
3223 continue;
3224 }
3225
3226 if(task_mem_precentage + ni_card_info->card_info[0][i].shared_mem_usage >= 100)//all shared memory usages are the same in one card
3227 {
3228 card_remove[i] = 1;
3229 }
3230 }
3231
3232}
3233} // namespace
3234
3235/*!*********************************************************************************************
3236* \brief Create and alloc a pointer to ni_hw_device_info_quadra_coder_param_t
3237* This function is used for ni_check_hw_info()
3238*
3239* \param[in] mode 0 for decoder,1 for encoder,2 for scaler,3 for AI, >= 4 for hw_mode
3240*
3241* \return a pointer to ni_hw_device_info_quadra_coder_param_t on success,NULL for otherwise
3242***********************************************************************************************/
3244{
3245 ni_hw_device_info_quadra_coder_param_t *p_coder_param = NULL;
3247 if(p_coder_param == NULL)
3248 {
3249 ni_log(NI_LOG_ERROR, "Error: Failed to allocate memory for hw_device_info_quadra_coder_param\n");
3250 return p_coder_param;
3251 }
3252 memset(p_coder_param,0,sizeof(ni_hw_device_info_quadra_coder_param_t));
3253 p_coder_param->hw_mode = 0;
3254 if(mode == 0)//decoder
3255 {
3257 if(p_coder_param->decoder_param == NULL)
3258 {
3259 ni_log(NI_LOG_ERROR, "Error: Failed to allocate memory for hw_device_info_quadra_decoder_param\n");
3260 free(p_coder_param);
3261 p_coder_param = NULL;
3262 return p_coder_param;
3263 }
3264 }
3265 else if(mode == 1)//encoder
3266 {
3268 if(p_coder_param->encoder_param == NULL)
3269 {
3270 ni_log(NI_LOG_ERROR, "Error: Failed to allocate memory for hw_device_info_quadra_encoder_param\n");
3271 free(p_coder_param);
3272 p_coder_param = NULL;
3273 return p_coder_param;
3274 }
3275 }
3276 else if(mode == 2)//scaler
3277 {
3279 if(p_coder_param->scaler_param == NULL)
3280 {
3281 ni_log(NI_LOG_ERROR, "Error: Failed to allocate memory for hw_device_info_quadra_scaler_param\n");
3282 free(p_coder_param);
3283 p_coder_param = NULL;
3284 return p_coder_param;
3285 }
3286 }
3287 else if(mode == 3)//AI
3288 {
3290 if(p_coder_param->ai_param == NULL)
3291 {
3292 ni_log(NI_LOG_ERROR, "Error: Failed to allocate memory for hw_device_info_quadra_ai_param\n");
3293 free(p_coder_param);
3294 p_coder_param = NULL;
3295 return p_coder_param;
3296 }
3297 }
3298 else//hw_mode
3299 {
3301 if(p_coder_param->encoder_param == NULL)
3302 {
3303 ni_log(NI_LOG_ERROR, "Error: Failed to allocate memory for hw_device_info_quadra_encoder_param\n");
3304 free(p_coder_param);
3305 p_coder_param = NULL;
3306 return p_coder_param;
3307 }
3309 if(p_coder_param->decoder_param == NULL)
3310 {
3311 ni_log(NI_LOG_ERROR, "Error: Failed to allocate memory for hw_device_info_quadra_decoder_param\n");
3312 free(p_coder_param->encoder_param);
3313 p_coder_param->encoder_param = NULL;
3314 free(p_coder_param);
3315 p_coder_param = NULL;
3316 return p_coder_param;
3317 }
3319 if(p_coder_param->scaler_param == NULL)
3320 {
3321 ni_log(NI_LOG_ERROR, "Error: Failed to allocate memory for hw_device_info_quadra_scaler_param\n");
3322 free(p_coder_param->encoder_param);
3323 p_coder_param->encoder_param = NULL;
3324 free(p_coder_param->decoder_param);
3325 p_coder_param->decoder_param = NULL;
3326 free(p_coder_param);
3327 p_coder_param = NULL;
3328 return p_coder_param;
3329 }
3331 if(p_coder_param->ai_param == NULL)
3332 {
3333 ni_log(NI_LOG_ERROR, "Error: Failed to allocate memory for hw_device_info_quadra_ai_param\n");
3334 free(p_coder_param->encoder_param);
3335 p_coder_param->encoder_param = NULL;
3336 free(p_coder_param->decoder_param);
3337 p_coder_param->decoder_param = NULL;
3338 free(p_coder_param->scaler_param);
3339 p_coder_param->scaler_param = NULL;
3340 free(p_coder_param);
3341 p_coder_param = NULL;
3342 return p_coder_param;
3343 }
3344 p_coder_param->hw_mode = 1;
3345 }
3346 if(p_coder_param->encoder_param)
3347 {
3348 p_coder_param->encoder_param->bit_8_10 = 8;
3349 p_coder_param->encoder_param->code_format = 0;
3350 p_coder_param->encoder_param->fps = 30;
3351 p_coder_param->encoder_param->lookaheadDepth = 0;
3352 p_coder_param->encoder_param->rdoLevel = 0;
3353 p_coder_param->encoder_param->w = 1920;
3354 p_coder_param->encoder_param->h = 1080;
3355 p_coder_param->encoder_param->ui8enableRdoQuant = 0;
3356 p_coder_param->encoder_param->uploader = 0;
3357 p_coder_param->encoder_param->rgba = 0;
3358 }
3359 if(p_coder_param->decoder_param)
3360 {
3361 p_coder_param->decoder_param->w = 1920;
3362 p_coder_param->decoder_param->h = 1080;
3363 p_coder_param->decoder_param->bit_8_10 = 8;
3364 p_coder_param->decoder_param->fps = 30;
3365 p_coder_param->decoder_param->rgba = 0;
3366 p_coder_param->decoder_param->hw_frame = 1;
3367 }
3368 if(p_coder_param->scaler_param)
3369 {
3370 p_coder_param->scaler_param->h = 1920;
3371 p_coder_param->scaler_param->w = 1080;
3372 p_coder_param->scaler_param->bit_8_10 = 8;
3373 p_coder_param->scaler_param->rgba = 0;
3374 }
3375 if(p_coder_param->ai_param)
3376 {
3377 p_coder_param->ai_param->h = 1920;
3378 p_coder_param->ai_param->w = 1080;
3379 p_coder_param->ai_param->bit_8_10 = 8;
3380 p_coder_param->ai_param->rgba = 0;
3381 }
3382 return p_coder_param;
3383}
3384
3385
3386/*!*********************************************************************************************
3387* \brief Free resource in p_hw_device_info_quadra_coder_param
3388* This function is used for ni_check_hw_info()
3389*
3390* \param[in] device_type_num
3391*
3392* \param[in] avaliable_card_num
3393*
3394* \return a pointer to ni_hw_device_info_quadra_t on success,NULL for otherwise
3395***********************************************************************************************/
3397{
3398 if(p_hw_device_info_quadra_coder_param == NULL)
3399 {
3400 return;
3401 }
3402 if(p_hw_device_info_quadra_coder_param->encoder_param)
3403 {
3404 free(p_hw_device_info_quadra_coder_param->encoder_param);
3405 p_hw_device_info_quadra_coder_param->encoder_param = NULL;
3406 }
3407 if(p_hw_device_info_quadra_coder_param->decoder_param)
3408 {
3409 free(p_hw_device_info_quadra_coder_param->decoder_param);
3410 p_hw_device_info_quadra_coder_param->decoder_param = NULL;
3411 }
3412 if(p_hw_device_info_quadra_coder_param->scaler_param)
3413 {
3414 free(p_hw_device_info_quadra_coder_param->scaler_param);
3415 p_hw_device_info_quadra_coder_param->scaler_param = NULL;
3416 }
3417 if(p_hw_device_info_quadra_coder_param->ai_param)
3418 {
3419 free(p_hw_device_info_quadra_coder_param->ai_param);
3420 p_hw_device_info_quadra_coder_param->ai_param = NULL;
3421 }
3422 free(p_hw_device_info_quadra_coder_param);
3423 return;
3424}
3425
3426/*!*********************************************************************************************
3427* \brief Create a ni_hw_device_info_quadra_t
3428* This function is used for ni_check_hw_info()
3429*
3430* \param[in] device_type_num
3431* \param[in] avaliable_card_num
3432*
3433* \return a pointer to ni_hw_device_info_quadra_t on success,NULL for otherwise
3434***********************************************************************************************/
3435ni_hw_device_info_quadra_t *ni_hw_device_info_alloc_quadra(int device_type_num,int avaliable_card_num)
3436{
3437 int i;
3439 if(!p_hw_device_info)
3440 {
3441 ni_log(NI_LOG_ERROR,"ERROR: Failed to allocate memory for p_hw_device_info_quadra_t\n");
3442 goto p_hw_device_info_end;
3443 }
3444
3445 p_hw_device_info->device_type_num = device_type_num;
3446 p_hw_device_info->device_type = (ni_device_type_t *)malloc(sizeof(ni_device_type_t) * device_type_num);
3447 if(!p_hw_device_info->device_type)
3448 {
3449 ni_log(NI_LOG_ERROR,"ERROR: Failed to allocate memory for p_hw_device_info_quadra_t->device_type\n");
3450 goto device_type_end;
3451 }
3452
3453 p_hw_device_info->card_info = (ni_card_info_quadra_t **)malloc(sizeof(ni_card_info_quadra_t*) * p_hw_device_info->device_type_num);
3454 if(p_hw_device_info->card_info == NULL)
3455 {
3456 ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for p_hw_device_info_quadra_t->card_info\n", NI_ERRNO);
3457 p_hw_device_info->err_code = NI_RETCODE_ERROR_MEM_ALOC;
3458 //unlock_and_return
3459 goto card_info_end;
3460 }
3461 memset(reinterpret_cast<void*>(p_hw_device_info->card_info), 0, sizeof(ni_card_info_quadra_t*) * p_hw_device_info->device_type_num);
3462
3463 p_hw_device_info->available_card_num = avaliable_card_num;
3464 p_hw_device_info->consider_mem = 0;
3465 for(i = 0; i < p_hw_device_info->device_type_num; ++i)
3466 {
3467 p_hw_device_info->card_info[i] = (ni_card_info_quadra_t *)malloc(sizeof(ni_card_info_quadra_t) * p_hw_device_info->available_card_num);
3468 if(p_hw_device_info->card_info[i] == NULL)
3469 {
3470 ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for p_hw_device_info_quadra_t->card_info\n", NI_ERRNO);
3471 goto card_info_i_end;
3472 }
3473 }
3474
3475 return p_hw_device_info;
3476
3477card_info_i_end:
3478 for(i = 0; i < p_hw_device_info->device_type_num; ++i)
3479 {
3480 if(p_hw_device_info->card_info[i])
3481 {
3482 free(p_hw_device_info->card_info[i]);
3483 p_hw_device_info->card_info[i] = NULL;
3484 }
3485 }
3486 free(reinterpret_cast<void*>(p_hw_device_info->card_info));
3487 p_hw_device_info->card_info = NULL;
3488card_info_end:
3489 free(p_hw_device_info->device_type);
3490 p_hw_device_info->device_type = NULL;
3491device_type_end:
3492 free(p_hw_device_info);
3493 p_hw_device_info = NULL;
3494p_hw_device_info_end:
3495 return NULL;
3496}
3497
3498/*!*********************************************************************************************
3499* \brief Free resource in a pointer of ni_hw_device_info_quadra_t
3500* This function is used for ni_check_hw_info()
3501*
3502* \param[in] p_hw_device_info Poiner to a ni_hw_device_info_quadra_t struct
3503*
3504* \return None
3505***********************************************************************************************/
3507{
3508 int i;
3509 if(!p_hw_device_info)
3510 {
3511 return;
3512 }
3513 free(p_hw_device_info->device_type);
3514 p_hw_device_info->device_type = NULL;
3515 for(i = 0; i < p_hw_device_info->device_type_num; ++i)
3516 {
3517 free(p_hw_device_info->card_info[i]);
3518 p_hw_device_info->card_info[i] = NULL;
3519 }
3520 free(reinterpret_cast<void*>(p_hw_device_info->card_info));
3521 p_hw_device_info->card_info = NULL;
3522 free(p_hw_device_info);
3523 return;
3524}
3525
3526int ni_check_hw_info(ni_hw_device_info_quadra_t **pointer_to_p_hw_device_info,
3527 int task_mode,
3528 ni_hw_device_info_quadra_threshold_param_t *hw_info_threshold_param,
3529 ni_device_type_t preferential_device_type,
3531 int hw_mode,
3532 int consider_mem)
3533{
3534 //order of ni_hw_device_info_quadra_threshold_param_t *hw_info_threshold_param, order
3535 //order of ni_device_type_t all_need_device_type
3536 //ni_device_type_t preferential_device_type, in the first place
3537 //other order of device_type ni_device_type_t adjust to the order of all_need_device_type
3538 //int hw_info_param_num = hw_mode ? 2 : 1;adjust to 3
3539 const int should_match_rev = 1;
3540 int module_count = 1;
3541 ni_device_context_t *dev_ctxt_arr = NULL;
3542 int32_t *module_id_arr = NULL;
3543 // int32_t best_load_module_id = -1;
3544 ni_device_pool_t *p_device_pool = NULL;
3545 ni_device_queue_t *coders = NULL;
3546 ni_device_context_t *p_device_context = NULL;
3547 ni_session_context_t *p_xCtxt = NULL;
3548 int *card_remove = NULL;//cards which are not satisfied threshold
3549 // uint64_t reserved_memory = 0;
3550 // int needed_memory = 0;
3551 uint64_t decoder_need_load = 0;
3552 uint64_t encoder_need_load = 0;
3553 int retval = 0;//1 for success , 0 for failure
3554 int ret = 0;
3555 const int hw_info_param_num = hw_mode ? 4 : 1;
3556 int device_type_num = 1;
3557 const int all_device_type_num = 4;
3558
3559 ni_device_type_t all_need_device_type[4] = {NI_DEVICE_TYPE_DECODER,NI_DEVICE_TYPE_ENCODER,NI_DEVICE_TYPE_SCALER,NI_DEVICE_TYPE_AI};//decoder encoder scaler and AI
3560 /*note: preference device type will be moved to all_need_device_type[0],
3561 * and sequence of device type in other structs(such as p_hw_device_info.device_type) will be changed in the order of all_need_device_type
3562 */
3563
3564 int i = 0;
3565 bool b_valid = false;
3566
3567
3568 // int *mem_usage = NULL;
3569
3570 ni_hw_device_info_quadra_t *p_hw_device_info = NULL;
3571 bool pool_locked = false;
3572
3573 //check hw_info_param
3574 if(!pointer_to_p_hw_device_info)
3575 {
3576 ni_log(NI_LOG_ERROR, "Error: Invalid input params: pointer_to_p_hw_device_info is NULL.\n");
3577 return retval;
3578 }
3579
3580 if(*pointer_to_p_hw_device_info)
3581 {
3582 p_hw_device_info = *pointer_to_p_hw_device_info;
3583 b_valid = true;
3584 }
3585
3586 // Check input parameters here
3587 if(!coder_param){
3588 if(b_valid)
3589 {
3590 p_hw_device_info->err_code = NI_RETCODE_PARAM_INVALID_VALUE;
3591 }
3592 ni_log(NI_LOG_ERROR, "Error: Invalid input params: coder_param is NULL.\n");
3593 return retval;
3594 }else if(hw_mode && hw_mode != coder_param->hw_mode)
3595 {
3596 ni_log(NI_LOG_ERROR, "Error: Invalid input params: hw_mode = %d, coder_param->hw_mode = %d\n",
3597 hw_mode,coder_param->hw_mode);
3598 return retval;
3599 }else if(!hw_mode)
3600 {
3601 if(preferential_device_type == NI_DEVICE_TYPE_ENCODER && coder_param->encoder_param == NULL)
3602 {
3603 ni_log(NI_LOG_ERROR, "Error: Invalid input params: preferential_device_type == NI_DEVICE_TYPE_ENCODER but coder_param->encoder_param == NULL\n");
3604 return retval;
3605 }
3606 if(preferential_device_type == NI_DEVICE_TYPE_DECODER && coder_param->decoder_param == NULL)
3607 {
3608 ni_log(NI_LOG_ERROR, "Error: Invalid input params: preferential_device_type == NI_DEVICE_TYPE_DECODER but coder_param->decoder_param == NULL\n");
3609 return retval;
3610 }
3611 if(preferential_device_type == NI_DEVICE_TYPE_SCALER && coder_param->scaler_param == NULL)
3612 {
3613 ni_log(NI_LOG_ERROR, "Error: Invalid input params: preferential_device_type == NI_DEVICE_TYPE_SCALER but coder_param->scaler_param == NULL\n");
3614 return retval;
3615 }
3616 if(preferential_device_type == NI_DEVICE_TYPE_AI && coder_param->ai_param == NULL)
3617 {
3618 ni_log(NI_LOG_ERROR, "Error: Invalid input params: preferential_device_type == NI_DEVICE_TYPE_AI but coder_param->ai_param == NULL\n");
3619 return retval;
3620 }
3621 }
3622
3623
3624 if((task_mode != 0 && task_mode != 1) ||
3625 (preferential_device_type != NI_DEVICE_TYPE_DECODER && preferential_device_type != NI_DEVICE_TYPE_ENCODER &&
3626 preferential_device_type != NI_DEVICE_TYPE_SCALER && preferential_device_type != NI_DEVICE_TYPE_AI))//scaler
3627 {
3628 if(b_valid)
3629 {
3630 p_hw_device_info->err_code = NI_RETCODE_PARAM_INVALID_VALUE;
3631 }
3632 ni_log(NI_LOG_ERROR, "Error: Invalid input params: realtime %d device_type %d\n",
3633 task_mode, preferential_device_type);
3634 return retval;
3635 }
3636
3637 if(!hw_info_threshold_param)
3638 {
3639 if(b_valid)
3640 {
3641 p_hw_device_info->err_code = NI_RETCODE_PARAM_INVALID_VALUE;
3642 }
3643 ni_log(NI_LOG_ERROR, "Error: Invalid input params: hw_info_threshold_param is NULL.\n");
3644 return retval;
3645 }else{
3646 for(i = 0;i < hw_info_param_num; ++i)
3647 {
3648 if(hw_info_threshold_param[i].load_threshold < 0||//check this
3649 hw_info_threshold_param[i].load_threshold > 100 ||
3650 hw_info_threshold_param[i].task_num_threshold < 0 ||
3651 hw_info_threshold_param[i].task_num_threshold > NI_MAX_CONTEXTS_PER_HW_INSTANCE||
3652 ( hw_info_threshold_param[i].device_type != NI_DEVICE_TYPE_DECODER &&
3653 hw_info_threshold_param[i].device_type != NI_DEVICE_TYPE_ENCODER &&
3654 hw_info_threshold_param[i].device_type != NI_DEVICE_TYPE_SCALER &&
3655 hw_info_threshold_param[i].device_type != NI_DEVICE_TYPE_AI))
3656 {
3657 if(b_valid)
3658 {
3659 p_hw_device_info->err_code = NI_RETCODE_PARAM_INVALID_VALUE;
3660 }
3661 ni_log(NI_LOG_ERROR, "Error: Invalid input params: In %s, hw_info_threshold_param[%d].device_type = %d, hw_info_threshold_param[%d].load_threshold = %d, hw_info_threshold_param[%d].task_num_threshold = %d\n",
3662 (hw_mode ? "hardware_mode":"software_mode"), i, hw_info_threshold_param[i].device_type, i, hw_info_threshold_param[i].load_threshold, i, hw_info_threshold_param[i].task_num_threshold);
3663 return retval;
3664 }
3665 }
3666 }
3667 // all parameters have been checked
3668
3669 /* For load calculations and checking, restrict FPS to be within 5 - 120 */
3670 if(coder_param->encoder_param)
3671 {
3672 if(coder_param->encoder_param->fps > 120)
3673 {
3674 coder_param->encoder_param->fps = 120;
3675 }
3676 if(coder_param->encoder_param->fps < 5)
3677 {
3678 coder_param->encoder_param->fps = 5;
3679 }
3680 }
3681
3682 p_xCtxt = (ni_session_context_t *)calloc(1, sizeof(ni_session_context_t));
3683 if (!p_xCtxt)
3684 {
3685 if (b_valid)
3686 {
3687 p_hw_device_info->err_code = NI_RETCODE_ERROR_MEM_ALOC;
3688 }
3689 LRETURN;
3690 }
3691 if(coder_param->decoder_param)
3692 {
3693 if(coder_param->decoder_param->fps > 120)
3694 {
3695 coder_param->decoder_param->fps = 120;
3696 }
3697 if(coder_param->decoder_param->fps < 5)
3698 {
3699 coder_param->decoder_param->fps = 5;
3700 }
3701 }
3702
3703 //ni_rsrc_init() is unsafe in multi process/thread ,do not call ni_rsrc_init() here
3704
3705 ret = ni_rsrc_refresh(should_match_rev);
3706 if (NI_RETCODE_SUCCESS != ret)
3707 {
3708 ni_log(NI_LOG_ERROR, "Error: resource pool records might be corrupted!!\n");
3709 if(b_valid)
3710 {
3711 p_hw_device_info->err_code = ret;
3712 }
3713 LRETURN;
3714 }
3715
3716 p_device_pool = ni_rsrc_get_device_pool();
3717 if (!p_device_pool)
3718 {
3719 ni_log(NI_LOG_ERROR, "Error:Can not get device pool info ..\n");
3720 if(b_valid)
3721 {
3722 p_hw_device_info->err_code = NI_RETCODE_ERROR_GET_DEVICE_POOL;
3723 }
3724 LRETURN;
3725 }
3726
3727#ifdef _WIN32
3728 if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE)) // no time-out interval)
3729 {
3730 ni_log(NI_LOG_ERROR, "ERROR: Failed to obtain mutex: %p\n", p_device_pool->lock);
3731 LRETURN;
3732 }
3733 pool_locked = true;
3734#elif defined(__linux__)
3735 if (lockf(p_device_pool->lock, F_LOCK, 0))
3736 {
3737 ni_log(NI_LOG_ERROR, "Error lockf() failed\n");
3738 if(b_valid)
3739 {
3740 p_hw_device_info->err_code = NI_RETCODE_ERROR_LOCK_DOWN_DEVICE;
3741 }
3742 LRETURN;
3743 }
3744 pool_locked = true;
3745#endif
3746
3747 coders = p_device_pool->p_device_queue;
3748 if (!coders)
3749 {
3750 ni_log(NI_LOG_ERROR, "Error pdevice_queue null!!\n");
3751 if(b_valid)
3752 {
3753 p_hw_device_info->err_code = NI_RETCODE_ERROR_GET_DEVICE_POOL;
3754 }
3755 LRETURN;
3756 }
3757
3759
3760
3761 // move preferential_device_type in all_need_device_type to top
3762 for(i = 0; i < all_device_type_num; ++i)
3763 {
3764 if(all_need_device_type[i] == preferential_device_type)
3765 {
3766 const ni_device_type_t tmp = all_need_device_type[i];
3767 all_need_device_type[i] = all_need_device_type[0];
3768 all_need_device_type[0] = tmp;
3769 break;
3770 }
3771 //ni_device_type_t is a enum
3772 }
3773 qsort(&all_need_device_type[1], all_device_type_num - 1, sizeof(ni_device_type_t), int_cmp);
3774
3775 //adjust order of hw_info_threshold_param as all_need_device_type
3776 if(hw_mode)
3777 {
3778 // default device_type_num is 1
3779 device_type_num = 4;//decoder and encoder and scaler and AI
3780 //adjust order of hw_info_threshold_param as all_need_device_type
3781 for(i = 0; i < device_type_num; ++i)
3782 {
3783 if(hw_info_threshold_param[i].device_type == preferential_device_type)
3784 {
3785 const ni_hw_device_info_quadra_threshold_param_t tmp = hw_info_threshold_param[i];
3786 hw_info_threshold_param[i] = hw_info_threshold_param[0];
3787 hw_info_threshold_param[0] = tmp;
3788 break;
3789 }
3790 }
3791 qsort(&hw_info_threshold_param[1], device_type_num - 1,
3792 sizeof(ni_hw_device_info_quadra_threshold_param_t), ni_hw_device_info_quadra_threshold_param_t_compare);
3793 }
3794
3795 if(!(*pointer_to_p_hw_device_info))
3796 {
3797 p_hw_device_info = ni_hw_device_info_alloc_quadra(device_type_num,(int)coders->xcoder_cnt[preferential_device_type]);
3798 if(!p_hw_device_info)
3799 {
3800 ni_log(NI_LOG_ERROR,"ERROR: Failed to allocate memory for p_hw_device_info\n");
3801 LRETURN;
3802 }
3803 *pointer_to_p_hw_device_info = p_hw_device_info;
3804 b_valid = true;
3805 }
3806 else
3807 {
3808 // p_hw_device_info = *pointer_to_p_hw_device_info;
3809 //already set this before
3810
3811 //if user alloc hw_device_info themself check it
3812 if(!p_hw_device_info->device_type)
3813 {
3814 ni_log(NI_LOG_ERROR,"ERROR: pointer_to_p_hw_device_info is not a pointer to NULL, but ->device_type is NULL\n");
3815 p_hw_device_info->err_code = NI_RETCODE_PARAM_INVALID_VALUE;
3816 LRETURN;
3817 }
3818 if(!p_hw_device_info->card_info)
3819 {
3820 ni_log(NI_LOG_ERROR,"ERROR: pointer_to_p_hw_device_info is not a pointer to NULL, but ->card_info is NULL\n");
3821 p_hw_device_info->err_code = NI_RETCODE_PARAM_INVALID_VALUE;
3822 LRETURN;
3823 }
3824 for(i = 0; i < device_type_num; ++i)
3825 {
3826 if(!p_hw_device_info->card_info[i])
3827 {
3828 ni_log(NI_LOG_ERROR,"ERROR: pointer_to_p_hw_device_info is not a pointer to NULL, but ->card_info[%d] is NULL\n", i);
3829 p_hw_device_info->err_code = NI_RETCODE_PARAM_INVALID_VALUE;
3830 LRETURN;
3831 }
3832 }
3833 }
3834 //p_hw_device_info alloc succeed
3835
3836 //coders->decoders_cnt == coder->encoders_cnt has checked in the ni_logan_rsrc_refresh
3837 p_hw_device_info->available_card_num = (int)coders->xcoder_cnt[preferential_device_type];
3838 p_hw_device_info->device_type_num = device_type_num;
3839
3840 for(i = 0; i < p_hw_device_info->device_type_num; ++i)
3841 {
3842 p_hw_device_info->device_type[i] = all_need_device_type[i];
3843 for(int j = 0; j < p_hw_device_info->available_card_num; ++j)
3844 {
3845 p_hw_device_info->card_info[i][j].card_idx = -1;
3846 p_hw_device_info->card_info[i][j].load = -1;
3847 p_hw_device_info->card_info[i][j].model_load = -1;
3848 p_hw_device_info->card_info[i][j].task_num = -1;
3849 p_hw_device_info->card_info[i][j].max_task_num = NI_MAX_CONTEXTS_PER_HW_INSTANCE;
3850 p_hw_device_info->card_info[i][j].shared_mem_usage = -1;
3851 p_hw_device_info->card_info[i][j].firmware_load = -1;
3852 }
3853 }
3854
3855 p_hw_device_info->card_current_card = -1;
3856 p_hw_device_info->err_code = NI_RETCODE_SUCCESS;
3858
3859 if(consider_mem)
3860 {
3861 // mem_usage = (int *)malloc(sizeof(int) * (p_hw_device_info->available_card_num));
3862 // if(!mem_usage)
3863 // {
3864 // ni_log(NI_LOG_ERROR,"ERROR: Failed to allocate memory for p_hw_device_info\n");
3865 // p_hw_device_info->err_code = NI_RETCODE_ERROR_MEM_ALOC;
3866 // LRETURN;
3867 // }
3868 p_hw_device_info->consider_mem = 1;
3869 }
3870 else
3871 {
3872 p_hw_device_info->consider_mem = 0;
3873 }
3874
3875 if (p_hw_device_info->available_card_num <= 0)
3876 {
3877 LRETURN;
3878 }
3879
3880 card_remove = (int32_t *)malloc(sizeof(int32_t) * p_hw_device_info->available_card_num);
3881 if (!card_remove)
3882 {
3883 ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for card_remove\n", NI_ERRNO);
3884 p_hw_device_info->err_code = NI_RETCODE_ERROR_MEM_ALOC;
3885 LRETURN;
3886 }
3887 memset(card_remove, 0, sizeof(int32_t) * p_hw_device_info->available_card_num);
3888
3889
3890 module_count = (int)coders->xcoder_cnt[preferential_device_type];
3891 dev_ctxt_arr = (ni_device_context_t *)malloc(sizeof(ni_device_context_t) * module_count);
3892 if (!dev_ctxt_arr)
3893 {
3894 ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for ni_rsrc_detect\n", NI_ERRNO);
3895 p_hw_device_info->err_code = NI_RETCODE_ERROR_MEM_ALOC;
3896 LRETURN;
3897 }
3898 module_id_arr = (int32_t *)malloc(sizeof(int32_t) * module_count);
3899 if (!module_id_arr)
3900 {
3901 ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for ni_rsrc_detect\n", NI_ERRNO);
3902 p_hw_device_info->err_code = NI_RETCODE_ERROR_MEM_ALOC;
3903 LRETURN;
3904 }
3905
3906 //info start
3907 memcpy(module_id_arr, coders->xcoders[preferential_device_type], sizeof(int32_t) * module_count);//copy useful card
3908
3909 //First module ID in coders->decoders/encoders is of lowest load
3910 // memcpy((void *)&best_load_module_id, module_id_arr, sizeof(int32_t));
3911 qsort(module_id_arr, module_count, sizeof(int32_t), int_cmp);// why?
3912
3913 // p_hw_device_info->card_current_card = best_load_module_id;
3914
3915 for(i = 0; i < p_hw_device_info->available_card_num; ++i)
3916 {
3917 memset(p_xCtxt, 0, sizeof(*p_xCtxt));
3918 p_device_context = ni_rsrc_get_device_context(all_need_device_type[0], module_id_arr[i]);
3919 if (p_device_context)
3920 {
3921 p_xCtxt->blk_io_handle = ni_device_open2(p_device_context->p_device_info->blk_name,
3923 p_xCtxt->device_handle = p_xCtxt->blk_io_handle;
3924 //Check device can be opend
3925 if (NI_INVALID_DEVICE_HANDLE == p_xCtxt->device_handle)
3926 {
3927 ni_log(NI_LOG_ERROR, "Error open device %s, blk device %s\n",
3928 p_device_context->p_device_info->dev_name,
3929 p_device_context->p_device_info->blk_name);
3930 ni_rsrc_free_device_context(p_device_context);
3931 card_remove[i] = 1;
3932 continue;
3933 }
3934#ifdef _WIN32
3935 p_xCtxt->event_handle = ni_create_event();
3936 if (NI_INVALID_EVENT_HANDLE == p_xCtxt->event_handle)
3937 {
3938 ni_rsrc_free_device_context(p_device_context);
3940 ni_log(NI_LOG_ERROR, "ERROR %d: print_perf() create event\n", NI_ERRNO);
3941 card_remove[i] = 1;
3942 continue;
3943 }
3944#endif
3945 }
3946 else
3947 {
3948 ni_log(NI_LOG_ERROR, "ERROR %d: Failed to get device context\n", NI_ERRNO);
3949 p_hw_device_info->err_code = NI_RETCODE_ERROR_MEM_ALOC;
3950 LRETURN;
3951 }
3952
3953 for(int j = 0; j < device_type_num; ++j)//need to fix this
3954 {
3955 if (j != 0)
3956 p_device_context = ni_rsrc_get_device_context(all_need_device_type[j], module_id_arr[i]);
3957 if(p_device_context)
3958 {
3959 //Check decode/encode can be queired
3960 p_xCtxt->hw_id = p_device_context->p_device_info->hw_id;
3961 if (NI_RETCODE_SUCCESS != ni_device_session_query(p_xCtxt, all_need_device_type[j]))
3962 {
3963 ni_log(NI_LOG_ERROR, "Error query %s %s %s.%d\n",
3964 (all_need_device_type[j] == NI_DEVICE_TYPE_DECODER) ? "decoder" :
3965 (all_need_device_type[j] == NI_DEVICE_TYPE_ENCODER) ? "encoder" :
3966 (all_need_device_type[j] == NI_DEVICE_TYPE_SCALER) ? "scaler " : "AIs ",
3967 p_device_context->p_device_info->dev_name,
3968 p_device_context->p_device_info->blk_name,
3969 p_device_context->p_device_info->hw_id);
3970 ni_rsrc_free_device_context(p_device_context);
3971 card_remove[i] = 1;
3972 continue;
3973 }
3974
3975 if (0 == p_xCtxt->load_query.total_contexts)
3976 {
3977 p_xCtxt->load_query.current_load = 0;
3978 }
3979
3980 p_hw_device_info->card_info[j][i].card_idx = p_device_context->p_device_info->module_id;
3981
3982 //use model_load in card remove for encoder just like before
3983#ifdef XCODER_311
3984 p_hw_device_info->card_info[j][i].load = p_xCtxt->load_query.current_load; //monitor changes this
3985
3986#else
3987 p_hw_device_info->card_info[j][i].load =
3988 (int)((p_xCtxt->load_query.total_contexts == 0 || p_xCtxt->load_query.current_load > p_xCtxt->load_query.fw_load) ? p_xCtxt->load_query.current_load : p_xCtxt->load_query.fw_load);
3989#endif
3990 // module_load_user_can_not_see[j][i] = p_xCtxt->load_query.fw_model_load;
3991 p_hw_device_info->card_info[j][i].model_load = (int)p_xCtxt->load_query.fw_model_load;
3992
3993 p_hw_device_info->card_info[j][i].task_num = (int)p_xCtxt->load_query.total_contexts;
3994 p_hw_device_info->card_info[j][i].max_task_num = NI_MAX_CONTEXTS_PER_HW_INSTANCE;
3995
3996 p_hw_device_info->card_info[j][i].firmware_load = (int)p_xCtxt->load_query.fw_load;
3997 if(consider_mem)
3998 {
3999 // mem_usage[i] = p_xCtxt->load_query.fw_share_mem_usage;
4000 p_hw_device_info->card_info[j][i].shared_mem_usage = (int)p_xCtxt->load_query.fw_share_mem_usage;
4001 }
4002 ni_rsrc_free_device_context(p_device_context);
4003 p_device_context = NULL;
4004 }
4005 else
4006 {
4007 ni_log(NI_LOG_ERROR, "ERROR %d: Failed to get device context\n", NI_ERRNO);
4008 p_hw_device_info->err_code = NI_RETCODE_ERROR_MEM_ALOC;
4010#ifdef _WIN32
4011 ni_close_event(p_xCtxt->event_handle);
4012#endif
4013 LRETURN;
4014 }
4015 }
4017#ifdef _WIN32
4018 ni_close_event(p_xCtxt->event_handle);
4019#endif
4020 }
4021
4022 if(coder_param->decoder_param)
4023 {
4024 decoder_need_load = check_hw_info_decoder_need_load(coder_param->decoder_param);
4025 }
4026 if(coder_param->encoder_param)
4027 {
4028 encoder_need_load = check_hw_info_encoder_need_load(coder_param->encoder_param);
4029 }
4030 // if(coder_param->scaler_param)
4031 // {
4032 //cane not estimate scaler load now
4033 // }
4034
4035 //mark the card removed depends on the load_threshold or task_num_threshold
4036 //in hw_mode ,device_type_num == 4 but only encoder and decoder will be taken into account,we can not estimate scaler load now
4037 //in sw mode ,device_type_num == 1 only preferitial_device_type will be taken into account
4038 for(i = 0; i < p_hw_device_info->available_card_num; ++i)
4039 {
4040 for(int j = 0; j < p_hw_device_info->device_type_num; ++j)
4041 {
4042#ifdef XCODER_311
4043 ni_log(NI_LOG_DEBUG, "%s Card[%3d], load: %3d, task_num: %3d, firmware_load: %3d, model_load: %3d, shared_mem_usage: %3d\n",
4044#else
4045 ni_log(NI_LOG_INFO, "%s Card[%3d], load: %3d, task_num: %3d, firmware_load: %3d, model_load: %3d, shared_mem_usage: %3d\n",
4046#endif
4047 (p_hw_device_info->device_type[j] == NI_DEVICE_TYPE_DECODER ? "Decoder" :
4048 ((p_hw_device_info->device_type[j] == NI_DEVICE_TYPE_ENCODER) ? "Encoder" :
4049 (p_hw_device_info->device_type[j] == NI_DEVICE_TYPE_SCALER) ? "Scaler " : "AIs ")),
4050 p_hw_device_info->card_info[j][i].card_idx,
4051 p_hw_device_info->card_info[j][i].load,
4052 p_hw_device_info->card_info[j][i].task_num,
4053 p_hw_device_info->card_info[j][i].firmware_load,
4054 p_hw_device_info->card_info[j][i].model_load,
4055 p_hw_device_info->card_info[j][i].shared_mem_usage);
4056
4057 if(card_remove[i] == 1)
4058 {
4059 continue;//for print
4060 }
4061
4062 if(all_need_device_type[j] == NI_DEVICE_TYPE_DECODER)
4063 {
4064 if(decoder_need_load + p_hw_device_info->card_info[j][i].model_load >= 100)
4065 {
4066 card_remove[i] = 1;
4067 }
4068 }
4069
4070 if(all_need_device_type[j] == NI_DEVICE_TYPE_ENCODER)
4071 {
4072 if(encoder_need_load + p_hw_device_info->card_info[j][i].model_load >= 100)
4073 {
4074 card_remove[i] =1;
4075 }
4076 }
4077
4078 if (task_mode)
4079 {
4080 // replicate legacy behavior for task_mode to use enc model_load in place of enc real load
4081 if(all_need_device_type[i] == NI_DEVICE_TYPE_ENCODER)
4082 {
4083 if (p_hw_device_info->card_info[j][i].model_load > hw_info_threshold_param[j].load_threshold ||
4084 p_hw_device_info->card_info[j][i].task_num + 1 >= hw_info_threshold_param[j].task_num_threshold)
4085 {
4086 card_remove[i] = 1;
4087 }
4088 }
4089 else
4090 {
4091 if (p_hw_device_info->card_info[j][i].load > hw_info_threshold_param[j].load_threshold ||
4092 p_hw_device_info->card_info[j][i].task_num + 1 >= hw_info_threshold_param[j].task_num_threshold)
4093 {
4094 card_remove[i] = 1;
4095 }
4096 }
4097 }
4098 else
4099 {
4100 if (p_hw_device_info->card_info[j][i].task_num > hw_info_threshold_param[j].task_num_threshold)
4101 {
4102 card_remove[i] = 1;
4103 }
4104 }
4105 }
4106 }
4107
4108 if(consider_mem)
4109 {
4110 if(hw_mode)
4111 {
4112 check_hw_info_remove_card_with_memory(card_remove,p_hw_device_info,p_hw_device_info->available_card_num,coder_param,10);
4113 }
4114 else if(preferential_device_type == 0)
4115 {
4116 check_hw_info_remove_card_with_memory(card_remove,p_hw_device_info,p_hw_device_info->available_card_num,coder_param,0);
4117 }
4118 else if(preferential_device_type == 1)
4119 {
4120 check_hw_info_remove_card_with_memory(card_remove,p_hw_device_info,p_hw_device_info->available_card_num,coder_param,1);
4121 }
4122 else if(preferential_device_type == 2)
4123 {
4124 check_hw_info_remove_card_with_memory(card_remove,p_hw_device_info,p_hw_device_info->available_card_num,coder_param,2);
4125 }
4126 }
4127
4128 if (task_mode)
4129 {
4130 //select the min_task_num
4131 //p_hw_device_info->card_info[0] is the preferential_device_type
4132 int min_task_num = p_hw_device_info->card_info[0][0].max_task_num;
4133 for (i = 0; i < p_hw_device_info->available_card_num; i++)
4134 {
4135 if (p_hw_device_info->card_info[0][i].task_num < min_task_num &&
4136 card_remove[i] == 0)
4137 {
4138 min_task_num = p_hw_device_info->card_info[0][i].task_num;
4139 }
4140 }
4141 //select the min load
4142 int min_load = 100;
4143 for (i = 0; i < p_hw_device_info->available_card_num; i++)
4144 {
4145 if (p_hw_device_info->card_info[0][i].load < min_load &&
4146 card_remove[i] == 0 &&
4147 p_hw_device_info->card_info[0][i].task_num == min_task_num)
4148 {
4149 min_load = p_hw_device_info->card_info[0][i].load;
4150 p_hw_device_info->card_current_card = p_hw_device_info->card_info[0][i].card_idx;
4151 }
4152 }
4153 }
4154 else
4155 {
4156 //p_hw_device_info->card_info[0] is the preferential_device_type
4157 //select the min task num
4158 int min_task_num = p_hw_device_info->card_info[0][0].max_task_num;
4159 for (i = 0; i < p_hw_device_info->available_card_num; i++)
4160 {
4161 if (p_hw_device_info->card_info[0][i].task_num < min_task_num &&
4162 card_remove[i] == 0)
4163 {
4164 p_hw_device_info->card_current_card = p_hw_device_info->card_info[0][i].card_idx;
4165 min_task_num = p_hw_device_info->card_info[0][i].task_num;
4166 }
4167 }
4168 }
4169
4170 // cppcheck-suppress nullPointerRedundantCheck
4171 if (p_hw_device_info->card_current_card >= 0)
4172 {
4173 retval = 1; //has the card to use
4174 }
4175
4176END:
4177 if (pool_locked) /* p_device_pool is always valid when pool_locked is true */
4178 {
4179#ifdef _WIN32
4180 ReleaseMutex((HANDLE)p_device_pool->lock);
4181
4182#elif defined(__linux__)
4183 if (lockf(p_device_pool->lock, F_ULOCK,0))
4184 {
4185 ni_log(NI_LOG_ERROR, "Error lockf() failed\n");
4186 if(p_hw_device_info)
4187 {
4188 p_hw_device_info->err_code = NI_RETCODE_ERROR_UNLOCK_DEVICE;
4189 }
4190 retval = 0;
4191 }
4192#endif
4193 }
4194 if (p_device_pool)
4195 {
4196 ni_rsrc_free_device_pool(p_device_pool);
4197 p_device_context = NULL;
4198 }
4199 (void)fflush(stderr);
4200 if (module_id_arr)
4201 {
4202 free(module_id_arr);
4203 module_id_arr = NULL;
4204 }
4205 if (dev_ctxt_arr)
4206 {
4207 free(dev_ctxt_arr);
4208 dev_ctxt_arr = NULL;
4209 }
4210 if (card_remove)
4211 {
4212 free(card_remove);
4213 card_remove = NULL;
4214 }
4215 if (p_xCtxt)
4216 {
4217 free(p_xCtxt);
4218 p_xCtxt = NULL;
4219 }
4220 if(b_valid)
4221 {
4222 if(hw_mode)
4223 {
4224#ifdef XCODER_311
4225 ni_log(NI_LOG_DEBUG, "In hw_mode select card_current_card %d retval %d\n",
4226#else
4227 ni_log(NI_LOG_INFO, "In hw_mode select card_current_card %d retval %d\n",
4228#endif
4229 p_hw_device_info->card_current_card, retval);
4230 }
4231 else
4232 {
4233#ifdef XCODER_311
4234 ni_log(NI_LOG_DEBUG, "In sw_mode select device_type %s card_current_card %d retval %d\n",
4235#else
4236 ni_log(NI_LOG_INFO, "In sw_mode select device_type %s card_current_card %d retval %d\n",
4237#endif
4238 ((preferential_device_type == 0) ? "decode" : (preferential_device_type == 1 ? "encode" : (preferential_device_type == 2 ? "scaler" : "ai "))), p_hw_device_info->card_current_card, retval);
4239 }
4240 }
4241 return retval;
4242}
4243
4244
4245/*!*****************************************************************************
4246* \brief Allocate resources for decoding/encoding, based on the provided rule
4247*
4248* \param[in] device_type NI_DEVICE_TYPE_DECODER or NI_DEVICE_TYPE_ENCODER
4249* \param[in] rule allocation rule
4250* \param[in] codec EN_H264 or EN_H265
4251* \param[in] width width of video resolution
4252* \param[in] height height of video resolution
4253* \param[in] frame_rate video stream frame rate
4254* \param[out] p_load the p_load that will be generated by this encoding
4255* task. Returned *only* for encoder for now.
4256*
4257* \return pointer to ni_device_context_t if found, NULL otherwise
4258*
4259* Note: codec, width, height, fps need to be supplied for NI_DEVICE_TYPE_ENCODER only,
4260* they are ignored otherwize.
4261* Note: the returned ni_device_context_t content is not supposed to be used by
4262* caller directly: should only be passed to API in the subsequent
4263* calls; also after its use, the context should be released by
4264* calling ni_rsrc_free_device_context.
4265*******************************************************************************/
4267 ni_device_type_t device_type,
4268 ni_alloc_rule_t rule,
4269 ni_codec_t codec,
4270 int width, int height,
4271 int frame_rate,
4272 uint64_t *p_load)
4273{
4274 (void)codec;
4275 ni_device_pool_t *p_device_pool = NULL;
4276 ni_device_info_t *p_device_info = NULL;
4277 ni_device_context_t *p_device_context = NULL;
4278 ni_session_context_t *p_session_context = NULL;
4279 int *coders = NULL;
4280 int i = 0, count = 0, rc = NI_RETCODE_FAILURE;
4281 int guid = -1;
4282 int load = 0;
4283 uint32_t num_sw_instances = 0;
4284 int least_model_load = 0;
4285 uint64_t job_mload = 0;
4286
4287
4288 if(device_type != NI_DEVICE_TYPE_DECODER && device_type != NI_DEVICE_TYPE_ENCODER)
4289 {
4290 ni_log2(NULL, NI_LOG_ERROR, "ERROR: Device type %d is not allowed\n", device_type);
4291 return NULL;
4292 }
4295 p_device_pool = ni_rsrc_get_device_pool();
4296
4297 if (!p_device_pool)
4298 {
4299 ni_log2(NULL, NI_LOG_ERROR, "ERROR: %s() Could not get device pool\n", __func__);
4300 return NULL;
4301 }
4302
4303 p_session_context = ni_device_session_context_alloc_init();
4304 if (!p_session_context)
4305 {
4306 ni_rsrc_free_device_pool(p_device_pool);
4307 return NULL;
4308 }
4309#ifdef _WIN32
4310 if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE)) // no time-out interval) //we got the mutex
4311 {
4312 ni_log(NI_LOG_ERROR, "ERROR: %s() failed to obtain mutex: %p\n", __func__, p_device_pool->lock);
4313 }
4314#elif __linux__ || __APPLE__
4315 lockf(p_device_pool->lock, F_LOCK, 0);
4316#endif
4317
4318 coders = p_device_pool->p_device_queue->xcoders[device_type];
4319 count = (int)p_device_pool->p_device_queue->xcoder_cnt[device_type];
4320
4321 for (i = 0; i < count; i++)
4322 {
4324 p_device_context = ni_rsrc_get_device_context(device_type, coders[i]);
4325 if (!p_device_context)
4326 {
4328 "ERROR: %s() ni_rsrc_get_device_context() failed\n", __func__);
4329 continue;
4330 }
4331
4332 // p_first retrieve status from f/w and update storage
4333
4334 p_session_context->blk_io_handle = ni_device_open2(p_device_context->p_device_info->dev_name, NI_DEVICE_READ_ONLY);
4335 p_session_context->device_handle = p_session_context->blk_io_handle;
4336
4337 if (NI_INVALID_DEVICE_HANDLE == p_session_context->device_handle)
4338 {
4339 char errmsg[NI_ERRNO_LEN] = {0};
4341 ni_log(NI_LOG_ERROR, "ERROR %s() ni_device_open2() %s: %s\n",
4342 __func__, p_device_context->p_device_info->dev_name,
4343 errmsg);
4344 ni_rsrc_free_device_context(p_device_context);
4345 continue;
4346 }
4347
4348 p_session_context->hw_id = p_device_context->p_device_info->hw_id;
4349 rc = ni_device_session_query(p_session_context, device_type);
4350
4351 ni_device_close(p_session_context->device_handle);
4352
4353 if (NI_RETCODE_SUCCESS != rc)
4354 {
4355 ni_log(NI_LOG_ERROR, "ERROR: query %s %s.%d\n",
4356 g_device_type_str[device_type],
4357 p_device_context->p_device_info->dev_name,
4358 p_device_context->p_device_info->hw_id);
4359 ni_rsrc_free_device_context(p_device_context);
4360 continue;
4361 }
4362
4363#ifdef _WIN32
4364 if (WAIT_ABANDONED == WaitForSingleObject(p_device_context->lock, INFINITE)) // no time-out interval) //we got the mutex
4365 {
4366 ni_log(NI_LOG_ERROR, "ERROR: %s() failed to obtain mutex: %p\n",
4367 __func__, p_device_context->lock);
4368 }
4369#elif __linux__ || __APPLE__
4370 lockf(p_device_context->lock, F_LOCK, 0);
4371#endif
4372 ni_rsrc_update_record(p_device_context, p_session_context);
4373
4374 p_device_info = p_device_context->p_device_info;
4375 if (i == 0)
4376 {
4377 guid = coders[i];
4378 load = p_device_info->load;
4379 least_model_load = p_device_info->model_load;
4380 num_sw_instances = p_device_info->active_num_inst;
4381 }
4382
4383 ni_log(NI_LOG_INFO, "Coder [%d]: %d , load: %d (%d), activ_inst: %d , max_inst %d\n",
4384 i, coders[i], p_device_info->load, p_device_info->model_load, p_device_info->active_num_inst,
4385 p_device_info->max_instance_cnt);
4386
4387 switch (rule)
4388 {
4390 {
4391 if (p_device_info->active_num_inst < num_sw_instances)
4392 {
4393 guid = coders[i];
4394 num_sw_instances = p_device_info->active_num_inst;
4395 }
4396 break;
4397 }
4398
4400 default:
4401 {
4402 if (NI_DEVICE_TYPE_ENCODER == device_type)
4403 {
4404 if (p_device_info->model_load < least_model_load)
4405 {
4406 guid = coders[i];
4407 least_model_load = p_device_info->model_load;
4408 }
4409 }
4410 else if (p_device_info->load < load)
4411 {
4412 guid = coders[i];
4413 load = p_device_info->load;
4414 }
4415 break;
4416 }
4417 }
4418
4419#ifdef _WIN32
4420 ReleaseMutex(p_device_context->lock);
4421#elif __linux__ || __APPLE__
4422 lockf(p_device_context->lock, F_ULOCK, 0);
4423#endif
4424 ni_rsrc_free_device_context(p_device_context);
4425 }
4426
4427 if (guid >= 0)
4428 {
4429 p_device_context = ni_rsrc_get_device_context(device_type, guid);
4430 if (!p_device_context)
4431 {
4433 "ERROR: %s() ni_rsrc_get_device_context() failed\n", __func__);
4434 LRETURN;
4435 }
4436
4437 if (NI_DEVICE_TYPE_ENCODER == device_type)
4438 {
4439 job_mload = (uint64_t)width * height * frame_rate;
4440 }
4441 }
4442 else
4443 {
4444 ni_log(NI_LOG_ERROR, "ERROR: %s() cannot find guid\n", __func__);
4445 p_device_context = NULL;
4446 }
4447
4448END:
4449#ifdef _WIN32
4450 ReleaseMutex(p_device_pool->lock);
4451#elif __linux__ || __APPLE__
4452 lockf(p_device_pool->lock, F_ULOCK, 0);
4453#endif
4454 ni_device_session_context_free(p_session_context);
4455 ni_rsrc_free_device_pool(p_device_pool);
4456
4457 if (p_load)
4458 {
4459 *p_load = job_mload;
4460 }
4461 return p_device_context;
4462}
#define NI_DEPRECATED
Definition ni_defs.h:80
#define NI_XCODER_REVISION_API_MAJOR_VER_IDX
Definition ni_defs.h:99
#define NI_MAX_DEVICE_CNT
Definition ni_defs.h:235
#define END
Definition ni_defs.h:338
#define NI_XCODER_REVISION
Definition ni_defs.h:98
#define NI_MAX_DEVICE_NAME_LEN
Definition ni_defs.h:236
#define NI_MAX_CONTEXTS_PER_HW_INSTANCE
Definition ni_defs.h:248
ni_device_type_t
Definition ni_defs.h:356
@ NI_DEVICE_TYPE_SCALER
Definition ni_defs.h:362
@ NI_DEVICE_TYPE_AI
Definition ni_defs.h:363
@ NI_DEVICE_TYPE_DECODER
Definition ni_defs.h:360
@ NI_DEVICE_TYPE_UPLOAD
Definition ni_defs.h:367
@ NI_DEVICE_TYPE_ENCODER
Definition ni_defs.h:361
@ NI_DEVICE_TYPE_XCODER_MAX
Definition ni_defs.h:364
#define NI_ERRNO
Definition ni_defs.h:229
@ NI_SCALER_OPCODE_SCALE
Definition ni_defs.h:594
#define GET_XCODER_DEVICE_TYPE_STR(t)
Definition ni_defs.h:438
#define LRETURN
Definition ni_defs.h:337
ni_retcode_t
Definition ni_defs.h:447
@ NI_RETCODE_ERROR_LOCK_DOWN_DEVICE
Definition ni_defs.h:528
@ NI_RETCODE_FAILURE
Definition ni_defs.h:449
@ NI_RETCODE_ERROR_GET_DEVICE_POOL
Definition ni_defs.h:527
@ NI_RETCODE_ERROR_UNLOCK_DEVICE
Definition ni_defs.h:530
@ NI_RETCODE_SUCCESS
Definition ni_defs.h:448
@ NI_RETCODE_ERROR_INVALID_HANDLE
Definition ni_defs.h:532
@ NI_RETCODE_PARAM_INVALID_VALUE
Definition ni_defs.h:458
@ NI_RETCODE_ERROR_RESOURCE_UNAVAILABLE
Definition ni_defs.h:455
@ NI_RETCODE_ERROR_MEM_ALOC
Definition ni_defs.h:452
@ NI_RETCODE_ERROR_VPU_RECOVERY
Definition ni_defs.h:536
@ NI_RETCODE_INVALID_PARAM
Definition ni_defs.h:450
#define IS_XCODER_DEVICE_TYPE(t)
Definition ni_defs.h:431
void ni_device_session_context_free(ni_session_context_t *p_ctx)
Free previously allocated session context.
ni_retcode_t ni_device_session_close(ni_session_context_t *p_ctx, int eos_recieved, ni_device_type_t device_type)
Close device session that was previously opened by calling ni_device_session_open() If device_type is...
NI_DEPRECATED ni_retcode_t ni_device_capability_query(ni_device_handle_t device_handle, ni_device_capability_t *p_cap)
Query device and return device capability structure This function had been replaced by ni_device_capa...
ni_retcode_t ni_device_session_open(ni_session_context_t *p_ctx, ni_device_type_t device_type)
Open a new device session depending on the device_type parameter If device_type is NI_DEVICE_TYPE_DEC...
ni_event_handle_t ni_create_event(void)
Create event and return event handle if successful (Windows only)
ni_retcode_t ni_query_fl_fw_versions(ni_device_handle_t device_handle, ni_device_info_t *p_dev_info)
Query firmware loader and firmware versions from the device.
ni_retcode_t ni_encoder_init_default_params(ni_xcoder_params_t *p_param, int fps_num, int fps_denom, long bit_rate, int width, int height, ni_codec_format_t codec_format)
Initialize default encoder parameters.
ni_retcode_t ni_device_capability_query2(ni_device_handle_t device_handle, ni_device_capability_t *p_cap, bool device_in_ctxt)
Query device and return device capability structure This function had replaced ni_device_capability_q...
ni_retcode_t ni_device_session_query(ni_session_context_t *p_ctx, ni_device_type_t device_type)
Query session data from the device - If device_type is valid, will query session data from specified ...
ni_session_context_t * ni_device_session_context_alloc_init(void)
Allocate and initialize a new ni_session_context_t struct.
ni_retcode_t ni_decoder_init_default_params(ni_xcoder_params_t *p_param, int fps_num, int fps_denom, long bit_rate, int width, int height)
Initialize default decoder parameters.
void ni_close_event(ni_event_handle_t event_handle)
Close event and release resources (Windows only)
void ni_device_close(ni_device_handle_t device_handle)
Close device and release resources.
ni_retcode_t ni_query_extra_info(ni_device_handle_t device_handle, ni_device_extra_info_t *p_dev_extra_info, uint8_t fw_rev[])
Query CompositeTemp from device.
ni_device_handle_t ni_device_open2(const char *p_dev, ni_device_mode_t mode)
Open device and return device device_handle if successful.
@ NI_DEVICE_READ_ONLY
@ NI_DEVICE_READ_WRITE
#define NI_MIN_BITRATE
@ NI_CODEC_FORMAT_H264
#define NI_DEFAULT_KEEP_ALIVE_TIMEOUT
ni_log_level_t ni_log_get_level(void)
Get ni_log_level.
Definition ni_log.c:212
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_set_level(ni_log_level_t level)
Set ni_log_level.
Definition ni_log.c:202
void ni_log(ni_log_level_t level, const char *fmt,...)
print log message using ni_log_callback
Definition ni_log.c:183
#define NI_ERRNO_LEN
Definition ni_log.h:51
ni_log_level_t
Definition ni_log.h:58
@ NI_LOG_NONE
Definition ni_log.h:60
@ 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
int ni_rsrc_unlock(int device_type, ni_lock_handle_t lock)
unlock a file lock
int ni_rsrc_get_numa_node(char *device_name)
get linux numa_node
NI_DEPRECATED bool g_device_in_ctxt
ni_device_context_t * ni_rsrc_allocate_simple_direct(ni_device_type_t device_type, int guid)
Allocate resources for decoding/encoding, by designating explicitly the device to use....
void ni_destory_hw_device_info_quadra_coder_param(ni_hw_device_info_quadra_coder_param_t *p_hw_device_info_quadra_coder_param)
Free resource in p_hw_device_info_quadra_coder_param This function is used for ni_check_hw_info()
ni_retcode_t ni_rsrc_list_devices(ni_device_type_t device_type, ni_device_info_t *p_device_info, int *p_device_count)
List device(s) based on device type with full information including s/w instances on the system.
ni_hw_device_info_quadra_coder_param_t * ni_create_hw_device_info_quadra_coder_param(int mode)
Create and alloc a pointer to ni_hw_device_info_quadra_coder_param_t This function is used for ni_che...
void ni_rsrc_print_device_info(const ni_device_info_t *p_device_info)
Print the content of the ni_device_info_t struct.
void print_device(ni_device_t *p_device)
NI_DEPRECATED int g_xcoder_refresh_dev_count
int ni_rsrc_lock_and_open(int device_type, ni_lock_handle_t *lock)
lock a file lock and open a session on a device
NI_DEPRECATED char ** g_xcoder_refresh_dev_names
ni_retcode_t ni_rsrc_list_all_devices2(ni_device_t *p_device, bool list_uninitialized)
Grabs information for every initialized and uninitialized device.
void ni_rsrc_release_resource(ni_device_context_t *p_device_context, uint64_t load)
Release resources allocated for decoding/encoding. function This must be called at the end of transco...
void ni_rsrc_print_all_devices_capability2(bool list_uninitialized)
Prints detailed capability information for all initialized devices and general information about unin...
void ni_rsrc_free_device_context(ni_device_context_t *p_device_context)
Free previously allocated device context.
int ni_rsrc_remove_all_devices(void)
Remove all NetInt h/w devices from resource pool on the host.
int ni_rsrc_add_device(const char *dev, int should_match_rev)
Add an NetInt h/w device into resource pool on the host.
ni_retcode_t ni_rsrc_refresh(int should_match_rev)
Scan and refresh all resources on the host, taking into account hot-plugged and pulled out cards.
int ni_rsrc_update_device_load(ni_device_context_t *p_device_context, int load, int sw_instance_cnt, const ni_sw_instance_info_t sw_instance_info[])
Update the load value and s/w instances info of a specific decoder or encoder. This is used by resour...
int ni_rsrc_is_fw_compat(uint8_t fw_rev[8])
check if device FW revision is compatible with SW API
void ni_hw_device_info_free_quadra(ni_hw_device_info_quadra_t *p_hw_device_info)
Free resource in a pointer of ni_hw_device_info_quadra_t This function is used for ni_check_hw_info()
int ni_rsrc_get_device_by_block_name(const char *blk_name, ni_device_type_t device_type)
Get GUID of the device by block device name and type.
void ni_rsrc_free_device_pool(ni_device_pool_t *p_device_pool)
Free all resources taken by the device pool.
int ni_rsrc_remove_device(const char *dev)
Remove an NetInt h/w device from resource pool on the host.
int ni_rsrc_check_hw_available(int guid, ni_device_type_t device_type)
check the NetInt h/w device in resource pool on the host.
ni_retcode_t ni_rsrc_list_all_devices(ni_device_t *p_device)
List all devices with full information including s/w instances on the system.
ni_device_context_t * ni_rsrc_allocate_auto(ni_device_type_t device_type, ni_alloc_rule_t rule, ni_codec_t codec, int width, int height, int frame_rate, uint64_t *p_load)
Allocate resources for decoding/encoding, based on the provided rule.
void ni_rsrc_print_all_devices_capability(void)
Print detailed capability information of all devices on the system.
int ni_check_hw_info(ni_hw_device_info_quadra_t **pointer_to_p_hw_device_info, int task_mode, ni_hw_device_info_quadra_threshold_param_t *hw_info_threshold_param, ni_device_type_t preferential_device_type, ni_hw_device_info_quadra_coder_param_t *coder_param, int hw_mode, int consider_mem)
check hw info, return the appropriate card number to use depends on the load&task_num&used resource
ni_hw_device_info_quadra_t * ni_hw_device_info_alloc_quadra(int device_type_num, int avaliable_card_num)
Create a ni_hw_device_info_quadra_t This function is used for ni_check_hw_info()
NI_DEPRECATED ni_device_handle_t g_dev_handle
ni_device_info_t * ni_rsrc_get_device_info(ni_device_type_t device_type, int guid)
Query a specific device with detailed information on the system.
Public definitions for managing NETINT video processing devices.
LIB_API NI_DEPRECATED int ni_rsrc_get_local_device_list(char ni_devices[][NI_MAX_DEVICE_NAME_LEN], int max_handles)
Scans system for all NVMe devices and returns the system device names to the user which were identifi...
LIB_API int ni_rsrc_get_local_device_list2(char ni_devices[][NI_MAX_DEVICE_NAME_LEN], int max_handles, char **xcoder_refresh_dev_names, int xcoder_refresh_dev_count)
Scans system for all NVMe devices and returns the system device names to the user which were identifi...
LIB_API ni_device_context_t * ni_rsrc_get_device_context(ni_device_type_t type, int guid)
Allocates and returns a pointer to ni_device_context_t struct based on provided device_type and guid....
ni_codec_t
Definition ni_rsrc_api.h:48
@ EN_JPEG
Definition ni_rsrc_api.h:53
@ EN_INVALID
Definition ni_rsrc_api.h:49
@ EN_CODEC_MAX
Definition ni_rsrc_api.h:55
ni_alloc_rule_t
@ EN_ALLOC_LEAST_LOAD
@ EN_ALLOC_LEAST_INSTANCE
LIB_API ni_device_pool_t * ni_rsrc_get_device_pool(void)
Create and return the allocated ni_device_pool_t struct.
LIB_API int ni_rsrc_init(int should_match_rev, int timeout_seconds)
Initialize and create all resources required to work with NETINT NVMe transcoder devices....
Public definitions for managing NETINT video processing devices on Android.
android::sp< INidec > service
int ni_rsrc_android_init()
Init android net.int.SharedBuffer service for binder using.
uint32_t g_xcoder_stop_process
void ni_rsrc_get_shm_name(ni_device_type_t device_type, int32_t guid, char *p_name, size_t max_name_len)
ni_retcode_t ni_rsrc_create_retry_lck()
void ni_rsrc_get_lock_name(ni_device_type_t device_type, int32_t guid, char *p_name, size_t max_name_len)
bool add_to_shared_memory(const char device_name[NI_MAX_DEVICE_NAME_LEN], const bool device_open_should_succeed, const int should_match_rev, ni_device_queue_t *device_queue)
int ni_rsrc_strcmp(const void *p_str, const void *p_str1)
Private definitions used by ni_rsrc_api.cpp for management of NETINT video processing devices.
#define CODERS_LCK_NAME
void ni_rsrc_update_record(ni_device_context_t *p_device_context, ni_session_context_t *p_session_ctx)
#define CODERS_SHM_NAME
#define LOCK_WAIT
#define MAX_LOCK_RETRY
int ni_rsrc_enumerate_devices(char ni_devices[][NI_MAX_DEVICE_NAME_LEN], int max_handles)
int ni_rsrc_init_priv(const int should_match_rev, const int existing_number_of_devices, const char device_names[NI_MAX_DEVICE_CNT][NI_MAX_DEVICE_NAME_LEN], int limit_depth)
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:5435
ni_retcode_t ni_strncpy(char *dest, size_t dmax, const char *src, size_t slen)
Definition ni_util.c:525
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:4353
ni_retcode_t ni_strerror(char *dest, size_t dmax, int errnum)
Definition ni_util.c:663
ni_retcode_t ni_strcat(char *dest, size_t dmax, const char *src)
Definition ni_util.c:704
ni_retcode_t ni_strcpy(char *dest, size_t dmax, const char *src)
Definition ni_util.c:460
void ni_usleep(int64_t usec)
Definition ni_util.c:366
ni_retcode_t ni_check_dev_name(const char *p_dev)
check dev name
Definition ni_util.c:1892
ni_retcode_t ni_strtoi(const char *str, int32_t *out_val)
Safely convert a decimal string to a 32-bit integer with full validation. Trailing whitespace is tole...
Definition ni_util.c:2577
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:4383
Utility definitions.
#define XCODER_MIN_ENC_PIC_WIDTH
Definition ni_util.h:112
#define XCODER_MIN_ENC_PIC_HEIGHT
Definition ni_util.h:113
device capability type
uint8_t fw_branch_name[256]
ni_device_info_t * p_device_info
ni_lock_handle_t lock
char shm_name[NI_MAX_DEVICE_NAME_LEN]
uint8_t fw_build_id[256]
uint8_t fw_commit_time[26]
uint8_t serial_number[20]
char dev_name[NI_MAX_DEVICE_NAME_LEN]
uint8_t fw_rev[8]
uint8_t fw_commit_hash[41]
char blk_name[NI_MAX_DEVICE_NAME_LEN]
ni_sw_instance_info_t sw_instance[NI_MAX_CONTEXTS_PER_HW_INSTANCE]
uint64_t xcode_load_pixel
ni_device_type_t device_type
uint8_t fl_ver_last_ran[8]
uint8_t fw_branch_name[256]
uint8_t model_number[40]
uint8_t fw_rev_nor_flash[8]
uint32_t active_num_inst
uint8_t fw_build_time[26]
uint8_t fl_ver_nor_flash[8]
ni_device_video_capability_t dev_cap[EN_CODEC_MAX]
ni_device_queue_t * p_device_queue
Definition ni_rsrc_api.h:99
ni_lock_handle_t lock
Definition ni_rsrc_api.h:98
int32_t xcoders[NI_DEVICE_TYPE_XCODER_MAX][NI_MAX_DEVICE_CNT]
Definition ni_rsrc_api.h:70
uint32_t xcoder_cnt[NI_DEVICE_TYPE_XCODER_MAX]
Definition ni_rsrc_api.h:69
char level[NI_LEVELS_SUPP_STR_LEN]
Definition ni_rsrc_api.h:82
char profiles_supported[NI_PROFILES_SUPP_STR_LEN]
Definition ni_rsrc_api.h:81
ni_device_info_t xcoders[NI_DEVICE_TYPE_XCODER_MAX][NI_MAX_DEVICE_CNT]
int xcoder_cnt[NI_DEVICE_TYPE_XCODER_MAX]
ni_hw_device_info_quadra_encoder_param_t * encoder_param
ni_hw_device_info_quadra_ai_param_t * ai_param
ni_hw_device_info_quadra_decoder_param_t * decoder_param
ni_hw_device_info_quadra_scaler_param_t * scaler_param
ni_card_info_quadra_t ** card_info
ni_device_type_t * device_type
uint32_t fw_share_mem_usage
uint32_t fw_model_load
uint32_t current_load
uint32_t total_contexts
ni_device_handle_t device_handle
ni_load_query_t load_query
ni_event_handle_t event_handle
ni_device_handle_t blk_io_handle