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