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