libxcoder  3.5.1
ni_rsrc_api_logan.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_logan.c
24 *
25 * \brief Exported routines related to resource management of NI T-408 devices
26 *
27 *******************************************************************************/
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <fcntl.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <ctype.h>
35 
36 #if defined(__linux__) || defined(__APPLE__)
37 #ifdef __linux__
38 #include <sys/types.h>
39 #endif
40 #include <unistd.h>
41 #include <fcntl.h> /* For O_* constants */
42 #include <dirent.h>
43 #include <sys/mman.h>
44 #include <sys/stat.h> /* For mode constants */
45 #include <sys/file.h> /* For flock constants */
46 #endif
47 
48 #include "ni_rsrc_api_logan.h"
49 #include "ni_rsrc_priv_logan.h"
50 #include "ni_util_logan.h"
51 
52 static uint32_t decoder_guid = 0;
53 static uint32_t encoder_guid = 0;
54 static int int_cmp(const void *a, const void *b);
55 
56 // Decoder/Encoder reference (resolution_width, resolution_height, framerate) table
58 {
59  // decoder
60  {
61  {1920, 1080, 240}, // H264
62  {1920, 1080, 240}, // H265
63  },
64  // encoder
65  {
66  {1920, 1080, 240}, // H264
67  {1920, 1080, 240}, // H265
68  }
69 };
70 
71 #ifdef __ANDROID__
72 
74 
75 android::sp<INidec> service_logan = NULL;
76 
77 
78 /*!*****************************************************************************
79  * \brief Init android net.int.SharedBuffer service for binder using.
80  *
81  * \param none
82  *
83  * \return service (= 0) if get service , < 0 otherwise
84  *
85  ******************************************************************************/
87 {
88  if (service_logan == NULL)
89  {
90  service_logan = INidec::getService();
91  if(service_logan == nullptr) {
92  ni_log(NI_LOG_ERROR, "ni_logan_rsrc_android_init error\n");
93  return -2;
94  }
95  }
96  return 0;
97 }
98 
99 #endif
100 
101 /*!*****************************************************************************
102  * \brief Scans system for all NVMe devices and returns the system device
103  * names to the user which were identified as NETINT transcoder deivices.
104  * Names are suitable for resource management api usage afterwards
105  *
106  *
107  * \param[out] ni_logan_devices List of device names identified as NETINT NVMe
108  * transcoders
109  * \param[in] max_handles Max number of device names to return
110  *
111  * \return Number if devices found if successful operation completed
112  * 0 if no NETINT NVMe transcoder devices were found
113  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC if memory allocation failed
114  ******************************************************************************/
116  int max_handles)
117 {
118  if (ni_logan_devices == NULL || max_handles == 0)
119  {
120  ni_log(NI_LOG_INFO, "Error with input parameters\n");
121  return 0;
122  }
123 
124 #ifdef _WIN32
125  return ni_logan_rsrc_enumerate_devices(ni_logan_devices, max_handles);
126 #else
127  /* list all XCoder devices under /dev/.. */
128  const char* dir_name = "/dev";
129  int i, xcoder_device_cnt = 0;
130  DIR* FD;
131  struct dirent* in_file;
132  ni_logan_device_info_t device_info;
133  ni_logan_device_capability_t device_capabilites;
134  ni_device_handle_t dev_handle = NI_INVALID_DEVICE_HANDLE;
136  uint32_t tmp_io_size;
137 
138  if (NULL == (FD = opendir(dir_name)))
139  {
140  ni_log(NI_LOG_ERROR, "Error %d: failed to open directory %s\n",
141  NI_ERRNO, dir_name);
142  return 0;
143  }
144 
145  /* collect all the available NVMe devices and sort */
146  while ((in_file = readdir(FD)))
147  {
149  if (!strcmp(in_file->d_name, ".") || !strcmp(in_file->d_name, ".."))
150  {
151  continue;
152  }
153 
154  /* pick only those files with name nvmeX where X consists of 1-n
155  digits */
156  size_t lenstr = strlen(in_file->d_name);
157  if (!strncmp(in_file->d_name, NI_LOGAN_NVME_PREFIX, strlen(NI_LOGAN_NVME_PREFIX)))
158  {
159  int i;
160  int skip_this = 0;
161  for (i = strlen(NI_LOGAN_NVME_PREFIX); i < lenstr; i++)
162  {
163 #ifdef XCODER_LINUX_VIRTIO_DRIVER_ENABLED
164  // In Linux virtual machine with VirtIO driver, the device name does not contain a number,
165  // for examples "vda", "vdb", etc.
166  if (isdigit(in_file->d_name[i]))
167 #else
168  if (!isdigit(in_file->d_name[i]))
169 #endif
170  {
171  skip_this = 1;
172  break;
173  }
174  }
175  if (skip_this == 0)
176  {
177  memset(&device_info, 0, sizeof(ni_logan_device_info_t));
178  sprintf(device_info.dev_name, "/dev/%s", in_file->d_name);
179  memset(&device_capabilites, 0, sizeof(ni_logan_device_capability_t));
180 
181  ni_logan_find_blk_name(device_info.dev_name, device_info.blk_name, sizeof(device_info.blk_name));
182  dev_handle = ni_logan_device_open(device_info.blk_name, &tmp_io_size);
183 
184  if (NI_INVALID_DEVICE_HANDLE != dev_handle)
185  {
186  rc = ni_logan_device_capability_query(dev_handle,&device_capabilites);
187  if (NI_LOGAN_RETCODE_SUCCESS == rc)
188  {
189  if (device_capabilites.device_is_xcoder)
190  {
191  ni_logan_devices[xcoder_device_cnt][0] = '\0';
192  strncat(ni_logan_devices[xcoder_device_cnt],
193  device_info.dev_name, strlen(device_info.dev_name));
194  xcoder_device_cnt++;
195  }
196  }
197  ni_logan_device_close(dev_handle);
198  }
199  }
200  }
201 
202  if ((LOGAN_MAX_DEVICE_CNT <= xcoder_device_cnt) || (max_handles <= xcoder_device_cnt))
203  {
204  ni_log(NI_LOG_INFO, "Disregarding some Netint devices on system over "
205  "limit of LOGAN_MAX_DEVICE_CNT(%d) or max_handles(%d)\n",
206  LOGAN_MAX_DEVICE_CNT, max_handles);
207  break;
208  }
209  }
210  closedir(FD);
211 
212  qsort(ni_logan_devices, xcoder_device_cnt, (size_t) NI_LOGAN_MAX_DEVICE_NAME_LEN, ni_logan_rsrc_strcmp);
213 
214  return xcoder_device_cnt;
215 #endif
216 }
217 
218 /*!*****************************************************************************
219  * \brief the card with the card name like /dev/nvme0n1 get the device index.
220  *
221  * \param[in] p_device_pool Pointer to a caller allocated ni_logan_device_pool_t
222  * \param[in] device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
223  * \param[in] devicename device name
224  *
225  * \return On success valid device index
226  * On failure -1
227  ******************************************************************************/
228 int ni_logan_find_device_index_by_name(void *device_coders,
229  ni_logan_device_type_t device_type,
230  const char *dev_name)
231 {
232  int hw_id = -1;
233  ni_logan_device_queue_t *coders = (ni_logan_device_queue_t *)device_coders;
234  ni_logan_device_context_t *p_device_context = NULL;
235  int *module_id_arr = NULL;
236  int module_count = 0;
237 
238  if (dev_name == NULL)
239  {
240  return -1;
241  }
242 
243  if (device_type == NI_LOGAN_DEVICE_TYPE_DECODER)
244  {
245  module_count = coders->decoders_cnt;
246  module_id_arr = (int *)malloc(sizeof(int) * module_count);
247  if (!module_id_arr)
248  {
249  ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for module_id_arr\n", NI_ERRNO);
250  return -1;
251  }
252  memcpy(module_id_arr, coders->decoders, sizeof(int) * module_count);
253  }
254  else if (device_type == NI_LOGAN_DEVICE_TYPE_ENCODER ||
255  device_type == NI_LOGAN_DEVICE_TYPE_UPLOAD)
256  {
257  module_count = coders->encoders_cnt;
258  module_id_arr = (int *)malloc(sizeof(int) * module_count);
259  if (!module_id_arr)
260  {
261  ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for module_id_arr\n", NI_ERRNO);
262  return -1;
263  }
264  memcpy(module_id_arr, coders->encoders, sizeof(int) * module_count);
265  }
266  else
267  {
268  ni_log(NI_LOG_ERROR, "ERROR: Unknown device type: %d\n", NI_ERRNO);
269  return -1;
270  }
271 
272  for (int i = 0; i < module_count; i++)
273  {
274  p_device_context = ni_logan_rsrc_get_device_context(device_type, module_id_arr[i]);
275  if (! p_device_context)
276  {
277  ni_log(NI_LOG_ERROR, "%s: Error get device resource, guid %d, device_type %d\n",
278  __func__, module_id_arr[i], device_type);
279  continue;
280  }
281 #ifdef _WIN32
282  if (!strcmp(p_device_context->p_device_info->dev_name, dev_name))
283 #else
284  if (!strcmp(p_device_context->p_device_info->dev_name, dev_name) ||
285  !strcmp(p_device_context->p_device_info->blk_name, dev_name))
286 #endif
287  {
288  hw_id = p_device_context->p_device_info->module_id;
289  ni_logan_rsrc_free_device_context(p_device_context);
290  break;
291  }
292  ni_logan_rsrc_free_device_context(p_device_context);
293  }
294 
295  free(module_id_arr);
296 
297  return hw_id;
298 }
299 
300 /*!*****************************************************************************
301  * \brief Create and return the allocated ni_logan_device_pool_t struct
302  *
303  * \param None
304  *
305  * \return Pointer to ni_logan_device_pool_t struct on success, or NULL on failure
306  *******************************************************************************/
308 {
309  ni_logan_device_queue_t* p_device_queue = NULL;
310  ni_logan_device_pool_t* p_device_pool = NULL;
311 
312 #ifdef _WIN32
313  HANDLE map_file_handle = NULL;
314  HANDLE mutex_handle = NULL;
315 
316  //Create a mutex for protecting the memory area
317  mutex_handle = CreateMutex(
318  NULL, // default security attributes
319  FALSE, // initially owned
320  CODERS_LCK_NAME // unnamed mutex
321  );
322 
323  if (NULL == mutex_handle)
324  {
325  ni_log(NI_LOG_INFO, "CreateMutex %s failed: %d\n",
327  return NULL;
328  }
329 
330  // no time-out interval) //we got the mutex
331  if (WAIT_ABANDONED == WaitForSingleObject(mutex_handle, INFINITE))
332  {
333  ni_log(NI_LOG_INFO, "ERROR: %s() failed to obtain mutex: %p\n", __FUNCTION__, mutex_handle);
334  }
335 
336  map_file_handle = OpenFileMapping(
337  FILE_MAP_ALL_ACCESS, // read/write access
338  FALSE, // do not inherit the name
339  CODERS_SHM_NAME // name of mapping object
340  );
341 
342  if (NULL == map_file_handle)
343  {
344  ReleaseMutex(mutex_handle);
345  ni_log(NI_LOG_INFO, "Could not open file mapping object %s, error: %d.\n",
347  return NULL;
348  }
349 
350  p_device_queue = (ni_logan_device_queue_t *)MapViewOfFile(
351  map_file_handle, // handle to map object
352  FILE_MAP_ALL_ACCESS, // read/write permission
353  0,
354  0,
355  sizeof(ni_logan_device_queue_t));
356 
357  if (NULL == p_device_queue)
358  {
359  ReleaseMutex(mutex_handle);
360  CloseHandle(map_file_handle);
361  return NULL;
362  }
363 
364  p_device_pool = (ni_logan_device_pool_t *)malloc(sizeof(ni_logan_device_pool_t));
365  if (NULL == p_device_pool)
366  {
367  ni_log(NI_LOG_ERROR, "ERROR %d: %s() malloc failed\n",
368  __FUNCTION__, NI_ERRNO);
369  UnmapViewOfFile(p_device_queue);
370  }
371  else
372  {
373  p_device_pool->lock = mutex_handle;
374  p_device_pool->p_device_queue = p_device_queue;
375  }
376 
377  ReleaseMutex(mutex_handle);
378  CloseHandle(map_file_handle);
379 #else
380  int shm_fd = -1;
381  ni_lock_handle_t lock;
382 
383 #ifdef __ANDROID__
384  char workDir[] = "/dev/shm_netint";
385  if (0 != access(workDir,0))
386  {
387  if (0 != mkdir(workDir,777))
388  {
389  ni_log(NI_LOG_ERROR, "Error create /dev/shm_netint folder...");
390  return NULL;
391  }
392  }
393 #endif
394  lock = open(CODERS_LCK_NAME, O_RDWR | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
395  if (lock < 0)
396  {
397  ni_log(NI_LOG_ERROR, "Error %d: open CODERS_LCK_NAME...\n", NI_ERRNO);
398  return NULL;
399  }
400  flock(lock, LOCK_EX);
401 
402 #ifdef __ANDROID__
404  int ret = ni_logan_rsrc_android_init();
405 
406  if (service_logan == NULL)
407  {
408  ni_log(NI_LOG_ERROR, "ni_logan_rsrc_get_device_pool Error service ..\n");
409  return NULL;
410  }
411  string param = CODERS_SHM_NAME;
412  Return<void> retvalue = service_logan->GetAppFlag(param, [&](int32_t ret, hidl_handle handle)
413  {
414  ni_log(NI_LOG_INFO, "GetAppFlag: ret %d\n", ret);
415  if (ret > 0)
416  {
417  shm_fd = dup(handle->data[0]);
418  ni_log(NI_LOG_INFO, "vendor:GetAppFlag shm_fd:%d\n", shm_fd);
419  }
420  else
421  {
422  ni_log(NI_LOG_ERROR, "Error %d: shm_get shm_fd ..\n", NI_ERRNO);
423  }
424  });
425  if (!retvalue.isOk())
426  {
427  ni_log(NI_LOG_ERROR, "service_logan->GetAppFlag ret failed ..\n");
428  LRETURN;
429  }
430  if (shm_fd < 0)
431  {
432  int fd = ashmem_create_region(CODERS_SHM_NAME, sizeof(ni_logan_device_queue_t));
433  if (fd >= 0)
434  {
435  native_handle_t *handle = native_handle_create(1, 0);
436  handle->data[0] = fd;
437  service_logan->SetAppFlag(param, handle);
438  shm_fd = dup(fd);
439  ni_log(NI_LOG_ERROR, "Create shm fd %d\n", shm_fd);
440  }
441  else
442  {
443  ni_log(NI_LOG_ERROR, "Error %d: shm_open SHM_CODERS ..\n", NI_ERRNO);
444  LRETURN;
445  }
446  }
447 #else
448  struct stat statbuf = { 0 };
449 
450  shm_fd = shm_open(CODERS_SHM_NAME, O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
451  if (shm_fd < 0)
452  {
453  ni_log(NI_LOG_ERROR, "Error %d: shm_open SHM_CODERS ..\n", NI_ERRNO);
454  LRETURN;
455  }
456 
457  // check CODERS_SHM_NAME file size
458  if (fstat(shm_fd, &statbuf) < 0)
459  {
460  ni_log(NI_LOG_ERROR, "Error %d: Could not to get CODERS_SHM_NAME file state\n",
461  NI_ERRNO);
462  LRETURN;
463  }
464  if (statbuf.st_size != sizeof(ni_logan_device_queue_t))
465  {
466  ni_log(NI_LOG_ERROR, "Error: CODERS_SHM_NAME size (%d) is not as expected (%d)\n",
467  statbuf.st_size, sizeof(ni_logan_device_queue_t));
468  LRETURN;
469  }
470 #endif
471 
472  p_device_queue = (ni_logan_device_queue_t*)mmap(0, sizeof(ni_logan_device_queue_t), PROT_READ | PROT_WRITE,
473  MAP_SHARED, shm_fd, 0);
474  if (MAP_FAILED == p_device_queue)
475  {
476  ni_log(NI_LOG_ERROR, "Error %d: mmap ni_logan_device_queue_t ..\n", NI_ERRNO);
477  LRETURN;
478  }
479 
480  if (p_device_queue->decoders_cnt > LOGAN_MAX_DEVICE_CNT ||
481  p_device_queue->encoders_cnt > LOGAN_MAX_DEVICE_CNT)
482  {
483  munmap(p_device_queue, sizeof(ni_logan_device_queue_t));
484  ni_log(NI_LOG_ERROR, "Error: CODERS_SHM_NAME decoders_cnt (%d) or encoders_cnt (%d) is out of range\n",
485  p_device_queue->decoders_cnt, p_device_queue->encoders_cnt);
486  LRETURN;
487  }
488 
489  p_device_pool = (ni_logan_device_pool_t *)malloc(sizeof(ni_logan_device_pool_t));
490  if (NULL == p_device_pool)
491  {
492  ni_log(NI_LOG_ERROR, "Error %d: malloc ..\n", NI_ERRNO);
493  munmap(p_device_queue, sizeof(ni_logan_device_queue_t));
494  }
495  else
496  {
497  p_device_pool->lock = lock;
498  p_device_pool->p_device_queue = p_device_queue;
499  }
500 
501  END:
502 
503  flock(lock, LOCK_UN);
504 
505  if (NULL == p_device_pool)
506  {
507  close(lock);
508  }
509 
510  if (shm_fd >= 0)
511  {
512  close(shm_fd);
513  }
514 #endif
515  return p_device_pool;
516 }
517 
518 /*!******************************************************************************
519  * \brief Initialize and create all resources required to work with NETINT NVMe
520  * transcoder devices. This is a high level API function which is used
521  * mostly with user application like FFMpeg that relies on those resources.
522  * In case of custom application integration, revised functionality might
523  * be necessary utilizing corresponding API functions.
524  *
525  * \param[in] should_match_rev 0: transcoder firmware revision matching the
526  * * library's version is NOT required for
527  * placing the transcoder into resource pool
528  * 1: init all fully compatible and partially
529  * compatible cards, skipping non-compatible
530  * cards
531  * 2: init cards only if all detected cards are
532  * fully compatible
533  * timeout_seconds 0: No timeout amount, loop until init success
534  * or fail; else: timeout will fail init once reached
535  *
536  * \return
537  * NI_LOGAN_RETCODE_SUCCESS on success
538  * NI_LOGAN_RETCODE_INIT_ALREADY on already init
539  * NI_LOGAN_RETCODE_FAILURE on failure
540  *
541  *******************************************************************************/
542 int ni_logan_rsrc_init(int should_match_rev, int timeout_seconds)
543 {
544 #define SLEEPLOOP 3
546  char dev_names[LOGAN_MAX_DEVICE_CNT][NI_LOGAN_MAX_DEVICE_NAME_LEN] = { 0 };
547  int i = 0, j = 0, k = 0, xcoder_device_cnt = 0, compat_xcoder_device_cnt = 0,\
548  fw_ver_compat_warning = 0, runtime = 0, retval = NI_LOGAN_RETCODE_SUCCESS;
549  uint32_t tmp_io_size;
550  ni_lock_handle_t lock = NI_INVALID_DEVICE_HANDLE;
551  ni_lock_handle_t lock_enc = NI_INVALID_DEVICE_HANDLE;
552  ni_lock_handle_t lock_dec = NI_INVALID_DEVICE_HANDLE;
553  ni_logan_device_info_t device_info = { 0 };
554  ni_logan_device_info_t* p_device_info = NULL;
555  ni_logan_device_queue_t* p_device_queue = NULL;
556  ni_logan_device_capability_t device_capabilites = { 0 };
557  ni_device_handle_t dev_handle = NI_INVALID_DEVICE_HANDLE;
558 
559 #ifdef _WIN32
560  DWORD rc = 0;
561  HANDLE map_file_handle = NULL;
562 
563  map_file_handle = CreateFileMapping(
564  INVALID_HANDLE_VALUE, // use paging file
565  NULL, // default security
566  PAGE_READWRITE, // read/write access
567  0, // maximum object size (high-order DWORD)
568  sizeof(ni_logan_device_queue_t),// maximum object size (low-order DWORD)
569  CODERS_SHM_NAME // name of mapping object
570  );
571 
572  if (NULL == map_file_handle)
573  {
574  rc = NI_ERRNO;
575  ni_log(NI_LOG_INFO, "CreateFileMapping returned (%d).\n", rc);
576  retval = NI_LOGAN_RETCODE_FAILURE;
577  LRETURN;
578  }
579  else
580  {
581  rc = NI_ERRNO;
582  if (ERROR_ALREADY_EXISTS == rc)
583  {
584  ni_log(NI_LOG_INFO, "NETINT resources have been initialized already, exiting ..\n");
586  LRETURN;
587  }
588  else
589  {
590  ni_log(NI_LOG_INFO, "NETINT resources not initialized, starting initialization ..\n");
591  }
592  }
593 
594  while (0 == xcoder_device_cnt)
595  {
596  xcoder_device_cnt = ni_logan_rsrc_enumerate_devices(dev_names, LOGAN_MAX_DEVICE_CNT);
597  if (xcoder_device_cnt < 0)
598  {
599  ni_log(NI_LOG_INFO, "ni_logan_rsrc_init() fatal error %d, exiting ...\n", xcoder_device_cnt);
600  retval = NI_LOGAN_RETCODE_FAILURE;
601  LRETURN;
602  }
603  else if (0 == xcoder_device_cnt)
604  {
605  ni_log(NI_LOG_INFO, "Devices not ready, will retry again ...\n");
607  {
608  ni_log(NI_LOG_INFO, "Requested to stop, exiting ...\n");
609  retval = NI_LOGAN_RETCODE_FAILURE;
610  LRETURN;
611  }
612  if (runtime >= timeout_seconds && timeout_seconds != 0)
613  {
614  ni_log(NI_LOG_INFO, "Timeout reached at %d seconds! Failing\n", runtime);
615  retval = NI_LOGAN_RETCODE_FAILURE;
616  LRETURN;
617  }
618  runtime += SLEEPLOOP;
619  Sleep(SLEEPLOOP * 1000);
620  }
621  }
622 
627  p_device_queue = (ni_logan_device_queue_t*)MapViewOfFile(
628  map_file_handle, // handle to map object
629  FILE_MAP_ALL_ACCESS, // read/write permission
630  0,
631  0,
633  );
634 
635  if (NULL == p_device_queue)
636  {
637  ni_log(NI_LOG_INFO, "Could not map view of file, p_last error (%d).\n", NI_ERRNO);
638  retval = NI_LOGAN_RETCODE_FAILURE;
639  LRETURN;
640  }
641 
643  lock = CreateMutex(
644  NULL, // default security attributes
645  FALSE, // initially owned
646  CODERS_LCK_NAME // unnamed mutex
647  );
648  if (NULL == lock)
649  {
650  ni_log(NI_LOG_INFO, "Init CreateMutex %s failed: %d\n", CODERS_LCK_NAME, NI_ERRNO);
651  retval = NI_LOGAN_RETCODE_FAILURE;
652  LRETURN;
653  }
654 
655  if (WAIT_ABANDONED == WaitForSingleObject(lock, INFINITE)) // no time-out interval)
656  {
657  ni_log(NI_LOG_INFO, "ERROR %d: failed to obtain mutex: %p\n", NI_ERRNO, lock);
658  retval = NI_LOGAN_RETCODE_FAILURE;
659  LRETURN;
660  }
661 
662  // init the ni_logan_device_queue_t
663  p_device_queue->decoders_cnt = p_device_queue->encoders_cnt = 0;
664 
665  for (i = 0; i < LOGAN_MAX_DEVICE_CNT; i++)
666  {
667  p_device_queue->decoders[i] = -1;
668  }
669 
670  for (i = 0; i < LOGAN_MAX_DEVICE_CNT; i++)
671  {
672  p_device_queue->encoders[i] = -1;
673  }
674 
675  // For should_match_rev==2, detect version mismatch and return INCOMPATIBLE
676  // if not all T4XX cards on the machine is fully compatible
677  if (should_match_rev == 2)
678  {
679  for (i = 0; i < xcoder_device_cnt; i++)
680  {
684  memset(&device_info, 0, sizeof(ni_logan_device_info_t));
685  snprintf(device_info.dev_name, NI_LOGAN_MAX_DEVICE_NAME_LEN, "%s", dev_names[i]);
686  ni_logan_find_blk_name(device_info.dev_name, device_info.blk_name, sizeof(device_info.blk_name));
687  memset(&device_capabilites, 0, sizeof(ni_logan_device_capability_t));
688 
689  dev_handle = ni_logan_device_open(device_info.dev_name, &tmp_io_size);
690  if (NI_INVALID_DEVICE_HANDLE == dev_handle)
691  {
692  continue;
693  }
694 
695  rc = ni_logan_device_capability_query(dev_handle, &device_capabilites);
696  if (!rc && !ni_logan_is_fw_compatible(device_capabilites.fw_rev))
697  {
698  ni_logan_device_close(dev_handle);
699  ni_log(NI_LOG_INFO, "Error: not all T4XX cards contain fully "
700  "compatible FW. Not initializing any \n"
701  "cards.\n");
703  LRETURN;
704  }
705  ni_logan_device_close(dev_handle);
706  }
707  }
708 
709  for (i = 0; i < xcoder_device_cnt; i++)
710  {
714  snprintf(device_info.dev_name, NI_LOGAN_MAX_DEVICE_NAME_LEN, "%s", dev_names[i]);
715  ni_logan_find_blk_name(device_info.dev_name, device_info.blk_name, sizeof(device_info.blk_name));
716  memset(&device_capabilites, 0, sizeof(ni_logan_device_capability_t));
717 
718  dev_handle = ni_logan_device_open(device_info.dev_name, &tmp_io_size);
719  if (NI_INVALID_DEVICE_HANDLE == dev_handle)
720  {
721  continue;
722  }
723 
724  retval = ni_logan_device_capability_query(dev_handle, &device_capabilites);
725  if ((NI_LOGAN_RETCODE_SUCCESS == retval) &&
726  (device_capabilites.device_is_xcoder) &&
727  (! should_match_rev ||
728  (should_match_rev && ni_logan_is_fw_compatible(device_capabilites.fw_rev))))
729  {
730  fw_ver_compat_warning = 0;
731  if (ni_logan_is_fw_compatible(device_capabilites.fw_rev) == 2)
732  {
733  ni_log(NI_LOG_INFO, "WARNING - Query %s FW version: %.*s is below the minimum support version for "
734  "this SW version. Some features may be missing.\n",
735  device_info.dev_name, (int) sizeof(device_capabilites.fw_rev),
736  device_capabilites.fw_rev);
737  fw_ver_compat_warning = 1;
738  }
739  int total_modules = device_capabilites.h264_decoders_cnt + device_capabilites.h264_encoders_cnt +
740  device_capabilites.h265_decoders_cnt + device_capabilites.h265_encoders_cnt;
741 
742  for (j = 0; j < total_modules; j++)
743  {
744  p_device_info = NULL;
745  memset(&device_info, 0, sizeof(ni_logan_device_info_t));
746  snprintf(device_info.dev_name, NI_LOGAN_MAX_DEVICE_NAME_LEN, "%s", dev_names[i]);
747  ni_logan_find_blk_name(device_info.dev_name, device_info.blk_name, sizeof(device_info.blk_name));
748 
749  device_info.hw_id = device_capabilites.xcoder_devices[j].hw_id;
750  device_info.fw_ver_compat_warning = fw_ver_compat_warning;
751  memcpy(device_info.fw_rev, device_capabilites.fw_rev,
752  sizeof(device_info.fw_rev));
753  memcpy(device_info.fw_commit_hash, device_capabilites.fw_commit_hash,
754  sizeof(device_info.fw_commit_hash) - 1);
755  memcpy(device_info.fw_commit_time, device_capabilites.fw_commit_time,
756  sizeof(device_info.fw_commit_time) - 1);
757  memcpy(device_info.fw_branch_name, device_capabilites.fw_branch_name,
758  sizeof(device_info.fw_branch_name) - 1);
759  device_info.max_fps_1080p = device_capabilites.xcoder_devices[j].max_1080p_fps;
760  device_info.max_instance_cnt = device_capabilites.xcoder_devices[j].max_number_of_contexts;
761  device_info.device_type = (ni_logan_device_type_t)device_capabilites.xcoder_devices[j].codec_type;
762 
763  int device_cnt_so_far = (NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type ?
764  p_device_queue->decoders_cnt : p_device_queue->encoders_cnt);
765  int tmp_guid = -1;
766 
767  // check if entry has been created for this h/w (hw_id):
768  // if not, then create a new entry; otherwise just update it
769  for (k = 0; k < device_cnt_so_far; k++)
770  {
771  tmp_guid = (NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type ?
772  p_device_queue->decoders[k] : p_device_queue->encoders[k]);
773  ni_logan_device_context_t* p_device_context = ni_logan_rsrc_get_device_context(device_info.device_type, tmp_guid);
774  if ( (p_device_context) && (strcmp(p_device_context->p_device_info->dev_name, device_info.dev_name) == 0 ) &&
775  (p_device_context->p_device_info->hw_id == device_info.hw_id) )
776  {
777  p_device_info = p_device_context->p_device_info;
778  break;
779  }
780  ni_logan_rsrc_free_device_context(p_device_context);
781  }
782 
783  ni_codec_t fmt = (ni_codec_t)device_capabilites.xcoder_devices[j].codec_format;
784 
785  if (p_device_info)
786  {
787  ni_log(NI_LOG_INFO, "%s h/w id %d update\n", NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type ?
788  "decoder" : "encoder", device_info.hw_id);
789  retval = ni_logan_rsrc_fill_device_info(p_device_info, fmt, device_info.device_type,
790  &device_capabilites.xcoder_devices[j]);
791  }
792  else
793  {
794  ni_log(NI_LOG_INFO, "%s h/w id %d create\n", NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type ?
795  "decoder" : "encoder", device_info.hw_id);
796  p_device_info = &device_info;
797 
798  retval = ni_logan_rsrc_fill_device_info(p_device_info, fmt, device_info.device_type,
799  &device_capabilites.xcoder_devices[j]);
800 
801  if (NI_LOGAN_RETCODE_SUCCESS == retval)
802  {
804  if (NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type)
805  {
806  p_device_info->module_id = decoder_guid++;
807  p_device_queue->decoders_cnt = decoder_guid;
808  p_device_queue->decoders[p_device_info->module_id] = p_device_info->module_id;
809  }
810  else
811  {
812  p_device_info->module_id = encoder_guid++;
813  p_device_queue->encoders_cnt = encoder_guid;
814  p_device_queue->encoders[p_device_info->module_id] = p_device_info->module_id;
815  }
816  ni_logan_rsrc_get_one_device_info(&device_info);
817  }
818  }
819  }
820  }
821  else
822  {
823  ni_log(NI_LOG_INFO, "Query %s rc %d NOT xcoder-support: %u, or mismatch revision: "
824  "%s; Not added\n", device_info.dev_name, retval,
825  device_capabilites.device_is_xcoder,
826  device_capabilites.fw_rev);
827  }
828 
829  ni_logan_device_close(dev_handle);
830  }
832  p_device_queue->decoders_cnt = decoder_guid;
833  p_device_queue->encoders_cnt = encoder_guid;
834 
835  retval = NI_LOGAN_RETCODE_SUCCESS;
836 
837 END:
838 
839  if (NI_LOGAN_RETCODE_SUCCESS != retval)
840  {
841  if (NULL != p_device_queue)
842  {
843  UnmapViewOfFile(p_device_queue);
844  }
845  if (NULL != map_file_handle)
846  {
847  CloseHandle(map_file_handle);
848  }
849  if (NULL != lock)
850  {
851  ReleaseMutex(lock);
852  CloseHandle(lock);
853  }
854  }
855  else
856  {
857  UnmapViewOfFile(p_device_queue);
858  ReleaseMutex(lock);
859  CloseHandle(lock);
860  }
861 #else
862  DIR* FD;
863  struct dirent* in_file;
864  const char* dir_name = "/dev";
866 
867 #ifdef __ANDROID__
869  int ret = ni_logan_rsrc_android_init();
870 
871  char workDir[] = "/dev/shm_netint";
872  if (0 != access(workDir,0))
873  {
874  if (0 != mkdir(workDir,777))
875  {
876  perror("Error create /dev/shm_netint folder...");
877  return 1;
878  }
879  }
880 
881  if (service_logan == NULL)
882  {
883  ni_log(NI_LOG_ERROR, "ni_logan_rsrc_init 000 Error service ..\n");
885  }
886  int32_t shm_fd = -1;
887  string param = CODERS_SHM_NAME;
888  Return<void> retvalue = service_logan->GetAppFlag(param, [&](int32_t ret, hidl_handle handle)
889  {
890  ni_log(NI_LOG_INFO, "GetAppFlag: ret %d\n", ret);
891  if (ret > 0)
892  {
893  shm_fd = dup(handle->data[0]);
894  ni_log(NI_LOG_INFO, "vendor:GetAppFlag shm_fd:%d\n", shm_fd);
895  }
896  else
897  {
898  ni_log(NI_LOG_ERROR, "Error %d: shm_get shm_fd ..\n", NI_ERRNO);
899  }
900  });
901  if (!retvalue.isOk())
902  {
903  ni_log(NI_LOG_ERROR, "service_logan->GetAppFlag ret failed ..\n");
905  }
906  if (shm_fd < 0)
907  {
908  int fd = ashmem_create_region(CODERS_SHM_NAME, sizeof(ni_logan_device_queue_t));
909  if (fd >= 0)
910  {
911  native_handle_t *handle = native_handle_create(1, 0);
912  handle->data[0] = fd;
913  service_logan->SetAppFlag(param, handle);
914  shm_fd = dup(fd);
915  ni_log(NI_LOG_ERROR, "Create shm fd %d\n", shm_fd);
916  }
917  }
918 
919  if (shm_fd >= 0)
920  {
921  close(shm_fd);
922  }
923 #else
924  int shm_fd = shm_open(CODERS_SHM_NAME, O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
925  if (shm_fd >= 0)
926  {
927  ni_log(NI_LOG_INFO, "NI resource init'd already ..\n");
928  close(shm_fd);
930  }
931  else
932  {
933  if (ENOENT == NI_ERRNO)
934  {
935  ni_log(NI_LOG_INFO, "NI resource not init'd, continue ..\n");
936  }
937  else
938  {
939  ni_log(NI_LOG_ERROR, "Error access to NI resources, check privileges ..\n");
941  }
942  }
943 #endif
944 
945 read_dev_files:
946  xcoder_device_cnt = ni_logan_rsrc_get_local_device_list(dev_names, LOGAN_MAX_DEVICE_CNT);
947 
948  if (xcoder_device_cnt == 0)
949  {
950  ni_log(NI_LOG_INFO, "NVMe Devices not ready, wait ..\n");
952  {
953  ni_log(NI_LOG_INFO, "Requested to stop ..\n");
955  }
956 
957  if (runtime >= timeout_seconds && timeout_seconds != 0)
958  {
959  ni_log(NI_LOG_INFO, "Timeout reached at %d seconds! Failing\n", runtime);
961  }
962  runtime += SLEEPLOOP;
963  sleep(SLEEPLOOP);
964  goto read_dev_files;
965  }
966 
968  ni_log(NI_LOG_INFO, "Libxcoder SW ver: %s\n", NI_LOGAN_XCODER_REVISION);
969  ni_log(NI_LOG_INFO, "Compatible minimum FW ver: %s, FW API flavors: %s, minimum API ver: %d\n",
973 
978  ni_log(NI_LOG_INFO, "Creating shm_name: %s lck_name: %s\n", CODERS_SHM_NAME, CODERS_LCK_NAME);
979 
980 #ifdef __ANDROID__
983 
984  if (service_logan == NULL)
985  {
986  ni_log(NI_LOG_ERROR, "ni_logan_rsrc_init 111 Error service ..\n");
988  }
989  param = CODERS_SHM_NAME;
990  retvalue = service_logan->GetAppFlag(param, [&](int32_t ret, hidl_handle handle)
991  {
992  ni_log(NI_LOG_INFO, "GetAppFlag: ret %d\n", ret);
993  if (ret > 0)
994  {
995  shm_fd = dup(handle->data[0]);
996  ni_log(NI_LOG_INFO, "vendor:GetAppFlag shm_fd:%d\n", shm_fd);
997  }
998  else
999  {
1000  ni_log(NI_LOG_ERROR, "Error %d: shm_get shm_fd ..\n", NI_ERRNO);
1001  }
1002  });
1003  if (!retvalue.isOk())
1004  {
1005  ni_log(NI_LOG_ERROR, "service_logan->GetAppFlag ret failed ..\n");
1006  return NI_LOGAN_RETCODE_FAILURE;
1007  }
1008  if (shm_fd < 0)
1009  {
1010  int fd = ashmem_create_region(CODERS_SHM_NAME, sizeof(ni_logan_device_queue_t));
1011  if (fd >= 0)
1012  {
1013  native_handle_t *handle = native_handle_create(1, 0);
1014  handle->data[0] = fd;
1015  service_logan->SetAppFlag(param, handle);
1016  shm_fd = dup(fd);
1017  ni_log(NI_LOG_ERROR, "Create shm fd %d\n", shm_fd);
1018  }
1019  }
1020 #else
1021  shm_fd = shm_open(CODERS_SHM_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1022 #endif
1023 
1024  if (shm_fd < 0)
1025  {
1026  ni_log(NI_LOG_ERROR, "Error %d: shm_open ..\n", NI_ERRNO);
1027  return NI_LOGAN_RETCODE_FAILURE;
1028  }
1029 
1030 #ifndef __ANDROID__
1031  if (ftruncate(shm_fd, sizeof(ni_logan_device_queue_t)) < 0)
1032  {
1033  ni_log(NI_LOG_ERROR, "Error ftruncate ..\n");
1034  //TODO: Return without closing the shared memory file descriptor flose(shm_fd)!!!
1035  return NI_LOGAN_RETCODE_FAILURE;
1036  }
1037 #endif
1038 
1039  p_device_queue = (ni_logan_device_queue_t*)mmap(0, sizeof(ni_logan_device_queue_t), PROT_READ | PROT_WRITE,
1040  MAP_SHARED, shm_fd, 0);
1041  if (MAP_FAILED == p_device_queue)
1042  {
1043  ni_log(NI_LOG_ERROR, "Error %d: mmap ni_logan_device_queue_t ... trouble ..\n", NI_ERRNO);
1044  //TODO: Return without closing the shared memory file descriptor flose(shm_fd)!!!
1045  return NI_LOGAN_RETCODE_FAILURE;
1046  }
1047 
1048  if (shm_fd >= 0)
1049  {
1050  close(shm_fd);
1051  }
1052 
1054  lock = open(CODERS_LCK_NAME, O_RDWR | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1055  if (lock < 0)
1056  {
1057  ni_log(NI_LOG_ERROR, "Error %d: open lock file ....\n", NI_ERRNO);
1058  //TODO: Return without umappint the shared memory munmap(p_device_queue)!!!
1059  retval = NI_LOGAN_RETCODE_FAILURE;
1060  LRETURN;
1061  }
1062 
1064  lock_enc = open(CODERS_RETRY_ENLCK_NAME, O_RDWR | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1065  if (lock_enc < 0)
1066  {
1067  ni_log(NI_LOG_ERROR, "Error %d: open lock file ....\n", NI_ERRNO);
1068  //TODO: Return without umappint the shared memory munmap(p_device_queue)!!!
1069  retval = NI_LOGAN_RETCODE_FAILURE;
1070  LRETURN;
1071  }
1073  lock_dec = open(CODERS_RETRY_DELCK_NAME, O_RDWR | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1074  if (lock_dec < 0)
1075  {
1076  ni_log(NI_LOG_ERROR, "Error %d: open lock file ....\n", NI_ERRNO);
1077  //TODO: Return without umappint the shared memory munmap(p_device_queue)!!!
1078  retval = NI_LOGAN_RETCODE_FAILURE;
1079  LRETURN;
1080  }
1081 
1082  flock(lock, LOCK_EX);
1083 
1084  // init the ni_logan_device_queue_t
1085  p_device_queue->decoders_cnt = p_device_queue->encoders_cnt = 0;
1086  for (i = 0; i < LOGAN_MAX_DEVICE_CNT; i++)
1087  {
1088  p_device_queue->decoders[i] = -1;
1089  }
1090  for (i = 0; i < LOGAN_MAX_DEVICE_CNT; i++)
1091  {
1092  p_device_queue->encoders[i] = -1;
1093  }
1094 
1095  // For should_match_rev==2, detect version mismatch and return INCOMPATIBLE
1096  // if not all T4XX cards on the machine is fully compatible
1097  if (should_match_rev == 2)
1098  {
1099  for (i = 0; i < xcoder_device_cnt; i++)
1100  {
1104  memset(&device_info, 0, sizeof(ni_logan_device_info_t));
1105  strncpy(device_info.dev_name, dev_names[i],
1107  memset(&device_capabilites, 0, sizeof(ni_logan_device_capability_t));
1108 
1109  ni_logan_find_blk_name(device_info.dev_name, device_info.blk_name,
1110  sizeof(device_info.blk_name));
1111  dev_handle = ni_logan_device_open(device_info.blk_name, &tmp_io_size);
1112 
1113  rc = ni_logan_device_capability_query(dev_handle,
1114  &device_capabilites);
1115  if (!rc && !ni_logan_is_fw_compatible(device_capabilites.fw_rev))
1116  {
1117  ni_logan_device_close(dev_handle);
1118  flock(lock, LOCK_UN);
1119  ni_log(NI_LOG_INFO, "Error: not all T4XX cards contain fully "
1120  "compatible FW. Not initializing any \n"
1121  "cards.\n");
1123  LRETURN;
1124  }
1125  ni_logan_device_close(dev_handle);
1126  }
1127  }
1128 
1129  for (i = 0; i < xcoder_device_cnt; i++)
1130  {
1131  ni_log(NI_LOG_INFO, "%d. %s\n", i, dev_names[i]);
1132 
1136  memset(&device_info, 0, sizeof(ni_logan_device_info_t));
1137  strncpy(device_info.dev_name, dev_names[i], NI_LOGAN_MAX_DEVICE_NAME_LEN);
1138  memset(&device_capabilites, 0, sizeof(ni_logan_device_capability_t));
1139 
1140  ni_logan_find_blk_name(device_info.dev_name, device_info.blk_name, sizeof(device_info.blk_name));
1141  dev_handle = ni_logan_device_open(device_info.blk_name, &tmp_io_size);
1142 
1143  if (NI_INVALID_DEVICE_HANDLE != dev_handle)
1144  {
1145  rc = ni_logan_device_capability_query(dev_handle, &device_capabilites);
1146  if ((NI_LOGAN_RETCODE_SUCCESS == rc) &&
1147  (device_capabilites.device_is_xcoder) &&
1148  (should_match_rev && ni_logan_is_fw_compatible(device_capabilites.fw_rev)))
1149  {
1150  fw_ver_compat_warning = 0;
1151  if (ni_logan_is_fw_compatible(device_capabilites.fw_rev) == 2)
1152  {
1153  ni_log(NI_LOG_INFO, "WARNING - Query %s %s FW version: %.*s is below the minimum support version for "
1154  "this SW version. Some features may be missing.\n",
1155  device_info.dev_name,
1156  device_info.blk_name,
1157  (int) sizeof(device_capabilites.fw_rev),
1158  device_capabilites.fw_rev);
1159  fw_ver_compat_warning = 1;
1160  }
1161 
1162  int total_modules = device_capabilites.h264_decoders_cnt + device_capabilites.h264_encoders_cnt +
1163  device_capabilites.h265_decoders_cnt + device_capabilites.h265_encoders_cnt;
1164 
1165  ni_logan_device_info_t* p_device_info = NULL;
1166 
1167  for (j = 0; j < total_modules; j++)
1168  {
1169  p_device_info = NULL;
1170 
1171  memset(&device_info, 0, sizeof(ni_logan_device_info_t));
1172  strncpy(device_info.dev_name, dev_names[i], NI_LOGAN_MAX_DEVICE_NAME_LEN);
1173  ni_logan_find_blk_name(device_info.dev_name, device_info.blk_name, sizeof(device_info.blk_name));
1174  device_info.hw_id = device_capabilites.xcoder_devices[j].hw_id;
1175  device_info.fw_ver_compat_warning = fw_ver_compat_warning;
1176  memcpy(device_info.fw_rev, device_capabilites.fw_rev,
1177  sizeof(device_info.fw_rev));
1178  memcpy(device_info.fw_commit_hash, device_capabilites.fw_commit_hash,
1179  sizeof(device_info.fw_commit_hash) - 1);
1180  memcpy(device_info.fw_commit_time, device_capabilites.fw_commit_time,
1181  sizeof(device_info.fw_commit_time) - 1);
1182  memcpy(device_info.fw_branch_name, device_capabilites.fw_branch_name,
1183  sizeof(device_info.fw_branch_name) - 1);
1184  device_info.max_fps_1080p = device_capabilites.xcoder_devices[j].max_1080p_fps;
1185  device_info.max_instance_cnt = device_capabilites.xcoder_devices[j].max_number_of_contexts;
1186  device_info.device_type = (ni_logan_device_type_t)device_capabilites.xcoder_devices[j].codec_type;
1187 
1188  int device_cnt_so_far = (NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type ?
1189  p_device_queue->decoders_cnt : p_device_queue->encoders_cnt);
1190  int tmp_guid = -1;
1191  // check if entry has been created for this h/w (hw_id):
1192  // if not, then create a new entry; otherwise just update it
1193  for (k = 0; k < device_cnt_so_far; k++)
1194  {
1195  tmp_guid = (NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type ?
1196  p_device_queue->decoders[k] : p_device_queue->encoders[k]);
1197  ni_logan_device_context_t* p_device_context = ni_logan_rsrc_get_device_context(device_info.device_type, tmp_guid);
1198  if (p_device_context && strcmp(p_device_context->p_device_info->dev_name, device_info.dev_name) == 0 &&
1199  p_device_context->p_device_info->hw_id == device_info.hw_id)
1200  {
1201  p_device_info = p_device_context->p_device_info;
1202  break;
1203  }
1204  ni_logan_rsrc_free_device_context(p_device_context);
1205  }
1206 
1207  ni_codec_t fmt = (ni_codec_t)device_capabilites.xcoder_devices[j].codec_format;
1208  int rc;
1209 
1210  if (p_device_info)
1211  {
1212  ni_log(NI_LOG_INFO, "%s h/w id %d update\n", NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type ?
1213  "decoder" : "encoder", device_info.hw_id);
1214  rc = ni_logan_rsrc_fill_device_info(p_device_info, fmt, device_info.device_type,
1215  &device_capabilites.xcoder_devices[j]);
1216  }
1217  else
1218  {
1219  ni_log(NI_LOG_INFO, "%s h/w id %d create\n", NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type ?
1220  "decoder" : "encoder", device_info.hw_id);
1221  p_device_info = &device_info;
1222 
1223  rc = ni_logan_rsrc_fill_device_info(p_device_info, fmt, device_info.device_type,
1224  &device_capabilites.xcoder_devices[j]);
1225 
1226  if (rc == 0)
1227  {
1229  if (NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type)
1230  {
1231  p_device_info->module_id = decoder_guid++;
1232  p_device_queue->decoders_cnt = decoder_guid;
1233  p_device_queue->decoders[p_device_info->module_id] = p_device_info->module_id;
1234  }
1235  else
1236  {
1237  p_device_info->module_id = encoder_guid++;
1238  p_device_queue->encoders_cnt = encoder_guid;
1239  p_device_queue->encoders[p_device_info->module_id] = p_device_info->module_id;
1240  }
1241  ni_logan_rsrc_get_one_device_info(&device_info);
1242  }
1243  }
1244 
1245  }
1246  compat_xcoder_device_cnt++;
1247  }
1248  else
1249  {
1250  ni_log(NI_LOG_INFO, "Device %s not added as it is not an xcoder, or has incompatible FW rev: %s\n",
1251  device_info.dev_name,
1252  device_capabilites.fw_rev);
1253  }
1254 
1255  ni_logan_device_close(dev_handle);
1256  if (LOGAN_MAX_DEVICE_CNT <= compat_xcoder_device_cnt)
1257  {
1258  ni_log(NI_LOG_INFO, "Disregarding some compatible Netint devices on "
1259  "system over limit of LOGAN_MAX_DEVICE_CNT(%d)\n",
1261  break;
1262  }
1263  }
1264  }
1266  p_device_queue->decoders_cnt = decoder_guid;
1267  p_device_queue->encoders_cnt = encoder_guid;
1268 
1269  //ni_log(NI_LOG_INFO, "About to return from ni_logan_rsrc_init()\n");
1270 
1271  flock(lock, LOCK_UN);
1272 
1273  retval = xcoder_device_cnt;
1274 
1275 END:
1276 
1277  if (lock >= 0)
1278  {
1279  close(lock);
1280  }
1281  if (lock_enc >= 0)
1282  {
1283  close(lock_enc);
1284  }
1285  if (lock_dec >= 0)
1286  {
1287  close(lock_dec);
1288  }
1289 #endif
1290 
1291  return retval;
1292 }
1293 
1294 
1295 // return 1 if string key is found in array of strings, 0 otherwise
1296 static int is_str_in_str_array(const char key[],
1297  char arr[][NI_LOGAN_MAX_DEVICE_NAME_LEN],
1298  int array_size)
1299 {
1300  int found = 0, i;
1301 
1302  for (i = 0; i < array_size; i++)
1303  {
1304  if (0 == strcmp(key, arr[i]))
1305  {
1306  found = 1;
1307  break;
1308  }
1309  }
1310  return found;
1311 }
1312 
1313 /*!*****************************************************************************
1314  * \brief Scan and refresh all resources on the host, taking into account
1315  * hot-plugged and pulled out cards.
1316  *
1317  * \param[in] should_match_rev 0: transcoder firmware revision matching the
1318  * library's version is NOT required for placing
1319  * the transcoder into resource pool; 1: otherwise
1320  *
1321  * \return
1322  * NI_LOGAN_RETCODE_SUCCESS on success
1323  * NI_LOGAN_RETCODE_FAILURE on failure
1324  *
1325  ******************************************************************************/
1327 {
1328  char xcoder_dev_names[LOGAN_MAX_DEVICE_CNT][NI_LOGAN_MAX_DEVICE_NAME_LEN] = {0};
1329  int xcoder_dev_count = 0;
1330  char curr_dev_names[LOGAN_MAX_DEVICE_CNT][NI_LOGAN_MAX_DEVICE_NAME_LEN] = {0};
1331  int curr_dev_count = 0;
1333  int i = 0;
1334  // Store ni_logan_device_t in heap as it is ~450KB
1335  ni_logan_device_t *saved_coders = (ni_logan_device_t*) malloc(sizeof(ni_logan_device_t));
1336  if (NULL == saved_coders) {
1337  ni_log(NI_LOG_ERROR, "Error failed to malloc ni_logan_device_t\n");
1338  retval = NI_LOGAN_RETCODE_FAILURE;
1339  LRETURN;
1340  }
1341  memset(saved_coders, 0, sizeof(ni_logan_device_t));
1342 
1343  // retrieve saved info from resource pool at start up
1346  {
1347  // check if the decoder count equals to the encoder count
1348  if (saved_coders->decoders_cnt == saved_coders->encoders_cnt)
1349  {
1350  xcoder_dev_count = saved_coders->decoders_cnt;
1351  ni_log(NI_LOG_INFO, "%d devices retrieved from current pool at start up\n",
1352  xcoder_dev_count);
1353  }
1354  else
1355  {
1356  retval = NI_LOGAN_RETCODE_FAILURE;
1357  ni_log(NI_LOG_ERROR, "Error decoder count %d doesn't equal to encoder count %d\n",
1358  saved_coders->decoders_cnt, saved_coders->encoders_cnt);
1359  LRETURN;
1360  }
1361 
1362  // check the device name
1363  for (i = 0; i < saved_coders->decoders_cnt; i++)
1364  {
1365  if (0 == strcmp(saved_coders->decoders[i].dev_name, saved_coders->encoders[i].dev_name))
1366  {
1367  xcoder_dev_names[i][0] = '\0';
1368  strncat(xcoder_dev_names[i], saved_coders->decoders[i].dev_name, strlen(saved_coders->decoders[i].dev_name));
1369  }
1370  else
1371  {
1372  retval = NI_LOGAN_RETCODE_FAILURE;
1373  ni_log(NI_LOG_ERROR, "Error the names of the encoding(%s) and decoding(%s) devices don't match, Index:%d\n",
1374  saved_coders->decoders[i].dev_name, saved_coders->encoders[i].dev_name, i);
1375  LRETURN;
1376  }
1377  }
1378  }
1379  else
1380  {
1381  retval = NI_LOGAN_RETCODE_FAILURE;
1382  ni_log(NI_LOG_INFO, "Error retrieving from current pool at start up\n");
1383  LRETURN;
1384  }
1385 
1386  curr_dev_count = ni_logan_rsrc_get_local_device_list(curr_dev_names,
1388  // remove from resource pool any device that is not available now
1389  for (i = 0; i < xcoder_dev_count; i++)
1390  {
1391  if (! is_str_in_str_array(xcoder_dev_names[i], curr_dev_names,
1392  curr_dev_count))
1393  {
1394  ni_log(NI_LOG_INFO, "\n\n%d. %s NOT in current scanned list, removing !\n", i,
1395  xcoder_dev_names[i]);
1397  ni_logan_rsrc_remove_device(xcoder_dev_names[i]))
1398  {
1399  ni_log(NI_LOG_INFO, "%s deleted successfully !\n", xcoder_dev_names[i]);
1400  }
1401  else
1402  {
1403  ni_log(NI_LOG_INFO, "%s failed to delete !\n", xcoder_dev_names[i]);
1404  }
1405  }
1406 
1407  }
1408 
1409  // and add into resource pool any newly discoved ones
1410  for (i = 0; i < curr_dev_count; i++)
1411  {
1412  if (! is_str_in_str_array(curr_dev_names[i], xcoder_dev_names,
1413  xcoder_dev_count))
1414  {
1415  ni_log(NI_LOG_INFO, "\n\n%s NOT in previous list, adding !\n",curr_dev_names[i]);
1416  if (NI_LOGAN_RETCODE_SUCCESS == ni_logan_rsrc_add_device(curr_dev_names[i],
1417  should_match_rev))
1418  {
1419  ni_log(NI_LOG_INFO, "%s refresh added successfully !\n", curr_dev_names[i]);
1420  }
1421  else
1422  {
1423  ni_log(NI_LOG_INFO, "%s failed to add !\n", curr_dev_names[i]);
1424  }
1425  }
1426  }
1427 
1428  END:
1429 
1430  free(saved_coders);
1431  return retval;
1432 }
1433 
1434 /*!******************************************************************************
1435 * \brief Allocates and returns a pointer to ni_logan_device_context_t struct
1436 * based on provided device_type and guid.
1437 * To be used for load update and codec query.
1438 *
1439 * \param[in] device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
1440 * \param[in] guid GUID of the encoder or decoder device
1441 *
1442 * \return pointer to ni_logan_device_context_t if found, NULL otherwise
1443 *
1444 * Note: The returned ni_logan_device_context_t content is not supposed to be used by
1445 * caller directly: should only be passed to API in the subsequent
1446 * calls; also after its use, the context should be released by
1447 * calling ni_logan_rsrc_free_device_context.
1448 *******************************************************************************/
1450 {
1452  char shm_name[32] = { 0 };
1453  char lck_name[32] = { 0 };
1454  ni_logan_device_context_t *p_device_context = NULL;
1455  ni_logan_device_info_t *p_device_queue = NULL;
1456 
1457  if (guid >= LOGAN_MAX_DEVICE_CNT)
1458  {
1459  ni_log(NI_LOG_ERROR, "Error: guid (%d) is out of range (%d) for device type: %d\n",
1460  guid, LOGAN_MAX_DEVICE_CNT, device_type);
1461  return NULL;
1462  }
1463 
1465  ni_logan_rsrc_get_shm_name(device_type, guid, shm_name, sizeof(shm_name));
1466  ni_logan_rsrc_get_lock_name(device_type, guid, lck_name, sizeof(lck_name));
1467 
1468 #ifdef _WIN32
1469  HANDLE map_file_handle = NULL;
1470  HANDLE mutex_handle = NULL;
1471 
1472  //Create a mutex for protecting the memory area
1473  mutex_handle = CreateMutex(
1474  NULL, // default security attributes
1475  FALSE, // initially owned
1476  lck_name); // unnamed mutex
1477 
1478  if (NULL == mutex_handle)
1479  {
1480  ni_log(NI_LOG_INFO, "CreateMutex %s error: %d\n", lck_name, NI_ERRNO);
1481  p_device_context = NULL;
1482  LRETURN;
1483  }
1484 
1485  if (WAIT_ABANDONED == WaitForSingleObject(mutex_handle, INFINITE)) // no time-out interval) //we got the mutex
1486  {
1487  ni_log(NI_LOG_INFO, "ERROR: %s() failed to obtain mutex: %p\n", __FUNCTION__, mutex_handle);
1488  }
1489 
1490  map_file_handle = OpenFileMapping(
1491  FILE_MAP_ALL_ACCESS, // read/write access
1492  FALSE, // do not inherit the name
1493  (LPCSTR)shm_name
1494  ); // name of mapping object
1495  if (NULL == map_file_handle)
1496  {
1497  ni_log(NI_LOG_INFO, "Could not open file mapping object %s, error: %d.\n",
1498  shm_name, NI_ERRNO);
1499  p_device_context = NULL;
1500  LRETURN;
1501  }
1502 
1503  p_device_queue = (ni_logan_device_info_t*)MapViewOfFile(map_file_handle, // handle to map object
1504  FILE_MAP_ALL_ACCESS, // read/write permission
1505  0,
1506  0,
1507  sizeof(ni_logan_device_info_t)
1508  );
1509  if (NULL == p_device_queue)
1510  {
1511  ni_log(NI_LOG_INFO, "Could not map view of file, p_last error (%d).\n", NI_ERRNO);
1513  p_device_context = NULL;
1514  LRETURN;
1515  }
1516 
1517  p_device_context = (ni_logan_device_context_t *)malloc(sizeof(ni_logan_device_context_t));
1518  if (NULL == p_device_context)
1519  {
1520  ni_log(NI_LOG_ERROR, "ERROR %d: %s() malloc failed\n",
1521  __FUNCTION__, NI_ERRNO);
1522  p_device_context = NULL;
1523  LRETURN;
1524  }
1525 
1526  p_device_context->shm_name[0] = '\0';
1527  strncat(p_device_context->shm_name, shm_name, sizeof(p_device_context->shm_name));
1528  p_device_context->lock = mutex_handle;
1529  p_device_context->p_device_info = p_device_queue;
1530 
1531 END:
1532 
1533  if (NULL == p_device_context)
1534  {
1535  if (NULL != p_device_queue)
1536  {
1537  UnmapViewOfFile(p_device_queue);
1538  }
1539  if (NULL != mutex_handle)
1540  {
1541  ReleaseMutex(mutex_handle);
1542  CloseHandle(mutex_handle);
1543  }
1544 
1545  if (NULL != map_file_handle)
1546  {
1547  CloseHandle(map_file_handle);
1548  }
1549  }
1550  else
1551  {
1552  ReleaseMutex(mutex_handle);
1553  CloseHandle(map_file_handle);
1554  }
1555 #else
1556  int shm_fd = -1;
1557  int lock;
1558 
1559 #ifdef __ANDROID__
1560  lock = open(lck_name, O_CREAT | O_RDWR | O_CLOEXEC, S_IRWXU | S_IRWXG | S_IRWXO);
1561 #else
1562  lock = open(lck_name, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1563 #endif
1564  if (lock < 0)
1565  {
1566  ni_log(NI_LOG_ERROR, "Error %d: open lock file ..... %s %d \n",
1567  NI_ERRNO, lck_name, guid);
1568  return NULL;
1569  }
1570 
1571  flock(lock, LOCK_EX);
1572 
1573 #ifdef __ANDROID__
1574  int ret = ni_logan_rsrc_android_init();
1575 
1576  if (service_logan == NULL)
1577  {
1578  ni_log(NI_LOG_ERROR, "ni_logan_rsrc_get_device_context Error service ..\n");
1579  return NULL;
1580  }
1581  string param = shm_name;
1582  Return<void> retvalue = service_logan->GetAppFlag(param, [&](int32_t ret, hidl_handle handle)
1583  {
1584  ni_log(NI_LOG_INFO, "GetAppFlag: ret %d\n", ret);
1585  if (ret > 0)
1586  {
1587  shm_fd = dup(handle->data[0]);
1588  ni_log(NI_LOG_INFO, "vendor:GetAppFlag shm_fd:%d\n", shm_fd);
1589  }
1590  else
1591  {
1592  ni_log(NI_LOG_ERROR, "Error %d: shm_get shm_fd ..\n", NI_ERRNO);
1593  }
1594  });
1595  if (!retvalue.isOk())
1596  {
1597  ni_log(NI_LOG_ERROR, "service_logan->GetAppFlag ret failed ..\n");
1598  LRETURN;
1599  }
1600  if (shm_fd < 0)
1601  {
1602  int fd = ashmem_create_region(shm_name, sizeof(ni_logan_device_info_t));
1603  if (fd >= 0)
1604  {
1605  native_handle_t *handle = native_handle_create(1, 0);
1606  handle->data[0] = fd;
1607  service_logan->SetAppFlag(param, handle);
1608  shm_fd = dup(fd);
1609  ni_log(NI_LOG_ERROR, "Create shm fd %d\n", shm_fd);
1610  }
1611  }
1612 #else
1613  shm_fd = shm_open(shm_name, O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); //just open the share memory, not create
1614 #endif
1615 
1616  if (shm_fd < 0)
1617  {
1618  ni_log(NI_LOG_ERROR, "Error %d: shm_open ..\n", NI_ERRNO);
1619  LRETURN;
1620  }
1621 
1622  p_device_queue = (ni_logan_device_info_t *)mmap(0, sizeof(ni_logan_device_info_t),
1623  PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
1624  if (MAP_FAILED == p_device_queue)
1625  {
1626  ni_log(NI_LOG_ERROR, "Error %d: mmap ni_logan_rsrc_get_device_context ...\n",
1627  NI_ERRNO);
1628  LRETURN;
1629  }
1630 
1631  p_device_context = (ni_logan_device_context_t *)malloc(sizeof(ni_logan_device_context_t));
1632  if (!p_device_context)
1633  {
1634  ni_log(NI_LOG_ERROR, "Error %d: malloc ..\n", NI_ERRNO);
1635  munmap((void *)p_device_queue, sizeof(ni_logan_device_info_t));
1636 
1637  LRETURN;
1638  }
1639 
1640  strncpy(p_device_context->shm_name, shm_name, sizeof(shm_name));
1641  p_device_context->lock = lock;
1642  p_device_context->p_device_info = p_device_queue;
1643 
1644  END:
1645 
1646  flock(lock, LOCK_UN);
1647 
1648  if (shm_fd >= 0)
1649  {
1650  close(shm_fd);
1651  }
1652 #endif
1653 
1654  return p_device_context;
1655 }
1656 
1657 /*!******************************************************************************
1658  * \brief Free previously allocated device context
1659  *
1660  * \param p_device_context Pointer to previously allocated device context
1661  *
1662  * \return None
1663  *******************************************************************************/
1665 {
1666  if (p_device_context)
1667  {
1668 #ifdef _WIN32
1669  UnmapViewOfFile(p_device_context->p_device_info);
1670  CloseHandle(p_device_context->lock);
1671 #elif defined(__linux__) || defined(__APPLE__)
1672  close(p_device_context->lock);
1673  munmap((void *)p_device_context->p_device_info, sizeof(ni_logan_device_info_t));
1674 #endif
1675  free(p_device_context);
1676  p_device_context = NULL;
1677  }
1678 }
1679 
1680 /*!******************************************************************************
1681 * \brief List device(s) based on device type with full information
1682 * including s/w instances on the system.
1683 *
1684 * \param[in] device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
1685 * \param[out] p_device The device information returned.
1686 * \param[out] p_device_count The number of ni_logan_device_info_t structs returned.
1687 *
1688 * \return
1689 * NI_LOGAN_RETCODE_SUCCESS
1690 * NI_LOGAN_RETCODE_FAILURE
1691 *
1692 * Note: Caller is responsible for allocating memory for "p_device".
1693 *******************************************************************************/
1695  ni_logan_device_info_t *p_device_info,
1696  int * p_device_count)
1697 {
1698  int i, count;
1699  ni_logan_device_queue_t *p_device_queue = NULL;
1700  ni_logan_device_pool_t *p_device_pool = NULL;
1701  ni_logan_device_context_t *p_device_context = NULL;
1703  bool b_release_pool_mtx = false;
1704 
1705  if ( (NULL == p_device_info) || (NULL == p_device_count) )
1706  {
1707  retval = NI_LOGAN_RETCODE_FAILURE;
1708  LRETURN;
1709  }
1710 
1711  p_device_pool = ni_logan_rsrc_get_device_pool();
1712  if (NULL == p_device_pool)
1713  {
1714  retval = NI_LOGAN_RETCODE_FAILURE;
1715  LRETURN;
1716  }
1717 
1718 #ifdef _WIN32
1719  if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE)) // no time-out interval)
1720  {
1721  ni_log(NI_LOG_INFO, "ERROR: %s() failed to obtain mutex: %p\n",
1722  __FUNCTION__, p_device_pool->lock);
1723  retval = NI_LOGAN_RETCODE_FAILURE;
1724  LRETURN;
1725  }
1726 #elif defined(__linux__) || defined(__APPLE__)
1727  flock(p_device_pool->lock, LOCK_EX);
1728 #endif
1729 
1730  b_release_pool_mtx = true;
1731 
1732  p_device_queue = p_device_pool->p_device_queue;
1733  if (NI_LOGAN_DEVICE_TYPE_DECODER == device_type)
1734  {
1735  count = p_device_queue->decoders_cnt;
1736  }
1737  else
1738  {
1739  count = p_device_queue->encoders_cnt;
1740  }
1741  *p_device_count=0;
1742  for (i = 0; i < count; i++)
1743  {
1744  int guid = -1;
1745  if (NI_LOGAN_DEVICE_TYPE_DECODER == device_type)
1746  {
1747  guid = p_device_queue->decoders[i];
1748  }
1749  else
1750  {
1751  guid = p_device_queue->encoders[i];
1752  }
1753 
1754  p_device_context = ni_logan_rsrc_get_device_context(device_type, guid);
1755  if (p_device_context)
1756  {
1757 #ifdef _WIN32
1758  // no time-out interval) //we got the mutex
1759  if (WAIT_ABANDONED == WaitForSingleObject(p_device_context->lock, INFINITE))
1760  {
1761  ni_log(NI_LOG_INFO, "ERROR: %s() failed to obtain mutex: %p\n",
1762  __FUNCTION__, p_device_context->lock);
1763  ReleaseMutex(p_device_pool->lock);
1764  retval = NI_LOGAN_RETCODE_FAILURE;
1765  LRETURN;
1766  }
1767 
1768  memcpy(&p_device_info[i], p_device_context->p_device_info, sizeof(ni_logan_device_info_t));
1769  ReleaseMutex(p_device_context->lock);
1770 #elif defined(__linux__) || defined(__APPLE__)
1771  flock(p_device_context->lock, LOCK_EX);
1772  memcpy(&p_device_info[i], p_device_context->p_device_info, sizeof(ni_logan_device_info_t));
1773  flock(p_device_context->lock, LOCK_UN);
1774 #endif
1775 
1776  ni_logan_rsrc_free_device_context(p_device_context);
1777 
1778  (*p_device_count)++;
1779  }
1780  else
1781  {
1782  ni_log(NI_LOG_INFO, "Error find decoder guid: %d\n", guid);
1783  retval = NI_LOGAN_RETCODE_FAILURE;
1784  LRETURN;
1785  }
1786  }
1787 
1788  END:
1789 
1790  if (b_release_pool_mtx)
1791  {
1792 #ifdef _WIN32
1793  ReleaseMutex(p_device_pool->lock);
1794 #elif defined(__linux__) || defined(__APPLE__)
1795  flock(p_device_pool->lock, LOCK_UN);
1796 #endif
1797  }
1798 
1799  ni_logan_rsrc_free_device_pool(p_device_pool);
1800 
1801  return retval;
1802 }
1803 
1804 /*!******************************************************************************
1805 * \brief List all devices with full information including s/w instances
1806 * on the system.
1807 
1808 * \param[out] p_device The device information returned.
1809 *
1810 * \return
1811 * NI_LOGAN_RETCODE_SUCCESS
1812 * NI_LOGAN_RETCODE_INVALID_PARAM
1813 * NI_LOGAN_RETCODE_FAILURE
1814 *
1815 * Note: Caller is responsible for allocating memory for "p_device".
1816 *******************************************************************************/
1818 {
1820 
1821  if (NULL == p_device)
1822  {
1824  LRETURN;
1825  }
1826 
1828  if ( NI_LOGAN_RETCODE_FAILURE == retval )
1829  {
1830  ni_log(NI_LOG_INFO, "Error retrieving decoders\n");
1831  }
1832 
1834  if (NI_LOGAN_RETCODE_FAILURE == retval)
1835  {
1836  ni_log(NI_LOG_INFO, "Error retrieving encoders\n");
1837  }
1838 
1839  END:
1840 
1841  return retval;
1842 }
1843 
1845 {
1846  int32_t i;
1847 
1848  if(!p_device_info)
1849  {
1850  ni_log(NI_LOG_INFO, "ERROR: Cannot print device info!\n");
1851  }
1852  else
1853  {
1854  ni_log(NI_LOG_INFO, "%s #%d\n", p_device_info->device_type == NI_LOGAN_DEVICE_TYPE_DECODER ?
1855  "Decoder" : "Encoder", p_device_info->module_id);
1856  ni_log(NI_LOG_INFO, " DeviceID: %s\n", p_device_info->dev_name);
1857  ni_log(NI_LOG_INFO, " BlockID: %s\n", p_device_info->blk_name);
1858  ni_log(NI_LOG_INFO, " H/W ID: %d\n", p_device_info->hw_id);
1859  ni_log(NI_LOG_INFO, " F/W rev: %2.*s\n", (int)sizeof(p_device_info->fw_rev), p_device_info->fw_rev);
1860  ni_log(NI_LOG_INFO, " F/W & S/W compatibility: %s\n", p_device_info->fw_ver_compat_warning ?
1861  "no, possible missing features" : "yes");
1862  ni_log(NI_LOG_INFO, " F/W branch: %s\n", p_device_info->fw_branch_name);
1863  ni_log(NI_LOG_INFO, " F/W commit hash: %s\n", p_device_info->fw_commit_hash);
1864  ni_log(NI_LOG_INFO, " F/W commit time: %s\n", p_device_info->fw_commit_time);
1865  ni_log(NI_LOG_INFO, " MaxNumInstances: %d\n", p_device_info->max_instance_cnt);
1866  ni_log(NI_LOG_INFO, " ActiveNumInstances: %d\n", p_device_info->active_num_inst);
1867  ni_log(NI_LOG_INFO, " Max1080pFps: %d\n", p_device_info->max_fps_1080p);
1868  ni_log(NI_LOG_INFO, " CurrentLoad: %d\n", p_device_info->load);
1869  ni_log(NI_LOG_INFO, " H.264Capabilities:\n");
1870  ni_log(NI_LOG_INFO, " Supported: %s\n", p_device_info->supports_h264 ? "yes" : "no");
1871  ni_log(NI_LOG_INFO, " MaxResolution: %dx%d\n", p_device_info->h264_cap.max_res_width,
1872  5120); /*!* TODO: Change this value to HW capability reported by FW
1873  once HW capabilities repoting format has been revamped */
1874  // p_device_info->h264_cap.max_res_height);
1875  ni_log(NI_LOG_INFO, " MinResolution: %dx%d\n", p_device_info->h264_cap.min_res_width,
1876  p_device_info->h264_cap.min_res_height);
1877  ni_log(NI_LOG_INFO, " Profiles: %s\n", p_device_info->h264_cap.profiles_supported);
1878  ni_log(NI_LOG_INFO, " level: %s\n", p_device_info->h264_cap.level);
1879  ni_log(NI_LOG_INFO, " additional info: %s\n", p_device_info->h264_cap.additional_info);
1880  ni_log(NI_LOG_INFO, " H.265Capabilities:\n");
1881  ni_log(NI_LOG_INFO, " Supported: %s\n", p_device_info->supports_h265 ? "yes" : "no");
1882  ni_log(NI_LOG_INFO, " MaxResolution: %dx%d\n", p_device_info->h265_cap.max_res_width,
1883  5120); /*!* TODO: Change this value to HW capability reported by FW
1884  once HW capabilities repoting format has been revamped */
1885  // p_device_info->h265_cap.max_res_height);
1886  ni_log(NI_LOG_INFO, " MinResolution: %dx%d\n", p_device_info->h265_cap.min_res_width,
1887  p_device_info->h265_cap.min_res_height);
1888  ni_log(NI_LOG_INFO, " Profiles: %s\n", p_device_info->h265_cap.profiles_supported);
1889  ni_log(NI_LOG_INFO, " level: %s\n", p_device_info->h265_cap.level);
1890  ni_log(NI_LOG_INFO, " additional info: %s\n", p_device_info->h265_cap.additional_info);
1891 
1892  ni_log(NI_LOG_INFO, " num. s/w instances: %d\n", p_device_info->active_num_inst);
1893  for (i = 0; i < p_device_info->active_num_inst; i++) {
1894  ni_log(NI_LOG_INFO, " [id]: %d\n", p_device_info->sw_instance[i].id);
1895  ni_log(NI_LOG_INFO, " status: %s\n",
1896  p_device_info->sw_instance[i].status == EN_IDLE ? "Idle" : "Active");
1897  ni_log(NI_LOG_INFO, " codec: %s\n",
1898  p_device_info->sw_instance[i].codec == EN_H264 ? "H.264" : "H.265");
1899  ni_log(NI_LOG_INFO, " width: %d\n", p_device_info->sw_instance[i].width);
1900  ni_log(NI_LOG_INFO, " height: %d\n", p_device_info->sw_instance[i].height);
1901  ni_log(NI_LOG_INFO, " fps: %d\n", p_device_info->sw_instance[i].fps);
1902  }
1903  ni_log(NI_LOG_INFO, "\n");
1904  }
1905 }
1906 
1907 /*!*****************************************************************************
1908 * \brief Print detailed capability information of all devices
1909 * on the system.
1910 
1911 * \param none
1912 *
1913 * \return none
1914 *
1915 *******************************************************************************/
1917 {
1918  int32_t i = 0;
1919  ni_logan_device_t* p_xcoders = NULL;
1920 
1921  p_xcoders = (ni_logan_device_t *) malloc(sizeof(ni_logan_device_t));
1922 
1923  if (NULL != p_xcoders)
1924  {
1926  {
1928  ni_log(NI_LOG_INFO, "Num decoders: %d\n", p_xcoders->decoders_cnt);
1929 
1930  for (i = 0; i < p_xcoders->decoders_cnt; i++) {
1931  ni_logan_rsrc_print_device_info(&(p_xcoders->decoders[i]));
1932  }
1933  ni_log(NI_LOG_INFO, "Num encoders: %d\n", p_xcoders->encoders_cnt);
1934  for (i = 0; i < p_xcoders->encoders_cnt; i++) {
1935  ni_logan_rsrc_print_device_info(&(p_xcoders->encoders[i]));
1936  }
1937  }
1938  free(p_xcoders);
1939  }
1940  else
1941  {
1942  ni_log(NI_LOG_ERROR, "Error %d: malloc for %s()",
1943  NI_ERRNO, __FUNCTION__);
1944  }
1945 }
1946 
1947 /*!******************************************************************************
1948 * \brief Query a specific device with detailed information on the system
1949 
1950 * \param[in] device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
1951 * \param[in] guid unique device(decoder or encoder) id
1952 *
1953 * \return
1954 * pointer to ni_logan_device_info_t if found
1955 * NULL otherwise
1956 *
1957 * Note: Caller is responsible for releasing memory that was allocated for the
1958 * returned pointer
1959 *******************************************************************************/
1961 {
1962  ni_logan_device_info_t *p_device_info = NULL;
1963  ni_logan_device_context_t* p_device_context = NULL;
1964 
1965  p_device_context = ni_logan_rsrc_get_device_context(device_type, guid);
1966  if (NULL == p_device_context)
1967  {
1968  LRETURN;
1969  }
1970 
1971  p_device_info = (ni_logan_device_info_t *)malloc(sizeof(ni_logan_device_info_t));
1972  if (NULL == p_device_info)
1973  {
1974  ni_log(NI_LOG_ERROR, "Error %d: malloc for %s()",
1975  NI_ERRNO, __FUNCTION__);
1976  LRETURN;
1977  }
1978 
1979 #ifdef _WIN32
1980  // no time-out interval) //we got the mutex
1981  if (WAIT_ABANDONED == WaitForSingleObject(p_device_context->lock, INFINITE))
1982  {
1983  ni_log(NI_LOG_INFO, "ERROR: %s() failed to obtain mutex: %p\n",
1984  __FUNCTION__, p_device_context->lock);
1985  free(p_device_info);
1986  LRETURN;
1987  }
1988 
1989  memcpy(p_device_info, p_device_context->p_device_info, sizeof(ni_logan_device_info_t));
1990  ReleaseMutex(p_device_context->lock);
1991 #elif __linux
1992  flock(p_device_context->lock, LOCK_EX);
1993 
1994  memcpy(p_device_info, p_device_context->p_device_info, sizeof(ni_logan_device_info_t));
1995 
1996  flock(p_device_context->lock, LOCK_UN);
1997 #endif
1998 
1999  END:
2000 
2001  ni_logan_rsrc_free_device_context(p_device_context);
2002 
2003  return p_device_info;
2004 }
2005 
2006 /*!****************************************************************************
2007 
2008 * \brief Get the least used device that can handle decoding or encoding
2009 * a video stream of certain resolution/frame-rate/codec.
2010 *
2011 * \param[in] width width of video resolution
2012 * \param[in] height height of video resolution
2013 * \param[in] frame_rate video stream frame rate
2014 * \param[in] codec EN_H264 or EN_H265
2015 * \param[in] type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
2016 * \param[out] info detailed device information. If is non-NULL, the
2017 * device info is stored in the memory pointed to by it.
2018 *
2019 * \return device GUID (>= 0) if found , -1 otherwise
2020 *******************************************************************************/
2022  int height,
2023  int frame_rate,
2024  ni_codec_t codec,
2025  ni_logan_device_type_t device_type,
2026  ni_logan_device_info_t *p_device_info)
2027 {
2028  int i, rc;
2029  int guid = -1;
2030  int load = 0;
2031  int num_sw_instances = 0;
2032  ni_logan_device_pool_t *p_device_pool = NULL;
2033  ni_logan_device_info_t *p_dev_info = NULL;
2034  ni_logan_device_context_t *p_device_context = NULL;
2035  ni_logan_session_context_t p_session_context = {0};
2036  ni_logan_device_info_t dev_info = { 0 };
2037  int num_coders = 0;
2038  int least_model_load = 0;
2039  int tmp_id = -1;
2040 
2041  // query all the coders of device_type and update their status, and find the
2042  // device_info with the least load and least number of instances.
2043  p_device_pool = ni_logan_rsrc_get_device_pool();
2044  if (!p_device_pool)
2045  {
2046  ni_log(NI_LOG_INFO, "Error get Coders p_device_info ..\n");
2047  return NI_LOGAN_RETCODE_FAILURE;
2048  }
2049 
2050  ni_logan_device_session_context_init(&p_session_context);
2051 
2052 #ifdef _WIN32
2053  // no time-out interval) //we got the mutex
2054  if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE))
2055  {
2056  ni_log(NI_LOG_INFO, "ERROR: %s() failed to obtain mutex: %p\n",
2057  __FUNCTION__, p_device_pool->lock);
2058  ni_logan_rsrc_free_device_pool(p_device_pool);
2059  return NI_LOGAN_RETCODE_FAILURE;
2060  }
2061 #elif defined(__linux__) || defined(__APPLE__)
2062  flock(p_device_pool->lock, LOCK_EX);
2063 #endif
2064 
2065  if (NI_LOGAN_DEVICE_TYPE_DECODER == device_type)
2066  {
2067  num_coders = p_device_pool->p_device_queue->decoders_cnt;
2068  }
2069  else
2070  {
2071  num_coders = p_device_pool->p_device_queue->encoders_cnt;
2072  }
2073 
2074  for (i = 0; i < num_coders; i++)
2075  {
2076  if (NI_LOGAN_DEVICE_TYPE_DECODER == device_type)
2077  {
2078  tmp_id = p_device_pool->p_device_queue->decoders[i];
2079  } else
2080  {
2081  tmp_id = p_device_pool->p_device_queue->encoders[i];
2082  }
2083 
2084  p_device_context = ni_logan_rsrc_get_device_context(device_type, tmp_id);
2085  if (! p_device_context)
2086  {
2087  ni_log(NI_LOG_ERROR, "%s: Error get device resource, guid %d, device_type %d\n", __func__, tmp_id, device_type);
2088  continue;
2089  }
2090 
2091  p_session_context.blk_io_handle = ni_logan_device_open(p_device_context->p_device_info->blk_name,
2092  &p_session_context.max_nvme_io_size);
2093  p_session_context.device_handle = p_session_context.blk_io_handle;
2094 
2095  if (NI_INVALID_DEVICE_HANDLE == p_session_context.device_handle)
2096  {
2097  ni_logan_rsrc_free_device_context(p_device_context);
2098  ni_log(NI_LOG_INFO, "Error open device %s %s\n", p_device_context->p_device_info->dev_name,
2099  p_device_context->p_device_info->blk_name);
2100  ni_log(NI_LOG_ERROR, "Error open device");
2101  continue;
2102  }
2103 
2104  p_session_context.hw_id = p_device_context->p_device_info->hw_id;
2105 
2106 #ifdef _WIN32
2107  p_session_context.event_handle = ni_logan_create_event();
2108  if (NI_INVALID_EVENT_HANDLE == p_session_context.event_handle)
2109  {
2110  ni_logan_rsrc_free_device_context(p_device_context);
2111  ni_logan_device_close(p_session_context.device_handle);
2112  ni_log(NI_LOG_ERROR, "Error create envet");
2113  continue;
2114  }
2115 #endif
2116 
2117  rc = ni_logan_device_session_query(&p_session_context, device_type);
2118 
2119  if (NI_INVALID_DEVICE_HANDLE != p_session_context.device_handle)
2120  {
2121  ni_logan_device_close(p_session_context.device_handle);
2122  }
2123 
2124 #ifdef _WIN32
2125  if (NI_INVALID_EVENT_HANDLE != p_session_context.event_handle)
2126  {
2127  ni_logan_close_event(p_session_context.event_handle);
2128  }
2129 #endif
2130 
2131  if (NI_LOGAN_RETCODE_SUCCESS != rc)
2132  {
2133  ni_logan_rsrc_free_device_context(p_device_context);
2134  ni_log(NI_LOG_INFO, "Error query %s %s %s.%d\n",
2135  NI_LOGAN_DEVICE_TYPE_DECODER == device_type ? "decoder" : "encoder",
2136  p_device_context->p_device_info->dev_name,
2137  p_device_context->p_device_info->blk_name,
2138  p_device_context->p_device_info->hw_id);
2139  continue;
2140  }
2141 
2142 #ifdef _WIN32
2143  // no time-out interval) //we got the mutex
2144  if (WAIT_ABANDONED == WaitForSingleObject(p_device_context->lock, INFINITE))
2145  {
2146  ni_log(NI_LOG_INFO, "ERROR: %s() failed to obtain mutex: %p\n",
2147  __FUNCTION__, p_device_context->lock);
2148  //ni_logan_rsrc_free_device_pool(p_device_pool);
2149  //return -1;
2150  }
2151 #elif defined(__linux__) || defined(__APPLE__)
2152  flock(p_device_context->lock, LOCK_EX);
2153 #endif
2154  ni_logan_rsrc_update_record(p_device_context, &p_session_context);
2155 
2156  p_dev_info = p_device_context->p_device_info;
2157 
2158  if (i == 0 || p_dev_info->model_load < least_model_load ||
2159  (p_dev_info->model_load == least_model_load &&
2160  p_dev_info->active_num_inst < num_sw_instances))
2161  {
2162  guid = tmp_id;
2163  least_model_load = p_dev_info->model_load;
2164  num_sw_instances = p_dev_info->active_num_inst;
2165  memcpy(&dev_info, p_dev_info, sizeof(ni_logan_device_info_t));
2166  }
2167 
2168 
2169 #ifdef _WIN32
2170  ReleaseMutex(p_device_context->lock);
2171 #elif defined(__linux__) || defined(__APPLE__)
2172  flock(p_device_context->lock, LOCK_UN);
2173 #endif
2174  ni_logan_rsrc_free_device_context(p_device_context);
2175  }
2176 
2177  if (guid >= 0)
2178  {
2179  // calculate the load this stream will generate based on its resolution and
2180  // fps required
2181  p_device_context = ni_logan_rsrc_get_device_context(device_type, guid);
2183  if ((!p_device_context) || (refCap.fps == 0))
2184  {
2185  guid = -1;
2186  }
2187  else if ((device_type == NI_LOGAN_DEVICE_TYPE_ENCODER) || (device_type == NI_LOGAN_DEVICE_TYPE_DECODER))
2188  {
2189  unsigned long total_cap = refCap.width * refCap.height * refCap.fps;
2190  unsigned long xcode_cap = width * height * frame_rate;
2191  if (xcode_cap + p_device_context->p_device_info->xcode_load_pixel > total_cap)
2192  {
2193  ni_log(NI_LOG_INFO, "Warning xcode cap: %ld (%.1f) + current load %ld (%.1f) "
2194  "> total %ld (1) ..\n",
2195  xcode_cap, (float)xcode_cap / total_cap,
2196  p_device_context->p_device_info->xcode_load_pixel,
2197  (float)p_device_context->p_device_info->xcode_load_pixel / total_cap, total_cap);
2198  guid = -1;
2199  }
2200  }
2201  else
2202  {
2203  float fRef = (float)refCap.width * refCap.height * refCap.fps;
2204  float fLoad = (float)width * height * frame_rate * 100;
2205  if ((fLoad / fRef) > (100.0 - (float)load))
2206  {
2207  guid = -1;
2208  }
2209  }
2210  }
2211 
2212 #ifdef _WIN32
2213  ReleaseMutex(p_device_pool->lock);
2214 #elif defined(__linux__) || defined(__APPLE__)
2215  flock(p_device_pool->lock, LOCK_UN);
2216 #endif
2217 
2218  ni_logan_device_session_context_clear(&p_session_context);
2219 
2220  ni_logan_rsrc_free_device_pool(p_device_pool);
2221 
2222  ni_log(NI_LOG_INFO, "Get %s for %dx%d fps %d : %d %s.%d\n",
2223  NI_LOGAN_DEVICE_TYPE_DECODER == device_type ? "decoder" : "encoder",
2224  width, height, frame_rate,
2225  guid, guid == -1 ? "NULL" : dev_info.dev_name,
2226  guid == -1 ? -1 : dev_info.hw_id);
2227 
2228  //Copy to user only if the pointer is not NULL
2229  if ( (p_device_info) && (guid >= 0) )
2230  {
2231  memcpy(p_device_info, &dev_info, sizeof(ni_logan_device_info_t));
2232  }
2233 
2234  return guid;
2235 }
2236 
2237 /*!*****************************************************************************
2238 * \brief Update the load value and s/w instances info of a specific decoder or
2239 * encoder. This is used by resource management daemon to update periodically.
2240 *
2241 * \param[in] p_ctxt The device context returned by ni_logan_rsrc_get_device_context
2242 * \param[in] p_load The latest load value to update
2243 * \param[in] sw_instance_cnt Number of s/w instances
2244 * \param[in] sw_instance_info Info of s/w instances
2245 *
2246 * \return
2247 * NI_LOGAN_RETCODE_SUCCESS
2248 * NI_LOGAN_RETCODE_FAILURE
2249 *******************************************************************************/
2251  int load,
2252  int sw_instance_cnt,
2253  const ni_logan_sw_instance_info_t sw_instance_info[])
2254 {
2255  int i;
2256  if (!p_device_context || !sw_instance_info)
2257  {
2258  ni_log(NI_LOG_INFO, "Error in resource update device load: invalid input pointers ..\n");
2259  return NI_LOGAN_RETCODE_FAILURE;
2260  }
2261 
2262 #ifdef _WIN32
2263  // no time-out interval) //we got the mutex
2264  if (WAIT_ABANDONED == WaitForSingleObject(p_device_context->lock, INFINITE))
2265  {
2266  ni_log(NI_LOG_INFO, "ERROR: %s() failed to obtain mutex: %p\n",
2267  __FUNCTION__, p_device_context->lock);
2268  return NI_LOGAN_RETCODE_FAILURE;
2269  }
2270 #elif defined(__linux__) || defined(__APPLE__)
2271  flock(p_device_context->lock, LOCK_EX);
2272 #endif
2273 
2274  p_device_context->p_device_info->load = load;
2275  p_device_context->p_device_info->active_num_inst = sw_instance_cnt;
2276  for (i = 0; i < sw_instance_cnt; i++)
2277  {
2278  p_device_context->p_device_info->sw_instance[i] = sw_instance_info[i];
2279  }
2280 
2281 #ifdef _WIN32
2282  ReleaseMutex(p_device_context->lock);
2283 #elif defined(__linux__) || defined(__APPLE__)
2284  flock(p_device_context->lock, LOCK_UN);
2285 #endif
2286 
2287  return NI_LOGAN_RETCODE_SUCCESS;
2288 }
2289 
2290 /*!*****************************************************************************
2291 * \brief Allocate resources for decoding/encoding, based on the provided rule
2292 *
2293 * \param[in] type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
2294 * \param[in] rule allocation rule
2295 * \param[in] codec EN_H264 or EN_H265
2296 * \param[in] width width of video resolution
2297 * \param[in] height height of video resolution
2298 * \param[in] frame_rate video stream frame rate
2299 * \param[out] p_load the p_load that will be generated by this encoding
2300 * task. Returned *only* for encoder for now.
2301 *
2302 * \return pointer to ni_logan_device_context_t if found, NULL otherwise
2303 *
2304 * Note: codec, width, height, fps need to be supplied for NI_LOGAN_DEVICE_TYPE_ENCODER only,
2305 * they are ignored otherwize.
2306 * Note: the returned ni_logan_device_context_t content is not supposed to be used by
2307 * caller directly: should only be passed to API in the subsequent
2308 * calls; also after its use, the context should be released by
2309 * calling ni_logan_rsrc_free_device_context.
2310 *******************************************************************************/
2312  ni_alloc_rule_t rule,
2313  ni_codec_t codec,
2314  int width,
2315  int height,
2316  int frame_rate,
2317  unsigned long* p_load)
2318 {
2319  ni_logan_device_pool_t *p_device_pool = NULL;
2320  ni_logan_device_info_t *p_device_info = NULL;
2321  ni_logan_device_context_t *p_device_context = NULL;
2322  ni_logan_session_context_t p_session_context = { 0 };
2323  int *coders = NULL;
2324  int i, count, rc;
2325  int guid = -1;
2326  int load = 0;
2327  int num_sw_instances = 0;
2328  int least_model_load = 0;
2329 
2332  p_device_pool = ni_logan_rsrc_get_device_pool();
2333  if (p_device_pool)
2334  {
2335  ni_logan_device_session_context_init(&p_session_context);
2336 
2337 #ifdef _WIN32
2338  // no time-out interval) //we got the mutex
2339  if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE))
2340  {
2341  ni_log(NI_LOG_INFO, "ERROR: %s() failed to obtain mutex: %p\n",
2342  __FUNCTION__, p_device_pool->lock);
2343  }
2344 #elif defined(__linux__) || defined(__APPLE__)
2345  flock(p_device_pool->lock, LOCK_EX);
2346 #endif
2347 
2348  coders = ( NI_LOGAN_DEVICE_TYPE_DECODER == device_type ? p_device_pool->p_device_queue->decoders :
2349  p_device_pool->p_device_queue->encoders);
2350 
2351  count = ( NI_LOGAN_DEVICE_TYPE_DECODER == device_type ? p_device_pool->p_device_queue->decoders_cnt :
2352  p_device_pool->p_device_queue->encoders_cnt);
2353 
2354  for (i = 0; i < count; i++)
2355  {
2357  p_device_context = ni_logan_rsrc_get_device_context(device_type, coders[i]);
2358  if (!p_device_context)
2359  {
2360  ni_log(NI_LOG_ERROR, "%s: Error get device resource, guid %d, device_type %d\n", __func__, coders[i], device_type);
2361  continue;
2362  }
2363 
2364  // p_first retrieve status from f/w and update storage
2365  p_session_context.blk_io_handle = ni_logan_device_open(p_device_context->p_device_info->blk_name,
2366  &p_session_context.max_nvme_io_size);
2367  p_session_context.device_handle = p_session_context.blk_io_handle;
2368 
2369  if (NI_INVALID_DEVICE_HANDLE == p_session_context.device_handle)
2370  {
2371  ni_log(NI_LOG_INFO, "Error open device %s %s\n",
2372  p_device_context->p_device_info->dev_name,
2373  p_device_context->p_device_info->blk_name);
2374  ni_log(NI_LOG_ERROR, "Error open device");
2375  ni_logan_rsrc_free_device_context(p_device_context);
2376  continue;
2377  }
2378 
2379  p_session_context.hw_id = p_device_context->p_device_info->hw_id;
2380 
2381 #ifdef _WIN32
2382  p_session_context.event_handle = ni_logan_create_event();
2383  if (NI_INVALID_EVENT_HANDLE != p_session_context.event_handle)
2384  {
2385  ni_logan_rsrc_free_device_context(p_device_context);
2386  ni_logan_device_close(p_session_context.device_handle);
2387  ni_log(NI_LOG_ERROR, "Error create envet");
2388  continue;
2389  }
2390 #endif
2391 
2392  rc = ni_logan_device_session_query(&p_session_context, device_type);
2393 
2394  ni_logan_device_close(p_session_context.device_handle);
2395 #ifdef _WIN32
2396  ni_logan_close_event(p_session_context.event_handle);
2397 #endif
2398 
2399  if (NI_LOGAN_RETCODE_SUCCESS != rc)
2400  {
2401  ni_log(NI_LOG_INFO, "Error query %s %s %s.%d\n",
2402  NI_LOGAN_DEVICE_TYPE_DECODER == device_type ? "decoder" : "encoder",
2403  p_device_context->p_device_info->dev_name,
2404  p_device_context->p_device_info->blk_name,
2405  p_device_context->p_device_info->hw_id);
2406  ni_logan_rsrc_free_device_context(p_device_context);
2407  continue;
2408  }
2409 
2410 #ifdef _WIN32
2411  // no time-out interval) //we got the mutex
2412  if (WAIT_ABANDONED == WaitForSingleObject(p_device_context->lock, INFINITE))
2413  {
2414  ni_log(NI_LOG_INFO, "ERROR: %s() failed to obtain mutex: %p\n",
2415  __FUNCTION__, p_device_context->lock);
2416  }
2417 #elif defined(__linux__) || defined(__APPLE__)
2418  flock(p_device_context->lock, LOCK_EX);
2419 #endif
2420  ni_logan_rsrc_update_record(p_device_context, &p_session_context);
2421 
2422  p_device_info = p_device_context->p_device_info;
2423  if (i == 0)
2424  {
2425  guid = coders[i];
2426  load = p_device_info->load;
2427  least_model_load = p_device_info->model_load;
2428  num_sw_instances = p_device_info->active_num_inst;
2429  }
2430 
2431  ni_log(NI_LOG_INFO, "Coder [%d]: %d , load: %d (%d), activ_inst: %d , max_inst %d\n",
2432  i, coders[i], p_device_info->load, p_device_info->model_load,
2433  p_device_info->active_num_inst, p_device_info->max_instance_cnt);
2434 
2435  switch (rule)
2436  {
2438  {
2439  if (p_device_info->active_num_inst < num_sw_instances)
2440  {
2441  guid = coders[i];
2442  num_sw_instances = p_device_info->active_num_inst;
2443  }
2444  break;
2445  }
2446 
2447  case EN_ALLOC_LEAST_LOAD:
2448  default:
2449  {
2450  if (NI_LOGAN_DEVICE_TYPE_ENCODER == device_type)
2451  {
2452  if (p_device_info->model_load < least_model_load)
2453  {
2454  guid = coders[i];
2455  least_model_load = p_device_info->model_load;
2456  }
2457  }
2458  else if (p_device_info->load < load)
2459  {
2460  guid = coders[i];
2461  load = p_device_info->load;
2462  }
2463  break;
2464  }
2465  }
2466 
2467 #ifdef _WIN32
2468  ReleaseMutex(p_device_context->lock);
2469 #elif defined(__linux__) || defined(__APPLE__)
2470  flock(p_device_context->lock, LOCK_UN);
2471 #endif
2472  ni_logan_rsrc_free_device_context(p_device_context);
2473  }
2474 
2475  if (guid >= 0)
2476  {
2477  p_device_context = ni_logan_rsrc_get_device_context(device_type, guid);
2478  if (p_device_context && NI_LOGAN_DEVICE_TYPE_ENCODER == device_type)
2479  {
2481  unsigned long total_cap = refCap.width * refCap.height * refCap.fps;
2482  if (total_cap == 0)
2483  {
2484  ni_log(NI_LOG_INFO, "Capacity is 0, guid %d ..\n", guid);
2485  p_device_context = NULL;
2486  LRETURN;
2487  }
2488  else
2489  {
2490  *p_load = width * height * frame_rate;
2491 
2492 #ifdef _WIN32
2493  // no time-out interval) //we got the mutex
2494  if (WAIT_ABANDONED == WaitForSingleObject(p_device_context->lock, INFINITE))
2495  {
2496  ni_log(NI_LOG_INFO, "ERROR: %s() failed to obtain mutex: %p\n",
2497  __FUNCTION__, p_device_context->lock);
2498  }
2499 #elif defined(__linux__) || defined(__APPLE__)
2500  flock(p_device_context->lock, LOCK_EX);
2501 #endif
2502  p_device_context->p_device_info->xcode_load_pixel += *p_load;
2503 #ifdef _WIN32
2504  ReleaseMutex(p_device_context->lock);
2505 #elif defined(__linux__) || defined(__APPLE__)
2506  if (msync((void *)p_device_context->p_device_info, sizeof(ni_logan_device_info_t),
2507  MS_SYNC | MS_INVALIDATE))
2508  {
2509  ni_log(NI_LOG_ERROR, "%s msync\n", __FUNCTION__);
2510  }
2511  flock(p_device_context->lock, LOCK_UN);
2512 #endif
2513  }
2514  }
2515  }
2516  else
2517  {
2518  ni_log(NI_LOG_INFO, "Error find guid ..\n");
2519  p_device_context = NULL;
2520  }
2521 
2522  END:
2523 #ifdef _WIN32
2524  ReleaseMutex(p_device_pool->lock);
2525 #elif defined(__linux__) || defined(__APPLE__)
2526  flock(p_device_pool->lock, LOCK_UN);
2527 #endif
2528  ni_logan_device_session_context_clear(&p_session_context);
2529  ni_logan_rsrc_free_device_pool(p_device_pool);
2530  }
2531  return p_device_context;
2532 }
2533 
2534 /*!*****************************************************************************
2535 * \brief Allocate resources for decoding/encoding, by designating explicitly
2536 * the device to use.
2537 *
2538 * \param[in] device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
2539 * \param[in] guid unique device (decoder or encoder) module id
2540 * \param[in] codec EN_H264 or EN_H265
2541 * \param[in] width width of video resolution
2542 * \param[in] height height of video resolution
2543 * \param[in] frame_rate video stream frame rate
2544 * \param[out] p_load the load that will be generated by this encoding
2545 * task. Returned *only* for encoder for now.
2546 *
2547 * \return pointer to ni_logan_device_context_t if found, NULL otherwise
2548 *
2549 * Note: codec, width, height, fps need to be supplied by encoder; they
2550 * are ignored for decoder.
2551 *
2552 * Note: the returned ni_logan_device_context_t content is not supposed to be used by
2553 * caller directly: should only be passed to API in the subsequent
2554 * calls; also after its use, the context should be released by
2555 * calling ni_logan_rsrc_free_device_context.
2556 *******************************************************************************/
2558  int guid,
2559  ni_codec_t codec,
2560  int width,
2561  int height,
2562  int frame_rate,
2563  unsigned long* p_load)
2564 {
2565  ni_logan_device_context_t *p_device_context = ni_logan_rsrc_get_device_context(device_type, guid);
2566  if (p_device_context)
2567  {
2568 #ifdef _WIN32
2569  // no time-out interval) //we got the mutex
2570  if (WAIT_ABANDONED == WaitForSingleObject(p_device_context->lock, INFINITE))
2571  {
2572  ni_log(NI_LOG_INFO, "ERROR: %s() failed to obtain mutex: %p\n",
2573  __FUNCTION__, p_device_context->lock);
2574  }
2575 #elif defined(__linux__) || defined(__APPLE__)
2576  flock(p_device_context->lock, LOCK_EX);
2577 #endif
2578 
2583  if (NI_LOGAN_DEVICE_TYPE_ENCODER == device_type)
2584  {
2586  unsigned long total_cap = refCap.width * refCap.height * refCap.fps;
2587  if (total_cap > 0)
2588  {
2589  *p_load = width * height * frame_rate;
2590  p_device_context->p_device_info->xcode_load_pixel += *p_load;
2591 #if defined(__linux__) || defined(__APPLE__)
2592  if (msync((void *)p_device_context->p_device_info, sizeof(ni_logan_device_info_t),
2593  MS_SYNC | MS_INVALIDATE))
2594  {
2595  ni_log(NI_LOG_ERROR, "%s msync\n", __FUNCTION__);
2596  }
2597 #endif
2598  }
2599  }
2600 
2601 #ifdef _WIN32
2602  ReleaseMutex(p_device_context->lock);
2603 #elif defined(__linux__) || defined(__APPLE__)
2604  flock(p_device_context->lock, LOCK_UN);
2605 #endif
2606  }
2607  return p_device_context;
2608 }
2609 
2610 
2611 /*!*****************************************************************************
2612 * \brief Allocate resources for decoding/encoding, by designating explicitly
2613 * the device to use. do not track the load on the host side
2614 *
2615 * \param[in] device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
2616 * \param[in] guid unique device (decoder or encoder) module id
2617 * \return pointer to ni_logan_device_context_t if found, NULL otherwise
2618 *
2619 * Note: only need to specify the device type and guid and codec type
2620 *
2621 *
2622 * Note: the returned ni_logan_device_context_t content is not supposed to be used by
2623 * caller directly: should only be passed to API in the subsequent
2624 * calls; also after its use, the context should be released by
2625 * calling ni_logan_rsrc_free_device_context.
2626 *******************************************************************************/
2628  int guid)
2629 {
2630  ni_logan_device_pool_t *p_device_pool = NULL;
2631 
2632  ni_logan_device_context_t *p_device_context = ni_logan_rsrc_get_device_context(device_type, guid);
2633 
2634  return p_device_context;
2635 }
2636 
2637 
2638 /*!*****************************************************************************
2639 * \brief Release resources allocated for decoding/encoding.
2640 * function This *must* be called at the end of transcoding
2641 * with previously assigned load value by allocate* functions.
2642 *
2643 * \param[in/] p_ctxt the device context
2644 * \param[in] codec EN_H264 or EN_H265
2645 * \param[in] load the load value returned by allocate* functions
2646 *
2647 * \return None
2648 * THE API needs to be removed from this fild and related test needs to cleanup
2649 *******************************************************************************/
2651  ni_codec_t codec,
2652  unsigned long load)
2653 {
2655  unsigned long total_cap = refCap.width * refCap.height * refCap.fps;
2656 
2657 #ifdef _WIN32
2658  // no time-out interval) //we got the mutex
2659  if (WAIT_ABANDONED == WaitForSingleObject(p_device_context->lock, INFINITE))
2660  {
2661  ni_log(NI_LOG_INFO, "ERROR: %s() failed to obtain mutex: %p\n",
2662  __FUNCTION__, p_device_context->lock);
2663  }
2664 #elif defined(__linux__) || defined(__APPLE__)
2665  flock(p_device_context->lock, LOCK_EX);
2666 #endif
2667 
2668  if (p_device_context->p_device_info->xcode_load_pixel < load)
2669  {
2670  ni_log(NI_LOG_INFO, "Warning: releasing resource load %ld > current load %ld\n",
2671  load, p_device_context->p_device_info->xcode_load_pixel);
2672  }
2673  else
2674  {
2675  p_device_context->p_device_info->xcode_load_pixel -= load;
2676 #if defined(__linux__) || defined(__APPLE__)
2677  if (msync((void *)p_device_context->p_device_info, sizeof(ni_logan_device_info_t), MS_SYNC | MS_INVALIDATE))
2678  {
2679  ni_log(NI_LOG_ERROR, "%s msync\n", __FUNCTION__);
2680  }
2681 #endif
2682  }
2683 
2684 #ifdef _WIN32
2685  ReleaseMutex(p_device_context->lock);
2686 #elif defined(__linux__) || defined(__APPLE__)
2687  flock(p_device_context->lock, LOCK_UN);
2688 #endif
2689 }
2690 
2691 /*!*****************************************************************************
2692 * \brief Check software instance.
2693 *
2694 * \param[in] p_device_context the device context
2695 *
2696 * \return the count of active instances
2697 * if error, return NI_LOGAN_RETCODE_FAILURE
2698 *
2699 *******************************************************************************/
2701  ni_logan_device_type_t device_type)
2702 {
2703  int retval = NI_LOGAN_RETCODE_SUCCESS;
2704  int count = 0; // default the count is zero.
2705  ni_logan_session_context_t session_ctx = { 0 };
2706 
2708 
2709  session_ctx.blk_io_handle = ni_logan_device_open(p_device_context->p_device_info->blk_name,
2710  &session_ctx.max_nvme_io_size);
2711  session_ctx.device_handle = session_ctx.blk_io_handle;
2712 
2713  // Check if device can be opened
2714  if (NI_INVALID_DEVICE_HANDLE == session_ctx.device_handle)
2715  {
2716  // Suppose that no instance is active when the device cannot be opened.
2717  ni_log(NI_LOG_INFO, "open device %s failed, remove it\n", p_device_context->p_device_info->dev_name);
2718  return count;
2719  }
2720 
2721  session_ctx.hw_id = p_device_context->p_device_info->hw_id;
2722 #ifdef _WIN32
2723  session_ctx.event_handle = ni_logan_create_event();
2724  if (NI_INVALID_EVENT_HANDLE == session_ctx.event_handle)
2725  {
2726  ni_log(NI_LOG_INFO, "ERROR: %s() create envent\n", __FUNCTION__);
2727  retval = NI_LOGAN_RETCODE_FAILURE;
2728  return retval;
2729  }
2730 #endif
2731 
2732  retval = ni_logan_device_session_query(&session_ctx, device_type);
2733  if (NI_LOGAN_RETCODE_SUCCESS != retval)
2734  {
2735  // Suppose that no instance is active when query fails.
2736  ni_log(NI_LOG_INFO, "query device %s failed, retval=%d\n", p_device_context->p_device_info->dev_name, retval);
2737  }
2738  else
2739  {
2740  count = session_ctx.load_query.total_contexts;
2741  ni_log(NI_LOG_INFO, "device %s active %s instance conut is %d\n",
2742  device_type == NI_LOGAN_DEVICE_TYPE_DECODER ? "decoder" : "encoder",
2743  p_device_context->p_device_info->dev_name,
2744  count);
2745  }
2746 
2747  ni_logan_device_close(session_ctx.device_handle);
2748 
2749 #ifdef _WIN32
2750  ni_logan_close_event(session_ctx.event_handle);
2751 #endif
2752 
2754 
2755  return count;
2756 }
2757 
2758 /*!*****************************************************************************
2759 * \brief check the NetInt h/w device in resource pool on the host.
2760 *
2761 * \param[in] guid the global unique device index in resource pool
2762 * device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
2763 *
2764 * \return
2765 * NI_LOGAN_RETCODE_SUCCESS if codec is available,
2766 * otherwise ni_logan_retcode_t errors (negative values)
2767 *******************************************************************************/
2769 {
2770  ni_logan_device_pool_t *p_device_pool = NULL;
2771  ni_logan_device_context_t *p_device_ctx = NULL;
2772  ni_logan_session_context_t session_ctx = {0};
2773  uint32_t max_nvme_io_size = 0;
2774  bool b_release_pool_mtx = false;
2776 
2777  if (guid < 0)
2778  {
2779  ni_log(NI_LOG_ERROR, "ERROR invalid guid:%d\n", guid);
2781  }
2782 
2783  if (! (NI_LOGAN_DEVICE_TYPE_DECODER == device_type ||
2784  NI_LOGAN_DEVICE_TYPE_ENCODER == device_type))
2785  {
2786  ni_log(NI_LOG_ERROR, "ERROR: Unknown device type:%d\n", device_type);
2788  }
2789 
2790  p_device_pool = ni_logan_rsrc_get_device_pool();
2791  if (!p_device_pool)
2792  {
2793  ni_log(NI_LOG_ERROR, "ERROR: get device poll failed\n");
2795  LRETURN;
2796  }
2797 
2799 
2800 #ifdef _WIN32
2801  if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE)) // no time-out interval)
2802  {
2803  ni_log(NI_LOG_INFO, "ERROR: ni_logan_rsrc_list_devices() failed to obtain mutex: %p\n", p_device_pool->lock);
2804  retval = NI_LOGAN_RETCODE_FAILURE;
2805  LRETURN;
2806  }
2807 #elif defined(__linux__) || defined(__APPLE__)
2808  flock(p_device_pool->lock, LOCK_EX);
2809 #endif
2810  b_release_pool_mtx = true;
2811 
2812  // get device context
2813  p_device_ctx = ni_logan_rsrc_get_device_context(device_type, guid);
2814  if (p_device_ctx)
2815  {
2816  session_ctx.device_handle = ni_logan_device_open(p_device_ctx->p_device_info->blk_name,
2817  &max_nvme_io_size);
2818  session_ctx.blk_io_handle = session_ctx.device_handle;
2819 
2820  if (NI_INVALID_DEVICE_HANDLE == session_ctx.device_handle)
2821  {
2822  ni_log(NI_LOG_ERROR, "open device failed: %d\n", NI_ERRNO);
2824  }
2825  else
2826  {
2827 #ifdef _WIN32
2828  session_ctx.event_handle = ni_logan_create_event();
2829  if (NI_INVALID_EVENT_HANDLE == session_ctx.event_handle)
2830  {
2831  ni_log(NI_LOG_INFO, "Error create envent:%d\n", NI_ERRNO);
2832  retval = NI_LOGAN_RETCODE_FAILURE;
2833  LRETURN;
2834  }
2835 #endif
2836 
2837  retval = ni_logan_device_session_query(&session_ctx, device_type);
2838  if (NI_LOGAN_RETCODE_SUCCESS != retval)
2839  {
2840  ni_log(NI_LOG_ERROR, "guid %d. %s, %s is not avaiable, type: %d, retval:%d\n",
2841  guid,
2842  p_device_ctx->p_device_info->dev_name,
2843  p_device_ctx->p_device_info->blk_name,
2844  device_type,
2845  retval);
2846  retval = NI_LOGAN_RETCODE_FAILURE;
2847  }
2848  else
2849  {
2850  ni_log(NI_LOG_INFO, "guid %d. %s %s is avaiable\n",
2851  guid,
2852  p_device_ctx->p_device_info->dev_name,
2853  p_device_ctx->p_device_info->blk_name);
2854  }
2855  }
2856  }
2857  else
2858  {
2859  ni_log(NI_LOG_ERROR, "Error get device resource: guid %d, device_ctx %p\n",
2860  guid, p_device_ctx);
2861  retval = NI_LOGAN_RETCODE_FAILURE;
2862  }
2863 
2864  END:
2865 
2866  if (b_release_pool_mtx)
2867  {
2868 #ifdef _WIN32
2869  ReleaseMutex(p_device_pool->lock);
2870 #elif defined(__linux__) || defined(__APPLE__)
2871  flock(p_device_pool->lock, LOCK_UN);
2872 #endif
2873  }
2874 
2875  ni_logan_close_event(session_ctx.event_handle);
2876  ni_logan_device_close(session_ctx.device_handle);
2877 
2878  ni_logan_rsrc_free_device_context(p_device_ctx);
2879 
2881  ni_logan_rsrc_free_device_pool(p_device_pool);
2882 
2883  return retval;
2884 }
2885 
2886 /*!*****************************************************************************
2887 * \brief check the NetInt h/w device in resource pool on the host.
2888 *
2889 * \param[in] guid the global unique device index in resource pool
2890 * device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
2891 *
2892 * \return
2893 * NI_LOGAN_RETCODE_SUCCESS
2894 *******************************************************************************/
2896 {
2897  ni_logan_device_pool_t *p_device_pool = NULL;
2898  ni_logan_device_context_t *p_device_ctx = NULL;
2899  ni_logan_session_context_t session_ctx = {0};
2900  ni_logan_encoder_params_t enc_api_param = {0};
2901  ni_logan_decoder_params_t dec_api_param = {0};
2902  uint32_t max_nvme_io_size = 0;
2903  bool b_release_pool_mtx = false;
2905  int retry_cnt = 0;
2906 
2907  if (guid < 0)
2908  {
2909  ni_log(NI_LOG_ERROR, "ERROR invalid guid:%d\n", guid);
2911  }
2912 
2913  if (! (NI_LOGAN_DEVICE_TYPE_DECODER == device_type ||
2914  NI_LOGAN_DEVICE_TYPE_ENCODER == device_type))
2915  {
2916  ni_log(NI_LOG_ERROR, "ERROR: Unknown device type:%d\n", device_type);
2918  }
2919 
2922  session_ctx.src_bit_depth = 8;
2923 
2924  if (NI_LOGAN_DEVICE_TYPE_DECODER == device_type)
2925  {
2926  if (ni_logan_decoder_init_default_params(&dec_api_param, 30, 1, NI_LOGAN_MIN_BITRATE,
2928  {
2929  ni_log(NI_LOG_ERROR, "ERROR: set decoder default params error\n");
2931  }
2932  session_ctx.p_session_config = &dec_api_param;
2933  }
2934  else
2935  {
2936  if (ni_logan_encoder_init_default_params(&enc_api_param, 30, 1, NI_LOGAN_MIN_BITRATE,
2938  {
2939  ni_log(NI_LOG_ERROR, "ERROR: set encoder default params error\n");
2941  }
2942  session_ctx.p_session_config = &enc_api_param;
2943  }
2944 
2945  p_device_pool = ni_logan_rsrc_get_device_pool();
2946  if (!p_device_pool)
2947  {
2948  ni_log(NI_LOG_ERROR, "ERROR: get device poll failed\n");
2950  LRETURN;
2951  }
2952 
2953 #ifdef _WIN32
2954  if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE)) // no time-out interval)
2955  {
2956  ni_log(NI_LOG_INFO, "ERROR: ni_logan_rsrc_list_devices() failed to obtain mutex: %p\n", p_device_pool->lock);
2957  retval = NI_LOGAN_RETCODE_FAILURE;
2958  LRETURN;
2959  }
2960 #elif defined(__linux__) || defined(__APPLE__)
2961  lockf(p_device_pool->lock, F_LOCK, 0);
2962 #endif
2963  b_release_pool_mtx = true;
2964 
2965  // get device context
2966  p_device_ctx = ni_logan_rsrc_get_device_context(device_type, guid);
2967  if (p_device_ctx)
2968  {
2969  session_ctx.device_handle = ni_logan_device_open(p_device_ctx->p_device_info->blk_name,
2970  &max_nvme_io_size);
2971  session_ctx.blk_io_handle = session_ctx.device_handle;
2972 
2973  if (NI_INVALID_DEVICE_HANDLE == session_ctx.device_handle)
2974  {
2975  ni_log(NI_LOG_ERROR, "open device failed: %d\n", errno);
2977  }
2978  else
2979  {
2980 #ifdef _WIN32
2981  session_ctx.event_handle = ni_logan_create_event();
2982  if (NI_INVALID_EVENT_HANDLE == session_ctx.event_handle)
2983  {
2984  ni_log(NI_LOG_INFO, "Error create envent:%d\n",GetLastError());
2985  retval = NI_LOGAN_RETCODE_FAILURE;
2986  LRETURN;
2987  }
2988 #endif
2989 
2990  retval = ni_logan_device_session_query(&session_ctx, device_type);
2991  if (NI_LOGAN_RETCODE_SUCCESS != retval)
2992  {
2993  ni_log(NI_LOG_ERROR, "guid %d. %s, %s is not avaiable, type: %d, retval:%d\n",
2994  guid,
2995  p_device_ctx->p_device_info->dev_name,
2996  p_device_ctx->p_device_info->blk_name,
2997  device_type,
2998  retval);
2999  retval = NI_LOGAN_RETCODE_FAILURE;
3000  }
3001  else
3002  {
3003  while (1)
3004  {
3005  retry_cnt ++;
3006  retval = ni_logan_device_session_open(&session_ctx, device_type);
3007  ni_logan_device_session_close(&session_ctx, 0, device_type);
3008  if (retval == NI_LOGAN_RETCODE_SUCCESS)
3009  {
3010  ni_log(NI_LOG_INFO, "guid %d. %s %s is avaiable\n",
3011  guid,
3012  p_device_ctx->p_device_info->dev_name,
3013  p_device_ctx->p_device_info->blk_name);
3014  break;
3015  }
3016  else if (retry_cnt < 10 && retval == NI_LOGAN_RETCODE_ERROR_VPU_RECOVERY) // max 2 seconds
3017  {
3018  ni_log(NI_LOG_INFO, "vpu recovery happened on guid %d. %s %s, retry cnt:%d\n",
3019  guid,
3020  p_device_ctx->p_device_info->dev_name,
3021  p_device_ctx->p_device_info->blk_name,
3022  retry_cnt);
3023 #ifndef _WIN32
3024  ni_logan_usleep(200000); // 200 ms
3025 #endif
3026  continue;
3027  }
3028  else
3029  {
3030  ni_log(NI_LOG_ERROR, "session open error guid %d. %s, %s, type: %d, retval:%d\n",
3031  guid,
3032  p_device_ctx->p_device_info->dev_name,
3033  p_device_ctx->p_device_info->blk_name,
3034  device_type,
3035  retval);
3036  retval = NI_LOGAN_RETCODE_FAILURE;
3037  break;
3038  }
3039  }
3040  }
3041  }
3042  }
3043  else
3044  {
3045  ni_log(NI_LOG_ERROR, "Error get device resource: guid %d, device_ctx %p\n",
3046  guid, p_device_ctx);
3047  retval = NI_LOGAN_RETCODE_FAILURE;
3048  }
3049 
3050  END:
3051 
3052  if (b_release_pool_mtx)
3053  {
3054 #ifdef _WIN32
3055  ReleaseMutex(p_device_pool->lock);
3056 #elif defined(__linux__) || defined(__APPLE__)
3057  lockf(p_device_pool->lock, F_ULOCK, 0);
3058 #endif
3059  }
3060 
3061  ni_logan_close_event(session_ctx.event_handle);
3062  ni_logan_device_close(session_ctx.device_handle);
3063 
3064  ni_logan_rsrc_free_device_context(p_device_ctx);
3065 
3066  ni_logan_rsrc_free_device_pool(p_device_pool);
3067 
3069 
3070  return retval;
3071 }
3072 
3073 /*!******************************************************************************
3074  * \brief check hw info, return the appropriate card number to use depends on the load&task_num&used resource
3075  *
3076  * \param[out] p_hw_device_info : record the device info, including available card num and which card to select,
3077  * and each card's informaton, such as, the load and task num
3078  * \param[in] task_mode: affect the scheduling strategy,
3079  * 1 - both the load_num and task_num should consider, usually applied to live scenes
3080  * 0 - only consider the task_num, donnot care the load_num
3081  * \param[in] load_threshold : load threshold [0 - 100]
3082  * \param[in] task_num_threshold : task threshold [0 - max_task_num(32)]
3083  * \param[in] device_type: 1:decode 2:encode
3084  * \param[in] resolution:it is the product of width and height, i.e. widthxheight
3085  *
3086  * \return 0-error 1-success
3087  *******************************************************************************/
3088 
3089 int ni_logan_check_hw_info(hw_device_info_t *p_hw_device_info, int task_mode,
3090  int load_threshold, int task_num_threshold,
3091  ni_logan_device_type_t device_type, int resolution)
3092 {
3093  int should_match_rev = 1;
3094  int module_count = 0;
3095  ni_logan_device_context_t *dev_ctxt_arr = NULL;
3096  int32_t *module_id_arr = NULL;
3097  int32_t best_load_module_id = -1;
3098  ni_logan_device_pool_t *p_device_pool = NULL;
3099  ni_logan_device_queue_t *coders = NULL;
3100  ni_logan_device_context_t *p_device_context = NULL;
3101  ni_logan_session_context_t xCtxt = { 0 };
3102  int *card_remove = NULL;
3103  uint64_t reserved_memory = 0;
3104  int needed_memory = 0;
3105  int retval = 0;
3106  int ret = 0;
3107  int i = 0;
3108 
3109  if (p_hw_device_info == NULL ||
3110  (task_mode != 0 && task_mode != 1) ||
3111  load_threshold <= 0 ||
3112  load_threshold > 100 ||
3113  task_num_threshold < 0 ||
3114  task_num_threshold > NI_LOGAN_MAX_CONTEXTS_PER_HW_INSTANCE ||
3115  (device_type != NI_LOGAN_DEVICE_TYPE_DECODER
3116  && device_type != NI_LOGAN_DEVICE_TYPE_ENCODER))
3117  {
3118  if (p_hw_device_info != NULL)
3119  {
3120  p_hw_device_info->err_code = NI_LOGAN_RETCODE_INVALID_PARAM;
3121  }
3122 
3123  ni_log(NI_LOG_ERROR, "Error Invalid input params: p_hw_device_info %p realtime %d load_thread %d task_num_threshold %d device_type %d\n",
3124  p_hw_device_info, task_mode, load_threshold, task_num_threshold, device_type);
3125  LRETURN;
3126  }
3127 
3128  if (ni_logan_rsrc_init(1, -1) < 0)
3129  {
3130  ni_log(NI_LOG_ERROR, "Error rsrc init fail in ni_logan_check_hw_info..\n");
3131  p_hw_device_info->err_code = NI_LOGAN_RETCODE_FAILURE;
3132  LRETURN;
3133  }
3134 
3135  p_device_pool = ni_logan_rsrc_get_device_pool();
3136  if (!p_device_pool)
3137  {
3138  ni_log(NI_LOG_ERROR, "Error get device pool info ..\n");
3140  LRETURN;
3141  }
3142 
3143  if (NI_LOGAN_RETCODE_SUCCESS != (ret = ni_logan_rsrc_refresh(should_match_rev)))
3144  {
3145  ni_log(NI_LOG_ERROR, "Error: resource pool records might be corrupted!!\n");
3146  p_hw_device_info->err_code = ret;
3147  LRETURN;
3148  }
3149 
3150 #ifdef _WIN32
3151  if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE)) // no time-out interval)
3152  {
3153  ni_log(NI_LOG_ERROR, "ERROR: Failed to obtain mutex: %p\n", p_device_pool->lock);
3154  LRETURN;
3155  }
3156 #elif defined(__linux__)
3157  if (flock(p_device_pool->lock, LOCK_EX))
3158  {
3159  ni_log(NI_LOG_ERROR, "Error flock() failed\n");
3161  LRETURN;
3162  }
3163 #endif
3164 
3165  coders = p_device_pool->p_device_queue;
3166  if (!coders)
3167  {
3168  ni_log(NI_LOG_ERROR, "Error pdevice_queue null!!\n");
3170  LRETURN;
3171  }
3172 
3174  //coders->decoders_cnt == coder->encoders_cnt has checked in the ni_logan_rsrc_refresh
3175  p_hw_device_info->available_card_num = coders->decoders_cnt;
3176  if (p_hw_device_info->card_info == NULL) {
3177  p_hw_device_info->card_info = (card_info_t *)malloc(sizeof(card_info_t) * p_hw_device_info->available_card_num);
3178  }
3179 
3180  if (!p_hw_device_info->card_info)
3181  {
3182  ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for card_info\n", NI_ERRNO);
3183  p_hw_device_info->err_code = NI_LOGAN_RETCODE_ERROR_MEM_ALOC;
3184  LRETURN;
3185  } else {
3186  for (i = 0; i < p_hw_device_info->available_card_num; i++)
3187  {
3188  p_hw_device_info->card_info[i].card_idx = -1;
3189  p_hw_device_info->card_info[i].load = -1;
3190  p_hw_device_info->card_info[i].task_num = -1;
3192  }
3193  }
3194  p_hw_device_info->card_current_card = -1;
3195  p_hw_device_info->err_code = NI_LOGAN_RETCODE_SUCCESS;
3197 
3198  //card_remove is used to record the card which cannot used know
3199  card_remove = (int32_t *)malloc(sizeof(int32_t) * p_hw_device_info->available_card_num);
3200  if (!card_remove)
3201  {
3202  ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for card_remove\n", NI_ERRNO);
3203  p_hw_device_info->err_code = NI_LOGAN_RETCODE_ERROR_MEM_ALOC;
3204  LRETURN;
3205  }
3206  memset(card_remove, 0, sizeof(int32_t) * p_hw_device_info->available_card_num);
3207 
3208  module_count = coders->decoders_cnt;
3209  dev_ctxt_arr = (ni_logan_device_context_t *)malloc(sizeof(ni_logan_device_context_t) * module_count);
3210  if (!dev_ctxt_arr)
3211  {
3212  ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for ni_logan_rsrc_detect\n", NI_ERRNO);
3213  p_hw_device_info->err_code = NI_LOGAN_RETCODE_ERROR_MEM_ALOC;
3214  LRETURN;
3215  }
3216  module_id_arr = (int32_t *)malloc(sizeof(int32_t) * module_count);
3217  if (!module_id_arr)
3218  {
3219  ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for ni_logan_rsrc_detect\n", NI_ERRNO);
3220  p_hw_device_info->err_code = NI_LOGAN_RETCODE_ERROR_MEM_ALOC;
3221  LRETURN;
3222  }
3223 
3224  //decoder info start
3225  memcpy(module_id_arr, coders->decoders, sizeof(int32_t) * module_count);
3226 
3227  //First module ID in coders->decoders/encoders is of lowest load
3228  memcpy((void *)&best_load_module_id, module_id_arr, sizeof(int32_t));
3229  qsort(module_id_arr, module_count, sizeof(int32_t), int_cmp);
3230 
3231  p_hw_device_info->card_current_card = best_load_module_id;
3232 
3233  task_num_threshold = task_num_threshold > NI_LOGAN_MAX_CONTEXTS_PER_HW_INSTANCE ? NI_LOGAN_MAX_CONTEXTS_PER_HW_INSTANCE : task_num_threshold;
3234 
3235  for (i = 0; i < p_hw_device_info->available_card_num; i++)
3236  {
3237  memset(&xCtxt, 0, sizeof(xCtxt));
3238  p_device_context = ni_logan_rsrc_get_device_context(device_type, module_id_arr[i]);
3239 
3241  if (p_device_context)
3242  {
3243  xCtxt.blk_io_handle = ni_logan_device_open(p_device_context->p_device_info->blk_name,
3244  &(xCtxt.max_nvme_io_size));
3245  xCtxt.device_handle = xCtxt.blk_io_handle;
3246  //Check device can be opend
3247  if (NI_INVALID_DEVICE_HANDLE == xCtxt.device_handle)
3248  {
3249  ni_log(NI_LOG_ERROR, "Error open device %s, blk device %s\n",
3250  p_device_context->p_device_info->dev_name,
3251  p_device_context->p_device_info->blk_name);
3252  ni_logan_rsrc_free_device_context(p_device_context);
3253  card_remove[i] = 1;
3254  continue;
3255  }
3256 #ifdef _WIN32
3258  if (NI_INVALID_EVENT_HANDLE == xCtxt.event_handle)
3259  {
3260  ni_logan_rsrc_free_device_context(p_device_context);
3262  ni_log(NI_LOG_ERROR, "ERROR %d: print_perf() create event\n", NI_ERRNO);
3263  continue;
3264  }
3265 #endif
3266 
3267  //Check decode/encode can be queired
3268  xCtxt.hw_id = p_device_context->p_device_info->hw_id;
3269  if (NI_LOGAN_RETCODE_SUCCESS != ni_logan_device_session_query(&xCtxt, device_type))
3270  {
3272 #ifdef _WIN32
3274 #endif
3275  ni_log(NI_LOG_ERROR, "Error query %s %s %s.%d\n", (device_type == NI_LOGAN_DEVICE_TYPE_DECODER) ? "decoder" : "encoder",
3276  p_device_context->p_device_info->dev_name,
3277  p_device_context->p_device_info->blk_name,
3278  p_device_context->p_device_info->hw_id);
3279  ni_logan_rsrc_free_device_context(p_device_context);
3280  card_remove[i] = 1;
3281  continue;
3282  }
3284 #ifdef _WIN32
3286 #endif
3287 
3288  if (0 == xCtxt.load_query.total_contexts)
3289  {
3290  xCtxt.load_query.current_load = 0;
3291  }
3292 
3293  p_hw_device_info->card_info[i].card_idx = i;
3294  if (device_type == NI_LOGAN_DEVICE_TYPE_ENCODER)
3295  p_hw_device_info->card_info[i].load = xCtxt.load_query.fw_model_load;//customer want use the model_load for encoder
3296  else
3297  p_hw_device_info->card_info[i].load = xCtxt.load_query.current_load;
3298  p_hw_device_info->card_info[i].task_num = xCtxt.load_query.total_contexts;
3300 
3301  ni_logan_rsrc_free_device_context(p_device_context);
3302  }
3303  }
3304 
3305  //mark the card removed depends on the load_threshold or task_num_threshold
3306  for (i = 0; i < p_hw_device_info->available_card_num; i++)
3307  {
3308  ni_log(NI_LOG_INFO, "%s Card[%d] load %d task_num %d memory_usage %d\n",
3309  (device_type == 0 ? "Decoder" : "Encoder"), i,
3310  p_hw_device_info->card_info[i].load,
3311  p_hw_device_info->card_info[i].task_num,
3313  if (task_mode)
3314  {
3315  if (p_hw_device_info->card_info[i].load > load_threshold ||
3316  p_hw_device_info->card_info[i].task_num > task_num_threshold)
3317  card_remove[i] = 1;
3318  } else {
3319  if (p_hw_device_info->card_info[i].task_num > task_num_threshold)
3320  card_remove[i] = 1;
3321  }
3322  }
3323 
3324  if (task_mode)
3325  {
3326  //select the min_task_num
3327  int min_task_num = p_hw_device_info->card_info[0].max_task_num;
3328  for (i = 0; i < p_hw_device_info->available_card_num; i++)
3329  {
3330  if (p_hw_device_info->card_info[i].task_num < min_task_num &&
3331  card_remove[i] == 0)
3332  min_task_num = p_hw_device_info->card_info[i].task_num;
3333  }
3334 
3335  //select the min load
3336  int min_load = 100;
3337  for (i = 0; i < p_hw_device_info->available_card_num; i++)
3338  {
3339  if (p_hw_device_info->card_info[i].load < min_load &&
3340  card_remove[i] == 0 &&
3341  p_hw_device_info->card_info[i].task_num == min_task_num)
3342  {
3343  min_load = p_hw_device_info->card_info[i].load;
3344  p_hw_device_info->card_current_card = i;
3345  }
3346  }
3347  }
3348  else
3349  {
3350  int min_task_num = p_hw_device_info->card_info[0].max_task_num;
3351  for (i = 0; i < p_hw_device_info->available_card_num; i++)
3352  {
3353  if (p_hw_device_info->card_info[i].task_num < min_task_num &&
3354  card_remove[i] == 0)
3355  {
3356  p_hw_device_info->card_current_card = i;
3357  min_task_num = p_hw_device_info->card_info[i].task_num;
3358  }
3359  }
3360  }
3361 
3362  if ((p_hw_device_info->card_info[p_hw_device_info->card_current_card].task_num + 1 >= task_num_threshold) ||
3363  (p_hw_device_info->card_info[p_hw_device_info->card_current_card].load > load_threshold && task_mode))
3364  p_hw_device_info->card_current_card = -1;
3365 
3366  if (p_hw_device_info->card_current_card >= 0 && p_hw_device_info->card_current_card < p_hw_device_info->available_card_num)
3367  retval = 1; //has the card to use
3368 
3369  //check if the memory is enough
3370  reserved_memory = ((uint64_t)(100 - xCtxt.load_query.fw_video_mem_usage)) * VDI_INIT_VMEM_SIZE / 100;
3371  if (resolution <= 1280*720)
3372  {
3373  needed_memory = VDI_INIT_VMEM_SIZE / 32;
3374  }
3375  else if (resolution <= 1920*1080)
3376  {
3377  needed_memory = VDI_INIT_VMEM_SIZE / 16;
3378  }
3379  else if (resolution <= 3840*2160)
3380  {
3381  needed_memory = VDI_INIT_VMEM_SIZE / 8;
3382  }
3383  else
3384  {
3385  needed_memory = VDI_INIT_VMEM_SIZE / 4;
3386  }
3387  if (device_type == NI_LOGAN_DEVICE_TYPE_ENCODER) {
3388  //if (reserved_memory < resolution * 3 / 2 * 12 + 7 * 1024 * 1024) //12 * resolution bitstreams buffer + 7M max WAVEBUFFER
3389  needed_memory = needed_memory > resolution * 3 / 2 * 12 + 7 * 1024 * 1024 ? needed_memory : resolution * 3 / 2 * 12 + 7 * 1024 * 1024;
3390  if (reserved_memory < needed_memory)
3391  {
3392  ni_log(NI_LOG_ERROR, "Resolution Unavailable\n");
3393  p_hw_device_info->card_current_card = -1;
3394  retval = 0;
3395  }
3396  } else if (device_type == NI_LOGAN_DEVICE_TYPE_DECODER) {
3397  //if (reserved_memory < 39 * 1024 * 1024)
3398  //39M is approximately equal to 32M(bitstream) + 7M max WAVEBUFFER
3399  needed_memory = needed_memory > 39 * 1024 * 1024 ? needed_memory : 39 * 1024 * 1024;
3400  if (reserved_memory < needed_memory)
3401  {
3402  ni_log(NI_LOG_ERROR, "Resolution Unavailable\n");
3403  p_hw_device_info->card_current_card = -1;
3404  retval = 0;
3405  }
3406  }
3407 
3408 #ifdef _WIN32
3409  ReleaseMutex((HANDLE)p_device_pool->lock);
3410 
3411 #elif defined(__linux__)
3412  if (flock(p_device_pool->lock, LOCK_UN))
3413  {
3414  ni_log(NI_LOG_ERROR, "Error flock() failed\n");
3415  p_hw_device_info->err_code = NI_LOGAN_RETCODE_ERROR_UNLOCK_DEVICE;
3416  retval = 0;
3417  LRETURN;
3418  }
3419 #endif
3420 
3421 END:
3422  fflush(stderr);
3423  if (module_id_arr)
3424  free(module_id_arr);
3425  if (dev_ctxt_arr)
3426  free(dev_ctxt_arr);
3427  if (card_remove)
3428  free(card_remove);
3429 
3430  ni_logan_rsrc_free_device_pool(p_device_pool);
3431  ni_log(NI_LOG_INFO, "Select device_type %s card_current_card %d retval %d\n",
3432  ((device_type == 0) ? "decode" : "encode"), p_hw_device_info->card_current_card, retval);
3433  return retval;
3434 }
3435 
3436 /*!*****************************************************************************
3437 * \brief Remove an NetInt h/w device from resource pool on the host.
3438 *
3439 * \param[in] p_dev the NVMe device name
3440 *
3441 * \return
3442 * NI_LOGAN_RETCODE_SUCCESS
3443 * NI_LOGAN_RETCODE_FAILURE
3444 *******************************************************************************/
3445 int ni_logan_rsrc_remove_device(const char* dev)
3446 {
3447  int i, j, count, rc = NI_LOGAN_RETCODE_FAILURE;
3448  ni_logan_device_queue_t *p_device_queue = NULL;
3450  ni_logan_device_context_t *p_decoder_device_ctx = NULL, *p_encoder_device_ctx = NULL;
3451 
3452  if (!dev)
3453  {
3454  ni_log(NI_LOG_INFO, "%s: ERROR input parameter\n", __FUNCTION__);
3455  return NI_LOGAN_RETCODE_FAILURE;
3456  }
3457 
3458  if (p_device_pool)
3459  {
3460 #ifdef _WIN32
3461  // no time-out interval) //we got the mutex
3462  if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE))
3463  {
3464  ni_log(NI_LOG_INFO, "ERROR: ni_logan_rsrc_release_resource() failed to obtain mutex: %p\n",
3465  p_device_pool->lock);
3466  }
3467 #elif defined(__linux__) || defined(__APPLE__)
3468  flock(p_device_pool->lock, LOCK_EX);
3469 #endif
3470 
3471  p_device_queue = p_device_pool->p_device_queue;
3472  count = p_device_queue->decoders_cnt;
3473  int guid = -1;
3474  for (i = 0; i < count; i++)
3475  {
3476  guid = p_device_queue->decoders[i];
3477  p_decoder_device_ctx = ni_logan_rsrc_get_device_context(NI_LOGAN_DEVICE_TYPE_DECODER, guid);
3478  p_encoder_device_ctx = ni_logan_rsrc_get_device_context(NI_LOGAN_DEVICE_TYPE_ENCODER, guid);
3479  if (p_decoder_device_ctx && p_encoder_device_ctx && 0 == strcmp(p_decoder_device_ctx->p_device_info->dev_name, dev) &&
3480  0 == strcmp(p_encoder_device_ctx->p_device_info->dev_name, dev))
3481  {
3482  // found the device_info and remove its lock and storage
3483  char enc_lck_name[32] = {0};
3484  char dec_lck_name[32] = {0};
3485  ni_logan_rsrc_get_lock_name(NI_LOGAN_DEVICE_TYPE_ENCODER, guid, enc_lck_name, sizeof(enc_lck_name));
3486  ni_logan_rsrc_get_lock_name(NI_LOGAN_DEVICE_TYPE_DECODER, guid, dec_lck_name, sizeof(dec_lck_name));
3487  ni_log(NI_LOG_INFO, "dec_guid %d shm_name: %s lck_name: %s, "
3488  "enc_guid %d shm_name: %s lck_name: %s \n",
3489  guid, p_decoder_device_ctx->shm_name, dec_lck_name,
3490  guid, p_encoder_device_ctx->shm_name, enc_lck_name);
3491  // check if device can be removed
3492  if (0 != ni_logan_rsrc_check_sw_instance(p_decoder_device_ctx, NI_LOGAN_DEVICE_TYPE_DECODER)) //check decoder
3493  {
3494  ni_logan_rsrc_free_device_context(p_decoder_device_ctx);
3495  ni_logan_rsrc_free_device_context(p_encoder_device_ctx);
3496  break;
3497  }
3498  else if (0 != ni_logan_rsrc_check_sw_instance(p_encoder_device_ctx, NI_LOGAN_DEVICE_TYPE_ENCODER)) //check encoder
3499  {
3500  ni_logan_rsrc_free_device_context(p_decoder_device_ctx);
3501  ni_logan_rsrc_free_device_context(p_encoder_device_ctx);
3502  break;
3503  }
3504 
3505  // remove it from coders queue and decrement device_info counter, re-arrange
3506  // coders queue
3507 #ifdef _WIN32
3508  CloseHandle(p_decoder_device_ctx->lock);
3509  CloseHandle(p_encoder_device_ctx->lock);
3511 #elif defined(__linux__) || defined(__APPLE__)
3512 
3513 #ifndef __ANDROID__
3514 
3515  if (0 == shm_unlink(p_decoder_device_ctx->shm_name))
3516  {
3517  ni_log(NI_LOG_INFO, "dec shm_name %s deleted.\n", p_decoder_device_ctx->shm_name);
3518  }
3519  else
3520  {
3521  ni_log(NI_LOG_INFO, "dec shm_name %s deletion failure.\n", p_decoder_device_ctx->shm_name);
3522  break;
3523  }
3524 
3525  if (0 == shm_unlink(p_encoder_device_ctx->shm_name))
3526  {
3527  ni_log(NI_LOG_INFO, "enc shm_name %s deleted.\n", p_encoder_device_ctx->shm_name);
3528  }
3529  else
3530  {
3531  ni_log(NI_LOG_INFO, "enc shm_name %s deletion failure.\n", p_encoder_device_ctx->shm_name);
3532  break;
3533  }
3534 
3535  if (0 == unlink(dec_lck_name))
3536  {
3537  ni_log(NI_LOG_INFO, "dec lck_name %s deleted.\n", dec_lck_name);
3538  }
3539  else
3540  {
3541  ni_log(NI_LOG_INFO, "dec lck_name %s deletion failure.\n", dec_lck_name);
3542  break;
3543  }
3544 
3545  if (0 == unlink(enc_lck_name))
3546  {
3547  ni_log(NI_LOG_INFO, "enc lck_name %s deleted.\n", enc_lck_name);
3548  }
3549  else
3550  {
3551  ni_log(NI_LOG_INFO, "enc lck_name %s deletion failure.\n", enc_lck_name);
3552  break;
3553  }
3554 #endif
3555 
3556 #endif
3557  // move everything after position i forward
3558  for (j = i + 1; j < count; j++)
3559  {
3560  p_device_queue->decoders[j - 1] = p_device_queue->decoders[j];
3561  p_device_queue->encoders[j - 1] = p_device_queue->encoders[j];
3562  }
3563  p_device_queue->decoders[count - 1] = -1;
3564  p_device_queue->encoders[count - 1] = -1;
3565  p_device_queue->decoders_cnt--;
3566  p_device_queue->encoders_cnt--;
3567 #if defined(__linux__) || defined(__APPLE__)
3568  if (msync((void *)p_device_pool->p_device_queue, sizeof(ni_logan_device_queue_t),
3569  MS_SYNC | MS_INVALIDATE))
3570  {
3571  ni_log(NI_LOG_ERROR, "%s msync", __FUNCTION__);
3572  }
3573  else
3574  {
3575  ni_log(NI_LOG_INFO, "%s deleted successfully !\n", dev);
3577  }
3578 #endif
3579  break;
3580  }
3581 
3582  ni_logan_rsrc_free_device_context(p_decoder_device_ctx);
3583  ni_logan_rsrc_free_device_context(p_encoder_device_ctx);
3584  }
3585 
3586 #ifdef _WIN32
3587  ReleaseMutex(p_device_pool->lock);
3588 #elif defined(__linux__) || defined(__APPLE__)
3589  flock(p_device_pool->lock, LOCK_UN);
3590 #endif
3591  ni_logan_rsrc_free_device_pool(p_device_pool);
3592  }
3593 
3594  return rc;
3595 }
3596 
3597 static int int_cmp(const void *a, const void *b)
3598 {
3599  const int *ia = (const int *)a;
3600  const int *ib = (const int *)b;
3601  return *ia - *ib;
3602  /* integer comparison: returns negative if b > a and positive if a > b */
3603 }
3604 
3605 
3606 /*!*****************************************************************************
3607 * \brief Add an NetInt h/w device into resource pool on the host.
3608 *
3609 * \param[in] p_dev the NVMe device name
3610 * \param[in] should_match_rev 0: transcoder firmware revision matching the
3611 * library's version is NOT required for placing
3612 * the transcoder into resource pool; 1: otherwise
3613 *
3614 * \return
3615 * NI_LOGAN_RETCODE_SUCCESS
3616 * NI_LOGAN_RETCODE_FAILURE
3617 *******************************************************************************/
3618 int ni_logan_rsrc_add_device(const char* dev, int should_match_rev)
3619 {
3620  uint32_t i=0, j=0, k=0, count=0, fw_ver_compat_warning=0;
3622  ni_device_handle_t fd = 0;
3623  ni_logan_device_queue_t *p_device_queue;
3624  ni_logan_device_info_t device_info;
3627  int guids[LOGAN_MAX_DEVICE_CNT];
3628 
3629  if (!dev)
3630  {
3631  ni_log(NI_LOG_INFO, "%s ERROR input parameter\n", __FUNCTION__);
3632  return NI_LOGAN_RETCODE_FAILURE;
3633  }
3634  // get the first free guid that is in sequence 0,1,2, ... n, so that empty
3635  // index left behind by device removal can be reused
3636  if (p_device_pool)
3637  {
3638 #ifdef _WIN32
3639  // no time-out interval) //we got the mutex
3640  if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE))
3641  {
3642  ni_log(NI_LOG_INFO, "ERROR: ni_logan_rsrc_release_resource() failed to obtain mutex: %p\n",
3643  p_device_pool->lock);
3644  }
3645 #elif defined(__linux__) || defined(__APPLE__)
3646  flock(p_device_pool->lock, LOCK_EX);
3647 #endif
3648 
3649  p_device_queue = p_device_pool->p_device_queue;
3650  count = p_device_queue->decoders_cnt;
3651 
3652  int32_t guid = -1;
3653  for (i = 0; i < count; i++)
3654  {
3656  if (tmp_ctxt && 0 == strcmp(tmp_ctxt->p_device_info->dev_name, dev))
3657  {
3659  ni_log(NI_LOG_INFO, "Transcoder %s already active, guid: %d\n",
3660  dev, p_device_queue->decoders[i]);
3662  LRETURN;
3663  }
3664  else
3665  {
3667  }
3668 
3669  guids[i] = p_device_queue->decoders[i];
3670  }
3671 
3672  // sort guid index in ascending order and pick the first free guid
3673  qsort(guids, count, sizeof(int), int_cmp);
3674  for (i = 0; i < count; i++)
3675  {
3676  if (1 == guids[i] - guid)
3677  {
3678  guid = guids[i];
3679  }
3680  else
3681  {
3682  break;
3683  }
3684  }
3685  guid++;
3686  if (guid >= LOGAN_MAX_DEVICE_CNT || count >= LOGAN_MAX_DEVICE_CNT)
3687  {
3688  ni_log(NI_LOG_ERROR, "Warning: initialized Netint devices(%d) on "
3689  "system reach limit of LOGAN_MAX_DEVICE_CNT(%d)\n",
3690  count, LOGAN_MAX_DEVICE_CNT);
3691  ni_log(NI_LOG_ERROR, "New transcoder %s should not be added\n", dev);
3693  LRETURN;
3694  }
3695  else
3696  {
3697  ni_log(NI_LOG_INFO, "GUID to be added: %d\n", guid);
3698  }
3699 
3700  // retrieve the device_info capability info from f/w
3701  memset(&device_info, 0, sizeof(ni_logan_device_info_t));
3702  sprintf(device_info.dev_name, "%s", dev);
3703  memset(&cap, 0, sizeof(ni_logan_device_capability_t));
3704 
3705  uint32_t tmp_io_size;
3706 
3707  ni_logan_find_blk_name(device_info.dev_name, device_info.blk_name, sizeof(device_info.blk_name));
3708  fd = ni_logan_device_open(device_info.blk_name, &tmp_io_size);
3709 
3710  if (NI_INVALID_DEVICE_HANDLE == fd)
3711  {
3713  ni_log(NI_LOG_INFO, "Failed to open device: %s %s\n", device_info.dev_name, device_info.blk_name);
3714  LRETURN;
3715  }
3716 
3717  rc = ni_logan_device_capability_query(fd, &cap);
3718  if ((NI_LOGAN_RETCODE_SUCCESS == rc) && (cap.device_is_xcoder) &&
3719  (! should_match_rev ||
3720  (should_match_rev && ni_logan_is_fw_compatible(cap.fw_rev))))
3721  {
3722  fw_ver_compat_warning = 0;
3723  if (ni_logan_is_fw_compatible(cap.fw_rev) == 2)
3724  {
3725  ni_log(NI_LOG_INFO, "WARNING - Query %s FW version: %.*s is below the minimum support version for "
3726  "this SW version. Some features may be missing.\n",
3727  device_info.dev_name, (int) sizeof(cap.fw_rev), cap.fw_rev);
3728  fw_ver_compat_warning = 1;
3729  }
3730 
3731  ni_log(NI_LOG_INFO, "%s num_hw: %d\n", device_info.dev_name, cap.hw_elements_cnt);
3732  uint32_t total_modules = cap.h264_decoders_cnt + cap.h264_encoders_cnt +
3734 
3735  ni_logan_device_info_t *pCoderInfo = NULL;
3736  int decoders_cnt = 0, encoders_cnt = 0;
3737  for (j = 0; j < total_modules; j++)
3738  {
3739  int rc;
3740  pCoderInfo = NULL;
3741 
3742  memset(&device_info, 0, sizeof(ni_logan_device_info_t));
3743  sprintf(device_info.dev_name, "%s", dev);
3744  ni_logan_find_blk_name(device_info.dev_name, device_info.blk_name, sizeof(device_info.blk_name));
3745  device_info.hw_id = cap.xcoder_devices[j].hw_id;
3746  device_info.fw_ver_compat_warning = fw_ver_compat_warning;
3747  memcpy(device_info.fw_rev, cap.fw_rev, sizeof(device_info.fw_rev));
3748  memcpy(device_info.fw_commit_hash, cap.fw_commit_hash, sizeof(device_info.fw_commit_hash) - 1);
3749  memcpy(device_info.fw_commit_time, cap.fw_commit_time, sizeof(device_info.fw_commit_time) - 1);
3750  memcpy(device_info.fw_branch_name, cap.fw_branch_name, sizeof(device_info.fw_branch_name) - 1);
3751  device_info.max_fps_1080p = cap.xcoder_devices[j].max_1080p_fps;
3754 
3755  // check if entry has been created for this h/w (hw_id):
3756  // if not, then create a new entry; otherwise just update it
3757  ni_logan_device_context_t *p_device_context = ni_logan_rsrc_get_device_context(device_info.device_type, guid);
3758  if ( (p_device_context) && (p_device_context->p_device_info->hw_id == device_info.hw_id) )
3759  {
3760  pCoderInfo = p_device_context->p_device_info;
3761  }
3763  if (pCoderInfo)
3764  {
3765  ni_log(NI_LOG_INFO, "%s h/w id %d update\n", NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type ? "decoder" :
3766  "encoder", device_info.hw_id);
3767  rc = ni_logan_rsrc_fill_device_info(pCoderInfo, fmt, device_info.device_type, &cap.xcoder_devices[j]);
3768  if (NI_LOGAN_RETCODE_SUCCESS == rc)
3769  {
3770  if (NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type)
3771  {
3772  decoders_cnt++;
3773  }
3774  else
3775  {
3776  encoders_cnt++;
3777  }
3778  }
3779  }
3780  else
3781  {
3782  ni_log(NI_LOG_INFO, "%s h/w id %d create\n", NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type ? "decoder" :
3783  "encoder", device_info.hw_id);
3784  pCoderInfo = &device_info;
3785 
3786  rc = ni_logan_rsrc_fill_device_info(pCoderInfo, fmt, device_info.device_type, &cap.xcoder_devices[j]);
3787  if (NI_LOGAN_RETCODE_SUCCESS == rc)
3788  {
3790  pCoderInfo->module_id = guid;
3791  if (NI_LOGAN_DEVICE_TYPE_DECODER == device_info.device_type)
3792  {
3793  decoders_cnt++;
3794  }
3795  else
3796  {
3797  encoders_cnt++;
3798  }
3799  ni_logan_rsrc_get_one_device_info(&device_info);
3800  }
3801  }
3802  } // for each device_info module
3803 
3804  // there are some cases that updating failed or NI_LOGAN_shm_* already exist.
3805  // so check and update device pool here
3806  if ((decoders_cnt == (cap.h264_decoders_cnt + cap.h265_decoders_cnt)) &&
3807  (encoders_cnt == (cap.h264_encoders_cnt + cap.h265_encoders_cnt)))
3808  {
3809  p_device_queue->decoders_cnt++;
3810  p_device_queue->decoders[p_device_queue->decoders_cnt - 1] = pCoderInfo->module_id;
3811  p_device_queue->encoders_cnt++;
3812  p_device_queue->encoders[p_device_queue->encoders_cnt - 1] = pCoderInfo->module_id;
3813  }
3814  else
3815  {
3817  ni_log(NI_LOG_INFO, "Failed to update share memory: %s %s\n", device_info.dev_name, device_info.blk_name);
3818  LRETURN;
3819  }
3820 
3821 #if defined(__linux__) || defined(__APPLE__)
3822  if (msync((void *)p_device_pool->p_device_queue, sizeof(ni_logan_device_queue_t),
3823  MS_SYNC | MS_INVALIDATE))
3824  {
3825  ni_log(NI_LOG_ERROR, "%s msync\n", __FUNCTION__);
3827  } else
3828  ni_log(NI_LOG_INFO, "%s added successfully !\n", dev);
3829 #endif
3830  }
3831  else
3832  { // xcoder NOT supported
3834  ni_log(NI_LOG_INFO, "Query %s rc %d NOT xcoder-support: %u, or mismatch revision: "
3835  "%s; not added\n", dev, rc, cap.device_is_xcoder, cap.fw_rev);
3836  }
3837 
3838  END:
3839  if (NI_INVALID_DEVICE_HANDLE != fd)
3840  {
3842  }
3843 
3844 #ifdef _WIN32
3845  ReleaseMutex(p_device_pool->lock);
3846 #elif defined(__linux__) || defined(__APPLE__)
3847  flock(p_device_pool->lock, LOCK_UN);
3848 #endif
3849 
3850  ni_logan_rsrc_free_device_pool(p_device_pool);
3851  }
3852 
3853  return rc;
3854 }
3855 
3856 /*!*****************************************************************************
3857 * \brief Free all resources taken by the device pool
3858 *
3859 * \param[in] p_device_pool Poiner to a device pool struct
3860 *
3861 * \return None
3862 *******************************************************************************/
3864 {
3865  if (p_device_pool)
3866  {
3867  if (NI_INVALID_LOCK_HANDLE != p_device_pool->lock)
3868  {
3869 #ifdef _WIN32
3870  CloseHandle(p_device_pool->lock);
3871 #elif defined(__linux__) || defined(__APPLE__)
3872  close(p_device_pool->lock);
3873 #endif
3874  }
3875 #ifdef _WIN32
3876  UnmapViewOfFile(p_device_pool->p_device_queue);
3877 #else
3878  munmap(p_device_pool->p_device_queue, sizeof(ni_logan_device_queue_t));
3879 #endif
3880 
3881  free(p_device_pool);
3882  p_device_pool = NULL;
3883  }
3884 }
3885 
3886 /*!*****************************************************************************
3887  * \brief lock a file lock and open a session on a device
3888  *
3889  * \param device_type
3890  * \param lock
3891  *
3892  * \return None
3893  *******************************************************************************/
3894 int ni_logan_rsrc_lock_and_open(int device_type, ni_lock_handle_t* lock)
3895 {
3896 
3897  int count = 0;
3899  const char *lock_name = device_type == NI_LOGAN_DEVICE_TYPE_DECODER ? CODERS_RETRY_DELCK_NAME : CODERS_RETRY_ENLCK_NAME;
3900 #ifdef _WIN32
3901  // Here we try to open the file lock, retry if it failed
3902  *lock = CreateMutex(
3903  NULL, // default security attributes
3904  FALSE, // initially no owned
3905  lock_name // unnamed mutex
3906  );
3907 
3908  if (NULL == *lock)
3909  {
3910  ni_log(NI_LOG_ERROR, "%s() CreateMutex %s failed, error=%d\n",
3911  __FUNCTION__, lock_name, NI_ERRNO);
3913  }
3914 #else
3915  do
3916  {
3917  if (count > 0)
3918  {
3919  //sleep 10ms if the file lock is locked by other FFmpeg process
3921  }
3922  // Here we try to open the file lock, retry if it failed
3923  *lock = open(lock_name, O_RDWR | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
3924  if (*lock < 0)
3925  {
3926  count++;
3927  if (count > MAX_LOCK_RETRY)
3928  {
3929  ni_log(NI_LOG_TRACE, "Can not lock down the file lock after 6s\n");
3931  }
3932  }
3933  }
3934  while (*lock < 0);
3935 #endif
3936 
3937  // Now the lock is free so we lock it down
3938  count = 0;
3939  do
3940  {
3941  //sleep 10ms if the file lock is locked by other FFmpeg process
3942  if (count > 0)
3943  {
3944  //sleep 10ms if the file lock is locked by other FFmpeg process
3946  }
3947 #ifdef _WIN32
3948  DWORD ret = WaitForSingleObject(*lock, 1); // time-out 1ms
3949  if (WAIT_OBJECT_0 == ret)
3950  {
3951  status = NI_LOGAN_RETCODE_SUCCESS;
3952  }
3953  else if (WAIT_TIMEOUT != ret)
3954  {
3955  ni_log(NI_LOG_ERROR, "ERROR %d: %s() failed to obtain mutex\n", __FUNCTION__,
3956  NI_ERRNO);
3957  }
3958 #else
3959  status = flock(*lock, LOCK_EX);
3960 #endif
3961  if (status != 0)
3962  {
3963  count++;
3964  if (count > MAX_LOCK_RETRY)
3965  {
3966  ni_log(NI_LOG_ERROR, "Can not put down the lock after 6s\n");
3968  }
3969  }
3970  }
3971  while (status != 0);
3972 
3973  return NI_LOGAN_RETCODE_SUCCESS;
3974 }
3975 
3976 /*!*****************************************************************************
3977  * \brief unlock a file lock
3978  *
3979  * \param device_type
3980  * \param lock
3981  *
3982  * \return None
3983  *******************************************************************************/
3984 int ni_logan_rsrc_unlock(int device_type, ni_lock_handle_t lock)
3985 {
3986  int status = NI_LOGAN_RETCODE_SUCCESS;
3987  int count = 0;
3988 
3989  if (lock == NI_INVALID_LOCK_HANDLE)
3990  {
3991  return NI_LOGAN_RETCODE_FAILURE;
3992  }
3993  else
3994  {
3995  do
3996  {
3997  if (count>=1)
3998  {
4000  }
4001 #ifdef _WIN32
4002  if (ReleaseMutex(lock))
4003  {
4004  status = NI_LOGAN_RETCODE_SUCCESS;
4005  }
4006 #else
4007  status = flock(lock, LOCK_UN);
4008 #endif
4009  count++;
4010  if (count > MAX_LOCK_RETRY)
4011  {
4012  ni_log(NI_LOG_TRACE, "Can not unlock the lock after 6s\n");
4014  }
4015  }
4016  while (status != NI_LOGAN_RETCODE_SUCCESS);
4017  }
4018 #ifdef _WIN32
4019  CloseHandle(lock);
4020 #else
4021  close(lock);
4022 #endif //defined(__linux__) defined
4023  return NI_LOGAN_RETCODE_SUCCESS;
4024 }
ni_logan_retcode_t
@ NI_LOGAN_RETCODE_ERROR_INVALID_HANDLE
@ NI_LOGAN_RETCODE_ERROR_UNLOCK_DEVICE
@ NI_LOGAN_RETCODE_INVALID_PARAM
@ NI_LOGAN_RETCODE_ERROR_MEM_ALOC
@ NI_LOGAN_RETCODE_ERROR_VERSION_INCOMPATIBLE
@ NI_LOGAN_RETCODE_ERROR_VPU_RECOVERY
@ NI_LOGAN_RETCODE_ERROR_GET_DEVICE_POOL
@ NI_LOGAN_RETCODE_SUCCESS
@ NI_LOGAN_RETCODE_FAILURE
@ NI_LOGAN_RETCODE_ERROR_LOCK_DOWN_DEVICE
#define LOGAN_MAX_DEVICE_CNT
#define END
#define NI_LOGAN_RETCODE_INIT_ALREADY
#define NI_LOGAN_MAX_CONTEXTS_PER_HW_INSTANCE
#define NI_LOGAN_XCODER_REVISION
Definition: ni_defs_logan.h:62
#define NI_ERRNO
#define NI_LOGAN_XCODER_FW_API_VER_SUPPORTED_MIN
Definition: ni_defs_logan.h:65
#define NI_LOGAN_XCODER_FW_VER_SUPPORTED_MIN
Definition: ni_defs_logan.h:63
#define NI_LOGAN_MAX_DEVICE_NAME_LEN
ni_logan_device_type_t
@ NI_LOGAN_DEVICE_TYPE_UPLOAD
@ NI_LOGAN_DEVICE_TYPE_ENCODER
@ NI_LOGAN_DEVICE_TYPE_DECODER
#define LRETURN
#define VDI_INIT_VMEM_SIZE
#define NI_LOGAN_XCODER_FW_API_FLAVORS_SUPPORTED
Definition: ni_defs_logan.h:64
ni_logan_retcode_t ni_logan_device_capability_query(ni_device_handle_t device_handle, ni_logan_device_capability_t *p_cap)
Queries device and returns device capability structure.
ni_device_handle_t ni_logan_device_open(const char *p_dev, uint32_t *p_max_io_size_out)
Opens device and returnes device device_handle if successful.
ni_logan_retcode_t ni_logan_device_session_query(ni_logan_session_context_t *p_ctx, ni_logan_device_type_t device_type)
Query session data from the device - Currently not implemented If device_type is NI_LOGAN_DEVICE_TYPE...
ni_logan_retcode_t ni_logan_device_session_close(ni_logan_session_context_t *p_ctx, int eos_recieved, ni_logan_device_type_t device_type)
Closes device session that was previously opened by calling ni_logan_device_session_open() If device_...
void ni_logan_device_session_context_init(ni_logan_session_context_t *p_ctx)
Initialize already allocated session context to a known state.
void ni_logan_close_event(ni_event_handle_t event_handle)
Closes event and releases resources.
void ni_logan_device_session_context_clear(ni_logan_session_context_t *p_ctx)
Clear already allocated session context to all zeros.
ni_logan_retcode_t ni_logan_encoder_init_default_params(ni_logan_encoder_params_t *p_param, int fps_num, int fps_denom, long bit_rate, int width, int height)
Initialize default encoder parameters.
ni_logan_retcode_t ni_logan_device_session_open(ni_logan_session_context_t *p_ctx, ni_logan_device_type_t device_type)
Opens a new device session depending on the device_type parameter If device_type is NI_LOGAN_DEVICE_T...
ni_event_handle_t ni_logan_create_event(void)
Create event and returnes event handle if successful.
void ni_logan_device_close(ni_device_handle_t device_handle)
Closes device and releases resources.
ni_logan_retcode_t ni_logan_decoder_init_default_params(ni_logan_decoder_params_t *p_param, int fps_num, int fps_denom, long bit_rate, int width, int height)
Initialize default decoder parameters.
#define NI_LOGAN_DEFAULT_KEEP_ALIVE_TIMEOUT
#define NI_LOGAN_MIN_BITRATE
void ni_log(ni_log_level_t level, const char *fmt,...)
print log message using ni_log_callback
Definition: ni_log_logan.c:120
@ NI_LOG_TRACE
Definition: ni_log_logan.h:67
@ NI_LOG_ERROR
Definition: ni_log_logan.h:64
@ NI_LOG_INFO
Definition: ni_log_logan.h:65
int ni_logan_rsrc_android_init()
Init android net.int.SharedBuffer service for binder using.
android::sp< INidec > service_logan
ni_logan_rsrc_device_video_ref_cap_t g_device_reference_table[2][2]
ni_logan_retcode_t ni_logan_rsrc_list_all_devices(ni_logan_device_t *p_device)
List all devices with full information including s/w instances on the system.
ni_logan_device_context_t * ni_logan_rsrc_get_device_context(ni_logan_device_type_t device_type, int guid)
Allocates and returns a pointer to ni_logan_device_context_t struct based on provided device_type and...
#define SLEEPLOOP
int ni_logan_rsrc_check_hw_available(int guid, ni_logan_device_type_t device_type)
check the NetInt h/w device in resource pool on the host.
ni_logan_retcode_t ni_logan_rsrc_list_devices(ni_logan_device_type_t device_type, ni_logan_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.
void ni_logan_rsrc_free_device_pool(ni_logan_device_pool_t *p_device_pool)
Free all resources taken by the device pool.
int ni_logan_rsrc_add_device(const char *dev, int should_match_rev)
Add an NetInt h/w device into resource pool on the host.
int ni_logan_find_device_index_by_name(void *device_coders, ni_logan_device_type_t device_type, const char *dev_name)
the card with the card name like /dev/nvme0n1 get the device index.
void ni_logan_rsrc_release_resource(ni_logan_device_context_t *p_device_context, ni_codec_t codec, unsigned long load)
Release resources allocated for decoding/encoding. function This must be called at the end of transco...
void ni_logan_rsrc_free_device_context(ni_logan_device_context_t *p_device_context)
Free previously allocated device context.
ni_logan_device_context_t * ni_logan_rsrc_allocate_direct(ni_logan_device_type_t device_type, int guid, ni_codec_t codec, int width, int height, int frame_rate, unsigned long *p_load)
Allocate resources for decoding/encoding, by designating explicitly the device to use.
int ni_logan_rsrc_get_local_device_list(char ni_logan_devices[][NI_LOGAN_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...
ni_logan_device_context_t * ni_logan_rsrc_allocate_auto(ni_logan_device_type_t device_type, ni_alloc_rule_t rule, ni_codec_t codec, int width, int height, int frame_rate, unsigned long *p_load)
Allocate resources for decoding/encoding, based on the provided rule.
int ni_logan_rsrc_codec_is_available(int guid, ni_logan_device_type_t device_type)
check the NetInt h/w device in resource pool on the host.
ni_logan_device_context_t * ni_logan_rsrc_allocate_simple_direct(ni_logan_device_type_t device_type, int guid)
Allocate resources for decoding/encoding, by designating explicitly the device to use....
int ni_logan_rsrc_check_sw_instance(ni_logan_device_context_t *p_device_context, ni_logan_device_type_t device_type)
Check software instance.
int ni_logan_rsrc_remove_device(const char *dev)
Remove an NetInt h/w device from resource pool on the host.
LIB_API void ni_logan_rsrc_print_all_devices_capability(void)
Print detailed capability information of all devices on the system.
int ni_logan_rsrc_init(int should_match_rev, int timeout_seconds)
Initialize and create all resources required to work with NETINT NVMe transcoder devices....
int ni_logan_rsrc_unlock(int device_type, ni_lock_handle_t lock)
unlock a file lock
ni_logan_device_info_t * ni_logan_rsrc_get_device_info(ni_logan_device_type_t device_type, int guid)
Query a specific device with detailed information on the system.
int ni_logan_check_hw_info(hw_device_info_t *p_hw_device_info, int task_mode, int load_threshold, int task_num_threshold, ni_logan_device_type_t device_type, int resolution)
check hw info, return the appropriate card number to use depends on the load&task_num&used resource
ni_logan_retcode_t ni_logan_rsrc_refresh(int should_match_rev)
Scan and refresh all resources on the host, taking into account hot-plugged and pulled out cards.
void ni_logan_rsrc_print_device_info(const ni_logan_device_info_t *p_device_info)
Print the content of the ni_logan_device_info_t struct.
ni_logan_device_pool_t * ni_logan_rsrc_get_device_pool(void)
Create and return the allocated ni_logan_device_pool_t struct.
int ni_logan_rsrc_update_device_load(ni_logan_device_context_t *p_device_context, int load, int sw_instance_cnt, const ni_logan_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_logan_rsrc_get_available_device(int width, int height, int frame_rate, ni_codec_t codec, ni_logan_device_type_t device_type, ni_logan_device_info_t *p_device_info)
Get the least used device that can handle decoding or encoding a video stream of certain resolution/f...
int ni_logan_rsrc_lock_and_open(int device_type, ni_lock_handle_t *lock)
lock a file lock and open a session on a device
Exported definitions related to resource management of NI T-408 devices.
@ EN_IDLE
ni_codec_t
@ EN_H264
ni_alloc_rule_t
@ EN_ALLOC_LEAST_LOAD
@ EN_ALLOC_LEAST_INSTANCE
void ni_logan_rsrc_get_lock_name(ni_logan_device_type_t device_type, int32_t guid, char *p_name, size_t max_name_len)
Returns the device lock name.
ni_logan_retcode_t ni_logan_rsrc_fill_device_info(ni_logan_device_info_t *p_device_info, ni_codec_t fmt, ni_logan_device_type_t type, ni_logan_hw_capability_t *p_hw_cap)
Update codec record info with retrieved device info from HW.
void ni_logan_rsrc_get_shm_name(ni_logan_device_type_t device_type, int32_t guid, char *p_name, size_t max_name_len)
Returns the name of shared memory of the codec record.
uint32_t g_logan_xcoder_stop_process
int ni_logan_is_fw_compatible(uint8_t fw_rev[8])
Check if a FW_rev retrieved from card is supported by libxcoder. Support is checked for API flavor,...
int ni_logan_rsrc_strcmp(const void *p_str, const void *p_str1)
String comparison function.
Private definitions related to resource management of NI T-408 devices.
#define CODERS_LCK_NAME
void ni_logan_rsrc_get_one_device_info(ni_logan_device_info_t *p_device_info)
Retrieve codec record info.
#define CODERS_SHM_NAME
void ni_logan_rsrc_update_record(ni_logan_device_context_t *p_device_context, ni_logan_session_context_t *p_session_ctx)
Updates the codec record.
#define LOCK_WAIT
#define MAX_LOCK_RETRY
int ni_logan_rsrc_enumerate_devices(char ni_logan_devices[][NI_LOGAN_MAX_DEVICE_NAME_LEN], int max_handles)
List NETINT nvme devices.
#define CODERS_RETRY_DELCK_NAME
#define CODERS_RETRY_ENLCK_NAME
ni_logan_retcode_t ni_logan_find_blk_name(const char *p_dev, char *p_out_buf, int out_buf_len)
Find NVMe name space block from device name If none is found, assume nvme multi-pathing is disabled a...
void ni_logan_usleep(int64_t usec)
Exported utility routines definition.
#define LOGAN_XCODER_MIN_ENC_PIC_WIDTH
Definition: ni_util_logan.h:66
#define LOGAN_XCODER_MIN_ENC_PIC_HEIGHT
Definition: ni_util_logan.h:67
#define NI_LOGAN_NVME_PREFIX
Definition: ni_util_logan.h:54
ni_logan_hw_capability_t xcoder_devices[NI_LOGAN_MAX_DEVICES_PER_HW_INSTANCE]
char shm_name[NI_LOGAN_MAX_DEVICE_NAME_LEN]
ni_logan_device_info_t * p_device_info
ni_logan_device_video_capability_t h264_cap
ni_logan_device_type_t device_type
char dev_name[NI_LOGAN_MAX_DEVICE_NAME_LEN]
ni_logan_device_video_capability_t h265_cap
char blk_name[NI_LOGAN_MAX_DEVICE_NAME_LEN]
ni_logan_sw_instance_info_t sw_instance[NI_LOGAN_MAX_CONTEXTS_PER_HW_INSTANCE]
unsigned long xcode_load_pixel
ni_logan_device_queue_t * p_device_queue
int32_t decoders[LOGAN_MAX_DEVICE_CNT]
int32_t encoders[LOGAN_MAX_DEVICE_CNT]
char level[NI_LOGAN_MAX_LEVEL_NAME_LEN]
char additional_info[NI_LOGAN_MAX_ADDITIONAL_INFO_LEN]
char profiles_supported[NI_LOGAN_MAX_PROFILE_NAME_LEN]
ni_logan_device_info_t encoders[LOGAN_MAX_DEVICE_CNT]
ni_logan_device_info_t decoders[LOGAN_MAX_DEVICE_CNT]
ni_logan_load_query_t load_query
ni_device_handle_t device_handle
ni_device_handle_t blk_io_handle
ni_sw_instance_status_t status
card_info_t * card_info