libxcoder  3.5.1
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  }
2034 
2035  p_frame->data_len[0] = luma_size;
2036  p_frame->data_len[1] = chroma_b_size;
2037  p_frame->data_len[2] = chroma_r_size;
2038  p_frame->data_len[3] = 0; //for hwdesc
2039 
2040  p_frame->video_width = width_aligned;
2041  p_frame->video_height = height_aligned;
2042 
2043  ni_log(NI_LOG_TRACE, "%s: success: p_frame->buffer_size=%d\n",
2044  __FUNCTION__, p_frame->buffer_size);
2045 
2046  END:
2047 
2048  return retval;
2049 }
2050 
2051 /*!*****************************************************************************
2052  * \brief Allocate memory for the frame buffer for encoding based on given
2053  * parameters, taking into account pic line size and extra data.
2054  * Applicable to YUV420p AVFrame only. 8 or 10 bit/pixel.
2055  * Cb/Cr size matches that of Y.
2056  *
2057  * \param[in] p_frame Pointer to a caller allocated ni_logan_frame_t struct
2058  *
2059  * \param[in] video_width Width of the video frame
2060  * \param[in] video_height Height of the video frame
2061  * \param[in] linesize Picture line size
2062  * \param[in] alignment Allignment requirement
2063  * \param[in] extra_len Extra data size (incl. meta data)
2064  *
2065  * \return On success
2066  * NI_LOGAN_RETCODE_SUCCESS
2067  * On failure
2068  * NI_LOGAN_RETCODE_INVALID_PARAM
2069  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
2070  *****************************************************************************/
2072  int video_width,
2073  int video_height,
2074  int linesize[],
2075  int alignment,
2076  int extra_len,
2077  int factor)
2078 {
2079  void* p_buffer = NULL;
2080  int height_aligned = video_height;
2081  int retval = NI_LOGAN_RETCODE_SUCCESS;
2082 
2083  if (!p_frame || !linesize || linesize[0] <= 0 ||
2084  linesize[0] > NI_LOGAN_MAX_RESOLUTION_WIDTH * factor ||
2085  video_width > NI_LOGAN_MAX_RESOLUTION_WIDTH || video_width <= 0 ||
2086  video_height>NI_LOGAN_MAX_RESOLUTION_HEIGHT || video_height<=0)
2087  {
2088  ni_log(NI_LOG_TRACE, "ERROR: %s passed parameters are null!, return\n",
2089  __FUNCTION__);
2091  }
2092  // TBD height has to be 8-aligned; had a checking at codec opening, but
2093  // if still getting non-8-aligned here, that could only be the case of
2094  // resolution change mid-stream: device_handle it by making them 8-aligned
2095  height_aligned = ((video_height + 7) / 8) * 8;
2096 
2097  if (alignment)
2098  {
2099  height_aligned = ((video_height + 15) / 16) * 16;
2100  }
2101 
2102  if (height_aligned < NI_LOGAN_MIN_HEIGHT)
2103  {
2104  height_aligned = NI_LOGAN_MIN_HEIGHT;
2105  }
2106 
2107  ni_log(NI_LOG_TRACE, "%s: aligned=%dx%d orig=%dx%d linesize=%d/%d/%d "
2108  "extra_len=%d\n", __FUNCTION__, video_width, height_aligned,
2109  video_width, video_height, linesize[0], linesize[1], linesize[2],
2110  extra_len);
2111 
2112  int luma_size = linesize[0] * height_aligned;
2113  int chroma_b_size = luma_size / 4;
2114  int chroma_r_size = luma_size / 4;
2115  int buffer_size = luma_size + chroma_b_size + chroma_r_size + extra_len;
2116 
2117  buffer_size = ((buffer_size + (NI_LOGAN_MEM_PAGE_ALIGNMENT - 1)) / NI_LOGAN_MEM_PAGE_ALIGNMENT) *
2119 
2120  //Check if Need to free
2121  if (p_frame->buffer_size != buffer_size && p_frame->buffer_size > 0)
2122  {
2123  ni_log(NI_LOG_TRACE, "%s: free current p_frame, p_frame->buffer_size=%d\n",
2124  __FUNCTION__, p_frame->buffer_size);
2125  ni_logan_frame_buffer_free(p_frame);
2126  }
2127 
2128  //Check if need to realocate
2129  if (p_frame->buffer_size != buffer_size)
2130  {
2131 #ifndef XCODER_SIM_ENABLED
2132  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size))
2133  {
2134  ni_log(NI_LOG_ERROR, "ERROR %d: Cannot allocate p_frame buffer.\n",
2135  NI_ERRNO);
2137  LRETURN;
2138  }
2139 #else
2140  p_buffer = malloc(buffer_size);
2141  if (!p_buffer)
2142  {
2143  ni_log(NI_LOG_ERROR, "ERROR %d: Cannot allocate p_frame buffer.\n",
2144  NI_ERRNO);
2146  LRETURN;
2147  }
2148 #endif
2149  // init once after allocation
2150  memset(p_buffer, 0, buffer_size);
2151  p_frame->buffer_size = buffer_size;
2152  p_frame->p_buffer = p_buffer;
2153 
2154  ni_log(NI_LOG_TRACE, "%s: allocated new p_frame buffer\n", __FUNCTION__);
2155  }
2156  else
2157  {
2158  ni_log(NI_LOG_TRACE, "%s: reuse p_frame buffer\n", __FUNCTION__);
2159  }
2160 
2161  p_frame->p_data[0] = (uint8_t*)p_frame->p_buffer;
2162  p_frame->p_data[1] = (uint8_t*)p_frame->p_data[0] + luma_size;
2163  p_frame->p_data[2] = (uint8_t*)p_frame->p_data[1] + chroma_b_size;
2164  p_frame->p_data[3] = (uint8_t*)p_frame->p_data[2] + chroma_r_size;
2165 
2166  p_frame->data_len[0] = luma_size;
2167  p_frame->data_len[1] = chroma_b_size;
2168  p_frame->data_len[2] = chroma_r_size;
2169  p_frame->data_len[3] = 0;//unused by hwdesc
2170 
2171  p_frame->video_width = video_width;
2172  p_frame->video_height = height_aligned;
2173 
2174  ni_log(NI_LOG_TRACE, "%s: success: p_frame->buffer_size=%d\n",
2175  __FUNCTION__, p_frame->buffer_size);
2176 
2177  END:
2178 
2179  if (NI_LOGAN_RETCODE_SUCCESS != retval)
2180  {
2181  ni_logan_aligned_free(p_buffer);
2182  }
2183 
2184  return retval;
2185 }
2186 
2187 /*!******************************************************************************
2188  * \brief Free frame buffer that was previously allocated with either
2189  * ni_logan_frame_buffer_alloc or ni_logan_encoder_frame_buffer_alloc
2190  *
2191  * \param[in] p_frame Pointer to a previously allocated ni_logan_frame_t struct
2192  *
2193  * \return On success NI_LOGAN_RETCODE_SUCCESS
2194  * On failure NI_LOGAN_RETCODE_INVALID_PARAM
2195  *******************************************************************************/
2197 {
2198  int i;
2200 
2201  ni_log(NI_LOG_TRACE, "%s: enter\n", __FUNCTION__);
2202 
2203  if (!p_frame)
2204  {
2205  ni_log(NI_LOG_TRACE, "WARN: %s(): p_frame is NULL\n", __FUNCTION__);
2206  LRETURN;
2207  }
2208 
2209  if (!p_frame->p_buffer)
2210  {
2211  ni_log(NI_LOG_TRACE, "WARN: %s(): already freed, nothing to free\n",
2212  __FUNCTION__);
2213  // made idempotent so that aux data of dummy frame can be freed
2214  }
2215 
2216  ni_logan_aligned_free(p_frame->p_buffer);
2217  p_frame->p_buffer = NULL;
2218 
2219  p_frame->buffer_size = 0;
2220  for (i = 0; i < NI_LOGAN_MAX_NUM_DATA_POINTERS; i++)
2221  {
2222  p_frame->data_len[i] = 0;
2223  p_frame->p_data[i] = NULL;
2224  }
2226 
2227  END:
2228 
2229  ni_log(NI_LOG_TRACE, "%s: exit\n", __FUNCTION__);
2230 
2231  return retval;
2232 }
2233 
2234 /*!*****************************************************************************
2235  * \brief Free decoder frame buffer that was previously allocated with
2236  * ni_logan_decoder_frame_buffer_alloc, returning memory to a buffer pool.
2237  *
2238  * \param[in] p_frame Pointer to a previously allocated ni_logan_frame_t struct
2239  *
2240  * \return On success NI_LOGAN_RETCODE_SUCCESS
2241  * On failure NI_LOGAN_RETCODE_INVALID_PARAM
2242  ******************************************************************************/
2244 {
2245  int i;
2247 
2248  ni_log(NI_LOG_TRACE, "%s: enter\n", __FUNCTION__);
2249 
2250  if (!p_frame)
2251  {
2252  ni_log(NI_LOG_TRACE, "WARN: %s(): p_frame is NULL\n", __FUNCTION__);
2254  LRETURN;
2255  }
2256 
2257  if (p_frame->dec_buf)
2258  {
2260  ni_log(NI_LOG_TRACE, "%s(): Mem buf returned ptr %p buf %p!\n",
2261  __FUNCTION__, p_frame->dec_buf->buf, p_frame->dec_buf);
2262  }
2263  else
2264  {
2265  ni_log(NI_LOG_TRACE, "%s(): NO mem buf returned !\n", __FUNCTION__);
2266  }
2267 
2268  p_frame->dec_buf = p_frame->p_buffer = NULL;
2269 
2270  p_frame->buffer_size = 0;
2271  for (i = 0; i < NI_LOGAN_MAX_NUM_DATA_POINTERS; i++)
2272  {
2273  p_frame->data_len[i] = 0;
2274  p_frame->p_data[i] = NULL;
2275  }
2277 
2278  END:
2279 
2280  ni_log(NI_LOG_TRACE, "%s: exit\n", __FUNCTION__);
2281 
2282  return retval;
2283 }
2284 
2285 /*!*****************************************************************************
2286  * \brief Return a memory buffer to memory buffer pool.
2287  *
2288  * \param[in] buf Buffer to be returned.
2289  * \param[in] p_buffer_pool Buffer pool to return buffer to.
2290  *
2291  * \return None
2292  ******************************************************************************/
2294 {
2295  ni_logan_buf_pool_return_buffer(buf, p_buffer_pool);
2296 }
2297 
2298 /*!******************************************************************************
2299  * \brief Allocate memory for the packet buffer based on provided packet size
2300  *
2301  * \param[in] p_packet Pointer to a caller allocated
2302  * ni_logan_packet_t struct
2303  * \param[in] packet_size Required allocation size
2304  *
2305  * \return On success
2306  * NI_LOGAN_RETCODE_SUCCESS
2307  * On failure
2308  * NI_LOGAN_RETCODE_INVALID_PARAM
2309  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
2310  *******************************************************************************/
2312 {
2313  void* p_buffer = NULL;
2314  int metadata_size = 0;
2315  int retval = NI_LOGAN_RETCODE_SUCCESS;
2316 
2317  metadata_size = NI_LOGAN_FW_META_DATA_SZ;
2318 
2319  int buffer_size = (((packet_size + metadata_size) / NI_LOGAN_MAX_PACKET_SZ) + 1) * NI_LOGAN_MAX_PACKET_SZ;
2320 
2321  ni_log(NI_LOG_TRACE, "%s: packet_size=%d\n",
2322  __FUNCTION__, packet_size + metadata_size);
2323 
2324  if (!p_packet || !packet_size)
2325  {
2326  ni_log(NI_LOG_TRACE, "ERROR: %s(): null pointer parameters passed\n",
2327  __FUNCTION__);
2329  }
2330 
2331  if (buffer_size % NI_LOGAN_MEM_PAGE_ALIGNMENT)
2332  {
2334  }
2335 
2336  if (p_packet->buffer_size == buffer_size)
2337  {
2338  p_packet->p_data = p_packet->p_buffer;
2339  ni_log(NI_LOG_TRACE, "%s(): reuse current p_packet buffer\n", __FUNCTION__);
2340  LRETURN; //Already allocated the exact size
2341  }
2342  else if (p_packet->buffer_size > 0)
2343  {
2344  ni_log(NI_LOG_TRACE, "%s(): free current p_packet buffer_size=%d\n",
2345  __FUNCTION__, p_packet->buffer_size);
2346  ni_logan_packet_buffer_free(p_packet);
2347  }
2348  ni_log(NI_LOG_TRACE, "%s(): Allocating p_frame buffer, buffer_size=%d\n",
2349  __FUNCTION__, buffer_size);
2350 #ifndef XCODER_SIM_ENABLED
2351  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size))
2352  {
2353  ni_log(NI_LOG_TRACE, "ERROR %d: %s() Cannot allocate p_frame buffer.\n",
2354  NI_ERRNO, __FUNCTION__);
2356  LRETURN;
2357  }
2358 #else
2359  p_buffer = malloc(buffer_size);
2360  if (p_buffer == NULL)
2361  {
2362  ni_log(NI_LOG_ERROR, "ERROR %d: %s(): Cannot allocate p_frame buffer.\n",
2363  NI_ERRNO, __FUNCTION__);
2365  LRETURN;
2366  }
2367 #endif
2368  memset(p_buffer, 0, buffer_size);
2369  p_packet->buffer_size = buffer_size;
2370  p_packet->p_buffer = p_buffer;
2371  p_packet->p_data = p_packet->p_buffer;
2372 
2373  END:
2374 
2375  if (NI_LOGAN_RETCODE_SUCCESS != retval)
2376  {
2377  ni_logan_aligned_free(p_buffer);
2378  }
2379 
2380  ni_log(NI_LOG_TRACE, "%s: exit: p_packet->buffer_size=%d\n",
2381  __FUNCTION__, p_packet->buffer_size);
2382 
2383  return retval;
2384 }
2385 
2386 /*!******************************************************************************
2387  * \brief Free packet buffer that was previously allocated with either
2388  * ni_logan_packet_buffer_alloc
2389  *
2390  * \param[in] p_packet Pointer to a previously allocated ni_logan_packet_t struct
2391  *
2392  * \return On success NI_LOGAN_RETCODE_SUCCESS
2393  * On failure NI_LOGAN_RETCODE_INVALID_PARAM
2394  *******************************************************************************/
2396 {
2398 
2399  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
2400 
2401  if (!p_packet)
2402  {
2403  ni_log(NI_LOG_TRACE, "ERROR: %s(): p_packet is NULL\n", __FUNCTION__);
2404  retval = NI_LOGAN_RETCODE_FAILURE;
2405  LRETURN;
2406  }
2407 
2408  if (!p_packet->p_buffer)
2409  {
2410  p_packet->data_len = 0;
2411  ni_log(NI_LOG_TRACE, "%s(): already freed nothing to free\n", __FUNCTION__);
2412  LRETURN;
2413  }
2414 
2415  ni_logan_aligned_free(p_packet->p_buffer);
2416  p_packet->p_buffer = NULL;
2417 
2418  p_packet->buffer_size = 0;
2419  p_packet->data_len = 0;
2420  p_packet->p_data = NULL;
2421 
2422  END:
2423 
2424  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
2425 
2426  return retval;
2427 }
2428 
2429 /*!******************************************************************************
2430  * \brief Copy video packet accounting for allighment
2431  *
2432  * \param[in] p_destination Destination to where to copy to
2433  * \param[in] p_source Source from where to copy from
2434  * \param[in] cur_size current size
2435  * \param[out] p_leftover Pointer to the data that was left over
2436  * \param[out] p_prev_size Size of the data leftover ??
2437  *
2438  * \return On success Total number of bytes that were copied
2439  * On failure NI_LOGAN_RETCODE_FAILURE
2440  *******************************************************************************/
2441 int ni_logan_packet_copy(void* p_destination,
2442  const void* const p_source,
2443  int cur_size,
2444  void* p_leftover,
2445  int* p_prev_size)
2446 {
2447  int copy_size = 0;
2448  int padding_size = 0;
2449  int prev_size = p_prev_size == NULL? 0 : *p_prev_size;
2450  int total_size = cur_size + prev_size;
2451  uint8_t* p_src = (uint8_t*)p_source;
2452  uint8_t* p_dst = (uint8_t*)p_destination;
2453  uint8_t* p_lftover = (uint8_t*)p_leftover;
2454 
2455  ni_log(NI_LOG_TRACE, "%s(): enter, cur_size=%d, copy_size=%d, prev_size=%d\n",
2456  __FUNCTION__, cur_size, copy_size, *p_prev_size);
2457 
2458  if (0 == cur_size && 0 == prev_size)
2459  {
2460  return copy_size;
2461  }
2462 
2463  if (((0 != cur_size) && (!p_source)) || (!p_destination) || (!p_leftover))
2464  {
2465  return NI_LOGAN_RETCODE_FAILURE;
2466  }
2467 
2469 
2470  if (copy_size > total_size)
2471  {
2472  padding_size = copy_size - total_size;
2473  }
2474 
2475  if (prev_size > 0)
2476  {
2477  memcpy(p_dst, p_lftover, prev_size);
2478  }
2479 
2480  p_dst += prev_size;
2481 
2482  memcpy(p_dst, p_src, cur_size);
2483 
2484  if (padding_size)
2485  {
2486  p_dst += cur_size;
2487  memset(p_dst, 0, padding_size);
2488  }
2489 
2490  if (p_prev_size)
2491  {
2492  *p_prev_size = 0;
2493  }
2494 
2495  ni_log(NI_LOG_TRACE, "%s(): exit, cur_size=%d, copy_size=%d, prev_size=%d\n",
2496  __FUNCTION__, cur_size, copy_size, *p_prev_size);
2497 
2498  return copy_size;
2499 }
2500 
2501 /*!******************************************************************************
2502  * \brief Initialize default encoder parameters
2503  *
2504  * \param[out] param Pointer to a user allocated ni_logan_encoder_params_t
2505  * to initialize to default parameters
2506  * \param[in] fps_num Frames per second
2507  * \param[in] fps_denom FPS denomination
2508  * \param[in] bit_rate bit rate
2509  * \param[in] width width
2510  * \param[in] height height
2511  *
2512  * \return On success
2513  * NI_LOGAN_RETCODE_SUCCESS
2514  * On failure
2515  * NI_LOGAN_RETCODE_FAILURE
2516  * NI_LOGAN_RETCODE_INVALID_PARAM
2517  *******************************************************************************/
2519  int fps_num,
2520  int fps_denom,
2521  long bit_rate,
2522  int width,
2523  int height)
2524 {
2525  ni_logan_encoder_input_params_t* p_enc = NULL;
2526  int i = 0;
2528 
2529  //Initialize p_param structure
2530  if (!p_param)
2531  {
2532  ni_log(NI_LOG_TRACE, "ERROR: %s(): null pointer parameters passed\n",
2533  __FUNCTION__);
2535  LRETURN;
2536  }
2537 
2538  ni_log(NI_LOG_TRACE, "%s()\n", __FUNCTION__);
2539 
2540  //Initialize p_param structure
2541  memset(p_param, 0, sizeof(ni_logan_encoder_params_t));
2542 
2543  p_enc = &p_param->enc_input_params;
2544 
2545  // Rev. B: unified for HEVC/H.264
2546  p_enc->profile = 0;
2547  p_enc->level_idc = 0;
2548  p_enc->high_tier = 0;
2549 
2551  p_enc->use_recommend_enc_params = 0; // TBD: remove this param from API as it is revA specific
2552 
2553  p_enc->rc.trans_rate = 0;
2554 
2555  p_enc->rc.enable_rate_control = 0;
2556  p_enc->rc.enable_cu_level_rate_control = 1;
2557  p_enc->rc.enable_hvs_qp = 0;
2558  p_enc->rc.enable_hvs_qp_scale = 1;
2559  p_enc->rc.hvs_qp_scale = 2;
2563  p_enc->rc.rc_init_delay = 3000;
2564 
2565  p_enc->roi_enable = 0;
2566 
2568  p_enc->long_term_ref_enable = 0;
2569 
2570  p_enc->lossless_enable = 0;
2571 
2572  p_enc->conf_win_top = 0;
2573  p_enc->conf_win_bottom = 0;
2574  p_enc->conf_win_left = 0;
2575  p_enc->conf_win_right = 0;
2576 
2577  p_enc->intra_period = 92;
2579  // TBD Rev. B: could be shared for HEVC and H.264 ?
2580  p_enc->rc.enable_mb_level_rc = 1;
2581 
2582  p_enc->decoding_refresh_type = 2;
2583  p_enc->slice_mode = 0;
2584  p_enc->slice_arg = 0;
2585 
2586  p_enc->rc.max_frame_size = 0;
2587  p_enc->rc.max_frame_ratio = 0;
2588 
2589  // Rev. B: H.264 only parameters.
2590  p_enc->enable_transform_8x8 = 1;
2591  p_enc->avc_slice_mode = 0;
2592  p_enc->avc_slice_arg = 0;
2593  p_enc->entropy_coding_mode = 1;
2594 
2595  p_enc->intra_mb_refresh_mode = 0;
2596  p_enc->intra_mb_refresh_arg = 0;
2597 
2599  for (i = 0; i < NI_LOGAN_MAX_GOP_NUM; i++)
2600  {
2602  p_enc->custom_gop_params.pic_param[i].poc_offset = 0;
2603  p_enc->custom_gop_params.pic_param[i].pic_qp = 0;
2604 
2605  // syed todo: check this initial value, added for T408 5
2607 
2608  p_enc->custom_gop_params.pic_param[i].ref_poc_L0 = 0;
2609  p_enc->custom_gop_params.pic_param[i].ref_poc_L1 = 0;
2610  p_enc->custom_gop_params.pic_param[i].temporal_id = 0;
2611  }
2613  p_enc->set_high_priority = 0;
2614 
2615  p_param->source_width = width;
2616  p_param->source_height = height;
2617 
2618  p_param->fps_number = fps_num;
2619  p_param->fps_denominator = fps_denom;
2620 
2621  if (p_param->fps_number && p_param->fps_denominator)
2622  {
2623  p_enc->frame_rate = p_param->fps_number / p_param->fps_denominator;
2624  }
2625  else
2626  {
2627  p_enc->frame_rate = 30;
2628  }
2629 
2630  p_param->bitrate = bit_rate;
2631  p_param->roi_demo_mode = 0;
2632  p_param->reconf_demo_mode = 0; // NETINT_INTERNAL - currently only for internal testing
2633  p_param->force_pic_qp_demo_mode = 0;
2634  p_param->force_frame_type = 0;
2635  p_param->hdrEnableVUI = 0;
2636  p_param->crf = -1;
2637  p_param->crfIpRatio = 0.0;
2638  p_param->crfPbRatio = 0.0;
2639  p_param->cbr = 0;
2640  p_param->cacheRoi = 0;
2641  p_param->ui32flushGop = 0;
2642  p_param->ui32minIntraRefreshCycle = 0;
2643  p_param->low_delay_mode = 0;
2644  p_param->padding = 1;
2645  p_param->generate_enc_hdrs = 0;
2646  p_param->use_low_delay_poc_type = 0;
2647  p_param->strict_timeout_mode = 0;
2648 
2650 
2651  p_param->dolby_vision_profile = 0;
2652  p_param->hrd_enable = 0;
2653  p_param->enable_aud = 0;
2654 
2655  p_param->color_primaries = 2; // default COL_PRI_UNSPECIFIED
2656  p_param->color_transfer_characteristic = 2; // default COL_TRC_UNSPECIFIED
2657  p_param->color_space = 2; // default COL_SPC_UNSPECIFIED
2658  p_param->sar_num = 0; // default SAR numerator 0
2659  p_param->sar_denom = 1; // default SAR denominator 1
2660  p_param->video_full_range_flag = -1;
2661 
2662  p_param->nb_save_pkt = 0;
2663 
2664  if (p_param->source_width > NI_LOGAN_PARAM_MAX_WIDTH)
2665  {
2667  LRETURN;
2668  }
2669  if (p_param->source_width < NI_LOGAN_PARAM_MIN_WIDTH)
2670  {
2672  LRETURN;
2673  }
2674 
2676  {
2678  LRETURN;
2679  }
2681  {
2683  LRETURN;
2684  }
2686  {
2688  LRETURN;
2689  }
2690 
2691  END:
2692 
2693  return retval;
2694 }
2695 
2697  int fps_num,
2698  int fps_denom,
2699  long bit_rate,
2700  int width,
2701  int height)
2702 {
2703  ni_logan_decoder_input_params_t* p_dec = NULL;
2704  int i = 0;
2706 
2707  //Initialize p_param structure
2708  if (!p_param)
2709  {
2710  ni_log(NI_LOG_TRACE, "%s(): null pointer parameter passed\n", __FUNCTION__);
2712  LRETURN;
2713  }
2714 
2715  ni_log(NI_LOG_TRACE, "%s\n", __FUNCTION__);
2716 
2717  //Initialize p_param structure
2718  memset(p_param, 0, sizeof(ni_logan_decoder_params_t));
2719 
2720  p_dec = &p_param->dec_input_params;
2721  p_dec->hwframes = 0;
2723  p_dec->set_high_priority = 0;
2724  p_dec->enable_user_data_sei_passthru = 0;
2725  p_dec->check_packet = 0;
2727  p_dec->lowdelay = 0;
2728  p_dec->enable_follow_iframe = 0;
2729  p_dec->enable_vui_info_passthru = 0;
2730 
2731  p_param->source_width = width;
2732  p_param->source_height = height;
2733  p_param->fps_number = fps_num;
2734  p_param->fps_denominator = fps_denom;
2735  p_param->bitrate = bit_rate;
2736 
2737  p_param->nb_save_pkt = 0;
2738 
2739  END:
2740 
2741  return retval;
2742 }
2743 
2744 // read demo reconfig data file and parse out reconfig key/values in the format:
2745 // key:val1,val2,val3,...val9 (max 9 values); only digit/:/,/newline is allowed
2746 ni_logan_retcode_t ni_logan_parse_reconf_file(const char* reconf_file, int hash_map[100][10])
2747 {
2748  char keyChar[10] = "";
2749  int key = 0;
2750  char valChar[10] = "";
2751  int val = 0;
2752  int valIdx = 1;
2753  int parseKey = 1;
2754  int idx = 0;
2755  int readc = EOF;
2756 
2757  if (!reconf_file)
2758  {
2759  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n",
2760  __FUNCTION__);
2762  }
2763 
2764  FILE *reconf = fopen(reconf_file, "r");
2765  if (!reconf)
2766  {
2767  ni_log(NI_LOG_ERROR, "ERROR %d: %s(): Cannot open reconfig_file: %s\n",
2768  NI_ERRNO, __FUNCTION__, reconf_file);
2769  return NI_LOGAN_RETCODE_FAILURE;
2770  }
2771 
2772  while ((readc = fgetc(reconf)) != EOF)
2773  {
2774  //parse lines
2775  if (isdigit(readc))
2776  {
2777  if (parseKey)
2778  {
2779  strncat(keyChar, (const char *)(&readc), 1);
2780  }
2781  else
2782  {
2783  strncat(valChar, (const char *)(&readc), 1);
2784  }
2785  }
2786  else if (readc == ':')
2787  {
2788  parseKey = 0;
2789  key = atoi(keyChar);
2790  hash_map[idx][0] = key;
2791  }
2792  else if (readc == ',')
2793  {
2794  val = atoi(valChar);
2795  hash_map[idx][valIdx] = val;
2796  valIdx++;
2797  memset(valChar, 0, 10);
2798  }
2799  else if (readc == '\n')
2800  {
2801  parseKey = 1;
2802  val = atoi (valChar);
2803  hash_map[idx][valIdx] = val;
2804  valIdx = 1;
2805  memset(keyChar,0,10);
2806  memset(valChar,0,10);
2807  idx ++;
2808  }
2809  else
2810  {
2811  ni_log(NI_LOG_TRACE, "error character %c in reconfig file. this may lead "
2812  "to mistaken reconfiguration values \n", readc);
2813  }
2814  }
2815 
2816  fclose(reconf);
2817 
2818  return NI_LOGAN_RETCODE_SUCCESS;
2819 }
2820 
2821 #undef atoi
2822 #undef atof
2823 #define atoi(p_str) ni_logan_atoi(p_str, &b_error)
2824 #define atof(p_str) ni_logan_atof(p_str, &b_error)
2825 #define atobool(p_str) (ni_logan_atobool(p_str, &b_error))
2826 /*!******************************************************************************
2827 * \brief Set value referenced by name in decoder parameters structure
2828 *
2829 * \param[in] p_params Pointer to a user allocated ni_logan_decoder_params_t
2830 * to find and set a particular parameter
2831 * \param[in] name String represented parameter name to search
2832 * \param[in] value Parameter value to set
2833 *
2834 * \return On success
2835 * NI_LOGAN_RETCODE_SUCCESS
2836 * On failure
2837 * NI_LOGAN_RETCODE_FAILURE
2838 * NI_LOGAN_RETCODE_INVALID_PARAM
2839 *******************************************************************************/
2841 {
2842  bool b_error = false;
2843  bool bNameWasBool = false;
2844  bool bValueWasNull = !value;
2846  char nameBuf[64] = { 0 };
2847  const char delim[2] = ",";
2848  const char xdelim[2] = "x";
2849 
2850  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
2851 
2852  if (!p_params)
2853  {
2854  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n", __FUNCTION__);
2856  }
2857 
2858  if (!name)
2859  {
2860  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n", __FUNCTION__);
2862  }
2863 
2864  // skip -- prefix if provided
2865  if (name[0] == '-' && name[1] == '-')
2866  {
2867  name += 2;
2868  }
2869 
2870  // s/_/-/g
2871  if (strlen(name) + 1 < sizeof(nameBuf) && strchr(name, '_'))
2872  {
2873  char* c;
2874  strcpy(nameBuf, name);
2875  while ((c = strchr(nameBuf, '_')) != 0)
2876  {
2877  *c = '-';
2878  }
2879 
2880  name = nameBuf;
2881  }
2882 
2883  if (!strncmp(name, "no-", 3))
2884  {
2885  name += 3;
2886  value = !value || ni_logan_atobool(value, &b_error) ? "false" : "true";
2887  }
2888  else if (!strncmp(name, "no", 2))
2889  {
2890  name += 2;
2891  value = !value || ni_logan_atobool(value, &b_error) ? "false" : "true";
2892  }
2893  else if (!value)
2894  {
2895  value = "true";
2896  }
2897  else if (value[0] == '=')
2898  {
2899  value++;
2900  }
2901 
2902 #ifdef _MSC_VER
2903 #define OPT(STR) else if (!_stricmp(name, STR))
2904 #define OPT2(STR1, STR2) else if (!_stricmp(name, STR1) || !_stricmp(name, STR2))
2905 #else
2906 #define OPT(STR) else if (!strcasecmp(name, STR))
2907 #define OPT2(STR1, STR2) else if (!strcasecmp(name, STR1) || !strcasecmp(name, STR2))
2908 #endif
2909  if (0)
2910  ;
2912  {
2913  if (!strncmp(value, "hw", 2)){
2914  p_dec->hwframes = 1;
2915  }
2916  else if (!strncmp(value, "sw", 2)) {
2917  p_dec->hwframes = 0;
2918  }
2919  else{
2920  ni_log(NI_LOG_ERROR, "ERROR: %s(): out can only be <hw,sw> got %s\n",
2921  __FUNCTION__, value);
2923  }
2924  }
2926  {
2927  if(atoi(value) != NI_LOGAN_MIN_PRIORITY &&
2928  atoi(value) != NI_LOGAN_MAX_PRIORITY)
2929  {
2931  }
2932  p_dec->set_high_priority = atoi(value);
2933  }
2935  {
2936  if(atoi(value) < NI_LOGAN_MIN_KEEP_ALIVE_TIMEOUT ||
2938  {
2940  }
2941  p_dec->keep_alive_timeout = atoi(value);
2942  }
2944  {
2947  {
2949  }
2950  p_dec->enable_user_data_sei_passthru = atoi(value);
2951  }
2953  {
2954  if(atoi(value) != NI_LOGAN_ENABLE_CHECK_PACKET &&
2956  {
2958  }
2959  p_dec->check_packet = atoi(value);
2960  }
2962  {
2963  if(atoi(value) < NI_LOGAN_MIN_CUSTOM_SEI_PASSTHRU ||
2965  {
2967  }
2968  p_dec->custom_sei_passthru = atoi(value);
2969  }
2971  {
2972  p_dec->lowdelay = atoi(value);
2973  }
2975  {
2976  p_params->nb_save_pkt = atoi(value);
2977  }
2979  {
2980  if (atoi(value) != 0 && atoi(value) != 1 && atoi(value) != 2)
2981  {
2983  }
2984  p_dec->low_delay_mode = atoi(value);
2985  }
2987  {
2988  if(atoi(value) != 0 && atoi(value) != 1)
2989  {
2991  }
2992  p_dec->enable_follow_iframe = atoi(value);
2993  }
2995  {
2996  if (atoi(value) != 0 && atoi(value) != 1)
2997  {
2998  ni_log(NI_LOG_ERROR, "Invalid %s: out of range\n", value);
3000  }
3001  p_dec->enable_vui_info_passthru = atoi(value);
3002  }
3003  else
3004  {
3006  }
3007 #undef OPT
3008 #undef atobool
3009 #undef atoi
3010 #undef atof
3011  b_error |= bValueWasNull && !bNameWasBool;
3012 
3013  ni_log(NI_LOG_TRACE, "ni_logan_decoder_params_set_value: exit, b_error=%d\n", b_error);
3014 
3016 }
3017 
3018 
3019 #undef atoi
3020 #undef atof
3021 #define atoi(p_str) ni_logan_atoi(p_str, &b_error)
3022 #define atof(p_str) ni_logan_atof(p_str, &b_error)
3023 #define atobool(p_str) (ni_logan_atobool(p_str, &b_error))
3024 
3025 static ni_logan_retcode_t ni_logan_check_level(int level, int codec_id)
3026 {
3027  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};
3028  const int l_levels_265[] = {10, 20, 21, 30, 31, 40, 41, 50, 51, 52, 60, 61, 62, 0};
3029  const int *l_levels = l_levels_264;
3030 
3031  if ( level == 0 )
3032  {
3033  return NI_LOGAN_RETCODE_SUCCESS;
3034  }
3035 
3036  if ( codec_id == NI_LOGAN_CODEC_FORMAT_H265 )
3037  {
3038  l_levels = l_levels_265;
3039  }
3040 
3041  while( *l_levels != 0 )
3042  {
3043  if ( *l_levels == level )
3044  {
3045  return NI_LOGAN_RETCODE_SUCCESS;
3046  }
3047 
3048  l_levels++;
3049  }
3050 
3051  return NI_LOGAN_RETCODE_FAILURE;
3052 }
3053 
3054 
3055 /*!******************************************************************************
3056  * \brief Set value referenced by name in encoder parameters structure
3057  *
3058  * \param[in] p_params Pointer to a user allocated ni_logan_encoder_params_t
3059  * to find and set a particular parameter
3060  * \param[in] name String represented parameter name to search
3061  * \param[in] value Parameter value to set
3062 *
3063  * \return On success
3064  * NI_LOGAN_RETCODE_SUCCESS
3065  * On failure
3066  * NI_LOGAN_RETCODE_FAILURE
3067  * NI_LOGAN_RETCODE_INVALID_PARAM
3068  *******************************************************************************/
3070  const char* name,
3071  const char* value,
3073 {
3074  bool b_error = false;
3075  bool bNameWasBool = false;
3076  bool bValueWasNull = !value;
3078  char nameBuf[64] = { 0 };
3079 
3080  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
3081 
3082  if (!p_params)
3083  {
3084  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n",
3085  __FUNCTION__);
3087  }
3088 
3089  if ( !name )
3090  {
3091  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n",
3092  __FUNCTION__);
3094  }
3095 
3096  // skip -- prefix if provided
3097  if (name[0] == '-' && name[1] == '-')
3098  {
3099  name += 2;
3100  }
3101 
3102  // s/_/-/g
3103  if (strlen(name) + 1 < sizeof(nameBuf) && strchr(name, '_'))
3104  {
3105  char* c;
3106  nameBuf[0] = '\0';
3107  strncat(nameBuf, name, strlen(name));
3108  while ((c = strchr(nameBuf, '_')) != 0)
3109  {
3110  *c = '-';
3111  }
3112 
3113  name = nameBuf;
3114  }
3115 
3116  if (!strncmp(name, "no-", 3))
3117  {
3118  name += 3;
3119  value = !value || ni_logan_atobool(value, &b_error) ? "false" : "true";
3120  }
3121  else if (!strncmp(name, "no", 2))
3122  {
3123  name += 2;
3124  value = !value || ni_logan_atobool(value, &b_error) ? "false" : "true";
3125  }
3126  else if (!value)
3127  {
3128  value = "true";
3129  }
3130  else if (value[0] == '=')
3131  {
3132  value++;
3133  }
3134 
3135 #ifdef _MSC_VER
3136 #define OPT(STR) else if (!_stricmp(name, STR))
3137 #define OPT2(STR1, STR2) else if (!_stricmp(name, STR1) || !_stricmp(name, STR2))
3138 #else
3139 #define OPT(STR) else if (!strcasecmp(name, STR))
3140 #define OPT2(STR1, STR2) else if (!strcasecmp(name, STR1) || !strcasecmp(name, STR2))
3141 #endif
3142 #define COMPARE(STR1, STR2, STR3) \
3143 if ((atoi(STR1) > STR2) || (atoi(STR1) < STR3)) \
3144 { \
3145  ni_log(NI_LOG_ERROR, "Invalid %s: out of range\n", name); \
3146  return NI_LOGAN_RETCODE_PARAM_ERROR_OOR; \
3147 }
3148 #define COMPARE_F(STR1, STR2, STR3) \
3149 if ((atof(STR1) > STR2) || (atof(STR1) < STR3)) \
3150 { \
3151  return NI_LOGAN_RETCODE_PARAM_ERROR_OOR; \
3152 }
3153 #define CHECK2VAL(STR, VAL1, VAL2) \
3154 if (atoi(STR) != VAL1 && atoi(STR) != VAL2) \
3155 { \
3156  ni_log(NI_LOG_ERROR, "Invalid %s: out of range\n", name); \
3157  return NI_LOGAN_RETCODE_PARAM_ERROR_OOR; \
3158 }
3159 
3160  if (0)
3161  ;
3163  {
3164  if (LOGAN_AV_CODEC_DEFAULT_BITRATE == p_params->bitrate)
3165  {
3166  if (atoi(value) > NI_LOGAN_MAX_BITRATE)
3167  {
3168  ni_log(NI_LOG_ERROR, "Invalid %s: too big\n", name);
3170  }
3171  if (atoi(value) < NI_LOGAN_MIN_BITRATE)
3172  {
3173  ni_log(NI_LOG_ERROR, "Invalid %s: too small\n", name);
3175  }
3176  p_params->bitrate = atoi(value);
3177  }
3178  }
3180  {
3181  p_params->reconf_demo_mode = atoi(value); // NETINT_INTERNAL - currently only for internal testing
3182  }
3184  {
3185  ni_logan_retcode_t retval = ni_logan_parse_reconf_file(value, p_params->reconf_hash);
3186  if (retval != NI_LOGAN_RETCODE_SUCCESS) // NETINT_INTERNAL - currently only for internal testing
3187  {
3188  return retval;
3189  }
3190  }
3192  {
3193  // NETINT_INTERNAL - currently only for internal testing
3194  CHECK2VAL(value, 1, 2)
3195  p_params->roi_demo_mode = atoi(value);
3196  }
3198  {
3199  p_params->low_delay_mode = atoi(value);
3200  }
3202  {
3203  p_params->padding = atoi(value);
3204  }
3206  {
3207  p_params->generate_enc_hdrs = atoi(value);
3208  }
3210  {
3211  p_params->use_low_delay_poc_type = atoi(value);
3212  }
3214  {
3215  p_params->force_frame_type = atoi(value);
3216  }
3218  {
3219  p_enc->profile = atoi(value);
3220  }
3222  {
3223  p_enc->level_idc = (int)(10 * strtof(value, NULL)); // if value is not digital number, it return 0
3224  if ( ( p_enc->level_idc== 0 && strcmp(value, "0") )||
3225  ( strlen(value) > 3 ) ||
3226  ( ni_logan_check_level(p_enc->level_idc,
3228  {
3229  b_error = true;
3230  }
3231  }
3233  {
3234  p_enc->high_tier = atobool(value);
3235  }
3237  {
3238  p_params->log = atoi(value);
3239  if (b_error)
3240  {
3241  b_error = false;
3242  p_params->log = ni_logan_parse_name(value, g_logan_xcoder_log_names, &b_error) - 1;
3243  }
3244  }
3246  {
3248  p_enc->gop_preset_index = atoi(value);
3249  }
3251  {
3253  p_enc->use_recommend_enc_params = atoi(value);
3254  }
3256  {
3258  p_enc->rc.enable_rate_control = atoi(value);
3259  }
3261  {
3263  p_enc->rc.enable_cu_level_rate_control = atoi(value);
3264  }
3266  {
3267  p_enc->rc.enable_hvs_qp = atoi(value);
3268  }
3270  {
3271  p_enc->rc.enable_hvs_qp_scale = atoi(value);
3272  }
3274  {
3275  p_enc->rc.hvs_qp_scale = atoi(value);
3276  }
3278  {
3280  p_enc->rc.min_qp = atoi(value);
3281  }
3283  {
3285  p_enc->rc.max_qp = atoi(value);
3286  }
3288  {
3290  p_enc->rc.max_delta_qp = atoi(value);
3291  }
3293  {
3294  p_enc->rc.rc_init_delay = atoi(value);
3295  }
3297  {
3298  p_enc->forced_header_enable = atoi(value);
3299  }
3301  {
3302  p_enc->roi_enable = atoi(value);
3303  }
3305  {
3306  p_enc->conf_win_top = atoi(value);
3307  }
3309  {
3310  p_enc->conf_win_bottom = atoi(value);
3311  }
3313  {
3314  p_enc->conf_win_left = atoi(value);
3315  }
3317  {
3318  p_enc->conf_win_right = atoi(value);
3319  }
3321  {
3323  p_enc->intra_period = atoi(value);
3324  }
3326  {
3327  if (atoi(value) > NI_LOGAN_MAX_BITRATE)
3328  {
3329  ni_log(NI_LOG_ERROR, "Invalid %s: too big\n", name);
3331  }
3332  if (atoi(value) < NI_LOGAN_MIN_BITRATE)
3333  {
3334  ni_log(NI_LOG_ERROR, "Invalid %s: too small\n", name);
3336  }
3337  p_enc->rc.trans_rate = atoi(value);
3338  }
3340  {
3341  if (atoi(value) <= 0 )
3342  {
3343  ni_log(NI_LOG_ERROR, "Error setting option %s to value 0\n", name);
3345  }
3346  p_params->fps_number = atoi(value);
3347  p_params->fps_denominator = 1;
3348  p_enc->frame_rate = p_params->fps_number;
3349  }
3351  {
3352  p_params->fps_denominator = atoi(value);
3353  if(p_params->fps_denominator == 0)
3354  {
3355  ni_log(NI_LOG_ERROR, "Error setting option %s to value 0\n", name);
3357  }
3358  p_enc->frame_rate = p_params->fps_number / p_params->fps_denominator;
3359  }
3361  {
3363  p_enc->rc.intra_qp = atoi(value);
3364  }
3366  {
3368  p_params->force_pic_qp_demo_mode = atoi(value);
3369  }
3371  {
3373  p_enc->decoding_refresh_type = atoi(value);
3374  }
3375 
3376  // only for HEVC
3378  {
3379 #ifdef _MSC_VER
3380  if (!_strnicmp(value, "ratio", 5))
3381 #else
3382  if (!strncasecmp(value, "ratio", 5))
3383 #endif
3384  {
3385  int i = 0;
3386  char value_buf[32] = {0};
3387  while( i < 32)
3388  {
3389  if((value[i+6]) == ']')
3390  {
3391  break;
3392  }
3393  else
3394  {
3395  value_buf[i] = value[i+6];
3396  i++;
3397  }
3398  }
3399  if(i == 32)
3400  {
3402  }
3403  if (atoi(value_buf) < 0)
3404  {
3406  }
3407 
3408  p_enc->rc.max_frame_ratio = atoi(value_buf);
3409  p_enc->rc.max_frame_size = 0;
3410  }
3411  else
3412  {
3413  if (atoi(value) < 0)
3414  {
3416  }
3417 
3418  p_enc->rc.max_frame_ratio = 0;
3419  p_enc->rc.max_frame_size = atoi(value);
3420  }
3421  }
3422  // only for HEVC
3424  {
3425 #ifdef _MSC_VER
3426  if (!_strnicmp(value, "ratio", 5))
3427 #else
3428  if (!strncasecmp(value, "ratio", 5))
3429 #endif
3430  {
3431  int i = 0;
3432  char value_buf[32] = {0};
3433  while( i < 32)
3434  {
3435  if((value[i+6]) == ']')
3436  {
3437  break;
3438  }
3439  else
3440  {
3441  value_buf[i] = value[i+6];
3442  i++;
3443  }
3444  }
3445  if(i == 32)
3446  {
3448  }
3449  if (atoi(value_buf) < 0)
3450  {
3452  }
3453 
3454  p_enc->rc.max_frame_ratio = atoi(value_buf);
3455  p_enc->rc.max_frame_size = 0;
3456  }
3457  else
3458  {
3459  if (atoi(value) < 0)
3460  {
3462  }
3463 
3464  p_enc->rc.max_frame_ratio = 0;
3465  p_enc->rc.max_frame_size = atoi(value) * 8;
3466  }
3467  }
3468 
3469 // Rev. B: H.264 only parameters.
3471  {
3472  p_enc->enable_transform_8x8 = atoi(value);
3473  }
3475  {
3476  CHECK2VAL(value, 0, 1)
3477  p_enc->avc_slice_mode = atoi(value);
3478  }
3480  {
3481  p_enc->avc_slice_arg = atoi(value);
3482  }
3484  {
3485  p_enc->entropy_coding_mode = atoi(value);
3486  }
3487 // Rev. B: shared between HEVC and H.264
3489  {
3490  CHECK2VAL(value, 0, 1)
3492  {
3493  p_enc->avc_slice_mode = atoi(value);
3494  }
3495  else
3496  {
3497  p_enc->slice_mode = atoi(value);
3498  }
3499  }
3501  {
3503  {
3504  p_enc->avc_slice_arg = atoi(value);
3505  }
3506  else
3507  {
3508  p_enc->slice_arg = atoi(value);
3509  }
3510  }
3512  {
3513  p_enc->intra_mb_refresh_mode = atoi(value);
3514  }
3516  {
3517  p_enc->intra_mb_refresh_arg = atoi(value);
3518  }
3520  {
3521  p_enc->intra_mb_refresh_mode = atoi(value);
3522  }
3524  {
3525  p_enc->intra_mb_refresh_arg = atoi(value);
3526  }
3527 // TBD Rev. B: could be shared for HEVC and H.264
3529  {
3530  p_enc->rc.enable_mb_level_rc = atoi(value);
3531  }
3533  {
3534  COMPARE(value, 255, 0)
3535  p_enc->preferred_transfer_characteristics = atoi(value);
3536  }
3538  {
3539  CHECK2VAL(value, 0, 5)
3540  p_params->dolby_vision_profile = atoi(value);
3541  }
3543  {
3544  CHECK2VAL(value, 0, 1)
3545  p_params->hrd_enable = atoi(value);
3546  }
3548  {
3549  CHECK2VAL(value, 0, 1)
3550  p_params->enable_aud = atoi(value);
3551  }
3553  {
3554  char *pTemp;
3555  pTemp = strchr(value, '.');
3556  if(pTemp != NULL)
3557  {
3558  if(strlen(pTemp) > 3)
3559  {
3560  ni_log(NI_LOG_ERROR, "ERROR: CRF QP only supports two bit fraction\n" );
3562  }
3563  }
3564 
3566  p_params->crf = (float)atof(value);
3567  }
3569  {
3570  char *pTemp;
3571  pTemp = strchr(value, '.');
3572  if(pTemp != NULL)
3573  {
3574  if(strlen(pTemp) > 3)
3575  {
3576  ni_log(NI_LOG_ERROR, "ERROR: CRF ip ratio only supports two bit fraction\n" );
3578  }
3579  }
3580 
3581  COMPARE_F(value, 15.99, 0);
3582  p_params->crfIpRatio = (float)atof(value);
3583  }
3585  {
3586  char *pTemp;
3587  pTemp = strchr(value, '.');
3588  if(pTemp != NULL)
3589  {
3590  if(strlen(pTemp) > 3)
3591  {
3592  ni_log(NI_LOG_ERROR, "ERROR: CRF pb ratio only supports two bit fraction\n" );
3594  }
3595  }
3596 
3597  COMPARE_F(value, 15.99, 0);
3598  p_params->crfPbRatio = (float)atof(value);
3599  }
3601  {
3602  CHECK2VAL(value, 0, 1)
3603  p_params->cbr = atoi(value);
3604  }
3606  {
3607  CHECK2VAL(value, 0, 1)
3608  p_params->cacheRoi = atoi(value);
3609  }
3611  {
3612  CHECK2VAL(value, 0, 1)
3613  p_params->ui32flushGop = atoi(value);
3614  }
3616  {
3618  p_params->ui32minIntraRefreshCycle = atoi(value);
3619  }
3621  {
3622  CHECK2VAL(value, 0, 1)
3623  p_enc->long_term_ref_enable = atoi(value);
3624  }
3626  {
3627  p_params->strict_timeout_mode = atoi(value);
3628  }
3630  {
3631  CHECK2VAL(value, 0, 1)
3632  p_enc->lossless_enable = atoi(value);
3633  }
3635  {
3636  COMPARE(value, 22, 0)
3637  p_params->color_primaries = atoi(value);
3638  }
3640  {
3641  COMPARE(value, 18, 0)
3642  p_params->color_transfer_characteristic = atoi(value);
3643  }
3645  {
3646  COMPARE(value, 14, 0)
3647  p_params->color_space = atoi(value);
3648  }
3650  {
3651  p_params->sar_num = atoi(value);
3652  }
3654  {
3655  p_params->sar_denom = atoi(value);
3656  }
3658  {
3659  p_params->video_full_range_flag = atoi(value);
3660  }
3662  {
3663  if (atoi(value) != 0 && atoi(value) != 1)
3664  {
3665  ni_log(NI_LOG_ERROR, "Invalid %s: out of range\n", name);
3667  }
3668  p_params->enable_vfr = atoi(value);
3669  }
3671  {
3672  if (atoi(value) != 0 && atoi(value) != 1)
3673  {
3674  ni_log(NI_LOG_ERROR, "Invalid %s: out of range\n", name);
3676  }
3677  p_params->enable_explicit_rpl = atoi(value);
3678  }
3680  {
3681  if (atoi(value) != 0 && atoi(value) != 1)
3682  {
3683  ni_log(NI_LOG_ERROR, "Invalid %s: out of range\n", name);
3685  }
3686  p_params->disable_timing_info = atoi(value);
3687  }
3689  {
3691  p_enc->set_high_priority = atoi(value);
3692  }
3694  {
3696  p_enc->keep_alive_timeout = atoi(value);
3697  }
3699  {
3700  CHECK2VAL(value, 0, 1)
3701  p_params->intra_refresh_reset = atoi(value);
3702  }
3704  {
3705  if (atoi(value) < -12 || atoi(value) > 12)
3706  {
3708  }
3709  p_params->chromaQpOffset = atoi(value);
3710  }
3711  else
3712  {
3713  ni_log(NI_LOG_ERROR, "Unknown option: %s.\n", name);
3715  }
3716 
3717 
3718 #undef OPT
3719 #undef atobool
3720 #undef atoi
3721 #undef atof
3722 
3723  b_error |= bValueWasNull && !bNameWasBool;
3724  if (b_error)
3725  {
3726  ni_log(NI_LOG_ERROR, "Invalid value for %s: %s.\n", name, value);
3728  }
3729 
3730  ni_log(NI_LOG_TRACE, "%s: exit, b_error=%d\n", __FUNCTION__, b_error);
3731 
3732  return NI_LOGAN_RETCODE_SUCCESS;
3733 }
3734 
3735 /*!*****************************************************************************
3736 * \brief Validate relationship of some params in encoder parameters structure
3737 *
3738 * \param[in] p_params Pointer to a user allocated ni_logan_encoder_params_t
3739 * \param[in] codec encoding codec
3740 *
3741 * \return On success
3742 * NI_LOGAN_RETCODE_SUCCESS
3743 * On failure
3744 * NI_LOGAN_RETCODE_FAILURE
3745 * NI_LOGAN_RETCODE_PARAM_ERROR_OOR and other error rc
3746 *******************************************************************************/
3749 {
3751 
3752  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
3753 
3754  if (p_enc->rc.min_qp > p_enc->rc.max_qp)
3755  {
3756  ni_log(NI_LOG_ERROR, "MinQP(%d) > MaxQP(%d)\n", p_enc->rc.min_qp,
3757  p_enc->rc.max_qp);
3759  }
3760 
3761  if (p_enc->lossless_enable)
3762  {
3763  if (NI_LOGAN_CODEC_FORMAT_H264 == codec)
3764  {
3765  ni_log(NI_LOG_ERROR, "losslessEnable is not valid for H.264\n");
3767  }
3768 
3769  if (p_enc->rc.enable_rate_control || p_enc->roi_enable)
3770  {
3771  ni_log(NI_LOG_ERROR, "losslessEnable can not be enabled if RcEnable "
3772  "or roiEnable is enabled\n");
3774  }
3775  }
3776 
3777  ni_log(NI_LOG_TRACE, "%s: exit\n", __FUNCTION__);
3778 
3779  return NI_LOGAN_RETCODE_SUCCESS;
3780 }
3781 
3782 
3783 
3784 #undef atoi
3785 #undef atof
3786 #define atoi(p_str) ni_logan_atoi(p_str, &b_error)
3787 #define atof(p_str) ni_logan_atof(p_str, &b_error)
3788 #define atobool(p_str) (ni_logan_atobool(p_str, &b_error))
3789 
3790 /*!******************************************************************************
3791  * \brief Set got parameter value referenced by name in encoder parameters structure
3792  *
3793  * \param[in] p_params Pointer to a user allocated ni_logan_encoder_params_t
3794  * to find and set a particular parameter
3795  * \param[in] name String represented parameter name to search
3796  * \param[in] value Parameter value to set
3797 *
3798  * \return On success
3799  * NI_LOGAN_RETCODE_SUCCESS
3800  * On failure
3801  * NI_LOGAN_RETCODE_FAILURE
3802  * NI_LOGAN_RETCODE_INVALID_PARAM
3803  *******************************************************************************/
3805  const char* name,
3806  const char* value)
3807 {
3808  bool b_error = false;
3809  bool bNameWasBool = false;
3810  bool bValueWasNull = !value;
3813  char nameBuf[64] = { 0 };
3814 
3815  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
3816 
3817  if (!p_params || !name)
3818  {
3819  ni_log(NI_LOG_ERROR, "Unknown option: %s.\n", name);
3820  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n",
3821  __FUNCTION__);
3823  }
3824 
3825  // skip -- prefix if provided
3826  if ((name[0] == '-') && (name[1] == '-'))
3827  {
3828  name += 2;
3829  }
3830 
3831  // s/_/-/g
3832  if (strlen(name) + 1 < sizeof(nameBuf) && strchr(name, '_'))
3833  {
3834  char* c;
3835  nameBuf[0] = '\0';
3836  strncat(nameBuf, name, strlen(name));
3837  while ((c = strchr(nameBuf, '_')) != 0)
3838  {
3839  *c = '-';
3840  }
3841 
3842  name = nameBuf;
3843  }
3844 
3845  if (!strncmp(name, "no-", 3))
3846  {
3847  name += 3;
3848  value = !value || ni_logan_atobool(value, &b_error) ? "false" : "true";
3849  }
3850  else if (!strncmp(name, "no", 2))
3851  {
3852  name += 2;
3853  value = !value || ni_logan_atobool(value, &b_error) ? "false" : "true";
3854  }
3855  else if (!value)
3856  {
3857  value = "true";
3858  }
3859  else if (value[0] == '=')
3860  {
3861  value++;
3862  }
3863 
3864 #ifdef _MSC_VER
3865 #define OPT(STR) else if (!_stricmp(name, STR))
3866 #else
3867 #define OPT(STR) else if (!strcasecmp(name, STR))
3868 #endif
3869  if (0)
3870  ;
3872  {
3873  if (atoi(value) > NI_LOGAN_MAX_GOP_SIZE)
3874  {
3875  ni_log(NI_LOG_ERROR, "Invalid custom GOP parameters: %s too big\n", name);
3877  }
3878  if (atoi(value) < NI_LOGAN_MIN_GOP_SIZE)
3879  {
3880  ni_log(NI_LOG_ERROR, "Invalid custom GOP parameters: %s too small\n", name);
3882  }
3883  p_gop->custom_gop_size = atoi(value);
3884  }
3885 
3887  {
3888  p_gop->pic_param[0].pic_type = atoi(value);
3889  }
3891  {
3892  p_gop->pic_param[0].poc_offset = atoi(value);
3893  }
3895  {
3897  p_gop->pic_param[0].pic_qp = atoi(value);
3898  }
3900  {
3901  p_gop->pic_param[0].num_ref_pic_L0 = atoi(value);
3902  }
3904  {
3905  p_gop->pic_param[0].ref_poc_L0 = atoi(value);
3906  }
3908  {
3909  p_gop->pic_param[0].ref_poc_L1 = atoi(value);
3910  }
3912  {
3913  p_gop->pic_param[0].temporal_id = atoi(value);
3914  }
3915 
3917  {
3918  p_gop->pic_param[1].pic_type = atoi(value);
3919  }
3921  {
3922  p_gop->pic_param[1].poc_offset = atoi(value);
3923  }
3925  {
3927  p_gop->pic_param[1].pic_qp = atoi(value);
3928  }
3930  {
3931  p_gop->pic_param[1].num_ref_pic_L0 = atoi(value);
3932  }
3934  {
3935  p_gop->pic_param[1].ref_poc_L0 = atoi(value);
3936  }
3938  {
3939  p_gop->pic_param[1].ref_poc_L1 = atoi(value);
3940  }
3942  {
3943  p_gop->pic_param[1].temporal_id = atoi(value);
3944  }
3945 
3947  {
3948  p_gop->pic_param[2].pic_type = atoi(value);
3949  }
3951  {
3952  p_gop->pic_param[2].poc_offset = atoi(value);
3953  }
3955  {
3957  p_gop->pic_param[2].pic_qp = atoi(value);
3958  }
3960  {
3961  p_gop->pic_param[2].num_ref_pic_L0 = atoi(value);
3962  }
3964  {
3965  p_gop->pic_param[2].ref_poc_L0 = atoi(value);
3966  }
3968  {
3969  p_gop->pic_param[2].ref_poc_L1 = atoi(value);
3970  }
3972  {
3973  p_gop->pic_param[2].temporal_id = atoi(value);
3974  }
3975 
3977  {
3978  p_gop->pic_param[3].pic_type = atoi(value);
3979  }
3981  {
3982  p_gop->pic_param[3].poc_offset = atoi(value);
3983  }
3985  {
3987  p_gop->pic_param[3].pic_qp = atoi(value);
3988  }
3990  {
3991  p_gop->pic_param[3].num_ref_pic_L0 = atoi(value);
3992  }
3994  {
3995  p_gop->pic_param[3].ref_poc_L0 = atoi(value);
3996  }
3998  {
3999  p_gop->pic_param[3].ref_poc_L1 = atoi(value);
4000  }
4002  {
4003  p_gop->pic_param[3].temporal_id = atoi(value);
4004  }
4005 
4007  {
4008  p_gop->pic_param[4].pic_type = atoi(value);
4009  }
4011  {
4012  p_gop->pic_param[4].poc_offset = atoi(value);
4013  }
4015  {
4017  p_gop->pic_param[4].pic_qp = atoi(value);
4018  }
4020  {
4021  p_gop->pic_param[4].num_ref_pic_L0 = atoi(value);
4022  }
4024  {
4025  p_gop->pic_param[4].ref_poc_L0 = atoi(value);
4026  }
4028  {
4029  p_gop->pic_param[4].ref_poc_L1 = atoi(value);
4030  }
4032  {
4033  p_gop->pic_param[4].temporal_id = atoi(value);
4034  }
4035 
4037  {
4038  p_gop->pic_param[5].pic_type = atoi(value);
4039  }
4041  {
4042  p_gop->pic_param[5].poc_offset = atoi(value);
4043  }
4045  {
4047  p_gop->pic_param[5].pic_qp = atoi(value);
4048  }
4050  {
4051  p_gop->pic_param[5].num_ref_pic_L0 = atoi(value);
4052  }
4054  {
4055  p_gop->pic_param[5].ref_poc_L0 = atoi(value);
4056  }
4058  {
4059  p_gop->pic_param[5].ref_poc_L1 = atoi(value);
4060  }
4062  {
4063  p_gop->pic_param[5].temporal_id = atoi(value);
4064  }
4065 
4067  {
4068  p_gop->pic_param[6].pic_type = atoi(value);
4069  }
4071  {
4072  p_gop->pic_param[6].poc_offset = atoi(value);
4073  }
4075  {
4077  p_gop->pic_param[6].pic_qp = atoi(value);
4078  }
4080  {
4081  p_gop->pic_param[6].num_ref_pic_L0 = atoi(value);
4082  }
4084  {
4085  p_gop->pic_param[6].ref_poc_L0 = atoi(value);
4086  }
4088  {
4089  p_gop->pic_param[6].ref_poc_L1 = atoi(value);
4090  }
4092  {
4093  p_gop->pic_param[6].temporal_id = atoi(value);
4094  }
4095 
4097  {
4098  p_gop->pic_param[7].pic_type = atoi(value);
4099  }
4101  {
4102  p_gop->pic_param[7].poc_offset = atoi(value);
4103  }
4105  {
4107  p_gop->pic_param[7].pic_qp = atoi(value);
4108  }
4110  {
4111  p_gop->pic_param[7].num_ref_pic_L0 = atoi(value);
4112  }
4114  {
4115  p_gop->pic_param[7].ref_poc_L0 = atoi(value);
4116  }
4118  {
4119  p_gop->pic_param[7].ref_poc_L1 = atoi(value);
4120  }
4122  {
4123  p_gop->pic_param[7].temporal_id = atoi(value);
4124  }
4125  else
4126  {
4127  ni_log(NI_LOG_ERROR, "Unknown option: %s.\n", name);
4128  ni_log(NI_LOG_TRACE, "%s(): Invalid parameter name passed\n", __FUNCTION__);
4130  }
4131 
4132 #undef OPT
4133 #undef atobool
4134 #undef atoi
4135 #undef atof
4136 
4137  b_error |= bValueWasNull && !bNameWasBool;
4138  if (b_error)
4139  {
4140  ni_log(NI_LOG_ERROR, "Invalid value for GOP param %s: %s.\n", name, value);
4142  }
4143 
4144  ni_log(NI_LOG_TRACE, "%s(): exit, b_error=%d\n", __FUNCTION__, b_error);
4145 
4146  return NI_LOGAN_RETCODE_SUCCESS;
4147 }
4148 
4149 /*!*****************************************************************************
4150  * \brief Get GOP's max number of reorder frames
4151  *
4152  * \param[in] p_params Pointer to a user allocated ni_logan_encoder_params_t
4153  *
4154  * \return max number of reorder frames of the GOP, -1 on error
4155  ******************************************************************************/
4157 {
4158  int gopPreset = p_params->enc_input_params.gop_preset_index;
4159  int reorder = 0;
4160  int i;
4161  ni_logan_encoder_input_params_t* p_enc = NULL;
4162 
4163  if (! p_params)
4164  {
4165  ni_log(NI_LOG_ERROR, "%s: NULL input!\n", __FUNCTION__);
4166  return -1;
4167  }
4168  p_enc = &p_params->enc_input_params;
4169 
4170  // low delay gopPreset (1, 2, 3, 6, 7, 9) has reorder of 0
4171  if (GOP_PRESET_IDX_ALL_I == gopPreset || GOP_PRESET_IDX_IPP == gopPreset ||
4172  GOP_PRESET_IDX_IBBB == gopPreset || GOP_PRESET_IDX_IPPPP == gopPreset ||
4173  GOP_PRESET_IDX_IBBBB == gopPreset || GOP_PRESET_IDX_SP == gopPreset)
4174  {
4175  reorder = 0;
4176  }
4177  else if (GOP_PRESET_IDX_IBPBP == gopPreset)
4178  {
4179  reorder = 1;
4180  }
4181  else if (GOP_PRESET_IDX_IBBBP == gopPreset)
4182  {
4183  reorder = 3;
4184  }
4185  else if (GOP_PRESET_IDX_RA_IB == gopPreset)
4186  {
4187  reorder = 7;
4188  }
4189  else if (GOP_PRESET_IDX_CUSTOM == gopPreset)
4190  {
4191  for (i = 0; i < p_enc->custom_gop_params.custom_gop_size; i++)
4192  {
4193  if (abs(p_enc->custom_gop_params.pic_param[i].poc_offset - i - 1) >
4194  reorder)
4195  {
4196  reorder = abs(p_enc->custom_gop_params.pic_param[i].poc_offset - i - 1);
4197  }
4198  }
4199  }
4200  else
4201  {
4202  ni_log(NI_LOG_ERROR, "%s: gopPresetIdx=%d not supported\n",
4203  __FUNCTION__, gopPreset);
4204  }
4205  return reorder;
4206 }
4207 
4208 /*!*****************************************************************************
4209  * \brief Get GOP's number of reference frames
4210  *
4211  * \param[in] p_params Pointer to a user allocated ni_logan_encoder_params_t
4212  *
4213  * \return number of reference frames of the GOP
4214  ******************************************************************************/
4216 {
4217  int gopPreset = p_params->enc_input_params.gop_preset_index;
4218  int ref_frames = 0;
4219  int i;
4220  ni_logan_encoder_input_params_t* p_enc = NULL;
4221 
4222  if (! p_params)
4223  {
4224  ni_log(NI_LOG_ERROR, "%s: NULL input!\n", __FUNCTION__);
4225  return -1;
4226  }
4227  p_enc = &p_params->enc_input_params;
4228 
4229  if (GOP_PRESET_IDX_ALL_I == gopPreset)
4230  {
4231  ref_frames = 0;
4232  }
4233  else if (gopPreset >= GOP_PRESET_IDX_IPP && gopPreset <= GOP_PRESET_IDX_RA_IB)
4234  {
4235  ref_frames = 2;
4236  }
4237  else if (GOP_PRESET_IDX_SP == gopPreset)
4238  {
4239  ref_frames = 1;
4240  }
4241  else if (GOP_PRESET_IDX_CUSTOM == gopPreset)
4242  {
4243  for (i = 0; i < p_enc->custom_gop_params.custom_gop_size; i++)
4244  {
4245  if (p_enc->custom_gop_params.pic_param[i].num_ref_pic_L0 > ref_frames)
4246  {
4247  ref_frames = p_enc->custom_gop_params.pic_param[i].num_ref_pic_L0;
4248  }
4249  }
4250  }
4251  else
4252  {
4253  ni_log(NI_LOG_ERROR, "%s: gopPresetIdx=%d not supported\n",
4254  __FUNCTION__, gopPreset);
4255  }
4256 
4257  return ref_frames;
4258 }
4259 
4260 /*!*****************************************************************************
4261  * \brief Add a new auxiliary data to a frame
4262  *
4263  * \param[in/out] frame a frame to which the auxiliary data should be added
4264  * \param[in] type type of the added auxiliary data
4265  * \param[in] data_size size of the added auxiliary data
4266  *
4267  * \return a pointer to the newly added aux data on success, NULL otherwise
4268  ******************************************************************************/
4270  ni_aux_data_type_t type,
4271  int data_size)
4272 {
4273  ni_aux_data_t *ret;
4274 
4276  ! (ret = malloc(sizeof(ni_aux_data_t))))
4277  {
4278  ni_log(NI_LOG_ERROR, "ni_logan_frame_new_aux_data No memory or exceeding max "
4279  "aux_data number !\n");
4280  return NULL;
4281  }
4282 
4283  ret->type = type;
4284  ret->size = data_size;
4285  ret->data = calloc(1, data_size);
4286  if (! ret->data)
4287  {
4288  ni_log(NI_LOG_ERROR, "ni_logan_frame_new_aux_data No memory for aux data !\n");
4289  free(ret);
4290  ret = NULL;
4291  }
4292  else
4293  {
4294  frame->aux_data[frame->nb_aux_data++] = ret;
4295  }
4296 
4297  return ret;
4298 }
4299 
4300 /*!*****************************************************************************
4301  * \brief Add a new auxiliary data to a frame and copy in the raw data
4302  *
4303  * \param[in/out] frame a frame to which the auxiliary data should be added
4304  * \param[in] type type of the added auxiliary data
4305  * \param[in] raw_data the raw data of the aux data
4306  * \param[in] data_size size of the added auxiliary data
4307  *
4308  * \return a pointer to the newly added aux data on success, NULL otherwise
4309  ******************************************************************************/
4311  ni_aux_data_type_t type,
4312  const uint8_t* raw_data,
4313  int data_size)
4314 {
4315  ni_aux_data_t *ret = ni_logan_frame_new_aux_data(frame, type, data_size);
4316  if (ret)
4317  {
4318  memcpy(ret->data, raw_data, data_size);
4319  }
4320  return ret;
4321 }
4322 
4323 /*!*****************************************************************************
4324  * \brief Retrieve from the frame auxiliary data of a given type if exists
4325  *
4326  * \param[in] frame a frame from which the auxiliary data should be retrieved
4327  * \param[in] type type of the auxiliary data to be retrieved
4328  *
4329  * \return a pointer to the aux data of a given type on success, NULL otherwise
4330  ******************************************************************************/
4332  ni_aux_data_type_t type)
4333 {
4334  int i;
4335  for (i = 0; i < frame->nb_aux_data; i++)
4336  {
4337  if (frame->aux_data[i]->type == type)
4338  {
4339  return frame->aux_data[i];
4340  }
4341  }
4342  return NULL;
4343 }
4344 
4345 /*!*****************************************************************************
4346  * \brief If auxiliary data of the given type exists in the frame, free it
4347  * and remove it from the frame.
4348  *
4349  * \param[in/out] frame a frame from which the auxiliary data should be removed
4350  * \param[in] type type of the auxiliary data to be removed
4351  *
4352  * \return None
4353  ******************************************************************************/
4355  ni_aux_data_type_t type)
4356 {
4357  int i;
4358  ni_aux_data_t *aux;
4359 
4360  for (i = 0; i < frame->nb_aux_data; i++)
4361  {
4362  aux = frame->aux_data[i];
4363  if (aux->type == type)
4364  {
4365  frame->aux_data[i] = frame->aux_data[frame->nb_aux_data - 1];
4366  frame->aux_data[frame->nb_aux_data - 1] = NULL;
4367  frame->nb_aux_data--;
4368 
4369  free(aux->data);
4370  free(aux);
4371  }
4372  }
4373 }
4374 
4375 /*!*****************************************************************************
4376  * \brief Free and remove all auxiliary data from the frame.
4377  *
4378  * \param[in/out] frame a frame from which the auxiliary data should be removed
4379  *
4380  * \return None
4381  ******************************************************************************/
4383 {
4384  int i;
4385  ni_aux_data_t *aux;
4386 
4387  for (i = 0; i < frame->nb_aux_data; i++)
4388  {
4389  aux = frame->aux_data[i];
4390  free(aux->data);
4391  free(aux);
4392  frame->aux_data[i] = NULL;
4393  }
4394  frame->nb_aux_data = 0;
4395 }
4396 
4397 /*!******************************************************************************
4398 * \brief Queries device Serial number
4399 *
4400 * \param[in] device_handle Device handle used to backtrace serial Num
4401 * \param[in] p_serial_num Pointer to a caller allocated ni_logan_serial_num_t struct
4402 * \return On success
4403 * NI_LOGAN_RETCODE_SUCCESS
4404 * On failure
4405 * NI_LOGAN_RETCODE_INVALID_PARAM
4406 * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
4407 * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
4408 *******************************************************************************/
4409 ni_logan_retcode_t ni_logan_device_handle_map_SN(ni_device_handle_t device_handle,
4410  ni_logan_serial_num_t *p_serial_num)
4411 {
4412  ni_logan_nvme_result_t nvme_result = 0;
4413  ni_logan_nvme_command_t cmd = { 0 };
4414  void * p_buffer = NULL;
4416  ni_event_handle_t event_handle = NI_INVALID_EVENT_HANDLE;
4417 
4418  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
4419 
4420  if (NI_INVALID_DEVICE_HANDLE == device_handle || !p_serial_num)
4421  {
4422  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
4424  LRETURN;
4425  }
4426 
4427  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), NI_LOGAN_NVME_IDENTITY_CMD_DATA_SZ))
4428  {
4429  ni_log(NI_LOG_ERROR, "ERROR: %s() Cannot allocate buffer.\n", __FUNCTION__);
4431  LRETURN;
4432  }
4433 
4434  memset(p_buffer, 0, NI_LOGAN_NVME_IDENTITY_CMD_DATA_SZ);
4435 
4436 #ifdef _WIN32
4437  event_handle = ni_logan_create_event();
4438  if (NI_INVALID_EVENT_HANDLE == event_handle)
4439  {
4441  LRETURN;
4442  }
4443 #endif
4444 
4445  uint32_t ui32LBA = IDENTIFY_DEVICE_R;
4446  if (ni_logan_nvme_send_read_cmd(device_handle, event_handle, p_buffer, NI_LOGAN_NVME_IDENTITY_CMD_DATA_SZ, ui32LBA) < 0)
4447  {
4449  LRETURN;
4450  }
4451 
4452  ni_logan_populate_serial_number(p_serial_num, p_buffer);
4453 
4454  END:
4455 
4456  ni_logan_aligned_free(p_buffer);
4457 
4458  ni_log(NI_LOG_TRACE, "%s(): retval: %d\n", __FUNCTION__, retval);
4459 
4460  return retval;
4461 }
4462 
4463 /*!******************************************************************************
4464 * \brief Copies existing decoding session params for hw frame usage
4465 *
4466 * \param[in] src_p_ctx Pointer to a caller allocated source
4467 * ni_logan_session_context_t struct
4468 * \param[in] dst_p_ctx Pointer to a caller allocated destination
4469 * ni_logan_session_context_t struct
4470 * \return On success
4471 * NI_LOGAN_RETCODE_SUCCESS
4472 * On failure
4473 * NI_LOGAN_RETCODE_INVALID_PARAM
4474 * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
4475 * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
4476 * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
4477 *******************************************************************************/
4479  ni_logan_session_context_t *dst_p_ctx)
4480 {
4481  ni_logan_retcode_t retval;
4482 
4483  ni_logan_pthread_mutex_lock(&src_p_ctx->mutex);
4484 
4485  // Hold the lock of decoding session context here.
4486  retval = ni_logan_decoder_session_copy_internal(src_p_ctx, dst_p_ctx);
4487 
4488  ni_logan_pthread_mutex_unlock(&src_p_ctx->mutex);
4489 
4490  return retval;
4491 }
4492 
4493 /*!******************************************************************************
4494 * \brief Reads data from the device
4495 * device_type should be NI_LOGAN_DEVICE_TYPE_DECODER,
4496 * and reads data hwdesc from decoder when hw transcoding
4497 *
4498 * \param[in] p_ctx Pointer to a caller allocated
4499 * ni_logan_session_context_t struct
4500 * \param[in] p_data Pointer to a caller allocated
4501 * ni_logan_session_data_io_t struct which contains either a
4502 * ni_logan_frame_t data frame or ni_logan_packet_t data packet to send
4503 * \return On success
4504 * Total number of bytes read
4505 * On failure
4506 * NI_LOGAN_RETCODE_INVALID_PARAM
4507 * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
4508 * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
4509 *******************************************************************************/
4512 {
4514  int seq_change_read_count = 0;
4515 
4516  if (!p_ctx || !p_data)
4517  {
4518  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
4520  }
4521 
4522  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
4523 
4524  for (; ;)
4525  {
4526  int aligned_width;
4527  //retval = ni_logan_decoder_session_read(p_ctx, &(p_data->data.frame));
4528  retval = ni_logan_decoder_session_read_desc(p_ctx, &(p_data->data.frame));
4529  // check resolution change only after initial setting obtained
4530  // p_data->data.frame.video_width is picture width and will be 32-align
4531  // adjusted to frame size; p_data->data.frame.video_height is the same as
4532  // frame size, then compare them to saved one for resolution checking
4533  //
4534  aligned_width = ((p_data->data.frame.video_width + 31) / 32) * 32;
4535  ni_log(NI_LOG_TRACE, "FNum %" PRIu64 ", DFVWxDFVH %u x %u, AlWid %d, "
4536  "AVW x AVH %u x %u\n ", p_ctx->frame_num,
4537  p_data->data.frame.video_width, p_data->data.frame.video_height,
4538  aligned_width, p_ctx->active_video_width, p_ctx->active_video_height);
4539 
4540  if (0 == retval && seq_change_read_count)
4541  {
4542  ni_log(NI_LOG_TRACE, "%s (decoder): seq change NO data, next time.\n",
4543  __FUNCTION__);
4544  p_ctx->active_video_width = 0;
4545  p_ctx->active_video_height = 0;
4546  p_ctx->active_bit_depth = 0;
4547  break;
4548  }
4549  else if (retval < 0)
4550  {
4551  ni_log(NI_LOG_ERROR, "%s (decoder): failure ret %d, return ..\n",
4552  __FUNCTION__, retval);
4553  break;
4554  }
4555  else if (p_ctx->frame_num && p_data->data.frame.video_width &&
4556  p_data->data.frame.video_height && p_data->data.frame.bit_depth &&
4557  (aligned_width != p_ctx->active_video_width ||
4558  p_data->data.frame.video_height != p_ctx->active_video_height ||
4559  p_data->data.frame.bit_depth != p_ctx->active_bit_depth))
4560  {
4561  ni_log(NI_LOG_TRACE, "%s (decoder): sequence change, frame size %ux%u %d"
4562  "bits -> %ux%u %dbits, continue read ...\n", __FUNCTION__,
4563  p_ctx->active_video_width, p_ctx->active_video_height,
4564  p_ctx->active_bit_depth, p_data->data.frame.video_width,
4565  p_data->data.frame.video_height, p_data->data.frame.bit_depth);
4566  // reset active video resolution to 0 so it can be queried in the re-read
4567  p_ctx->active_video_width = 0;
4568  p_ctx->active_video_height = 0;
4569  p_ctx->active_bit_depth = 0;
4570  seq_change_read_count++;
4571  }
4572  else
4573  {
4574  break;
4575  }
4576  }
4577 
4578  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
4579 
4580  return retval;
4581 }
4582 
4583 /*!******************************************************************************
4584 * \brief Reads data from hw descriptor from decoder output buffer
4585 *
4586 * \param[in] p_data Pointer to a caller allocated
4587 * ni_logan_session_data_io_t struct which contains either a
4588 * ni_logan_frame_t data frame or ni_logan_packet_t data packet to send
4589 * \param[in] hwdesc HW descriptor to find frame in XCODER
4590 * \return On success
4591 * Total number of bytes read
4592 * On failure
4593 * NI_LOGAN_RETCODE_INVALID_PARAM
4594 * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
4595 * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
4596 *******************************************************************************/
4600 {
4602 
4603  if (!hwdesc || !p_data)
4604  {
4605  ni_log(NI_LOG_ERROR, "%s(): Error passed parameters are null!, return\n",
4606  __FUNCTION__);
4608  }
4609 
4610  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
4611 
4612  p_ctx->session_id = hwdesc->ui16SessionID;
4613 
4614 #ifdef _WIN32
4615  int64_t handle = (((int64_t) hwdesc->device_handle_ext) << 32) | hwdesc->device_handle;
4616  p_ctx->blk_io_handle = (ni_device_handle_t) handle;
4617 #else
4618  p_ctx->blk_io_handle = (ni_device_handle_t) hwdesc->device_handle;
4619 #endif
4620 
4621  p_ctx->codec_format = hwdesc->encoding_type; //unused
4622 
4623  p_ctx->bit_depth_factor = hwdesc->bit_depth;
4625 
4626  ni_log(NI_LOG_TRACE, "%s(): bit_depth_factor %u\n",
4627  __FUNCTION__, p_ctx->bit_depth_factor);
4628 
4629  retval = ni_logan_hwdownload_session_read(p_ctx, &(p_data->data.frame), hwdesc); //cut me down as needed
4630 
4631  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
4632 
4633  return retval;
4634 }
4635 
4636 /*!******************************************************************************
4637 * \brief Writes data and reads back hw descriptor from decoder output buffer
4638 *
4639 * \param[in] p_src_data Pointer to a caller allocated
4640 * ni_logan_session_data_io_t struct which contains either a
4641 * ni_logan_frame_t data frame or ni_logan_packet_t data packet to send
4642 * \param[in] hwdesc HW descriptor to find frame in XCODER
4643 * \return On success
4644 * Total number of bytes read
4645 * On failure
4646 * NI_LOGAN_RETCODE_INVALID_PARAM
4647 * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
4648 * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
4649 *******************************************************************************/
4651  ni_logan_session_data_io_t *p_src_data,
4653 {
4654  unsigned int hwaddress = 0;
4656  if (!hwdesc || !p_src_data)
4657  {
4658  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
4660  }
4661 
4662  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
4663 
4664  retval = ni_logan_hwupload_session_write(p_ctx, &p_src_data->data.frame);
4665  if (retval <= 0)
4666  {
4667  return retval;
4668  }
4669  retval = ni_logan_hwupload_session_read_hwdesc(p_ctx, hwdesc, &hwaddress);
4670 
4671  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
4672 
4673  return retval;
4674 }
4675 
4676 
4677 /*!*****************************************************************************
4678 * \brief Allocate memory for the frame buffer based on provided parameters
4679 * taking into account pic line size and extra data.
4680 * Applicable to YUV420p AVFrame for hw only.
4681 *
4682 * \param[in] p_frame Pointer to a caller allocated ni_logan_frame_t struct
4683 *
4684 * \param[in] video_width Width of the video frame
4685 * \param[in] video_height Height of the video frame
4686 * \param[in] linesize Picture line size
4687 * \param[in] alignment Allignment requirement
4688 * \param[in] extra_len Extra data size (incl. meta data)
4689 *
4690 * \return On success
4691 * NI_LOGAN_RETCODE_SUCCESS
4692 * On failure
4693 * NI_LOGAN_RETCODE_INVALID_PARAM
4694 * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
4695 *****************************************************************************/
4697  int video_width,
4698  int video_height,
4699  int extra_len)
4700 {
4701  void* p_buffer = NULL;
4702  int height_aligned = video_height;
4703  int retval = NI_LOGAN_RETCODE_SUCCESS;
4704 
4705  if (!p_frame)
4706  {
4707  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
4709  }
4710 
4711  ni_log(NI_LOG_TRACE, "%s: extra_len=%d\n", __FUNCTION__, extra_len);
4712 
4713  int luma_size = 0;//linesize[0] * height_aligned;
4714  int chroma_b_size = 0;//luma_size / 4;
4715  int chroma_r_size = 0;//luma_size / 4;
4716  int buffer_size = sizeof(ni_logan_hwframe_surface_t) + extra_len;
4717 
4719 
4720  //Check if Need to free
4721  if ((p_frame->buffer_size != buffer_size) && (p_frame->buffer_size > 0))
4722  {
4723  ni_log(NI_LOG_TRACE, "%s: free current p_frame p_frame->buffer_size=%d\n",
4724  __FUNCTION__, p_frame->buffer_size);
4725  ni_logan_frame_buffer_free(p_frame);
4726  }
4727 
4728  //Check if need to realocate
4729  if (p_frame->buffer_size != buffer_size)
4730  {
4731 #ifndef XCODER_SIM_ENABLED
4732  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size))
4733  {
4734  ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate p_frame buffer.\n");
4736  LRETURN;
4737  }
4738 #else
4739  p_buffer = malloc(buffer_size);
4740  if (!p_buffer)
4741  {
4742  ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate p_frame buffer.\n");
4744  LRETURN;
4745  }
4746 #endif
4747  // init once after allocation
4748  memset(p_buffer, 0, buffer_size);
4749  p_frame->buffer_size = buffer_size;
4750  p_frame->p_buffer = p_buffer;
4751  ni_log(NI_LOG_TRACE, "%s: allocated new p_frame buffer\n", __FUNCTION__);
4752  }
4753  else
4754  {
4755  ni_log(NI_LOG_TRACE, "%s: reuse p_frame buffer\n", __FUNCTION__);
4756  }
4757 
4758  p_frame->p_data[3] = (uint8_t*)p_frame->p_buffer;
4759  p_frame->p_data[0] = NULL;
4760  p_frame->p_data[1] = NULL;
4761  p_frame->p_data[2] = NULL;
4762 
4763  p_frame->data_len[0] = 0;//luma_size;
4764  p_frame->data_len[1] = 0;//chroma_b_size;
4765  p_frame->data_len[2] = 0;//chroma_r_size;
4766  p_frame->data_len[3] = sizeof(ni_logan_hwframe_surface_t);
4767 
4768  p_frame->video_width = video_width;
4769  p_frame->video_height = height_aligned;
4770 
4771  ni_log(NI_LOG_TRACE, "%s: success: p_frame->buffer_size=%d\n",
4772  __FUNCTION__, p_frame->buffer_size);
4773 
4774  END:
4775 
4776  if (NI_LOGAN_RETCODE_SUCCESS != retval)
4777  {
4778  ni_logan_aligned_free(p_buffer);
4779  }
4780 
4781  return retval;
4782 }
4783 
4784 #ifndef _WIN32
4785 /*!*****************************************************************************
4786  * \brief Calculate the total size of a frame based on the upload
4787  * context attributes and includes rounding up to the page size
4788  *
4789  * \param[in] p_upl_ctx pointer to an uploader session context
4790  * \param[in] linesize array of line stride
4791  *
4792  * \return size
4793  * NI_RETCODE_INVALID_PARAM
4794  *
4795  ******************************************************************************/
4797  const int linesize[], const int heightsize[])
4798 {
4799  int pixel_format;
4800  int width, height;
4801  int luma, chroma_b, chroma_r;
4802  int total;
4803 
4804  pixel_format = p_upl_ctx->pixel_format;
4805  width = p_upl_ctx->active_video_width;
4806  height = p_upl_ctx->active_video_height;
4807 
4808  switch (pixel_format)
4809  {
4812  if (width < 0 || width > NI_LOGAN_MAX_RESOLUTION_WIDTH)
4813  {
4815  }
4816 
4817  if ((height < 0) || (height > NI_LOGAN_MAX_RESOLUTION_HEIGHT))
4818  {
4820  }
4821  break;
4822 
4823  default:
4825  }
4826 
4827  switch (pixel_format)
4828  {
4831  luma = linesize[0] * heightsize[0];
4832  chroma_b = linesize[1] * heightsize[1];
4833  chroma_r = linesize[2] * heightsize[2];
4834  total =
4835  luma + chroma_b + chroma_r + NI_LOGAN_APP_ENC_FRAME_META_DATA_SIZE;
4836  break;
4837 
4838  default:
4840  break;
4841  }
4842 
4843  total = NI_LOGAN_VPU_CEIL(total, 0x1000);
4844 
4845  return total;
4846 }
4847 
4848 /*!*****************************************************************************
4849 * \brief Acquire a P2P frame buffer from the hwupload session
4850 *
4851 * \param[in] p_ctx Pointer to a caller allocated
4852 * ni_session_context_t struct
4853 * \param[out] p_frame Pointer to a caller allocated hw frame
4854 *
4855 * \return On success
4856 * NI_RETCODE_SUCCESS
4857 * On failure
4858 * NI_RETCODE_INVALID_PARAM
4859 * NI_RETCODE_ERROR_NVME_CMD_FAILED
4860 * NI_RETCODE_ERROR_INVALID_SESSION
4861 *******************************************************************************/
4863 {
4866  unsigned int offset;
4867  unsigned int hwaddress = 0;
4868  int ret;
4869  int linestride[NI_LOGAN_MAX_NUM_DATA_POINTERS];
4870  int alignedheight[NI_LOGAN_MAX_NUM_DATA_POINTERS];
4871  ni_logan_hwframe_surface_t hwdesc = {0};
4872  ni_logan_hwframe_surface_t *p_surface;
4873 
4874  if (p_ctx == NULL || p_frame == NULL || p_frame->p_data[3] == NULL)
4875  {
4876  ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n",
4877  __func__);
4879  }
4880 
4881  p_surface = (ni_logan_hwframe_surface_t *)p_frame->p_data[3];
4882 
4883  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
4884 
4885  retval = ni_logan_hwupload_session_read_hwdesc(p_ctx, &hwdesc, &hwaddress);
4886 
4887  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
4888 
4889  if (retval != NI_LOGAN_RETCODE_SUCCESS)
4890  {
4891  ni_log(NI_LOG_ERROR, "ERROR: hwdesc read failure %d\n", retval);
4892  return retval;
4893  }
4894 
4895  retval = ni_get_memory_offset(p_ctx, &hwdesc, &offset, hwaddress);
4896  if (retval != NI_LOGAN_RETCODE_SUCCESS)
4897  {
4898  ni_log(NI_LOG_ERROR, "ERROR: bad buffer id\n");
4900  }
4901 
4903  p_ctx->bit_depth_factor, 1, linestride,
4904  alignedheight);
4905 
4906  uexp.fd = -1;
4907  uexp.flags = 0;
4908  uexp.offset = offset;
4909 
4910  uexp.length = ni_calculate_total_frame_size(p_ctx, linestride, alignedheight);
4911  uexp.domain = p_ctx->domain;
4912  uexp.bus = p_ctx->bus;
4913  uexp.dev = p_ctx->dev;
4914  uexp.fn = p_ctx->fn;
4915  uexp.bar = 4; // PCI BAR4 configuration space
4916 
4917  ret = ioctl(p_ctx->netint_fd, NETINT_LOGAN_IOCTL_EXPORT_DMABUF, &uexp);
4918  if (ret < 0)
4919  {
4920  ni_log(NI_LOG_ERROR, "%s: Failed to export dmabuf %d errno %d, offset %x, length %d\n",
4921  __func__, ret, NI_ERRNO, uexp.offset, uexp.length);
4922  return NI_LOGAN_RETCODE_FAILURE;
4923  }
4924 
4925  *p_surface = hwdesc;
4926  p_surface->ui16width = p_ctx->active_video_width;
4927  p_surface->ui16height = p_ctx->active_video_height;
4928  //p_surface->ui32nodeAddress = 0; // unused field
4929  p_surface->encoding_type = (int8_t)p_ctx->codec_format;;
4930  p_surface->dma_buf_fd = uexp.fd;
4931 
4932  return retval;
4933 }
4934 
4935 /*!*****************************************************************************
4936  * \brief Lock a hardware P2P frame prior to encoding
4937  *
4938  * \param[in] p_upl_ctx pointer to caller allocated upload context
4939  * [in] p_frame pointer to caller allocated hardware P2P frame
4940  *
4941  * \return On success
4942  * NI_RETCODE_SUCCESS
4943  * On failure NI_RETCODE_FAILURE
4944  * NI_RETCODE_INVALID_PARAM
4945 *******************************************************************************/
4947  ni_logan_frame_t *p_frame)
4948 {
4949  int ret;
4950  struct netint_logan_iocmd_attach_rfence uatch = {0};
4951  struct pollfd pfds[1] = {0};
4952  ni_logan_hwframe_surface_t *p_surface;
4953 
4954  if (p_upl_ctx == NULL || p_frame == NULL)
4955  {
4956  ni_log(NI_LOG_ERROR, "%s: bad parameters\n", __func__);
4958  }
4959 
4960  if (p_frame->p_data[3] == NULL)
4961  {
4962  ni_log(NI_LOG_ERROR, "%s: not a hardware frame\n", __func__);
4964  }
4965 
4966  p_surface = (ni_logan_hwframe_surface_t *)p_frame->p_data[3];
4967 
4968  pfds[0].fd = p_surface->dma_buf_fd;
4969  pfds[0].events = POLLIN;
4970  pfds[0].revents = 0;
4971 
4972  ret = poll(pfds, 1, -1);
4973  if (ret < 0)
4974  {
4975  ni_log(NI_LOG_ERROR, "%s:failed to poll dmabuf fd errno %d\n", __func__,
4976  NI_ERRNO);
4977  return ret;
4978  }
4979 
4980  uatch.fd = p_surface->dma_buf_fd;
4981  ret = ioctl(p_upl_ctx->netint_fd, NETINT_LOGAN_IOCTL_ATTACH_RFENCE, &uatch);
4982  if (ret < 0)
4983  {
4985  "%s: failed to attach dmabuf read fence errno %d\n", __func__,
4986  NI_ERRNO);
4987  return ret;
4988  }
4989 
4990  return NI_LOGAN_RETCODE_SUCCESS;
4991 }
4992 
4993 /*!*****************************************************************************
4994 * \brief Unlock a hardware P2P frame after encoding
4995 *
4996 * \param[in] p_upl_ctx pointer to caller allocated upload context
4997 * [in] p_frame pointer to caller allocated hardware P2P frame
4998 *
4999 * \return On success
5000 * NI_RETCODE_SUCCESS
5001 * On failure NI_RETCODE_FAILURE
5002 * NI_RETCODE_INVALID_PARAM
5003 *******************************************************************************/
5005  ni_logan_frame_t *p_frame)
5006 {
5007  int ret;
5008  struct netint_logan_iocmd_signal_rfence usigl = {0};
5009  ni_logan_hwframe_surface_t *p_surface;
5010 
5011  if ((p_upl_ctx == NULL) || (p_frame == NULL))
5012  {
5013  ni_log(NI_LOG_ERROR, "%s: Invalid parameters %p %p\n", __func__,
5014  p_upl_ctx, p_frame);
5016  }
5017 
5018  p_surface = (ni_logan_hwframe_surface_t *)p_frame->p_data[3];
5019 
5020  if (p_surface == NULL)
5021  {
5022  ni_log(NI_LOG_ERROR, "%s: Invalid hw frame\n", __func__);
5024  }
5025 
5026  usigl.fd = p_surface->dma_buf_fd;
5027  ret = ioctl(p_upl_ctx->netint_fd, NETINT_LOGAN_IOCTL_SIGNAL_RFENCE, &usigl);
5028  if (ret < 0)
5029  {
5030  ni_log(NI_LOG_ERROR, "Failed to signal dmabuf read fence\n");
5031  return NI_LOGAN_RETCODE_FAILURE;
5032  }
5033 
5034  return NI_LOGAN_RETCODE_SUCCESS;
5035 }
5036 
5037 /*!*****************************************************************************
5038  * \brief Special P2P test API function. Copies YUV data from the software
5039  * frame to the hardware P2P frame on the T408 device
5040  *
5041  * \param[in] p_upl_ctx pointer to caller allocated uploader session
5042  * context
5043  * [in] p_swframe pointer to a caller allocated software frame
5044  * [in] p_hwframe pointer to a caller allocated hardware frame
5045  *
5046  * \return On success
5047  * NI_RETCODE_SUCCESS
5048  * On failure
5049  * NI_RETCODE_FAILURE
5050  * NI_RETCODE_INVALID_PARAM
5051 *******************************************************************************/
5053  uint8_t *p_data, uint32_t len,
5054  ni_logan_frame_t *p_hwframe)
5055 {
5056  int ret;
5057  struct netint_logan_iocmd_issue_request uis = {0};
5058  ni_logan_hwframe_surface_t *p_surface;
5059 
5060  if (p_upl_ctx == NULL || p_data == NULL || p_hwframe == NULL)
5061  {
5062  ni_log(NI_LOG_ERROR, "%s: invalid null parameters\n", __func__);
5064  }
5065 
5066  if (p_hwframe->p_data[3] == NULL)
5067  {
5068  ni_log(NI_LOG_ERROR, "%s: empty frame\n", __func__);
5070  }
5071 
5072  p_surface = (ni_logan_hwframe_surface_t *)p_hwframe->p_data[3];
5073 
5074  uis.fd = p_surface->dma_buf_fd;
5075  uis.data = p_data;
5076  uis.len = len;
5078 
5079  ret = ioctl(p_upl_ctx->netint_fd, NETINT_LOGAN_IOCTL_ISSUE_REQ, &uis);
5080  if (ret < 0)
5081  {
5083  "%s: Failed to request dmabuf rendering errno %d\n", __func__,
5084  NI_ERRNO);
5085  return NI_LOGAN_RETCODE_FAILURE;
5086  }
5087 
5088  return NI_LOGAN_RETCODE_SUCCESS;
5089 }
5090 
5091 #endif
5092 
5093 /*!*****************************************************************************
5094  * \brief Set the incoming frame format for the encoder
5095  *
5096  * \param[in] p_enc_ctx pointer to encoder context
5097  * [in] p_enc_params pointer to encoder parameters
5098  * [in] width input width
5099  * [in] height input height
5100  * [in] bit_depth 8 for 8-bit YUV, 10 for 10-bit YUV
5101  * [in] src_endian NI_FRAME_LITTLE_ENDIAN or NI_FRAME_BIG_ENDIAN
5102  *
5103  * \return on success
5104  * NI_RETCODE_SUCCESS
5105  *
5106  * on failure
5107  * NI_RETCODE_INVALID_PARAM
5108 *******************************************************************************/
5110  ni_logan_session_context_t *p_enc_ctx, ni_logan_encoder_params_t *p_enc_params,
5111  int width, int height, int bit_depth, int src_endian)
5112 {
5113  int alignedw;
5114  int alignedh;
5115 
5116  if (p_enc_ctx == NULL || p_enc_params == NULL)
5117  {
5118  ni_log(NI_LOG_ERROR, "%s: null ptr\n", __func__);
5120  }
5121 
5122  if (!(bit_depth == 8) && !(bit_depth == 10))
5123  {
5124  ni_log(NI_LOG_ERROR, "%s: bad bit depth %d\n", __func__, bit_depth);
5126  }
5127 
5128  if (!(src_endian == NI_LOGAN_FRAME_LITTLE_ENDIAN) &&
5129  !(src_endian == NI_LOGAN_FRAME_BIG_ENDIAN))
5130  {
5131  ni_log(NI_LOG_ERROR, "%s: bad endian %d\n", __func__, src_endian);
5133  }
5134 
5135  p_enc_ctx->src_bit_depth = bit_depth;
5136  p_enc_ctx->bit_depth_factor = (bit_depth == 8) ? 1 : 2;
5137  p_enc_ctx->src_endian = src_endian;
5138 
5139  alignedw = width;
5140 
5141  if (alignedw < NI_LOGAN_MIN_WIDTH)
5142  {
5143  p_enc_params->enc_input_params.conf_win_right +=
5144  (NI_LOGAN_MIN_WIDTH - width) / 2 * 2;
5145  alignedw = NI_LOGAN_MIN_WIDTH;
5146  } else
5147  {
5148  alignedw = ((width + 1) / 2) * 2;
5149  p_enc_params->enc_input_params.conf_win_right +=
5150  (alignedw - width) / 2 * 2;
5151  }
5152 
5153  p_enc_params->source_width = alignedw;
5154  alignedh = height;
5155 
5156  if (alignedh < NI_LOGAN_MIN_HEIGHT)
5157  {
5158  p_enc_params->enc_input_params.conf_win_bottom +=
5159  (NI_LOGAN_MIN_HEIGHT - height) / 2 * 2;
5160  alignedh = NI_LOGAN_MIN_HEIGHT;
5161  } else
5162  {
5163  alignedh = ((height + 1) / 2) * 2;
5164  p_enc_params->enc_input_params.conf_win_bottom +=
5165  (alignedh - height) / 2 * 2;
5166  }
5167 
5168  p_enc_params->source_height = alignedh;
5169 
5170  return NI_LOGAN_RETCODE_SUCCESS;
5171 }
5172 
5173 
5174 /*!******************************************************************************
5175 * \brief Recycle a frame buffer on card
5176 *
5177 * \param[in] surface Stuct containing device and frame location to clear out
5178 *
5179 * \return On success NI_LOGAN_RETCODE_SUCCESS
5180 * On failure NI_LOGAN_RETCODE_INVALID_PARAM
5181 *******************************************************************************/
5183  ni_device_handle_t device_handle,
5184  ni_event_handle_t event_handle)
5185 {
5187  if (surface)
5188  {
5189  if (surface->seq_change)
5190  {
5191  // clear meta buffer index when sequence change happened
5192  ni_logan_hwframe_surface_t surface_meta = {0};
5193  surface_meta.ui16SessionID = surface->ui16SessionID;
5195  surface_meta.i8InstID = surface->i8InstID;
5196  ni_log(NI_LOG_TRACE, "%s(): clear meta buffer\n", __FUNCTION__);
5197  retval = ni_logan_clear_instance_buf(&surface_meta, device_handle, event_handle);
5198  }
5199  ni_log(NI_LOG_TRACE, "%s(): Start cleaning out buffer\n", __FUNCTION__);
5200  ni_log(NI_LOG_TRACE, "%s(): ui16FrameIdx=%d sessionId=%d device_handle=0x%x\n",
5201  __FUNCTION__, surface->i8FrameIdx, surface->ui16SessionID, device_handle);
5202  retval = ni_logan_clear_instance_buf(surface, device_handle, event_handle);
5203  }
5204  else
5205  {
5206  ni_log(NI_LOG_TRACE, "%s(): Surface is empty\n", __FUNCTION__);
5207  }
5208  return retval;
5209 }
5210 
5211 /*!******************************************************************************
5212 * \brief Sends frame pool setup info to device
5213 *
5214 * \param[in] p_ctx Pointer to a caller allocated
5215 * ni_logan_session_context_t struct
5216 * \param[in] p_data Pointer to a caller allocated
5217 * ni_logan_session_data_io_t struct which contains either a
5218 * ni_logan_frame_t data frame or ni_logan_packet_t data packet to send
5219 * \return On success Return code
5220 * On failure
5221 * NI_LOGAN_RETCODE_INVALID_PARAM
5222 * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
5223 * NI_LOGAN_RETCODE_ERROR_INVALID_SESSION
5224 *******************************************************************************/
5226  uint32_t pool_size, uint32_t p2p_pool)
5227 {
5229 
5230  if (!p_ctx)
5231  {
5232  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
5234  }
5235 
5236  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
5237 
5238  retval = ni_logan_hwupload_init_framepool(p_ctx, pool_size, p2p_pool);
5239 
5240  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
5241 
5242  return retval;
5243 }
5244 
5245 /*!******************************************************************************
5246  * \brief Allocate memory for the frame buffer based on provided parameters
5247  * taking into account width, height, format, stride, alignment, and
5248  * extra data
5249  *
5250  * \param[in] p_frame Pointer to caller allocated ni_logan_frame_t
5251  * \param[in] pixel_format pixel format
5252  * \param[in] video_width width, in pixels
5253  * \param[in] video_height height, in pixels
5254  * \param[in] linesize horizontal stride
5255  * \param[in] alignment apply a 16 pixel height alignment (T408 only)
5256  * \param[in] extra_len meta data size
5257  *
5258  * \return NI_LOGAN_RETCODE_SUCCESS
5259  * NI_LOGAN_RETCODE_INVALID_PARAM
5260  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
5261  *
5262  *******************************************************************************/
5264  int video_width, int video_height,
5265  int linesize[], int alignment, int extra_len)
5266 {
5267  int buffer_size;
5268  void *p_buffer = NULL;
5269  int retval = NI_LOGAN_RETCODE_SUCCESS;
5270  int height_aligned;
5271  int luma_size, chroma_b_size, chroma_r_size;
5272 
5273  if (!p_frame)
5274  {
5275  ni_log(NI_LOG_ERROR, "Invalid frame pointer\n");
5277  }
5278 
5279  switch (pixel_format)
5280  {
5285  /*
5286  * The encoder will pad a small frame up to 256x128 before encoding
5287  * and set the cropping value in the packet header to the original
5288  * dimension.
5289  */
5290  if ((video_width < 0) || (video_width > NI_LOGAN_MAX_RESOLUTION_WIDTH))
5291  {
5292  ni_log(NI_LOG_ERROR, "Video resolution width %d out of range\n", video_width);
5294  }
5295 
5296  if ((video_height < 0) || (video_height > NI_LOGAN_MAX_RESOLUTION_HEIGHT))
5297  {
5298  ni_log(NI_LOG_ERROR, "Video resolution height %d out of range\n", video_width);
5300  }
5301  break;
5302  default:
5303  ni_log(NI_LOG_ERROR, "Unknown pixel format %d\n", pixel_format);
5305  }
5306 
5307  height_aligned = NI_LOGAN_VPU_ALIGN8(video_height);
5308 
5309  if (alignment)
5310  {
5311  /* 16-pixel aligned pixel height for Quadra */
5312  height_aligned = NI_LOGAN_VPU_ALIGN16(video_height);
5313  }
5314 
5315  /* Round up to the minimum 256 pixel height if necessary */
5316  height_aligned = height_aligned > NI_LOGAN_MIN_HEIGHT? height_aligned : NI_LOGAN_MIN_HEIGHT;
5317 
5318  switch (pixel_format)
5319  {
5324  luma_size = linesize[0] * height_aligned;
5325  chroma_b_size = luma_size / 4;
5326  chroma_r_size = luma_size / 4;
5327 
5328  buffer_size = luma_size + chroma_b_size + chroma_r_size + extra_len;
5329  break;
5330  default:
5331  ni_log(NI_LOG_ERROR, "Error: unsupported pixel format %d\n", pixel_format);
5333  }
5334 
5335  /* Allocate a buffer size that is page aligned for the host */
5337 
5338  /* If this buffer has a different size, realloc a new buffer */
5339  if ((p_frame->buffer_size > 0) && (p_frame->buffer_size != buffer_size))
5340  {
5341  ni_log(NI_LOG_TRACE, "Free current p_frame, p_frame->buffer_size %d\n",
5342  p_frame->buffer_size);
5343  ni_logan_frame_buffer_free(p_frame);
5344  }
5345 
5346  if (p_frame->buffer_size != buffer_size)
5347  {
5348  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size))
5349  {
5350  ni_log(NI_LOG_ERROR, "Error: Cannot allocate p_frame\n");
5352  LRETURN;
5353  }
5354 
5355  memset(p_buffer, 0, buffer_size);
5356  p_frame->buffer_size = buffer_size;
5357  p_frame->p_buffer = p_buffer;
5358  ni_log(NI_LOG_TRACE, "%s: allocated new p_frame buffer\n", __FUNCTION__);
5359  }
5360  else
5361  {
5362  ni_log(NI_LOG_TRACE, "%s: reuse p_frame buffer\n", __FUNCTION__);
5363  }
5364 
5365  switch (pixel_format)
5366  {
5371  p_frame->p_data[0] = (uint8_t*) p_frame->p_buffer;
5372  p_frame->p_data[1] = (uint8_t*) p_frame->p_data[0] + luma_size;
5373  p_frame->p_data[2] = (uint8_t*) p_frame->p_data[1] + chroma_b_size;
5374  p_frame->p_data[3] = NULL;
5375 
5376  p_frame->data_len[0] = luma_size;
5377  p_frame->data_len[1] = chroma_b_size;
5378  p_frame->data_len[2] = chroma_r_size;
5379  p_frame->data_len[3] = 0;
5380  break;
5381  /* fall through */
5382  default:
5383  ni_log(NI_LOG_ERROR, "Error: unsupported pixel format %d\n",pixel_format);
5385  LRETURN;
5386  }
5387 
5388  p_frame->video_width = video_width;
5389  p_frame->video_height = height_aligned;
5390 
5391  ni_log(NI_LOG_TRACE, "%s success: w=%d; h=%d; aligned buffer size=%d\n",
5392  __FUNCTION__, video_width, video_height, buffer_size);
5393 
5394  END:
5395 
5396  if (retval != NI_LOGAN_RETCODE_SUCCESS)
5397  {
5398  ni_logan_aligned_free(p_buffer);
5399  }
5400 
5401  return retval;
5402 }
5403 
5404 /*!*****************************************************************************
5405 * \brief Allocate memory for the frame buffer based on provided parameters
5406 * Applicable to use YUV420p AVFrame for zerocopy case.
5407 * Allocat extra_len only.
5408 *
5409 * \param[in] p_frame Pointer to a caller allocated ni_logan_frame_t struct
5410 *
5411 * \param[in] video_width Width of the video frame
5412 * \param[in] video_height Height of the video frame
5413 * \param[in] linesize Picture line size
5414 * \param[in] extra_len Extra data size (incl. meta data)
5415 * \param[in] buffer[] Buffer address of video frame.
5416 *
5417 * \return On success
5418 * NI_LOGAN_RETCODE_SUCCESS
5419 * On failure
5420 * NI_LOGAN_RETCODE_INVALID_PARAM
5421 * NI_LOGAN_RETCODE_ERROR_MEM_ALOC
5422 *****************************************************************************/
5424  int video_width,
5425  int video_height,
5426  int linesize[],
5427  int extra_len,
5428  int factor,
5429  uint8_t* buffer[])
5430 {
5431  void* p_buffer = NULL;
5432  int retval = NI_LOGAN_RETCODE_SUCCESS;
5433 
5434  if (!p_frame || !linesize || linesize[0] <= 0 ||
5435  linesize[0] > NI_LOGAN_MAX_RESOLUTION_WIDTH * factor ||
5436  video_width > NI_LOGAN_MAX_RESOLUTION_WIDTH || video_width <= 0 ||
5437  video_height > NI_LOGAN_MAX_RESOLUTION_HEIGHT || video_height % 16 != 0 || video_height < NI_LOGAN_MIN_HEIGHT ||
5438  !buffer[0] || !buffer[1] || !buffer[2])
5439  {
5440  ni_log(NI_LOG_TRACE, "ERROR: %s passed parameters are null!, return\n",
5441  __FUNCTION__);
5443  }
5444 
5445  ni_log(NI_LOG_TRACE, "%s: orig=%dx%d linesize=%d/%d/%d "
5446  "extra_len=%d\n", __FUNCTION__, video_width, video_height,
5447  linesize[0], linesize[1], linesize[2],
5448  extra_len);
5449 
5450  int buffer_size = extra_len;//only allocate extra_len.
5452 
5453  //Check if Need to free
5454  if ((p_frame->buffer_size != buffer_size) && (p_frame->buffer_size > 0))
5455  {
5456  ni_log(NI_LOG_TRACE, "%s: free current p_frame p_frame->buffer_size=%d\n",
5457  __FUNCTION__, p_frame->buffer_size);
5458  ni_logan_frame_buffer_free(p_frame);
5459  }
5460 
5461  //Check if need to realocate
5462  if (p_frame->buffer_size != buffer_size)
5463  {
5464 #ifndef XCODER_SIM_ENABLED
5465  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size))
5466  {
5467  ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate p_frame buffer.\n");
5469  LRETURN;
5470  }
5471 #else
5472  p_buffer = malloc(buffer_size);
5473  if (!p_buffer)
5474  {
5475  ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate p_frame buffer.\n");
5477  LRETURN;
5478  }
5479 #endif
5480  // init once after allocation
5481  memset(p_buffer, 0, buffer_size);
5482  p_frame->buffer_size = buffer_size;
5483  p_frame->p_buffer = p_buffer;
5484  ni_log(NI_LOG_TRACE, "%s: allocated new p_frame buffer\n", __FUNCTION__);
5485  }
5486  else
5487  {
5488  ni_log(NI_LOG_TRACE, "%s: reuse p_frame buffer\n", __FUNCTION__);
5489  }
5490 
5491  p_frame->p_data[3] = (uint8_t*)p_frame->p_buffer;
5492  p_frame->p_data[0] = buffer[0];
5493  p_frame->p_data[1] = buffer[1];
5494  p_frame->p_data[2] = buffer[2];
5495 
5496  p_frame->data_len[0] = linesize[0] * video_height;
5497  p_frame->data_len[1] = p_frame->data_len[0] / 4;
5498  p_frame->data_len[2] = p_frame->data_len[0] / 4;
5499  p_frame->data_len[3] = extra_len;
5500 
5501  p_frame->video_width = video_width;//used for sequence change feature
5502  p_frame->video_height = video_height;//used for sequence change feature
5503  ni_log(NI_LOG_TRACE, "%s: success: p_frame->buffer_size=%d\n",
5504  __FUNCTION__, p_frame->buffer_size);
5505 
5506  END:
5507 
5508  if (NI_LOGAN_RETCODE_SUCCESS != retval)
5509  {
5510  ni_logan_aligned_free(p_buffer);
5511  }
5512 
5513  return retval;
5514 }
5515 
5516 /*!*****************************************************************************
5517  * \brief Check if incoming frame is encoder zero copy compatible or not
5518  *
5519  * \param[in] width width of encoder frame.
5520  * \param[in] height height of encoder frame.
5521  * \param[in] linesize linesizes (pointer to array).
5522  * \param[in] dst_stride dst_stride (produced by ni_logan_get_hw_yuv420p_dim).
5523  * \param[in] src_height src height of every planar.
5524  * \param[in] dst_height dst_height_aligned(produced by ni_logan_get_hw_yuv420p_dim).
5525  * \param[in] bit_depth_factor bit_depth of frame.
5526  * \param[in] data CPU address of frame planar.
5527  *
5528  * \return on success
5529  * NI_LOGAN_RETCODE_SUCCESS
5530  *
5531  * on failure
5532  * NI_LOGAN_RETCODE_FAILURE
5533  *
5534 *******************************************************************************/
5536  const int height,
5537  const int linesize[],
5538  const int dst_stride[],
5539  const int src_height[],
5540  const int dst_height[],
5541  const int bit_depth_factor,
5542  const uint8_t * data[])
5543 {
5544  if (((uintptr_t)data[0] % NI_LOGAN_MEM_PAGE_ALIGNMENT) == 0 && //buffer address aligned
5545  width % 2 == 0 && dst_stride[0] == width * bit_depth_factor && //except width padding case
5546  height % 16 == 0 && //height 16 aligned
5547  dst_height[0] == src_height[0] && //except height paddding case
5548  dst_height[1] == src_height[1] &&
5549  dst_height[2] == src_height[2] &&
5550  dst_stride[0] == linesize[0] && //stride aligned
5551  dst_stride[1] == linesize[1] && //stride aligned
5552  dst_stride[2] == linesize[2] && //stride aligned
5553  data[1] == data[0] + dst_stride[0] * height && //continous
5554  data[2] == data[1] + dst_stride[1] * height / 2)
5555  return NI_LOGAN_RETCODE_SUCCESS;
5556  return NI_LOGAN_RETCODE_FAILURE;
5557 }
5558 
5559 /*!*****************************************************************************
5560  * \brief Check if logan firmware version is higher than expected api flavor and version
5561  *
5562  * \param[in] p_ctx Pointer to a caller allocated
5563  * ni_logan_session_context_t struct
5564  * \param[in] fw_api_fla expected firmware api flavor
5565  * \param[in] fw_api_ver expected firmware api version
5566  *
5567  * \return on success
5568  * NI_LOGAN_RETCODE_SUCCESS
5569  * On failure
5570  * NI_LOGAN_RETCODE_FAILURE
5571  *
5572 *******************************************************************************/
5573 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)
5574 {
5575  return (atoi(&p_ctx->fw_rev[NI_LOGAN_XCODER_VER_SZ + 1]) > (fw_api_fla * 100 + fw_api_ver)) ?
5578 }
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_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.
int ni_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...
#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....
ni_logan_retcode_t ni_logan_device_session_open(ni_logan_session_context_t *p_ctx, ni_logan_device_type_t device_type)
Opens a new device session depending on the device_type parameter If device_type is NI_LOGAN_DEVICE_T...
ni_event_handle_t ni_logan_create_event(void)
Create event and returnes event handle if successful.
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_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_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_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