libxcoder  3.5.4
ni_device_api_logan.c
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * Copyright (C) 2022 NETINT Technologies
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18  * SOFTWARE.
19  *
20  ******************************************************************************/
21 
22 /*!*****************************************************************************
23 * \file ni_device_api_logan.c
24 *
25 * \brief Main NETINT device API file
26 * provides the ability to communicate with NI T-408 type hardware
27 * transcoder devices
28 *
29 *******************************************************************************/
30 
31 #ifdef _WIN32
32 #include <windows.h>
33 #elif defined(__linux__) || defined(__APPLE__)
34 #define _GNU_SOURCE //O_DIRECT is Linux-specific. One must define _GNU_SOURCE to obtain its definitions
35 #if defined(__linux__)
36 #include <sys/types.h>
37 #endif
38 #include <sys/ioctl.h>
39 #include <sys/stat.h>
40 #include <unistd.h>
41 #include <sys/ioctl.h>
42 #include <sys/mman.h>
43 #include <sys/stat.h>
44 #include <sys/time.h>
45 #include <fcntl.h>
46 #include <limits.h>
47 #include <unistd.h>
48 #include <sys/poll.h>
49 #endif
50 
51 #include "ni_device_api_logan.h"
53 #include "ni_nvme_logan.h"
54 #include "ni_util_logan.h"
55 #include "ni_rsrc_api_logan.h"
56 #include "ni_rsrc_priv_logan.h"
57 #if defined(__linux__)
58 #include "ni_logan_p2p_ioctl.h"
59 #endif
60 
63 };
64 
68 };
69 
70 #if defined(__linux__) || defined(__APPLE__)
71 static struct stat g_nvme_stat = { 0 };
72 #endif
73 
74 typedef struct _ni_err_rc_txt_entry
75 {
77  const char *str;
79 
80 static const ni_logan_err2str_entry_t ni_logan_err2str_desc[] =
81 {
82  NI_LOGAN_RETCODE_SUCCESS, "SUCCESS",
83  NI_LOGAN_RETCODE_FAILURE, "FAILURE",
84  NI_LOGAN_RETCODE_INVALID_PARAM, "INVALID_PARAM",
85  NI_LOGAN_RETCODE_ERROR_MEM_ALOC, "ERROR_MEM_ALOC",
86  NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED, "ERROR_NVME_CMD_FAILED",
87  NI_LOGAN_RETCODE_ERROR_INVALID_SESSION, "ERROR_INVALID_SESSION",
88  NI_LOGAN_RETCODE_ERROR_RESOURCE_UNAVAILABLE, "ERROR_RESOURCE_UNAVAILABLE",
89  NI_LOGAN_RETCODE_PARAM_INVALID_NAME, "PARAM_INVALID_NAME",
90  NI_LOGAN_RETCODE_PARAM_INVALID_VALUE, "PARAM_INVALID_VALUE",
91  NI_LOGAN_RETCODE_PARAM_ERROR_FRATE, "PARAM_ERROR_FRATE",
92  NI_LOGAN_RETCODE_PARAM_ERROR_BRATE, "PARAM_ERROR_BRATE",
93  NI_LOGAN_RETCODE_PARAM_ERROR_TRATE, "PARAM_ERROR_TRATE",
94  NI_LOGAN_RETCODE_PARAM_ERROR_RC_INIT_DELAY, "PARAM_ERROR_RC_INIT_DELAY",
95  NI_LOGAN_RETCODE_PARAM_ERROR_INTRA_PERIOD, "PARAM_ERROR_INTRA_PERIOD",
96  NI_LOGAN_RETCODE_PARAM_ERROR_INTRA_QP, "PARAM_ERROR_INTRA_QP",
97  NI_LOGAN_RETCODE_PARAM_ERROR_GOP_PRESET, "PARAM_ERROR_GOP_PRESET",
98  NI_LOGAN_RETCODE_PARAM_ERROR_CU_SIZE_MODE, "PARAM_ERROR_CU_SIZE_MODE",
99  NI_LOGAN_RETCODE_PARAM_ERROR_MX_NUM_MERGE, "PARAM_ERROR_MX_NUM_MERGE",
100  NI_LOGAN_RETCODE_PARAM_ERROR_DY_MERGE_8X8_EN, "PARAM_ERROR_DY_MERGE_8X8_EN",
101  NI_LOGAN_RETCODE_PARAM_ERROR_DY_MERGE_16X16_EN, "PARAM_ERROR_DY_MERGE_16X16_EN",
102  NI_LOGAN_RETCODE_PARAM_ERROR_DY_MERGE_32X32_EN, "PARAM_ERROR_DY_MERGE_32X32_EN",
103  NI_LOGAN_RETCODE_PARAM_ERROR_CU_LVL_RC_EN, "PARAM_ERROR_CU_LVL_RC_EN",
104  NI_LOGAN_RETCODE_PARAM_ERROR_HVS_QP_EN, "PARAM_ERROR_HVS_QP_EN",
105  NI_LOGAN_RETCODE_PARAM_ERROR_HVS_QP_SCL, "PARAM_ERROR_HVS_QP_SCL",
106  NI_LOGAN_RETCODE_PARAM_ERROR_MN_QP, "PARAM_ERROR_MN_QP",
107  NI_LOGAN_RETCODE_PARAM_ERROR_MX_QP, "PARAM_ERROR_MX_QP",
108  NI_LOGAN_RETCODE_PARAM_ERROR_MX_DELTA_QP, "PARAM_ERROR_MX_DELTA_QP",
109  NI_LOGAN_RETCODE_PARAM_ERROR_CONF_WIN_TOP, "PARAM_ERROR_CONF_WIN_TOP",
110  NI_LOGAN_RETCODE_PARAM_ERROR_CONF_WIN_BOT, "PARAM_ERROR_CONF_WIN_BOT",
111  NI_LOGAN_RETCODE_PARAM_ERROR_CONF_WIN_L, "PARAM_ERROR_CONF_WIN_L",
112  NI_LOGAN_RETCODE_PARAM_ERROR_CONF_WIN_R, "PARAM_ERROR_CONF_WIN_R",
113  NI_LOGAN_RETCODE_PARAM_ERROR_USR_RMD_ENC_PARAM, "PARAM_ERROR_USR_RMD_ENC_PARAM",
114  NI_LOGAN_RETCODE_PARAM_ERROR_BRATE_LT_TRATE, "PARAM_ERROR_BRATE_LT_TRATE",
115  NI_LOGAN_RETCODE_PARAM_ERROR_RCINITDELAY, "PARAM_ERROR_RCINITDELAY",
116  NI_LOGAN_RETCODE_PARAM_ERROR_RCENABLE, "PARAM_ERROR_RCENABLE",
117  NI_LOGAN_RETCODE_PARAM_ERROR_MAXNUMMERGE, "PARAM_ERROR_MAXNUMMERGE",
118  NI_LOGAN_RETCODE_PARAM_ERROR_CUSTOM_GOP, "PARAM_ERROR_CUSTOM_GOP",
119  NI_LOGAN_RETCODE_PARAM_ERROR_PIC_WIDTH, "PARAM_ERROR_PIC_WIDTH",
120  NI_LOGAN_RETCODE_PARAM_ERROR_PIC_HEIGHT, "PARAM_ERROR_PIC_HEIGHT",
121  NI_LOGAN_RETCODE_PARAM_ERROR_DECODING_REFRESH_TYPE, "PARAM_ERROR_DECODING_REFRESH_TYPE",
122  NI_LOGAN_RETCODE_PARAM_ERROR_CUSIZE_MODE_8X8_EN, "PARAM_ERROR_CUSIZE_MODE_8X8_EN",
123  NI_LOGAN_RETCODE_PARAM_ERROR_CUSIZE_MODE_16X16_EN, "PARAM_ERROR_CUSIZE_MODE_16X16_EN",
124  NI_LOGAN_RETCODE_PARAM_ERROR_CUSIZE_MODE_32X32_EN, "PARAM_ERROR_CUSIZE_MODE_32X32_EN",
125  NI_LOGAN_RETCODE_PARAM_ERROR_TOO_BIG, "PARAM_ERROR_TOO_BIG",
126  NI_LOGAN_RETCODE_PARAM_ERROR_TOO_SMALL, "PARAM_ERROR_TOO_SMALL",
127  NI_LOGAN_RETCODE_PARAM_ERROR_ZERO, "PARAM_ERROR_ZERO",
128  NI_LOGAN_RETCODE_PARAM_ERROR_OOR, "PARAM_ERROR_OOR",
129  NI_LOGAN_RETCODE_PARAM_ERROR_WIDTH_TOO_BIG, "PARAM_ERROR_WIDTH_TOO_BIG",
130  NI_LOGAN_RETCODE_PARAM_ERROR_WIDTH_TOO_SMALL, "PARAM_ERROR_WIDTH_TOO_SMALL",
131  NI_LOGAN_RETCODE_PARAM_ERROR_HEIGHT_TOO_BIG, "PARAM_ERROR_HEIGHT_TOO_BIG",
132  NI_LOGAN_RETCODE_PARAM_ERROR_HEIGHT_TOO_SMALL, "PARAM_ERROR_HEIGHT_TOO_SMALL",
133  NI_LOGAN_RETCODE_PARAM_ERROR_AREA_TOO_BIG, "PARAM_ERROR_AREA_TOO_BIG",
134  NI_LOGAN_RETCODE_ERROR_EXCEED_MAX_NUM_SESSIONS, "ERROR_EXCEED_MAX_NUM_SESSIONS",
135  NI_LOGAN_RETCODE_ERROR_GET_DEVICE_POOL, "ERROR_GET_DEVICE_POOL",
136  NI_LOGAN_RETCODE_ERROR_LOCK_DOWN_DEVICE, "ERROR_LOCK_DOWN_DEVICE",
137  NI_LOGAN_RETCODE_ERROR_UNLOCK_DEVICE, "ERROR_UNLOCK_DEVICE",
138  NI_LOGAN_RETCODE_ERROR_OPEN_DEVICE, "ERROR_OPEN_DEVICE",
139  NI_LOGAN_RETCODE_ERROR_INVALID_HANDLE, "ERROR_INVALID_HANDLE",
140  NI_LOGAN_RETCODE_ERROR_INVALID_ALLOCATION_METHOD, "ERROR_INVALID_ALLOCATION_METHOD",
141  NI_LOGAN_RETCODE_ERROR_VPU_RECOVERY, "ERROR_VPU_RECOVERY",
142  NI_LOGAN_RETCODE_PARAM_GOP_INTRA_INCOMPATIBLE, "PARAM_GOP_INTRA_INCOMPATIBLE",
143 
144  NI_LOGAN_RETCODE_NVME_SC_WRITE_BUFFER_FULL, "NVME_SC_WRITE_BUFFER_FULL",
145  NI_LOGAN_RETCODE_NVME_SC_RESOURCE_UNAVAILABLE, "NVME_SC_RESOURCE_UNAVAILABLE",
146  NI_LOGAN_RETCODE_NVME_SC_RESOURCE_IS_EMPTY, "NVME_SC_RESOURCE_IS_EMPTY",
147  NI_LOGAN_RETCODE_NVME_SC_RESOURCE_NOT_FOUND, "NVME_SC_RESOURCE_NOT_FOUND",
148  NI_LOGAN_RETCODE_NVME_SC_REQUEST_NOT_COMPLETED, "NVME_SC_REQUEST_NOT_COMPLETED",
149  NI_LOGAN_RETCODE_NVME_SC_REQUEST_IN_PROGRESS, "NVME_SC_REQUEST_IN_PROGRESS",
150  NI_LOGAN_RETCODE_NVME_SC_INVALID_PARAMETER, "NVME_SC_INVALID_PARAMETER",
151  NI_LOGAN_RETCODE_NVME_SC_VPU_RECOVERY, "NVME_SC_VPU_RECOVERY",
152  NI_LOGAN_RETCODE_NVME_SC_VPU_RSRC_INSUFFICIENT, "NVME_SC_VPU_RSRC_INSUFFICIENT",
153  NI_LOGAN_RETCODE_NVME_SC_VPU_GENERAL_ERROR, "NVME_SC_VPU_GENERAL_ERROR",
154 
155  NI_LOGAN_RETCODE_DEFAULT_SESSION_ERR_NO, "DEFAULT_SESSION_ERR_NO",
156 };
157 
158 /*!*****************************************************************************
159  * \brief Convert error numver into error messages
160  *
161  *
162  * \return the string of error message
163  ******************************************************************************/
164 const char* ni_logan_err2str(int err)
165 {
166  int i;
167  for (i = 0; i < sizeof(ni_logan_err2str_desc) / sizeof(ni_logan_err2str_entry_t);
168  i++)
169  {
170  if (err == ni_logan_err2str_desc[i].err)
171  {
172  return ni_logan_err2str_desc[i].str;
173  }
174  }
175  return "UNKNOWN_ERROR";
176 }
177 
178 /*!******************************************************************************
179  * \brief Allocates and initializes a new ni_logan_session_context_t struct
180  *
181  *
182  * \return On success returns a valid pointer to newly allocated context
183  * On failure returns NULL
184  *******************************************************************************/
186 {
187  ni_logan_session_context_t *p_ctx = NULL;
188 
189  p_ctx = malloc(sizeof(ni_logan_session_context_t));
190  if (!p_ctx)
191  {
192  ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for session context\n",
193  NI_ERRNO);
194  }
195  else
196  {
197  p_ctx->needs_dealoc = 1;
199  }
200 
201  return p_ctx;
202 }
203 
204  /*!******************************************************************************
205  * \brief Frees previously allocated session context
206  *
207  * \param[in] p_ctx Pointer to an already allocated ni_logan_session_context_t struct
208  *
209  *******************************************************************************/
211 {
212  if (p_ctx && p_ctx->needs_dealoc)
213  {
215  free(p_ctx);
216  }
217 }
218 
219 /*!******************************************************************************
220  * \brief Initialize already allocated session context to a known state
221  *
222  * \param[in] p_ctx Pointer to an already allocated ni_logan_session_context_t struct
223  *
224  *
225  *******************************************************************************/
227 {
228  int i = 0;
229  if (!p_ctx)
230  {
231  return;
232  }
233 
234  memset(p_ctx, 0, sizeof(ni_logan_session_context_t));
235 
236  // Init the max IO size to be invalid
240  p_ctx->blk_io_handle = NI_INVALID_DEVICE_HANDLE;
241  p_ctx->device_handle = NI_INVALID_DEVICE_HANDLE;
242  p_ctx->hw_id = NI_LOGAN_INVALID_HWID;
243  p_ctx->dev_xcoder[0] = '\0';
244  p_ctx->event_handle = NI_INVALID_EVENT_HANDLE;
245  p_ctx->thread_event_handle = NI_INVALID_EVENT_HANDLE;
247  p_ctx->set_high_priority = 0;
248  p_ctx->p_hdr_buf = NULL;
249  p_ctx->hdr_buf_size = 0;
250  p_ctx->roi_side_data_size = p_ctx->nb_rois = 0;
251  p_ctx->av_rois = NULL;
252  p_ctx->avc_roi_map = NULL;
253  p_ctx->hevc_sub_ctu_roi_buf = NULL;
254  p_ctx->hevc_roi_map = NULL;
255  p_ctx->p_master_display_meta_data = NULL;
256  p_ctx->enc_change_params = NULL;
257  ni_logan_pthread_mutex_init(&p_ctx->mutex);
258 
259  for (i = 0; i < NI_LOGAN_FIFO_SZ; i++)
260  {
261  p_ctx->pkt_custom_sei[i] = NULL;
262  }
263 
264  strncat(p_ctx->dev_xcoder, BEST_MODEL_LOAD_STR, strlen(BEST_MODEL_LOAD_STR));
265 #ifdef MEASURE_LATENCY
266  p_ctx->frame_time_q = ni_logan_lat_meas_q_create(2000);
267  p_ctx->prev_read_frame_time = 0;
268 #endif
269 }
270 
271 /*!******************************************************************************
272  * \brief Clear already allocated session context to all zeros
273  *
274  * \param[in] p_ctx Pointer to an already allocated ni_logan_session_context_t struct
275  *
276  *
277  *******************************************************************************/
279  {
280  ni_logan_pthread_mutex_destroy(&p_ctx->mutex);
281  memset(p_ctx, 0, sizeof(ni_logan_session_context_t));
282  }
283 
284 /*!******************************************************************************
285  * \brief Create event and returnes event handle if successful
286  *
287  * \return On success returns a event handle
288  * On failure returns NI_INVALID_EVENT_HANDLE
289  *******************************************************************************/
290 ni_event_handle_t ni_logan_create_event(void)
291 {
292 #ifdef _WIN32
293  ni_event_handle_t event_handle = NI_INVALID_EVENT_HANDLE;
294  DWORD retval = 0;
295 
296  // Input-0 determines whether the returned handle can be inherited by the child process.
297  // If lpEventAttributes is NULL, this handle cannot be inherited.
298  // Input-1 specifies whether the event object is created to be restored manually or automatically.
299  // If set to FALSE, when a thread waits for an event signal,
300  // the system automatically restores the event state to a non-signaled state.
301  // Input-2 specifies the initial state of the event object.
302  // If TRUE, the initial state is signaled;Otherwise, no signal state.
303  // Input-3 If the lpName is NULL, a nameless event object is created.
304  event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
305  if (event_handle == NI_INVALID_EVENT_HANDLE)
306  {
307  retval = NI_ERRNO;
308  ni_log(NI_LOG_ERROR, "ERROR %d: create event failed\n",retval);
309  return NI_INVALID_EVENT_HANDLE;
310  }
311  return event_handle;
312 #else
313  return NI_INVALID_EVENT_HANDLE;
314 #endif
315 }
316 
317 /*!******************************************************************************
318  * \brief Closes event and releases resources
319  *
320  * \return NONE
321  *
322  *******************************************************************************/
323 void ni_logan_close_event(ni_event_handle_t event_handle)
324 {
325  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
326 
327  if (NI_INVALID_EVENT_HANDLE == event_handle)
328  {
329  ni_log(NI_LOG_TRACE, "Warning %s: null parameter passed %" PRIx64 "\n",
330  __FUNCTION__, (int64_t)event_handle);
331  return;
332  }
333 
334 #ifdef _WIN32
335  BOOL retval;
336  ni_log(NI_LOG_TRACE, "%s(): closing %p\n", __FUNCTION__, event_handle);
337 
338  retval = CloseHandle(event_handle);
339  if (FALSE == retval)
340  {
341  ni_log(NI_LOG_ERROR, "ERROR %d: %s(): closing event_handle %p failed\n",
342  __FUNCTION__, NI_ERRNO, event_handle);
343  }
344  else
345  {
346  ni_log(NI_LOG_TRACE, "%s(): device %p closed successfuly\n",
347  __FUNCTION__, event_handle);
348  }
349 #elif defined(__linux__) || defined(__APPLE__)
350  int err = 0;
351  ni_log(NI_LOG_TRACE, "%s(): closing %d\n", __FUNCTION__, event_handle);
352  err = close(event_handle);
353  if (err)
354  {
355  switch (err)
356  {
357  case EBADF:
358  ni_log(NI_LOG_TRACE, "ERROR: %s(): failed error EBADF\n", __FUNCTION__);
359  break;
360  case EINTR:
361  ni_log(NI_LOG_TRACE, "ERROR: %s(): error EINTR\n", __FUNCTION__);
362  break;
363  case EIO:
364  ni_log(NI_LOG_TRACE, "ERROR: %s(): error EIO\n", __FUNCTION__);
365  break;
366  default:
367  ni_log(NI_LOG_TRACE, "ERROR: %s(): unknoen error %d\n", __FUNCTION__, err);
368  }
369 
370  }
371 #endif //defined(__linux__)
372 
373  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
374 }
375 
376 /*!******************************************************************************
377  * \brief Opens device and returnes device device_handle if successful
378  *
379  * \param[in] p_dev Device name represented as c string. ex: "/dev/nvme0"
380  * \param[out] p_max_io_size_out Maximum IO Transfer size supported
381  *
382  * \return On success returns a device device_handle
383  * On failure returns NI_INVALID_DEVICE_HANDLE
384  *******************************************************************************/
385 ni_device_handle_t ni_logan_device_open(const char * p_dev, uint32_t * p_max_io_size_out)
386 {
387  if (!p_dev || !p_max_io_size_out)
388  {
389  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
390 #ifdef _WIN32
391  return NI_INVALID_DEVICE_HANDLE;
392 #else
394 #endif
395  }
396 
397  ni_log(NI_LOG_TRACE, "%s: opening %s\n", __FUNCTION__, p_dev);
398 
399 #ifdef _WIN32
400  DWORD retval = 0;
401 
402  *p_max_io_size_out = 0;
403 
404  HANDLE device_handle = CreateFile( p_dev,
405  GENERIC_READ | GENERIC_WRITE,
406  FILE_SHARE_READ | FILE_SHARE_WRITE,
407  NULL,
408  OPEN_EXISTING,
409  FILE_FLAG_NO_BUFFERING,
410  NULL
411  );
412 
413  if (INVALID_HANDLE_VALUE == device_handle)
414  {
415  retval = NI_ERRNO;
416  ni_log(NI_LOG_TRACE, "Failed to open %s, retval %d \n", p_dev, retval);
417  }
418  else
419  {
420  ni_log(NI_LOG_TRACE, "Found NVME Controller at %s \n", p_dev);
421  }
422  return device_handle;
423 
424 #elif defined(__linux__) || defined(__APPLE__)
425 
426  int retval = -1;
427  ni_device_handle_t fd = NI_INVALID_DEVICE_HANDLE;
428 
429  if (*p_max_io_size_out == NI_INVALID_IO_SIZE)
430  {
431 #if defined(__linux__)
432  *p_max_io_size_out = ni_logan_get_kernel_max_io_size(p_dev);
433 #elif defined(__APPLE__)
434  *p_max_io_size_out = MAX_IO_TRANSFER_SIZE;
435 #endif
436  }
437 
438  ni_log(NI_LOG_TRACE, "%s: opening reg i/o %s\n", __FUNCTION__, p_dev);
439  //O_SYNC is added to ensure that data is written to the card when the pread/pwrite function returns
440 #if defined(__linux__)
441  //O_DIRECT is added to ensure that data can be sent directly to the card instead of to cache memory
442  fd = open(p_dev, O_RDWR | O_SYNC | O_DIRECT);
443 #elif defined(__APPLE__)
444  //O_DIRECT isn't available, so instead we use F_NOCACHE below
445  fd = open(p_dev, O_RDWR | O_SYNC);
446 #endif
447 
448  if (fd < 0)
449  {
450  ni_log(NI_LOG_ERROR, "ERROR %d: open() failed on %s\n", NI_ERRNO, p_dev);
451  ni_log(NI_LOG_ERROR, "ERROR: %s() failed!\n", __FUNCTION__);
452  fd = NI_INVALID_DEVICE_HANDLE;
453  LRETURN;
454  }
455 #if defined(__APPLE__)
456  //F_NOCACHE is set to ensure that data can be sent directly to the card instead of to cache memory
457  retval = fcntl(fd, F_NOCACHE, 1);
458  if (retval < 0)
459  {
460  ni_log(NI_LOG_ERROR, "ERROR: fnctl() failed on %s\n", p_dev);
461  ni_log(NI_LOG_ERROR, "ERROR: ni_device_open() failed!\n");
462  close(fd);
463  fd = NI_INVALID_DEVICE_HANDLE;
464  LRETURN;
465  }
466 #endif
467  retval = fstat(fd, &g_nvme_stat);
468  if (retval < 0)
469  {
470  ni_log(NI_LOG_TRACE, "ERROR: fstat() failed on %s\n", p_dev);
471  ni_log(NI_LOG_TRACE, "ERROR: %s() failed!\n", __FUNCTION__);
472  close(fd);
473  fd = NI_INVALID_DEVICE_HANDLE;
474  LRETURN;
475  }
476 
477  if (!S_ISCHR(g_nvme_stat.st_mode) && !S_ISBLK(g_nvme_stat.st_mode))
478  {
479  ni_log(NI_LOG_TRACE, "ERROR: %s is not a block or character device\n", p_dev);
480  ni_log(NI_LOG_TRACE, "ERROR: %s() failed!\n", __FUNCTION__);
481  close(fd);
482  fd = NI_INVALID_DEVICE_HANDLE;
483  LRETURN;
484  }
485 
486  ni_log(NI_LOG_TRACE, "%s: success, fd=%d\n", __FUNCTION__, fd);
487 
488  END:
489 
490  return (fd);
491 #endif //defined(__linux__)
492 }
493 
494 /*!******************************************************************************
495  * \brief Closes device and releases resources
496  *
497  * \param[in] device_handle Device handle obtained by calling ni_logan_device_open()
498  *
499  * \return NONE
500  *
501  *******************************************************************************/
502 void ni_logan_device_close(ni_device_handle_t device_handle)
503 {
504  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
505 
506  if ( NI_INVALID_DEVICE_HANDLE == device_handle )
507  {
508  ni_log(NI_LOG_TRACE, "ERROR %s: null parameter passed\n", __FUNCTION__);
509  return;
510  }
511 
512 #ifdef _WIN32
513  BOOL retval;
514 
515  ni_log(NI_LOG_TRACE, "%s(): closing %p\n", __FUNCTION__, device_handle);
516 
517  retval = CloseHandle(device_handle);
518  if (FALSE == retval)
519  {
520  ni_log(NI_LOG_ERROR, "ERROR: %s(): closing device device_handle %p failed, "
521  "error: %d\n", __FUNCTION__, device_handle,
522  NI_ERRNO);
523  }
524  else
525  {
526  ni_log(NI_LOG_TRACE, "%s(): device %p closed successfuly\n",
527  __FUNCTION__, device_handle);
528  }
529 #elif defined(__linux__) || defined(__APPLE__)
530  int err = 0;
531  ni_log(NI_LOG_TRACE, "%s(): closing %d\n", __FUNCTION__, device_handle);
532  err = close(device_handle);
533  if (err)
534  {
535  switch (err)
536  {
537  case EBADF:
538  ni_log(NI_LOG_TRACE, "ERROR: %s(): failed error EBADF\n", __FUNCTION__);
539  break;
540  case EINTR:
541  ni_log(NI_LOG_TRACE, "ERROR: %s(): error EINTR\n", __FUNCTION__);
542  break;
543  case EIO:
544  ni_log(NI_LOG_TRACE, "ERROR: %s(): error EIO\n", __FUNCTION__);
545  break;
546  default:
547  ni_log(NI_LOG_TRACE, "ERROR: %s(): unknoen error %d\n", __FUNCTION__, err);
548  }
549  }
550 #endif //defined(__linux__)
551 
552  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
553 }
554 
555 
556 /*!******************************************************************************
557  * \brief Queries device and returns device capability structure
558  *
559  * \param[in] device_handle Device handle obtained by calling ni_logan_device_open()
560  * \param[in] p_cap Pointer to a caller allocated ni_logan_device_capability_t struct
561  * \return On success
562  * NI_LOGAN_RETCODE_SUCCESS
563  * On failure
564  NI_LOGAN_RETCODE_INVALID_PARAM
565  NI_LOGAN_RETCODE_ERROR_MEM_ALOC
566  NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
567  *******************************************************************************/
568 ni_logan_retcode_t ni_logan_device_capability_query(ni_device_handle_t device_handle,
570 {
571  ni_logan_nvme_result_t nvme_result = 0;
572  ni_logan_nvme_command_t cmd = { 0 };
573  void * p_buffer = NULL;
575  ni_event_handle_t event_handle = NI_INVALID_EVENT_HANDLE;
576 
577  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
578 
579  if ( (NI_INVALID_DEVICE_HANDLE == device_handle) || (!p_cap) )
580  {
581  ni_log(NI_LOG_TRACE, "ERROR: %s(): passed parameters are null!, return\n",
582  __FUNCTION__);
584  LRETURN;
585  }
586 
587  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), NI_LOGAN_NVME_IDENTITY_CMD_DATA_SZ))
588  {
589  ni_log(NI_LOG_TRACE, "ERROR %d: %s(): Cannot allocate buffer.\n",
590  NI_ERRNO, __FUNCTION__);
592  LRETURN;
593  }
594 
595  memset(p_buffer, 0, NI_LOGAN_NVME_IDENTITY_CMD_DATA_SZ);
596 
597 #ifdef _WIN32
598  event_handle = ni_logan_create_event();
599  if (NI_INVALID_EVENT_HANDLE == event_handle)
600  {
602  LRETURN;
603  }
604 #endif
605 
606  uint32_t ui32LBA = IDENTIFY_DEVICE_R;
607  if (ni_logan_nvme_send_read_cmd(device_handle, event_handle, p_buffer, NI_LOGAN_NVME_IDENTITY_CMD_DATA_SZ, ui32LBA) < 0)
608  {
610  LRETURN;
611  }
612 
614 
615  END:
616 
617  ni_logan_aligned_free(p_buffer);
618 #ifdef _WIN32
619  ni_logan_close_event(event_handle);
620 #endif
621 
622  ni_log(NI_LOG_TRACE, "%s(): retval: %d\n", __FUNCTION__, retval);
623 
624  return retval;
625 }
626 
627 /*!******************************************************************************
628  * \brief Opens a new device session depending on the device_type parameter
629  * If device_type is NI_LOGAN_DEVICE_TYPE_DECODER opens decoding session
630  * If device_type is NI_LOGAN_DEVICE_TYPE_EECODER opens encoding session
631  *
632  * \param[in] p_ctx Pointer to a caller allocated
633  * ni_logan_session_context_t struct
634  * \param[in] p_config Pointer to a caller allocated
635  * ni_logan_session_config_t struct
636  * \param[in] device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
637  * \return On success
638  * NI_LOGAN_RETCODE_SUCCESS
639  * On failure
640  * NI_LOGAN_RETCODE_INVALID_PARAM
641  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
642  * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
643  * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
644  *******************************************************************************/
646  ni_logan_device_type_t device_type)
647 {
649  ni_logan_device_pool_t *p_device_pool = NULL;
650  ni_logan_nvme_result_t nvme_result = {0};
651  ni_logan_device_context_t *p_device_context = NULL;
652  ni_logan_device_info_t *p_dev_info = NULL;
653  ni_logan_device_info_t dev_info = { 0 };
655  ni_logan_device_context_t *rsrc_ctx = NULL;
656  int i = 0;
657  int rc = 0;
658  int num_coders = 0;
659  int least_model_load = 0;
660  int least_real_load = 0;
661  int least_instance = 0;
662  int guid = NI_LOGAN_INVALID_HWID;
663  int num_sw_instances = 0;
664  int user_handles = false;
665  ni_lock_handle_t lock = NI_INVALID_LOCK_HANDLE;
666  ni_device_handle_t handle = NI_INVALID_DEVICE_HANDLE;
667  ni_device_handle_t handle1 = NI_INVALID_DEVICE_HANDLE;
668  // For none nvme block device we just need to pass in dummy
669  uint32_t dummy_io_size = 0;
670  ni_logan_session_context_t p_session_context;
671 
672  if (!p_ctx)
673  {
674  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
676  }
677 
678  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
679 
680  ni_logan_device_session_context_init(&p_session_context);
681 
682  handle = p_ctx->device_handle;
683  handle1 = p_ctx->blk_io_handle;
684 
685  if (p_ctx->session_id != NI_LOGAN_INVALID_SESSION_ID || p_ctx->ready_to_close)
686  {
687  ni_log(NI_LOG_ERROR, "ERROR: trying to overwrite existing session\n");
689  LRETURN;
690  }
691 #ifdef __linux__
692  if(p_ctx->set_high_priority == 1)
694 #endif
695  p_device_pool = ni_logan_rsrc_get_device_pool();
696  if (!p_device_pool)
697  {
698  ni_log(NI_LOG_TRACE, "ERROR: Error calling ni_logan_rsrc_get_device_pool()\n");
700  LRETURN;
701  }
702  if (p_ctx->hw_name != NULL && strcmp(p_ctx->hw_name, ""))
703  {
704  int temphw_id = ni_logan_find_device_index_by_name(p_device_pool->p_device_queue, device_type, p_ctx->hw_name);
705  if (temphw_id != -1)
706  {
707  p_ctx->hw_id = temphw_id;
708  }
709  else
710  {
711  ni_log(NI_LOG_ERROR, "ERROR: No device of %s\n", p_ctx->hw_name);
713  LRETURN;
714  }
715  }
716  // User did not pass in any handle, so we create it for them
717  if ((handle1 == NI_INVALID_DEVICE_HANDLE) && (handle == NI_INVALID_DEVICE_HANDLE))
718  {
719  if (p_ctx->hw_id >=0) // User selected the encoder/ decoder number
720  {
721  if ((rsrc_ctx = ni_logan_rsrc_allocate_simple_direct(device_type, p_ctx->hw_id)) == NULL)
722  {
723  ni_log(NI_LOG_INFO, "Error XCoder resource allocation: inst %d \n", p_ctx->hw_id);
725  LRETURN;
726  }
727  ni_log(NI_LOG_TRACE, "device %p\n", rsrc_ctx);
728  // Now the device name is in the rsrc_ctx, we open this device to get the file handles
729 #ifdef _WIN32
730  //This is windows version!!!
731  if ((handle = ni_logan_device_open(rsrc_ctx->p_device_info->dev_name, &dummy_io_size)) == NI_INVALID_DEVICE_HANDLE)
732  {
735  LRETURN;
736  }
737  else
738  {
739  user_handles = true;
740  p_ctx->device_handle = handle;
741  p_ctx->blk_io_handle = handle;
742  handle1 = handle;
743  p_ctx->dev_xcoder_name[0] = '\0';
744  p_ctx->blk_xcoder_name[0] = '\0';
745  strncat(p_ctx->dev_xcoder_name, rsrc_ctx->p_device_info->dev_name, strlen(rsrc_ctx->p_device_info->dev_name));
746  strncat(p_ctx->blk_xcoder_name, rsrc_ctx->p_device_info->blk_name, strlen(rsrc_ctx->p_device_info->blk_name));
747  memcpy(p_ctx->fw_rev, rsrc_ctx->p_device_info->fw_rev, 8);
748 
750  }
751 #elif defined(__linux__) || defined(__APPLE__)
752  //The original design (code below) is to open char and block device file separately.
753  //And the ffmpeg will close the device twice.
754  //However, in I/O version, char device can't be opened.
755  //For compatibility, and to avoid errors, open the block device twice.
756  if (((handle = ni_logan_device_open(rsrc_ctx->p_device_info->blk_name, &dummy_io_size)) == NI_INVALID_DEVICE_HANDLE) ||
757  ((handle1 = ni_logan_device_open(rsrc_ctx->p_device_info->blk_name, &p_ctx->max_nvme_io_size)) == NI_INVALID_DEVICE_HANDLE))
758  {
761  LRETURN;
762  }
763  else
764  {
765  user_handles = true;
766  p_ctx->device_handle = handle;
767  p_ctx->blk_io_handle = handle1;
768  p_ctx->dev_xcoder_name[0] = '\0';
769  p_ctx->blk_xcoder_name[0] = '\0';
770  strncat(p_ctx->dev_xcoder_name, rsrc_ctx->p_device_info->dev_name, strlen(rsrc_ctx->p_device_info->dev_name));
771  strncat(p_ctx->blk_xcoder_name, rsrc_ctx->p_device_info->blk_name, strlen(rsrc_ctx->p_device_info->blk_name));
772  memcpy(p_ctx->fw_rev, rsrc_ctx->p_device_info->fw_rev, 8);
773 
775  }
776 #endif
777  }
778  // we use this to support the best model load & best instance
779  else if ((0 == strcmp(p_ctx->dev_xcoder, BEST_LOAD_STR)) ||
780  (0 == strcmp(p_ctx->dev_xcoder, BEST_MODEL_LOAD_STR)) ||
781  (0 == strcmp(p_ctx->dev_xcoder, BEST_DEVICE_INST_STR)))
782  {
783  int tmp_id = -1;
784  char str_fw_API_ver[3];
785  int fw_API_ver;
786 
787  if (ni_logan_rsrc_lock_and_open(device_type, &lock) != NI_LOGAN_RETCODE_SUCCESS)
788  {
790  LRETURN;
791  }
792 
793  // Then we need to query through all the board to confirm the least model load/ instance load board
794  if ((NI_LOGAN_DEVICE_TYPE_DECODER == device_type) || (NI_LOGAN_DEVICE_TYPE_ENCODER == device_type))
795  {
796  num_coders = p_device_pool->p_device_queue->decoders_cnt;
797  }
798  else
799  {
801  if ( ni_logan_rsrc_unlock(device_type, lock) != NI_LOGAN_RETCODE_SUCCESS)
802  {
804  LRETURN;
805  }
806  LRETURN;
807  }
808 
809  for (i = 0; i < num_coders; i++)
810  {
811  if (NI_LOGAN_DEVICE_TYPE_DECODER == device_type)
812  {
813  tmp_id = p_device_pool->p_device_queue->decoders[i];
814  }
815  else if (NI_LOGAN_DEVICE_TYPE_ENCODER == device_type)
816  {
817  tmp_id = p_device_pool->p_device_queue->encoders[i];
818  }
819  p_device_context = ni_logan_rsrc_get_device_context(device_type, tmp_id);
820  if (! p_device_context)
821  {
822  ni_log(NI_LOG_INFO, "Error getting device type %d id %d",
823  device_type, tmp_id);
824  continue;
825  }
826 
827  //Code is included in the for loop. In the loop, the device is just opened once, and it will be closed once too.
828  p_session_context.blk_io_handle = ni_logan_device_open(p_device_context->p_device_info->blk_name, &dummy_io_size);
829  p_session_context.device_handle = p_session_context.blk_io_handle;
830 
831  if (NI_INVALID_DEVICE_HANDLE == p_session_context.device_handle)
832  {
833  ni_logan_rsrc_free_device_context(p_device_context);
834  ni_log(NI_LOG_TRACE, "Error open device");
835  continue;
836  }
837 
838 #ifdef _WIN32
839  p_session_context.event_handle = ni_logan_create_event();
840  if (NI_INVALID_EVENT_HANDLE == p_session_context.event_handle)
841  {
842  ni_logan_rsrc_free_device_context(p_device_context);
843  ni_logan_device_close(p_session_context.device_handle);
844  ni_log(NI_LOG_TRACE, "Error create event");
845  continue;
846  }
847 #endif
848 
849  memcpy(str_fw_API_ver,
852  str_fw_API_ver[NI_LOGAN_XCODER_API_VER_SZ] = '\0';
853  fw_API_ver = atoi(str_fw_API_ver);
854  ni_log(NI_LOG_TRACE,"Current FW API version is: %d\n", fw_API_ver);
855 
856  p_session_context.hw_id = p_device_context->p_device_info->hw_id;
857  rc = ni_logan_device_session_query(&p_session_context, device_type);
858  if (NI_INVALID_DEVICE_HANDLE != p_session_context.device_handle)
859  {
860  ni_logan_device_close(p_session_context.device_handle);
861  }
862 
863 #ifdef _WIN32
864  if (NI_INVALID_EVENT_HANDLE != p_session_context.event_handle)
865  {
866  ni_logan_close_event(p_session_context.event_handle);
867  }
868 #endif
869  if (NI_LOGAN_RETCODE_SUCCESS != rc)
870  {
871  ni_log(NI_LOG_TRACE, "Error query %s %s.%d\n",
872  NI_LOGAN_DEVICE_TYPE_DECODER == device_type ? "decoder" : "encoder",
873  p_device_context->p_device_info->dev_name, p_device_context->p_device_info->hw_id);
874  ni_logan_rsrc_free_device_context(p_device_context);
875  continue;
876  }
877  ni_logan_rsrc_update_record(p_device_context, &p_session_context);
878  p_dev_info = p_device_context->p_device_info;
879 
880  if ((0 == strcmp(p_ctx->dev_xcoder, BEST_LOAD_STR)))
881  {
882  // here we select the best real load
883  if (((guid == NI_LOGAN_INVALID_HWID) || p_dev_info->load < least_real_load ||
884  ((p_dev_info->load == least_real_load) && (p_dev_info->active_num_inst < num_sw_instances))) &&
885  (p_dev_info->active_num_inst < p_dev_info->max_instance_cnt))
886  {
887  guid = tmp_id;
888  least_real_load = p_dev_info->load;
889  num_sw_instances = p_dev_info->active_num_inst;
890  memcpy(&dev_info, p_dev_info, sizeof(ni_logan_device_info_t));
891  }
892  }
893  else if ((0 == strcmp(p_ctx->dev_xcoder, BEST_MODEL_LOAD_STR)))
894  {
895  // here we select the best model load
896  if (((guid == NI_LOGAN_INVALID_HWID) || p_dev_info->model_load < least_model_load ||
897  ((p_dev_info->model_load == least_model_load) && (p_dev_info->active_num_inst < num_sw_instances))) &&
898  (p_dev_info->active_num_inst < p_dev_info->max_instance_cnt))
899  {
900  guid = tmp_id;
901  least_model_load = p_dev_info->model_load;
902  num_sw_instances = p_dev_info->active_num_inst;
903  memcpy(&dev_info, p_dev_info, sizeof(ni_logan_device_info_t));
904  }
905  }
906  else
907  {
908  // here we select the best instance
909  if (((guid == NI_LOGAN_INVALID_HWID) || (p_dev_info->active_num_inst < least_instance) ||
910  (p_dev_info->active_num_inst == least_instance)) &&
911  (p_dev_info->active_num_inst < p_dev_info->max_instance_cnt))
912  {
913  guid = tmp_id;
914  least_instance = p_dev_info->active_num_inst;
915  memcpy(&dev_info, p_dev_info, sizeof(ni_logan_device_info_t));
916  }
917  }
918  ni_logan_rsrc_free_device_context(p_device_context);
919  }
920 
921  if (guid == NI_LOGAN_INVALID_HWID)
922  {
924  ni_log(NI_LOG_ERROR, "Error: Resource unavailable, could not find an "
925  "available %s device.\n",
926  (device_type == NI_LOGAN_DEVICE_TYPE_DECODER? "decoder" : "encoder"));
927  LRETURN;
928  }
929 
930  // Now we have the device info that has the least model load/least instance of the FW
931  // we open this device and assign the FD
932 #ifdef _WIN32
933  //This is windows version!!!
934  if ((handle = ni_logan_device_open(dev_info.dev_name, &dummy_io_size)) == NI_INVALID_DEVICE_HANDLE)
935  {
937  if ( ni_logan_rsrc_unlock(device_type, lock) != NI_LOGAN_RETCODE_SUCCESS)
938  {
940  LRETURN;
941  }
942  LRETURN;
943  }
944  else
945  {
946  p_ctx->device_handle = handle;
947  p_ctx->blk_io_handle = handle;
948  handle1 = handle;
949  p_ctx->hw_id = guid;
950  p_ctx->dev_xcoder_name[0] = '\0';
951  p_ctx->blk_xcoder_name[0] = '\0';
952  strncat(p_ctx->dev_xcoder_name, dev_info.dev_name, strlen(dev_info.dev_name));
953  strncat(p_ctx->blk_xcoder_name, dev_info.blk_name, strlen(dev_info.blk_name));
954  memcpy(p_ctx->fw_rev, dev_info.fw_rev, 8);
955  }
956 #elif defined(__linux__) || defined(__APPLE__)
957  //The original design (code below) is to open char and block device file separately.
958  //And the ffmpeg will close the device twice.
959  //However, in I/O version, char device can't be opened.
960  //For compatibility, and to avoid errors, open the block device twice.
961  if (((handle = ni_logan_device_open(dev_info.blk_name, &dummy_io_size)) == NI_INVALID_DEVICE_HANDLE) ||
962  ((handle1 = ni_logan_device_open(dev_info.blk_name, &p_ctx->max_nvme_io_size)) == NI_INVALID_DEVICE_HANDLE))
963  {
965  if ( ni_logan_rsrc_unlock(device_type, lock) != NI_LOGAN_RETCODE_SUCCESS)
966  {
968  LRETURN;
969  }
970  LRETURN;
971  }
972  else
973  {
974  p_ctx->device_handle = handle;
975  p_ctx->blk_io_handle = handle1;
976  p_ctx->hw_id = guid;
977  p_ctx->dev_xcoder_name[0] = '\0';
978  p_ctx->blk_xcoder_name[0] = '\0';
979  strncat(p_ctx->dev_xcoder_name, dev_info.dev_name, strlen(dev_info.dev_name));
980  strncat(p_ctx->blk_xcoder_name, dev_info.blk_name, strlen(dev_info.blk_name));
981  memcpy(p_ctx->fw_rev, dev_info.fw_rev, 8);
982  }
983 #endif
984  }
985  // Otherwise the command passed in is invalid
986  else
987  {
988  ni_log(NI_LOG_TRACE, "Error XCoder command line options\n");
990  LRETURN;
991  }
992 
993  }
994  // user passed in the handle, but one of them is invalid, this is error case so we return error
995  else if ((handle1 == NI_INVALID_DEVICE_HANDLE) || (handle == NI_INVALID_DEVICE_HANDLE))
996  {
998  LRETURN;
999  }
1000  // User passed in both handles, so we do not need to allocate for it
1001  else
1002  {
1003  user_handles = true;
1004  }
1005 
1006 #ifdef _WIN32
1007  ni_log(NI_LOG_TRACE, "Finish open the session dev:%s blk:%s guid:%d handle:%p handle1:%p\n",
1008  p_ctx->dev_xcoder_name, p_ctx->blk_xcoder_name, p_ctx->hw_id,
1009  p_ctx->device_handle, p_ctx->blk_io_handle);
1010 #else
1011  ni_log(NI_LOG_TRACE, "Finish open the session dev:%s blk:%s guid:%d handle:%d handle1:%d\n",
1012  p_ctx->dev_xcoder_name, p_ctx->blk_xcoder_name, p_ctx->hw_id,
1013  p_ctx->device_handle, p_ctx->blk_io_handle);
1014 #endif
1015 
1016  switch (device_type)
1017  {
1019  {
1020  for (i = 0; i< NI_LOGAN_MAX_SESSION_OPEN_RETRIES; i++) // 20 retries
1021  {
1022  retval = ni_logan_decoder_session_open(p_ctx);
1024  {
1026  ni_log(NI_LOG_DEBUG, "Encoder vpu recovery retry count: %d", i);
1028  continue;
1029  }
1030  else
1031  {
1032  break;
1033  }
1034  }
1035  if (user_handles != true)
1036  {
1037  if ( ni_logan_rsrc_unlock(device_type, lock) != NI_LOGAN_RETCODE_SUCCESS)
1038  {
1040  LRETURN;
1041  }
1042  }
1043  // send keep alive signal thread
1044  if (NI_LOGAN_RETCODE_SUCCESS != retval)
1045  {
1046  LRETURN;
1047  }
1048  break;
1049  }
1051  {
1052 #ifndef _WIN32
1053  // p2p is not supported on Windows, so skip following assignments.
1054  ni_logan_encoder_params_t *p_enc_params;
1055 
1056  p_enc_params = p_ctx->p_session_config;
1057 
1058  if (p_enc_params && p_enc_params->hwframes &&
1059  p_enc_params->p_first_frame)
1060  {
1061  ni_logan_hwframe_surface_t *pSurface;
1062  pSurface =
1063  (ni_logan_hwframe_surface_t *)p_enc_params->p_first_frame->p_data[3];
1064  p_ctx->sender_handle =
1065  (ni_device_handle_t)(int64_t)pSurface->device_handle;
1066  }
1067 #endif
1068 
1069  for (i = 0; i< NI_LOGAN_MAX_SESSION_OPEN_RETRIES; i++) // 20 retries
1070  {
1071  retval = ni_logan_encoder_session_open(p_ctx);
1073  {
1075  ni_log(NI_LOG_DEBUG, "Encoder vpu recovery retry count: %d", i);
1077  continue;
1078  }
1079  else
1080  {
1081  break;
1082  }
1083  }
1084  if (user_handles != true)
1085  {
1086  if ( ni_logan_rsrc_unlock(device_type, lock) != NI_LOGAN_RETCODE_SUCCESS)
1087  {
1089  LRETURN;
1090  }
1091  }
1092  // send keep alive signal thread
1093  if (NI_LOGAN_RETCODE_SUCCESS != retval)
1094  {
1095  LRETURN;
1096  }
1097  break;
1098  }
1100  {
1101  retval = ni_logan_uploader_session_open(p_ctx);
1102  if (user_handles != true)
1103  {
1104  if( ni_logan_rsrc_unlock(device_type, lock) != NI_LOGAN_RETCODE_SUCCESS)
1105  {
1107  LRETURN;
1108  }
1109  }
1110  // send keep alive signal thread
1111  if (NI_LOGAN_RETCODE_SUCCESS != retval)
1112  {
1113  LRETURN;
1114  }
1115  break;
1116  }
1117  default:
1118  {
1119  if (user_handles != true)
1120  {
1121  if ( ni_logan_rsrc_unlock(device_type, lock) != NI_LOGAN_RETCODE_SUCCESS)
1122  {
1124  LRETURN;
1125  }
1126  }
1128  ni_log(NI_LOG_TRACE, "Unrecognized device type: %d", device_type);
1129  LRETURN;
1130  }
1131  }
1132 
1134  if (!p_ctx->keep_alive_thread_args)
1135  {
1136  ni_log(NI_LOG_ERROR, "ERROR %d: thread_args allocation failed!\n", NI_ERRNO);
1137  ni_logan_device_session_close(p_ctx,0,device_type);
1139  LRETURN;
1140  }
1141 
1142  // Initializes the variables required by the keep alive thread
1143  p_ctx->keep_alive_thread_args->hw_id = p_ctx->hw_id;
1144  p_ctx->keep_alive_thread_args->session_id = p_ctx->session_id;
1148  p_ctx->keep_alive_thread_args->close_thread = false;
1152 
1153  if ( 0 != ni_logan_pthread_create(&p_ctx->keep_alive_thread, NULL, ni_logan_session_keep_alive_thread,
1154  (void *)p_ctx->keep_alive_thread_args) )
1155  {
1156  ni_log(NI_LOG_ERROR, "ERROR %d: failed to create keep alive thread\n", NI_ERRNO);
1157  retval = NI_LOGAN_RETCODE_FAILURE;
1158  p_ctx->keep_alive_thread = (ni_pthread_t){ 0 };
1159  free(p_ctx->keep_alive_thread_args);
1160  p_ctx->keep_alive_thread_args = NULL;
1161  ni_logan_device_session_close(p_ctx,0,device_type);
1162  }
1163 
1164  END:
1165 
1166  if (p_device_pool)
1167  {
1168  ni_logan_rsrc_free_device_pool(p_device_pool);
1169  p_device_pool = NULL;
1170  }
1171 
1172  ni_logan_device_session_context_clear(&p_session_context);
1173 
1174  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
1175 
1176  return retval;
1177 }
1178 
1179 /*!******************************************************************************
1180  * \brief Closes device session that was previously opened by calling
1181  * ni_logan_device_session_open()
1182  * If device_type is NI_LOGAN_DEVICE_TYPE_DECODER closes decoding session
1183  * If device_type is NI_LOGAN_DEVICE_TYPE_EECODER closes encoding session
1184  *
1185  * \param[in] p_ctx Pointer to a caller allocated
1186  * ni_logan_session_context_t struct
1187  * \param[in] eos_recieved Flag indicating if End Of Stream indicator was recieved
1188  * \param[in] device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
1189  * \return On success
1190  * NI_LOGAN_RETCODE_SUCCESS
1191  * On failure
1192  * NI_LOGAN_RETCODE_INVALID_PARAM
1193  * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
1194  * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
1195  *******************************************************************************/
1197  int eos_recieved,
1198  ni_logan_device_type_t device_type)
1199 {
1201 
1202  if (!p_ctx)
1203  {
1204  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null! return\n");
1206  }
1207 
1208  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
1209 
1210 #ifdef _WIN32
1211  if (p_ctx->keep_alive_thread.handle)
1212 #else
1213  if (p_ctx->keep_alive_thread)
1214 #endif
1215  {
1216  p_ctx->keep_alive_thread_args->close_thread = true;
1217  ni_logan_pthread_join(p_ctx->keep_alive_thread, NULL);
1218  if (p_ctx->keep_alive_thread_args)
1219  {
1220  free(p_ctx->keep_alive_thread_args);
1221  }
1222  p_ctx->keep_alive_thread = (ni_pthread_t){ 0 };
1223  p_ctx->keep_alive_thread_args = NULL;
1224  }
1225  else
1226  {
1227  ni_log(NI_LOG_TRACE, "Cancel invalid keep alive thread: %d",
1228  p_ctx->session_id);
1229  }
1230 
1231  switch (device_type)
1232  {
1235  {
1236  retval = ni_logan_decoder_session_close(p_ctx, eos_recieved);
1237  break;
1238  }
1240  {
1241  retval = ni_logan_encoder_session_close(p_ctx, eos_recieved);
1242  break;
1243  }
1244 #if 0
1246  {
1247  retval = ni_logan_uploader_session_close(p_ctx, eos_recieved);
1248  break;
1249  }
1250 #endif
1251  default:
1252  {
1254  ni_log(NI_LOG_TRACE, "ERROR: Unrecognized device type: %d", device_type);
1255  break;
1256  }
1257  }
1258 
1259 #ifdef _WIN32
1260  if (p_ctx->event_handle != NI_INVALID_EVENT_HANDLE)
1261  {
1263  p_ctx->event_handle = NI_INVALID_EVENT_HANDLE;
1264  }
1265 
1266  if (p_ctx->thread_event_handle != NI_INVALID_EVENT_HANDLE)
1267  {
1269  p_ctx->thread_event_handle = NI_INVALID_EVENT_HANDLE;
1270  }
1271 
1272  p_ctx->session_id = NI_LOGAN_INVALID_SESSION_ID; /*!* need set invalid after closed.
1273  May cause open invalid parameters. */
1274 #endif
1275 
1276  free(p_ctx->p_hdr_buf);
1277  p_ctx->p_hdr_buf = NULL;
1278  p_ctx->hdr_buf_size = 0;
1279 
1280  free(p_ctx->av_rois);
1281  free(p_ctx->avc_roi_map);
1282  free(p_ctx->hevc_sub_ctu_roi_buf);
1283  free(p_ctx->hevc_roi_map);
1284  free(p_ctx->p_master_display_meta_data);
1285  p_ctx->av_rois = NULL;
1286  p_ctx->avc_roi_map = NULL;
1287  p_ctx->hevc_sub_ctu_roi_buf = NULL;
1288  p_ctx->hevc_roi_map = NULL;
1289  p_ctx->p_master_display_meta_data = NULL;
1290  p_ctx->roi_side_data_size = p_ctx->nb_rois = 0;
1291 
1292  free(p_ctx->enc_change_params);
1293  p_ctx->enc_change_params = NULL;
1294 
1295  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
1296 
1297  return retval;
1298 }
1299 
1300 /*!******************************************************************************
1301  * \brief Sends a flush command to the device
1302  * ni_logan_device_session_open()
1303  * If device_type is NI_LOGAN_DEVICE_TYPE_DECODER sends flush command to decoder
1304  * If device_type is NI_LOGAN_DEVICE_TYPE_EECODER sends flush command to decoder
1305  *
1306  * \param[in] p_ctx Pointer to a caller allocated
1307  * ni_logan_session_context_t struct
1308  * \param[in] device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
1309  * \return On success
1310  * NI_LOGAN_RETCODE_SUCCESS
1311  * On failure
1312  * NI_LOGAN_RETCODE_INVALID_PARAM
1313  * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
1314  * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
1315  *******************************************************************************/
1317  ni_logan_device_type_t device_type)
1318 {
1320 
1321  if (!p_ctx)
1322  {
1323  ni_log(NI_LOG_TRACE, "ERROR: %s passed parameters are null!, return\n",
1324  __FUNCTION__);
1326  }
1327 
1328  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
1329 
1330  switch (device_type)
1331  {
1333  {
1334  retval = ni_logan_decoder_session_flush(p_ctx);
1335  break;
1336  }
1338  {
1339  retval = ni_logan_encoder_session_flush(p_ctx);
1340  break;
1341  }
1342  default:
1343  {
1345  ni_log(NI_LOG_TRACE, "ERROR: Unrecognized device type: %d", device_type);
1346  break;
1347  }
1348  }
1349 
1350  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
1351 
1352  return retval;
1353 }
1354 
1355 /*!*****************************************************************************
1356  * \brief Sends a flush command to the decoder
1357  * ni_logan_device_session_open()
1358  *
1359  * \param[in] p_ctx Pointer to a caller allocated
1360  * ni_logan_session_context_t struct
1361  * \return On success
1362  * NI_LOGAN_RETCODE_SUCCESS
1363  * On failure
1364  * NI_LOGAN_RETCODE_INVALID_PARAM
1365  * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
1366  * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
1367  ******************************************************************************/
1369 {
1371  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
1372 
1373  if (!p_ctx)
1374  {
1375  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
1377  }
1378  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
1379 
1381 
1382  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
1383  ni_log(NI_LOG_TRACE, "%s(): success exit\n", __FUNCTION__);
1384 
1385  return retval;
1386 }
1387 
1388 /*!*****************************************************************************
1389  * \brief Save a stream's headers in a decoder session that can be used later
1390  * for continuous decoding from the same source.
1391  *
1392  * \param[in] p_ctx Pointer to a caller allocated
1393  * ni_logan_session_context_t struct
1394  * \param[in] hdr_data Pointer to header data
1395  * \param[in] hdr_size Size of header data in bytes
1396  * \return On success
1397  * NI_LOGAN_RETCODE_SUCCESS
1398  * On failure
1399  * NI_LOGAN_RETCODE_INVALID_PARAM
1400  * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
1401  * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
1402  ******************************************************************************/
1404  uint8_t *hdr_data, uint8_t hdr_size)
1405 {
1407 
1408  if (! p_ctx || ! hdr_data)
1409  {
1410  ni_log(NI_LOG_ERROR, "ERROR: ni_logan_device_dec_session_save_hdrs para null, "
1411  "return\n");
1413  }
1414 
1415  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
1416 
1417  if (p_ctx->p_hdr_buf && p_ctx->hdr_buf_size == hdr_size &&
1418  0 == memcmp(p_ctx->p_hdr_buf, hdr_data, hdr_size))
1419  {
1420  // no change from the saved headers, success !
1421  LRETURN;
1422  }
1423 
1424  // update the saved header data
1425  free(p_ctx->p_hdr_buf);
1426  p_ctx->hdr_buf_size = 0;
1427  p_ctx->p_hdr_buf = malloc(hdr_size);
1428  if (p_ctx->p_hdr_buf)
1429  {
1430  memcpy(p_ctx->p_hdr_buf, hdr_data, hdr_size);
1431  p_ctx->hdr_buf_size = hdr_size;
1432  ni_log(NI_LOG_TRACE, "ni_logan_device_dec_session_save_hdrs saved hdr size %u\n",
1433  p_ctx->hdr_buf_size);
1434  }
1435  else
1436  {
1438  ni_log(NI_LOG_ERROR, "ERROR: ni_logan_device_dec_session_save_hdrs no memory.\n");
1439  }
1440 
1441  END:
1442 
1443  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
1444 
1445  return retval;
1446 }
1447 
1448 /*!*****************************************************************************
1449  * \brief Flush a decoder session to get ready to continue decoding.
1450  *
1451  * \param[in] p_ctx Pointer to a caller allocated
1452  * ni_logan_session_context_t struct
1453  * \return On success
1454  * NI_LOGAN_RETCODE_SUCCESS
1455  * On failure
1456  * NI_LOGAN_RETCODE_INVALID_PARAM
1457  * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
1458  * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
1459  ******************************************************************************/
1461 {
1463  uint8_t *p_tmp_data = NULL;
1464  uint8_t tmp_data_size = 0;
1465 
1466  if (! p_ctx)
1467  {
1468  ni_log(NI_LOG_TRACE, "ERROR: ni_logan_device_dec_session_flush ctx null, "
1469  "return\n");
1471  }
1472 
1473  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
1474 
1475  // save the stream header data for the new session to be opened
1476  if (p_ctx->p_hdr_buf && p_ctx->hdr_buf_size)
1477  {
1478  p_tmp_data = malloc(p_ctx->hdr_buf_size);
1479  if (p_tmp_data)
1480  {
1481  memcpy(p_tmp_data, p_ctx->p_hdr_buf, p_ctx->hdr_buf_size);
1482  tmp_data_size = p_ctx->hdr_buf_size;
1483  }
1484  else
1485  {
1487  }
1488  }
1489 
1490  // close the current session and open a new one
1492 
1495  {
1496  // copy over the saved stream header to be sent as part of the first data
1497  // to decoder
1498  if (p_tmp_data && tmp_data_size && p_ctx->p_leftover)
1499  {
1500  p_ctx->p_hdr_buf = p_tmp_data;
1501  p_ctx->hdr_buf_size = tmp_data_size;
1502 
1503  memcpy(p_ctx->p_leftover, p_ctx->p_hdr_buf, p_ctx->hdr_buf_size);
1504  p_ctx->prev_size = p_ctx->hdr_buf_size;
1505  }
1506  ni_log(NI_LOG_TRACE, "ni_logan_device_dec_session_flush completed, hdr size %u "
1507  "saved.\n", p_ctx->hdr_buf_size);
1508  }
1509 
1510  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
1511 
1512  return retval;
1513 }
1514 
1515 /*!******************************************************************************
1516  * \brief Sends data the device
1517  * If device_type is NI_LOGAN_DEVICE_TYPE_DECODER sends data packet to decoder
1518  * If device_type is NI_LOGAN_DEVICE_TYPE_EECODER sends data frame to encoder
1519  *
1520  * \param[in] p_ctx Pointer to a caller allocated
1521  * ni_logan_session_context_t struct
1522  * \param[in] p_data Pointer to a caller allocated
1523  * ni_logan_session_data_io_t struct which contains either a
1524  * ni_logan_frame_t data frame or ni_logan_packet_t data packet to send
1525  * \param[in] device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
1526  * If NI_LOGAN_DEVICE_TYPE_DECODER is specified, it is expected
1527  * that the ni_logan_packet_t struct inside the p_data pointer
1528  * contains data to send.
1529  * If NI_LOGAN_DEVICE_TYPE_ENCODER is specified, it is expected
1530  * that the ni_logan_frame_t struct inside the p_data pointer
1531  * contains data to send.
1532  * \return On success
1533  * Total number of bytes written
1534  * On failure
1535  * NI_LOGAN_RETCODE_INVALID_PARAM
1536  * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
1537  * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
1538  *******************************************************************************/
1541  ni_logan_device_type_t device_type)
1542 {
1544 
1545  if (!p_ctx || !p_data)
1546  {
1547  ni_log(NI_LOG_TRACE, "ERROR: %s passed parameters are null!, return\n",
1548  __FUNCTION__);
1550  }
1551 
1552  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
1553 
1554  // Here check if keep alive thread is closed.
1555 #ifdef _WIN32
1556  if (p_ctx->keep_alive_thread.handle && p_ctx->keep_alive_thread_args->close_thread)
1557 #else
1559 #endif
1560  {
1561  ni_log(NI_LOG_ERROR, "ERROR: %s() keep alive thread has been closed, "
1562  "hw:%d, session:%d\n", __FUNCTION__, p_ctx->hw_id, p_ctx->session_id);
1564  LRETURN;
1565  }
1566 
1567  switch (device_type)
1568  {
1570  {
1571  retval = ni_logan_decoder_session_write(p_ctx, &(p_data->data.packet));
1572  break;
1573  }
1575  {
1576  retval = ni_logan_encoder_session_write(p_ctx, &(p_data->data.frame));
1577  break;
1578  }
1579  default:
1580  {
1582  ni_log(NI_LOG_TRACE, "ERROR: Unrecognized device type: %d", device_type);
1583  break;
1584  }
1585  }
1586 
1587  END:
1588 
1589  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
1590 
1591  return retval;
1592 }
1593 
1594 /*!******************************************************************************
1595  * \brief Reads data the device
1596  * If device_type is NI_LOGAN_DEVICE_TYPE_DECODER reads data packet from decoder
1597  * If device_type is NI_LOGAN_DEVICE_TYPE_EECODER reads data frame from encoder
1598  *
1599  * \param[in] p_ctx Pointer to a caller allocated
1600  * ni_logan_session_context_t struct
1601  * \param[in] p_data Pointer to a caller allocated
1602  * ni_logan_session_data_io_t struct which contains either a
1603  * ni_logan_frame_t data frame or ni_logan_packet_t data packet to send
1604  * \param[in] device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
1605  * If NI_LOGAN_DEVICE_TYPE_DECODER is specified, data that was
1606  * read will be placed into ni_logan_frame_t struct inside the p_data pointer
1607  * If NI_LOGAN_DEVICE_TYPE_ENCODER is specified, data that was
1608  * read will be placed into ni_logan_packet_t struct inside the p_data pointer
1609  * \return On success
1610  * Total number of bytes read
1611  * On failure
1612  * NI_LOGAN_RETCODE_INVALID_PARAM
1613  * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
1614  * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
1615  *******************************************************************************/
1618  ni_logan_device_type_t device_type)
1619 {
1621 
1622  if (!p_ctx || !p_data)
1623  {
1624  ni_log(NI_LOG_TRACE, "ERROR: %s passed parameters are null!, return\n",
1625  __FUNCTION__);
1627  }
1628 
1629  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
1630 
1631  // Here check if keep alive thread is closed.
1632 #ifdef _WIN32
1633  if (p_ctx->keep_alive_thread.handle && p_ctx->keep_alive_thread_args->close_thread)
1634 #else
1636 #endif
1637  {
1638  ni_log(NI_LOG_ERROR, "ERROR: %s() keep alive thread has been closed, hw:%d "
1639  "session:%d\n", __FUNCTION__, p_ctx->hw_id, p_ctx->session_id);
1641  LRETURN;
1642  }
1643 
1644  switch (device_type)
1645  {
1647  {
1648  int seq_change_read_count = 0;
1649  for (; ;)
1650  {
1651  retval = ni_logan_decoder_session_read(p_ctx, &(p_data->data.frame));
1652  // check resolution change only after initial setting obtained
1653  // p_data->data.frame.video_width is picture width and will be 32-align
1654  // adjusted to frame size; p_data->data.frame.video_height is the same as
1655  // frame size, then compare them to saved one for resolution checking
1656  //
1657  int aligned_width = ((p_data->data.frame.video_width + 31) / 32) * 32;
1658  if ((0 == retval) && seq_change_read_count)
1659  {
1660  ni_log(NI_LOG_TRACE, "%s (decoder): seq change NO data next time.\n",
1661  __FUNCTION__);
1662  p_ctx->active_video_width = 0;
1663  p_ctx->active_video_height = 0;
1664  p_ctx->active_bit_depth = 0;
1665  break;
1666  }
1667  else if (retval < 0)
1668  {
1669  ni_log(NI_LOG_TRACE, "%s (decoder): failure return %d ..\n",
1670  __FUNCTION__, retval);
1671  break;
1672  }
1673  else if (p_ctx->frame_num && p_data->data.frame.video_width &&
1674  p_data->data.frame.video_height && p_data->data.frame.bit_depth &&
1675  ((aligned_width != p_ctx->active_video_width) ||
1676  (p_data->data.frame.video_height != p_ctx->active_video_height) || (p_data->data.frame.bit_depth != p_ctx->active_bit_depth) ))
1677  {
1678  ni_log(NI_LOG_TRACE, "%s (decoder): sequence change, frame size "
1679  "%ux%u %dbits -> %ux%u %dbits, continue read \n", __FUNCTION__,
1680  p_ctx->active_video_width, p_ctx->active_video_height,
1681  p_ctx->active_bit_depth, p_data->data.frame.video_width,
1682  p_data->data.frame.video_height, p_data->data.frame.bit_depth);
1683  // reset active video resolution to 0 so it can be queried in the re-read
1684  p_ctx->active_video_width = 0;
1685  p_ctx->active_video_height = 0;
1686  p_ctx->active_bit_depth = 0;
1687  seq_change_read_count++;
1688  }
1689  else
1690  {
1691  break;
1692  }
1693  }
1694  break;
1695  }
1697  {
1698  retval = ni_logan_encoder_session_read(p_ctx, &(p_data->data.packet));
1699  break;
1700  }
1701  default:
1702  {
1704  ni_log(NI_LOG_TRACE, "ERROR: Unrecognized device type: %d", device_type);
1705  break;
1706  }
1707  }
1708 
1709  END:
1710 
1711  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
1712 
1713  return retval;
1714 }
1715 
1716 /*!******************************************************************************
1717  * \brief Query session data from the device - Currently not implemented
1718  * If device_type is NI_LOGAN_DEVICE_TYPE_DECODER query session data
1719  * from decoder
1720  * If device_type is NI_LOGAN_DEVICE_TYPE_EECODER query session data
1721  * from encoder
1722  *
1723  * \param[in] p_ctx Pointer to a caller allocated
1724  * ni_logan_session_context_t struct
1725  * \param[in] device_type NI_LOGAN_DEVICE_TYPE_DECODER or NI_LOGAN_DEVICE_TYPE_ENCODER
1726  *
1727  * \return On success
1728  * NI_LOGAN_RETCODE_SUCCESS
1729  * On failure
1730  * NI_LOGAN_RETCODE_INVALID_PARAM
1731  * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
1732  * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
1733  *******************************************************************************/
1735  ni_logan_device_type_t device_type)
1736 {
1738  if (!p_ctx)
1739  {
1740  ni_log(NI_LOG_TRACE, "ERROR: %s passed parameters are null!, return\n",
1741  __FUNCTION__);
1743  }
1744 
1745  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
1746 
1747  switch (device_type)
1748  {
1750  {
1751  retval = ni_logan_decoder_session_query(p_ctx);
1752  break;
1753  }
1755  {
1756  retval = ni_logan_encoder_session_query(p_ctx);
1757  break;
1758  }
1759  default:
1760  {
1762  ni_log(NI_LOG_TRACE, "ERROR: Unrecognized device type: %d", device_type);
1763  break;
1764  }
1765  }
1766 
1767  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
1768 
1769  return retval;
1770 }
1771 
1772 /*!******************************************************************************
1773  * \brief Allocate preliminary memory for the frame buffer for encoding
1774  * based on provided parameters. Applicable to YUV420 Planar pixel
1775  * format only, 8 or 10 bit/pixel.
1776  *
1777  * \param[in] p_frame Pointer to a caller allocated
1778  * ni_logan_frame_t struct
1779  * \param[in] video_width Width of the video frame
1780  * \param[in] video_height Height of the video frame
1781  * \param[in] alignment Allignment requirement
1782  * \param[in] metadata_flag Flag indicating if space for additional metadata
1783  * should be allocated
1784  * \param[in] factor 1 for 8 bits/pixel format, 2 for 10 bits/pixel
1785  *
1786  * \return On success
1787  * NI_LOGAN_RETCODE_SUCCESS
1788  * On failure
1789  * NI_LOGAN_RETCODE_INVALID_PARAM
1790  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
1791  *******************************************************************************/
1793  int video_width,
1794  int video_height,
1795  int alignment,
1796  int metadata_flag,
1797  int factor,
1798  int hw_frame_count)
1799 {
1800  void* p_buffer = NULL;
1801  int metadata_size = 0;
1802  int retval = NI_LOGAN_RETCODE_SUCCESS;
1803  // TBD for sequence change (non-regular resolution video sample):
1804  // width has to be 16-aligned to prevent f/w assertion
1805  int width_aligned = video_width;
1806  int height_aligned = video_height;
1807 
1808  if ((!p_frame) || ((factor!=1) && (factor!=2))
1809  || (video_width>NI_LOGAN_MAX_RESOLUTION_WIDTH) || (video_width<=0)
1810  || (video_height>NI_LOGAN_MAX_RESOLUTION_HEIGHT) || (video_height<=0))
1811  {
1812  ni_log(NI_LOG_TRACE, "ERROR: %s passed parameters are null!, return\n",
1813  __FUNCTION__);
1815  }
1816 
1817  if (metadata_flag)
1818  {
1820  }
1821 
1822  width_aligned = ((video_width + 31) / 32) * 32;
1823  height_aligned = ((video_height + 7) / 8) * 8;
1824  if (alignment)
1825  {
1826  height_aligned = ((video_height + 15) / 16) * 16;
1827  }
1828 
1829  ni_log(NI_LOG_TRACE, "%s: aligned=%dx%d orig=%dx%d\n", __FUNCTION__,
1830  width_aligned, height_aligned, video_width, video_height);
1831 
1832  int luma_size = width_aligned * height_aligned * factor;
1833  int chroma_b_size = luma_size / 4;
1834  int chroma_r_size = chroma_b_size;
1835 
1836  int buffer_size = 0;
1837  /* if hw_frame_count is zero, this is a software frame */
1838  if (hw_frame_count == 0)
1839  {
1840  buffer_size = luma_size + chroma_b_size + chroma_r_size + metadata_size;
1841  }
1842  else
1843  {
1844  buffer_size = sizeof(ni_logan_hwframe_surface_t)*hw_frame_count + metadata_size;
1845  }
1846 
1847  // added 2 blocks of 512 bytes buffer space to handle any extra metadata
1848  // retrieval from fw
1849  buffer_size = ((buffer_size + (NI_LOGAN_MEM_PAGE_ALIGNMENT - 1)) / NI_LOGAN_MEM_PAGE_ALIGNMENT) *
1851 
1852  //Check if need to free
1853  if ((p_frame->buffer_size != buffer_size) && (p_frame->buffer_size > 0))
1854  {
1855  ni_log(NI_LOG_TRACE, "%s: free current p_frame->buffer_size=%d\n",
1856  __FUNCTION__, p_frame->buffer_size);
1857  ni_logan_frame_buffer_free(p_frame);
1858  }
1859 
1860  //Check if need to realocate
1861  if (p_frame->buffer_size != buffer_size)
1862  {
1863 #ifndef XCODER_SIM_ENABLED
1864  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size))
1865  {
1866  ni_log(NI_LOG_ERROR, "ERROR %d: Cannot allocate p_frame buffer.\n",
1867  NI_ERRNO);
1869  LRETURN;
1870  }
1871 #else
1872  buffer = malloc(buffer_size);
1873  if (!buffer)
1874  {
1875  ni_log(NI_LOG_ERROR, "ERROR %d: Cannot allocate p_frame buffer.\n",
1876  NI_ERRNO);
1878  LRETURN;
1879  }
1880 #endif
1881  // init once after allocation
1882  //memset(p_buffer, 0, buffer_size);
1883  p_frame->buffer_size = buffer_size;
1884  p_frame->p_buffer = p_buffer;
1885  ni_log(NI_LOG_TRACE, "%s: Allocate new p_frame buffer\n", __FUNCTION__);
1886  }
1887  else
1888  {
1889  ni_log(NI_LOG_TRACE, "%s: reuse p_frame buffer\n", __FUNCTION__);
1890  }
1891 
1892  if (hw_frame_count)
1893  {
1894  p_frame->data_len[0] = 0;
1895  p_frame->data_len[1] = 0;
1896  p_frame->data_len[2] = 0;
1897  p_frame->data_len[3] = sizeof(ni_logan_hwframe_surface_t) * hw_frame_count;
1898  }
1899  else
1900  {
1901  p_frame->data_len[0] = luma_size;
1902  p_frame->data_len[1] = chroma_b_size;
1903  p_frame->data_len[2] = chroma_r_size;
1904  p_frame->data_len[3] = 0;//unused by hwdesc
1905  }
1906 
1907  p_frame->p_data[0] = (uint8_t*)p_frame->p_buffer;
1908  p_frame->p_data[1] = (uint8_t*)p_frame->p_data[0] + p_frame->data_len[0];
1909  p_frame->p_data[2] = (uint8_t*)p_frame->p_data[1] + p_frame->data_len[1];
1910  p_frame->p_data[3] = (uint8_t*)p_frame->p_data[2] + p_frame->data_len[2]; //hwdescriptor
1911 
1912  p_frame->video_width = width_aligned;
1913  p_frame->video_height = height_aligned;
1914 
1915  ni_log(NI_LOG_TRACE, "%s: success: p_frame->buffer_size=%d\n",
1916  __FUNCTION__, p_frame->buffer_size);
1917 
1918  END:
1919 
1920  if (NI_LOGAN_RETCODE_SUCCESS != retval)
1921  {
1922  ni_logan_aligned_free(p_buffer);
1923  }
1924 
1925  return retval;
1926 }
1927 
1928 /*!*****************************************************************************
1929  * \brief Allocate memory for decoder frame buffer based on provided
1930  * parameters; the memory is retrieved from a buffer pool and will be
1931  * returned to the same buffer pool by ni_logan_decoder_frame_buffer_free.
1932  * Note: all attributes of ni_logan_frame_t will be set up except for memory and
1933  * buffer, which rely on the pool being allocated; the pool will be
1934  * allocated only after the frame resolution is known.
1935  *
1936  * \param[in] p_pool Buffer pool to get the memory from
1937  * \param[in] p_frame Pointer to a caller allocated ni_logan_frame_t struct
1938  * \param[in] alloc_mem Whether to get memory from buffer pool
1939  * \param[in] video_width Width of the video frame
1940  * \param[in] video_height Height of the video frame
1941  * \param[in] alignment Allignment requirement
1942  * \param[in] factor 1 for 8 bits/pixel format, 2 for 10 bits/pixel
1943  *
1944  * \return On success
1945  * NI_LOGAN_RETCODE_SUCCESS
1946  * On failure
1947  * NI_LOGAN_RETCODE_INVALID_PARAM
1948  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
1949  ******************************************************************************/
1951  ni_logan_frame_t *p_frame,
1952  int alloc_mem,
1953  int video_width,
1954  int video_height,
1955  int alignment,
1956  int factor)
1957 {
1958  void* p_buffer = NULL;
1959  int retval = NI_LOGAN_RETCODE_SUCCESS;
1960  int width_aligned = video_width;
1961  int height_aligned = video_height;
1962 
1963  if (!p_frame || (factor != 1 && factor != 2) ||
1964  video_width > NI_LOGAN_MAX_RESOLUTION_WIDTH || video_width <= 0 ||
1965  video_height > NI_LOGAN_MAX_RESOLUTION_HEIGHT || video_height <= 0)
1966  {
1967  ni_log(NI_LOG_TRACE, "ERROR: %s passed parameters are null!, return\n",
1968  __FUNCTION__);
1970  }
1971 
1972  width_aligned = ((video_width + 31) / 32) * 32;
1973  height_aligned = ((video_height + 7) / 8) * 8;
1974  if (alignment)
1975  {
1976  height_aligned = ((video_height + 15) / 16) * 16;
1977  }
1978 
1979  ni_log(NI_LOG_TRACE, "%s: aligned=%dx%d orig=%dx%d\n", __FUNCTION__,
1980  width_aligned, height_aligned, video_width, video_height);
1981 
1982  int luma_size = width_aligned * height_aligned * factor;
1983  int chroma_b_size = luma_size / 4;
1984  int chroma_r_size = chroma_b_size;
1985  int buffer_size = luma_size + chroma_b_size + chroma_r_size +
1987 
1988  // added 2 blocks of 512 bytes buffer space to handle any extra metadata
1989  // retrieval from fw
1990  buffer_size = ((buffer_size + (NI_LOGAN_MEM_PAGE_ALIGNMENT - 1)) / NI_LOGAN_MEM_PAGE_ALIGNMENT) *
1992 
1993  p_frame->buffer_size = buffer_size;
1994 
1995  // if need to get a buffer from pool, pool must have been set up
1996  if (alloc_mem)
1997  {
1998  if (! p_pool)
1999  {
2000  ni_log(NI_LOG_TRACE, "ERROR %s: invalid pool!\n", __FUNCTION__);
2002  LRETURN;
2003  }
2004 
2005  p_frame->dec_buf = ni_logan_buf_pool_get_buffer(p_pool);
2006  if (! p_frame->dec_buf)
2007  {
2009  LRETURN;
2010  }
2011 
2012  p_frame->p_buffer = p_frame->dec_buf->buf;
2013 
2014  ni_log(NI_LOG_TRACE, "%s: got new frame ptr %p buffer %p\n",
2015  __FUNCTION__, p_frame->p_buffer, p_frame->dec_buf);
2016  }
2017  else
2018  {
2019  p_frame->dec_buf = p_frame->p_buffer = NULL;
2020  ni_log(NI_LOG_TRACE, "%s: NOT alloc mem buffer\n", __FUNCTION__);
2021  }
2022 
2023  if (p_frame->p_buffer)
2024  {
2025  p_frame->p_data[0] = (uint8_t*)p_frame->p_buffer;
2026  p_frame->p_data[1] = (uint8_t*)p_frame->p_data[0] + luma_size;
2027  p_frame->p_data[2] = (uint8_t*)p_frame->p_data[1] + chroma_b_size;
2028  p_frame->p_data[3] = (uint8_t*)p_frame->p_data[2] + chroma_r_size;
2029  }
2030  else
2031  {
2032  p_frame->p_data[0] = p_frame->p_data[1] = p_frame->p_data[2] = p_frame->p_data[3] = NULL;
2033  luma_size = chroma_b_size = chroma_r_size = 0;
2034  p_frame->buffer_size = 0;
2035  }
2036 
2037  p_frame->data_len[0] = luma_size;
2038  p_frame->data_len[1] = chroma_b_size;
2039  p_frame->data_len[2] = chroma_r_size;
2040  p_frame->data_len[3] = 0; //for hwdesc
2041 
2042  p_frame->video_width = width_aligned;
2043  p_frame->video_height = height_aligned;
2044 
2045  ni_log(NI_LOG_TRACE, "%s: success: p_frame->buffer_size=%d\n",
2046  __FUNCTION__, p_frame->buffer_size);
2047 
2048  END:
2049 
2050  return retval;
2051 }
2052 
2053 /*!*****************************************************************************
2054  * \brief Allocate memory for the frame buffer for encoding based on given
2055  * parameters, taking into account pic line size and extra data.
2056  * Applicable to YUV420p AVFrame only. 8 or 10 bit/pixel.
2057  * Cb/Cr size matches that of Y.
2058  *
2059  * \param[in] p_frame Pointer to a caller allocated ni_logan_frame_t struct
2060  *
2061  * \param[in] video_width Width of the video frame
2062  * \param[in] video_height Height of the video frame
2063  * \param[in] linesize Picture line size
2064  * \param[in] alignment Allignment requirement
2065  * \param[in] extra_len Extra data size (incl. meta data)
2066  *
2067  * \return On success
2068  * NI_LOGAN_RETCODE_SUCCESS
2069  * On failure
2070  * NI_LOGAN_RETCODE_INVALID_PARAM
2071  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
2072  *****************************************************************************/
2074  int video_width,
2075  int video_height,
2076  int linesize[],
2077  int alignment,
2078  int extra_len,
2079  int factor)
2080 {
2081  void* p_buffer = NULL;
2082  int height_aligned = video_height;
2083  int retval = NI_LOGAN_RETCODE_SUCCESS;
2084 
2085  if (!p_frame || !linesize || linesize[0] <= 0 ||
2086  linesize[0] > NI_LOGAN_MAX_RESOLUTION_WIDTH * factor ||
2087  video_width > NI_LOGAN_MAX_RESOLUTION_WIDTH || video_width <= 0 ||
2088  video_height>NI_LOGAN_MAX_RESOLUTION_HEIGHT || video_height<=0)
2089  {
2090  ni_log(NI_LOG_TRACE, "ERROR: %s passed parameters are null!, return\n",
2091  __FUNCTION__);
2093  }
2094  // TBD height has to be 8-aligned; had a checking at codec opening, but
2095  // if still getting non-8-aligned here, that could only be the case of
2096  // resolution change mid-stream: device_handle it by making them 8-aligned
2097  height_aligned = ((video_height + 7) / 8) * 8;
2098 
2099  if (alignment)
2100  {
2101  height_aligned = ((video_height + 15) / 16) * 16;
2102  }
2103 
2104  if (height_aligned < NI_LOGAN_MIN_HEIGHT)
2105  {
2106  height_aligned = NI_LOGAN_MIN_HEIGHT;
2107  }
2108 
2109  ni_log(NI_LOG_TRACE, "%s: aligned=%dx%d orig=%dx%d linesize=%d/%d/%d "
2110  "extra_len=%d\n", __FUNCTION__, video_width, height_aligned,
2111  video_width, video_height, linesize[0], linesize[1], linesize[2],
2112  extra_len);
2113 
2114  int luma_size = linesize[0] * height_aligned;
2115  int chroma_b_size = luma_size / 4;
2116  int chroma_r_size = luma_size / 4;
2117  int buffer_size = luma_size + chroma_b_size + chroma_r_size + extra_len;
2118 
2119  buffer_size = ((buffer_size + (NI_LOGAN_MEM_PAGE_ALIGNMENT - 1)) / NI_LOGAN_MEM_PAGE_ALIGNMENT) *
2121 
2122  //Check if Need to free
2123  if (p_frame->buffer_size != buffer_size && p_frame->buffer_size > 0)
2124  {
2125  ni_log(NI_LOG_TRACE, "%s: free current p_frame, p_frame->buffer_size=%d\n",
2126  __FUNCTION__, p_frame->buffer_size);
2127  ni_logan_frame_buffer_free(p_frame);
2128  }
2129 
2130  //Check if need to realocate
2131  if (p_frame->buffer_size != buffer_size)
2132  {
2133 #ifndef XCODER_SIM_ENABLED
2134  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size))
2135  {
2136  ni_log(NI_LOG_ERROR, "ERROR %d: Cannot allocate p_frame buffer.\n",
2137  NI_ERRNO);
2139  LRETURN;
2140  }
2141 #else
2142  p_buffer = malloc(buffer_size);
2143  if (!p_buffer)
2144  {
2145  ni_log(NI_LOG_ERROR, "ERROR %d: Cannot allocate p_frame buffer.\n",
2146  NI_ERRNO);
2148  LRETURN;
2149  }
2150 #endif
2151  // init once after allocation
2152  memset(p_buffer, 0, buffer_size);
2153  p_frame->buffer_size = buffer_size;
2154  p_frame->p_buffer = p_buffer;
2155 
2156  ni_log(NI_LOG_TRACE, "%s: allocated new p_frame buffer\n", __FUNCTION__);
2157  }
2158  else
2159  {
2160  ni_log(NI_LOG_TRACE, "%s: reuse p_frame buffer\n", __FUNCTION__);
2161  }
2162 
2163  p_frame->p_data[0] = (uint8_t*)p_frame->p_buffer;
2164  p_frame->p_data[1] = (uint8_t*)p_frame->p_data[0] + luma_size;
2165  p_frame->p_data[2] = (uint8_t*)p_frame->p_data[1] + chroma_b_size;
2166  p_frame->p_data[3] = (uint8_t*)p_frame->p_data[2] + chroma_r_size;
2167 
2168  p_frame->data_len[0] = luma_size;
2169  p_frame->data_len[1] = chroma_b_size;
2170  p_frame->data_len[2] = chroma_r_size;
2171  p_frame->data_len[3] = 0;//unused by hwdesc
2172 
2173  p_frame->video_width = video_width;
2174  p_frame->video_height = height_aligned;
2175 
2176  ni_log(NI_LOG_TRACE, "%s: success: p_frame->buffer_size=%d\n",
2177  __FUNCTION__, p_frame->buffer_size);
2178 
2179  END:
2180 
2181  if (NI_LOGAN_RETCODE_SUCCESS != retval)
2182  {
2183  ni_logan_aligned_free(p_buffer);
2184  }
2185 
2186  return retval;
2187 }
2188 
2189 /*!******************************************************************************
2190  * \brief Free frame buffer that was previously allocated with either
2191  * ni_logan_frame_buffer_alloc or ni_logan_encoder_frame_buffer_alloc
2192  *
2193  * \param[in] p_frame Pointer to a previously allocated ni_logan_frame_t struct
2194  *
2195  * \return On success NI_LOGAN_RETCODE_SUCCESS
2196  * On failure NI_LOGAN_RETCODE_INVALID_PARAM
2197  *******************************************************************************/
2199 {
2200  int i;
2202 
2203  ni_log(NI_LOG_TRACE, "%s: enter\n", __FUNCTION__);
2204 
2205  if (!p_frame)
2206  {
2207  ni_log(NI_LOG_TRACE, "WARN: %s(): p_frame is NULL\n", __FUNCTION__);
2208  LRETURN;
2209  }
2210 
2211  if (!p_frame->p_buffer)
2212  {
2213  ni_log(NI_LOG_TRACE, "WARN: %s(): already freed, nothing to free\n",
2214  __FUNCTION__);
2215  // made idempotent so that aux data of dummy frame can be freed
2216  }
2217 
2218  ni_logan_aligned_free(p_frame->p_buffer);
2219  p_frame->p_buffer = NULL;
2220 
2221  p_frame->buffer_size = 0;
2222  for (i = 0; i < NI_LOGAN_MAX_NUM_DATA_POINTERS; i++)
2223  {
2224  p_frame->data_len[i] = 0;
2225  p_frame->p_data[i] = NULL;
2226  }
2228 
2229  END:
2230 
2231  ni_log(NI_LOG_TRACE, "%s: exit\n", __FUNCTION__);
2232 
2233  return retval;
2234 }
2235 
2236 /*!*****************************************************************************
2237  * \brief Free decoder frame buffer that was previously allocated with
2238  * ni_logan_decoder_frame_buffer_alloc, returning memory to a buffer pool.
2239  *
2240  * \param[in] p_frame Pointer to a previously allocated ni_logan_frame_t struct
2241  *
2242  * \return On success NI_LOGAN_RETCODE_SUCCESS
2243  * On failure NI_LOGAN_RETCODE_INVALID_PARAM
2244  ******************************************************************************/
2246 {
2247  int i;
2249 
2250  ni_log(NI_LOG_TRACE, "%s: enter\n", __FUNCTION__);
2251 
2252  if (!p_frame)
2253  {
2254  ni_log(NI_LOG_TRACE, "WARN: %s(): p_frame is NULL\n", __FUNCTION__);
2256  LRETURN;
2257  }
2258 
2259  if (p_frame->dec_buf)
2260  {
2262  ni_log(NI_LOG_TRACE, "%s(): Mem buf returned ptr %p buf %p!\n",
2263  __FUNCTION__, p_frame->dec_buf->buf, p_frame->dec_buf);
2264  }
2265  else
2266  {
2267  ni_log(NI_LOG_TRACE, "%s(): NO mem buf returned !\n", __FUNCTION__);
2268  }
2269 
2270  p_frame->dec_buf = p_frame->p_buffer = NULL;
2271 
2272  p_frame->buffer_size = 0;
2273  for (i = 0; i < NI_LOGAN_MAX_NUM_DATA_POINTERS; i++)
2274  {
2275  p_frame->data_len[i] = 0;
2276  p_frame->p_data[i] = NULL;
2277  }
2279 
2280  END:
2281 
2282  ni_log(NI_LOG_TRACE, "%s: exit\n", __FUNCTION__);
2283 
2284  return retval;
2285 }
2286 
2287 /*!*****************************************************************************
2288  * \brief Return a memory buffer to memory buffer pool.
2289  *
2290  * \param[in] buf Buffer to be returned.
2291  * \param[in] p_buffer_pool Buffer pool to return buffer to.
2292  *
2293  * \return None
2294  ******************************************************************************/
2296 {
2297  ni_logan_buf_pool_return_buffer(buf, p_buffer_pool);
2298 }
2299 
2300 /*!******************************************************************************
2301  * \brief Allocate memory for the packet buffer based on provided packet size
2302  *
2303  * \param[in] p_packet Pointer to a caller allocated
2304  * ni_logan_packet_t struct
2305  * \param[in] packet_size Required allocation size
2306  *
2307  * \return On success
2308  * NI_LOGAN_RETCODE_SUCCESS
2309  * On failure
2310  * NI_LOGAN_RETCODE_INVALID_PARAM
2311  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
2312  *******************************************************************************/
2314 {
2315  void* p_buffer = NULL;
2316  int metadata_size = 0;
2317  int retval = NI_LOGAN_RETCODE_SUCCESS;
2318 
2319  metadata_size = NI_LOGAN_FW_META_DATA_SZ;
2320 
2321  int buffer_size = (((packet_size + metadata_size) / NI_LOGAN_MAX_PACKET_SZ) + 1) * NI_LOGAN_MAX_PACKET_SZ;
2322 
2323  ni_log(NI_LOG_TRACE, "%s: packet_size=%d\n",
2324  __FUNCTION__, packet_size + metadata_size);
2325 
2326  if (!p_packet || !packet_size)
2327  {
2328  ni_log(NI_LOG_TRACE, "ERROR: %s(): null pointer parameters passed\n",
2329  __FUNCTION__);
2331  }
2332 
2333  if (buffer_size % NI_LOGAN_MEM_PAGE_ALIGNMENT)
2334  {
2336  }
2337 
2338  if (p_packet->buffer_size == buffer_size)
2339  {
2340  p_packet->p_data = p_packet->p_buffer;
2341  ni_log(NI_LOG_TRACE, "%s(): reuse current p_packet buffer\n", __FUNCTION__);
2342  LRETURN; //Already allocated the exact size
2343  }
2344  else if (p_packet->buffer_size > 0)
2345  {
2346  ni_log(NI_LOG_TRACE, "%s(): free current p_packet buffer_size=%d\n",
2347  __FUNCTION__, p_packet->buffer_size);
2348  ni_logan_packet_buffer_free(p_packet);
2349  }
2350  ni_log(NI_LOG_TRACE, "%s(): Allocating p_frame buffer, buffer_size=%d\n",
2351  __FUNCTION__, buffer_size);
2352 #ifndef XCODER_SIM_ENABLED
2353  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size))
2354  {
2355  ni_log(NI_LOG_TRACE, "ERROR %d: %s() Cannot allocate p_frame buffer.\n",
2356  NI_ERRNO, __FUNCTION__);
2358  LRETURN;
2359  }
2360 #else
2361  p_buffer = malloc(buffer_size);
2362  if (p_buffer == NULL)
2363  {
2364  ni_log(NI_LOG_ERROR, "ERROR %d: %s(): Cannot allocate p_frame buffer.\n",
2365  NI_ERRNO, __FUNCTION__);
2367  LRETURN;
2368  }
2369 #endif
2370  memset(p_buffer, 0, buffer_size);
2371  p_packet->buffer_size = buffer_size;
2372  p_packet->p_buffer = p_buffer;
2373  p_packet->p_data = p_packet->p_buffer;
2374 
2375  END:
2376 
2377  if (NI_LOGAN_RETCODE_SUCCESS != retval)
2378  {
2379  ni_logan_aligned_free(p_buffer);
2380  }
2381 
2382  ni_log(NI_LOG_TRACE, "%s: exit: p_packet->buffer_size=%d\n",
2383  __FUNCTION__, p_packet->buffer_size);
2384 
2385  return retval;
2386 }
2387 
2388 /*!******************************************************************************
2389  * \brief Free packet buffer that was previously allocated with either
2390  * ni_logan_packet_buffer_alloc
2391  *
2392  * \param[in] p_packet Pointer to a previously allocated ni_logan_packet_t struct
2393  *
2394  * \return On success NI_LOGAN_RETCODE_SUCCESS
2395  * On failure NI_LOGAN_RETCODE_INVALID_PARAM
2396  *******************************************************************************/
2398 {
2400 
2401  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
2402 
2403  if (!p_packet)
2404  {
2405  ni_log(NI_LOG_TRACE, "ERROR: %s(): p_packet is NULL\n", __FUNCTION__);
2406  retval = NI_LOGAN_RETCODE_FAILURE;
2407  LRETURN;
2408  }
2409 
2410  if (!p_packet->p_buffer)
2411  {
2412  p_packet->data_len = 0;
2413  ni_log(NI_LOG_TRACE, "%s(): already freed nothing to free\n", __FUNCTION__);
2414  LRETURN;
2415  }
2416 
2417  ni_logan_aligned_free(p_packet->p_buffer);
2418  p_packet->p_buffer = NULL;
2419 
2420  p_packet->buffer_size = 0;
2421  p_packet->data_len = 0;
2422  p_packet->p_data = NULL;
2423 
2424  END:
2425 
2426  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
2427 
2428  return retval;
2429 }
2430 
2431 /*!******************************************************************************
2432  * \brief Copy video packet accounting for allighment
2433  *
2434  * \param[in] p_destination Destination to where to copy to
2435  * \param[in] p_source Source from where to copy from
2436  * \param[in] cur_size current size
2437  * \param[out] p_leftover Pointer to the data that was left over
2438  * \param[out] p_prev_size Size of the data leftover ??
2439  *
2440  * \return On success Total number of bytes that were copied
2441  * On failure NI_LOGAN_RETCODE_FAILURE
2442  *******************************************************************************/
2443 int ni_logan_packet_copy(void* p_destination,
2444  const void* const p_source,
2445  int cur_size,
2446  void* p_leftover,
2447  int* p_prev_size)
2448 {
2449  int copy_size = 0;
2450  int padding_size = 0;
2451  int prev_size = p_prev_size == NULL? 0 : *p_prev_size;
2452  int total_size = cur_size + prev_size;
2453  uint8_t* p_src = (uint8_t*)p_source;
2454  uint8_t* p_dst = (uint8_t*)p_destination;
2455  uint8_t* p_lftover = (uint8_t*)p_leftover;
2456 
2457  ni_log(NI_LOG_TRACE, "%s(): enter, cur_size=%d, copy_size=%d, prev_size=%d\n",
2458  __FUNCTION__, cur_size, copy_size, *p_prev_size);
2459 
2460  if (0 == cur_size && 0 == prev_size)
2461  {
2462  return copy_size;
2463  }
2464 
2465  if (((0 != cur_size) && (!p_source)) || (!p_destination) || (!p_leftover))
2466  {
2467  return NI_LOGAN_RETCODE_FAILURE;
2468  }
2469 
2471 
2472  if (copy_size > total_size)
2473  {
2474  padding_size = copy_size - total_size;
2475  }
2476 
2477  if (prev_size > 0)
2478  {
2479  memcpy(p_dst, p_lftover, prev_size);
2480  }
2481 
2482  p_dst += prev_size;
2483 
2484  memcpy(p_dst, p_src, cur_size);
2485 
2486  if (padding_size)
2487  {
2488  p_dst += cur_size;
2489  memset(p_dst, 0, padding_size);
2490  }
2491 
2492  if (p_prev_size)
2493  {
2494  *p_prev_size = 0;
2495  }
2496 
2497  ni_log(NI_LOG_TRACE, "%s(): exit, cur_size=%d, copy_size=%d, prev_size=%d\n",
2498  __FUNCTION__, cur_size, copy_size, *p_prev_size);
2499 
2500  return copy_size;
2501 }
2502 
2503 /*!******************************************************************************
2504  * \brief Initialize default encoder parameters
2505  *
2506  * \param[out] param Pointer to a user allocated ni_logan_encoder_params_t
2507  * to initialize to default parameters
2508  * \param[in] fps_num Frames per second
2509  * \param[in] fps_denom FPS denomination
2510  * \param[in] bit_rate bit rate
2511  * \param[in] width width
2512  * \param[in] height height
2513  *
2514  * \return On success
2515  * NI_LOGAN_RETCODE_SUCCESS
2516  * On failure
2517  * NI_LOGAN_RETCODE_FAILURE
2518  * NI_LOGAN_RETCODE_INVALID_PARAM
2519  *******************************************************************************/
2521  int fps_num,
2522  int fps_denom,
2523  long bit_rate,
2524  int width,
2525  int height)
2526 {
2527  ni_logan_encoder_input_params_t* p_enc = NULL;
2528  int i = 0;
2530 
2531  //Initialize p_param structure
2532  if (!p_param)
2533  {
2534  ni_log(NI_LOG_TRACE, "ERROR: %s(): null pointer parameters passed\n",
2535  __FUNCTION__);
2537  LRETURN;
2538  }
2539 
2540  ni_log(NI_LOG_TRACE, "%s()\n", __FUNCTION__);
2541 
2542  //Initialize p_param structure
2543  memset(p_param, 0, sizeof(ni_logan_encoder_params_t));
2544 
2545  p_enc = &p_param->enc_input_params;
2546 
2547  // Rev. B: unified for HEVC/H.264
2548  p_enc->profile = 0;
2549  p_enc->level_idc = 0;
2550  p_enc->high_tier = 0;
2551 
2553  p_enc->use_recommend_enc_params = 0; // TBD: remove this param from API as it is revA specific
2554 
2555  p_enc->rc.trans_rate = 0;
2556 
2557  p_enc->rc.enable_rate_control = 0;
2558  p_enc->rc.enable_cu_level_rate_control = 1;
2559  p_enc->rc.enable_hvs_qp = 0;
2560  p_enc->rc.enable_hvs_qp_scale = 1;
2561  p_enc->rc.hvs_qp_scale = 2;
2565  p_enc->rc.rc_init_delay = 3000;
2566 
2567  p_enc->roi_enable = 0;
2568 
2570  p_enc->long_term_ref_enable = 0;
2571 
2572  p_enc->lossless_enable = 0;
2573 
2574  p_enc->conf_win_top = 0;
2575  p_enc->conf_win_bottom = 0;
2576  p_enc->conf_win_left = 0;
2577  p_enc->conf_win_right = 0;
2578 
2579  p_enc->intra_period = 92;
2581  // TBD Rev. B: could be shared for HEVC and H.264 ?
2582  p_enc->rc.enable_mb_level_rc = 1;
2583 
2584  p_enc->decoding_refresh_type = 2;
2585  p_enc->slice_mode = 0;
2586  p_enc->slice_arg = 0;
2587 
2588  p_enc->rc.max_frame_size = 0;
2589  p_enc->rc.max_frame_ratio = 0;
2590 
2591  // Rev. B: H.264 only parameters.
2592  p_enc->enable_transform_8x8 = 1;
2593  p_enc->avc_slice_mode = 0;
2594  p_enc->avc_slice_arg = 0;
2595  p_enc->entropy_coding_mode = 1;
2596 
2597  p_enc->intra_mb_refresh_mode = 0;
2598  p_enc->intra_mb_refresh_arg = 0;
2599 
2601  for (i = 0; i < NI_LOGAN_MAX_GOP_NUM; i++)
2602  {
2604  p_enc->custom_gop_params.pic_param[i].poc_offset = 0;
2605  p_enc->custom_gop_params.pic_param[i].pic_qp = 0;
2606 
2607  // syed todo: check this initial value, added for T408 5
2609 
2610  p_enc->custom_gop_params.pic_param[i].ref_poc_L0 = 0;
2611  p_enc->custom_gop_params.pic_param[i].ref_poc_L1 = 0;
2612  p_enc->custom_gop_params.pic_param[i].temporal_id = 0;
2613  }
2615  p_enc->set_high_priority = 0;
2616 
2617  p_param->source_width = width;
2618  p_param->source_height = height;
2619 
2620  p_param->fps_number = fps_num;
2621  p_param->fps_denominator = fps_denom;
2622 
2623  if (p_param->fps_number && p_param->fps_denominator)
2624  {
2625  p_enc->frame_rate = p_param->fps_number / p_param->fps_denominator;
2626  }
2627  else
2628  {
2629  p_enc->frame_rate = 30;
2630  }
2631 
2632  p_param->bitrate = bit_rate;
2633  p_param->roi_demo_mode = 0;
2634  p_param->reconf_demo_mode = 0; // NETINT_INTERNAL - currently only for internal testing
2635  p_param->force_pic_qp_demo_mode = 0;
2636  p_param->force_frame_type = 0;
2637  p_param->hdrEnableVUI = 0;
2638  p_param->crf = -1;
2639  p_param->crfIpRatio = 0.0;
2640  p_param->crfPbRatio = 0.0;
2641  p_param->cbr = 0;
2642  p_param->cacheRoi = 0;
2643  p_param->ui32flushGop = 0;
2644  p_param->ui32minIntraRefreshCycle = 0;
2645  p_param->low_delay_mode = 0;
2646  p_param->padding = 1;
2647  p_param->generate_enc_hdrs = 0;
2648  p_param->use_low_delay_poc_type = 0;
2649  p_param->strict_timeout_mode = 0;
2650 
2652 
2653  p_param->dolby_vision_profile = 0;
2654  p_param->hrd_enable = 0;
2655  p_param->enable_aud = 0;
2656 
2657  p_param->color_primaries = 2; // default COL_PRI_UNSPECIFIED
2658  p_param->color_transfer_characteristic = 2; // default COL_TRC_UNSPECIFIED
2659  p_param->color_space = 2; // default COL_SPC_UNSPECIFIED
2660  p_param->sar_num = 0; // default SAR numerator 0
2661  p_param->sar_denom = 1; // default SAR denominator 1
2662  p_param->video_full_range_flag = -1;
2663 
2664  p_param->nb_save_pkt = 0;
2665 
2666  if (p_param->source_width > NI_LOGAN_PARAM_MAX_WIDTH)
2667  {
2669  LRETURN;
2670  }
2671  if (p_param->source_width < NI_LOGAN_PARAM_MIN_WIDTH)
2672  {
2674  LRETURN;
2675  }
2676 
2678  {
2680  LRETURN;
2681  }
2683  {
2685  LRETURN;
2686  }
2688  {
2690  LRETURN;
2691  }
2692 
2693  END:
2694 
2695  return retval;
2696 }
2697 
2699  int fps_num,
2700  int fps_denom,
2701  long bit_rate,
2702  int width,
2703  int height)
2704 {
2705  ni_logan_decoder_input_params_t* p_dec = NULL;
2706  int i = 0;
2708 
2709  //Initialize p_param structure
2710  if (!p_param)
2711  {
2712  ni_log(NI_LOG_TRACE, "%s(): null pointer parameter passed\n", __FUNCTION__);
2714  LRETURN;
2715  }
2716 
2717  ni_log(NI_LOG_TRACE, "%s\n", __FUNCTION__);
2718 
2719  //Initialize p_param structure
2720  memset(p_param, 0, sizeof(ni_logan_decoder_params_t));
2721 
2722  p_dec = &p_param->dec_input_params;
2723  p_dec->hwframes = 0;
2725  p_dec->set_high_priority = 0;
2726  p_dec->enable_user_data_sei_passthru = 0;
2727  p_dec->check_packet = 0;
2729  p_dec->lowdelay = 0;
2730  p_dec->enable_follow_iframe = 0;
2731  p_dec->enable_vui_info_passthru = 0;
2732 
2733  p_param->source_width = width;
2734  p_param->source_height = height;
2735  p_param->fps_number = fps_num;
2736  p_param->fps_denominator = fps_denom;
2737  p_param->bitrate = bit_rate;
2738 
2739  p_param->nb_save_pkt = 0;
2740 
2741  END:
2742 
2743  return retval;
2744 }
2745 
2746 // read demo reconfig data file and parse out reconfig key/values in the format:
2747 // key:val1,val2,val3,...val9 (max 9 values); only digit/:/,/newline is allowed
2748 ni_logan_retcode_t ni_logan_parse_reconf_file(const char* reconf_file, int hash_map[100][10])
2749 {
2750  char keyChar[10] = "";
2751  int key = 0;
2752  char valChar[10] = "";
2753  int val = 0;
2754  int valIdx = 1;
2755  int parseKey = 1;
2756  int idx = 0;
2757  int readc = EOF;
2758 
2759  if (!reconf_file)
2760  {
2761  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n",
2762  __FUNCTION__);
2764  }
2765 
2766  FILE *reconf = fopen(reconf_file, "r");
2767  if (!reconf)
2768  {
2769  ni_log(NI_LOG_ERROR, "ERROR %d: %s(): Cannot open reconfig_file: %s\n",
2770  NI_ERRNO, __FUNCTION__, reconf_file);
2771  return NI_LOGAN_RETCODE_FAILURE;
2772  }
2773 
2774  while ((readc = fgetc(reconf)) != EOF)
2775  {
2776  //parse lines
2777  if (isdigit(readc))
2778  {
2779  if (parseKey)
2780  {
2781  strncat(keyChar, (const char *)(&readc), 1);
2782  }
2783  else
2784  {
2785  strncat(valChar, (const char *)(&readc), 1);
2786  }
2787  }
2788  else if (readc == ':')
2789  {
2790  parseKey = 0;
2791  key = atoi(keyChar);
2792  hash_map[idx][0] = key;
2793  }
2794  else if (readc == ',')
2795  {
2796  val = atoi(valChar);
2797  hash_map[idx][valIdx] = val;
2798  valIdx++;
2799  memset(valChar, 0, 10);
2800  }
2801  else if (readc == '\n')
2802  {
2803  parseKey = 1;
2804  val = atoi (valChar);
2805  hash_map[idx][valIdx] = val;
2806  valIdx = 1;
2807  memset(keyChar,0,10);
2808  memset(valChar,0,10);
2809  idx ++;
2810  }
2811  else
2812  {
2813  ni_log(NI_LOG_TRACE, "error character %c in reconfig file. this may lead "
2814  "to mistaken reconfiguration values \n", readc);
2815  }
2816  }
2817 
2818  fclose(reconf);
2819 
2820  return NI_LOGAN_RETCODE_SUCCESS;
2821 }
2822 
2823 #undef atoi
2824 #undef atof
2825 #define atoi(p_str) ni_logan_atoi(p_str, &b_error)
2826 #define atof(p_str) ni_logan_atof(p_str, &b_error)
2827 #define atobool(p_str) (ni_logan_atobool(p_str, &b_error))
2828 /*!******************************************************************************
2829 * \brief Set value referenced by name in decoder parameters structure
2830 *
2831 * \param[in] p_params Pointer to a user allocated ni_logan_decoder_params_t
2832 * to find and set a particular parameter
2833 * \param[in] name String represented parameter name to search
2834 * \param[in] value Parameter value to set
2835 *
2836 * \return On success
2837 * NI_LOGAN_RETCODE_SUCCESS
2838 * On failure
2839 * NI_LOGAN_RETCODE_FAILURE
2840 * NI_LOGAN_RETCODE_INVALID_PARAM
2841 *******************************************************************************/
2843 {
2844  bool b_error = false;
2845  bool bNameWasBool = false;
2846  bool bValueWasNull = !value;
2848  char nameBuf[64] = { 0 };
2849  const char delim[2] = ",";
2850  const char xdelim[2] = "x";
2851 
2852  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
2853 
2854  if (!p_params)
2855  {
2856  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n", __FUNCTION__);
2858  }
2859 
2860  if (!name)
2861  {
2862  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n", __FUNCTION__);
2864  }
2865 
2866  // skip -- prefix if provided
2867  if (name[0] == '-' && name[1] == '-')
2868  {
2869  name += 2;
2870  }
2871 
2872  // s/_/-/g
2873  if (strlen(name) + 1 < sizeof(nameBuf) && strchr(name, '_'))
2874  {
2875  char* c;
2876  strcpy(nameBuf, name);
2877  while ((c = strchr(nameBuf, '_')) != 0)
2878  {
2879  *c = '-';
2880  }
2881 
2882  name = nameBuf;
2883  }
2884 
2885  if (!strncmp(name, "no-", 3))
2886  {
2887  name += 3;
2888  value = !value || ni_logan_atobool(value, &b_error) ? "false" : "true";
2889  }
2890  else if (!strncmp(name, "no", 2))
2891  {
2892  name += 2;
2893  value = !value || ni_logan_atobool(value, &b_error) ? "false" : "true";
2894  }
2895  else if (!value)
2896  {
2897  value = "true";
2898  }
2899  else if (value[0] == '=')
2900  {
2901  value++;
2902  }
2903 
2904 #ifdef _MSC_VER
2905 #define OPT(STR) else if (!_stricmp(name, STR))
2906 #define OPT2(STR1, STR2) else if (!_stricmp(name, STR1) || !_stricmp(name, STR2))
2907 #else
2908 #define OPT(STR) else if (!strcasecmp(name, STR))
2909 #define OPT2(STR1, STR2) else if (!strcasecmp(name, STR1) || !strcasecmp(name, STR2))
2910 #endif
2911  if (0)
2912  ;
2914  {
2915  if (!strncmp(value, "hw", 2)){
2916  p_dec->hwframes = 1;
2917  }
2918  else if (!strncmp(value, "sw", 2)) {
2919  p_dec->hwframes = 0;
2920  }
2921  else{
2922  ni_log(NI_LOG_ERROR, "ERROR: %s(): out can only be <hw,sw> got %s\n",
2923  __FUNCTION__, value);
2925  }
2926  }
2928  {
2929  if(atoi(value) != NI_LOGAN_MIN_PRIORITY &&
2930  atoi(value) != NI_LOGAN_MAX_PRIORITY)
2931  {
2933  }
2934  p_dec->set_high_priority = atoi(value);
2935  }
2937  {
2938  if(atoi(value) < NI_LOGAN_MIN_KEEP_ALIVE_TIMEOUT ||
2940  {
2942  }
2943  p_dec->keep_alive_timeout = atoi(value);
2944  }
2946  {
2949  {
2951  }
2952  p_dec->enable_user_data_sei_passthru = atoi(value);
2953  }
2955  {
2956  if(atoi(value) != NI_LOGAN_ENABLE_CHECK_PACKET &&
2958  {
2960  }
2961  p_dec->check_packet = atoi(value);
2962  }
2964  {
2965  if(atoi(value) < NI_LOGAN_MIN_CUSTOM_SEI_PASSTHRU ||
2967  {
2969  }
2970  p_dec->custom_sei_passthru = atoi(value);
2971  }
2973  {
2974  p_dec->lowdelay = atoi(value);
2975  }
2977  {
2978  p_params->nb_save_pkt = atoi(value);
2979  }
2981  {
2982  if (atoi(value) != 0 && atoi(value) != 1 && atoi(value) != 2)
2983  {
2985  }
2986  p_dec->low_delay_mode = atoi(value);
2987  }
2989  {
2990  if(atoi(value) != 0 && atoi(value) != 1)
2991  {
2993  }
2994  p_dec->enable_follow_iframe = atoi(value);
2995  }
2997  {
2998  if (atoi(value) != 0 && atoi(value) != 1)
2999  {
3000  ni_log(NI_LOG_ERROR, "Invalid %s: out of range\n", value);
3002  }
3003  p_dec->enable_vui_info_passthru = atoi(value);
3004  }
3006  {
3007  if(atoi(value) != 0 && atoi(value) != 1)
3008  {
3009  ni_log(NI_LOG_ERROR, "Invalid %s: out of range\n", value);
3011  }
3012  p_dec->enable_skip_fmt_none_check = atoi(value);
3013  }
3014  else
3015  {
3017  }
3018 #undef OPT
3019 #undef atobool
3020 #undef atoi
3021 #undef atof
3022  b_error |= bValueWasNull && !bNameWasBool;
3023 
3024  ni_log(NI_LOG_TRACE, "ni_logan_decoder_params_set_value: exit, b_error=%d\n", b_error);
3025 
3027 }
3028 
3029 
3030 #undef atoi
3031 #undef atof
3032 #define atoi(p_str) ni_logan_atoi(p_str, &b_error)
3033 #define atof(p_str) ni_logan_atof(p_str, &b_error)
3034 #define atobool(p_str) (ni_logan_atobool(p_str, &b_error))
3035 
3036 static ni_logan_retcode_t ni_logan_check_level(int level, int codec_id)
3037 {
3038  const int l_levels_264[] = {10, 11, 12, 13, 20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51, 52, 60, 61, 62, 0};
3039  const int l_levels_265[] = {10, 20, 21, 30, 31, 40, 41, 50, 51, 52, 60, 61, 62, 0};
3040  const int *l_levels = l_levels_264;
3041 
3042  if ( level == 0 )
3043  {
3044  return NI_LOGAN_RETCODE_SUCCESS;
3045  }
3046 
3047  if ( codec_id == NI_LOGAN_CODEC_FORMAT_H265 )
3048  {
3049  l_levels = l_levels_265;
3050  }
3051 
3052  while( *l_levels != 0 )
3053  {
3054  if ( *l_levels == level )
3055  {
3056  return NI_LOGAN_RETCODE_SUCCESS;
3057  }
3058 
3059  l_levels++;
3060  }
3061 
3062  return NI_LOGAN_RETCODE_FAILURE;
3063 }
3064 
3065 
3066 /*!******************************************************************************
3067  * \brief Set value referenced by name in encoder parameters structure
3068  *
3069  * \param[in] p_params Pointer to a user allocated ni_logan_encoder_params_t
3070  * to find and set a particular parameter
3071  * \param[in] name String represented parameter name to search
3072  * \param[in] value Parameter value to set
3073 *
3074  * \return On success
3075  * NI_LOGAN_RETCODE_SUCCESS
3076  * On failure
3077  * NI_LOGAN_RETCODE_FAILURE
3078  * NI_LOGAN_RETCODE_INVALID_PARAM
3079  *******************************************************************************/
3081  const char* name,
3082  const char* value,
3084 {
3085  bool b_error = false;
3086  bool bNameWasBool = false;
3087  bool bValueWasNull = !value;
3089  char nameBuf[64] = { 0 };
3090 
3091  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
3092 
3093  if (!p_params)
3094  {
3095  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n",
3096  __FUNCTION__);
3098  }
3099 
3100  if ( !name )
3101  {
3102  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n",
3103  __FUNCTION__);
3105  }
3106 
3107  // skip -- prefix if provided
3108  if (name[0] == '-' && name[1] == '-')
3109  {
3110  name += 2;
3111  }
3112 
3113  // s/_/-/g
3114  if (strlen(name) + 1 < sizeof(nameBuf) && strchr(name, '_'))
3115  {
3116  char* c;
3117  nameBuf[0] = '\0';
3118  strncat(nameBuf, name, strlen(name));
3119  while ((c = strchr(nameBuf, '_')) != 0)
3120  {
3121  *c = '-';
3122  }
3123 
3124  name = nameBuf;
3125  }
3126 
3127  if (!strncmp(name, "no-", 3))
3128  {
3129  name += 3;
3130  value = !value || ni_logan_atobool(value, &b_error) ? "false" : "true";
3131  }
3132  else if (!strncmp(name, "no", 2))
3133  {
3134  name += 2;
3135  value = !value || ni_logan_atobool(value, &b_error) ? "false" : "true";
3136  }
3137  else if (!value)
3138  {
3139  value = "true";
3140  }
3141  else if (value[0] == '=')
3142  {
3143  value++;
3144  }
3145 
3146 #ifdef _MSC_VER
3147 #define OPT(STR) else if (!_stricmp(name, STR))
3148 #define OPT2(STR1, STR2) else if (!_stricmp(name, STR1) || !_stricmp(name, STR2))
3149 #else
3150 #define OPT(STR) else if (!strcasecmp(name, STR))
3151 #define OPT2(STR1, STR2) else if (!strcasecmp(name, STR1) || !strcasecmp(name, STR2))
3152 #endif
3153 #define COMPARE(STR1, STR2, STR3) \
3154 if ((atoi(STR1) > STR2) || (atoi(STR1) < STR3)) \
3155 { \
3156  ni_log(NI_LOG_ERROR, "Invalid %s: out of range\n", name); \
3157  return NI_LOGAN_RETCODE_PARAM_ERROR_OOR; \
3158 }
3159 #define COMPARE_F(STR1, STR2, STR3) \
3160 if ((atof(STR1) > STR2) || (atof(STR1) < STR3)) \
3161 { \
3162  return NI_LOGAN_RETCODE_PARAM_ERROR_OOR; \
3163 }
3164 #define CHECK2VAL(STR, VAL1, VAL2) \
3165 if (atoi(STR) != VAL1 && atoi(STR) != VAL2) \
3166 { \
3167  ni_log(NI_LOG_ERROR, "Invalid %s: out of range\n", name); \
3168  return NI_LOGAN_RETCODE_PARAM_ERROR_OOR; \
3169 }
3170 
3171  if (0)
3172  ;
3174  {
3175  if (LOGAN_AV_CODEC_DEFAULT_BITRATE == p_params->bitrate)
3176  {
3177  if (atoi(value) > NI_LOGAN_MAX_BITRATE)
3178  {
3179  ni_log(NI_LOG_ERROR, "Invalid %s: too big\n", name);
3181  }
3182  if (atoi(value) < NI_LOGAN_MIN_BITRATE)
3183  {
3184  ni_log(NI_LOG_ERROR, "Invalid %s: too small\n", name);
3186  }
3187  p_params->bitrate = atoi(value);
3188  }
3189  }
3191  {
3192  p_params->reconf_demo_mode = atoi(value); // NETINT_INTERNAL - currently only for internal testing
3193  }
3195  {
3196  ni_logan_retcode_t retval = ni_logan_parse_reconf_file(value, p_params->reconf_hash);
3197  if (retval != NI_LOGAN_RETCODE_SUCCESS) // NETINT_INTERNAL - currently only for internal testing
3198  {
3199  return retval;
3200  }
3201  }
3203  {
3204  // NETINT_INTERNAL - currently only for internal testing
3205  CHECK2VAL(value, 1, 2)
3206  p_params->roi_demo_mode = atoi(value);
3207  }
3209  {
3210  p_params->low_delay_mode = atoi(value);
3211  }
3213  {
3214  p_params->padding = atoi(value);
3215  }
3217  {
3218  p_params->generate_enc_hdrs = atoi(value);
3219  }
3221  {
3222  p_params->use_low_delay_poc_type = atoi(value);
3223  }
3225  {
3226  p_params->force_frame_type = atoi(value);
3227  }
3229  {
3230  p_enc->profile = atoi(value);
3231  }
3233  {
3234  p_enc->level_idc = (int)(10 * strtof(value, NULL)); // if value is not digital number, it return 0
3235  if ( ( p_enc->level_idc== 0 && strcmp(value, "0") )||
3236  ( strlen(value) > 3 ) ||
3237  ( ni_logan_check_level(p_enc->level_idc,
3239  {
3240  b_error = true;
3241  }
3242  }
3244  {
3245  p_enc->high_tier = atobool(value);
3246  }
3248  {
3249  p_params->log = atoi(value);
3250  if (b_error)
3251  {
3252  b_error = false;
3253  p_params->log = ni_logan_parse_name(value, g_logan_xcoder_log_names, &b_error) - 1;
3254  }
3255  }
3257  {
3259  p_enc->gop_preset_index = atoi(value);
3260  }
3262  {
3264  p_enc->use_recommend_enc_params = atoi(value);
3265  }
3267  {
3269  p_enc->rc.enable_rate_control = atoi(value);
3270  }
3272  {
3274  p_enc->rc.enable_cu_level_rate_control = atoi(value);
3275  }
3277  {
3278  p_enc->rc.enable_hvs_qp = atoi(value);
3279  }
3281  {
3282  p_enc->rc.enable_hvs_qp_scale = atoi(value);
3283  }
3285  {
3286  p_enc->rc.hvs_qp_scale = atoi(value);
3287  }
3289  {
3291  p_enc->rc.min_qp = atoi(value);
3292  }
3294  {
3296  p_enc->rc.max_qp = atoi(value);
3297  }
3299  {
3301  p_enc->rc.max_delta_qp = atoi(value);
3302  }
3304  {
3305  p_enc->rc.rc_init_delay = atoi(value);
3306  }
3308  {
3309  p_enc->forced_header_enable = atoi(value);
3310  }
3312  {
3313  p_enc->roi_enable = atoi(value);
3314  }
3316  {
3317  p_enc->conf_win_top = atoi(value);
3318  }
3320  {
3321  p_enc->conf_win_bottom = atoi(value);
3322  }
3324  {
3325  p_enc->conf_win_left = atoi(value);
3326  }
3328  {
3329  p_enc->conf_win_right = atoi(value);
3330  }
3332  {
3334  p_enc->intra_period = atoi(value);
3335  }
3337  {
3338  if (atoi(value) > NI_LOGAN_MAX_BITRATE)
3339  {
3340  ni_log(NI_LOG_ERROR, "Invalid %s: too big\n", name);
3342  }
3343  if (atoi(value) < NI_LOGAN_MIN_BITRATE)
3344  {
3345  ni_log(NI_LOG_ERROR, "Invalid %s: too small\n", name);
3347  }
3348  p_enc->rc.trans_rate = atoi(value);
3349  }
3351  {
3352  if (atoi(value) <= 0 )
3353  {
3354  ni_log(NI_LOG_ERROR, "Error setting option %s to value 0\n", name);
3356  }
3357  p_params->fps_number = atoi(value);
3358  p_params->fps_denominator = 1;
3359  p_enc->frame_rate = p_params->fps_number;
3360  }
3362  {
3363  p_params->fps_denominator = atoi(value);
3364  if(p_params->fps_denominator == 0)
3365  {
3366  ni_log(NI_LOG_ERROR, "Error setting option %s to value 0\n", name);
3368  }
3369  p_enc->frame_rate = p_params->fps_number / p_params->fps_denominator;
3370  }
3372  {
3374  p_enc->rc.intra_qp = atoi(value);
3375  }
3377  {
3379  p_params->force_pic_qp_demo_mode = atoi(value);
3380  }
3382  {
3384  p_enc->decoding_refresh_type = atoi(value);
3385  }
3386 
3387  // only for HEVC
3389  {
3390 #ifdef _MSC_VER
3391  if (!_strnicmp(value, "ratio", 5))
3392 #else
3393  if (!strncasecmp(value, "ratio", 5))
3394 #endif
3395  {
3396  int i = 0;
3397  char value_buf[32] = {0};
3398  while( i < 32)
3399  {
3400  if((value[i+6]) == ']')
3401  {
3402  break;
3403  }
3404  else
3405  {
3406  value_buf[i] = value[i+6];
3407  i++;
3408  }
3409  }
3410  if(i == 32)
3411  {
3413  }
3414  if (atoi(value_buf) < 0)
3415  {
3417  }
3418 
3419  p_enc->rc.max_frame_ratio = atoi(value_buf);
3420  p_enc->rc.max_frame_size = 0;
3421  }
3422  else
3423  {
3424  if (atoi(value) < 0)
3425  {
3427  }
3428 
3429  p_enc->rc.max_frame_ratio = 0;
3430  p_enc->rc.max_frame_size = atoi(value);
3431  }
3432  }
3433  // only for HEVC
3435  {
3436 #ifdef _MSC_VER
3437  if (!_strnicmp(value, "ratio", 5))
3438 #else
3439  if (!strncasecmp(value, "ratio", 5))
3440 #endif
3441  {
3442  int i = 0;
3443  char value_buf[32] = {0};
3444  while( i < 32)
3445  {
3446  if((value[i+6]) == ']')
3447  {
3448  break;
3449  }
3450  else
3451  {
3452  value_buf[i] = value[i+6];
3453  i++;
3454  }
3455  }
3456  if(i == 32)
3457  {
3459  }
3460  if (atoi(value_buf) < 0)
3461  {
3463  }
3464 
3465  p_enc->rc.max_frame_ratio = atoi(value_buf);
3466  p_enc->rc.max_frame_size = 0;
3467  }
3468  else
3469  {
3470  if (atoi(value) < 0)
3471  {
3473  }
3474 
3475  p_enc->rc.max_frame_ratio = 0;
3476  p_enc->rc.max_frame_size = atoi(value) * 8;
3477  }
3478  }
3479 
3480 // Rev. B: H.264 only parameters.
3482  {
3483  p_enc->enable_transform_8x8 = atoi(value);
3484  }
3486  {
3487  CHECK2VAL(value, 0, 1)
3488  p_enc->avc_slice_mode = atoi(value);
3489  }
3491  {
3492  p_enc->avc_slice_arg = atoi(value);
3493  }
3495  {
3496  p_enc->entropy_coding_mode = atoi(value);
3497  }
3498 // Rev. B: shared between HEVC and H.264
3500  {
3501  CHECK2VAL(value, 0, 1)
3503  {
3504  p_enc->avc_slice_mode = atoi(value);
3505  }
3506  else
3507  {
3508  p_enc->slice_mode = atoi(value);
3509  }
3510  }
3512  {
3514  {
3515  p_enc->avc_slice_arg = atoi(value);
3516  }
3517  else
3518  {
3519  p_enc->slice_arg = atoi(value);
3520  }
3521  }
3523  {
3524  p_enc->intra_mb_refresh_mode = atoi(value);
3525  }
3527  {
3528  p_enc->intra_mb_refresh_arg = atoi(value);
3529  }
3531  {
3532  p_enc->intra_mb_refresh_mode = atoi(value);
3533  }
3535  {
3536  p_enc->intra_mb_refresh_arg = atoi(value);
3537  }
3538 // TBD Rev. B: could be shared for HEVC and H.264
3540  {
3541  p_enc->rc.enable_mb_level_rc = atoi(value);
3542  }
3544  {
3545  COMPARE(value, 255, 0)
3546  p_enc->preferred_transfer_characteristics = atoi(value);
3547  }
3549  {
3550  CHECK2VAL(value, 0, 5)
3551  p_params->dolby_vision_profile = atoi(value);
3552  }
3554  {
3555  CHECK2VAL(value, 0, 1)
3556  p_params->hrd_enable = atoi(value);
3557  }
3559  {
3560  CHECK2VAL(value, 0, 1)
3561  p_params->enable_aud = atoi(value);
3562  }
3564  {
3565  char *pTemp;
3566  pTemp = strchr(value, '.');
3567  if(pTemp != NULL)
3568  {
3569  if(strlen(pTemp) > 3)
3570  {
3571  ni_log(NI_LOG_ERROR, "ERROR: CRF QP only supports two bit fraction\n" );
3573  }
3574  }
3575 
3577  p_params->crf = (float)atof(value);
3578  }
3580  {
3581  char *pTemp;
3582  pTemp = strchr(value, '.');
3583  if(pTemp != NULL)
3584  {
3585  if(strlen(pTemp) > 3)
3586  {
3587  ni_log(NI_LOG_ERROR, "ERROR: CRF ip ratio only supports two bit fraction\n" );
3589  }
3590  }
3591 
3592  COMPARE_F(value, 15.99, 0);
3593  p_params->crfIpRatio = (float)atof(value);
3594  }
3596  {
3597  char *pTemp;
3598  pTemp = strchr(value, '.');
3599  if(pTemp != NULL)
3600  {
3601  if(strlen(pTemp) > 3)
3602  {
3603  ni_log(NI_LOG_ERROR, "ERROR: CRF pb ratio only supports two bit fraction\n" );
3605  }
3606  }
3607 
3608  COMPARE_F(value, 15.99, 0);
3609  p_params->crfPbRatio = (float)atof(value);
3610  }
3612  {
3613  CHECK2VAL(value, 0, 1)
3614  p_params->cbr = atoi(value);
3615  }
3617  {
3618  CHECK2VAL(value, 0, 1)
3619  p_params->cacheRoi = atoi(value);
3620  }
3622  {
3623  CHECK2VAL(value, 0, 1)
3624  p_params->ui32flushGop = atoi(value);
3625  }
3627  {
3629  p_params->ui32minIntraRefreshCycle = atoi(value);
3630  }
3632  {
3633  CHECK2VAL(value, 0, 1)
3634  p_enc->long_term_ref_enable = atoi(value);
3635  }
3637  {
3638  p_params->strict_timeout_mode = atoi(value);
3639  }
3641  {
3642  CHECK2VAL(value, 0, 1)
3643  p_enc->lossless_enable = atoi(value);
3644  }
3646  {
3647  COMPARE(value, 22, 0)
3648  p_params->color_primaries = atoi(value);
3649  }
3651  {
3652  COMPARE(value, 18, 0)
3653  p_params->color_transfer_characteristic = atoi(value);
3654  }
3656  {
3657  COMPARE(value, 14, 0)
3658  p_params->color_space = atoi(value);
3659  }
3661  {
3662  p_params->sar_num = atoi(value);
3663  }
3665  {
3666  p_params->sar_denom = atoi(value);
3667  }
3669  {
3670  p_params->video_full_range_flag = atoi(value);
3671  }
3673  {
3674  if (atoi(value) != 0 && atoi(value) != 1)
3675  {
3676  ni_log(NI_LOG_ERROR, "Invalid %s: out of range\n", name);
3678  }
3679  p_params->enable_vfr = atoi(value);
3680  }
3682  {
3683  if (atoi(value) != 0 && atoi(value) != 1)
3684  {
3685  ni_log(NI_LOG_ERROR, "Invalid %s: out of range\n", name);
3687  }
3688  p_params->enable_explicit_rpl = atoi(value);
3689  }
3691  {
3692  if (atoi(value) != 0 && atoi(value) != 1)
3693  {
3694  ni_log(NI_LOG_ERROR, "Invalid %s: out of range\n", name);
3696  }
3697  p_params->disable_timing_info = atoi(value);
3698  }
3700  {
3702  p_enc->set_high_priority = atoi(value);
3703  }
3705  {
3707  p_enc->keep_alive_timeout = atoi(value);
3708  }
3710  {
3711  CHECK2VAL(value, 0, 1)
3712  p_params->intra_refresh_reset = atoi(value);
3713  }
3715  {
3716  if (atoi(value) < -12 || atoi(value) > 12)
3717  {
3719  }
3720  p_params->chromaQpOffset = atoi(value);
3721  }
3722  else
3723  {
3724  ni_log(NI_LOG_ERROR, "Unknown option: %s.\n", name);
3726  }
3727 
3728 
3729 #undef OPT
3730 #undef atobool
3731 #undef atoi
3732 #undef atof
3733 
3734  b_error |= bValueWasNull && !bNameWasBool;
3735  if (b_error)
3736  {
3737  ni_log(NI_LOG_ERROR, "Invalid value for %s: %s.\n", name, value);
3739  }
3740 
3741  ni_log(NI_LOG_TRACE, "%s: exit, b_error=%d\n", __FUNCTION__, b_error);
3742 
3743  return NI_LOGAN_RETCODE_SUCCESS;
3744 }
3745 
3746 /*!*****************************************************************************
3747 * \brief Validate relationship of some params in encoder parameters structure
3748 *
3749 * \param[in] p_params Pointer to a user allocated ni_logan_encoder_params_t
3750 * \param[in] codec encoding codec
3751 *
3752 * \return On success
3753 * NI_LOGAN_RETCODE_SUCCESS
3754 * On failure
3755 * NI_LOGAN_RETCODE_FAILURE
3756 * NI_LOGAN_RETCODE_PARAM_ERROR_OOR and other error rc
3757 *******************************************************************************/
3760 {
3762 
3763  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
3764 
3765  if (p_enc->rc.min_qp > p_enc->rc.max_qp)
3766  {
3767  ni_log(NI_LOG_ERROR, "MinQP(%d) > MaxQP(%d)\n", p_enc->rc.min_qp,
3768  p_enc->rc.max_qp);
3770  }
3771 
3772  if (p_enc->lossless_enable)
3773  {
3774  if (NI_LOGAN_CODEC_FORMAT_H264 == codec)
3775  {
3776  ni_log(NI_LOG_ERROR, "losslessEnable is not valid for H.264\n");
3778  }
3779 
3780  if (p_enc->rc.enable_rate_control || p_enc->roi_enable)
3781  {
3782  ni_log(NI_LOG_ERROR, "losslessEnable can not be enabled if RcEnable "
3783  "or roiEnable is enabled\n");
3785  }
3786  }
3787 
3788  ni_log(NI_LOG_TRACE, "%s: exit\n", __FUNCTION__);
3789 
3790  return NI_LOGAN_RETCODE_SUCCESS;
3791 }
3792 
3793 
3794 
3795 #undef atoi
3796 #undef atof
3797 #define atoi(p_str) ni_logan_atoi(p_str, &b_error)
3798 #define atof(p_str) ni_logan_atof(p_str, &b_error)
3799 #define atobool(p_str) (ni_logan_atobool(p_str, &b_error))
3800 
3801 /*!******************************************************************************
3802  * \brief Set got parameter value referenced by name in encoder parameters structure
3803  *
3804  * \param[in] p_params Pointer to a user allocated ni_logan_encoder_params_t
3805  * to find and set a particular parameter
3806  * \param[in] name String represented parameter name to search
3807  * \param[in] value Parameter value to set
3808 *
3809  * \return On success
3810  * NI_LOGAN_RETCODE_SUCCESS
3811  * On failure
3812  * NI_LOGAN_RETCODE_FAILURE
3813  * NI_LOGAN_RETCODE_INVALID_PARAM
3814  *******************************************************************************/
3816  const char* name,
3817  const char* value)
3818 {
3819  bool b_error = false;
3820  bool bNameWasBool = false;
3821  bool bValueWasNull = !value;
3824  char nameBuf[64] = { 0 };
3825 
3826  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
3827 
3828  if (!p_params || !name)
3829  {
3830  ni_log(NI_LOG_ERROR, "Unknown option: %s.\n", name);
3831  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n",
3832  __FUNCTION__);
3834  }
3835 
3836  // skip -- prefix if provided
3837  if ((name[0] == '-') && (name[1] == '-'))
3838  {
3839  name += 2;
3840  }
3841 
3842  // s/_/-/g
3843  if (strlen(name) + 1 < sizeof(nameBuf) && strchr(name, '_'))
3844  {
3845  char* c;
3846  nameBuf[0] = '\0';
3847  strncat(nameBuf, name, strlen(name));
3848  while ((c = strchr(nameBuf, '_')) != 0)
3849  {
3850  *c = '-';
3851  }
3852 
3853  name = nameBuf;
3854  }
3855 
3856  if (!strncmp(name, "no-", 3))
3857  {
3858  name += 3;
3859  value = !value || ni_logan_atobool(value, &b_error) ? "false" : "true";
3860  }
3861  else if (!strncmp(name, "no", 2))
3862  {
3863  name += 2;
3864  value = !value || ni_logan_atobool(value, &b_error) ? "false" : "true";
3865  }
3866  else if (!value)
3867  {
3868  value = "true";
3869  }
3870  else if (value[0] == '=')
3871  {
3872  value++;
3873  }
3874 
3875 #ifdef _MSC_VER
3876 #define OPT(STR) else if (!_stricmp(name, STR))
3877 #else
3878 #define OPT(STR) else if (!strcasecmp(name, STR))
3879 #endif
3880  if (0)
3881  ;
3883  {
3884  if (atoi(value) > NI_LOGAN_MAX_GOP_SIZE)
3885  {
3886  ni_log(NI_LOG_ERROR, "Invalid custom GOP parameters: %s too big\n", name);
3888  }
3889  if (atoi(value) < NI_LOGAN_MIN_GOP_SIZE)
3890  {
3891  ni_log(NI_LOG_ERROR, "Invalid custom GOP parameters: %s too small\n", name);
3893  }
3894  p_gop->custom_gop_size = atoi(value);
3895  }
3896 
3898  {
3899  p_gop->pic_param[0].pic_type = atoi(value);
3900  }
3902  {
3903  p_gop->pic_param[0].poc_offset = atoi(value);
3904  }
3906  {
3908  p_gop->pic_param[0].pic_qp = atoi(value);
3909  }
3911  {
3912  p_gop->pic_param[0].num_ref_pic_L0 = atoi(value);
3913  }
3915  {
3916  p_gop->pic_param[0].ref_poc_L0 = atoi(value);
3917  }
3919  {
3920  p_gop->pic_param[0].ref_poc_L1 = atoi(value);
3921  }
3923  {
3924  p_gop->pic_param[0].temporal_id = atoi(value);
3925  }
3926 
3928  {
3929  p_gop->pic_param[1].pic_type = atoi(value);
3930  }
3932  {
3933  p_gop->pic_param[1].poc_offset = atoi(value);
3934  }
3936  {
3938  p_gop->pic_param[1].pic_qp = atoi(value);
3939  }
3941  {
3942  p_gop->pic_param[1].num_ref_pic_L0 = atoi(value);
3943  }
3945  {
3946  p_gop->pic_param[1].ref_poc_L0 = atoi(value);
3947  }
3949  {
3950  p_gop->pic_param[1].ref_poc_L1 = atoi(value);
3951  }
3953  {
3954  p_gop->pic_param[1].temporal_id = atoi(value);
3955  }
3956 
3958  {
3959  p_gop->pic_param[2].pic_type = atoi(value);
3960  }
3962  {
3963  p_gop->pic_param[2].poc_offset = atoi(value);
3964  }
3966  {
3968  p_gop->pic_param[2].pic_qp = atoi(value);
3969  }
3971  {
3972  p_gop->pic_param[2].num_ref_pic_L0 = atoi(value);
3973  }
3975  {
3976  p_gop->pic_param[2].ref_poc_L0 = atoi(value);
3977  }
3979  {
3980  p_gop->pic_param[2].ref_poc_L1 = atoi(value);
3981  }
3983  {
3984  p_gop->pic_param[2].temporal_id = atoi(value);
3985  }
3986 
3988  {
3989  p_gop->pic_param[3].pic_type = atoi(value);
3990  }
3992  {
3993  p_gop->pic_param[3].poc_offset = atoi(value);
3994  }
3996  {
3998  p_gop->pic_param[3].pic_qp = atoi(value);
3999  }
4001  {
4002  p_gop->pic_param[3].num_ref_pic_L0 = atoi(value);
4003  }
4005  {
4006  p_gop->pic_param[3].ref_poc_L0 = atoi(value);
4007  }
4009  {
4010  p_gop->pic_param[3].ref_poc_L1 = atoi(value);
4011  }
4013  {
4014  p_gop->pic_param[3].temporal_id = atoi(value);
4015  }
4016 
4018  {
4019  p_gop->pic_param[4].pic_type = atoi(value);
4020  }
4022  {
4023  p_gop->pic_param[4].poc_offset = atoi(value);
4024  }
4026  {
4028  p_gop->pic_param[4].pic_qp = atoi(value);
4029  }
4031  {
4032  p_gop->pic_param[4].num_ref_pic_L0 = atoi(value);
4033  }
4035  {
4036  p_gop->pic_param[4].ref_poc_L0 = atoi(value);
4037  }
4039  {
4040  p_gop->pic_param[4].ref_poc_L1 = atoi(value);
4041  }
4043  {
4044  p_gop->pic_param[4].temporal_id = atoi(value);
4045  }
4046 
4048  {
4049  p_gop->pic_param[5].pic_type = atoi(value);
4050  }
4052  {
4053  p_gop->pic_param[5].poc_offset = atoi(value);
4054  }
4056  {
4058  p_gop->pic_param[5].pic_qp = atoi(value);
4059  }
4061  {
4062  p_gop->pic_param[5].num_ref_pic_L0 = atoi(value);
4063  }
4065  {
4066  p_gop->pic_param[5].ref_poc_L0 = atoi(value);
4067  }
4069  {
4070  p_gop->pic_param[5].ref_poc_L1 = atoi(value);
4071  }
4073  {
4074  p_gop->pic_param[5].temporal_id = atoi(value);
4075  }
4076 
4078  {
4079  p_gop->pic_param[6].pic_type = atoi(value);
4080  }
4082  {
4083  p_gop->pic_param[6].poc_offset = atoi(value);
4084  }
4086  {
4088  p_gop->pic_param[6].pic_qp = atoi(value);
4089  }
4091  {
4092  p_gop->pic_param[6].num_ref_pic_L0 = atoi(value);
4093  }
4095  {
4096  p_gop->pic_param[6].ref_poc_L0 = atoi(value);
4097  }
4099  {
4100  p_gop->pic_param[6].ref_poc_L1 = atoi(value);
4101  }
4103  {
4104  p_gop->pic_param[6].temporal_id = atoi(value);
4105  }
4106 
4108  {
4109  p_gop->pic_param[7].pic_type = atoi(value);
4110  }
4112  {
4113  p_gop->pic_param[7].poc_offset = atoi(value);
4114  }
4116  {
4118  p_gop->pic_param[7].pic_qp = atoi(value);
4119  }
4121  {
4122  p_gop->pic_param[7].num_ref_pic_L0 = atoi(value);
4123  }
4125  {
4126  p_gop->pic_param[7].ref_poc_L0 = atoi(value);
4127  }
4129  {
4130  p_gop->pic_param[7].ref_poc_L1 = atoi(value);
4131  }
4133  {
4134  p_gop->pic_param[7].temporal_id = atoi(value);
4135  }
4136  else
4137  {
4138  ni_log(NI_LOG_ERROR, "Unknown option: %s.\n", name);
4139  ni_log(NI_LOG_TRACE, "%s(): Invalid parameter name passed\n", __FUNCTION__);
4141  }
4142 
4143 #undef OPT
4144 #undef atobool
4145 #undef atoi
4146 #undef atof
4147 
4148  b_error |= bValueWasNull && !bNameWasBool;
4149  if (b_error)
4150  {
4151  ni_log(NI_LOG_ERROR, "Invalid value for GOP param %s: %s.\n", name, value);
4153  }
4154 
4155  ni_log(NI_LOG_TRACE, "%s(): exit, b_error=%d\n", __FUNCTION__, b_error);
4156 
4157  return NI_LOGAN_RETCODE_SUCCESS;
4158 }
4159 
4160 /*!*****************************************************************************
4161  * \brief Get GOP's max number of reorder frames
4162  *
4163  * \param[in] p_params Pointer to a user allocated ni_logan_encoder_params_t
4164  *
4165  * \return max number of reorder frames of the GOP, -1 on error
4166  ******************************************************************************/
4168 {
4169  int gopPreset = p_params->enc_input_params.gop_preset_index;
4170  int reorder = 0;
4171  int i;
4172  ni_logan_encoder_input_params_t* p_enc = NULL;
4173 
4174  if (! p_params)
4175  {
4176  ni_log(NI_LOG_ERROR, "%s: NULL input!\n", __FUNCTION__);
4177  return -1;
4178  }
4179  p_enc = &p_params->enc_input_params;
4180 
4181  // low delay gopPreset (1, 2, 3, 6, 7, 9) has reorder of 0
4182  if (GOP_PRESET_IDX_ALL_I == gopPreset || GOP_PRESET_IDX_IPP == gopPreset ||
4183  GOP_PRESET_IDX_IBBB == gopPreset || GOP_PRESET_IDX_IPPPP == gopPreset ||
4184  GOP_PRESET_IDX_IBBBB == gopPreset || GOP_PRESET_IDX_SP == gopPreset)
4185  {
4186  reorder = 0;
4187  }
4188  else if (GOP_PRESET_IDX_IBPBP == gopPreset)
4189  {
4190  reorder = 1;
4191  }
4192  else if (GOP_PRESET_IDX_IBBBP == gopPreset)
4193  {
4194  reorder = 3;
4195  }
4196  else if (GOP_PRESET_IDX_RA_IB == gopPreset)
4197  {
4198  reorder = 7;
4199  }
4200  else if (GOP_PRESET_IDX_CUSTOM == gopPreset)
4201  {
4202  for (i = 0; i < p_enc->custom_gop_params.custom_gop_size; i++)
4203  {
4204  if (abs(p_enc->custom_gop_params.pic_param[i].poc_offset - i - 1) >
4205  reorder)
4206  {
4207  reorder = abs(p_enc->custom_gop_params.pic_param[i].poc_offset - i - 1);
4208  }
4209  }
4210  }
4211  else
4212  {
4213  ni_log(NI_LOG_ERROR, "%s: gopPresetIdx=%d not supported\n",
4214  __FUNCTION__, gopPreset);
4215  }
4216  return reorder;
4217 }
4218 
4219 /*!*****************************************************************************
4220  * \brief Get GOP's number of reference frames
4221  *
4222  * \param[in] p_params Pointer to a user allocated ni_logan_encoder_params_t
4223  *
4224  * \return number of reference frames of the GOP
4225  ******************************************************************************/
4227 {
4228  int gopPreset = p_params->enc_input_params.gop_preset_index;
4229  int ref_frames = 0;
4230  int i;
4231  ni_logan_encoder_input_params_t* p_enc = NULL;
4232 
4233  if (! p_params)
4234  {
4235  ni_log(NI_LOG_ERROR, "%s: NULL input!\n", __FUNCTION__);
4236  return -1;
4237  }
4238  p_enc = &p_params->enc_input_params;
4239 
4240  if (GOP_PRESET_IDX_ALL_I == gopPreset)
4241  {
4242  ref_frames = 0;
4243  }
4244  else if (gopPreset >= GOP_PRESET_IDX_IPP && gopPreset <= GOP_PRESET_IDX_RA_IB)
4245  {
4246  ref_frames = 2;
4247  }
4248  else if (GOP_PRESET_IDX_SP == gopPreset)
4249  {
4250  ref_frames = 1;
4251  }
4252  else if (GOP_PRESET_IDX_CUSTOM == gopPreset)
4253  {
4254  for (i = 0; i < p_enc->custom_gop_params.custom_gop_size; i++)
4255  {
4256  if (p_enc->custom_gop_params.pic_param[i].num_ref_pic_L0 > ref_frames)
4257  {
4258  ref_frames = p_enc->custom_gop_params.pic_param[i].num_ref_pic_L0;
4259  }
4260  }
4261  }
4262  else
4263  {
4264  ni_log(NI_LOG_ERROR, "%s: gopPresetIdx=%d not supported\n",
4265  __FUNCTION__, gopPreset);
4266  }
4267 
4268  return ref_frames;
4269 }
4270 
4271 /*!*****************************************************************************
4272  * \brief Add a new auxiliary data to a frame
4273  *
4274  * \param[in/out] frame a frame to which the auxiliary data should be added
4275  * \param[in] type type of the added auxiliary data
4276  * \param[in] data_size size of the added auxiliary data
4277  *
4278  * \return a pointer to the newly added aux data on success, NULL otherwise
4279  ******************************************************************************/
4281  ni_aux_data_type_t type,
4282  int data_size)
4283 {
4284  ni_aux_data_t *ret;
4285 
4287  ! (ret = malloc(sizeof(ni_aux_data_t))))
4288  {
4289  ni_log(NI_LOG_ERROR, "ni_logan_frame_new_aux_data No memory or exceeding max "
4290  "aux_data number !\n");
4291  return NULL;
4292  }
4293 
4294  ret->type = type;
4295  ret->size = data_size;
4296  ret->data = calloc(1, data_size);
4297  if (! ret->data)
4298  {
4299  ni_log(NI_LOG_ERROR, "ni_logan_frame_new_aux_data No memory for aux data !\n");
4300  free(ret);
4301  ret = NULL;
4302  }
4303  else
4304  {
4305  frame->aux_data[frame->nb_aux_data++] = ret;
4306  }
4307 
4308  return ret;
4309 }
4310 
4311 /*!*****************************************************************************
4312  * \brief Add a new auxiliary data to a frame and copy in the raw data
4313  *
4314  * \param[in/out] frame a frame to which the auxiliary data should be added
4315  * \param[in] type type of the added auxiliary data
4316  * \param[in] raw_data the raw data of the aux data
4317  * \param[in] data_size size of the added auxiliary data
4318  *
4319  * \return a pointer to the newly added aux data on success, NULL otherwise
4320  ******************************************************************************/
4322  ni_aux_data_type_t type,
4323  const uint8_t* raw_data,
4324  int data_size)
4325 {
4326  ni_aux_data_t *ret = ni_logan_frame_new_aux_data(frame, type, data_size);
4327  if (ret)
4328  {
4329  memcpy(ret->data, raw_data, data_size);
4330  }
4331  return ret;
4332 }
4333 
4334 /*!*****************************************************************************
4335  * \brief Retrieve from the frame auxiliary data of a given type if exists
4336  *
4337  * \param[in] frame a frame from which the auxiliary data should be retrieved
4338  * \param[in] type type of the auxiliary data to be retrieved
4339  *
4340  * \return a pointer to the aux data of a given type on success, NULL otherwise
4341  ******************************************************************************/
4343  ni_aux_data_type_t type)
4344 {
4345  int i;
4346  for (i = 0; i < frame->nb_aux_data; i++)
4347  {
4348  if (frame->aux_data[i]->type == type)
4349  {
4350  return frame->aux_data[i];
4351  }
4352  }
4353  return NULL;
4354 }
4355 
4356 /*!*****************************************************************************
4357  * \brief If auxiliary data of the given type exists in the frame, free it
4358  * and remove it from the frame.
4359  *
4360  * \param[in/out] frame a frame from which the auxiliary data should be removed
4361  * \param[in] type type of the auxiliary data to be removed
4362  *
4363  * \return None
4364  ******************************************************************************/
4366  ni_aux_data_type_t type)
4367 {
4368  int i;
4369  ni_aux_data_t *aux;
4370 
4371  for (i = 0; i < frame->nb_aux_data; i++)
4372  {
4373  aux = frame->aux_data[i];
4374  if (aux->type == type)
4375  {
4376  frame->aux_data[i] = frame->aux_data[frame->nb_aux_data - 1];
4377  frame->aux_data[frame->nb_aux_data - 1] = NULL;
4378  frame->nb_aux_data--;
4379 
4380  free(aux->data);
4381  free(aux);
4382  }
4383  }
4384 }
4385 
4386 /*!*****************************************************************************
4387  * \brief Free and remove all auxiliary data from the frame.
4388  *
4389  * \param[in/out] frame a frame from which the auxiliary data should be removed
4390  *
4391  * \return None
4392  ******************************************************************************/
4394 {
4395  int i;
4396  ni_aux_data_t *aux;
4397 
4398  for (i = 0; i < frame->nb_aux_data; i++)
4399  {
4400  aux = frame->aux_data[i];
4401  free(aux->data);
4402  free(aux);
4403  frame->aux_data[i] = NULL;
4404  }
4405  frame->nb_aux_data = 0;
4406 }
4407 
4408 /*!******************************************************************************
4409 * \brief Queries device Serial number
4410 *
4411 * \param[in] device_handle Device handle used to backtrace serial Num
4412 * \param[in] p_serial_num Pointer to a caller allocated ni_logan_serial_num_t struct
4413 * \return On success
4414 * NI_LOGAN_RETCODE_SUCCESS
4415 * On failure
4416 * NI_LOGAN_RETCODE_INVALID_PARAM
4417 * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
4418 * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
4419 *******************************************************************************/
4420 ni_logan_retcode_t ni_logan_device_handle_map_SN(ni_device_handle_t device_handle,
4421  ni_logan_serial_num_t *p_serial_num)
4422 {
4423  ni_logan_nvme_result_t nvme_result = 0;
4424  ni_logan_nvme_command_t cmd = { 0 };
4425  void * p_buffer = NULL;
4427  ni_event_handle_t event_handle = NI_INVALID_EVENT_HANDLE;
4428 
4429  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
4430 
4431  if (NI_INVALID_DEVICE_HANDLE == device_handle || !p_serial_num)
4432  {
4433  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
4435  LRETURN;
4436  }
4437 
4438  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), NI_LOGAN_NVME_IDENTITY_CMD_DATA_SZ))
4439  {
4440  ni_log(NI_LOG_ERROR, "ERROR: %s() Cannot allocate buffer.\n", __FUNCTION__);
4442  LRETURN;
4443  }
4444 
4445  memset(p_buffer, 0, NI_LOGAN_NVME_IDENTITY_CMD_DATA_SZ);
4446 
4447 #ifdef _WIN32
4448  event_handle = ni_logan_create_event();
4449  if (NI_INVALID_EVENT_HANDLE == event_handle)
4450  {
4452  LRETURN;
4453  }
4454 #endif
4455 
4456  uint32_t ui32LBA = IDENTIFY_DEVICE_R;
4457  if (ni_logan_nvme_send_read_cmd(device_handle, event_handle, p_buffer, NI_LOGAN_NVME_IDENTITY_CMD_DATA_SZ, ui32LBA) < 0)
4458  {
4460  LRETURN;
4461  }
4462 
4463  ni_logan_populate_serial_number(p_serial_num, p_buffer);
4464 
4465  END:
4466 
4467  ni_logan_aligned_free(p_buffer);
4468 
4469  ni_log(NI_LOG_TRACE, "%s(): retval: %d\n", __FUNCTION__, retval);
4470 
4471  return retval;
4472 }
4473 
4474 /*!******************************************************************************
4475 * \brief Copies existing decoding session params for hw frame usage
4476 *
4477 * \param[in] src_p_ctx Pointer to a caller allocated source
4478 * ni_logan_session_context_t struct
4479 * \param[in] dst_p_ctx Pointer to a caller allocated destination
4480 * ni_logan_session_context_t struct
4481 * \return On success
4482 * NI_LOGAN_RETCODE_SUCCESS
4483 * On failure
4484 * NI_LOGAN_RETCODE_INVALID_PARAM
4485 * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
4486 * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
4487 * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
4488 *******************************************************************************/
4490  ni_logan_session_context_t *dst_p_ctx)
4491 {
4492  ni_logan_retcode_t retval;
4493 
4494  ni_logan_pthread_mutex_lock(&src_p_ctx->mutex);
4495 
4496  // Hold the lock of decoding session context here.
4497  retval = ni_logan_decoder_session_copy_internal(src_p_ctx, dst_p_ctx);
4498 
4499  ni_logan_pthread_mutex_unlock(&src_p_ctx->mutex);
4500 
4501  return retval;
4502 }
4503 
4504 /*!******************************************************************************
4505 * \brief Reads data from the device
4506 * device_type should be NI_LOGAN_DEVICE_TYPE_DECODER,
4507 * and reads data hwdesc from decoder when hw transcoding
4508 *
4509 * \param[in] p_ctx Pointer to a caller allocated
4510 * ni_logan_session_context_t struct
4511 * \param[in] p_data Pointer to a caller allocated
4512 * ni_logan_session_data_io_t struct which contains either a
4513 * ni_logan_frame_t data frame or ni_logan_packet_t data packet to send
4514 * \return On success
4515 * Total number of bytes read
4516 * On failure
4517 * NI_LOGAN_RETCODE_INVALID_PARAM
4518 * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
4519 * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
4520 *******************************************************************************/
4523 {
4525  int seq_change_read_count = 0;
4526 
4527  if (!p_ctx || !p_data)
4528  {
4529  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
4531  }
4532 
4533  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
4534 
4535  for (; ;)
4536  {
4537  int aligned_width;
4538  //retval = ni_logan_decoder_session_read(p_ctx, &(p_data->data.frame));
4539  retval = ni_logan_decoder_session_read_desc(p_ctx, &(p_data->data.frame));
4540  // check resolution change only after initial setting obtained
4541  // p_data->data.frame.video_width is picture width and will be 32-align
4542  // adjusted to frame size; p_data->data.frame.video_height is the same as
4543  // frame size, then compare them to saved one for resolution checking
4544  //
4545  aligned_width = ((p_data->data.frame.video_width + 31) / 32) * 32;
4546  ni_log(NI_LOG_TRACE, "FNum %" PRIu64 ", DFVWxDFVH %u x %u, AlWid %d, "
4547  "AVW x AVH %u x %u\n ", p_ctx->frame_num,
4548  p_data->data.frame.video_width, p_data->data.frame.video_height,
4549  aligned_width, p_ctx->active_video_width, p_ctx->active_video_height);
4550 
4551  if (0 == retval && seq_change_read_count)
4552  {
4553  ni_log(NI_LOG_TRACE, "%s (decoder): seq change NO data, next time.\n",
4554  __FUNCTION__);
4555  p_ctx->active_video_width = 0;
4556  p_ctx->active_video_height = 0;
4557  p_ctx->active_bit_depth = 0;
4558  break;
4559  }
4560  else if (retval < 0)
4561  {
4562  ni_log(NI_LOG_ERROR, "%s (decoder): failure ret %d, return ..\n",
4563  __FUNCTION__, retval);
4564  break;
4565  }
4566  else if (p_ctx->frame_num && p_data->data.frame.video_width &&
4567  p_data->data.frame.video_height && p_data->data.frame.bit_depth &&
4568  (aligned_width != p_ctx->active_video_width ||
4569  p_data->data.frame.video_height != p_ctx->active_video_height ||
4570  p_data->data.frame.bit_depth != p_ctx->active_bit_depth))
4571  {
4572  ni_log(NI_LOG_TRACE, "%s (decoder): sequence change, frame size %ux%u %d"
4573  "bits -> %ux%u %dbits, continue read ...\n", __FUNCTION__,
4574  p_ctx->active_video_width, p_ctx->active_video_height,
4575  p_ctx->active_bit_depth, p_data->data.frame.video_width,
4576  p_data->data.frame.video_height, p_data->data.frame.bit_depth);
4577  // reset active video resolution to 0 so it can be queried in the re-read
4578  p_ctx->active_video_width = 0;
4579  p_ctx->active_video_height = 0;
4580  p_ctx->active_bit_depth = 0;
4581  seq_change_read_count++;
4582  }
4583  else
4584  {
4585  break;
4586  }
4587  }
4588 
4589  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
4590 
4591  return retval;
4592 }
4593 
4594 /*!******************************************************************************
4595 * \brief Reads data from hw descriptor from decoder output buffer
4596 *
4597 * \param[in] p_data Pointer to a caller allocated
4598 * ni_logan_session_data_io_t struct which contains either a
4599 * ni_logan_frame_t data frame or ni_logan_packet_t data packet to send
4600 * \param[in] hwdesc HW descriptor to find frame in XCODER
4601 * \return On success
4602 * Total number of bytes read
4603 * On failure
4604 * NI_LOGAN_RETCODE_INVALID_PARAM
4605 * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
4606 * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
4607 *******************************************************************************/
4611 {
4613 
4614  if (!hwdesc || !p_data)
4615  {
4616  ni_log(NI_LOG_ERROR, "%s(): Error passed parameters are null!, return\n",
4617  __FUNCTION__);
4619  }
4620 
4621  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
4622 
4623  p_ctx->session_id = hwdesc->ui16SessionID;
4624 
4625 #ifdef _WIN32
4626  int64_t handle = (((int64_t) hwdesc->device_handle_ext) << 32) | hwdesc->device_handle;
4627  p_ctx->blk_io_handle = (ni_device_handle_t) handle;
4628 #else
4629  p_ctx->blk_io_handle = (ni_device_handle_t) hwdesc->device_handle;
4630 #endif
4631 
4632  p_ctx->codec_format = hwdesc->encoding_type; //unused
4633 
4634  p_ctx->bit_depth_factor = hwdesc->bit_depth;
4636 
4637  ni_log(NI_LOG_TRACE, "%s(): bit_depth_factor %u\n",
4638  __FUNCTION__, p_ctx->bit_depth_factor);
4639 
4640  retval = ni_logan_hwdownload_session_read(p_ctx, &(p_data->data.frame), hwdesc); //cut me down as needed
4641 
4642  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
4643 
4644  return retval;
4645 }
4646 
4647 /*!******************************************************************************
4648 * \brief Writes data and reads back hw descriptor from decoder output buffer
4649 *
4650 * \param[in] p_src_data Pointer to a caller allocated
4651 * ni_logan_session_data_io_t struct which contains either a
4652 * ni_logan_frame_t data frame or ni_logan_packet_t data packet to send
4653 * \param[in] hwdesc HW descriptor to find frame in XCODER
4654 * \return On success
4655 * Total number of bytes read
4656 * On failure
4657 * NI_LOGAN_RETCODE_INVALID_PARAM
4658 * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
4659 * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
4660 *******************************************************************************/
4662  ni_logan_session_data_io_t *p_src_data,
4664 {
4665  unsigned int hwaddress = 0;
4667  if (!hwdesc || !p_src_data)
4668  {
4669  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
4671  }
4672 
4673  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
4674 
4675  retval = ni_logan_hwupload_session_write(p_ctx, &p_src_data->data.frame);
4676  if (retval <= 0)
4677  {
4678  return retval;
4679  }
4680  retval = ni_logan_hwupload_session_read_hwdesc(p_ctx, hwdesc, &hwaddress);
4681 
4682  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
4683 
4684  return retval;
4685 }
4686 
4687 
4688 /*!*****************************************************************************
4689 * \brief Allocate memory for the frame buffer based on provided parameters
4690 * taking into account pic line size and extra data.
4691 * Applicable to YUV420p AVFrame for hw only.
4692 *
4693 * \param[in] p_frame Pointer to a caller allocated ni_logan_frame_t struct
4694 *
4695 * \param[in] video_width Width of the video frame
4696 * \param[in] video_height Height of the video frame
4697 * \param[in] linesize Picture line size
4698 * \param[in] alignment Allignment requirement
4699 * \param[in] extra_len Extra data size (incl. meta data)
4700 *
4701 * \return On success
4702 * NI_LOGAN_RETCODE_SUCCESS
4703 * On failure
4704 * NI_LOGAN_RETCODE_INVALID_PARAM
4705 * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
4706 *****************************************************************************/
4708  int video_width,
4709  int video_height,
4710  int extra_len)
4711 {
4712  void* p_buffer = NULL;
4713  int height_aligned = video_height;
4714  int retval = NI_LOGAN_RETCODE_SUCCESS;
4715 
4716  if (!p_frame)
4717  {
4718  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
4720  }
4721 
4722  ni_log(NI_LOG_TRACE, "%s: extra_len=%d\n", __FUNCTION__, extra_len);
4723 
4724  int luma_size = 0;//linesize[0] * height_aligned;
4725  int chroma_b_size = 0;//luma_size / 4;
4726  int chroma_r_size = 0;//luma_size / 4;
4727  int buffer_size = sizeof(ni_logan_hwframe_surface_t) + extra_len;
4728 
4730 
4731  //Check if Need to free
4732  if ((p_frame->buffer_size != buffer_size) && (p_frame->buffer_size > 0))
4733  {
4734  ni_log(NI_LOG_TRACE, "%s: free current p_frame p_frame->buffer_size=%d\n",
4735  __FUNCTION__, p_frame->buffer_size);
4736  ni_logan_frame_buffer_free(p_frame);
4737  }
4738 
4739  //Check if need to realocate
4740  if (p_frame->buffer_size != buffer_size)
4741  {
4742 #ifndef XCODER_SIM_ENABLED
4743  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size))
4744  {
4745  ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate p_frame buffer.\n");
4747  LRETURN;
4748  }
4749 #else
4750  p_buffer = malloc(buffer_size);
4751  if (!p_buffer)
4752  {
4753  ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate p_frame buffer.\n");
4755  LRETURN;
4756  }
4757 #endif
4758  // init once after allocation
4759  memset(p_buffer, 0, buffer_size);
4760  p_frame->buffer_size = buffer_size;
4761  p_frame->p_buffer = p_buffer;
4762  ni_log(NI_LOG_TRACE, "%s: allocated new p_frame buffer\n", __FUNCTION__);
4763  }
4764  else
4765  {
4766  ni_log(NI_LOG_TRACE, "%s: reuse p_frame buffer\n", __FUNCTION__);
4767  }
4768 
4769  p_frame->p_data[3] = (uint8_t*)p_frame->p_buffer;
4770  p_frame->p_data[0] = NULL;
4771  p_frame->p_data[1] = NULL;
4772  p_frame->p_data[2] = NULL;
4773 
4774  p_frame->data_len[0] = 0;//luma_size;
4775  p_frame->data_len[1] = 0;//chroma_b_size;
4776  p_frame->data_len[2] = 0;//chroma_r_size;
4777  p_frame->data_len[3] = sizeof(ni_logan_hwframe_surface_t);
4778 
4779  p_frame->video_width = video_width;
4780  p_frame->video_height = height_aligned;
4781 
4782  ni_log(NI_LOG_TRACE, "%s: success: p_frame->buffer_size=%d\n",
4783  __FUNCTION__, p_frame->buffer_size);
4784 
4785  END:
4786 
4787  if (NI_LOGAN_RETCODE_SUCCESS != retval)
4788  {
4789  ni_logan_aligned_free(p_buffer);
4790  }
4791 
4792  return retval;
4793 }
4794 
4795 #ifndef _WIN32
4796 /*!*****************************************************************************
4797  * \brief Calculate the total size of a frame based on the upload
4798  * context attributes and includes rounding up to the page size
4799  *
4800  * \param[in] p_upl_ctx pointer to an uploader session context
4801  * \param[in] linesize array of line stride
4802  *
4803  * \return size
4804  * NI_RETCODE_INVALID_PARAM
4805  *
4806  ******************************************************************************/
4808  const int linesize[], const int heightsize[])
4809 {
4810  int pixel_format;
4811  int width, height;
4812  int luma, chroma_b, chroma_r;
4813  int total;
4814 
4815  pixel_format = p_upl_ctx->pixel_format;
4816  width = p_upl_ctx->active_video_width;
4817  height = p_upl_ctx->active_video_height;
4818 
4819  switch (pixel_format)
4820  {
4823  if (width < 0 || width > NI_LOGAN_MAX_RESOLUTION_WIDTH)
4824  {
4826  }
4827 
4828  if ((height < 0) || (height > NI_LOGAN_MAX_RESOLUTION_HEIGHT))
4829  {
4831  }
4832  break;
4833 
4834  default:
4836  }
4837 
4838  switch (pixel_format)
4839  {
4842  luma = linesize[0] * heightsize[0];
4843  chroma_b = linesize[1] * heightsize[1];
4844  chroma_r = linesize[2] * heightsize[2];
4845  total =
4846  luma + chroma_b + chroma_r + NI_LOGAN_APP_ENC_FRAME_META_DATA_SIZE;
4847  break;
4848 
4849  default:
4851  break;
4852  }
4853 
4854  total = NI_LOGAN_VPU_CEIL(total, 0x1000);
4855 
4856  return total;
4857 }
4858 
4859 /*!*****************************************************************************
4860 * \brief Acquire a P2P frame buffer from the hwupload session
4861 *
4862 * \param[in] p_ctx Pointer to a caller allocated
4863 * ni_session_context_t struct
4864 * \param[out] p_frame Pointer to a caller allocated hw frame
4865 *
4866 * \return On success
4867 * NI_RETCODE_SUCCESS
4868 * On failure
4869 * NI_RETCODE_INVALID_PARAM
4870 * NI_RETCODE_ERROR_NVME_CMD_FAILED
4871 * NI_RETCODE_ERROR_INVALID_SESSION
4872 *******************************************************************************/
4874 {
4877  unsigned int offset;
4878  unsigned int hwaddress = 0;
4879  int ret;
4880  int linestride[NI_LOGAN_MAX_NUM_DATA_POINTERS];
4881  int alignedheight[NI_LOGAN_MAX_NUM_DATA_POINTERS];
4882  ni_logan_hwframe_surface_t hwdesc = {0};
4883  ni_logan_hwframe_surface_t *p_surface;
4884 
4885  if (p_ctx == NULL || p_frame == NULL || p_frame->p_data[3] == NULL)
4886  {
4887  ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n",
4888  __func__);
4890  }
4891 
4892  p_surface = (ni_logan_hwframe_surface_t *)p_frame->p_data[3];
4893 
4894  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
4895 
4896  retval = ni_logan_hwupload_session_read_hwdesc(p_ctx, &hwdesc, &hwaddress);
4897 
4898  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
4899 
4900  if (retval != NI_LOGAN_RETCODE_SUCCESS)
4901  {
4902  ni_log(NI_LOG_ERROR, "ERROR: hwdesc read failure %d\n", retval);
4903  return retval;
4904  }
4905 
4906  retval = ni_logan_get_memory_offset(p_ctx, &hwdesc, &offset, hwaddress);
4907  if (retval != NI_LOGAN_RETCODE_SUCCESS)
4908  {
4909  ni_log(NI_LOG_ERROR, "ERROR: bad buffer id\n");
4911  }
4912 
4914  p_ctx->bit_depth_factor, 1, linestride,
4915  alignedheight);
4916 
4917  uexp.fd = -1;
4918  uexp.flags = 0;
4919  uexp.offset = offset;
4920 
4921  uexp.length = ni_logan_calculate_total_frame_size(p_ctx, linestride, alignedheight);
4922  uexp.domain = p_ctx->domain;
4923  uexp.bus = p_ctx->bus;
4924  uexp.dev = p_ctx->dev;
4925  uexp.fn = p_ctx->fn;
4926  uexp.bar = 4; // PCI BAR4 configuration space
4927 
4928  ret = ioctl(p_ctx->netint_fd, NETINT_LOGAN_IOCTL_EXPORT_DMABUF, &uexp);
4929  if (ret < 0)
4930  {
4931  ni_log(NI_LOG_ERROR, "%s: Failed to export dmabuf %d errno %d, offset %x, length %d\n",
4932  __func__, ret, NI_ERRNO, uexp.offset, uexp.length);
4933  return NI_LOGAN_RETCODE_FAILURE;
4934  }
4935 
4936  *p_surface = hwdesc;
4937  p_surface->ui16width = p_ctx->active_video_width;
4938  p_surface->ui16height = p_ctx->active_video_height;
4939  //p_surface->ui32nodeAddress = 0; // unused field
4940  p_surface->encoding_type = (int8_t)p_ctx->codec_format;;
4941  p_surface->dma_buf_fd = uexp.fd;
4942 
4943  return retval;
4944 }
4945 
4946 /*!*****************************************************************************
4947  * \brief Lock a hardware P2P frame prior to encoding
4948  *
4949  * \param[in] p_upl_ctx pointer to caller allocated upload context
4950  * [in] p_frame pointer to caller allocated hardware P2P frame
4951  *
4952  * \return On success
4953  * NI_RETCODE_SUCCESS
4954  * On failure NI_RETCODE_FAILURE
4955  * NI_RETCODE_INVALID_PARAM
4956 *******************************************************************************/
4958  ni_logan_frame_t *p_frame)
4959 {
4960  int ret;
4961  struct netint_logan_iocmd_attach_rfence uatch = {0};
4962  struct pollfd pfds[1] = {0};
4963  ni_logan_hwframe_surface_t *p_surface;
4964 
4965  if (p_upl_ctx == NULL || p_frame == NULL)
4966  {
4967  ni_log(NI_LOG_ERROR, "%s: bad parameters\n", __func__);
4969  }
4970 
4971  if (p_frame->p_data[3] == NULL)
4972  {
4973  ni_log(NI_LOG_ERROR, "%s: not a hardware frame\n", __func__);
4975  }
4976 
4977  p_surface = (ni_logan_hwframe_surface_t *)p_frame->p_data[3];
4978 
4979  pfds[0].fd = p_surface->dma_buf_fd;
4980  pfds[0].events = POLLIN;
4981  pfds[0].revents = 0;
4982 
4983  ret = poll(pfds, 1, -1);
4984  if (ret < 0)
4985  {
4986  ni_log(NI_LOG_ERROR, "%s:failed to poll dmabuf fd errno %d\n", __func__,
4987  NI_ERRNO);
4988  return ret;
4989  }
4990 
4991  uatch.fd = p_surface->dma_buf_fd;
4992  ret = ioctl(p_upl_ctx->netint_fd, NETINT_LOGAN_IOCTL_ATTACH_RFENCE, &uatch);
4993  if (ret < 0)
4994  {
4996  "%s: failed to attach dmabuf read fence errno %d\n", __func__,
4997  NI_ERRNO);
4998  return ret;
4999  }
5000 
5001  return NI_LOGAN_RETCODE_SUCCESS;
5002 }
5003 
5004 /*!*****************************************************************************
5005 * \brief Unlock a hardware P2P frame after encoding
5006 *
5007 * \param[in] p_upl_ctx pointer to caller allocated upload context
5008 * [in] p_frame pointer to caller allocated hardware P2P frame
5009 *
5010 * \return On success
5011 * NI_RETCODE_SUCCESS
5012 * On failure NI_RETCODE_FAILURE
5013 * NI_RETCODE_INVALID_PARAM
5014 *******************************************************************************/
5016  ni_logan_frame_t *p_frame)
5017 {
5018  int ret;
5019  struct netint_logan_iocmd_signal_rfence usigl = {0};
5020  ni_logan_hwframe_surface_t *p_surface;
5021 
5022  if ((p_upl_ctx == NULL) || (p_frame == NULL))
5023  {
5024  ni_log(NI_LOG_ERROR, "%s: Invalid parameters %p %p\n", __func__,
5025  p_upl_ctx, p_frame);
5027  }
5028 
5029  p_surface = (ni_logan_hwframe_surface_t *)p_frame->p_data[3];
5030 
5031  if (p_surface == NULL)
5032  {
5033  ni_log(NI_LOG_ERROR, "%s: Invalid hw frame\n", __func__);
5035  }
5036 
5037  usigl.fd = p_surface->dma_buf_fd;
5038  ret = ioctl(p_upl_ctx->netint_fd, NETINT_LOGAN_IOCTL_SIGNAL_RFENCE, &usigl);
5039  if (ret < 0)
5040  {
5041  ni_log(NI_LOG_ERROR, "Failed to signal dmabuf read fence\n");
5042  return NI_LOGAN_RETCODE_FAILURE;
5043  }
5044 
5045  return NI_LOGAN_RETCODE_SUCCESS;
5046 }
5047 
5048 /*!*****************************************************************************
5049  * \brief Special P2P test API function. Copies YUV data from the software
5050  * frame to the hardware P2P frame on the T408 device
5051  *
5052  * \param[in] p_upl_ctx pointer to caller allocated uploader session
5053  * context
5054  * [in] p_swframe pointer to a caller allocated software frame
5055  * [in] p_hwframe pointer to a caller allocated hardware frame
5056  *
5057  * \return On success
5058  * NI_RETCODE_SUCCESS
5059  * On failure
5060  * NI_RETCODE_FAILURE
5061  * NI_RETCODE_INVALID_PARAM
5062 *******************************************************************************/
5064  uint8_t *p_data, uint32_t len,
5065  ni_logan_frame_t *p_hwframe)
5066 {
5067  int ret;
5068  struct netint_logan_iocmd_issue_request uis = {0};
5069  ni_logan_hwframe_surface_t *p_surface;
5070 
5071  if (p_upl_ctx == NULL || p_data == NULL || p_hwframe == NULL)
5072  {
5073  ni_log(NI_LOG_ERROR, "%s: invalid null parameters\n", __func__);
5075  }
5076 
5077  if (p_hwframe->p_data[3] == NULL)
5078  {
5079  ni_log(NI_LOG_ERROR, "%s: empty frame\n", __func__);
5081  }
5082 
5083  p_surface = (ni_logan_hwframe_surface_t *)p_hwframe->p_data[3];
5084 
5085  uis.fd = p_surface->dma_buf_fd;
5086  uis.data = p_data;
5087  uis.len = len;
5089 
5090  ret = ioctl(p_upl_ctx->netint_fd, NETINT_LOGAN_IOCTL_ISSUE_REQ, &uis);
5091  if (ret < 0)
5092  {
5094  "%s: Failed to request dmabuf rendering errno %d\n", __func__,
5095  NI_ERRNO);
5096  return NI_LOGAN_RETCODE_FAILURE;
5097  }
5098 
5099  return NI_LOGAN_RETCODE_SUCCESS;
5100 }
5101 
5102 #endif
5103 
5104 /*!*****************************************************************************
5105  * \brief Set the incoming frame format for the encoder
5106  *
5107  * \param[in] p_enc_ctx pointer to encoder context
5108  * [in] p_enc_params pointer to encoder parameters
5109  * [in] width input width
5110  * [in] height input height
5111  * [in] bit_depth 8 for 8-bit YUV, 10 for 10-bit YUV
5112  * [in] src_endian NI_FRAME_LITTLE_ENDIAN or NI_FRAME_BIG_ENDIAN
5113  *
5114  * \return on success
5115  * NI_RETCODE_SUCCESS
5116  *
5117  * on failure
5118  * NI_RETCODE_INVALID_PARAM
5119 *******************************************************************************/
5121  ni_logan_session_context_t *p_enc_ctx, ni_logan_encoder_params_t *p_enc_params,
5122  int width, int height, int bit_depth, int src_endian)
5123 {
5124  int alignedw;
5125  int alignedh;
5126 
5127  if (p_enc_ctx == NULL || p_enc_params == NULL)
5128  {
5129  ni_log(NI_LOG_ERROR, "%s: null ptr\n", __func__);
5131  }
5132 
5133  if (!(bit_depth == 8) && !(bit_depth == 10))
5134  {
5135  ni_log(NI_LOG_ERROR, "%s: bad bit depth %d\n", __func__, bit_depth);
5137  }
5138 
5139  if (!(src_endian == NI_LOGAN_FRAME_LITTLE_ENDIAN) &&
5140  !(src_endian == NI_LOGAN_FRAME_BIG_ENDIAN))
5141  {
5142  ni_log(NI_LOG_ERROR, "%s: bad endian %d\n", __func__, src_endian);
5144  }
5145 
5146  p_enc_ctx->src_bit_depth = bit_depth;
5147  p_enc_ctx->bit_depth_factor = (bit_depth == 8) ? 1 : 2;
5148  p_enc_ctx->src_endian = src_endian;
5149 
5150  alignedw = width;
5151 
5152  if (alignedw < NI_LOGAN_MIN_WIDTH)
5153  {
5154  p_enc_params->enc_input_params.conf_win_right +=
5155  (NI_LOGAN_MIN_WIDTH - width) / 2 * 2;
5156  alignedw = NI_LOGAN_MIN_WIDTH;
5157  } else
5158  {
5159  alignedw = ((width + 1) / 2) * 2;
5160  p_enc_params->enc_input_params.conf_win_right +=
5161  (alignedw - width) / 2 * 2;
5162  }
5163 
5164  p_enc_params->source_width = alignedw;
5165  alignedh = height;
5166 
5167  if (alignedh < NI_LOGAN_MIN_HEIGHT)
5168  {
5169  p_enc_params->enc_input_params.conf_win_bottom +=
5170  (NI_LOGAN_MIN_HEIGHT - height) / 2 * 2;
5171  alignedh = NI_LOGAN_MIN_HEIGHT;
5172  } else
5173  {
5174  alignedh = ((height + 1) / 2) * 2;
5175  p_enc_params->enc_input_params.conf_win_bottom +=
5176  (alignedh - height) / 2 * 2;
5177  }
5178 
5179  p_enc_params->source_height = alignedh;
5180 
5181  return NI_LOGAN_RETCODE_SUCCESS;
5182 }
5183 
5184 
5185 /*!******************************************************************************
5186 * \brief Recycle a frame buffer on card
5187 *
5188 * \param[in] surface Stuct containing device and frame location to clear out
5189 *
5190 * \return On success NI_LOGAN_RETCODE_SUCCESS
5191 * On failure NI_LOGAN_RETCODE_INVALID_PARAM
5192 *******************************************************************************/
5194  ni_device_handle_t device_handle,
5195  ni_event_handle_t event_handle)
5196 {
5198  if (surface)
5199  {
5200  if (surface->seq_change)
5201  {
5202  // clear meta buffer index when sequence change happened
5203  ni_logan_hwframe_surface_t surface_meta = {0};
5204  surface_meta.ui16SessionID = surface->ui16SessionID;
5206  surface_meta.i8InstID = surface->i8InstID;
5207  ni_log(NI_LOG_TRACE, "%s(): clear meta buffer\n", __FUNCTION__);
5208  retval = ni_logan_clear_instance_buf(&surface_meta, device_handle, event_handle);
5209  }
5210  ni_log(NI_LOG_TRACE, "%s(): Start cleaning out buffer\n", __FUNCTION__);
5211  ni_log(NI_LOG_TRACE, "%s(): ui16FrameIdx=%d sessionId=%d device_handle=0x%x\n",
5212  __FUNCTION__, surface->i8FrameIdx, surface->ui16SessionID, device_handle);
5213  retval = ni_logan_clear_instance_buf(surface, device_handle, event_handle);
5214  }
5215  else
5216  {
5217  ni_log(NI_LOG_TRACE, "%s(): Surface is empty\n", __FUNCTION__);
5218  }
5219  return retval;
5220 }
5221 
5222 /*!******************************************************************************
5223 * \brief Sends frame pool setup info to device
5224 *
5225 * \param[in] p_ctx Pointer to a caller allocated
5226 * ni_logan_session_context_t struct
5227 * \param[in] p_data Pointer to a caller allocated
5228 * ni_logan_session_data_io_t struct which contains either a
5229 * ni_logan_frame_t data frame or ni_logan_packet_t data packet to send
5230 * \return On success Return code
5231 * On failure
5232 * NI_LOGAN_RETCODE_INVALID_PARAM
5233 * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
5234 * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
5235 *******************************************************************************/
5237  uint32_t pool_size, uint32_t p2p_pool)
5238 {
5240 
5241  if (!p_ctx)
5242  {
5243  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
5245  }
5246 
5247  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
5248 
5249  retval = ni_logan_hwupload_init_framepool(p_ctx, pool_size, p2p_pool);
5250 
5251  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
5252 
5253  return retval;
5254 }
5255 
5256 /*!******************************************************************************
5257  * \brief Allocate memory for the frame buffer based on provided parameters
5258  * taking into account width, height, format, stride, alignment, and
5259  * extra data
5260  *
5261  * \param[in] p_frame Pointer to caller allocated ni_logan_frame_t
5262  * \param[in] pixel_format pixel format
5263  * \param[in] video_width width, in pixels
5264  * \param[in] video_height height, in pixels
5265  * \param[in] linesize horizontal stride
5266  * \param[in] alignment apply a 16 pixel height alignment (T408 only)
5267  * \param[in] extra_len meta data size
5268  *
5269  * \return NI_LOGAN_RETCODE_SUCCESS
5270  * NI_LOGAN_RETCODE_INVALID_PARAM
5271  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
5272  *
5273  *******************************************************************************/
5275  int video_width, int video_height,
5276  int linesize[], int alignment, int extra_len)
5277 {
5278  int buffer_size;
5279  void *p_buffer = NULL;
5280  int retval = NI_LOGAN_RETCODE_SUCCESS;
5281  int height_aligned;
5282  int luma_size, chroma_b_size, chroma_r_size;
5283 
5284  if (!p_frame)
5285  {
5286  ni_log(NI_LOG_ERROR, "Invalid frame pointer\n");
5288  }
5289 
5290  switch (pixel_format)
5291  {
5296  /*
5297  * The encoder will pad a small frame up to 256x128 before encoding
5298  * and set the cropping value in the packet header to the original
5299  * dimension.
5300  */
5301  if ((video_width < 0) || (video_width > NI_LOGAN_MAX_RESOLUTION_WIDTH))
5302  {
5303  ni_log(NI_LOG_ERROR, "Video resolution width %d out of range\n", video_width);
5305  }
5306 
5307  if ((video_height < 0) || (video_height > NI_LOGAN_MAX_RESOLUTION_HEIGHT))
5308  {
5309  ni_log(NI_LOG_ERROR, "Video resolution height %d out of range\n", video_width);
5311  }
5312  break;
5313  default:
5314  ni_log(NI_LOG_ERROR, "Unknown pixel format %d\n", pixel_format);
5316  }
5317 
5318  height_aligned = NI_LOGAN_VPU_ALIGN8(video_height);
5319 
5320  if (alignment)
5321  {
5322  /* 16-pixel aligned pixel height for Quadra */
5323  height_aligned = NI_LOGAN_VPU_ALIGN16(video_height);
5324  }
5325 
5326  /* Round up to the minimum 256 pixel height if necessary */
5327  height_aligned = height_aligned > NI_LOGAN_MIN_HEIGHT? height_aligned : NI_LOGAN_MIN_HEIGHT;
5328 
5329  switch (pixel_format)
5330  {
5335  luma_size = linesize[0] * height_aligned;
5336  chroma_b_size = luma_size / 4;
5337  chroma_r_size = luma_size / 4;
5338 
5339  buffer_size = luma_size + chroma_b_size + chroma_r_size + extra_len;
5340  break;
5341  default:
5342  ni_log(NI_LOG_ERROR, "Error: unsupported pixel format %d\n", pixel_format);
5344  }
5345 
5346  /* Allocate a buffer size that is page aligned for the host */
5348 
5349  /* If this buffer has a different size, realloc a new buffer */
5350  if ((p_frame->buffer_size > 0) && (p_frame->buffer_size != buffer_size))
5351  {
5352  ni_log(NI_LOG_TRACE, "Free current p_frame, p_frame->buffer_size %d\n",
5353  p_frame->buffer_size);
5354  ni_logan_frame_buffer_free(p_frame);
5355  }
5356 
5357  if (p_frame->buffer_size != buffer_size)
5358  {
5359  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size))
5360  {
5361  ni_log(NI_LOG_ERROR, "Error: Cannot allocate p_frame\n");
5363  LRETURN;
5364  }
5365 
5366  memset(p_buffer, 0, buffer_size);
5367  p_frame->buffer_size = buffer_size;
5368  p_frame->p_buffer = p_buffer;
5369  ni_log(NI_LOG_TRACE, "%s: allocated new p_frame buffer\n", __FUNCTION__);
5370  }
5371  else
5372  {
5373  ni_log(NI_LOG_TRACE, "%s: reuse p_frame buffer\n", __FUNCTION__);
5374  }
5375 
5376  switch (pixel_format)
5377  {
5382  p_frame->p_data[0] = (uint8_t*) p_frame->p_buffer;
5383  p_frame->p_data[1] = (uint8_t*) p_frame->p_data[0] + luma_size;
5384  p_frame->p_data[2] = (uint8_t*) p_frame->p_data[1] + chroma_b_size;
5385  p_frame->p_data[3] = NULL;
5386 
5387  p_frame->data_len[0] = luma_size;
5388  p_frame->data_len[1] = chroma_b_size;
5389  p_frame->data_len[2] = chroma_r_size;
5390  p_frame->data_len[3] = 0;
5391  break;
5392  /* fall through */
5393  default:
5394  ni_log(NI_LOG_ERROR, "Error: unsupported pixel format %d\n",pixel_format);
5396  LRETURN;
5397  }
5398 
5399  p_frame->video_width = video_width;
5400  p_frame->video_height = height_aligned;
5401 
5402  ni_log(NI_LOG_TRACE, "%s success: w=%d; h=%d; aligned buffer size=%d\n",
5403  __FUNCTION__, video_width, video_height, buffer_size);
5404 
5405  END:
5406 
5407  if (retval != NI_LOGAN_RETCODE_SUCCESS)
5408  {
5409  ni_logan_aligned_free(p_buffer);
5410  }
5411 
5412  return retval;
5413 }
5414 
5415 /*!*****************************************************************************
5416 * \brief Allocate memory for the frame buffer based on provided parameters
5417 * Applicable to use YUV420p AVFrame for zerocopy case.
5418 * Allocat extra_len only.
5419 *
5420 * \param[in] p_frame Pointer to a caller allocated ni_logan_frame_t struct
5421 *
5422 * \param[in] video_width Width of the video frame
5423 * \param[in] video_height Height of the video frame
5424 * \param[in] linesize Picture line size
5425 * \param[in] extra_len Extra data size (incl. meta data)
5426 * \param[in] buffer[] Buffer address of video frame.
5427 *
5428 * \return On success
5429 * NI_LOGAN_RETCODE_SUCCESS
5430 * On failure
5431 * NI_LOGAN_RETCODE_INVALID_PARAM
5432 * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
5433 *****************************************************************************/
5435  int video_width,
5436  int video_height,
5437  int linesize[],
5438  int extra_len,
5439  int factor,
5440  uint8_t* buffer[])
5441 {
5442  void* p_buffer = NULL;
5443  int retval = NI_LOGAN_RETCODE_SUCCESS;
5444 
5445  if (!p_frame || !linesize || linesize[0] <= 0 ||
5446  linesize[0] > NI_LOGAN_MAX_RESOLUTION_WIDTH * factor ||
5447  video_width > NI_LOGAN_MAX_RESOLUTION_WIDTH || video_width <= 0 ||
5448  video_height > NI_LOGAN_MAX_RESOLUTION_HEIGHT || video_height % 16 != 0 || video_height < NI_LOGAN_MIN_HEIGHT ||
5449  !buffer[0] || !buffer[1] || !buffer[2])
5450  {
5451  ni_log(NI_LOG_TRACE, "ERROR: %s passed parameters are null!, return\n",
5452  __FUNCTION__);
5454  }
5455 
5456  ni_log(NI_LOG_TRACE, "%s: orig=%dx%d linesize=%d/%d/%d "
5457  "extra_len=%d\n", __FUNCTION__, video_width, video_height,
5458  linesize[0], linesize[1], linesize[2],
5459  extra_len);
5460 
5461  int buffer_size = extra_len;//only allocate extra_len.
5463 
5464  //Check if Need to free
5465  if ((p_frame->buffer_size != buffer_size) && (p_frame->buffer_size > 0))
5466  {
5467  ni_log(NI_LOG_TRACE, "%s: free current p_frame p_frame->buffer_size=%d\n",
5468  __FUNCTION__, p_frame->buffer_size);
5469  ni_logan_frame_buffer_free(p_frame);
5470  }
5471 
5472  //Check if need to realocate
5473  if (p_frame->buffer_size != buffer_size)
5474  {
5475 #ifndef XCODER_SIM_ENABLED
5476  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size))
5477  {
5478  ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate p_frame buffer.\n");
5480  LRETURN;
5481  }
5482 #else
5483  p_buffer = malloc(buffer_size);
5484  if (!p_buffer)
5485  {
5486  ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate p_frame buffer.\n");
5488  LRETURN;
5489  }
5490 #endif
5491  // init once after allocation
5492  memset(p_buffer, 0, buffer_size);
5493  p_frame->buffer_size = buffer_size;
5494  p_frame->p_buffer = p_buffer;
5495  ni_log(NI_LOG_TRACE, "%s: allocated new p_frame buffer\n", __FUNCTION__);
5496  }
5497  else
5498  {
5499  ni_log(NI_LOG_TRACE, "%s: reuse p_frame buffer\n", __FUNCTION__);
5500  }
5501 
5502  p_frame->p_data[3] = (uint8_t*)p_frame->p_buffer;
5503  p_frame->p_data[0] = buffer[0];
5504  p_frame->p_data[1] = buffer[1];
5505  p_frame->p_data[2] = buffer[2];
5506 
5507  p_frame->data_len[0] = linesize[0] * video_height;
5508  p_frame->data_len[1] = p_frame->data_len[0] / 4;
5509  p_frame->data_len[2] = p_frame->data_len[0] / 4;
5510  p_frame->data_len[3] = extra_len;
5511 
5512  p_frame->video_width = video_width;//used for sequence change feature
5513  p_frame->video_height = video_height;//used for sequence change feature
5514  ni_log(NI_LOG_TRACE, "%s: success: p_frame->buffer_size=%d\n",
5515  __FUNCTION__, p_frame->buffer_size);
5516 
5517  END:
5518 
5519  if (NI_LOGAN_RETCODE_SUCCESS != retval)
5520  {
5521  ni_logan_aligned_free(p_buffer);
5522  }
5523 
5524  return retval;
5525 }
5526 
5527 /*!*****************************************************************************
5528  * \brief Check if incoming frame is encoder zero copy compatible or not
5529  *
5530  * \param[in] width width of encoder frame.
5531  * \param[in] height height of encoder frame.
5532  * \param[in] linesize linesizes (pointer to array).
5533  * \param[in] dst_stride dst_stride (produced by ni_logan_get_hw_yuv420p_dim).
5534  * \param[in] src_height src height of every planar.
5535  * \param[in] dst_height dst_height_aligned(produced by ni_logan_get_hw_yuv420p_dim).
5536  * \param[in] bit_depth_factor bit_depth of frame.
5537  * \param[in] data CPU address of frame planar.
5538  *
5539  * \return on success
5540  * NI_LOGAN_RETCODE_SUCCESS
5541  *
5542  * on failure
5543  * NI_LOGAN_RETCODE_FAILURE
5544  *
5545 *******************************************************************************/
5547  const int height,
5548  const int linesize[],
5549  const int dst_stride[],
5550  const int src_height[],
5551  const int dst_height[],
5552  const int bit_depth_factor,
5553  const uint8_t * data[])
5554 {
5555  if (((uintptr_t)data[0] % NI_LOGAN_MEM_PAGE_ALIGNMENT) == 0 && //buffer address aligned
5556  width % 2 == 0 && dst_stride[0] == width * bit_depth_factor && //except width padding case
5557  height % 16 == 0 && //height 16 aligned
5558  dst_height[0] == src_height[0] && //except height paddding case
5559  dst_height[1] == src_height[1] &&
5560  dst_height[2] == src_height[2] &&
5561  dst_stride[0] == linesize[0] && //stride aligned
5562  dst_stride[1] == linesize[1] && //stride aligned
5563  dst_stride[2] == linesize[2] && //stride aligned
5564  data[1] == data[0] + dst_stride[0] * height && //continous
5565  data[2] == data[1] + dst_stride[1] * height / 2)
5566  return NI_LOGAN_RETCODE_SUCCESS;
5567  return NI_LOGAN_RETCODE_FAILURE;
5568 }
5569 
5570 /*!*****************************************************************************
5571  * \brief Check if logan firmware version is higher than expected api flavor and version
5572  *
5573  * \param[in] p_ctx Pointer to a caller allocated
5574  * ni_logan_session_context_t struct
5575  * \param[in] fw_api_fla expected firmware api flavor
5576  * \param[in] fw_api_ver expected firmware api version
5577  *
5578  * \return on success
5579  * NI_LOGAN_RETCODE_SUCCESS
5580  * On failure
5581  * NI_LOGAN_RETCODE_FAILURE
5582  *
5583 *******************************************************************************/
5584 LIB_API ni_logan_retcode_t is_logan_fw_rev_higher(ni_logan_session_context_t* p_ctx, int fw_api_fla, int fw_api_ver)
5585 {
5586  return (atoi(&p_ctx->fw_rev[NI_LOGAN_XCODER_VER_SZ + 1]) > (fw_api_fla * 100 + fw_api_ver)) ?
5589 }
5590 
5591 /*!*****************************************************************************
5592  * \brief Allocate log buffer if needed and retrieve firmware logs from device
5593  *
5594  * \param[in] p_ctx Pointer to a caller allocated
5595  * ni_logan_session_context_t struct
5596  * \param[in] p_log_buffer Reference to pointer to a log buffer.
5597  * If log buffer pointer is NULL, this function will
5598  * allocate log buffer.
5599  * NOTE - caller is responsible for freeing log buffer
5600  * after calling this function.
5601  * \param[in] gen_log_file Indicating whether it is required to generate log files
5602  *
5603  *
5604  * \return on success
5605  * NI_LOGAN_RETCODE_SUCCESS
5606  *
5607  * on failure
5608  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
5609  * NI_LOGAN_RETCODE_INVALID_PARAM
5610 *******************************************************************************/
5612  void** p_log_buffer,
5613  bool gen_log_file)
5614 {
5616  bool is_ext_buf = true;
5617  if (*p_log_buffer == NULL)
5618  {
5619  if (ni_logan_posix_memalign(p_log_buffer, sysconf(_SC_PAGESIZE), NI_LOGAN_CPU_LOG_BUFFER_SIZE))
5620  {
5621  ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate log buffer\n",
5622  NI_ERRNO, __func__);
5624  }
5625  is_ext_buf = false;
5626  }
5627 
5628  if(*p_log_buffer != NULL){
5629  memset(*p_log_buffer, 0, NI_LOGAN_CPU_LOG_BUFFER_SIZE);
5630  retval = ni_logan_dump_logs(p_ctx, *p_log_buffer, gen_log_file); // dump FW logs
5631  if(!is_ext_buf)
5632  ni_logan_aligned_free(*p_log_buffer);
5633  }else{
5635  }
5636 
5637  return retval;
5638 }
ni_logan_retcode_t
@ NI_LOGAN_RETCODE_PARAM_ERROR_MN_QP
@ NI_LOGAN_RETCODE_ERROR_INVALID_HANDLE
@ NI_LOGAN_RETCODE_NVME_SC_VPU_GENERAL_ERROR
@ NI_LOGAN_RETCODE_PARAM_ERROR_CONF_WIN_R
@ NI_LOGAN_RETCODE_PARAM_ERROR_HEIGHT_TOO_SMALL
@ NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
@ NI_LOGAN_RETCODE_PARAM_ERROR_ZERO
@ NI_LOGAN_RETCODE_PARAM_ERROR_FRATE
@ NI_LOGAN_RETCODE_PARAM_INVALID_VALUE
@ NI_LOGAN_RETCODE_PARAM_ERROR_TOO_SMALL
@ NI_LOGAN_RETCODE_PARAM_ERROR_OOR
@ NI_LOGAN_RETCODE_PARAM_ERROR_CONF_WIN_TOP
@ NI_LOGAN_RETCODE_PARAM_ERROR_USR_RMD_ENC_PARAM
@ NI_LOGAN_RETCODE_PARAM_ERROR_CU_SIZE_MODE
@ NI_LOGAN_RETCODE_PARAM_ERROR_TRATE
@ NI_LOGAN_RETCODE_PARAM_ERROR_GOP_PRESET
@ NI_LOGAN_RETCODE_PARAM_ERROR_AREA_TOO_BIG
@ NI_LOGAN_RETCODE_PARAM_ERROR_RCENABLE
@ NI_LOGAN_RETCODE_PARAM_ERROR_WIDTH_TOO_SMALL
@ NI_LOGAN_RETCODE_NVME_SC_RESOURCE_IS_EMPTY
@ NI_LOGAN_RETCODE_ERROR_UNLOCK_DEVICE
@ NI_LOGAN_RETCODE_DEFAULT_SESSION_ERR_NO
@ NI_LOGAN_RETCODE_PARAM_GOP_INTRA_INCOMPATIBLE
@ NI_LOGAN_RETCODE_PARAM_ERROR_CONF_WIN_L
@ NI_LOGAN_RETCODE_NVME_SC_REQUEST_IN_PROGRESS
@ NI_LOGAN_RETCODE_PARAM_ERROR_TOO_BIG
@ NI_LOGAN_RETCODE_ERROR_RESOURCE_UNAVAILABLE
@ NI_LOGAN_RETCODE_PARAM_ERROR_MX_QP
@ NI_LOGAN_RETCODE_PARAM_ERROR_BRATE_LT_TRATE
@ NI_LOGAN_RETCODE_PARAM_ERROR_CUSIZE_MODE_8X8_EN
@ NI_LOGAN_RETCODE_PARAM_ERROR_DY_MERGE_16X16_EN
@ NI_LOGAN_RETCODE_PARAM_ERROR_CUSIZE_MODE_16X16_EN
@ NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
@ NI_LOGAN_RETCODE_INVALID_PARAM
@ NI_LOGAN_RETCODE_ERROR_MEM_ALOC
@ NI_LOGAN_RETCODE_PARAM_ERROR_DY_MERGE_8X8_EN
@ NI_LOGAN_RETCODE_PARAM_ERROR_PIC_HEIGHT
@ NI_LOGAN_RETCODE_PARAM_ERROR_INTRA_PERIOD
@ NI_LOGAN_RETCODE_ERROR_VPU_RECOVERY
@ NI_LOGAN_RETCODE_PARAM_INVALID_NAME
@ NI_LOGAN_RETCODE_ERROR_GET_DEVICE_POOL
@ NI_LOGAN_RETCODE_PARAM_ERROR_BRATE
@ NI_LOGAN_RETCODE_PARAM_ERROR_HEIGHT_TOO_BIG
@ NI_LOGAN_RETCODE_PARAM_ERROR_RCINITDELAY
@ NI_LOGAN_RETCODE_PARAM_ERROR_MAXNUMMERGE
@ NI_LOGAN_RETCODE_PARAM_ERROR_CONF_WIN_BOT
@ NI_LOGAN_RETCODE_PARAM_ERROR_HVS_QP_EN
@ NI_LOGAN_RETCODE_PARAM_ERROR_CUSTOM_GOP
@ NI_LOGAN_RETCODE_SUCCESS
@ NI_LOGAN_RETCODE_NVME_SC_WRITE_BUFFER_FULL
@ NI_LOGAN_RETCODE_FAILURE
@ NI_LOGAN_RETCODE_NVME_SC_VPU_RECOVERY
@ NI_LOGAN_RETCODE_PARAM_ERROR_PIC_WIDTH
@ NI_LOGAN_RETCODE_PARAM_ERROR_DY_MERGE_32X32_EN
@ NI_LOGAN_RETCODE_PARAM_ERROR_MX_DELTA_QP
@ NI_LOGAN_RETCODE_NVME_SC_RESOURCE_UNAVAILABLE
@ NI_LOGAN_RETCODE_PARAM_ERROR_CUSIZE_MODE_32X32_EN
@ NI_LOGAN_RETCODE_PARAM_ERROR_HVS_QP_SCL
@ NI_LOGAN_RETCODE_PARAM_ERROR_INTRA_QP
@ NI_LOGAN_RETCODE_PARAM_ERROR_DECODING_REFRESH_TYPE
@ NI_LOGAN_RETCODE_PARAM_ERROR_CU_LVL_RC_EN
@ NI_LOGAN_RETCODE_ERROR_LOCK_DOWN_DEVICE
@ NI_LOGAN_RETCODE_PARAM_ERROR_WIDTH_TOO_BIG
@ NI_LOGAN_RETCODE_ERROR_INVALID_ALLOCATION_METHOD
@ NI_LOGAN_RETCODE_ERROR_OPEN_DEVICE
@ NI_LOGAN_RETCODE_ERROR_EXCEED_MAX_NUM_SESSIONS
@ NI_LOGAN_RETCODE_PARAM_ERROR_RC_INIT_DELAY
@ NI_LOGAN_RETCODE_NVME_SC_VPU_RSRC_INSUFFICIENT
@ NI_LOGAN_RETCODE_PARAM_ERROR_MX_NUM_MERGE
@ NI_LOGAN_RETCODE_NVME_SC_INVALID_PARAMETER
@ NI_LOGAN_RETCODE_NVME_SC_REQUEST_NOT_COMPLETED
@ NI_LOGAN_RETCODE_NVME_SC_RESOURCE_NOT_FOUND
#define END
#define NI_LOGAN_INVALID_SEI_TYPE
#define NI_LOGAN_APP_ENC_FRAME_META_DATA_SIZE
#define NI_INVALID_IO_SIZE
#define NI_LOGAN_MAX_NUM_DATA_POINTERS
#define NI_LOGAN_XCODER_API_VER_SZ
Definition: ni_defs_logan.h:69
#define NI_LOGAN_XCODER_VER_SZ
Definition: ni_defs_logan.h:67
#define NI_LOGAN_CPU_LOG_BUFFER_SIZE
#define NI_ERRNO
#define NI_LOGAN_FIFO_SZ
#define NI_LOGAN_MEM_PAGE_ALIGNMENT
ni_logan_device_type_t
@ NI_LOGAN_DEVICE_TYPE_UPLOAD
@ NI_LOGAN_DEVICE_TYPE_ENCODER
@ NI_LOGAN_DEVICE_TYPE_DECODER
#define NI_LOGAN_MAX_PACKET_SZ
#define NI_LOGAN_XCODER_API_FLAVOR_SZ
Definition: ni_defs_logan.h:68
#define LRETURN
#define NI_LOGAN_FW_META_DATA_SZ
#define COMPARE_F(STR1, STR2, STR3)
#define atof(p_str)
ni_logan_retcode_t ni_logan_uploader_frame_buffer_unlock(ni_logan_session_context_t *p_upl_ctx, ni_logan_frame_t *p_frame)
Unlock a hardware P2P frame after encoding.
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_logan_retcode_t ni_logan_packet_buffer_alloc(ni_logan_packet_t *p_packet, int packet_size)
Allocate memory for the packet buffer based on provided packet size.
ni_logan_retcode_t ni_logan_device_dec_session_save_hdrs(ni_logan_session_context_t *p_ctx, uint8_t *hdr_data, uint8_t hdr_size)
Save a stream's headers in a decoder session that can be used later for continuous decoding from the ...
ni_logan_retcode_t ni_logan_encoder_params_check(ni_logan_encoder_params_t *p_params, ni_logan_codec_format_t codec)
Validate relationship of some params in encoder parameters structure.
#define COMPARE(STR1, STR2, STR3)
LIB_API ni_logan_retcode_t ni_logan_frame_zerocopy_check(const int width, const int height, const int linesize[], const int dst_stride[], const int src_height[], const int dst_height[], const int bit_depth_factor, const uint8_t *data[])
Check if incoming frame is encoder zero copy compatible or not.
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.
#define OPT(STR)
ni_logan_retcode_t ni_logan_device_session_flush(ni_logan_session_context_t *p_ctx, ni_logan_device_type_t device_type)
Sends a flush command to the device ni_logan_device_session_open() If device_type is NI_LOGAN_DEVICE_...
ni_logan_session_context_t * ni_logan_device_session_context_alloc_init(void)
Allocates and initializes a new ni_logan_session_context_t struct.
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_frame_zerocopy_buffer_alloc(ni_logan_frame_t *p_frame, int video_width, int video_height, int linesize[], int extra_len, int factor, uint8_t *buffer[])
Allocate memory for the frame buffer based on provided parameters Applicable to use YUV420p AVFrame f...
ni_logan_retcode_t ni_logan_encoder_gop_params_set_value(ni_logan_encoder_params_t *p_params, const char *name, const char *value)
Set got parameter value referenced by name in encoder parameters structure.
void ni_logan_frame_free_aux_data(ni_logan_frame_t *frame, ni_aux_data_type_t type)
If auxiliary data of the given type exists in the frame, free it and remove it from the frame.
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_...
ni_logan_retcode_t ni_logan_frame_buffer_alloc_hwenc(ni_logan_frame_t *p_frame, int video_width, int video_height, int extra_len)
Allocate memory for the frame buffer based on provided parameters taking into account pic line size a...
const char *const g_logan_xcoder_preset_names[NI_LOGAN_XCODER_PRESET_NAMES_ARRAY_LEN]
ni_logan_retcode_t ni_logan_uploader_frame_buffer_lock(ni_logan_session_context_t *p_upl_ctx, ni_logan_frame_t *p_frame)
Lock a hardware P2P frame prior to encoding.
void ni_logan_frame_wipe_aux_data(ni_logan_frame_t *frame)
Free and remove all auxiliary data from the frame.
int ni_logan_device_session_acquire(ni_logan_session_context_t *p_ctx, ni_logan_frame_t *p_frame)
Acquire a P2P frame buffer from the hwupload session.
ni_logan_retcode_t ni_logan_packet_buffer_free(ni_logan_packet_t *p_packet)
Free packet buffer that was previously allocated with either ni_logan_packet_buffer_alloc.
ni_logan_retcode_t ni_logan_parse_reconf_file(const char *reconf_file, int hash_map[100][10])
ni_logan_retcode_t ni_logan_decoder_frame_buffer_alloc(ni_logan_buf_pool_t *p_pool, ni_logan_frame_t *p_frame, int alloc_mem, int video_width, int video_height, int alignment, int factor)
Allocate memory for decoder frame buffer based on provided parameters; the memory is retrieved from a...
#define OPT2(STR1, STR2)
LIB_API ni_logan_retcode_t ni_logan_device_dec_session_flush(ni_logan_session_context_t *p_ctx)
Flush a decoder session to get ready to continue decoding.
#define CHECK2VAL(STR, VAL1, VAL2)
ni_logan_retcode_t ni_logan_decoder_frame_buffer_free(ni_logan_frame_t *p_frame)
Free decoder frame buffer that was previously allocated with ni_logan_decoder_frame_buffer_alloc,...
void ni_logan_device_session_context_init(ni_logan_session_context_t *p_ctx)
Initialize already allocated session context to a known state.
int ni_logan_get_num_reorder_of_gop_structure(ni_logan_encoder_params_t *p_params)
Get GOP's max number of reorder frames.
ni_logan_retcode_t ni_logan_frame_buffer_free(ni_logan_frame_t *p_frame)
Free frame buffer that was previously allocated with either ni_logan_frame_buffer_alloc or ni_logan_e...
ni_aux_data_t * ni_logan_frame_get_aux_data(const ni_logan_frame_t *frame, ni_aux_data_type_t type)
Retrieve from the frame auxiliary data of a given type if exists.
ni_aux_data_t * ni_logan_frame_new_aux_data_from_raw_data(ni_logan_frame_t *frame, ni_aux_data_type_t type, const uint8_t *raw_data, int data_size)
Add a new auxiliary data to a frame and copy in the raw data.
int ni_logan_device_session_init_framepool(ni_logan_session_context_t *p_ctx, uint32_t pool_size, uint32_t p2p_pool)
Sends frame pool setup info to device.
ni_logan_retcode_t ni_logan_encoder_frame_buffer_alloc(ni_logan_frame_t *p_frame, int video_width, int video_height, int linesize[], int alignment, int extra_len, int factor)
Allocate memory for the frame buffer for encoding based on given parameters, taking into account pic ...
int ni_logan_packet_copy(void *p_destination, const void *const p_source, int cur_size, void *p_leftover, int *p_prev_size)
Copy video packet accounting for allighment.
ni_logan_retcode_t ni_logan_uploader_p2p_test_send(ni_logan_session_context_t *p_upl_ctx, uint8_t *p_data, uint32_t len, ni_logan_frame_t *p_hwframe)
Special P2P test API function. Copies YUV data from the software frame to the hardware P2P frame on t...
ni_logan_retcode_t ni_logan_decoder_session_send_flush(ni_logan_session_context_t *p_ctx)
Sends a flush command to the decoder ni_logan_device_session_open()
ni_logan_retcode_t ni_logan_device_session_copy(ni_logan_session_context_t *src_p_ctx, ni_logan_session_context_t *dst_p_ctx)
Copies existing decoding session params for hw frame usage.
void ni_logan_close_event(ni_event_handle_t event_handle)
Closes event and releases resources.
int ni_logan_device_session_read_hwdesc(ni_logan_session_context_t *p_ctx, ni_logan_session_data_io_t *p_data)
Reads data from the device device_type should be NI_LOGAN_DEVICE_TYPE_DECODER, and reads data hwdesc ...
int ni_logan_device_session_hwup(ni_logan_session_context_t *p_ctx, ni_logan_session_data_io_t *p_src_data, ni_logan_hwframe_surface_t *hwdesc)
Writes data and reads back hw descriptor from decoder output buffer.
int ni_logan_get_num_ref_frame_of_gop_structure(ni_logan_encoder_params_t *p_params)
Get GOP's number of reference frames.
int ni_logan_device_session_read(ni_logan_session_context_t *p_ctx, ni_logan_session_data_io_t *p_data, ni_logan_device_type_t device_type)
Reads data the device If device_type is NI_LOGAN_DEVICE_TYPE_DECODER reads data packet from decoder I...
ni_logan_retcode_t ni_logan_encoder_params_set_value(ni_logan_encoder_params_t *p_params, const char *name, const char *value, ni_logan_session_context_t *ctx)
Set value referenced by name in encoder parameters structure.
int ni_logan_device_session_hwdl(ni_logan_session_context_t *p_ctx, ni_logan_session_data_io_t *p_data, ni_logan_hwframe_surface_t *hwdesc)
Reads data from hw descriptor from decoder output buffer.
#define atoi(p_str)
void ni_logan_device_session_context_clear(ni_logan_session_context_t *p_ctx)
Clear already allocated session context to all zeros.
const char * ni_logan_err2str(int err)
Convert error numver into error messages.
LIB_API ni_logan_retcode_t ni_logan_encoder_set_input_frame_format(ni_logan_session_context_t *p_enc_ctx, ni_logan_encoder_params_t *p_enc_params, int width, int height, int bit_depth, int src_endian)
Set the incoming frame format for the encoder.
ni_logan_retcode_t ni_logan_decode_buffer_free(ni_logan_hwframe_surface_t *surface, ni_device_handle_t device_handle, ni_event_handle_t event_handle)
Recycle a frame buffer on card.
ni_logan_retcode_t ni_logan_device_handle_map_SN(ni_device_handle_t device_handle, ni_logan_serial_num_t *p_serial_num)
Queries device Serial number.
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.
void ni_logan_device_session_context_free(ni_logan_session_context_t *p_ctx)
Frees previously allocated session context.
ni_logan_retcode_t ni_logan_frame_buffer_alloc_v4(ni_logan_frame_t *p_frame, int pixel_format, int video_width, int video_height, int linesize[], int alignment, int extra_len)
Allocate memory for the frame buffer based on provided parameters taking into account width,...
const char *const g_logan_xcoder_log_names[NI_LOGAN_XCODER_LOG_NAMES_ARRAY_LEN]
LIB_API ni_logan_retcode_t is_logan_fw_rev_higher(ni_logan_session_context_t *p_ctx, int fw_api_fla, int fw_api_ver)
Check if logan firmware version is higher than expected api flavor and version.
struct _ni_err_rc_txt_entry ni_logan_err2str_entry_t
ni_logan_retcode_t ni_logan_frame_buffer_alloc(ni_logan_frame_t *p_frame, int video_width, int video_height, int alignment, int metadata_flag, int factor, int hw_frame_count)
Allocate preliminary memory for the frame buffer for encoding based on provided parameters....
int ni_logan_calculate_total_frame_size(const ni_logan_session_context_t *p_upl_ctx, const int linesize[], const int heightsize[])
Calculate the total size of a frame based on the upload context attributes and includes rounding up t...
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_logan_retcode_t ni_logan_alloc_and_get_fw_logs(ni_logan_session_context_t *p_ctx, void **p_log_buffer, bool gen_log_file)
Allocate log buffer if needed and retrieve firmware logs from device.
ni_event_handle_t ni_logan_create_event(void)
Create event and returnes event handle if successful.
ni_aux_data_t * ni_logan_frame_new_aux_data(ni_logan_frame_t *frame, ni_aux_data_type_t type, int data_size)
Add a new auxiliary data to a frame.
int ni_logan_device_session_write(ni_logan_session_context_t *p_ctx, ni_logan_session_data_io_t *p_data, ni_logan_device_type_t device_type)
Sends data the device If device_type is NI_LOGAN_DEVICE_TYPE_DECODER sends data packet to decoder If ...
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.
ni_logan_retcode_t ni_logan_decoder_params_set_value(ni_logan_decoder_params_t *p_params, const char *name, char *value)
Set value referenced by name in decoder parameters structure.
void ni_logan_decoder_frame_buffer_pool_return_buf(ni_logan_buf_t *buf, ni_logan_buf_pool_t *p_buffer_pool)
Return a memory buffer to memory buffer pool.
#define atobool(p_str)
Main NETINT device API header file provides the ability to communicate with NI T-408 type hardware tr...
#define NI_LOGAN_ENC_PARAM_CONF_WIN_BOTTOM
#define NI_LOGAN_ENC_GOP_PARAMS_G4_TEMPORAL_ID
#define NI_LOGAN_ENC_GOP_PARAMS_G4_NUM_REF_PIC_L0
#define NI_LOGAN_MAX_INTRA_QP
#define NI_LOGAN_ENC_PARAM_FRAME_RATE_DENOM
#define NI_LOGAN_ENC_GOP_PARAMS_G3_NUM_REF_POC_L0
#define NI_LOGAN_XCODER_LOG_NAME_FULL
#define NI_LOGAN_ENC_PARAM_INTRA_QP
#define NI_LOGAN_ENC_PARAM_ENTROPY_CODING_MODE
#define NI_LOGAN_DEC_PARAM_LOW_DELAY_MODE
#define NI_LOGAN_ENC_GOP_PARAMS_G7_PIC_TYPE
#define NI_LOGAN_ENC_GOP_PARAMS_G0_NUM_REF_POC_L0
#define NI_LOGAN_ENC_PARAM_LEVEL
#define NI_LOGAN_ENC_PARAM_MAX_DELTA_QP
#define NI_LOGAN_MAX_MIN_QP
#define NI_LOGAN_ENC_GOP_PARAMS_G0_PIC_TYPE
#define NI_LOGAN_ENC_PARAM_ENABLE_HVS_QP
#define BEST_MODEL_LOAD_STR
#define NI_LOGAN_SESSION_OPEN_RETRY_INTERVAL_US
#define NI_LOGAN_ENC_PARAM_MIN_QP
#define NI_LOGAN_ENC_PARAM_INTRA_REFRESH_RESET
#define NI_LOGAN_ENC_GOP_PARAMS_G6_NUM_REF_PIC_L0
#define NI_LOGAN_ENC_PARAM_SAR_DENOM
#define NI_LOGAN_MAX_BIN
#define LOGAN_AV_CODEC_DEFAULT_BITRATE
#define NI_LOGAN_DEFAULT_INTRA_QP
#define NI_LOGAN_ENC_GOP_PARAMS_G3_TEMPORAL_ID
#define NI_LOGAN_ENC_PARAM_DISABLE_TIMING_INFO
#define NI_LOGAN_ENC_GOP_PARAMS_G0_NUM_REF_POC_L1
#define NI_LOGAN_DEC_PARAM_SAVE_PKT
#define NI_LOGAN_ENC_PARAM_MAX_QP
#define NI_LOGAN_MAX_CUSTOM_SEI_PASSTHRU
#define NI_LOGAN_MIN_DECODING_REFRESH_TYPE
#define NI_LOGAN_ENC_PARAM_AVC_SLICE_MODE
#define NI_LOGAN_MIN_INTRA_PERIOD
#define NI_LOGAN_ENC_PARAM_HRD_ENABLE
#define NI_LOGAN_MAX_GOP_SIZE
#define NI_LOGAN_MIN_MAX_DELTA_QP
struct _ni_logan_hwframe_surface ni_logan_hwframe_surface_t
#define NI_LOGAN_ENC_GOP_PARAMS_G6_POC_OFFSET
#define NI_LOGAN_ENC_PARAM_ENABLE_VFR
#define NI_LOGAN_ENC_GOP_PARAMS_G2_PIC_QP
#define NI_LOGAN_ENC_PARAM_LOSSLESS_ENABLE
#define NI_LOGAN_ENC_PARAM_HIGH_TIER
#define NI_LOGAN_ENC_PARAM_PROFILE
#define NI_LOGAN_MAX_KEEP_ALIVE_TIMEOUT
#define NI_LOGAN_MIN_KEEP_ALIVE_TIMEOUT
#define NI_LOGAN_MAX_GOP_PRESET_IDX
#define NI_LOGAN_ENC_PARAM_CONF_WIN_LEFT
#define NI_LOGAN_ENC_GOP_PARAMS_G3_NUM_REF_POC_L1
#define NI_LOGAN_ENC_GOP_PARAMS_G2_PIC_TYPE
#define NI_LOGAN_ENC_PARAM_BITRATE
#define NI_LOGAN_MIN_PRIORITY
#define NI_LOGAN_ENC_PARAM_CHROMA_QP_OffSET
#define NI_LOGAN_ENC_PARAM_DOLBY_VISION_PROFILE
#define NI_LOGAN_ENABLE_USR_DATA_SEI_PASSTHRU
#define NI_LOGAN_ENC_GOP_PARAMS_G5_NUM_REF_POC_L0
#define NI_LOGAN_ENC_PARAM_LOW_DELAY
#define NI_LOGAN_ENC_GOP_PARAMS_G7_NUM_REF_POC_L0
#define NI_LOGAN_PARAM_MAX_HEIGHT
#define NI_LOGAN_ENC_PARAM_VIDEO_FULL_RANGE_FLAG
#define NI_LOGAN_ENC_PARAM_ENABLE_MB_LEVEL_RC
#define NI_LOGAN_ENC_PARAM_AVC_SLICE_ARG
#define NI_LOGAN_ENC_PARAM_CRF
#define NI_LOGAN_ENC_GOP_PARAMS_G2_NUM_REF_POC_L0
#define NI_LOGAN_ENC_PARAM_ROI_ENABLE
#define NI_LOGAN_DEC_PARAM_OUT
#define BEST_LOAD_STR
@ NI_LOGAN_CODEC_HW_DOWNLOAD
#define NI_LOGAN_ENC_PARAM_RC_INIT_DELAY
#define NI_LOGAN_KEEP_ALIVE_TIMEOUT
#define NI_LOGAN_MAX_MAX_QP
#define NI_LOGAN_ENC_GOP_PARAMS_G3_POC_OFFSET
#define NI_LOGAN_ENC_PARAM_ROI_DEMO_MODE
#define NI_LOGAN_ENC_GOP_PARAMS_G4_NUM_REF_POC_L1
#define NI_LOGAN_ENC_GOP_PARAMS_G7_POC_OFFSET
#define NI_LOGAN_MIN_INTRA_QP
#define NI_LOGAN_ENC_PARAM_FRAME_RATE
#define NI_LOGAN_ENC_PARAM_SLICE_ARG
#define NI_LOGAN_PARAM_MAX_WIDTH
#define NI_LOGAN_ENC_GOP_PARAMS_G6_NUM_REF_POC_L0
#define NI_LOGAN_ENC_PARAM_GOP_PRESET_IDX
#define NI_LOGAN_ENC_PARAM_DECODING_REFRESH_TYPE
#define NI_LOGAN_ENC_GOP_PARAMS_CUSTOM_GOP_SIZE
#define NI_LOGAN_DISABLE_USR_DATA_SEI_PASSTHRU
#define NI_LOGAN_ENC_PARAM_INTRA_MB_REFRESH_ARG
#define NI_LOGAN_ENC_PARAM_ENABLE_HVS_QP_SCALE
#define NI_LOGAN_ENC_PARAM_PREFERRED_TRANSFER_CHARACTERISTICS
#define NI_LOGAN_ENC_GOP_PARAMS_G5_NUM_REF_PIC_L0
#define NI_LOGAN_XCODER_PRESET_NAME_DEFAULT
#define NI_LOGAN_MIN_MIN_QP
#define NI_LOGAN_XCODER_LOG_NAME_DEBUG
#define NI_LOGAN_INVALID_HW_META_IDX
#define NI_LOGAN_ENC_GOP_PARAMS_G7_TEMPORAL_ID
#define NI_LOGAN_ENC_PARAM_COLOR_TRANSFER_CHARACTERISTIC
#define NI_LOGAN_ENC_PARAM_ENABLE_RATE_CONTROL
#define NI_LOGAN_ENC_PARAM_INTRA_REFRESH_MODE
#define NI_LOGAN_ENC_GOP_PARAMS_G1_PIC_TYPE
#define NI_LOGAN_ENC_PARAM_CRF_IP_RATIO
#define NI_LOGAN_XCODER_LOG_NAME_INFO
#define NI_LOGAN_MAX_INTRA_REFRESH_MIN_PERIOD
#define NI_LOGAN_ENC_GOP_PARAMS_G6_TEMPORAL_ID
#define NI_LOGAN_ENC_GOP_PARAMS_G2_NUM_REF_POC_L1
#define NI_LOGAN_ENC_GOP_PARAMS_G7_NUM_REF_POC_L1
#define NI_LOGAN_MIN_WIDTH
#define NI_LOGAN_ENC_PARAM_GEN_HDRS
#define NI_LOGAN_DISABLE_CHECK_PACKET
#define NI_LOGAN_ENC_PARAM_SAR_NUM
#define NI_LOGAN_ENC_GOP_PARAMS_G7_NUM_REF_PIC_L0
#define NI_LOGAN_ENC_PARAM_CACHE_ROI
#define NI_LOGAN_ENC_GOP_PARAMS_G5_TEMPORAL_ID
#define NI_LOGAN_ENC_GOP_PARAMS_G1_NUM_REF_PIC_L0
#define NI_LOGAN_MAX_DECODING_REFRESH_TYPE
#define NI_LOGAN_DEFAULT_MAX_QP
#define NI_LOGAN_MAX_RESOLUTION_HEIGHT
#define NI_LOGAN_XCODER_LOG_NAME_ERROR
#define NI_LOGAN_ENC_PARAM_USE_RECOMMENDED_ENC_PARAMS
#define NI_LOGAN_ENABLE_CHECK_PACKET
#define NI_LOGAN_ENC_GOP_PARAMS_G2_NUM_REF_PIC_L0
@ LOGAN_PIC_TYPE_I
#define NI_LOGAN_ENC_PARAM_COLOR_PRIMARY
#define NI_LOGAN_ENC_PARAM_PADDING
#define NI_LOGAN_ENC_PARAM_ENABLE_8X8_TRANSFORM
#define NI_LOGAN_MAX_PRIORITY
#define NI_LOGAN_ENC_GOP_PARAMS_G0_POC_OFFSET
#define NI_LOGAN_ENC_PARAM_FLUSH_GOP
#define NI_LOGAN_MAX_INTRA_PERIOD
#define NI_LOGAN_ENC_GOP_PARAMS_G0_NUM_REF_PIC_L0
#define NI_LOGAN_PARAM_MIN_WIDTH
#define NI_LOGAN_ENC_GOP_PARAMS_G4_NUM_REF_POC_L0
#define NI_LOGAN_ENC_PARAM_FORCE_FRAME_TYPE
#define NI_LOGAN_ENC_GOP_PARAMS_G1_TEMPORAL_ID
#define NI_LOGAN_DEC_PARAM_CUSTOM_SEI_PASSTHRU
#define NI_LOGAN_MAX_SEI_DATA
#define NI_LOGAN_ENC_PARAM_TRANS_RATE
#define NI_LOGAN_DEC_PARAM_ENABLE_VUI_INFO_PASSTHRU
#define NI_LOGAN_DEC_PARAM_ENABLE_SKIP_FMT_NONE_CHECK
#define NI_LOGAN_XCODER_LOG_NAME_WARN
#define NI_LOGAN_ENC_PARAM_ENABLE_AUD
#define NI_LOGAN_ENC_PARAM_INTRA_REFRESH_MIN_PERIOD
#define NI_LOGAN_ENC_PARAM_SLICE_MODE
#define NI_LOGAN_XCODER_PRESET_NAME_CUSTOM
#define NI_LOGAN_ENC_PARAM_RECONF_FILE
#define NI_LOGAN_ENC_GOP_PARAMS_G7_PIC_QP
enum _ni_logan_frame_aux_data_type ni_aux_data_type_t
#define NI_LOGAN_ENC_GOP_PARAMS_G1_NUM_REF_POC_L0
#define NI_LOGAN_ENC_PARAM_LOG_LEVEL
#define NI_LOGAN_MIN_HEIGHT
#define NI_LOGAN_ENC_PARAM_CBR
#define NI_LOGAN_ENC_GOP_PARAMS_G1_POC_OFFSET
#define NI_LOGAN_XCODER_LOG_NAME_NONE
#define NI_LOGAN_VPU_CEIL(_data, _align)
#define NI_LOGAN_ENC_PARAM_INTRA_MB_REFRESH_MODE
#define NI_LOGAN_ENC_GOP_PARAMS_G1_PIC_QP
#define NI_LOGAN_ENC_PARAM_HVS_QP_SCALE
#define BEST_DEVICE_INST_STR
#define NI_LOGAN_SET_HIGH_PRIORITY
#define NI_LOGAN_MIN_BIN
#define NI_LOGAN_ENC_GOP_PARAMS_G1_NUM_REF_POC_L1
#define NI_LOGAN_DEFAULT_KEEP_ALIVE_TIMEOUT
#define NI_LOGAN_MAX_SESSION_OPEN_RETRIES
#define NI_LOGAN_ENC_PARAM_MAX_FRAME_SIZE_BYTES
#define NI_LOGAN_XCODER_PRESET_NAMES_ARRAY_LEN
#define NI_LOGAN_DEFAULT_MIN_QP
#define NI_LOGAN_MIN_BITRATE
#define NI_LOGAN_MIN_MAX_QP
#define NI_LOGAN_ENC_PARAM_FORCE_PIC_QP_DEMO_MODE
#define NI_LOGAN_ENC_GOP_PARAMS_G6_NUM_REF_POC_L1
#define NI_LOGAN_ENC_GOP_PARAMS_G0_PIC_QP
#define NI_LOGAN_ENC_GOP_PARAMS_G4_PIC_TYPE
#define NI_LOGAN_MAX_BITRATE
#define NI_LOGAN_DEC_PARAM_CHECK_PACKET
#define NI_LOGAN_MAX_MAX_DELTA_QP
#define NI_LOGAN_INVALID_HWID
#define NI_LOGAN_VPU_ALIGN8(_x)
#define NI_LOGAN_ENC_GOP_PARAMS_G6_PIC_QP
#define NI_LOGAN_ENC_PARAM_LOG
#define NI_LOGAN_MIN_USE_RECOMMENDED_ENC_PARAMS
#define NI_LOGAN_MIN_GOP_SIZE
#define NI_LOGAN_ENC_GOP_PARAMS_G5_POC_OFFSET
#define NI_LOGAN_VPU_ALIGN16(_x)
#define NI_LOGAN_MAX_GOP_NUM
#define NI_LOGAN_ENC_GOP_PARAMS_G5_NUM_REF_POC_L1
@ LOGAN_SESSION_RUN_STATE_NORMAL
#define NI_LOGAN_DEC_PARAM_ENABLE_FOLLOW_IFRAME
#define NI_LOGAN_ENC_PARAM_CRF_PB_RATIO
#define NI_LOGAN_ENC_PARAM_MAX_FRAME_SIZE_BITS
#define NI_LOGAN_FRAME_LITTLE_ENDIAN
#define NI_LOGAN_DEFAULT_MAX_DELTA_QP
#define NI_LOGAN_ENC_GOP_PARAMS_G5_PIC_QP
#define NI_LOGAN_MIN_CUSTOM_SEI_PASSTHRU
#define NI_LOGAN_ENC_PARAM_ENABLE_CU_LEVEL_RATE_CONTROL
#define NI_LOGAN_ENC_REPEAT_HEADERS_ALL_KEY_FRAMES
enum _ni_logan_codec_format ni_logan_codec_format_t
This is an enumeration for supported codec formats.
#define NI_LOGAN_MIN_INTRA_REFRESH_MIN_PERIOD
#define NI_MAX_NUM_AUX_DATA_PER_FRAME
#define NI_LOGAN_ENC_PARAM_MAX_FRAME_SIZE
#define NI_LOGAN_DEC_PARAM_LOW_DELAY
#define NI_LOGAN_ENC_GOP_PARAMS_G2_POC_OFFSET
#define NI_LOGAN_ENC_GOP_PARAMS_G3_PIC_TYPE
#define NI_LOGAN_MAX_USE_RECOMMENDED_ENC_PARAMS
#define NI_LOGAN_ENC_PARAM_LONG_TERM_REFERENCE_ENABLE
#define NI_LOGAN_ENC_PARAM_USE_LOW_DELAY_POC_TYPE
#define NI_LOGAN_ENC_PARAM_INTRA_REFRESH_ARG
#define NI_LOGAN_ENC_PARAM_ENABLE_EXPLICIT_RPL
@ NI_LOGAN_CODEC_FORMAT_H265
@ NI_LOGAN_CODEC_FORMAT_H264
#define NI_LOGAN_ENC_GOP_PARAMS_G3_NUM_REF_PIC_L0
#define NI_LOGAN_MAX_RESOLUTION_AREA
@ NI_LOGAN_PIX_FMT_YUV420P
@ NI_LOGAN_PIX_FMT_YUV420P10BE
@ NI_LOGAN_PIX_FMT_YUV420P10LE
@ NI_LOGAN_PIX_FMT_YUVJ420P
#define NI_LOGAN_ENC_GOP_PARAMS_G4_PIC_QP
#define NI_LOGAN_ENC_PARAM_CONF_WIN_TOP
#define NI_LOGAN_INVALID_SESSION_ID
#define NI_LOGAN_DEC_PARAM_USR_DATA_SEI_PASSTHRU
#define NI_LOGAN_ENC_PARAM_RECONF_DEMO_MODE
#define NI_LOGAN_ENC_PARAM_COLOR_SPACE
#define NI_LOGAN_ENC_GOP_PARAMS_G4_POC_OFFSET
#define NI_LOGAN_ENC_PARAM_FORCED_HEADER_ENABLE
#define NI_LOGAN_ENC_PARAM_CONF_WIN_RIGHT
#define NI_LOGAN_PARAM_MIN_HEIGHT
#define NI_LOGAN_ENC_PARAM_STRICT_TIMEOUT_MODE
#define NI_LOGAN_ENC_PARAM_INTRA_PERIOD
#define NI_LOGAN_ENC_GOP_PARAMS_G0_TEMPORAL_ID
#define NI_LOGAN_MAX_RESOLUTION_WIDTH
#define NI_LOGAN_ENC_GOP_PARAMS_G5_PIC_TYPE
#define NI_LOGAN_XCODER_LOG_NAMES_ARRAY_LEN
#define NI_LOGAN_ENC_GOP_PARAMS_G2_TEMPORAL_ID
#define NI_LOGAN_ENC_GOP_PARAMS_G3_PIC_QP
#define NI_LOGAN_MIN_CRF
#define NI_LOGAN_ENC_GOP_PARAMS_G6_PIC_TYPE
#define NI_LOGAN_FRAME_BIG_ENDIAN
#define NI_LOGAN_MAX_CRF
#define NI_LOGAN_MIN_GOP_PRESET_IDX
ni_logan_retcode_t ni_logan_decoder_session_query(ni_logan_session_context_t *p_ctx)
Query current decoder status.
ni_logan_retcode_t ni_logan_encoder_session_close(ni_logan_session_context_t *p_ctx, int eos_recieved)
Close a xcoder encoder instance.
int ni_logan_encoder_session_read(ni_logan_session_context_t *p_ctx, ni_logan_packet_t *p_packet)
Retrieve an encoded packet from encoder.
ni_logan_retcode_t ni_logan_get_memory_offset(ni_logan_session_context_t *p_ctx, const ni_logan_hwframe_surface_t *hwdesc, unsigned int *p_offset, unsigned int hwaddress)
Get an address offset from a hw descriptor.
int ni_logan_hwupload_session_write(ni_logan_session_context_t *p_ctx, ni_logan_frame_t *p_frame)
Send a YUV to hardware, hardware will store it.
int ni_logan_encoder_session_query(ni_logan_session_context_t *p_ctx)
Query current encoder status.
int ni_logan_decoder_session_write(ni_logan_session_context_t *p_ctx, ni_logan_packet_t *p_packet)
Send a video p_packet to decoder.
ni_logan_retcode_t ni_logan_clear_instance_buf(ni_logan_hwframe_surface_t *surface, ni_device_handle_t device_handle, ni_event_handle_t event_handle)
clear a particular xcoder instance buffer/data The device handle is got from decoder or uploader,...
ni_logan_retcode_t ni_logan_encoder_session_open(ni_logan_session_context_t *p_ctx)
Open a xcoder encoder instance.
ni_logan_retcode_t ni_logan_encoder_session_flush(ni_logan_session_context_t *p_ctx)
Flush encoder output.
int ni_logan_hwdownload_session_read(ni_logan_session_context_t *p_ctx, ni_logan_frame_t *p_frame, ni_logan_hwframe_surface_t *hwdesc)
Retrieve a YUV through HW descriptor from decoder.
void ni_logan_populate_serial_number(ni_logan_serial_num_t *p_serial_num, void *p_data)
Get Card Serial Number from received Nvme Indentify info.
int ni_logan_hwupload_session_read_hwdesc(ni_logan_session_context_t *p_ctx, ni_logan_hwframe_surface_t *hwdesc, unsigned int *hwaddress)
Retrieve a HW descriptor of uploaded frame The HW descriptor will contain the YUV frame index,...
ni_logan_retcode_t ni_logan_dump_logs(ni_logan_session_context_t *p_ctx, void *p_data, bool gen_log_file)
Dump firmware logs.
ni_logan_retcode_t ni_logan_hwupload_init_framepool(ni_logan_session_context_t *p_ctx, uint32_t pool_size, uint32_t p2p_pool)
Setup framepool for hwupload. Uses decoder framepool.
ni_logan_retcode_t ni_logan_decoder_session_copy_internal(ni_logan_session_context_t *src_p_ctx, ni_logan_session_context_t *dst_p_ctx)
Copy a xcoder decoder card info and create worker thread.
void ni_logan_change_priority(void)
Set up schedule priority. First try to run with RR mode. If fails, try to set nice value....
void * ni_logan_session_keep_alive_thread(void *arguments)
decoder keep alive thread function triggers every 1 second
ni_logan_retcode_t ni_logan_decoder_session_close(ni_logan_session_context_t *p_ctx, int eos_recieved)
Close a xcoder decoder instance.
void ni_logan_populate_device_capability_struct(ni_logan_device_capability_t *p_cap, void *p_data)
Get info from received xcoder capability.
ni_logan_retcode_t ni_logan_decoder_session_flush_buffers(ni_logan_session_context_t *p_ctx)
Flush decoder output.
ni_logan_retcode_t ni_logan_decoder_session_flush(ni_logan_session_context_t *p_ctx)
Flush decoder output.
ni_logan_retcode_t ni_logan_decoder_session_open(ni_logan_session_context_t *p_ctx)
Open a xcoder decoder instance.
ni_logan_retcode_t ni_logan_uploader_session_open(ni_logan_session_context_t *p_ctx)
Open a xcoder uploader instance.
int ni_logan_decoder_session_read(ni_logan_session_context_t *p_ctx, ni_logan_frame_t *p_frame)
Retrieve a YUV p_frame from decoder.
int ni_logan_encoder_session_write(ni_logan_session_context_t *p_ctx, ni_logan_frame_t *p_frame)
Send a YUV p_frame to encoder.
ni_logan_retcode_t ni_logan_decoder_session_read_desc(ni_logan_session_context_t *p_ctx, ni_logan_frame_t *p_frame)
Retrieve a hw desc p_frame from decoder When yuvbypass enabled, this is used for decoder to read hard...
Private definitions used by main ni_device_api_logan file.
@ GOP_PRESET_IDX_CUSTOM
@ GOP_PRESET_IDX_IBPBP
@ GOP_PRESET_IDX_IBBBB
@ GOP_PRESET_IDX_RA_IB
@ GOP_PRESET_IDX_IPPPP
@ GOP_PRESET_IDX_ALL_I
@ GOP_PRESET_IDX_IBBBP
@ GOP_PRESET_IDX_IPP
@ GOP_PRESET_IDX_IBBB
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_DEBUG
Definition: ni_log_logan.h:66
@ 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
Definitions related to NETINT P2P kernel driver interface.
#define NETINT_LOGAN_IOCTL_SIGNAL_RFENCE
#define NETINT_LOGAN_IOCTL_ISSUE_REQ
#define NETINT_LOGAN_IOCTL_EXPORT_DMABUF
#define NETINT_LOGAN_IOCTL_ATTACH_RFENCE
@ NI_DMABUF_WRITE_TO_DEVICE
int32_t ni_logan_nvme_send_read_cmd(ni_device_handle_t handle, ni_event_handle_t event_handle, void *p_data, uint32_t data_len, uint32_t lba)
Compose a io read command.
Definitions related to working with NI T-408 over NVME interface.
#define NI_LOGAN_NVME_IDENTITY_CMD_DATA_SZ
Definition: ni_nvme_logan.h:42
#define IDENTIFY_DEVICE_R
uint32_t ni_logan_nvme_result_t
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...
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_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_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_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_unlock(int device_type, ni_lock_handle_t lock)
unlock a file lock
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_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.
Private definitions related to resource management of NI T-408 devices.
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.
int32_t ni_logan_posix_memalign(void **pp_memptr, size_t alignment, size_t size)
int32_t ni_logan_atobool(const char *p_str, bool *b_error)
Convert string to boolean.
int32_t ni_logan_parse_name(const char *arg, const char *const *names, bool *b_error)
Parse name.
void ni_logan_get_hw_yuv420p_dim(int width, int height, int bit_depth_factor, int is_h264, int plane_stride[NI_LOGAN_MAX_NUM_DATA_POINTERS], int plane_height[NI_LOGAN_MAX_NUM_DATA_POINTERS])
Get dimension information of Netint HW YUV420p frame to be sent to encoder for encoding....
void ni_logan_usleep(int64_t usec)
void ni_logan_buf_pool_return_buffer(ni_logan_buf_t *buf, ni_logan_buf_pool_t *p_buffer_pool)
return a used memory buffer to the pool
ni_logan_buf_t * ni_logan_buf_pool_get_buffer(ni_logan_buf_pool_t *p_buffer_pool)
get a free memory buffer from the pool
Exported utility routines definition.
#define ni_logan_aligned_free(p_memptr)
ni_logan_retcode_t err
const char * str
ni_aux_data_type_t type
struct _ni_logan_buf_pool_t * pool
ni_logan_gop_params_t pic_param[NI_LOGAN_MAX_GOP_NUM]
ni_logan_decoder_input_params_t dec_input_params
ni_logan_device_info_t * p_device_info
char dev_name[NI_LOGAN_MAX_DEVICE_NAME_LEN]
char blk_name[NI_LOGAN_MAX_DEVICE_NAME_LEN]
ni_logan_device_queue_t * p_device_queue
int32_t decoders[LOGAN_MAX_DEVICE_CNT]
int32_t encoders[LOGAN_MAX_DEVICE_CNT]
struct _ni_logan_encoder_input_params::@3 rc
ni_logan_custom_gop_params_t custom_gop_params
ni_logan_encoder_input_params_t enc_input_params
ni_logan_frame_t * p_first_frame
ni_logan_buf_t * dec_buf
uint32_t data_len[NI_LOGAN_MAX_NUM_DATA_POINTERS]
ni_aux_data_t * aux_data[NI_MAX_NUM_AUX_DATA_PER_FRAME]
void * p_data[NI_LOGAN_MAX_NUM_DATA_POINTERS]
ni_logan_encoder_change_params_t * enc_change_params
ni_event_handle_t thread_event_handle
ni_logan_enc_avc_roi_custom_map_t * avc_roi_map
ni_device_handle_t sender_handle
ni_device_handle_t device_handle
ni_logan_lat_meas_q_t * frame_time_q
ni_logan_thread_arg_struct_t * keep_alive_thread_args
ni_logan_session_run_state_t session_run_state
char blk_xcoder_name[LOGAN_MAX_CHAR_IN_DEVICE_NAME]
ni_device_handle_t blk_io_handle
ni_logan_enc_hevc_roi_custom_map_t * hevc_roi_map
char dev_xcoder[LOGAN_MAX_CHAR_IN_DEVICE_NAME]
ni_region_of_interest_t * av_rois
ni_logan_all_custom_sei_t * pkt_custom_sei[NI_LOGAN_FIFO_SZ]
char dev_xcoder_name[LOGAN_MAX_CHAR_IN_DEVICE_NAME]
union _ni_logan_session_data_io::@4 data