libxcoder  3.5.4
ni_device_api_priv_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_priv_logan.c
24 *
25 * \brief Private functions used by main ni_device_api file
26 *
27 *******************************************************************************/
28 
29 #ifdef _WIN32
30 #include <windows.h>
31 #elif defined(__linux__) || defined(__APPLE__)
32 #if defined(__linux__)
33 #include <sys/types.h>
34 #endif
35 #include <sys/file.h>
36 #include <sys/ioctl.h>
37 #include <sys/stat.h>
38 #include <unistd.h>
39 #include <sys/ioctl.h>
40 #include <sys/mman.h>
41 #include <sys/time.h>
42 #include <fcntl.h>
43 #include <limits.h>
44 #include <unistd.h>
45 #include <utime.h>
46 #include <signal.h>
47 #include <sched.h>
48 #include <sys/syscall.h>
49 #include <sys/resource.h>
50 #include <dirent.h>
51 #endif
52 
53 #include <errno.h>
54 #include <stdint.h>
55 #include <string.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <stdint.h>
59 #include <inttypes.h>
60 #include "ni_nvme_logan.h"
61 #include "ni_device_api_logan.h"
63 #include "ni_rsrc_api_logan.h"
64 #include "ni_rsrc_priv_logan.h"
65 #include "ni_util_logan.h"
66 #include "ni_av_codec_logan.h"
67 
68 #ifdef XCODER_SIGNATURE_FILE
69 // this file has an array defined for signature content: ni_logan_session_sign
70 #include "../build/xcoder_signature_headers.h"
71 #endif
72 
74 {
78 
79 static uint8_t g_itu_t_t35_cc_sei_hdr_hevc[NI_CC_SEI_HDR_HEVC_LEN] =
80 {
81  0x00, 0x00, 0x00, 0x01, // NAL start code 00 00 00 01
82  0x4e,
83  0x01, // nal_unit_header() {forbidden bit=0 nal_unit_type=39,
84  // nuh_layer_id=0 nuh_temporal_id_plus1=1)
85  0x04, // payloadType= 4 (user_data_registered_itu_t_t35)
86  0 + 11, // payLoadSize= ui16Len + 11; to be set (index 7)
87  0xb5, // itu_t_t35_country_code =181 (North America)
88  0x00,
89  0x31, // itu_t_t35_provider_code = 49
90  0x47, 0x41, 0x39,
91  0x34, // ATSC_user_identifier = "GA94"
92  0x03, // ATSC1_data_user_data_type_code=3
93  0 | 0xc0, // (ui16Len/3) | 0xc0 (to be set; index 16) (each CC character
94  //is 3 bytes)
95  0xFF // em_data = 255
96 };
97 
98 static uint8_t g_itu_t_t35_hdr10p_sei_hdr_hevc[NI_HDR10P_SEI_HDR_HEVC_LEN] =
99 {
100  0x00, 0x00, 0x00, 0x01, // NAL start code 00 00 00 01
101  0x4e,
102  0x01, // nal_unit_header() {forbidden bit=0 nal_unit_type=39,
103  // nuh_layer_id=0 nuh_temporal_id_plus1=1)
104  0x04, // payloadType= 4 (user_data_registered_itu_t_t35)
105  0x00, // payLoadSize; to be set (index 7)
106  0xb5, // u8 itu_t_t35_country_code =181 (North America)
107  //0x00,
108  //0x3c, // u16 itu_t_t35_provider_code = 0x003c
109  //0x00,
110  //0x01, // u16 itu_t_t35_provider_oriented_code = 0x0001
111  // payLoadSize count starts from itu_t_t35_provider_code and goes until
112  // and including trailer
113 };
114 
115 static uint8_t g_itu_t_t35_cc_sei_hdr_h264[NI_CC_SEI_HDR_H264_LEN] =
116 {
117  0x00, 0x00, 0x00, 0x01, // NAL start code 00 00 00 01
118  0x06, // nal_unit_header() {forbidden bit=0 nal_ref_idc=0, nal_unit_type=6
119  0x04, // payloadType= 4 (user_data_registered_itu_t_t35)
120  0 + 11, // payLoadSize= ui16Len + 11; to be set (index 6)
121  0xb5, // itu_t_t35_country_code =181 (North America)
122  0x00,
123  0x31, // itu_t_t35_provider_code = 49
124  0x47, 0x41, 0x39,
125  0x34, // ATSC_user_identifier = "GA94"
126  0x03, // ATSC1_data_user_data_type_code=3
127  0 | 0xc0, // (ui16Len/3) | 0xc0 (to be set; index 15) (each CC character
128  //is 3 bytes)
129  0xFF // em_data = 255
130 };
131 
132 static uint8_t g_itu_t_t35_hdr10p_sei_hdr_h264[NI_HDR10P_SEI_HDR_H264_LEN] =
133 {
134  0x00, 0x00, 0x00, 0x01, // NAL start code 00 00 00 01
135  0x06, // nal_unit_header() {forbidden bit=0 nal_ref_idc=0, nal_unit_type=6
136  0x04, // payloadType= 4 (user_data_registered_itu_t_t35)
137  0x00, // payLoadSize; to be set (index 6)
138  0xb5, // itu_t_t35_country_code =181 (North America)
139  //0x00,
140  //0x3c, // u16 itu_t_t35_provider_code = 0x003c
141  //0x00,
142  //0x01, // u16 itu_t_t35_provider_oriented_code = 0x0001
143  // payLoadSize count starts from itu_t_t35_provider_code and goes until
144  // and including trailer
145 };
146 
147 static uint8_t g_sei_trailer[NI_CC_SEI_TRAILER_LEN] =
148 {
149  0xFF, // marker_bits = 255
150  0x80 // RBSP trailing bits - rbsp_stop_one_bit and 7 rbsp_alignment_zero_bit
151 };
152 
153 #define NI_LOGAN_XCODER_FAILURES_MAX 25
154 
155 #ifdef _WIN32
156 #define CHECK_ERR_RC(ctx, rc, opcode, type, hw_id, inst_id) \
157 { \
158  ni_logan_instance_status_info_t err_rc_info = { 0 }; \
159  int err_rc = ni_logan_query_status_info(ctx, type, &err_rc_info, rc, opcode); \
160  rc = err_rc_info.inst_err_no; \
161  if (err_rc_info.sess_err_no || rc) ctx->rc_error_count++; else ctx->rc_error_count = 0; \
162  int tmp_rc = NI_LOGAN_RETCODE_FAILURE; \
163  if (err_rc_info.sess_err_no || ctx->rc_error_count >= NI_LOGAN_XCODER_FAILURES_MAX || \
164  (tmp_rc = ni_logan_nvme_check_error_code(rc, opcode, type, hw_id, inst_id))) { \
165  ni_log(NI_LOG_INFO, "Persistent failures detected, %s() line-%d: session_no 0x%x sess_err_no %u " \
166  "inst_err_no %u rc_error_count: %d\n", __FUNCTION__, __LINE__, *inst_id, \
167  err_rc_info.sess_err_no, err_rc_info.inst_err_no, ctx->rc_error_count); \
168  rc = tmp_rc; \
169  LRETURN; \
170  } \
171 }
172 
173 #define CHECK_ERR_RC2(ctx, rc, info, opcode, type, hw_id, inst_id) \
174 { \
175  rc = info.inst_err_no; \
176  if (info.sess_err_no || rc) ctx->rc_error_count++; else ctx->rc_error_count = 0; \
177  int tmp_rc = NI_LOGAN_RETCODE_FAILURE; \
178  if (info.sess_err_no || ctx->rc_error_count >= NI_LOGAN_XCODER_FAILURES_MAX || \
179  (tmp_rc = ni_logan_nvme_check_error_code(rc, opcode, type, hw_id, inst_id))) { \
180  ni_log(NI_LOG_INFO, "Persistent failures detected, %s() line-%d: session_no 0x%x sess_err_no %u " \
181  "inst_err_no %u rc_error_count: %d\n", __FUNCTION__, __LINE__, *inst_id, \
182  info.sess_err_no, info.inst_err_no, ctx->rc_error_count); \
183  rc = tmp_rc; \
184  LRETURN; \
185  } \
186 }
187 #elif defined(__linux__) || defined(__APPLE__)
188 static struct stat g_nvme_stat = {0};
189 
190 #ifdef XCODER_SELF_KILL_ERR
191 #define CHECK_ERR_RC(ctx, rc, opcode, type, hw_id, inst_id) \
192 { \
193  ni_logan_instance_status_info_t err_rc_info = { 0 }; \
194  int err_rc = ni_logan_query_status_info(ctx, type, &err_rc_info, rc, opcode); \
195  rc = err_rc_info.inst_err_no; \
196  if (err_rc_info.sess_err_no || rc) ctx->rc_error_count++; else ctx->rc_error_count = 0; \
197  if (err_rc_info.sess_err_no || ctx->rc_error_count >= NI_LOGAN_XCODER_FAILURES_MAX || \
198  ni_logan_nvme_check_error_code(rc, opcode, type, hw_id, inst_id)) { \
199  ni_log(NI_LOG_INFO, "Terminating due to persistent failures, %s() line-%d: session_no 0x%x " \
200  "sess_err_no %u inst_err_no %u rc_error_count: %d\n", __FUNCTION__, __LINE__, *inst_id, \
201  err_rc_info.sess_err_no, err_rc_info.inst_err_no, ctx->rc_error_count); \
202  kill(getpid(), SIGTERM); \
203  } \
204 }
205 
206 #define CHECK_ERR_RC2(ctx, rc, err_rc_info, opcode, type, hw_id, inst_id) \
207 { \
208  rc = err_rc_info.inst_err_no; \
209  if (err_rc_info.sess_err_no || rc) ctx->rc_error_count++; else ctx->rc_error_count = 0; \
210  if (err_rc_info.sess_err_no || ctx->rc_error_count >= NI_LOGAN_XCODER_FAILURES_MAX || \
211  ni_logan_nvme_check_error_code(rc, opcode, type, hw_id, inst_id)) { \
212  ni_log(NI_LOG_INFO, "Terminating due to persistent failures, %s() line-%d: session_no 0x%x " \
213  "sess_err_no %u inst_err_no %u rc_error_count: %d\n", __FUNCTION__, __LINE__, *inst_id, \
214  err_rc_info.sess_err_no, err_rc_info.inst_err_no, ctx->rc_error_count); \
215  kill(getpid(), SIGTERM); \
216  } \
217 }
218 #else
219 #define CHECK_ERR_RC(ctx, rc, opcode, type, hw_id, inst_id) \
220 { \
221  ni_logan_instance_status_info_t err_rc_info = { 0 }; \
222  int err_rc = ni_logan_query_status_info(ctx, type, &err_rc_info, rc, opcode); \
223  rc = err_rc_info.inst_err_no; \
224  if (err_rc_info.sess_err_no || rc) ctx->rc_error_count++; else ctx->rc_error_count = 0; \
225  int tmp_rc = NI_LOGAN_RETCODE_FAILURE; \
226  if (err_rc_info.sess_err_no || ctx->rc_error_count >= NI_LOGAN_XCODER_FAILURES_MAX || \
227  (tmp_rc = ni_logan_nvme_check_error_code(rc, opcode, type, hw_id, inst_id))) { \
228  ni_log(NI_LOG_INFO, "Persistent failures detected, %s() line-%d: session_no 0x%x sess_err_no %u " \
229  "inst_err_no %u rc_error_count: %d\n", __FUNCTION__, __LINE__, *inst_id, \
230  err_rc_info.sess_err_no, err_rc_info.inst_err_no, ctx->rc_error_count); \
231  rc = tmp_rc; \
232  LRETURN; \
233  } \
234 }
235 
236 #define CHECK_ERR_RC2(ctx, rc, err_rc_info, opcode, type, hw_id, inst_id) \
237 { \
238  rc = err_rc_info.inst_err_no; \
239  if (err_rc_info.sess_err_no || rc) ctx->rc_error_count++; else ctx->rc_error_count = 0; \
240  int tmp_rc = NI_LOGAN_RETCODE_FAILURE; \
241  if (err_rc_info.sess_err_no || ctx->rc_error_count >= NI_LOGAN_XCODER_FAILURES_MAX || \
242  (tmp_rc = ni_logan_nvme_check_error_code(rc, opcode, type, hw_id, inst_id))) { \
243  ni_log(NI_LOG_INFO, "Persistent failures detected, %s() line-%d: session_no 0x%x sess_err_no %u " \
244  "inst_err_no %u rc_error_count: %d\n", __FUNCTION__, __LINE__, *inst_id, \
245  err_rc_info.sess_err_no, err_rc_info.inst_err_no, ctx->rc_error_count); \
246  rc = tmp_rc; \
247  LRETURN; \
248  } \
249 }
250 #endif
251 
252 #endif
253 
254 #define CHECK_VPU_RECOVERY(ret) \
255 { \
256  if (NI_LOGAN_RETCODE_NVME_SC_VPU_RECOVERY == ret) { \
257  ni_log(NI_LOG_TRACE, "Error, vpu reset.\n"); \
258  ret = NI_LOGAN_RETCODE_ERROR_VPU_RECOVERY; \
259  LRETURN; \
260  } \
261 }
262 
263 static int rotated_array_binary_search(uint64_t *lefts, uint64_t *rights, uint32_t size, uint64_t target)
264 {
265  int lo = 0;
266  int hi = size - 1;
267  while (lo <= hi)
268  {
269  int mid = lo + (hi - lo) / 2;
270  if (lefts[mid] <= target && target < rights[mid])
271  {
272  return mid;
273  }
274 
275  if (rights[mid] == 0)
276  {
277  // empty in (mid, hi)
278  hi = mid - 1;
279  continue;
280  }
281 
282  if (rights[lo] <= rights[mid])
283  {
284  if (lefts[lo] <= target && target < lefts[mid])
285  {
286  // Elements are all monotonous in (lo, mid)
287  hi = mid - 1;
288  }
289  else
290  {
291  // Rotation in (mid, hi)
292  lo = mid + 1;
293  }
294  }
295  else
296  {
297  if (rights[mid] <= target && target < rights[hi])
298  {
299  // Elements are all monotonous in (mid, hi)
300  lo = mid + 1;
301  }
302  else
303  {
304  // Rotation in (lo, mid)
305  hi = mid - 1;
306  }
307  }
308  }
309 
310  return -1;
311 }
312 
313 // create folder bearing the card name (nvmeX) if not existing
314 // start working inside this folder: nvmeX
315 // find the earliest saved and/or non-existing stream folder and use it as
316 // the pkt saving destination; at most 32 such folders to be checked/created;
317 // folder name is in the format of: streamY, where Y is [1, 32]
318 static void decoder_dump_dir_open(ni_logan_session_context_t* p_ctx)
319 {
320 #ifdef _WIN32
321 #elif defined(__linux__) || defined(__APPLE__)
322  FILE *fp;
323  char dir_name[128] = { 0 };
324  char file_name[128] = { 0 };
325  ni_logan_device_context_t *p_device_context;
326  DIR* dir;
327  struct dirent *stream_folder;
328  int curr_stream_idx = 0;
329  int earliest_stream_idx = 0;
330  int max_exist_idx = 0;
331  time_t earliest_time = 0;
332  struct stat file_stat;
333 
334  p_device_context = ni_logan_rsrc_get_device_context(p_ctx->device_type,
335  p_ctx->hw_id);
336  if (! p_device_context)
337  {
338  ni_log(NI_LOG_ERROR, "Error retrieve device context for decoder guid %d\n",
339  p_ctx->hw_id);
340  return;
341  }
342 
343  flock(p_device_context->lock, LOCK_EX);
344 
345  strcpy(dir_name, &p_ctx->dev_xcoder_name[5]);
346  if (0 != access(dir_name, F_OK))
347  {
348  if (0 != mkdir(dir_name, S_IRWXU | S_IRWXG | S_IRWXO))
349  {
350  ni_log(NI_LOG_ERROR, "Error create folder %s, errno %d\n",
351  dir_name, errno);
352  }
353  else
354  {
355  ni_log(NI_LOG_INFO, "Created pkt folder for: %s\n", dir_name);
356  }
357  }
358 
359  if (NULL == (dir = opendir(dir_name)))
360  {
361  ni_log(NI_LOG_ERROR, "Error %d: failed to open directory %s\n",
362  NI_ERRNO, dir_name);
363  }
364  else
365  {
366  // have a quick first pass of streamY folders, and if existing Y < 32,
367  // create a new folder Y+1 directly without checking existing ones content
368  while ((stream_folder = readdir(dir)))
369  {
370  if (! strncmp(stream_folder->d_name, "stream", strlen("stream")))
371  {
372  curr_stream_idx = atoi(&(stream_folder->d_name[strlen("stream")]));
373  if (curr_stream_idx > 0)
374  {
375  if (curr_stream_idx > max_exist_idx)
376  {
377  max_exist_idx = curr_stream_idx;
378  }
379  if (32 == curr_stream_idx)
380  {
381  break;
382  }
383  }
384  }
385  }
386 
387  // if less than 32 streams created then create a new one, otherwise have to
388  // pick the stream folder that has the earliest modified file which is
389  // most likely done by finished session.
390  if (max_exist_idx < 32)
391  {
392  curr_stream_idx = max_exist_idx + 1;
393  }
394  else
395  {
396  rewinddir(dir);
397  curr_stream_idx = 0;
398  while ((stream_folder = readdir(dir)))
399  {
400  // go through each of these streamY folders and get modified time
401  // of the first pkt-* file to simplify the searching
402  if (! strncmp(stream_folder->d_name, "stream", strlen("stream")))
403  {
404  snprintf(file_name, sizeof(file_name), "%s/%s/pkt-0001.bin",
405  dir_name, stream_folder->d_name);
406 
407  curr_stream_idx = atoi(&(stream_folder->d_name[strlen("stream")]));
408 
409  if (curr_stream_idx > 0 && 0 == access(file_name, F_OK))
410  {
411  // just take pkt-0001 file timestamp to simplify search
412  if (stat(file_name, &file_stat))
413  {
414  ni_log(NI_LOG_ERROR, "Error %d: failed to stat file %s\n",
415  NI_ERRNO, file_name);
416  }
417  else
418  {
419  if (0 == earliest_stream_idx ||
420  file_stat.st_mtime < earliest_time)
421  {
422  earliest_stream_idx = curr_stream_idx;
423  earliest_time = file_stat.st_mtime;
424  }
425  }
426  } // check first file in streamX
427  } // go through each streamX folder
428  } // read all files in nvmeY
429 
430  curr_stream_idx = earliest_stream_idx;
431 
432  // set the access/modified time of chosen pkt file to NOW so its stream
433  // folder won't be taken by other sessions.
434  snprintf(file_name, sizeof(file_name), "%s/stream%02d/pkt-0001.bin",
435  dir_name, curr_stream_idx);
436  if (utime(file_name, NULL))
437  {
438  ni_log(NI_LOG_ERROR, "Error utime %s\n", file_name);
439  }
440  } // 32 streams in nvmeY already
441  closedir(dir);
442  }
443 
444  snprintf(p_ctx->stream_dir_name, sizeof(p_ctx->stream_dir_name),
445  "%s/stream%02d", dir_name, curr_stream_idx);
446 
447  if (0 != access(p_ctx->stream_dir_name, F_OK))
448  {
449  if (0 != mkdir(p_ctx->stream_dir_name, S_IRWXU | S_IRWXG | S_IRWXO))
450  {
451  ni_log(NI_LOG_ERROR, "Error create stream folder %s, errno %d\n",
452  p_ctx->stream_dir_name, errno);
453  }
454  else
455  {
456  ni_log(NI_LOG_INFO, "Created stream sub folder: %s\n",
457  p_ctx->stream_dir_name);
458  }
459  }
460  else
461  {
462  ni_log(NI_LOG_INFO, "Reusing stream sub folder: %s\n",
463  p_ctx->stream_dir_name);
464  }
465 
466  flock(p_device_context->lock, LOCK_UN);
467  ni_logan_rsrc_free_device_context(p_device_context);
468 
469  snprintf(file_name, sizeof(file_name), "%s/process_session_id.txt",
470  p_ctx->stream_dir_name);
471 
472  fp = fopen(file_name, "wb");
473  if (fp)
474  {
475  char number[64] = {'\0'};
476  ni_log(NI_LOG_INFO, "Decoder pkt dump log created: %s\n", file_name);
477  snprintf(number, sizeof(number), "proc id: %ld\nsession id: %u\n",
478  (long) getpid(), p_ctx->session_id);
479  fwrite(number, strlen(number), 1, fp);
480  fclose(fp);
481  }
482  else
483  {
484  ni_log(NI_LOG_ERROR, "Error create decoder pkt dump log: %s\n", file_name);
485  }
486 #endif
487 }
488 
489 
490 //Only create the dump dir
491 static void decoder_dump_dir_create(ni_logan_session_context_t* p_ctx)
492 {
493 #ifdef _WIN32
494 #elif defined(__linux__)
495  FILE *fp;
496  char dir_name[128] = { 0 };
497  char file_name[128] = { 0 };
498  ni_logan_device_context_t *p_device_context;
499  DIR* dir;
500  struct dirent *stream_folder;
501  int curr_stream_idx = 0;
502  int earliest_stream_idx = 0;
503  int max_exist_idx = 0;
504  time_t earliest_time = 0;
505  struct stat file_stat;
506 
507  p_device_context = ni_logan_rsrc_get_device_context(p_ctx->device_type,
508  p_ctx->hw_id);
509  if (! p_device_context)
510  {
511  ni_log(NI_LOG_ERROR, "Error retrieve device context for decoder guid %d\n",
512  p_ctx->hw_id);
513  return;
514  }
515 
516  flock(p_device_context->lock, LOCK_EX);
517 
518  strcpy(dir_name, &p_ctx->dev_xcoder_name[5]);
519  if (0 != access(dir_name, F_OK))
520  {
521  if (0 != mkdir(dir_name, S_IRWXU | S_IRWXG | S_IRWXO))
522  {
523  ni_log(NI_LOG_ERROR, "Error create folder %s, errno %d\n",
524  dir_name, errno);
525  }
526  else
527  {
528  ni_log(NI_LOG_INFO, "Created pkt folder for: %s\n", dir_name);
529  }
530  }
531 
532  if (NULL == (dir = opendir(dir_name)))
533  {
534  ni_log(NI_LOG_ERROR, "Error %d: failed to open directory %s\n",
535  NI_ERRNO, dir_name);
536  }
537  else
538  {
539  // have a quick first pass of streamY folders, and if existing Y < 32,
540  // create a new folder Y+1 directly without checking existing ones content
541  while ((stream_folder = readdir(dir)))
542  {
543  if (! strncmp(stream_folder->d_name, "stream", strlen("stream")))
544  {
545  curr_stream_idx = atoi(&(stream_folder->d_name[strlen("stream")]));
546  if (curr_stream_idx > 0)
547  {
548  if (curr_stream_idx > max_exist_idx)
549  {
550  max_exist_idx = curr_stream_idx;
551  }
552  if (32 == curr_stream_idx)
553  {
554  break;
555  }
556  }
557  }
558  }
559 
560  // if less than 32 streams created then create a new one, otherwise have to
561  // pick the stream folder that has the earliest modified file which is
562  // most likely done by finished session.
563  if (max_exist_idx < 32)
564  {
565  curr_stream_idx = max_exist_idx + 1;
566  }
567  else
568  {
569  rewinddir(dir);
570  curr_stream_idx = 0;
571  while ((stream_folder = readdir(dir)))
572  {
573  // go through each of these streamY folders and get modified time
574  // of the first pkt-* file to simplify the searching
575  if (! strncmp(stream_folder->d_name, "stream", strlen("stream")))
576  {
577  curr_stream_idx = atoi(&(stream_folder->d_name[strlen("stream")]));
578  if (curr_stream_idx > 0)
579  {
580  if (0 == earliest_stream_idx ||
581  file_stat.st_mtime < earliest_time)
582  {
583  earliest_stream_idx = curr_stream_idx;
584  earliest_time = file_stat.st_mtime;
585  }
586  }
587  } // go through each streamX folder
588  } // read all files in nvmeY
589 
590  curr_stream_idx = earliest_stream_idx;
591  } // 32 streams in nvmeY already
592  closedir(dir);
593  }
594 
595  snprintf(p_ctx->stream_dir_name, sizeof(p_ctx->stream_dir_name),
596  "%s/stream%02d", dir_name, curr_stream_idx);
597 
598  if (0 != access(p_ctx->stream_dir_name, F_OK))
599  {
600  if (0 != mkdir(p_ctx->stream_dir_name, S_IRWXU | S_IRWXG | S_IRWXO))
601  {
602  ni_log(NI_LOG_ERROR, "Error create stream folder %s, errno %d\n",
603  p_ctx->stream_dir_name, errno);
604  }
605  else
606  {
607  ni_log(NI_LOG_INFO, "Created stream sub folder: %s\n",
608  p_ctx->stream_dir_name);
609  }
610  }
611  else
612  {
613  ni_log(NI_LOG_INFO, "Reusing stream sub folder: %s\n",
614  p_ctx->stream_dir_name);
615  }
616 
617  ni_log(NI_LOG_ERROR, "create stream folder %s, errno %d\n",
618  p_ctx->stream_dir_name, errno);
619 
620  flock(p_device_context->lock, LOCK_UN);
621  ni_logan_rsrc_free_device_context(p_device_context);
622 #endif
623 }
624 
625 /*!******************************************************************************
626  * \brief Open a xcoder decoder instance
627  *
628  * \param
629  *
630  * \return
631 *******************************************************************************/
633 {
635  uint32_t model_load = 0;
636  uint32_t low_delay_mode = 0;
637  void *p_signature = NULL;
638  uint32_t buffer_size = 0;
639  void* p_buffer = NULL;
640  ni_logan_decoder_session_open_info_t session_info = { 0 };
641  uint32_t ui32LBA = 0;
642 
643  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
644 
645  if (!p_ctx)
646  {
647  ni_log(NI_LOG_TRACE, "ERROR %s(): passed parameters are null!, return\n", __FUNCTION__);
649  LRETURN;
650  }
651 
652  //Create the session if the create session flag is set
654  {
655  int i;
656 
658  p_ctx->pts_table = NULL;
659  p_ctx->dts_queue = NULL;
660  p_ctx->p_leftover = NULL;
661  p_ctx->buffer_pool = NULL;
662  p_ctx->dec_fme_buf_pool = NULL;
663  p_ctx->prev_size = 0;
664  p_ctx->sent_size = 0;
665  p_ctx->lone_sei_size = 0;
666  p_ctx->status = 0;
667  p_ctx->key_frame_type = 0;
668  p_ctx->required_buf_size = 0;
669  p_ctx->ready_to_close = 0;
671  p_ctx->rc_error_count = 0;
672  p_ctx->frame_num = 0;
673  p_ctx->pkt_num = 0;
674  p_ctx->pkt_index = 0;
675  p_ctx->session_timestamp = 0;
676  p_ctx->decoder_drop_frame_num = 0;
677  p_ctx->codec_total_ticks = 0;
678  p_ctx->p_all_zero_buf = NULL;
679  p_ctx->p_dec_packet_inf_buf = NULL;
680  p_ctx->decoder_last_drop_frame_num = 0;
681  struct timeval tv;
682  ni_logan_gettimeofday(&tv, NULL);
683  p_ctx->codec_start_time = tv.tv_sec*1000000ULL + tv.tv_usec;
684 
685 #ifdef _WIN32
687  if (p_ctx->event_handle == NI_INVALID_EVENT_HANDLE)
688  {
690  LRETURN;
691  }
692 
694  if (p_ctx->thread_event_handle == NI_INVALID_EVENT_HANDLE)
695  {
697  LRETURN;
698  }
699 #endif
700 
701  if (((ni_logan_decoder_params_t*)p_ctx->p_session_config)->fps_denominator != 0)
702  {
703  model_load = (((ni_logan_decoder_params_t*)p_ctx->p_session_config)->source_width *
704  ((ni_logan_decoder_params_t*)p_ctx->p_session_config)->source_height *
705  ((ni_logan_decoder_params_t*)p_ctx->p_session_config)->fps_number) /
706  (((ni_logan_decoder_params_t*)p_ctx->p_session_config)->fps_denominator);
707  }
708  else
709  {
710  ni_log(NI_LOG_TRACE, "fps_denominator should not be 0 at this point\n"
711  "Setting model load with guess of 30fps\n");
712  model_load = (((ni_logan_decoder_params_t*)p_ctx->p_session_config)->source_width *
713  ((ni_logan_decoder_params_t*)p_ctx->p_session_config)->source_height *
714  30);
715  // assert(false);
716  }
717 
718  ni_log(NI_LOG_TRACE, "Model load info:: W:%d H:%d F:%d :%d Load:%d",
719  ((ni_logan_decoder_params_t*)p_ctx->p_session_config)->source_width,
720  ((ni_logan_decoder_params_t*)p_ctx->p_session_config)->source_height,
721  ((ni_logan_decoder_params_t*)p_ctx->p_session_config)->fps_number,
722  ((ni_logan_decoder_params_t*)p_ctx->p_session_config)->fps_denominator,
723  model_load);
724 
725  //malloc zero data buffer
726  if(ni_logan_posix_memalign(&p_ctx->p_all_zero_buf, sysconf(_SC_PAGESIZE), NI_LOGAN_DATA_BUFFER_LEN))
727  {
728  ni_log(NI_LOG_ERROR, "ERROR %d: %s() alloc decoder all zero buffer failed\n",
729  NI_ERRNO, __FUNCTION__);
731  LRETURN;
732  }
733  memset(p_ctx->p_all_zero_buf, 0, NI_LOGAN_DATA_BUFFER_LEN);
734 
735  //malloc decoder packet info buffer
736  if(ni_logan_posix_memalign(&p_ctx->p_dec_packet_inf_buf, sysconf(_SC_PAGESIZE), NI_LOGAN_DATA_BUFFER_LEN))
737  {
738  ni_log(NI_LOG_ERROR, "ERROR %d:%s() alloc decoder packet info buffer failed\n",
739  NI_ERRNO, __FUNCTION__);
741  LRETURN;
742  }
744 
745  //malloc data buffer
746  if(ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), NI_LOGAN_DATA_BUFFER_LEN))
747  {
748  ni_log(NI_LOG_ERROR, "ERROR %d: %s() alloc data buffer failed\n",
749  NI_ERRNO, __FUNCTION__);
751  LRETURN;
752  }
753  memset(p_buffer, 0, NI_LOGAN_DATA_BUFFER_LEN);
754 
755  //Set session ID to be invalid. In case we cannot open session, the session id wold remain invalid.
756  //In case we can open sesison, the session id would become valid.
757  ((ni_logan_get_session_id_t *)p_buffer)->session_id = NI_LOGAN_INVALID_SESSION_ID;
758 
759  // Get session ID
762  p_buffer, NI_LOGAN_DATA_BUFFER_LEN, ui32LBA);
763 
764  if (NI_LOGAN_RETCODE_SUCCESS != retval)
765  {
766  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme read command failed, blk_io_handle:"
767  "%" PRIx64 ", hw_id, %d\n", __FUNCTION__,
768  (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id);
770  LRETURN;
771  }
772  p_ctx->session_id = ni_logan_ntohl(((ni_logan_get_session_id_t *)p_buffer)->session_id);
773  ni_log(NI_LOG_TRACE, "%s ID:0x%x\n", __FUNCTION__, p_ctx->session_id);
775  {
776  ni_log(NI_LOG_ERROR, "ERROR %s(): query session ID failed, "
777  "p_ctx->blk_io_handle=%" PRIx64 ", p_ctx->hw_id=%d, "
778  "p_ctx->session_id=%d\n", __FUNCTION__,
779  (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id, p_ctx->session_id);
781  LRETURN;
782  }
783 
784  //Send session Info
785  memset(p_buffer, 0, NI_LOGAN_DATA_BUFFER_LEN);
786  session_info.codec_format = ni_logan_htonl(p_ctx->codec_format);
787  session_info.model_load = ni_logan_htonl(model_load);
788  if(p_ctx->decoder_low_delay != 0)
789  {
790  if (((ni_logan_decoder_params_t*)p_ctx->p_session_config)->dec_input_params.low_delay_mode == 2)
791  low_delay_mode = 2;
792  else
793  low_delay_mode = 1;
794  ni_log(NI_LOG_TRACE, "%s low_delay_mode %d\n", __FUNCTION__, low_delay_mode);
795  }
796  else if (((ni_logan_decoder_params_t*)p_ctx->p_session_config)->dec_input_params.low_delay_mode)
797  {
798  ni_log(NI_LOG_ERROR, "ERROR %s(): \"lowDelay\" must be specified in low_delay_mode %d\n",
799  __FUNCTION__,
800  ((ni_logan_decoder_params_t*)p_ctx->p_session_config)->dec_input_params.low_delay_mode);
802  LRETURN;
803  }
804 
805  session_info.low_delay_mode = ni_logan_htonl(low_delay_mode);
806  session_info.hw_desc_mode = ni_logan_htonl(p_ctx->hw_action);
807  session_info.set_high_priority = ni_logan_htonl(p_ctx->set_high_priority);
808  memcpy(p_buffer, &session_info, sizeof(ni_logan_decoder_session_open_info_t));
811  p_buffer, NI_LOGAN_DATA_BUFFER_LEN, ui32LBA);
812  CHECK_ERR_RC(p_ctx, retval, NI_LOGAN_NO_CHECK_TS_NVME_CMD_OP,
813  p_ctx->device_type, p_ctx->hw_id,
814  &(p_ctx->session_id));
815  CHECK_VPU_RECOVERY(retval);
816 
817  if (NI_LOGAN_RETCODE_SUCCESS != retval)
818  {
819  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme write command failed blk_io_handle"
820  ": %" PRIx64 ", hw_id, %d\n", __FUNCTION__,
821  (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id);
823  LRETURN;
824  }
825 
826  //Send keep alive timeout Info
827  uint64_t keep_alive_timeout = p_ctx->keep_alive_timeout * 1000000; //send us to FW
828  memset(p_buffer, 0, NI_LOGAN_DATA_BUFFER_LEN);
829  memcpy(p_buffer, &keep_alive_timeout, sizeof(keep_alive_timeout));
830  ni_log(NI_LOG_TRACE, "%s keep_alive_timeout %" PRIx64 "\n",
831  __FUNCTION__, keep_alive_timeout);
834  p_buffer, NI_LOGAN_DATA_BUFFER_LEN, ui32LBA);
835  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config,
836  p_ctx->device_type, p_ctx->hw_id,
837  &(p_ctx->session_id));
838  CHECK_VPU_RECOVERY(retval);
839 
840  if (NI_LOGAN_RETCODE_SUCCESS != retval)
841  {
842  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme write keep_alive_timeout command "
843  "failed, blk_io_handle: %" PRIx64 ", hw_id, %d\n", __FUNCTION__,
844  (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id);
846  LRETURN;
847  }
848 
849  ni_log(NI_LOG_TRACE, "%s(): p_ctx->device_handle=%" PRIx64 " p_ctx->hw_id=%d"
850  ", p_ctx->session_id=%d\n", __FUNCTION__,
851  (int64_t)p_ctx->device_handle, p_ctx->hw_id, p_ctx->session_id);
852  }
853 
854  // init for frame pts calculation
857  p_ctx->last_dts_interval = 0;
859  p_ctx->pts_correction_last_dts = INT64_MIN;
861  p_ctx->pts_correction_last_pts = INT64_MIN;
862  p_ctx->decoder_reorder_delay = 0;
863 
864  //p_ctx->p_leftover = malloc(NI_LOGAN_MAX_PACKET_SZ * 2);
865  p_ctx->p_leftover = malloc(p_ctx->max_nvme_io_size * 2);
866  if (!p_ctx->p_leftover)
867  {
868  ni_log(NI_LOG_ERROR, "ERROR %d: %s(): Cannot allocate leftover buffer.\n",
869  NI_ERRNO, __FUNCTION__);
872  LRETURN;
873  }
874 
875  ni_logan_timestamp_init(p_ctx, (ni_logan_timestamp_table_t * *) & (p_ctx->pts_table), "dec_pts");
876  ni_logan_timestamp_init(p_ctx, (ni_logan_timestamp_table_t * *) & (p_ctx->dts_queue), "dec_dts");
877 
878  if (p_ctx->p_session_config)
879  {
882  }
883 
884  p_ctx->active_video_width = 0;
885  p_ctx->active_video_height = 0;
886  p_ctx->active_bit_depth = 0;
887 
888  ni_log(NI_LOG_TRACE, "%s(): p_ctx->device_handle=%" PRIx64 " p_ctx->hw_id=%d "
889  "p_ctx->session_id=%d\n", __FUNCTION__,
890  (int64_t)p_ctx->device_handle, p_ctx->hw_id, p_ctx->session_id);
891 
892  if (((ni_logan_decoder_params_t*)p_ctx->p_session_config)->nb_save_pkt)
893  {
894  decoder_dump_dir_open(p_ctx);
895  }
896 
897  END:
898 
899  ni_logan_aligned_free(p_buffer);
900  ni_logan_aligned_free(p_signature);
901 
902  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
903 
904  return retval;
905 }
906 
907 /*!******************************************************************************
908  * \brief send a keep alive message to firmware
909  *
910  * \param
911  *
912  * \return
913  *******************************************************************************/
915  ni_device_handle_t device_handle,
916  ni_event_handle_t event_handle,
917  void *p_data)
918 {
919  ni_logan_retcode_t retval;
920  uint32_t ui32LBA = 0;
921 
922  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
923 
924  if (NI_LOGAN_INVALID_SESSION_ID == session_id)
925  {
926  ni_log(NI_LOG_TRACE, "ERROR: %s(): Invalid session ID!, return\n", __FUNCTION__);
928  LRETURN;
929  }
930 
931  if (NI_INVALID_DEVICE_HANDLE == device_handle)
932  {
933  ni_log(NI_LOG_TRACE, "ERROR: %s(): xcoder instance id < 0, return\n", __FUNCTION__);
935  LRETURN;
936  }
937 
938  ui32LBA = CONFIG_SESSION_KeepAlive_W(session_id);
939  if (ni_logan_nvme_send_write_cmd(device_handle, event_handle, p_data, NI_LOGAN_DATA_BUFFER_LEN, ui32LBA) < 0)
940  {
941  ni_log(NI_LOG_ERROR, "ERROR %s(): device_handle=%" PRIx64 " , session_id=%d\n",
942  __FUNCTION__, (int64_t) device_handle, session_id);
943  retval = NI_LOGAN_RETCODE_FAILURE;
944  }
945  else
946  {
947  ni_log(NI_LOG_TRACE, "SUCCESS %s(): device_handle=%" PRIx64 " , session_id=%d\n",
948  __FUNCTION__, (int64_t) device_handle, session_id);
949  retval = NI_LOGAN_RETCODE_SUCCESS;
950  }
951 
952  END:
953 
954  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
955 
956  return retval;
957 }
958 
959 /*!******************************************************************************
960  * \brief Flush decoder output
961  *
962  * \param
963  *
964  * \return
965  *******************************************************************************/
967 {
968  ni_logan_retcode_t retval;
969  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
970 
971  if (!p_ctx)
972  {
973  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
975  LRETURN;
976  }
977 
979  {
980  ni_log(NI_LOG_TRACE, "ERROR: %s(): xcoder instance id < 0, return\n",
981  __FUNCTION__);
983  LRETURN;
984  }
985 
987  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config,
988  p_ctx->device_type, p_ctx->hw_id,
989  &(p_ctx->session_id));
990  CHECK_VPU_RECOVERY(retval);
991 
992  if (NI_LOGAN_RETCODE_SUCCESS == retval)
993  {
994  p_ctx->ready_to_close = 1;
995  }
996 
997  END:
998 
999  ni_log(NI_LOG_TRACE, "%s(): success exit\n", __FUNCTION__);
1000 
1001  return retval;
1002 }
1003 
1004 /*!******************************************************************************
1005  * \brief Flush decoder output
1006  *
1007  * \param ni_logan_session_context_t* p_ctx - xcoder Context
1008  *
1009  * \return NI_LOGAN_RETCODE_SUCCESS on success, NI_LOGAN_RETCODE_INVALID_PARAM
1010  * or NI_LOGAN_RETCODE_ERROR_INVALID_SESSION on failure
1011  *******************************************************************************/
1013 {
1014  ni_logan_retcode_t retval;
1015  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
1016 
1017  if (!p_ctx)
1018  {
1019  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
1021  LRETURN;
1022  }
1023 
1025  {
1026  ni_log(NI_LOG_TRACE, "ERROR: %s(): xcoder instance id < 0, return\n",
1027  __FUNCTION__);
1029  LRETURN;
1030  }
1031 
1033  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config,
1034  p_ctx->device_type, p_ctx->hw_id,
1035  &(p_ctx->session_id));
1036  CHECK_VPU_RECOVERY(retval);
1037 
1038  if (NI_LOGAN_RETCODE_SUCCESS == retval)
1039  {
1041  }
1042 
1043  END:
1044 
1045  ni_log(NI_LOG_TRACE, "%s(): success exit\n", __FUNCTION__);
1046 
1047  return retval;
1048 }
1049 
1050 /*!******************************************************************************
1051  * \brief Close a xcoder decoder instance
1052  *
1053  * \param
1054  *
1055  * \return
1056  *******************************************************************************/
1058 {
1060  int counter = 0;
1061  int ret = 0;
1062  void* p_buffer = NULL;
1063  uint32_t ui32LBA = 0;
1064  int i;
1065 
1066  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
1067 
1068  if (!p_ctx)
1069  {
1070  ni_log(NI_LOG_TRACE, "ERROR: %s() passed parameters are null!, return\n",
1071  __FUNCTION__);
1073  }
1074 
1076  {
1077  ni_log(NI_LOG_TRACE, "ERROR %s(): Cannot allocate leftover buffer.\n",
1078  __FUNCTION__);
1079  retval = NI_LOGAN_RETCODE_SUCCESS;
1080  LRETURN;
1081  }
1082 
1083  ni_log(NI_LOG_ERROR, "Decoder_complete_info: session_id 0x%x, total frames input: %u "
1084  "buffered: %u completed: %u output: %u dropped: %u , "
1085  "inst_errors: %u\n", p_ctx->session_id, p_ctx->session_stats.frames_input,
1088  p_ctx->session_stats.inst_errors);
1089 
1090  //malloc data buffer
1091  if(ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), NI_LOGAN_DATA_BUFFER_LEN))
1092  {
1093  ni_log(NI_LOG_ERROR, "ERROR %d: malloc decoder close data buffer failed\n",
1094  NI_ERRNO);
1096  LRETURN;
1097  }
1098  memset(p_buffer, 0, NI_LOGAN_DATA_BUFFER_LEN);
1099 
1101 
1102  int retry = 0;
1103  while (retry < NI_LOGAN_MAX_SESSION_CLOSE_RETRIES) // 10 retries
1104  {
1105  ni_log(NI_LOG_TRACE, "%s(): p_ctx->blk_io_handle=%" PRIx64 ", "
1106  "p_ctx->hw_id=%d, p_ctx->session_id=%d, close_mode=1\n", __FUNCTION__,
1107  (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id, p_ctx->session_id);
1108 
1110  p_buffer, NI_LOGAN_DATA_BUFFER_LEN, ui32LBA) < 0)
1111  {
1112  ni_log(NI_LOG_ERROR, "ERROR %s(): command failed!\n", __FUNCTION__);
1114  break;
1115  }
1116  else if(((ni_logan_session_closed_status_t *)p_buffer)->session_closed)
1117  {
1118  retval = NI_LOGAN_RETCODE_SUCCESS;
1120  break;
1121  }
1122  else
1123  {
1124  ni_log(NI_LOG_TRACE, "%s(): wait for close\n", __FUNCTION__);
1127  }
1128 
1129  retry++;
1130  }
1131 
1132  END:
1133 
1134  ni_logan_aligned_free(p_buffer);
1137 
1138  if (NULL != p_ctx->p_leftover)
1139  {
1140  free(p_ctx->p_leftover);
1141  p_ctx->p_leftover = NULL;
1142  }
1143 
1144  if (p_ctx->pts_table)
1145  {
1146  ni_logan_timestamp_table_t* p_pts_table = p_ctx->pts_table;
1147  ni_logan_queue_free(&p_pts_table->list, p_ctx->buffer_pool);
1148  free(p_ctx->pts_table);
1149  p_ctx->pts_table = NULL;
1150  ni_log(NI_LOG_TRACE, "ni_logan_timestamp_done: success\n");
1151  }
1152 
1153  if (p_ctx->dts_queue)
1154  {
1155  ni_logan_timestamp_table_t* p_dts_queue = p_ctx->dts_queue;
1156  ni_logan_queue_free(&p_dts_queue->list, p_ctx->buffer_pool);
1157  free(p_ctx->dts_queue);
1158  p_ctx->dts_queue = NULL;
1159  ni_log(NI_LOG_TRACE, "ni_logan_timestamp_done: success\n");
1160  }
1161 
1163  p_ctx->buffer_pool = NULL;
1164 
1166  p_ctx->dec_fme_buf_pool = NULL;
1167 
1168  for (i = 0; i < NI_LOGAN_FIFO_SZ; i++)
1169  {
1170  free(p_ctx->pkt_custom_sei[i]);
1171  p_ctx->pkt_custom_sei[i] = NULL;
1172  }
1173 
1174  struct timeval tv;
1175  ni_logan_gettimeofday(&tv, NULL);
1176  uint64_t codec_end_time = tv.tv_sec*1000000ULL + tv.tv_usec;
1177 
1178  //if close immediately after opened, end time may equals to start time
1179  if (p_ctx->codec_total_ticks && codec_end_time - p_ctx->codec_start_time)
1180  {
1181  uint32_t ni_logan_usage = (uint32_t)((p_ctx->codec_total_ticks / NI_LOGAN_VPU_FREQ) * 100 /
1182  (codec_end_time - p_ctx->codec_start_time));
1183  ni_log(NI_LOG_INFO, "Decoder HW[%d] INST[%d]-average usage:%d%%\n",
1184  p_ctx->hw_id, (p_ctx->session_id&0x7F), ni_logan_usage);
1185  }
1186  else if (p_ctx->codec_start_time == 0)
1187  {
1188  ni_log(NI_LOG_INFO, "Uploader close HW[%d] INST[%d]\n",
1189  p_ctx->hw_id, (p_ctx->session_id&0x7F));
1190  }
1191  else
1192  {
1193  ni_log(NI_LOG_INFO, "Warning Decoder HW[%d] INST[%d]-average usage equals to 0\n",
1194  p_ctx->hw_id, (p_ctx->session_id&0x7F));
1195  }
1196 
1197  ni_log(NI_LOG_TRACE, "decoder total_pkt:%" PRIu64 ", total_ticks:%" PRIu64 " "
1198  "total_time:%" PRIu64 " us\n", p_ctx->frame_num,
1199  p_ctx->codec_total_ticks, codec_end_time - p_ctx->codec_start_time);
1200 
1201  ni_log(NI_LOG_TRACE, "%s(): CTX[Card:%" PRIx64 " / HW:%d / INST:%d]\n",
1202  __FUNCTION__, (int64_t)p_ctx->device_handle, p_ctx->hw_id, p_ctx->session_id);
1203 
1204  // Prevent session open during closing.
1205  p_ctx->ready_to_close = 0;
1206 
1207  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
1208  return retval;
1209 }
1210 
1211 /*!******************************************************************************
1212  * \brief Send a video p_packet to decoder
1213  *
1214  * \param
1215  *
1216  * \return
1217  *******************************************************************************/
1219 {
1220  uint32_t sent_size = 0;
1221  uint32_t packet_size = 0;
1222  uint32_t write_size_bytes = 0;
1223  uint32_t actual_sent_size = 0;
1224  uint32_t pkt_chunk_count = 0;
1225  int retval = NI_LOGAN_RETCODE_SUCCESS;
1226  ni_logan_instance_status_info_t inst_info = { 0 };
1227  int query_retry = 0;
1228  uint32_t ui32LBA = 0;
1229 #ifdef MEASURE_LATENCY
1230  struct timespec logtv;
1231  uint64_t abs_time_ns;
1232 #endif
1233 
1234  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
1235 
1236  if (!p_ctx || !p_packet)
1237  {
1238  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
1240  }
1241 
1242  if ((NI_LOGAN_INVALID_SESSION_ID == p_ctx->session_id))
1243  {
1244  ni_log(NI_LOG_TRACE, "ERROR: %s(): xcoder instance id < 0, return\n",
1245  __FUNCTION__);
1247  LRETURN;
1248  }
1249 
1250 #ifdef MEASURE_LATENCY
1251  if ((p_packet->dts != NI_LOGAN_NOPTS_VALUE) && (p_ctx->frame_time_q != NULL)) {
1252 #ifdef _WIN32
1253  abs_time_ns = ni_logan_gettime_ns();
1254 #else
1255  clock_gettime(CLOCK_REALTIME, &logtv);
1256  abs_time_ns = (logtv.tv_sec*1000000000LL+logtv.tv_nsec);
1257 #endif
1258  ni_logan_lat_meas_q_add_entry(p_ctx->frame_time_q, abs_time_ns, p_packet->dts);
1259  }
1260 #endif
1261 
1262  packet_size = p_packet->data_len;
1263  int current_pkt_size = p_packet->data_len;
1264 
1265  for (; ;)
1266  {
1267  query_retry++;
1268  retval = ni_logan_query_status_info(p_ctx, p_ctx->device_type, &inst_info, retval, nvme_admin_cmd_xcoder_query);
1269  CHECK_ERR_RC2(p_ctx, retval, inst_info, nvme_admin_cmd_xcoder_query,
1270  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
1271  CHECK_VPU_RECOVERY(retval);
1272 
1273  if (NI_LOGAN_RETCODE_SUCCESS != retval ||
1274  inst_info.wr_buf_avail_size < packet_size)
1275  {
1276  ni_log(NI_LOG_TRACE, "Warning dec write query fail rc %d or available "
1277  "buf size %u < pkt size %u , retry: %d\n", retval,
1278  inst_info.wr_buf_avail_size, packet_size, query_retry);
1280  {
1281  p_ctx->required_buf_size = packet_size;
1283  retval = NI_LOGAN_RETCODE_SUCCESS;
1284  LRETURN;
1285  }
1286  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
1288  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
1289  }
1290  else
1291  {
1292  ni_log(NI_LOG_TRACE, "Info dec write query success, available buf size "
1293  "%u >= pkt size %u!\n", inst_info.wr_buf_avail_size, packet_size);
1294  break;
1295  }
1296  }
1297 
1299 
1300  //check for start of stream flag
1301  if (p_packet->start_of_stream)
1302  {
1304  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config,
1305  p_ctx->device_type, p_ctx->hw_id,
1306  &(p_ctx->session_id));
1307  CHECK_VPU_RECOVERY(retval);
1308  if (NI_LOGAN_RETCODE_SUCCESS != retval)
1309  {
1310  ni_log(NI_LOG_TRACE, "ERROR %s(): Failed to send SOS.\n", __FUNCTION__);
1311  LRETURN;
1312  }
1313 
1314  p_packet->start_of_stream = 0;
1315  }
1316 
1317  if (p_packet->p_data)
1318  {
1319  ni_log(NI_LOG_TRACE, "%s() had data to send: packet_size=%u, "
1320  "p_packet->sent_size=%d, p_packet->data_len=%d, "
1321  "p_packet->start_of_stream=%d, p_packet->end_of_stream=%d, "
1322  "p_packet->video_width=%d, p_packet->video_height=%d\n",
1323  __FUNCTION__, packet_size, p_packet->sent_size, p_packet->data_len,
1324  p_packet->start_of_stream, p_packet->end_of_stream,
1325  p_packet->video_width, p_packet->video_height);
1326 
1327  uint32_t send_count = 0;
1328  uint8_t* p_data = (uint8_t*)p_packet->p_data;
1329  // Note: session status is NOT reset but tracked between send
1330  // and recv to catch and recover from a loop condition
1331  // p_ctx->status = 0;
1332 
1333  ni_logan_instance_dec_packet_info_t *p_dec_packet_info;
1334  p_dec_packet_info = (ni_logan_instance_dec_packet_info_t *)p_ctx->p_dec_packet_inf_buf;
1335  p_dec_packet_info->packet_size = packet_size;
1337  p_ctx->blk_io_handle, p_ctx->event_handle, p_ctx->p_dec_packet_inf_buf,
1340  CHECK_ERR_RC(p_ctx, retval, nvme_cmd_xcoder_write,
1341  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
1342  CHECK_VPU_RECOVERY(retval);
1343  if (retval < 0)
1344  {
1345  ni_log(NI_LOG_ERROR, "ERROR %s(): config pkt size command failed\n",
1346  __FUNCTION__);
1348  LRETURN;
1349  }
1350 
1351  if (packet_size % NI_LOGAN_MEM_PAGE_ALIGNMENT) //packet size, already aligned
1352  {
1354  }
1355 
1357  p_data, packet_size, ui32LBA);
1358  CHECK_ERR_RC(p_ctx, retval, nvme_cmd_xcoder_write,
1359  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
1360  CHECK_VPU_RECOVERY(retval);
1361  if (retval < 0)
1362  {
1363  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme command failed\n", __FUNCTION__);
1365  LRETURN;
1366  }
1367 
1368  // reset session status after successful send
1369  p_ctx->status = 0;
1370  p_ctx->required_buf_size = 0;
1371 
1372  sent_size = p_packet->data_len;
1373  p_packet->data_len = 0;
1374 
1375  if (((ni_logan_decoder_params_t*)p_ctx->p_session_config)->nb_save_pkt)
1376  {
1377  char dump_file[128] = { 0 };
1378  long curr_pkt_num = ((long)p_ctx->pkt_num %
1379  ((ni_logan_decoder_params_t*)p_ctx->p_session_config)->nb_save_pkt) + 1;
1380 
1381  snprintf(dump_file, sizeof(dump_file), "%s/pkt-%04ld.bin",
1382  p_ctx->stream_dir_name, curr_pkt_num);
1383 
1384  FILE *f = fopen(dump_file, "wb");
1385  if (f)
1386  {
1387  fwrite(p_packet->p_data, sent_size, 1, f);
1388  fflush(f);
1389  fclose(f);
1390  }
1391  }
1392 
1393  p_ctx->pkt_num++;
1394  }
1395 
1396  //Handle end of stream flag
1397  if (p_packet->end_of_stream)
1398  {
1400  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config,
1401  p_ctx->device_type, p_ctx->hw_id,
1402  &(p_ctx->session_id));
1403  CHECK_VPU_RECOVERY(retval);
1404 
1405  if (NI_LOGAN_RETCODE_SUCCESS != retval)
1406  {
1407  ni_log(NI_LOG_TRACE, "ERROR %s(): Failed to send EOS.\n", __FUNCTION__);
1408  LRETURN;
1409  }
1410 
1411  p_packet->end_of_stream = 0;
1412  p_ctx->ready_to_close = 1;
1413  }
1414 
1415  // Handle PTS
1416  p_ctx->pts_offsets[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ] = p_packet->pts;
1417  p_ctx->flags_array[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ] = p_packet->flags;
1418  if (p_ctx->pkt_index == 0)
1419  {
1420  p_ctx->pkt_offsets_index_min[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ] = 0;
1421  /* minus 1 here. ffmpeg parses the msb 0 of long start code as the last packet's payload for hevc bitstream (hevc_parse).
1422  * move 1 byte forward on all the pkt_offset so that frame_offset coming from fw can fall into the correct range. */
1423  p_ctx->pkt_offsets_index[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ] = current_pkt_size - 1;
1424  }
1425  else
1426  {
1427  // cumulate sizes to correspond to FW offsets
1429  p_ctx->pkt_offsets_index[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ] = p_ctx->pkt_offsets_index[(p_ctx->pkt_index - 1) % NI_LOGAN_FIFO_SZ] + current_pkt_size;
1430 
1431  //Wrapping 32 bits since FW send u32 wrapped values
1432  if (p_ctx->pkt_offsets_index_min[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ] > 0xFFFFFFFF)
1433  {
1434  p_ctx->pkt_offsets_index_min[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ] = p_ctx->pkt_offsets_index_min[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ] - (0x100000000);
1435  p_ctx->pkt_offsets_index[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ] = p_ctx->pkt_offsets_index_min[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ] + current_pkt_size;
1436  }
1437  }
1438 
1439  /* if this wrap-around pkt_offset_index spot is about to be overwritten, free the previous one. */
1440  free(p_ctx->pkt_custom_sei[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ]);
1441 
1442  if (p_packet->p_all_custom_sei)
1443  {
1444  p_ctx->pkt_custom_sei[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ] = malloc(sizeof(ni_logan_all_custom_sei_t));
1445  if (p_ctx->pkt_custom_sei[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ])
1446  {
1447  memcpy(p_ctx->pkt_custom_sei[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ], p_packet->p_all_custom_sei,
1448  sizeof(ni_logan_all_custom_sei_t));
1449  }
1450  else
1451  {
1452  /* warn and lose the sei data. */
1453  ni_log(NI_LOG_ERROR, "%s: failed to allocate custom SEI buffer for pkt error=%d\n",
1454  __FUNCTION__, NI_ERRNO);
1455  }
1456  }
1457  else
1458  {
1459  p_ctx->pkt_custom_sei[p_ctx->pkt_index % NI_LOGAN_FIFO_SZ] = NULL;
1460  }
1461  p_ctx->pkt_index++;
1462 
1463  retval = ni_logan_timestamp_register(p_ctx->buffer_pool, p_ctx->dts_queue, p_packet->dts, 0);
1464  if (NI_LOGAN_RETCODE_SUCCESS != retval)
1465  {
1466  ni_log(NI_LOG_TRACE, "ERROR %s(): ni_logan_timestamp_register() for dts returned "
1467  "%d\n", __FUNCTION__, retval);
1468  }
1469 
1470  END:
1471 
1472  if (NI_LOGAN_RETCODE_SUCCESS == retval)
1473  {
1474  ni_log(NI_LOG_TRACE, "%s(): exit: packets: %" PRIu64 " offset %" PRIu64 " "
1475  "sent_size = %u, available_space = %u, status=%d\n", __FUNCTION__,
1476  p_ctx->pkt_num, (uint64_t)p_packet->pos, sent_size,
1477  inst_info.wr_buf_avail_size, p_ctx->status);
1478  return sent_size;
1479  }
1480  else
1481  {
1482  ni_log(NI_LOG_TRACE, "ERROR %s(): exit: returnErr: %d, p_ctx->status: %d\n",
1483  __FUNCTION__, retval, p_ctx->status);
1484  return retval;
1485  }
1486 }
1487 
1488 static int64_t guess_correct_pts(ni_logan_session_context_t* p_ctx, int64_t reordered_pts, int64_t dts, int64_t last_pts)
1489 {
1490  int64_t pts = NI_LOGAN_NOPTS_VALUE;
1491  if (dts != NI_LOGAN_NOPTS_VALUE)
1492  {
1494  p_ctx->pts_correction_last_dts = dts;
1495  }
1496  else if (reordered_pts != NI_LOGAN_NOPTS_VALUE)
1497  {
1498  p_ctx->pts_correction_last_dts = reordered_pts;
1499  }
1500  if (reordered_pts != NI_LOGAN_NOPTS_VALUE)
1501  {
1502  p_ctx->pts_correction_num_faulty_pts += reordered_pts <= p_ctx->pts_correction_last_pts;
1503  p_ctx->pts_correction_last_pts = reordered_pts;
1504  }
1505  else if (dts != NI_LOGAN_NOPTS_VALUE)
1506  {
1507  p_ctx->pts_correction_last_pts = dts;
1508  }
1510  && reordered_pts != NI_LOGAN_NOPTS_VALUE)
1511  {
1512  pts = reordered_pts;
1513  }
1514  else
1515  {
1516  if (NI_LOGAN_NOPTS_VALUE == last_pts)
1517  {
1518  pts = dts;
1519  }
1520  else if (NI_LOGAN_NOPTS_VALUE != last_pts && dts >= last_pts)
1521  {
1522  pts = dts;
1523  }
1524  else
1525  {
1526  pts = reordered_pts;
1527  }
1528  }
1529  //printf("here pts = %d\n", pts);
1530  return pts;
1531 }
1532 /*!******************************************************************************
1533  * \brief Retrieve a YUV p_frame from decoder
1534  *
1535  * \param
1536  *
1537  * \return
1538  *******************************************************************************/
1540 {
1542  int rx_size = 0;
1543  uint64_t frame_offset = 0;
1544  uint16_t yuvW = 0;
1545  uint16_t yuvH = 0;
1546  uint8_t* p_data_buffer = (uint8_t*) p_frame->p_buffer;
1547  uint32_t data_buffer_size = p_frame->buffer_size;
1548  int i = 0;
1549  int retval = NI_LOGAN_RETCODE_SUCCESS;
1550  int metadata_hdr_size = NI_LOGAN_FW_META_DATA_SZ - sizeof(ni_logan_hwframe_surface_t);
1551  int sei_size = 0;
1552  int frame_cycle = 0;
1553  uint32_t total_bytes_to_read = 0;
1554  uint32_t read_size_bytes = 0;
1555  uint32_t actual_read_size = 0;
1556  int keep_processing = 1;
1557  ni_logan_instance_status_info_t inst_info = { 0 };
1558  int query_retry = 0;
1559  int max_query_retries = (p_ctx->decoder_low_delay? (p_ctx->decoder_low_delay * 1000 / NI_LOGAN_RETRY_INTERVAL_200US + 1) : \
1561  int low_delay_mode = ((ni_logan_decoder_params_t*)p_ctx->p_session_config)->dec_input_params.low_delay_mode;
1562  uint16_t decoder_reorder_delay = (low_delay_mode == 2)? p_ctx->decoder_reorder_delay : 0;
1563  uint32_t ui32LBA = 0;
1564  unsigned int bytes_read_so_far = 0;
1565  int64_t drop_dts = 0;
1566  uint8_t alloc_extra_metadata = 0;
1567  void *p_metadata_buffer = NULL;
1568 
1569 #ifdef MEASURE_LATENCY
1570  struct timespec logtv;
1571  uint64_t abs_time_ns;
1572 #endif
1573 
1574  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
1575 
1576  if (!p_ctx || !p_frame)
1577  {
1578  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
1580  }
1581 
1583  {
1584  ni_log(NI_LOG_TRACE, "ERROR %s(): xcoder instance id < 0, return\n",
1585  __FUNCTION__);
1587  LRETURN;
1588  }
1589  // p_frame->p_data[] can be NULL before actual resolution is returned by
1590  // decoder and buffer pool is allocated, so no checking here.
1591 
1592  total_bytes_to_read = p_frame->data_len[0] + p_frame->data_len[1] +
1593  p_frame->data_len[2] + metadata_hdr_size;
1594  ni_log(NI_LOG_TRACE, "Total bytes to read %d \n",total_bytes_to_read);
1595  for (; ;)
1596  {
1597  query_retry++;
1598  retval = ni_logan_query_status_info(p_ctx, p_ctx->device_type, &inst_info, retval, nvme_admin_cmd_xcoder_query);
1599  CHECK_ERR_RC2(p_ctx, retval, inst_info, nvme_admin_cmd_xcoder_query,
1600  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
1601  CHECK_VPU_RECOVERY(retval);
1602 
1603  ni_log(NI_LOG_TRACE, "Info query inst_info.rd_buf_avail_size = %u\n",
1604  inst_info.rd_buf_avail_size);
1605 
1606  if (NI_LOGAN_RETCODE_SUCCESS != retval)
1607  {
1608  ni_log(NI_LOG_TRACE, "Warning dec read query fail rc %d retry %d\n",
1609  retval, query_retry);
1610 
1611  if (query_retry >= 1000)
1612  {
1613  retval = NI_LOGAN_RETCODE_SUCCESS;
1614  LRETURN;
1615  }
1616  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
1618  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
1619  }
1620  else if (inst_info.rd_buf_avail_size == metadata_hdr_size)
1621  {
1622  ni_log(NI_LOG_TRACE, "Info only metadata hdr is available, seq change?\n");
1623  total_bytes_to_read = metadata_hdr_size;
1624  break;
1625  }
1626  else if (0 == inst_info.rd_buf_avail_size)
1627  {
1628  // query to see if it is eos now, if we have sent it
1630  {
1631  ni_log(NI_LOG_TRACE, "Info dec query, ready_to_close %u, ready_to_flush %u, ctx status %d,"
1632  " try %d\n", p_ctx->ready_to_close, p_ctx->ready_to_flush, p_ctx->status, query_retry);
1633  retval = ni_logan_query_stream_info(p_ctx, NI_LOGAN_DEVICE_TYPE_DECODER, &data, 0);
1634  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_query,
1635  p_ctx->device_type, p_ctx->hw_id,
1636  &(p_ctx->session_id));
1637  CHECK_VPU_RECOVERY(retval);
1638 
1639  if (data.is_flushed ||
1640  query_retry >= NI_LOGAN_MAX_DEC_SESSION_READ_QUERY_EOS_RETRIES) // 15000 retries
1641  {
1642  ni_log(NI_LOG_DEBUG, "Info eos or flush buffers reached: is_flushed %u try %d.\n",
1643  data.is_flushed, query_retry);
1644  if (query_retry >= NI_LOGAN_MAX_DEC_SESSION_READ_QUERY_EOS_RETRIES) //15000 retries
1645  {
1646  ni_log(NI_LOG_INFO, "Info eos reached or flush buffers exceeding max retries: is_flushed %u try %d.\n",
1647  data.is_flushed, query_retry);
1648  }
1649  if (p_ctx->ready_to_close)
1650  {
1651  p_frame->end_of_stream = 1;
1652  }
1653  else
1654  {
1655  p_ctx->ready_to_flush = NI_LOGAN_DECODE_FLUSH_BUFFER_OFF; // decode flush buffers finished;
1656  }
1657  retval = NI_LOGAN_RETCODE_SUCCESS;
1658  LRETURN;
1659  }
1660  else
1661  {
1662  ni_log(NI_LOG_TRACE, "Dec read available buf size == 0, query try %d,"
1663  " retrying ..\n", query_retry);
1664  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
1666  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
1667  continue;
1668  }
1669  }
1670 
1671  if (p_ctx->decoder_low_delay && inst_info.frames_dropped && p_ctx->is_sequence_change)
1672  {
1673  ni_log(NI_LOG_TRACE, "Info inst_info.frames_dropped = %u\n",
1674  inst_info.frames_dropped);
1675  retval = NI_LOGAN_RETCODE_SUCCESS;
1676  LRETURN;
1677  }
1678 
1679  ni_log(NI_LOG_TRACE, "Warning dec read available buf size == 0, eos %u "
1680  "nb try %d\n", p_frame->end_of_stream, query_retry);
1681 
1683  (p_ctx->frame_num + decoder_reorder_delay < p_ctx->pkt_num && p_ctx->decoder_low_delay)) &&
1684  (query_retry < max_query_retries))
1685  {
1687  (inst_info.wr_buf_avail_size > p_ctx->required_buf_size))
1688  {
1689  ni_log(NI_LOG_TRACE, "Info dec write buffer is enough, available buf "
1690  "size %u >= required size %u !\n",
1691  inst_info.wr_buf_avail_size, p_ctx->required_buf_size);
1692  p_ctx->status = 0;
1693  p_ctx->required_buf_size = 0;
1694  }
1695  else
1696  {
1697  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
1699  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
1700  continue;
1701  }
1702  }
1703  else if (p_ctx->frame_num + decoder_reorder_delay < p_ctx->pkt_num &&
1704  p_ctx->decoder_low_delay && low_delay_mode == 2)
1705  {
1706  p_ctx->decoder_reorder_delay++;
1707  ni_log(NI_LOG_INFO, "Warning: time out on receiving a decoded frame"
1708  "from the decoder, increase reorder count: %d, received frame_num: "
1709  "%" PRIu64 ", sent pkt_num: %" PRIu64 ", sending another packet.\n",
1710  p_ctx->decoder_reorder_delay, p_ctx->frame_num, p_ctx->pkt_num);
1711  }
1712  else if (p_ctx->frame_num < p_ctx->pkt_num && p_ctx->decoder_low_delay && low_delay_mode != 2)
1713  {
1714  if((p_ctx->pkt_num - p_ctx->frame_num) != p_ctx->decoder_drop_frame_num)
1715  {
1716  p_ctx->decoder_drop_frame_num = p_ctx->pkt_num - p_ctx->frame_num;
1717  ni_log(NI_LOG_INFO, "Warning: time out on receiving a decoded frame"
1718  "from the decoder, assume dropped, received frame_num: "
1719  "%" PRIu64 ", sent pkt_num: %" PRIu64 ", pkt_num-frame_num: "
1720  "%d, sending another packet.\n", p_ctx->frame_num,
1721  p_ctx->pkt_num, p_ctx->decoder_drop_frame_num);
1722  }
1723  }
1724  retval = NI_LOGAN_RETCODE_SUCCESS;
1725  LRETURN;
1726  }
1727  else
1728  {
1729  // We have to ensure there are adequate number of DTS for picture
1730  // reorder delay otherwise wait for more packets to be sent to decoder.
1731  ni_logan_timestamp_table_t* p_dts_queue = p_ctx->dts_queue;
1732  if ((int)p_dts_queue->list.count < p_ctx->pic_reorder_delay + 1 &&
1733  !p_ctx->ready_to_close
1736  {
1737  retval = NI_LOGAN_RETCODE_SUCCESS;
1738  LRETURN;
1739  }
1740 
1741  // get actual YUV transfer size if this is the stream's very first read
1742  if (0 == p_ctx->active_video_width || 0 == p_ctx->active_video_height)
1743  {
1744  retval = ni_logan_query_stream_info(p_ctx, NI_LOGAN_DEVICE_TYPE_DECODER, &data, 0);
1745  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_query,
1746  p_ctx->device_type, p_ctx->hw_id,
1747  &(p_ctx->session_id));
1748  CHECK_VPU_RECOVERY(retval);
1749 
1750  ni_log(NI_LOG_TRACE, "Info dec YUV query, pic size %ux%u xfer frame size "
1751  "%ux%u frame-rate %u is_flushed %u\n", data.picture_width,
1753  data.transfer_frame_height, data.frame_rate, data.is_flushed);
1756  p_ctx->decoder_reorder_delay = data.reorder_delay;
1757  p_ctx->active_bit_depth = (p_ctx->bit_depth_factor==2) ? 10 : 8;
1758  p_ctx->is_sequence_change = 1;
1759 
1760  ni_log(NI_LOG_TRACE, "Info dec YUV, adjust frame size from %ux%u %dbits "
1761  "to %ux%u, reorder_delay=%u\n",
1762  p_frame->video_width, p_frame->video_height,p_ctx->active_bit_depth,
1763  p_ctx->active_video_width, p_ctx->active_video_height,
1764  p_ctx->decoder_reorder_delay);
1765 
1767 
1768  // set up decoder YUV frame buffer pool
1771  p_ctx->active_video_height,
1773  p_ctx->bit_depth_factor))
1774  {
1775  ni_log(NI_LOG_ERROR, "ERROR %s(): Cannot allocate fme buf pool.\n",
1776  __FUNCTION__);
1779 #ifdef XCODER_SELF_KILL_ERR
1780  // if need to terminate at such occasion when continuing is not
1781  // possible, trigger a codec closure
1782  ni_log(NI_LOG_ERROR, "Terminating due to persistent failures\n");
1783  kill(getpid(), SIGTERM);
1784 #endif
1785  LRETURN;
1786  }
1787 
1789  p_ctx->dec_fme_buf_pool, p_frame, 1, // get mem buffer
1790  p_ctx->active_video_width, p_ctx->active_video_height,
1792  p_ctx->bit_depth_factor);
1793 
1794  if (NI_LOGAN_RETCODE_SUCCESS != retval)
1795  {
1796  LRETURN;
1797  }
1798  total_bytes_to_read = p_frame->data_len[0] + p_frame->data_len[1] +
1799  p_frame->data_len[2] + metadata_hdr_size;
1800  p_data_buffer = (uint8_t*) p_frame->p_buffer;
1801 
1802  // make sure we don't read more than available
1803  ni_log(NI_LOG_TRACE, "Info dec buf size: %u YUV frame + meta-hdr size: %u "
1804  "available: %u\n", p_frame->buffer_size, total_bytes_to_read,
1805  inst_info.rd_buf_avail_size);
1806  }
1807  break;
1808  }
1809  }
1810 
1811  if (p_ctx->decoder_last_drop_frame_num < inst_info.frames_dropped) {
1812  for (i = p_ctx->decoder_last_drop_frame_num; i < inst_info.frames_dropped; i++)
1813  {
1814  ni_logan_timestamp_get_with_threshold(p_ctx->dts_queue, 0, &drop_dts,
1815  LOGAN_XCODER_FRAME_OFFSET_DIFF_THRES, (p_ctx->frame_num % 500 == 0),
1816  p_ctx->buffer_pool);
1817  }
1818  p_ctx->decoder_last_drop_frame_num = inst_info.frames_dropped;
1819  ni_log(NI_LOG_DEBUG, "drop total %d dts in queue\n", p_ctx->decoder_last_drop_frame_num);
1820  }
1821 
1822  // A workaround to handle continuous sequence changes, LGXCOD-3653
1823  if (inst_info.rd_buf_avail_size == metadata_hdr_size && !p_data_buffer && !p_frame->p_buffer)
1824  {
1825  // allocate p_data_buffer to read the metadata
1826  int buffer_size = ((metadata_hdr_size + (NI_LOGAN_MEM_PAGE_ALIGNMENT - 1)) /
1828  if (ni_logan_posix_memalign(&p_metadata_buffer, sysconf(_SC_PAGESIZE), buffer_size))
1829  {
1830  ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate metadata buffer.\n",
1831  NI_ERRNO, __func__);
1833  LRETURN;
1834  }
1835  p_data_buffer = (uint8_t *)p_metadata_buffer;
1836  p_frame->p_buffer = p_metadata_buffer;
1837  p_frame->buffer_size = buffer_size;
1838  alloc_extra_metadata = 1;
1839  }
1840 
1841  ni_log(NI_LOG_TRACE, "total_bytes_to_read %d max_nvme_io_size %d ylen %d "
1842  "cr len %d cb len %d hdr %d\n", total_bytes_to_read,
1843  p_ctx->max_nvme_io_size, p_frame->data_len[0], p_frame->data_len[1],
1844  p_frame->data_len[2], metadata_hdr_size);
1845 
1846  if (inst_info.rd_buf_avail_size < total_bytes_to_read ||
1847  inst_info.rd_buf_avail_size > p_frame->buffer_size)
1848  {
1849  ni_log(NI_LOG_ERROR, "ERROR %s() avaliable size(%u) less than needed (%u), "
1850  "or more than buffer allocated (%u)\n", __FUNCTION__,
1851  inst_info.rd_buf_avail_size, total_bytes_to_read, p_frame->buffer_size);
1852  ni_logan_assert(0);
1853  }
1854 
1855  read_size_bytes = inst_info.rd_buf_avail_size;
1857  if (read_size_bytes % NI_LOGAN_MEM_PAGE_ALIGNMENT)
1858  {
1859  read_size_bytes = ( (read_size_bytes / NI_LOGAN_MEM_PAGE_ALIGNMENT) * NI_LOGAN_MEM_PAGE_ALIGNMENT) + NI_LOGAN_MEM_PAGE_ALIGNMENT;
1860  }
1861 
1862  retval = ni_logan_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle,
1863  p_data_buffer, read_size_bytes, ui32LBA);
1864  CHECK_ERR_RC(p_ctx, retval, nvme_cmd_xcoder_read,
1865  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
1866  CHECK_VPU_RECOVERY(retval);
1867  if (retval < 0)
1868  {
1869  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme command failed\n", __FUNCTION__);
1871  LRETURN;
1872  }
1873  else
1874  {
1875  // command issued successfully, now exit
1876 
1878  (ni_logan_metadata_dec_frame_t*)((uint8_t*)p_frame->p_buffer
1879  + p_frame->data_len[0] + p_frame->data_len[1]
1880  + p_frame->data_len[2]);
1881 
1882  if (inst_info.rd_buf_avail_size != metadata_hdr_size)
1883  {
1884  sei_size = p_meta->sei_size;
1885  frame_cycle = p_meta->frame_cycle;
1886  }
1887  else if (low_delay_mode == 2 && !p_ctx->decoder_reorder_delay)
1888  {
1889  // get decoder_reorder_delay from meta when decoder_reorder_delay is 0.
1890  // Note this is not essential,
1891  // dec_reorder_delay should be already got through query command.
1892  p_ctx->decoder_reorder_delay = p_meta->dec_reorder_delay;
1893  }
1894  p_ctx->codec_total_ticks += frame_cycle;
1895  total_bytes_to_read = total_bytes_to_read + sei_size;
1896 
1897  ni_log(NI_LOG_TRACE, "%s success, size %d total_bytes_to_read include "
1898  "sei %d sei_size %d frame_cycle %d\n", __FUNCTION__, retval,
1899  total_bytes_to_read, sei_size, frame_cycle);
1900  }
1901 
1902  bytes_read_so_far = total_bytes_to_read;
1903  // Note: session status is NOT reset but tracked between send
1904  // and recv to catch and recover from a loop condition
1905 
1906  p_frame->src_codec = p_ctx->codec_format;
1907  rx_size = ni_logan_create_frame(p_frame, bytes_read_so_far, &frame_offset, false);
1908  p_ctx->frame_pkt_offset = frame_offset;
1909 
1910  // if using old firmware, bit_depth=0 so use bit_depth_factor
1911  if (!p_frame->bit_depth)
1912  p_frame->bit_depth = (p_ctx->bit_depth_factor==2)?10:8;
1913 
1914  // if sequence change, update bit depth factor
1915  if ((rx_size == 0))
1916  p_ctx->bit_depth_factor = (p_frame->bit_depth==10) ? 2: 1;
1917 
1918  if (rx_size > 0)
1919  {
1920  ni_log(NI_LOG_TRACE, "%s(): s-state %d seq change %d\n", __FUNCTION__,
1921  p_ctx->session_run_state, p_ctx->is_sequence_change);
1922  if (ni_logan_timestamp_get_with_threshold(p_ctx->dts_queue, 0, (int64_t*)&p_frame->dts,
1923  LOGAN_XCODER_FRAME_OFFSET_DIFF_THRES, (p_ctx->frame_num % 500 == 0),
1925  {
1926  if (p_ctx->last_dts != NI_LOGAN_NOPTS_VALUE && !p_ctx->ready_to_close &&
1928  {
1929  // Mark as DTS padding for offset compensation
1930  p_ctx->pic_reorder_delay++;
1931  p_frame->dts = p_ctx->last_dts + p_ctx->last_dts_interval;
1932  ni_log(NI_LOG_ERROR, "Padding DTS:%ld.\n", p_frame->dts);
1933  }
1934  else
1935  {
1936  p_frame->dts = NI_LOGAN_NOPTS_VALUE;
1937  }
1938  }
1939 
1940  // Read the following DTS for picture reorder delay
1941  if (p_ctx->is_sequence_change)
1942  {
1943  for (i = 0; i < p_ctx->pic_reorder_delay; i++)
1944  {
1945  if (p_ctx->last_pts == NI_LOGAN_NOPTS_VALUE && p_ctx->last_dts == NI_LOGAN_NOPTS_VALUE)
1946  {
1947  // If the p_frame->pts is unknown in the very beginning of the stream
1948  // (video stream only) we assume p_frame->pts == 0 as well as DTS less
1949  // than PTS by 1000 * 1/timebase
1950  if (p_frame->pts >= p_frame->dts && p_frame->pts - p_frame->dts < 1000)
1951  {
1952  break;
1953  }
1954  }
1955 
1956  if (ni_logan_timestamp_get_with_threshold(p_ctx->dts_queue, 0, (int64_t*)&p_frame->dts,
1957  LOGAN_XCODER_FRAME_OFFSET_DIFF_THRES, (p_ctx->frame_num % 500 == 0),
1959  {
1960  p_frame->dts = NI_LOGAN_NOPTS_VALUE;
1961  }
1962  }
1963  // Reset for DTS padding counting
1964  p_ctx->pic_reorder_delay = 0;
1965  }
1966 
1967  // Handle PTS
1968  i = rotated_array_binary_search(p_ctx->pkt_offsets_index_min,
1969  p_ctx->pkt_offsets_index,
1970  NI_LOGAN_FIFO_SZ, frame_offset);
1971  if (i >= 0)
1972  {
1973  // According to LGXCOD-3099 the frame_offset would be less than
1974  // expected by the size of SEI unit when there is malformed SEI
1975  // being sent into decoder. That will lead to mismatch of the
1976  // true PTS offset with the decoded frame. So we need to correct
1977  // the offset range when there is suspicious frame_offset for
1978  // decoded frames.
1979  uint64_t d1 = frame_offset - p_ctx->pkt_offsets_index_min[i];
1980  uint64_t d2 = p_ctx->pkt_offsets_index[i] - frame_offset;
1981  if (d1 > d2)
1982  {
1983  // When the frame_offset is closer to the right boundary, the
1984  // right margin is caused by the missing SEI size.
1985  i++;
1986  }
1987 
1988  p_frame->pts = p_ctx->pts_offsets[i];
1989  p_frame->flags = p_ctx->flags_array[i];
1990  p_frame->p_custom_sei = (uint8_t *)p_ctx->pkt_custom_sei[i % NI_LOGAN_FIFO_SZ];
1991  p_ctx->pkt_custom_sei[i % NI_LOGAN_FIFO_SZ] = NULL;
1992  }
1993  else
1994  {
1995  //backup solution pts
1996  p_frame->pts = p_ctx->last_pts + p_ctx->last_dts_interval;
1997  ni_log(NI_LOG_ERROR, "ERROR: NO pts found consider increasing NI_LOGAN_FIFO_SZ!\n");
1998  }
1999 
2000  p_frame->pts = guess_correct_pts(p_ctx, p_frame->pts, p_frame->dts, p_ctx->last_pts);
2001  p_ctx->last_pts = p_frame->pts;
2002  if ((0 == p_ctx->is_sequence_change) && (NI_LOGAN_NOPTS_VALUE != p_frame->dts) && (NI_LOGAN_NOPTS_VALUE != p_ctx->last_dts))
2003  {
2004  p_ctx->last_dts_interval = p_frame->dts - p_ctx->last_dts;
2005  }
2006  p_ctx->last_dts = p_frame->dts;
2007  p_ctx->is_sequence_change = 0;
2008  p_ctx->frame_num++;
2009  }
2010 
2011  ni_log(NI_LOG_TRACE, "%s(): received data [0x%08x]\n", __FUNCTION__, rx_size);
2012  ni_log(NI_LOG_TRACE, "%s(): p_frame->start_of_stream=%d "
2013  "p_frame->end_of_stream=%d p_frame->video_width=%d "
2014  "p_frame->video_height=%d\n", __FUNCTION__, p_frame->start_of_stream,
2015  p_frame->end_of_stream, p_frame->video_width, p_frame->video_height);
2016  ni_log(NI_LOG_TRACE, "%s(): p_frame->data_len[0/1/2]=%d/%d/%d\n", __FUNCTION__,
2017  p_frame->data_len[0], p_frame->data_len[1], p_frame->data_len[2]);
2018 
2019  if (p_ctx->frame_num % 500 == 0)
2020  {
2021  ni_log(NI_LOG_TRACE, "Decoder pts queue size = %d dts queue size = %d\n\n",
2022  ((ni_logan_timestamp_table_t*)p_ctx->pts_table)->list.count,
2023  ((ni_logan_timestamp_table_t*)p_ctx->dts_queue)->list.count);
2024  // scan and clean up
2026  }
2027 
2028 #ifdef MEASURE_LATENCY
2029  if (p_frame->dts != NI_LOGAN_NOPTS_VALUE && p_ctx->frame_time_q != NULL)
2030  {
2031 #ifdef _WIN32
2032  abs_time_ns = ni_logan_gettime_ns();
2033 #else
2034  clock_gettime(CLOCK_REALTIME, &logtv);
2035  abs_time_ns = (logtv.tv_sec*1000000000LL+logtv.tv_nsec);
2036 #endif
2037  ni_log(NI_LOG_INFO, "DTS:%lld,DELTA:%lu,dLAT:%lu,fLAT:%lu;\n",
2038  p_frame->dts,
2039  abs_time_ns - p_ctx->prev_read_frame_time,
2040  ni_logan_lat_meas_q_check_latency(p_ctx->frame_time_q, abs_time_ns, p_frame->dts),
2041  p_ctx->pkt_num - p_ctx->frame_num);
2042  p_ctx->prev_read_frame_time = abs_time_ns;
2043  }
2044 #endif
2045 
2046  END:
2047 
2049  {
2050  ni_log(NI_LOG_ERROR, "ni_logan_decoder_session_read(): bad exit, retval = %d\n",retval);
2051  void* p_buffer = NULL;
2052  void* p_debug_data_buffer = NULL;
2054  ni_logan_instance_debugInfo_t ni_logan_instance_debugInfo;
2055  uint32_t debug_dataLen;
2056  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), dataLen))
2057  {
2058  ni_log(NI_LOG_ERROR, "ERROR %d: ni_logan_query_instance_buf_info() Cannot allocate buffer.\n", NI_ERRNO);
2060  return retval;
2061  }
2062 
2063  memset(p_buffer, 0, dataLen);
2064 
2066 
2067  if (ni_logan_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_buffer, dataLen, ui32LBA) < 0)
2068  {
2069  ni_log(NI_LOG_ERROR, " QUERY_INSTANCE_DEBUG_INFO_R(): NVME command Failed\n");
2071  ni_logan_aligned_free(p_buffer);
2072  LRETURN;
2073  }
2074 
2075  //No need to flip the bytes since the datastruct has only uint8_t datatypes
2076  memcpy((void*)&ni_logan_instance_debugInfo, p_buffer, sizeof(ni_logan_instance_debugInfo_t));
2077 
2078  ni_log(NI_LOG_ERROR, "DEBUG INFO(): Core[%d][%d] ErrInst 0x%x, PktTotal %d, PktSize 0x%x, BufAddr 0x%x, WrPtr 0x%x, RdPtr 0x%x, Size %d\n",
2079  ni_logan_instance_debugInfo.ui8VpuCoreError,
2080  ni_logan_instance_debugInfo.ui8VpuInstId,
2081  ni_logan_instance_debugInfo.ui32VpuInstError,
2082  ni_logan_instance_debugInfo.ui8DataPktSeqTotal,
2083  ni_logan_instance_debugInfo.ui32DataPktSize,
2084  ni_logan_instance_debugInfo.ui32BufferAddr,
2085  ni_logan_instance_debugInfo.ui32BufferWrPt,
2086  ni_logan_instance_debugInfo.ui32BufferRdPt,
2087  ni_logan_instance_debugInfo.ui32BufferSize);
2088 
2089  if(ni_logan_instance_debugInfo.ui32VpuInstError & (1 << ni_logan_instance_debugInfo.ui8VpuInstId))
2090  {
2091  //Debug data buffer
2092  debug_dataLen = ((ni_logan_instance_debugInfo.ui32DataPktSize + (NI_LOGAN_MEM_PAGE_ALIGNMENT - 1)) / NI_LOGAN_MEM_PAGE_ALIGNMENT) * NI_LOGAN_MEM_PAGE_ALIGNMENT;
2093  if (ni_logan_posix_memalign(&p_debug_data_buffer, sysconf(_SC_PAGESIZE), debug_dataLen))
2094  {
2095  ni_log(NI_LOG_ERROR, "ERROR %d: ni_logan_query_instance_buf_info() Cannot allocate buffer.\n", NI_ERRNO);
2097  ni_logan_aligned_free(p_buffer);
2098  return retval;
2099  }
2100 #define DUMP
2101 #ifdef DUMP
2102  char dump_info_file[128] = { 0 };
2103  char dump_data_file[128] = { 0 };
2104  char dump_info[256] = { 0 };
2105  struct timeval tv;
2106  struct tm cur_tm;
2107  char cur_date[20];
2108  char cur_time[20];
2109 
2110 #ifdef _WIN32
2111  localtime_s(&cur_tm, (time_t*)&tv.tv_sec);
2112 #else
2113  localtime_r((time_t*)&tv.tv_sec, &cur_tm);
2114 #endif
2115  (void) ni_logan_gettimeofday(&tv, NULL);
2116  decoder_dump_dir_create(p_ctx);
2117 
2118  snprintf(cur_date,20,"%d-%02d-%02d", cur_tm.tm_year+1900,cur_tm.tm_mon+1,cur_tm.tm_mday);
2119  snprintf(cur_time,20,"%02d_%02d_%02d", cur_tm.tm_hour,cur_tm.tm_min,cur_tm.tm_sec);
2120 
2121  ni_log(NI_LOG_ERROR, "current data %s, time is %s\n", cur_date, cur_time);
2122 
2123  snprintf(dump_info_file, sizeof(dump_info_file), "%s/%s_%s_%u_%u_%u_DEBUG_INFO.txt",
2124  p_ctx->stream_dir_name,
2125  cur_date, cur_time,
2126  p_ctx->session_id,
2127  ni_logan_instance_debugInfo.ui8VpuCoreError,
2128  ni_logan_instance_debugInfo.ui8VpuInstId);
2129 
2130  FILE *fp_info = fopen(dump_info_file, "wb");
2131  if (!fp_info)
2132  {
2133  ni_log(NI_LOG_ERROR, "Error create decoder pkt dump log: %s\n", dump_info_file);
2134  }
2135 
2136  //Dump info
2137  snprintf(dump_info, sizeof(dump_info), "DEBUG INFO(): Core[%d][%d] ErrInst 0x%x, PktTotal %d, PktSize 0x%x, BufAddr 0x%x, WrPtr 0x%x, RdPtr 0x%x, Size %d\n",
2138  ni_logan_instance_debugInfo.ui8VpuCoreError,
2139  ni_logan_instance_debugInfo.ui8VpuInstId,
2140  ni_logan_instance_debugInfo.ui32VpuInstError,
2141  ni_logan_instance_debugInfo.ui8DataPktSeqTotal,
2142  ni_logan_instance_debugInfo.ui32DataPktSize,
2143  ni_logan_instance_debugInfo.ui32BufferAddr,
2144  ni_logan_instance_debugInfo.ui32BufferWrPt,
2145  ni_logan_instance_debugInfo.ui32BufferRdPt,
2146  ni_logan_instance_debugInfo.ui32BufferSize);
2147 
2148  if (fp_info)
2149  {
2150  fwrite(dump_info, strlen(dump_info), 1, fp_info);
2151  fflush(fp_info);
2152  fclose(fp_info);
2153  }
2154 
2155  //Dump data
2156  snprintf(dump_data_file, sizeof(dump_data_file), "%s/%s_%s_%u_%u_%u_DEBUG_DATA.bin",
2157  p_ctx->stream_dir_name,
2158  cur_date, cur_time,
2159  p_ctx->session_id,
2160  ni_logan_instance_debugInfo.ui8VpuCoreError,
2161  ni_logan_instance_debugInfo.ui8VpuInstId);
2162 
2163  FILE *fp_data = fopen(dump_data_file, "wb");
2164  if (!fp_data)
2165  {
2166  ni_log(NI_LOG_ERROR, "Error create decoder pkt dump log: %s\n", dump_data_file);
2167  }
2168 #endif
2169 
2170  while(ni_logan_instance_debugInfo.ui8DataPktSeqNum < (ni_logan_instance_debugInfo.ui8DataPktSeqTotal - 1))
2171  {
2172  memset(p_buffer, 0, dataLen);
2173 
2175 
2176  if (ni_logan_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_buffer, dataLen, ui32LBA) < 0)
2177  {
2178  ni_log(NI_LOG_ERROR, " QUERY_INSTANCE_DEBUG_INFO_R(): NVME command Failed\n");
2180  ni_logan_aligned_free(p_debug_data_buffer);
2181  ni_logan_aligned_free(p_buffer);
2182  LRETURN;
2183  }
2184 
2185  memcpy((void*)&ni_logan_instance_debugInfo, p_buffer, sizeof(ni_logan_instance_debugInfo_t));
2186 
2187  ni_log(NI_LOG_ERROR, "DEBUG INFO(): Dumping data packet - %d/%d\n",
2188  ni_logan_instance_debugInfo.ui8DataPktSeqNum,
2189  ni_logan_instance_debugInfo.ui8DataPktSeqTotal - 1);
2190 
2192 
2193  memset(p_debug_data_buffer, 0, debug_dataLen);
2194 
2195  if (ni_logan_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_debug_data_buffer, debug_dataLen, ui32LBA) < 0)
2196  {
2197  ni_log(NI_LOG_ERROR, " QUERY_INSTANCE_DEBUG_DATA_R(): NVME command Failed\n");
2199  ni_logan_aligned_free(p_debug_data_buffer);
2200  ni_logan_aligned_free(p_buffer);
2201  LRETURN;
2202  }
2203 
2204 #ifdef DUMP
2205  //TODO: Write out p_debug_data_buffer to a file and concat them at the end
2206  if (fp_data)
2207  {
2208  fwrite(p_debug_data_buffer, debug_dataLen, 1, fp_data);
2209  fflush(fp_data);
2210  }
2211 #endif
2212  }
2213  ni_logan_aligned_free(p_debug_data_buffer);
2214 
2215 #ifdef DUMP
2216  if (fp_data)
2217  {
2218  fclose(fp_data);
2219  }
2220 #endif
2221 
2222  }
2223  ni_logan_aligned_free(p_buffer);
2224  }
2225 
2226  if (alloc_extra_metadata && p_metadata_buffer)
2227  {
2228  ni_logan_aligned_free(p_metadata_buffer);
2229  p_frame->p_buffer = NULL;
2230  p_frame->buffer_size = 0;
2231  }
2232 
2233  if (NI_LOGAN_RETCODE_SUCCESS != retval)
2234  {
2235  ni_log(NI_LOG_TRACE, "%s(): bad exit, retval = %d\n", __FUNCTION__, retval);
2236  return retval;
2237  }
2238  else
2239  {
2240  ni_log(NI_LOG_TRACE, "%s(): exit, rx_size = %d\n", __FUNCTION__, rx_size);
2241  return rx_size;
2242  }
2243 }
2244 
2245 /*!******************************************************************************
2246  * \brief Query current decoder status
2247  *
2248  * \param
2249  *
2250  * \return
2251  *******************************************************************************/
2253 {
2255  int retval = NI_LOGAN_RETCODE_SUCCESS;
2256 
2257  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
2258 
2259  if (!p_ctx)
2260  {
2261  ni_log(NI_LOG_TRACE, "ERROR: %s() passed parameters are null!, return\n",
2262  __FUNCTION__);
2264  }
2265 
2267 
2268  if (NI_LOGAN_RETCODE_SUCCESS == retval)
2269  {
2270  p_ctx->load_query.current_load = (uint32_t)data.process_load_percent;
2271  p_ctx->load_query.fw_model_load = (uint32_t)data.fw_model_load;
2272  p_ctx->load_query.fw_video_mem_usage = (uint32_t)data.fw_video_mem_usage;
2273  p_ctx->load_query.total_contexts = (uint32_t)data.active_sub_instances_cnt;
2275  ni_log(NI_LOG_TRACE, "%s current_load:%d fw_model_load:%d fw_video_mem_usage:%d "
2276  "active_contexts %d temperature %d\n", __FUNCTION__,
2279  p_ctx->composite_temperature);
2280  }
2281 
2282  return retval;
2283 }
2284 
2285 /*!******************************************************************************
2286  * \brief Open a xcoder encoder instance
2287  *
2288  * \param
2289  *
2290  * \return
2291  *******************************************************************************/
2293 {
2295  uint32_t buffer_size = 0;
2296  void *p_signature = NULL;
2297  ni_logan_encoder_params_t* p_param;
2298  uint32_t model_load = 0;
2299  ni_logan_instance_status_info_t inst_info = { 0 };
2300  void* p_buffer = NULL;
2301  ni_logan_encoder_session_open_info_t session_info = { 0 };
2302  int query_retry = 0;
2303  uint32_t ui32LBA = 0;
2304 
2305  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
2306 
2307  if (!p_ctx)
2308  {
2309  ni_log(NI_LOG_TRACE, "ERROR: %s(): NULL pointer p_config passed\n", __FUNCTION__);
2311  LRETURN;
2312  }
2313 
2314  p_param = (ni_logan_encoder_params_t*)p_ctx->p_session_config;
2315  p_ctx->auto_dl_handle = NI_INVALID_DEVICE_HANDLE;
2316 
2317  // In yuvbypass mode, encoder device must keep consistent with uploader or decoder device
2318  // check the serial number here to confirm this.
2319  if (p_ctx->hw_action == NI_LOGAN_CODEC_HW_ENABLE)
2320  {
2321  int c;
2324 
2325  for (c = 0; c < 20; c++)
2326  {
2327  if (p_ctx->e_serial_number.ai8Sn[c] != p_ctx->d_serial_number.ai8Sn[c])
2328  {
2329  //QDFW-315 Autodownload
2330  p_ctx->auto_dl_handle = p_ctx->sender_handle;
2331  ni_log(NI_LOG_INFO, "Autodownload device handle set %d!\n", p_ctx->auto_dl_handle);
2333  break;
2334  }
2335  }
2336  }
2337 
2338  //Check if there is an instance or we need a new one
2340  {
2341  int i;
2343  p_ctx->pts_table = NULL;
2344  p_ctx->dts_queue = NULL;
2345  p_ctx->buffer_pool = NULL;
2346  p_ctx->status = 0;
2347  p_ctx->key_frame_type = 0;
2348  p_ctx->keyframe_factor = 1;
2349  p_ctx->frame_num = 0;
2350  p_ctx->pkt_num = 0;
2351  p_ctx->rc_error_count = 0;
2352  p_ctx->force_frame_type = 0;
2353  p_ctx->required_buf_size = 0;
2354  p_ctx->ready_to_close = 0;
2355  // Sequence change tracking related stuff
2356  p_ctx->active_video_width = 0;
2357  p_ctx->active_video_height = 0;
2358  p_ctx->active_bit_depth = 0;
2359  p_ctx->enc_pts_w_idx = 0;
2360  p_ctx->enc_pts_r_idx = 0;
2362  p_ctx->codec_total_ticks = 0;
2363  p_ctx->p_all_zero_buf = NULL;
2364  p_ctx->p_dec_packet_inf_buf = NULL;
2365  p_ctx->session_timestamp = 0;
2366  p_ctx->force_frame_pts_size = 0;
2367  p_ctx->force_frame_pkt_num = 0;
2368 
2369  memset(&p_ctx->force_frame_pts_table[0], 0, sizeof(p_ctx->force_frame_pts_table));
2370 
2371  struct timeval tv;
2372  ni_logan_gettimeofday(&tv, NULL);
2373  p_ctx->codec_start_time = tv.tv_sec*1000000ULL + tv.tv_usec;
2374 
2375 #ifdef _WIN32
2377  if (p_ctx->event_handle == NI_INVALID_EVENT_HANDLE)
2378  {
2380  LRETURN;
2381  }
2382 
2384  if (p_ctx->thread_event_handle == NI_INVALID_EVENT_HANDLE)
2385  {
2387  LRETURN;
2388  }
2389 #endif
2390 
2391  memset(&(p_ctx->param_err_msg[0]), 0, sizeof(p_ctx->param_err_msg));
2392  model_load = (uint32_t)p_param->source_width * (uint32_t)p_param->source_height * (uint32_t)p_param->enc_input_params.frame_rate;
2393 
2394  ni_log(NI_LOG_TRACE, "Model load info: Width:%d Height:%d FPS:%d Load %ld\n",
2395  p_param->source_width, p_param->source_height, p_param->enc_input_params.frame_rate, model_load);
2396 
2397  //malloc zero data buffer
2398  if(ni_logan_posix_memalign(&p_ctx->p_all_zero_buf, sysconf(_SC_PAGESIZE), NI_LOGAN_DATA_BUFFER_LEN))
2399  {
2400  ni_log(NI_LOG_ERROR, "ERROR %d: %s() alloc all zero buffer failed\n",
2401  NI_ERRNO, __FUNCTION__);
2403  LRETURN;
2404  }
2405  memset(p_ctx->p_all_zero_buf, 0, NI_LOGAN_DATA_BUFFER_LEN);
2406 
2407  //malloc data buffer
2408  if(ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), NI_LOGAN_DATA_BUFFER_LEN))
2409  {
2410  ni_log(NI_LOG_ERROR, "ERROR %d: %s() alloc data buffer failed\n",
2411  NI_ERRNO, __FUNCTION__);
2413  LRETURN;
2414  }
2415  memset(p_buffer, 0, NI_LOGAN_DATA_BUFFER_LEN);
2416 
2417  // Get session ID
2418  ((ni_logan_get_session_id_t *)p_buffer)->session_id = NI_LOGAN_INVALID_SESSION_ID;
2420  retval = ni_logan_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle,
2421  p_buffer, NI_LOGAN_DATA_BUFFER_LEN, ui32LBA);
2422 
2423  if (NI_LOGAN_RETCODE_SUCCESS != retval)
2424  {
2425  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme read command failed blk_io_handle "
2426  "%" PRIx64 ", hw_id, %d\n", __FUNCTION__,
2427  (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id);
2429  LRETURN;
2430  }
2431  p_ctx->session_id = ni_logan_ntohl(((ni_logan_get_session_id_t *)p_buffer)->session_id);
2432  ni_log(NI_LOG_TRACE, "%s ID:0x%x\n", __FUNCTION__, p_ctx->session_id);
2434  {
2435  ni_log(NI_LOG_ERROR, "ERROR %s(): query session ID failed, p_ctx->"
2436  "blk_io_handle=%" PRIx64 ", p_ctx->hw_id=%d, p_ctx->session_id=%d\n",
2437  __FUNCTION__, (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id,
2438  p_ctx->session_id);
2441  LRETURN;
2442  }
2443 
2444  //Send session Info
2445  memset(p_buffer, 0, NI_LOGAN_DATA_BUFFER_LEN);
2446  session_info.codec_format = ni_logan_htonl(p_ctx->codec_format);
2447  session_info.i32picWidth = ni_logan_htonl(p_param->source_width);
2448  session_info.i32picHeight = ni_logan_htonl(p_param->source_height);
2449  session_info.model_load = ni_logan_htonl(model_load);
2450 #ifdef ENCODER_SYNC_QUERY //enable with parameter "-q"
2451  if (((ni_logan_encoder_params_t *)p_ctx->p_session_config)->low_delay_mode == 1)
2452  {
2453  //In low latency mode, encoder read packet will just send query command one time. Set 1 to notify the FW.
2454  ni_log(NI_LOG_TRACE, "Low latency mode support encoder read sync query\n");
2455  session_info.EncoderReadSyncQuery = ni_logan_htonl(0x01);
2456  }
2457  else
2458  {
2459  session_info.EncoderReadSyncQuery = ni_logan_htonl(0x00);
2460  }
2461 #else
2462  session_info.EncoderReadSyncQuery = ni_logan_htonl(0x00);
2463 #endif
2464  session_info.hw_desc_mode = ni_logan_htonl(p_ctx->hw_action);
2465  session_info.set_high_priority = ni_logan_htonl(p_ctx->set_high_priority);
2466  memcpy(p_buffer, &session_info, sizeof(ni_logan_encoder_session_open_info_t));
2467 
2470  p_buffer, NI_LOGAN_DATA_BUFFER_LEN, ui32LBA);
2471  CHECK_ERR_RC(p_ctx, retval, NI_LOGAN_NO_CHECK_TS_NVME_CMD_OP,
2472  p_ctx->device_type, p_ctx->hw_id,
2473  &(p_ctx->session_id));
2474  CHECK_VPU_RECOVERY(retval);
2475 
2476  if (NI_LOGAN_RETCODE_SUCCESS != retval)
2477  {
2478  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme write command failed blk_io_handle: "
2479  "%" PRIx64 ", hw_id, %d\n", __FUNCTION__,
2480  (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id);
2482  LRETURN;
2483  }
2484  ni_log(NI_LOG_TRACE, "%s completed\n", __FUNCTION__);
2485 
2486  //Send keep alive timeout Info
2487  uint64_t keep_alive_timeout = p_ctx->keep_alive_timeout * 1000000; //send us to FW
2488  memset(p_buffer, 0, NI_LOGAN_DATA_BUFFER_LEN);
2489  memcpy(p_buffer, &keep_alive_timeout, sizeof(keep_alive_timeout));
2490  ni_log(NI_LOG_TRACE, "%s keep_alive_timeout %" PRIx64 "\n",
2491  __FUNCTION__, keep_alive_timeout);
2494  p_buffer, NI_LOGAN_DATA_BUFFER_LEN, ui32LBA);
2495  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config,
2496  p_ctx->device_type, p_ctx->hw_id,
2497  &(p_ctx->session_id));
2498  CHECK_VPU_RECOVERY(retval);
2499 
2500  if (NI_LOGAN_RETCODE_SUCCESS != retval)
2501  {
2502  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme write keep_alive_timeout command "
2503  "failed blk_io_handle: %" PRIx64 ", hw_id, %d\n", __FUNCTION__,
2504  (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id);
2506  LRETURN;
2507  }
2508  }
2509 
2511 
2513  {
2514  ni_log(NI_LOG_DEBUG, "Warning: ni_logan_config_instance_set_encoder_params() vpu recovery\n");
2515  LRETURN;
2516  }
2517  else if (NI_LOGAN_RETCODE_SUCCESS != retval)
2518  {
2519  ni_log(NI_LOG_ERROR, "ERROR: calling ni_logan_config_instance_set_encoder_params(): p_ctx->device_handle="
2520  "%" PRIx64 ", p_ctx->hw_id=%d, p_ctx->session_id=%d\n",
2521  (int64_t)p_ctx->device_handle, p_ctx->hw_id, p_ctx->session_id);
2524  LRETURN;
2525  }
2526 
2527  ni_log(NI_LOG_TRACE, "Encoder params sent\n");
2528 
2529  ni_logan_timestamp_init(p_ctx, (ni_logan_timestamp_table_t * *)& p_ctx->pts_table, "enc_pts");
2530  ni_logan_timestamp_init(p_ctx, (ni_logan_timestamp_table_t * *)& p_ctx->dts_queue, "enc_dts");
2531 
2532  // init close caption SEI header and trailer
2533  memcpy(p_ctx->itu_t_t35_cc_sei_hdr_hevc, g_itu_t_t35_cc_sei_hdr_hevc,
2535  memcpy(p_ctx->itu_t_t35_cc_sei_hdr_h264, g_itu_t_t35_cc_sei_hdr_h264,
2537  memcpy(p_ctx->sei_trailer, g_sei_trailer, NI_CC_SEI_TRAILER_LEN);
2538  // init hdr10+ SEI header
2539  memcpy(p_ctx->itu_t_t35_hdr10p_sei_hdr_hevc, g_itu_t_t35_hdr10p_sei_hdr_hevc,
2541  memcpy(p_ctx->itu_t_t35_hdr10p_sei_hdr_h264, g_itu_t_t35_hdr10p_sei_hdr_h264,
2543 
2544  // query to check the final encoder config status
2545  for (; ;)
2546  {
2547  query_retry++;
2548  retval = ni_logan_query_status_info(p_ctx, p_ctx->device_type, &inst_info, retval, nvme_admin_cmd_xcoder_query);
2549 
2550  if (inst_info.sess_err_no ||
2552  {
2553  ni_log(NI_LOG_ERROR, "ERROR: session error %u or VPU_RSRC_INSUFFICIENT\n",
2554  inst_info.sess_err_no);
2555  retval = NI_LOGAN_RETCODE_FAILURE;
2556  LRETURN;
2557  }
2558  else if (inst_info.wr_buf_avail_size > 0)
2559  {
2560  ni_log(NI_LOG_TRACE, "%s(): wr_buf_avail_size %u\n", __FUNCTION__,
2561  inst_info.wr_buf_avail_size);
2562  break;
2563  }
2564  else
2565  {
2566  ni_log(NI_LOG_TRACE, "ni_logan_query_status_info ret %d, sess_err_no %u "
2567  "inst_err_no %u inst_info.wr_buf_avail_size %d retry ..\n",
2568  retval, inst_info.sess_err_no, inst_info.inst_err_no,
2569  inst_info.wr_buf_avail_size);
2570  if (query_retry > NI_LOGAN_MAX_ENC_SESSION_OPEN_QUERY_RETRIES) // 3000 retries
2571  {
2572  ni_log(NI_LOG_ERROR, "ERROR: %s timeout\n", __FUNCTION__);
2573  retval = NI_LOGAN_RETCODE_FAILURE;
2574  LRETURN;
2575  }
2577  }
2578  }
2579 
2580  ni_log(NI_LOG_TRACE, "%s(): p_ctx->device_handle=%" PRIx64 " "
2581  "p_ctx->hw_id=%d, p_ctx->session_id=%d\n", __FUNCTION__,
2582  (int64_t)p_ctx->device_handle, p_ctx->hw_id, p_ctx->session_id);
2583 
2584  END:
2585 
2586  ni_logan_aligned_free(p_signature);
2587  ni_logan_aligned_free(p_buffer);
2588 
2589  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
2590 
2591  return retval;
2592 }
2593 
2594 /*!******************************************************************************
2595  * \brief Flush encoder output
2596  *
2597  * \param
2598  *
2599  * \return
2600  *******************************************************************************/
2602 {
2603  ni_logan_retcode_t retval;
2604  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
2605 
2606  if (!p_ctx)
2607  {
2608  ni_log(NI_LOG_TRACE, "ERROR: session context is null, return\n");
2610  LRETURN;
2611  }
2612 
2614  {
2615  ni_log(NI_LOG_TRACE, "ERROR: Invalid session id, return\n");
2617  LRETURN;
2618  }
2619 
2621  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config,
2622  p_ctx->device_type, p_ctx->hw_id,
2623  &(p_ctx->session_id));
2624  CHECK_VPU_RECOVERY(retval);
2625 
2626  if (NI_LOGAN_RETCODE_SUCCESS == retval)
2627  {
2628  p_ctx->ready_to_close = 1;
2629  }
2630  else
2631  {
2632  ni_log(NI_LOG_TRACE, "ERROR: %s(), return\n", __FUNCTION__);
2633  }
2634 
2635  END:
2636 
2637  ni_log(NI_LOG_TRACE, "%s(): success exit\n", __FUNCTION__);
2638 
2639  return retval;
2640 }
2641 
2642 /*!******************************************************************************
2643  * \brief Close a xcoder encoder instance
2644  *
2645  * \param
2646  *
2647  * \return
2648  *******************************************************************************/
2650 {
2652  void* p_buffer = NULL;
2653  uint32_t ui32LBA = 0;
2654  int counter = 0;
2655  int ret = 0;
2656  int i;
2657 
2658  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
2659 
2660  if (!p_ctx)
2661  {
2662  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null! return\n");
2664  }
2665 
2667  {
2668  ni_log(NI_LOG_TRACE, "ERROR: Invalid session ID, return\n");
2669  retval = NI_LOGAN_RETCODE_SUCCESS;
2670  LRETURN;
2671  }
2672 
2673  ni_log(NI_LOG_ERROR, "Encoder_complete_info: session_id 0x%x, total frames input: %u "
2674  "buffered: %u completed: %u output: %u dropped: %u , "
2675  "inst_errors: %u\n", p_ctx->session_id, p_ctx->session_stats.frames_input,
2678  p_ctx->session_stats.inst_errors);
2679 
2680  //malloc data buffer
2681  if(ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), NI_LOGAN_DATA_BUFFER_LEN))
2682  {
2683  ni_log(NI_LOG_ERROR, "ERROR %d: %s() alloc data buffer failed\n",
2684  NI_ERRNO, __FUNCTION__);
2686  LRETURN;
2687  }
2688  memset(p_buffer, 0, NI_LOGAN_DATA_BUFFER_LEN);
2689 
2691 
2692  int retry = 0;
2693  while (retry < NI_LOGAN_MAX_SESSION_CLOSE_RETRIES) // 10 retries
2694  {
2695  ni_log(NI_LOG_TRACE, "%s(): p_ctx->blk_io_handle=%" PRIx64 " p_ctx->hw_id=%d "
2696  "p_ctx->session_id=%d, close_mode=1\n", __FUNCTION__,
2697  (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id, p_ctx->session_id);
2698 
2700  p_buffer, NI_LOGAN_DATA_BUFFER_LEN, ui32LBA) < 0)
2701  {
2702  ni_log(NI_LOG_ERROR, "ERROR %s(): command failed\n", __FUNCTION__);
2704  break;
2705  }
2706  else if(((ni_logan_session_closed_status_t *)p_buffer)->session_closed)
2707  {
2708  retval = NI_LOGAN_RETCODE_SUCCESS;
2710  break;
2711  }
2712  else
2713  {
2714  ni_log(NI_LOG_TRACE, "%s(): wait for close\n", __FUNCTION__);
2717  }
2718 
2719  retry++;
2720  }
2721 
2722  END:
2723 
2724  ni_logan_aligned_free(p_buffer);
2726 
2727  //Sequence change related stuff cleanup here
2728  p_ctx->active_video_width = 0;
2729  p_ctx->active_video_height = 0;
2730  p_ctx->active_bit_depth = 0;
2731  //End of sequence change related stuff cleanup
2732 
2734  {
2735  if (p_ctx->pts_table)
2736  {
2737  ni_logan_timestamp_table_t* p_pts_table = p_ctx->pts_table;
2738  ni_logan_queue_free(&p_pts_table->list, p_ctx->buffer_pool);
2739  free(p_ctx->pts_table);
2740  p_ctx->pts_table = NULL;
2741  ni_log(NI_LOG_TRACE, "ni_logan_timestamp_done: success\n");
2742  }
2743 
2744  if (p_ctx->dts_queue)
2745  {
2746  ni_logan_timestamp_table_t* p_dts_queue = p_ctx->dts_queue;
2747  ni_logan_queue_free(&p_dts_queue->list, p_ctx->buffer_pool);
2748  free(p_ctx->dts_queue);
2749  p_ctx->dts_queue = NULL;
2750  ni_log(NI_LOG_TRACE, "ni_logan_timestamp_done: success\n");
2751  }
2752  }
2753 
2755  p_ctx->buffer_pool = NULL;
2756 
2757  for (i = 0; i < NI_LOGAN_FIFO_SZ; i++)
2758  {
2759  free(p_ctx->pkt_custom_sei[i]);
2760  p_ctx->pkt_custom_sei[i] = NULL;
2761  }
2762 
2763  struct timeval tv;
2764  ni_logan_gettimeofday(&tv, NULL);
2765  uint64_t codec_end_time = tv.tv_sec*1000000ULL + tv.tv_usec;
2766 
2767  //if close immediately after opened, end time may equals to start time
2768  if (p_ctx->codec_total_ticks && codec_end_time - p_ctx->codec_start_time)
2769  {
2770  uint32_t ni_logan_usage = (uint32_t)((p_ctx->codec_total_ticks / NI_LOGAN_VPU_FREQ) * 100 /
2771  (codec_end_time - p_ctx->codec_start_time));
2772  ni_log(NI_LOG_INFO, "Encoder HW[%d] INST[%d]-average usage:%d%%\n",
2773  p_ctx->hw_id, (p_ctx->session_id&0x7F), ni_logan_usage);
2774  }
2775  else
2776  {
2777  ni_log(NI_LOG_INFO, "Warning Encoder HW[%d] INST[%d]-average usage equals to 0\n",
2778  p_ctx->hw_id, (p_ctx->session_id&0x7F));
2779  }
2780 
2781  ni_log(NI_LOG_TRACE, "encoder total_pkt:%" PRIu64 " total_ticks:%" PRIu64 " "
2782  "total_time:%" PRIu64 " us\n", p_ctx->pkt_num, p_ctx->codec_total_ticks,
2783  codec_end_time - p_ctx->codec_start_time);
2784 
2785  ni_log(NI_LOG_TRACE, "%s(): CTX[Card:%" PRIx64 " / HW:%d / INST:%d]\n",
2786  __FUNCTION__, (int64_t)p_ctx->device_handle, p_ctx->hw_id, p_ctx->session_id);
2787 
2788  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
2789 
2790  return retval;
2791 }
2792 
2793 /*!******************************************************************************
2794  * \brief Send a YUV p_frame to encoder
2795  *
2796  * \param
2797  *
2798  * \return
2799  *******************************************************************************/
2801 {
2802  bool ishwframe = p_ctx->hw_action & NI_LOGAN_CODEC_HW_ENABLE;
2803  bool isseparate_metadata = p_frame->separate_metadata;
2804  uint32_t size = 0;
2805  uint32_t metadata_size = NI_LOGAN_APP_ENC_FRAME_META_DATA_SIZE;
2806  uint32_t send_count = 0;
2807  uint32_t i = 0;
2808  uint32_t tx_size = 0, aligned_tx_size = 0;
2809  uint32_t sent_size = 0;
2810  uint32_t frame_size_bytes = 0;
2811  int retval = 0;
2812  ni_logan_instance_status_info_t inst_info = { 0 };
2813  ni_logan_encoder_params_t *p_param;
2814 
2815 #ifdef MEASURE_LATENCY
2816  struct timespec logtv;
2817  uint64_t abs_time_ns;
2818 #endif
2819 
2820  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
2821 
2822  if (!p_ctx || !p_frame)
2823  {
2824  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
2826  LRETURN;
2827  }
2828 
2829  p_param = p_ctx->p_session_config;
2830 
2832  {
2833  ni_log(NI_LOG_TRACE, "ERROR: Invlid session ID, return\n");
2835  LRETURN;
2836  }
2837 
2838 #ifdef MEASURE_LATENCY
2839  if ((p_frame->dts != NI_LOGAN_NOPTS_VALUE) && (p_ctx->frame_time_q != NULL)) {
2840 #ifdef _WIN32
2841  abs_time_ns = ni_logan_gettime_ns();
2842 #else
2843  clock_gettime(CLOCK_REALTIME, &logtv);
2844  abs_time_ns = (logtv.tv_sec*1000000000LL+logtv.tv_nsec);
2845 #endif
2846  ni_logan_lat_meas_q_add_entry(p_ctx->frame_time_q, abs_time_ns, p_frame->dts);
2847  }
2848 #endif
2849 
2850  /*!********************************************************************/
2851  /*!************ Sequence Change related stuff *************************/
2852  //First check squence changed related stuff.
2853  //We need to record the current hight/width params if we didn't do it before:
2854 
2855  if ( p_frame->video_height)
2856  {
2857  p_ctx->active_video_width = p_frame->data_len[0] / p_frame->video_height;
2858  p_ctx->active_video_height = p_frame->video_height;
2859  p_ctx->active_bit_depth = p_frame->bit_depth;
2860  }
2861  else if (p_frame->video_width)
2862  {
2863  ni_log(NI_LOG_TRACE, "WARNING: passed video_height is not valid! return\n");
2864  p_ctx->active_video_height = p_frame->data_len[0] / p_frame->video_width;
2865  p_ctx->active_video_width = p_frame->video_width;
2866  p_ctx->active_bit_depth = p_frame->bit_depth;
2867  }
2868  else
2869  {
2870  ni_log(NI_LOG_TRACE, "ERROR: passed video_height and video_width are not valid! return\n");
2872  LRETURN;
2873  }
2874 
2875  /*!************ Sequence Change related stuff end*************************/
2876  /*!********************************************************************/
2877 
2878  frame_size_bytes = p_frame->data_len[0] + p_frame->data_len[1] + p_frame->data_len[2] + (isseparate_metadata ? 0 : p_frame->data_len[3]) + p_frame->extra_data_len;
2879 
2880  // this is a temporary fix to avoid hw frame buffer pool full when enable yuvbypass
2881  if (ishwframe && (p_ctx->frame_num >= (p_ctx->pkt_num + 8)) &&
2883  {
2885  ni_log(NI_LOG_TRACE, "Set Enc buffer full\n");
2886  }
2887 
2888  // skip query write buffer because we just send EOS
2889  if (!p_frame->end_of_stream)
2890  {
2891  for (; ;)
2892  {
2893  retval = ni_logan_query_status_info(p_ctx, p_ctx->device_type, &inst_info, retval, nvme_admin_cmd_xcoder_query);
2894  CHECK_ERR_RC2(p_ctx, retval, inst_info, nvme_admin_cmd_xcoder_query,
2895  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
2896  CHECK_VPU_RECOVERY(retval);
2897 
2898  if (NI_LOGAN_RETCODE_SUCCESS != retval ||
2899  inst_info.wr_buf_avail_size < frame_size_bytes)
2900  {
2901  ni_log(NI_LOG_TRACE, "Warning enc write query try %u fail rc %d or "
2902  "available buf size %u < frame size %u !\n", send_count, retval,
2903  inst_info.wr_buf_avail_size, frame_size_bytes);
2904  if (send_count >= NI_LOGAN_MAX_ENC_SESSION_WRITE_QUERY_RETRIES) // 2000 retries
2905  {
2906  ni_log(NI_LOG_TRACE, "ERROR enc query buf info exceeding max retries:%d",
2908  p_ctx->required_buf_size = frame_size_bytes;
2910  retval = NI_LOGAN_RETCODE_SUCCESS;
2911  LRETURN;
2912  }
2913  send_count++;
2914  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
2916  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
2917  }
2918  else
2919  {
2920  ni_log(NI_LOG_TRACE, "Info enc write query success, available buf "
2921  "size %u >= frame size %u !\n", inst_info.wr_buf_avail_size,
2922  frame_size_bytes);
2923  break;
2924  }
2925  }
2926  }
2927 
2928  // fill in metadata such as timestamp
2929  ni_logan_metadata_enc_frame_t *p_meta = isseparate_metadata ? (ni_logan_metadata_enc_frame_t *)((uint8_t *)p_frame->p_data[3]):
2930  (ni_logan_metadata_enc_frame_t *)((uint8_t *)p_frame->p_data[2 + ishwframe] +
2931  p_frame->data_len[2 + ishwframe]);
2932 
2933  if (p_meta) //When hwframe xcoding reaches eos, frame looks like swframe but no allocation for p_meta
2934  {
2935  p_meta->metadata_common.ui64_data.frame_tstamp = (uint64_t)p_frame->pts;
2936 
2937  p_meta->force_headers = 0; // p_frame->force_headers not implemented/used
2939  p_meta->use_long_term_ref = p_frame->use_long_term_ref;
2940 
2941  p_meta->frame_force_type_enable = 0;
2942  p_meta->frame_force_type = 0;
2943  p_meta->reset_intra_refresh = 0;
2944  // frame type to be forced to is supposed to be set correctly
2945  // in p_frame->ni_logan_pict_type
2946  if (1 == p_ctx->force_frame_type || p_frame->force_key_frame)
2947  {
2948  if (p_frame->ni_logan_pict_type)
2949  {
2950  if (p_param->intra_refresh_reset && p_frame->ni_logan_pict_type == 3)
2951  {
2952  p_meta->reset_intra_refresh = 1;
2953  p_ctx->force_frame_pts_table[p_ctx->force_frame_pts_size] = p_frame->pts;
2955  }
2956  else
2957  {
2958  p_meta->frame_force_type_enable = 1;
2959  p_meta->frame_force_type = p_frame->ni_logan_pict_type;
2960  }
2961  }
2962  }
2963  ni_log(NI_LOG_TRACE, "%s(): ctx->force_frame_type %d "
2964  "frame->force_key_frame %d force frame_num %" PRIu64 " type to %d"
2965  "p_param->intra_refresh_reset %d\n", __FUNCTION__,
2966  p_ctx->force_frame_type, p_frame->force_key_frame,
2967  p_ctx->frame_num, p_frame->ni_logan_pict_type,
2968  p_param->intra_refresh_reset);
2969  }
2970 
2971  // force pic qp if specified
2972  p_meta->force_pic_qp_enable = p_meta->force_pic_qp_i =
2973  p_meta->force_pic_qp_p = p_meta->force_pic_qp_b = 0;
2974  if (p_frame->force_pic_qp)
2975  {
2976  p_meta->force_pic_qp_enable = 1;
2977  p_meta->force_pic_qp_i = p_meta->force_pic_qp_p =
2978  p_meta->force_pic_qp_b = p_frame->force_pic_qp;
2979  }
2980  p_meta->frame_sei_data_size = p_frame->sei_total_len;
2981  p_meta->frame_roi_map_size = p_frame->roi_len;
2982  p_meta->frame_roi_avg_qp = p_ctx->roi_avg_qp;
2983  p_meta->enc_reconfig_data_size = p_frame->reconf_len;
2984 
2985  ni_log(NI_LOG_TRACE, "%s(): %d.%d p_ctx->frame_num=%" PRIu64 ", p_frame->start_of_stream=%u, end_of_stream=%u, "
2986  "video_width=%u, video_height=%u, pts=0x%08x 0x%08x, dts=0x%08x 0x%08x, sei_len=%u, roi size=%u "
2987  "avg_qp=%u reconf_len=%u force_pic_qp=%u force_headers=%u frame_force_type_enable=%u frame_force_type=%u "
2988  "force_pic_qp_enable=%u force_pic_qp_i/p/b=%u use_cur_src_as_long_term_pic %u use_long_term_ref %u\n",
2989  __FUNCTION__, p_ctx->hw_id, p_ctx->session_id, p_ctx->frame_num,
2990  p_frame->start_of_stream, p_frame->end_of_stream,
2991  p_frame->video_width, p_frame->video_height,
2992  (uint32_t)((p_frame->pts >> 32) & 0xFFFFFFFF),
2993  (uint32_t)(p_frame->pts & 0xFFFFFFFF),
2994  (uint32_t)((p_frame->dts >> 32) & 0xFFFFFFFF),
2995  (uint32_t)(p_frame->dts & 0xFFFFFFFF),
2996  p_meta->frame_sei_data_size, p_meta->frame_roi_map_size,
2997  p_meta->frame_roi_avg_qp, p_meta->enc_reconfig_data_size,
2998  p_meta->force_pic_qp_i, p_meta->force_headers,
2999  p_meta->frame_force_type_enable, p_meta->frame_force_type,
3000  p_meta->force_pic_qp_enable, p_meta->force_pic_qp_i,
3002 
3003  if (p_frame->start_of_stream)
3004  {
3005  //Send Start of stream p_config command here
3007  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config,
3008  p_ctx->device_type, p_ctx->hw_id,
3009  &(p_ctx->session_id));
3010  CHECK_VPU_RECOVERY(retval);
3011  if (NI_LOGAN_RETCODE_SUCCESS != retval)
3012  {
3013  LRETURN;
3014  }
3015 
3016  p_frame->start_of_stream = 0;
3017  }
3018 
3019  // skip direct to send eos without sending the passed in p_frame as it's been sent already
3020  if (p_frame->end_of_stream)
3021  {
3023  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config,
3024  p_ctx->device_type, p_ctx->hw_id,
3025  &(p_ctx->session_id));
3026  CHECK_VPU_RECOVERY(retval);
3027  if (NI_LOGAN_RETCODE_SUCCESS != retval)
3028  {
3029  LRETURN;
3030  }
3031 
3032  p_frame->end_of_stream = 0;
3033  p_ctx->ready_to_close = 1;
3034  }
3035  else //handle regular frame sending
3036  {
3037  if (p_frame->p_data)
3038  {
3039  retval = ni_logan_timestamp_register(p_ctx->buffer_pool, p_ctx->dts_queue, p_frame->dts, 0);
3040  if (NI_LOGAN_RETCODE_SUCCESS != retval)
3041  {
3042  ni_log(NI_LOG_ERROR, "ERROR %s(): ni_logan_timestamp_register() for dts returned: %d\n", __FUNCTION__, retval);
3043  }
3044 
3045  if (isseparate_metadata)
3046  {
3047  uint32_t ui32LBA =
3049  uint32_t ui32LBA_MetaData =
3052  "%s: separate_metadata case: "
3053  "p_data = %p, p_buffer = %p, "
3054  "p_data_len[3] = %u, extra_data_len = %u, "
3055  "p_ctx->frame_num = %" PRIu64 ", ui32LBA_MetaData = 0x%x, ui32LBA = 0x%x\n",
3056  __func__, p_frame->p_data[3],p_frame->p_buffer,
3057  p_frame->data_len[3],
3058  p_frame->extra_data_len,
3059  p_ctx->frame_num,
3060  ui32LBA_MetaData,
3061  ui32LBA);
3062  sent_size = p_frame->extra_data_len;
3063  if (sent_size % NI_LOGAN_MEM_PAGE_ALIGNMENT)
3064  {
3066  }
3068  p_ctx->blk_io_handle, p_ctx->event_handle,
3069  p_frame->p_data[3], sent_size,
3070  ui32LBA_MetaData);
3071  CHECK_ERR_RC(p_ctx, retval, nvme_cmd_xcoder_write, p_ctx->device_type,
3072  p_ctx->hw_id, &(p_ctx->session_id));
3073  CHECK_VPU_RECOVERY(retval);
3074  if (retval < 0)
3075  {
3076  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme command failed\n",
3077  __func__);
3079  LRETURN;
3080  }
3081 
3083  "%s: separate_metadata case: "
3084  "p_data[0] = %p, data_len[0] = %x, "
3085  "p_data[1] = %p, data_len[1] = %x, "
3086  "p_data[2] = %p, data_len[2] = %x, "
3087  "p_ctx->frame_num = %" PRIu64 ", LBA = 0x%x\n",
3088  __func__, p_frame->p_data[0], p_frame->data_len[0],
3089  p_frame->p_data[1], p_frame->data_len[1],
3090  p_frame->p_data[2], p_frame->data_len[2],
3091  p_ctx->frame_num,
3092  ui32LBA);
3093  sent_size = p_frame->data_len[0] + p_frame->data_len[1] + p_frame->data_len[2];
3094  if (sent_size % NI_LOGAN_MEM_PAGE_ALIGNMENT)
3095  {
3097  }
3099  p_ctx->blk_io_handle, p_ctx->event_handle,
3100  p_frame->p_data[0], sent_size,
3101  ui32LBA);
3102  CHECK_ERR_RC(p_ctx, retval, nvme_cmd_xcoder_write, p_ctx->device_type,
3103  p_ctx->hw_id, &(p_ctx->session_id));
3104  CHECK_VPU_RECOVERY(retval);
3105  if (retval < 0)
3106  {
3107  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme command failed\n",
3108  __func__);
3110  LRETURN;
3111  }
3112  }
3113  else
3114  {
3115  uint32_t ui32LBA = WRITE_INSTANCE_W(ishwframe, p_ctx->session_id, NI_LOGAN_DEVICE_TYPE_ENCODER);
3116  ni_log(NI_LOG_TRACE, "%s: p_data = %p, p_frame->buffer_size = %u, "
3117  "p_ctx->frame_num = %"PRIu64", LBA = 0x%x\n", __FUNCTION__,
3118  p_frame->p_data, p_frame->buffer_size, p_ctx->frame_num, ui32LBA);
3119  sent_size = frame_size_bytes;
3120  if (sent_size % NI_LOGAN_MEM_PAGE_ALIGNMENT)
3121  {
3123  }
3124 
3126  p_frame->p_buffer, sent_size, ui32LBA);
3127  CHECK_ERR_RC(p_ctx, retval, nvme_cmd_xcoder_write,
3128  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
3129  CHECK_VPU_RECOVERY(retval);
3130  if (retval < 0)
3131  {
3132  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme command failed\n", __FUNCTION__);
3134  LRETURN;
3135  }
3136  }
3137 
3138  size = frame_size_bytes;
3139  p_ctx->frame_num++;
3140  }
3141  }
3142 
3143  retval = size;
3144 
3145  END:
3146 
3147  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
3148 
3149  return retval;
3150 }
3151 
3153 {
3155  bool ishwframe = p_ctx->hw_action & NI_LOGAN_CODEC_HW_ENABLE;
3156  uint32_t chunk_max_size = p_ctx->max_nvme_io_size;
3157  uint32_t actual_read_size = 0, chunk_size, end_of_pkt;
3158  uint32_t actual_read_size_aligned = 0;
3159  int reading_partial_pkt = 0;
3160  uint32_t to_read_size = 0;
3161  int size = 0;
3162  uint32_t query_return_size = 0;
3163  uint8_t* p_data = NULL;
3164  int retval = NI_LOGAN_RETCODE_SUCCESS;
3165  uint32_t ui32LBA = 0;
3166  uint32_t query_retry = 0;
3167  ni_logan_metadata_enc_bstream_t *p_meta = NULL;
3168  ni_logan_instance_status_info_t inst_info = { 0 };
3169  ni_logan_encoder_params_t *p_param;
3170 
3171 #ifdef MEASURE_LATENCY
3172  struct timespec logtv;
3173  uint64_t abs_time_ns;
3174 #endif
3175 
3176  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
3177 
3178  if (!p_ctx || !p_packet || !p_packet->p_data)
3179  {
3180  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
3182  LRETURN;
3183  }
3184 
3185  p_param = p_ctx->p_session_config;
3186 
3188  {
3189  ni_log(NI_LOG_ERROR, "xcoder instance id == 0, return\n");
3191  LRETURN;
3192  }
3193 
3194  p_packet->data_len = 0;
3195  p_packet->pts = NI_LOGAN_NOPTS_VALUE;
3196  p_packet->dts = 0;
3197 
3198 enc_read_query:
3199  query_retry = 0;
3200 
3201  while (1)
3202  {
3203  query_retry++;
3204  retval = ni_logan_query_status_info(p_ctx, p_ctx->device_type, &inst_info,retval, nvme_admin_cmd_xcoder_query);
3205  CHECK_ERR_RC2(p_ctx, retval, inst_info, nvme_admin_cmd_xcoder_query,
3206  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
3207  CHECK_VPU_RECOVERY(retval);
3208 
3209  ni_log(NI_LOG_TRACE, "Info enc read query try %u rc %d, available buf size %u, "
3210  "frame_num=%"PRIu64", pkt_num=%"PRIu64" reading_partial_pkt %d\n",
3211  query_retry, retval, inst_info.rd_buf_avail_size, p_ctx->frame_num,
3212  p_ctx->pkt_num, reading_partial_pkt);
3213 
3214  if (NI_LOGAN_RETCODE_SUCCESS != retval)
3215  {
3216  ni_log(NI_LOG_ERROR, "Buffer info query failed in encoder read!!!!\n");
3217  LRETURN;
3218  }
3219  else if (0 == inst_info.rd_buf_avail_size)
3220  {
3221  // query to see if it is eos now, if we have sent it
3222  if (! reading_partial_pkt && p_ctx->ready_to_close)
3223  {
3224  retval = ni_logan_query_stream_info(p_ctx, NI_LOGAN_DEVICE_TYPE_ENCODER, &data, ishwframe);
3225  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_query,
3226  p_ctx->device_type, p_ctx->hw_id,
3227  &(p_ctx->session_id));
3228  CHECK_VPU_RECOVERY(retval);
3229 
3230  if (NI_LOGAN_RETCODE_SUCCESS != retval)
3231  {
3232  ni_log(NI_LOG_ERROR, "Stream info query failed in encoder read !!\n");
3233  LRETURN;
3234  }
3235 
3236  if (data.is_flushed)
3237  {
3238  p_packet->end_of_stream = 1;
3239  }
3240  }
3241  ni_log(NI_LOG_TRACE, "Info enc read available buf size %u, eos %u !\n",
3242  inst_info.rd_buf_avail_size, p_packet->end_of_stream);
3243 
3244  if (p_param->strict_timeout_mode
3245  && (query_retry > NI_LOGAN_MAX_ENC_SESSION_READ_QUERY_RETRIES)) // 3000 retries
3246  {
3247  ni_log(NI_LOG_ERROR, "ERROR Receive Packet Strict Timeout, Encoder low "
3248  "latency mode %d, buf_full %d eos sent %d, frame_num %"PRIu64" "
3249  ">= %"PRIu64" pkt_num, retry limit exceeded and exit encoder "
3250  "pkt reading.\n",
3251  p_param->low_delay_mode,
3253  p_ctx->ready_to_close, p_ctx->frame_num, p_ctx->pkt_num);
3255  LRETURN;
3256  }
3257 
3258  if ((p_param->low_delay_mode == 1 ||
3260  p_ctx->ready_to_close || reading_partial_pkt) &&
3261  ! p_packet->end_of_stream && p_ctx->frame_num >= p_ctx->pkt_num)
3262  {
3263  ni_log(NI_LOG_TRACE, "Encoder low latency mode %d, buf_full %d eos sent"
3264  " %d, reading_partial_pkt %d, frame_num %"PRIu64" >= %"PRIu64" "
3265  "pkt_num, keep querying.\n",
3266  p_param->low_delay_mode,
3268  p_ctx->ready_to_close, reading_partial_pkt,
3269  p_ctx->frame_num, p_ctx->pkt_num);
3270  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
3272  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
3273  continue;
3274  }
3275  retval = NI_LOGAN_RETCODE_SUCCESS;
3276  LRETURN;
3277  }
3278  else
3279  {
3281  (inst_info.wr_buf_avail_size > p_ctx->required_buf_size))
3282  {
3283  p_ctx->status = 0;
3284  }
3285  break;
3286  }
3287  }
3288  ni_log(NI_LOG_TRACE, "Encoder read buf_avail_size %u\n",
3289  inst_info.rd_buf_avail_size);
3290 
3291  to_read_size = inst_info.rd_buf_avail_size;
3292 
3293  ui32LBA = READ_INSTANCE_R(ishwframe, p_ctx->session_id, NI_LOGAN_DEVICE_TYPE_ENCODER);
3294 
3295  if (to_read_size % NI_LOGAN_MEM_PAGE_ALIGNMENT)
3296  {
3297  to_read_size = ((to_read_size / NI_LOGAN_MEM_PAGE_ALIGNMENT) *
3299  }
3300 
3301  if ((to_read_size + actual_read_size_aligned) > p_packet->buffer_size)
3302  {
3303  ni_log(NI_LOG_ERROR, "ERROR %s() avaliable size(%u) aligned(%u) is more than"
3304  " buffer allocated(%u)\n", __FUNCTION__, inst_info.rd_buf_avail_size,
3305  to_read_size + actual_read_size_aligned, p_packet->buffer_size);
3306  retval = NI_LOGAN_RETCODE_FAILURE;
3307  LRETURN;
3308  }
3309 
3310  retval = ni_logan_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle,
3311  (uint8_t *)p_packet->p_data + actual_read_size_aligned,
3312  to_read_size, ui32LBA);
3313  CHECK_ERR_RC(p_ctx, retval, nvme_cmd_xcoder_read,
3314  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
3315  CHECK_VPU_RECOVERY(retval);
3316  if (retval < 0)
3317  {
3318  ni_log(NI_LOG_ERROR, "ERROR %s(): read command failed\n", __FUNCTION__);
3320  LRETURN;
3321  }
3322 
3323  // retrieve metadata pkt related info only once, when eop = 1
3324  p_meta = (ni_logan_metadata_enc_bstream_t *)((uint8_t *)p_packet->p_data +
3325  actual_read_size_aligned);
3326  chunk_size = p_meta->bs_frame_size;
3327  end_of_pkt = p_meta->end_of_packet;
3328  if (end_of_pkt)
3329  {
3330  p_packet->frame_type = p_meta->frame_type;
3331  p_packet->pts = (int64_t)(p_meta->frame_tstamp);
3332  p_ctx->codec_total_ticks += p_meta->frame_cycle;
3333  p_packet->avg_frame_qp = p_meta->avg_frame_qp;
3334  p_packet->recycle_index = p_meta->recycle_index;
3335  ni_log(NI_LOG_TRACE, "RECYCLE INDEX = %d!!! \n", p_meta->recycle_index);
3336  }
3337 
3338  if (0 == actual_read_size)
3339  {
3340  actual_read_size = sizeof(ni_logan_metadata_enc_bstream_t) + chunk_size;
3341  }
3342  else
3343  {
3344  memmove((uint8_t *)p_packet->p_data + actual_read_size,
3345  (uint8_t*)p_packet->p_data + actual_read_size_aligned +
3346  sizeof(ni_logan_metadata_enc_bstream_t), chunk_size);
3347  actual_read_size += chunk_size;
3348  }
3349 
3350  actual_read_size_aligned = actual_read_size;
3351  if (actual_read_size_aligned % NI_LOGAN_MEM_PAGE_ALIGNMENT)
3352  {
3353  actual_read_size_aligned = ((actual_read_size / NI_LOGAN_MEM_PAGE_ALIGNMENT)
3355  }
3356 
3357  ni_log(NI_LOG_TRACE, "%s(): read %u so far %u (%u) bytes, end_of_pkt: %u\n",
3358  __FUNCTION__, chunk_size, actual_read_size, actual_read_size_aligned,
3359  end_of_pkt);
3360 
3361  if (! end_of_pkt)
3362  {
3363  reading_partial_pkt = 1;
3364  goto enc_read_query;
3365  }
3366 
3367  p_packet->data_len = actual_read_size;
3368 
3369  if (p_packet->data_len > p_packet->buffer_size)
3370  {
3371  ni_log(NI_LOG_ERROR, "ERROR %s(): packet data_len %d is more than buffer_size %d\n",
3372  __FUNCTION__, p_packet->data_len, p_packet->buffer_size);
3373  retval = NI_LOGAN_RETCODE_FAILURE;
3374  LRETURN;
3375  }
3376 
3377  size = p_packet->data_len;
3378 
3379  if (size > 0)
3380  {
3381  if (p_ctx->pkt_num >= 1)
3382  {
3383  if (ni_logan_timestamp_get_with_threshold(p_ctx->dts_queue, 0, (int64_t*)& p_packet->dts, 0,
3384  p_ctx->pkt_num % 500 == 0, p_ctx->buffer_pool) != NI_LOGAN_RETCODE_SUCCESS)
3385  {
3386  p_packet->dts = NI_LOGAN_NOPTS_VALUE;
3387  }
3388  p_ctx->pkt_num++;
3389  }
3390 
3391  }
3392 
3393  ni_log(NI_LOG_TRACE, "%s(): %d.%d p_packet->start_of_stream=%d end_of_stream=%d "
3394  "video_width=%d, video_height=%d, dts=0x%08x 0x%08x, pts=0x%08x 0x%08x, "
3395  "type=%u, avg_frame_qp=%u\n", __FUNCTION__, p_ctx->hw_id,
3396  p_ctx->session_id, p_packet->start_of_stream, p_packet->end_of_stream,
3397  p_packet->video_width, p_packet->video_height,
3398  (uint32_t)((p_packet->dts >> 32) & 0xFFFFFFFF),
3399  (uint32_t)(p_packet->dts & 0xFFFFFFFF),
3400  (uint32_t)((p_packet->pts >> 32) & 0xFFFFFFFF),
3401  (uint32_t)(p_packet->pts & 0xFFFFFFFF), p_packet->frame_type,
3402  p_packet->avg_frame_qp);
3403 
3404  ni_log(NI_LOG_TRACE, "%s(): p_packet->data_len=%u, size=%u\n",
3405  __FUNCTION__, p_packet->data_len, size);
3406 
3407  if (p_ctx->pkt_num % 500 == 0)
3408  {
3409  ni_log(NI_LOG_TRACE, "Encoder pts queue size = %d dts queue size = %d\n\n",
3410  ((ni_logan_timestamp_table_t*)p_ctx->pts_table)->list.count,
3411  ((ni_logan_timestamp_table_t*)p_ctx->dts_queue)->list.count);
3412  }
3413 
3414  retval = size;
3415 
3416 #ifdef MEASURE_LATENCY
3417  if (p_packet->dts != NI_LOGAN_NOPTS_VALUE && p_ctx->frame_time_q != NULL)
3418  {
3419 #ifdef _WIN32
3420  abs_time_ns = ni_logan_gettime_ns();
3421 #else
3422  clock_gettime(CLOCK_REALTIME, &logtv);
3423  abs_time_ns = (logtv.tv_sec*1000000000LL+logtv.tv_nsec);
3424 #endif
3425  ni_log(NI_LOG_INFO, "DTS:%lld,DELTA:%lu,eLAT:%lu,fLAT:%lu;\n",
3426  p_packet->dts,
3427  abs_time_ns - p_ctx->prev_read_frame_time,
3428  ni_logan_lat_meas_q_check_latency(p_ctx->frame_time_q, abs_time_ns, p_packet->dts),
3429  p_ctx->frame_num - p_ctx->pkt_num);
3430  p_ctx->prev_read_frame_time = abs_time_ns;
3431  }
3432 #endif
3433 
3434  END:
3435 
3436  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
3437 
3438  return retval;
3439 }
3440 
3441 /*!******************************************************************************
3442  * \brief Query current encoder status
3443  *
3444  * \param
3445  *
3446  * \return
3447  *******************************************************************************/
3449 {
3451  int retval = NI_LOGAN_RETCODE_SUCCESS;
3452 
3453  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
3454 
3455  if (!p_ctx)
3456  {
3457  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null! return\n");
3459  LRETURN;
3460  }
3461 
3463 
3464  if (NI_LOGAN_RETCODE_SUCCESS == retval)
3465  {
3466  p_ctx->load_query.current_load = (uint32_t)data.process_load_percent;
3467  p_ctx->load_query.fw_model_load = (uint32_t)data.fw_model_load;
3468  p_ctx->load_query.fw_video_mem_usage = (uint32_t)data.fw_video_mem_usage;
3469  p_ctx->load_query.total_contexts =
3470  (uint32_t)data.active_sub_instances_cnt;
3472  ni_log(NI_LOG_TRACE, "%s current_load:%d fw_model_load:%d fw_video_mem_usage:%d "
3473  "active_contexts %d temperature %d\n", __FUNCTION__,
3476  p_ctx->composite_temperature);
3477  }
3478 
3479  END:
3480 
3481  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
3482 
3483  return retval;
3484 }
3485 
3486 /*!******************************************************************************
3487  * \brief Query a particular xcoder instance to get GeneralStatus data
3488  *
3489  * \param ni_logan_session_context_t p_ctx - xcoder Context
3490  * \param ni_logan_device_type_t device_type - xcoder type Encoder or Decoder
3491  * \param ni_logan_instance_mgr_general_status_t *out - Struct preallocated from the caller where the
3492  * resulting data will be placed
3493  *
3494  * \return - NI_LOGAN_RETCODE_SUCCESS on success, NI_LOGAN_RETCODE_ERROR_MEM_ALOC or NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED on failure
3495  *******************************************************************************/
3497  ni_logan_device_type_t device_type,
3499 {
3500  void* p_buffer = NULL;
3501  int retval = NI_LOGAN_RETCODE_SUCCESS;
3502  uint32_t ui32LBA = 0;
3505 
3506  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
3507 
3508  if (!p_ctx || !p_gen_status)
3509  {
3510  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
3512  LRETURN;
3513  }
3514 
3515  if (! (NI_LOGAN_DEVICE_TYPE_DECODER == device_type ||
3516  NI_LOGAN_DEVICE_TYPE_ENCODER == device_type))
3517  {
3518  ni_log(NI_LOG_TRACE, "ERROR: Unknown device type, return\n");
3520  LRETURN;
3521  }
3522 
3523  ui32LBA = QUERY_GENERAL_GET_STATUS_R(device_type);
3524 
3525  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), dataLen))
3526  {
3527  ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer.\n",
3528  NI_ERRNO, __FUNCTION__);
3530  LRETURN;
3531  }
3532 
3533  memset(p_buffer, 0, dataLen);
3534 
3535  if (ni_logan_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_buffer, dataLen, ui32LBA) < 0)
3536  {
3537  ni_log(NI_LOG_TRACE, "%s(): NVME command Failed\n", __FUNCTION__);
3539  LRETURN;
3540  }
3541 
3542  //No need to flip the bytes since the datastruct has only uint8_t datatypes
3543  memcpy((void*)p_gen_status, p_buffer, sizeof(ni_logan_instance_mgr_general_status_t));
3544 
3545  ni_log(NI_LOG_TRACE, "%s(): model_load:%d qc:%d percent:%d\n", __FUNCTION__,
3546  p_gen_status->fw_model_load, p_gen_status->cmd_queue_count,
3547  p_gen_status->process_load_percent);
3548  END:
3549 
3550  ni_logan_aligned_free(p_buffer);
3551 
3552  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
3553 
3554  return retval;
3555 }
3556 
3557 /*!******************************************************************************
3558  * \brief Query a particular xcoder instance to get Stream Info data
3559  *
3560  * \param ni_logan_session_context_t p_ctx - xcoder Context
3561  * \param ni_logan_device_type_t device_type - xcoder type Encoder or Decoder
3562  * \param ni_logan_instance_mgr_stream_info_t *out - Struct preallocated from the caller where the
3563  * resulting data will be placed
3564  *
3565  * \return - NI_LOGAN_RETCODE_SUCCESS on success, NI_LOGAN_RETCODE_ERROR_INVALID_SESSION, NI_LOGAN_RETCODE_ERROR_MEM_ALOC
3566  * or NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED on failure
3567  *******************************************************************************/
3569  ni_logan_device_type_t device_type,
3570  ni_logan_instance_mgr_stream_info_t* p_stream_info,
3571  bool is_hw)
3572 {
3573  void* p_buffer = NULL;
3575  uint32_t ui32LBA = 0;
3578 
3579  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
3580 
3581  if (!p_ctx || !p_stream_info)
3582  {
3583  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
3585  LRETURN;
3586  }
3587 
3588  if (! (NI_LOGAN_DEVICE_TYPE_DECODER == device_type ||
3589  NI_LOGAN_DEVICE_TYPE_ENCODER == device_type))
3590  {
3591  ni_log(NI_LOG_TRACE, "ERROR: Unknown device type, return\n");
3593  LRETURN;
3594  }
3595 
3597  {
3598  ni_log(NI_LOG_TRACE, "ERROR: Invalid session ID, return\n");
3600  LRETURN;
3601  }
3602 
3603  ui32LBA = QUERY_INSTANCE_STREAM_INFO_R(is_hw, p_ctx->session_id, device_type);
3604 
3605  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), dataLen))
3606  {
3607  ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer.\n",
3608  NI_ERRNO, __FUNCTION__);
3610  LRETURN;
3611  }
3612  memset(p_buffer, 0, dataLen);
3613 
3614  if (ni_logan_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_buffer, dataLen, ui32LBA) < 0)
3615  {
3616  ni_log(NI_LOG_TRACE, "%s(): NVME command Failed\n", __FUNCTION__);
3618  LRETURN;
3619  }
3620 
3621  memcpy((void*)p_stream_info, p_buffer, sizeof(ni_logan_instance_mgr_stream_info_t));
3622 
3623  //flip the bytes to host order
3624  p_stream_info->picture_width = ni_logan_htons(p_stream_info->picture_width);
3625  p_stream_info->picture_height = ni_logan_htons(p_stream_info->picture_height);
3626  p_stream_info->frame_rate = ni_logan_htons(p_stream_info->frame_rate);
3627  p_stream_info->is_flushed = ni_logan_htons(p_stream_info->is_flushed);
3628  p_stream_info->reorder_delay = ni_logan_htons(p_stream_info->reorder_delay);
3629 
3630  END:
3631 
3632  ni_logan_aligned_free(p_buffer);
3633 
3634  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
3635 
3636  return retval;
3637 }
3638 
3639 /*!*****************************************************************************
3640  * \brief Query a particular xcoder instance to get status Info data
3641  *
3642  * \param ni_logan_session_context_t p_ctx - xcoder Context
3643  * \param ni_logan_device_type_t device_type - xcoder type Encoder or Decoder
3644  * \param ni_logan_instance_status_info_t *out - Struct preallocated from the
3645  * caller where the resulting data will be placed
3646  *
3647  * \return - NI_LOGAN_RETCODE_SUCCESS on success, NI_LOGAN_RETCODE_ERROR_INVALID_SESSION,
3648  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC or NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED
3649  * on failure
3650  ******************************************************************************/
3652  ni_logan_device_type_t device_type,
3653  ni_logan_instance_status_info_t* p_status_info,
3654  int rc,
3655  int opcode)
3656 {
3658 
3659  void* p_buffer = NULL;
3660  uint32_t ui32LBA = 0;
3663 
3664  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
3665 
3666  if (!p_ctx || !p_status_info)
3667  {
3668  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
3670  LRETURN;
3671  }
3672 
3673  if (! (NI_LOGAN_DEVICE_TYPE_DECODER == device_type ||
3674  NI_LOGAN_DEVICE_TYPE_ENCODER == device_type))
3675  {
3676  ni_log(NI_LOG_TRACE, "ERROR: Unknown device type, return\n");
3678  LRETURN;
3679  }
3680 
3682  {
3683  ni_log(NI_LOG_TRACE, "ERROR: Invalid session ID, return\n");
3685  LRETURN;
3686  }
3687 
3688  ui32LBA = QUERY_INSTANCE_CUR_STATUS_INFO_R(p_ctx->session_id, device_type);
3689 
3690  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), dataLen))
3691  {
3692  ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer.\n",
3693  NI_ERRNO, __FUNCTION__);
3695  LRETURN;
3696  }
3697  memset(p_buffer, 0, dataLen);
3698 
3699  // There are some cases that FW will not dma the data but just return error status, so add a default error number.
3700  // for example open more than 32 encoder sessions at the same time
3702  if (ni_logan_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_buffer, dataLen, ui32LBA)
3703  < 0)
3704  {
3705  ni_log(NI_LOG_ERROR, "%s(): read command Failed\n", __FUNCTION__);
3708  LRETURN;
3709  }
3710 
3711  memcpy((void*)p_status_info, p_buffer, sizeof(ni_logan_instance_status_info_t));
3712 
3713  // flip the bytes to host order
3714  p_status_info->sess_err_no = ni_logan_htons(p_status_info->sess_err_no);
3715  p_status_info->sess_rsvd = ni_logan_htons(p_status_info->sess_rsvd);
3716  p_status_info->inst_state = ni_logan_htons(p_status_info->inst_state);
3717  p_status_info->inst_err_no = ni_logan_htons(p_status_info->inst_err_no);
3718  p_status_info->wr_buf_avail_size = ni_logan_htonl(p_status_info->wr_buf_avail_size);
3719  p_status_info->rd_buf_avail_size = ni_logan_htonl(p_status_info->rd_buf_avail_size);
3720  p_status_info->sess_timestamp = ni_logan_htonll(p_status_info->sess_timestamp);
3721  // session statistics
3722  p_status_info->frames_input = ni_logan_htonl(p_status_info->frames_input);
3723  p_status_info->frames_buffered = ni_logan_htonl(p_status_info->frames_buffered);
3724  p_status_info->frames_completed = ni_logan_htonl(p_status_info->frames_completed);
3725  p_status_info->frames_output = ni_logan_htonl(p_status_info->frames_output);
3726  p_status_info->frames_dropped = ni_logan_htonl(p_status_info->frames_dropped);
3727  p_status_info->inst_errors = ni_logan_htonl(p_status_info->inst_errors);
3728 
3729  // get the session timestamp when open session
3730  // check the timestamp during transcoding
3731  if (NI_LOGAN_NO_CHECK_TS_NVME_CMD_OP == opcode)
3732  {
3733  p_ctx->session_timestamp = p_status_info->sess_timestamp;
3734  ni_log(NI_LOG_TRACE, "Session Open instance id:%u, timestamp:%" PRIu64 "\n",
3735  p_ctx->session_id, p_ctx->session_timestamp);
3736  }
3737  else if (p_ctx->session_timestamp != p_status_info->sess_timestamp &&
3738  ni_logan_xcoder_resource_recovery != p_status_info->inst_err_no) // if VPU recovery, the session timestamp will be reset.
3739  {
3740  ni_log(NI_LOG_ERROR, "instance id invalid:%u, timestamp:%" PRIu64 ", "
3741  "query timestamp:%" PRIu64 ", sess_err_no:%d\n",
3742  p_ctx->session_id, p_ctx->session_timestamp,
3743  p_status_info->sess_timestamp, p_status_info->sess_err_no);
3745  }
3746 
3747  // map the ni_logan_xcoder_mgr_retcode_t (regular i/o rc) to ni_logan_retcode_t
3748  switch (p_status_info->inst_err_no)
3749  {
3751  p_status_info->inst_err_no = NI_LOGAN_RETCODE_SUCCESS;
3752  break;
3755  break;
3758  break;
3761  break;
3764  break;
3765  default:
3766  ; // kept unchanged
3767  }
3768 
3769  // check rc here, if rc != NI_LOGAN_RETCODE_SUCCESS, it means that last read/write command failed
3770  // failures may be link layer errors, such as physical link errors or ERROR_WRITE_PROTECT in windows.
3771  if (NI_LOGAN_RETCODE_SUCCESS != rc)
3772  {
3773  ni_log(NI_LOG_ERROR, "%s():last command Failed: rc %d\n", __FUNCTION__, rc);
3775  }
3776  else
3777  {
3778  ni_log(NI_LOG_TRACE, "%s stats, frames input: %u buffered: %u "
3779  "completed: %u output: %u dropped: %u ,inst_errors: %u\n",
3780  __FUNCTION__, p_status_info->frames_input,
3781  p_status_info->frames_buffered, p_status_info->frames_completed,
3782  p_status_info->frames_output, p_status_info->frames_dropped,
3783  p_status_info->inst_errors);
3784  }
3785 
3786  ni_log(NI_LOG_TRACE, "%s(): sess_err_no %u inst_state %u inst_err_no 0x%x\n",
3787  __FUNCTION__, p_status_info->sess_err_no, p_status_info->inst_state,
3788  p_status_info->inst_err_no);
3789 
3790  p_ctx->session_stats = *p_status_info;
3791 
3792  END:
3793 
3794  ni_logan_aligned_free(p_buffer);
3795 
3796  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
3797 
3798  return retval;
3799 }
3800 
3801 
3802 /*!*****************************************************************************
3803  * \brief Query a particular xcoder instance to get buffer/data Info data
3804  *
3805  * \param ni_logan_session_context_t p_ctx - xcoder Context
3806  * \param ni_logan_instance_buf_info_rw_type_t rw_type
3807  * \param ni_logan_device_type_t device_type - xcoder type Encoder or Decoder
3808  * \param ni_logan_instance_buf_info_t *out - Struct preallocated from the caller
3809  * where the resulting data will be placed
3810  *
3811  * \return - NI_LOGAN_RETCODE_SUCCESS on success, NI_LOGAN_RETCODE_ERROR_INVALID_SESSION,
3812  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC or NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED on
3813  * failure
3814  ******************************************************************************/
3817  ni_logan_device_type_t device_type,
3818  ni_logan_instance_buf_info_t *p_inst_buf_info,
3819  bool is_hw)
3820 {
3821  void* p_buffer = NULL;
3823  uint32_t ui32LBA = 0;
3824  uint32_t dataLen = ((sizeof(ni_logan_instance_buf_info_t) +
3827 
3828  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
3829 
3830  if (!p_ctx || !p_inst_buf_info)
3831  {
3832  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
3834  LRETURN;
3835  }
3836 
3837  if (! (NI_LOGAN_DEVICE_TYPE_DECODER == device_type ||
3838  NI_LOGAN_DEVICE_TYPE_ENCODER == device_type))
3839  {
3840  ni_log(NI_LOG_TRACE, "ERROR: Unknown device type, return\n");
3842  LRETURN;
3843  }
3844 
3846  {
3847  ni_log(NI_LOG_TRACE, "ERROR: Invalid session ID, return\n");
3849  LRETURN;
3850  }
3851 
3852  if (INST_BUF_INFO_RW_READ == rw_type)
3853  {
3854  ui32LBA = QUERY_INSTANCE_RBUFF_SIZE_R(is_hw, p_ctx->session_id, device_type);
3855  }
3856  else if (INST_BUF_INFO_RW_WRITE == rw_type)
3857  {
3858  ui32LBA = QUERY_INSTANCE_WBUFF_SIZE_R(is_hw, p_ctx->session_id, device_type);
3859  }
3860  else if (INST_BUF_INFO_RW_UPLOAD == rw_type)
3861  {
3862  ui32LBA = QUERY_INSTANCE_UPLOAD_ID_R(is_hw, p_ctx->session_id, device_type);
3863  }
3864  else if (INST_BUF_INFO_R_ACQUIRE == rw_type)
3865  {
3866  ui32LBA = QUERY_INSTANCE_ACQUIRE_BUF(is_hw, p_ctx->session_id, device_type);
3867  }
3868  else
3869  {
3870  ni_log(NI_LOG_ERROR, "ERROR: Unknown query type, return\n");
3872  LRETURN;
3873  }
3874 
3875  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), dataLen))
3876  {
3877  ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer.\n",
3878  NI_ERRNO, __FUNCTION__);
3880  LRETURN;
3881  }
3882 
3883  memset(p_buffer, 0, dataLen);
3884 
3885  if (ni_logan_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_buffer, dataLen, ui32LBA) < 0)
3886  {
3887  ni_log(NI_LOG_TRACE, "%s(): NVME command Failed\n", __FUNCTION__);
3889  LRETURN;
3890  }
3891 
3892  memcpy((void*)p_inst_buf_info, p_buffer, sizeof(ni_logan_instance_buf_info_t));
3893 
3894  p_inst_buf_info->buf_avail_size = ni_logan_htonl(p_inst_buf_info->buf_avail_size);
3895 
3896  END:
3897 
3898  ni_logan_aligned_free(p_buffer);
3899 
3900  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
3901 
3902  return retval;
3903 }
3904 
3905 /*!*****************************************************************************
3906  * \brief Configure the read/write pipe for a session
3907  * Use HW frame index to read/write the YUV from/to HW
3908  *
3909  * \param ni_logan_session_context_t p_ctx - xcoder Context
3910  * \param ni_logan_session_config_rw_t rw_type
3911  * \param ni_logan_device_type_t device_type - xcoder type Encoder or Decoder
3912  * \param uint8_t enable
3913  * \param uint8_t hw_action
3914  * \param uint16_t frame_id
3915  *
3916  * \return - NI_LOGAN_RETCODE_SUCCESS on success, NI_LOGAN_RETCODE_ERROR_INVALID_SESSION,
3917  * NI_LOGAN_RETCODE_ERROR_MEM_ALOC or NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED on
3918  * failure
3919  ******************************************************************************/
3922  uint8_t enable,
3923  uint8_t hw_action,
3924  uint16_t frame_id)
3925 {
3927  uint32_t ui32LBA = 0;
3928  void * p_buffer = NULL;
3929  uint32_t buffer_size = 0;
3930  ni_logan_inst_config_rw_t * rw_config = NULL;
3931 
3932  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
3933 
3934  if (!p_ctx)
3935  {
3936  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
3938  LRETURN;
3939  }
3940 
3941  if ( !((INST_READ_CONFIG == rw_type) ||
3942  (INST_WRITE_CONFIG == rw_type)))
3943  {
3944  ni_log(NI_LOG_ERROR, "ERROR: Unknown rw type, return\n");
3946  LRETURN;
3947  }
3948 
3950  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size))
3951  {
3952  ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate read write config buffer.\n");
3954  LRETURN;
3955  }
3956 
3957  memset(p_buffer, 0, buffer_size);
3958 
3959  rw_config = (ni_logan_inst_config_rw_t *)p_buffer;
3960  rw_config->ui8Enable = enable;
3961  rw_config->ui8HWAccess = hw_action;
3962  switch(rw_type)
3963  {
3964  case INST_READ_CONFIG:
3965  rw_config->uHWAccessField.ui16ReadFrameId = frame_id;
3966  break;
3967  case INST_WRITE_CONFIG:
3968  rw_config->uHWAccessField.ui16WriteFrameId = frame_id;
3969  break;
3970  default:
3971  ni_log(NI_LOG_ERROR, "ERROR: Unknown rw type, return\n");
3973  LRETURN;
3974  }
3975 
3976  switch(rw_type)
3977  {
3978  case INST_READ_CONFIG:
3980  break;
3981  case INST_WRITE_CONFIG:
3982  ui32LBA = CONFIG_SESSION_Write_W(p_ctx->session_id);
3983  break;
3984  default:
3985  ni_log(NI_LOG_ERROR, "ERROR: Unknown rw type, return\n");
3987  LRETURN;
3988  }
3989  if (ni_logan_nvme_send_write_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_buffer, buffer_size, ui32LBA) < 0)
3990  {
3991  ni_log(NI_LOG_ERROR, "%s(): NVME command Failed\n", __FUNCTION__);
3993  LRETURN;
3994  }
3995 
3996  END:
3997 
3998  ni_logan_aligned_free(p_buffer);
3999 
4000  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
4001 
4002  return retval;
4003 }
4004 
4005 /*!******************************************************************************
4006  * \brief Send a p_config command for Start Of Stream
4007  *
4008  * \param ni_logan_session_context_t p_ctx - xcoder Context
4009  * \param ni_logan_device_type_t device_type - xcoder type Encoder, Decoder or Uploader
4010  *
4011  * \return - NI_LOGAN_RETCODE_SUCCESS on success, NI_LOGAN_RETCODE_ERROR_INVALID_SESSION. NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED on failure
4012  *******************************************************************************/
4014  ni_logan_device_type_t device_type)
4015 {
4017  uint32_t ui32LBA = 0;
4018  bool is_hw = (NI_LOGAN_DEVICE_TYPE_UPLOAD == device_type);
4019 
4020  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
4021 
4022  if (!p_ctx)
4023  {
4024  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
4026  LRETURN;
4027  }
4028 
4029  if (! (NI_LOGAN_DEVICE_TYPE_DECODER == device_type ||
4030  NI_LOGAN_DEVICE_TYPE_ENCODER == device_type ||
4031  NI_LOGAN_DEVICE_TYPE_UPLOAD == device_type))
4032  {
4033  ni_log(NI_LOG_TRACE, "ERROR: Unknown device type, return\n");
4035  LRETURN;
4036  }
4037 
4039  {
4040  ni_log(NI_LOG_TRACE, "ERROR: Invalid session ID, return\n");
4042  LRETURN;
4043  }
4044 
4045  ui32LBA = CONFIG_INSTANCE_SetSOS_W(is_hw, p_ctx->session_id, device_type);
4046 
4048  NI_LOGAN_DATA_BUFFER_LEN, ui32LBA) < 0)
4049  {
4050  ni_log(NI_LOG_TRACE, " %s(): NVME command Failed\n", __FUNCTION__);
4052  }
4053 
4054  END:
4055 
4056  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
4057 
4058  return retval;
4059 }
4060 
4061 /*!******************************************************************************
4062  * \brief Send a p_config command for End Of Stream
4063  *
4064  * \param ni_logan_session_context_t p_ctx - xcoder Context
4065  * \param ni_logan_device_type_t device_type - xcoder type Encoder or Decoder
4066  *
4067  * \return - NI_LOGAN_RETCODE_SUCCESS on success, NI_LOGAN_RETCODE_ERROR_INVALID_SESSION, NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED on failure
4068  *******************************************************************************/
4070  ni_logan_device_type_t device_type)
4071 {
4073  uint32_t ui32LBA = 0;
4074 
4075  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
4076 
4077  if (!p_ctx)
4078  {
4079  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
4081  LRETURN;
4082  }
4083 
4084  if (! (NI_LOGAN_DEVICE_TYPE_DECODER == device_type ||
4085  NI_LOGAN_DEVICE_TYPE_ENCODER == device_type))
4086  {
4087  ni_log(NI_LOG_TRACE, "ERROR: Unknown device type, return\n");
4089  LRETURN;
4090  }
4091 
4093  {
4094  ni_log(NI_LOG_TRACE, "ERROR: Invalid session ID, return\n");
4096  LRETURN;
4097  }
4098 
4099  ui32LBA = CONFIG_INSTANCE_SetEOS_W(p_ctx->session_id, device_type);
4100 
4102  NI_LOGAN_DATA_BUFFER_LEN, ui32LBA) < 0)
4103  {
4104  ni_log(NI_LOG_TRACE, "%s(): NVME command Failed\n", __FUNCTION__);
4106  }
4107 
4108  END:
4109 
4110  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
4111 
4112  return retval;
4113 }
4114 
4115 /*!******************************************************************************
4116  * \brief Send a p_config command for Flush Of Stream
4117  *
4118  * \param ni_logan_session_context_t p_ctx - xcoder Context
4119  * \param ni_logan_device_type_t device_type - xcoder type Encoder or Decoder
4120  *
4121  * \return - NI_LOGAN_RETCODE_SUCCESS on success, NI_LOGAN_RETCODE_ERROR_INVALID_SESSION,
4122  * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED on failure
4123  *******************************************************************************/
4125  ni_logan_device_type_t device_type)
4126 {
4128  uint32_t ui32LBA = 0;
4129 
4130  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
4131 
4132  if (!p_ctx)
4133  {
4134  ni_log(NI_LOG_TRACE, "ERROR: passed parameters are null!, return\n");
4136  LRETURN;
4137  }
4138 
4139  if (! (NI_LOGAN_DEVICE_TYPE_DECODER == device_type))
4140  {
4141  ni_log(NI_LOG_TRACE, "ERROR: Unknown device type, return\n");
4143  LRETURN;
4144  }
4145 
4147  {
4148  ni_log(NI_LOG_TRACE, "ERROR: Invalid session ID, return\n");
4150  LRETURN;
4151  }
4152 
4153  ui32LBA = CONFIG_INSTANCE_SetFlush_W(p_ctx->session_id, device_type);
4154 
4156  NI_LOGAN_DATA_BUFFER_LEN, ui32LBA) < 0)
4157  {
4158  ni_log(NI_LOG_TRACE, "%s(): NVME command Failed\n", __FUNCTION__);
4160  }
4161 
4162  END:
4163 
4164  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
4165 
4166  return retval;
4167 }
4168 
4169 /*!******************************************************************************
4170  * \brief Send a p_config command to configure encoding parameters.
4171  *
4172  * \param ni_logan_session_context_t p_ctx - xcoder Context
4173  *
4174  * \return - NI_LOGAN_RETCODE_SUCCESS on success, NI_LOGAN_RETCODE_ERROR_INVALID_SESSION, NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED on failure
4175  *******************************************************************************/
4177 {
4178  void* p_encoder_config = NULL;
4179  ni_logan_encoder_config_t* p_cfg = NULL;
4180  uint32_t buffer_size = sizeof(ni_logan_encoder_config_t);
4182  uint32_t ui32LBA = 0;
4183  uint32_t i = 0;
4184  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
4185 
4186  if (!p_ctx)
4187  {
4188  ni_log(NI_LOG_TRACE, "ERROR: %s(): NULL pointer p_config passed\n", __FUNCTION__);
4190  LRETURN;
4191  }
4192 
4194  {
4195  ni_log(NI_LOG_TRACE, "ERROR: Invalid session ID, return\n");
4197  LRETURN;
4198  }
4199 
4201  if (ni_logan_posix_memalign(&p_encoder_config, sysconf(_SC_PAGESIZE), buffer_size))
4202  {
4203  ni_log(NI_LOG_ERROR, "ERROR %d: Cannot allocate encConf buffer.\n", NI_ERRNO);
4205  LRETURN;
4206  }
4207  memset(p_encoder_config, 0, buffer_size);
4208 
4209  ni_logan_set_custom_template(p_ctx, p_encoder_config, p_ctx->p_session_config);
4210  if (NI_LOGAN_RETCODE_SUCCESS !=ni_logan_validate_custom_template(p_ctx, p_encoder_config, p_ctx->p_session_config,
4211  p_ctx->param_err_msg, sizeof(p_ctx->param_err_msg)))
4212  {
4213  ni_log(NI_LOG_TRACE, "ERROR: ni_logan_validate_custom_template failed. %s\n",
4214  p_ctx->param_err_msg);
4215  ni_log(NI_LOG_INFO, "ERROR: ni_logan_validate_custom_template failed. %s\n",
4216  p_ctx->param_err_msg);
4217  fflush(stderr);
4219  LRETURN;
4220  }
4221 
4222  // configure the session
4224 
4225  //Flip the bytes!!
4226  p_cfg = (ni_logan_encoder_config_t*)p_encoder_config;
4227 
4228  uint8_t str_vui[4 * NI_LOGAN_MAX_VUI_SIZE];
4229  for (i = 0; i < p_cfg->ui32VuiDataSizeBytes; i++)
4230  {
4231  snprintf(&str_vui[i * 3], 4, "%.2x ", p_cfg->ui8VuiRbsp[i]);
4232  }
4233  str_vui[3 * p_cfg->ui32VuiDataSizeBytes] = '\0';
4234  ni_log(NI_LOG_DEBUG, "VUI = %s\n", str_vui);
4235 
4236  p_cfg->i32picWidth = ni_logan_htonl(p_cfg->i32picWidth);
4237  p_cfg->i32picHeight = ni_logan_htonl(p_cfg->i32picHeight);
4238  p_cfg->i32meBlkMode = ni_logan_htonl(p_cfg->i32meBlkMode);
4239  p_cfg->i32frameRateInfo = ni_logan_htonl(p_cfg->i32frameRateInfo);
4240  p_cfg->i32vbvBufferSize = ni_logan_htonl(p_cfg->i32vbvBufferSize);
4241  p_cfg->i32userQpMax = ni_logan_htonl(p_cfg->i32userQpMax);
4242  p_cfg->i32maxIntraSize = ni_logan_htonl(p_cfg->i32maxIntraSize);
4243  p_cfg->i32userMaxDeltaQp = ni_logan_htonl(p_cfg->i32userMaxDeltaQp);
4244  p_cfg->i32userMinDeltaQp = ni_logan_htonl(p_cfg->i32userMinDeltaQp);
4245  p_cfg->i32userQpMin = ni_logan_htonl(p_cfg->i32userQpMin);
4246  p_cfg->i32bitRate = ni_logan_htonl(p_cfg->i32bitRate);
4247  p_cfg->i32bitRateBL = ni_logan_htonl(p_cfg->i32bitRateBL);
4248  p_cfg->i32srcBitDepth = ni_logan_htonl(p_cfg->i32srcBitDepth);
4249  p_cfg->hdrEnableVUI = ni_logan_htonl(p_cfg->hdrEnableVUI);
4250  p_cfg->ui32VuiDataSizeBits = ni_logan_htonl(p_cfg->ui32VuiDataSizeBits);
4251  p_cfg->ui32VuiDataSizeBytes = ni_logan_htonl(p_cfg->ui32VuiDataSizeBytes);
4252  p_cfg->ui32flushGop = ni_logan_htonl(p_cfg->ui32flushGop);
4253  p_cfg->ui32minIntraRefreshCycle = ni_logan_htonl(p_cfg->ui32minIntraRefreshCycle);
4254  p_cfg->ui32fillerEnable = ni_logan_htonl(p_cfg->ui32fillerEnable);
4255  p_cfg->ui8hwframes = ni_logan_htonl(p_cfg->ui8hwframes);
4256  p_cfg->ui8explicitRefListEnable = ni_logan_htonl(p_cfg->ui8explicitRefListEnable);
4257  // no flipping reserved field as enableAUD now takes one byte from it
4258 
4259  // flip the NI_LOGAN_MAX_VUI_SIZE bytes of the VUI field using 32 bits pointers
4260  for (i = 0 ; i < (NI_LOGAN_MAX_VUI_SIZE >> 2) ; i++) // apply on 32 bits
4261  {
4262  ((uint32_t*)p_cfg->ui8VuiRbsp)[i] = ni_logan_htonl(((uint32_t*)p_cfg->ui8VuiRbsp)[i]);
4263  }
4264 
4266  p_encoder_config, buffer_size, ui32LBA);
4267  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config,
4268  p_ctx->device_type, p_ctx->hw_id,
4269  &(p_ctx->session_id));
4270  CHECK_VPU_RECOVERY(retval);
4271  if (NI_LOGAN_RETCODE_SUCCESS != retval)
4272  {
4273  ni_log(NI_LOG_TRACE, "ERROR: ni_logan_nvme_send_write_cmd failed: blk_io_handle: %" PRIx64 ", "
4274  "hw_id, %u, xcoder_inst_id: %d\n", (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id, p_ctx->session_id);
4275  //Close the session since we can't configure it
4276  retval = ni_logan_encoder_session_close(p_ctx, 0);
4277  if (NI_LOGAN_RETCODE_SUCCESS != retval)
4278  {
4279  ni_log(NI_LOG_TRACE, "ERROR: ni_logan_encoder_session_close failed: blk_io_handle: %" PRIx64 ", "
4280  "hw_id, %u, xcoder_inst_id: %d\n", (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id, p_ctx->session_id);
4281  }
4283  }
4284 
4285  END:
4286 
4287  ni_logan_aligned_free(p_encoder_config);
4288 
4289  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
4290 
4291  return retval;
4292 }
4293 
4294 
4295 // return non-0 if SEI of requested type is found, 0 otherwise
4296 static int find_sei(uint32_t sei_header,
4299  uint32_t *pSeiOffset,
4300  uint32_t *pSeiSize)
4301 {
4302  int ret = 0;
4303 
4304  if ( (!pEntry) || (!pSeiOffset) || (!pSeiSize) )
4305  {
4306  return ret;
4307  }
4308 
4309  if (sei_header & (1 << type))
4310  {
4311  *pSeiOffset = pEntry[type].offset;
4312  *pSeiSize = pEntry[type].size;
4313  ni_log(NI_LOG_TRACE, "%s sei type %d, offset: %u size: %u\n",
4314  __FUNCTION__, type, *pSeiOffset, *pSeiSize);
4315  ret = 1;
4316  }
4317 
4318  return ret;
4319 }
4320 
4321 // return non-0 if prefix or suffix T.35 message is found
4322 static int find_prefix_suffix_t35(uint32_t sei_header,
4326  uint32_t *pCcOffset,
4327  uint32_t *pCcSize)
4328 {
4329  int ret = 0;
4330  uint8_t *ptr;
4331 
4332  if (!pEntry || !pCcOffset || !pCcSize)
4333  {
4334  return ret;
4335  }
4336 
4337  // Find first t35 message with CEA708 close caption (first 8
4338  // bytes are itu_t_t35_country_code 0xB5 0x00 (181),
4339  // itu_t_t35_provider_code = 0x31 (49),
4340  // ATSC_user_identifier = 0x47 0x41 0x39 0x34 ("GA94")
4341  // should check 8th byte for close caption : cc_data = 0x03
4342  // or HDR10+ header bytes
4343  if (sei_header & (1 << type))
4344  {
4345  ptr = (uint8_t*) pEntry + pEntry[type].offset;
4346  if (NI_LOGAN_T35_SEI_CLOSED_CAPTION == t35_type &&
4347  ptr[0] == NI_CC_SEI_BYTE0 && ptr[1] == NI_CC_SEI_BYTE1 &&
4348  ptr[2] == NI_CC_SEI_BYTE2 && ptr[3] == NI_CC_SEI_BYTE3 &&
4349  ptr[4] == NI_CC_SEI_BYTE4 && ptr[5] == NI_CC_SEI_BYTE5 &&
4350  ptr[6] == NI_CC_SEI_BYTE6 && ptr[7] == NI_CC_SEI_BYTE7)
4351  {
4352  *pCcOffset = pEntry[type].offset;
4353  *pCcSize = pEntry[type].size;
4354  ni_log(NI_LOG_TRACE, "%s: close Caption SEI found in T.35 type %d, offset: %u size: %u\n",
4355  __FUNCTION__, type, *pCcOffset, *pCcSize);
4356  ret = 1;
4357  }
4358  else if (NI_LOGAN_T35_SEI_HDR10_PLUS == t35_type &&
4359  ptr[0] == NI_HDR10P_SEI_BYTE0 && ptr[1] == NI_HDR10P_SEI_BYTE1 &&
4360  ptr[2] == NI_HDR10P_SEI_BYTE2 && ptr[3] == NI_HDR10P_SEI_BYTE3 &&
4361  ptr[4] == NI_HDR10P_SEI_BYTE4 && ptr[5] == NI_HDR10P_SEI_BYTE5 &&
4362  ptr[6] == NI_HDR10P_SEI_BYTE6)
4363  {
4364  *pCcOffset = pEntry[type].offset;
4365  *pCcSize = pEntry[type].size;
4366  ni_log(NI_LOG_TRACE, "%s: HDR10+ SEI found in T.35 type %d, offset: %u size: %u\n",
4367  __FUNCTION__, type, *pCcOffset, *pCcSize);
4368  ret = 1;
4369  }
4370  }
4371 
4372  return ret;
4373 }
4374 
4375 // return non-0 when HDR10+/close-caption is found, 0 otherwise
4376 static int find_t35_sei(uint32_t sei_header,
4379  uint32_t *pCcOffset,
4380  uint32_t *pCcSize)
4381 {
4382  int ret = 0;
4383 
4384  if ( (!pEntry) || (!pCcOffset) || (!pCcSize) )
4385  {
4386  return ret;
4387  }
4388 
4389  *pCcOffset = *pCcSize = 0;
4390 
4391  // Check up to 3 T35 Prefix and Suffix SEI for close captions
4392  if (find_prefix_suffix_t35(sei_header, t35_type, pEntry,
4394  pCcOffset, pCcSize) ||
4395  find_prefix_suffix_t35(sei_header, t35_type, pEntry,
4397  pCcOffset, pCcSize) ||
4398  find_prefix_suffix_t35(sei_header, t35_type, pEntry,
4400  pCcOffset, pCcSize) ||
4401  find_prefix_suffix_t35(sei_header, t35_type, pEntry,
4403  pCcOffset, pCcSize) ||
4404  find_prefix_suffix_t35(sei_header, t35_type, pEntry,
4406  pCcOffset, pCcSize) ||
4407  find_prefix_suffix_t35(sei_header, t35_type, pEntry,
4409  pCcOffset, pCcSize)
4410  )
4411  {
4412  ret = 1;
4413  }
4414  return ret;
4415 }
4416 
4417 /*!******************************************************************************
4418  * \brief Get info from received p_frame
4419  *
4420  * \param
4421  *
4422  * \return
4423  *******************************************************************************/
4424 int ni_logan_create_frame(ni_logan_frame_t* p_frame, uint32_t read_length, uint64_t* p_frame_offset, bool is_hw_frame)
4425 {
4426  uint32_t rx_size = read_length; //get the length since its the only thing in DW10 now
4427 
4428  if (!p_frame || !p_frame_offset)
4429  {
4430  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n", __FUNCTION__);
4432  }
4433 
4434  uint8_t* p_buf = (uint8_t*) p_frame->p_buffer;
4435 
4436  *p_frame_offset = 0;
4437 
4438  int metadata_size = NI_LOGAN_FW_META_DATA_SZ - (1 - is_hw_frame) * sizeof(ni_logan_hwframe_surface_t);
4439  unsigned int video_data_size = p_frame->data_len[0] + p_frame->data_len[1] + \
4440  p_frame->data_len[2] + ((is_hw_frame) ? p_frame->data_len[3] : 0);
4441  ni_log(NI_LOG_TRACE, "%s rx_size = %d video_data_size = %d metadataSize = %d\n",
4442  __FUNCTION__, rx_size, video_data_size, metadata_size);
4443 
4444  p_frame->p_custom_sei = NULL;
4445 
4446  if (rx_size == metadata_size)
4447  {
4448  video_data_size = 0;
4449  }
4450 
4451  if (rx_size > video_data_size)
4452  {
4453  ni_logan_metadata_dec_frame_t* p_meta = (ni_logan_metadata_dec_frame_t*)((uint8_t*)p_frame->p_buffer + video_data_size);
4454 
4455 
4456  *p_frame_offset = p_meta->metadata_common.ui64_data.frame_offset;
4457  rx_size -= metadata_size;
4458  p_frame->crop_top = p_meta->metadata_common.crop_top;
4459  p_frame->crop_bottom = p_meta->metadata_common.crop_bottom;
4460  p_frame->crop_left = p_meta->metadata_common.crop_left;
4461  p_frame->crop_right = p_meta->metadata_common.crop_right;
4462  p_frame->ni_logan_pict_type = p_meta->metadata_common.frame_type;
4463  p_frame->bit_depth = p_meta->metadata_common.bit_depth;
4464  p_frame->video_width = p_meta->metadata_common.frame_width;
4465  p_frame->video_height = p_meta->metadata_common.frame_height;
4466 
4467  ni_log(NI_LOG_TRACE, "%s: is_hw_frame=%d, [metadata] cropRight=%u, cropLeft=%u, "
4468  "cropBottom=%u, cropTop=%u, frame_offset=%" PRIu64 ", pic=%ux%u %dbits, pict_type=%d, "
4469  "crop=%ux%u, sei header: 0x%0x number %u size %u \n", __FUNCTION__,
4470  is_hw_frame, p_frame->crop_right, p_frame->crop_left, p_frame->crop_bottom, p_frame->crop_top,
4473  p_frame->crop_right - p_frame->crop_left, p_frame->crop_bottom - p_frame->crop_top,
4474  p_meta->sei_header, p_meta->sei_number, p_meta->sei_size);
4475 
4476  p_frame->sei_total_len =
4477  p_frame->sei_cc_offset = p_frame->sei_cc_len =
4482  p_frame->sei_hdr_plus_offset = p_frame->sei_hdr_plus_len =
4485  p_frame->vui_offset = p_frame->vui_len =
4486  p_frame->sei_user_data_unreg_offset = p_frame->sei_user_data_unreg_len = 0;
4487  if (p_meta->sei_header && p_meta->sei_number && p_meta->sei_size)
4488  {
4490  uint32_t ui32CCOffset = 0, ui32CCSize = 0;
4491 
4492  rx_size -= p_meta->sei_size;
4493 
4494  pEntry = (ni_logan_sei_user_data_entry_t *)((uint8_t*)p_meta + metadata_size);
4495 
4496  if (find_t35_sei(p_meta->sei_header, NI_LOGAN_T35_SEI_HDR10_PLUS, pEntry,
4497  &ui32CCOffset, &ui32CCSize))
4498  {
4499  p_frame->sei_hdr_plus_len = ui32CCSize;
4500  p_frame->sei_hdr_plus_offset =
4501  video_data_size + metadata_size + ui32CCOffset;
4502 
4503  p_frame->sei_total_len += ui32CCSize;
4504 
4505  ni_log(NI_LOG_TRACE, "%s: hdr10+ size=%u hdr10+ offset=%u\n",
4506  __FUNCTION__, p_frame->sei_hdr_plus_len, p_frame->sei_hdr_plus_offset);
4507  }
4508  else
4509  {
4510  ni_log(NI_LOG_TRACE, "%s: hdr+ NOT found in meta data!\n", __FUNCTION__);
4511  }
4512 
4513  if (find_t35_sei(p_meta->sei_header, NI_LOGAN_T35_SEI_CLOSED_CAPTION, pEntry,
4514  &ui32CCOffset, &ui32CCSize))
4515  {
4516  uint8_t *ptr;
4517  // Found CC data at pEntry + ui32CCOffset
4518  ptr = (uint8_t*)pEntry + ui32CCOffset;
4519  // number of 3 byte close captions is bottom 5 bits of
4520  // 9th byte of T35 payload
4521  ui32CCSize = (ptr[8] & 0x1F) * 3;
4522 
4523  // return close caption data offset and length, and
4524  // skip past 10 header bytes to close caption data
4525  p_frame->sei_cc_len = ui32CCSize;
4526  p_frame->sei_cc_offset = video_data_size + metadata_size
4527  + ui32CCOffset + 10;
4528 
4529  p_frame->sei_total_len += p_frame->sei_cc_len;
4530 
4531  ni_log(NI_LOG_TRACE, "%s: close caption size %u offset %u = video "
4532  "size %u meta size %u off %u + 10\n", __FUNCTION__,
4533  p_frame->sei_cc_len, p_frame->sei_cc_offset, video_data_size,
4534  metadata_size, ui32CCOffset);
4535  }
4536  else
4537  {
4538  ni_log(NI_LOG_TRACE, "%s: close caption NOT found in meta data!\n", __FUNCTION__);
4539  }
4540 
4541  if (find_sei(p_meta->sei_header, pEntry,
4543  &ui32CCOffset, &ui32CCSize))
4544  {
4545  p_frame->sei_hdr_mastering_display_color_vol_len = ui32CCSize;
4547  video_data_size + metadata_size + ui32CCOffset;
4548 
4549  p_frame->sei_total_len += ui32CCSize;
4550 
4552  (ni_logan_dec_mastering_display_colour_volume_t*)((uint8_t*)pEntry + ui32CCOffset);
4553 
4554  ni_log(NI_LOG_TRACE, "Display Primaries x[0]=%u y[0]=%u\n",
4555  pColourVolume->display_primaries_x[0],
4556  pColourVolume->display_primaries_y[0]);
4557  ni_log(NI_LOG_TRACE, "Display Primaries x[1]=%u y[1]=%u\n",
4558  pColourVolume->display_primaries_x[1],
4559  pColourVolume->display_primaries_y[1]);
4560  ni_log(NI_LOG_TRACE, "Display Primaries x[2]=%u y[2]=%u\n",
4561  pColourVolume->display_primaries_x[2],
4562  pColourVolume->display_primaries_y[2]);
4563 
4564  ni_log(NI_LOG_TRACE, "White Point x=%u y=%u\n",
4565  pColourVolume->white_point_x,
4566  pColourVolume->white_point_y);
4567  ni_log(NI_LOG_TRACE, "Display Mastering Lum, Max=%u Min=%u\n",
4568  pColourVolume->max_display_mastering_luminance, pColourVolume->min_display_mastering_luminance);
4569  }
4570  if (find_sei(p_meta->sei_header, pEntry,
4572  &ui32CCOffset, &ui32CCSize))
4573  {
4574  p_frame->sei_hdr_content_light_level_info_len = ui32CCSize;
4576  video_data_size + metadata_size + ui32CCOffset;
4577 
4578  p_frame->sei_total_len += ui32CCSize;
4579 
4581  (ni_logan_content_light_level_info_t*)((uint8_t*)pEntry + ui32CCOffset);
4582  ni_log(NI_LOG_TRACE, "Max Content Light level=%u Max Pic Avg Light Level=%u\n",
4583  pLightLevel->max_content_light_level, pLightLevel->max_pic_average_light_level);
4584  }
4585 
4586  if (find_sei(p_meta->sei_header, pEntry,
4588  &ui32CCOffset, &ui32CCSize) ||
4589  find_sei(p_meta->sei_header, pEntry,
4591  &ui32CCOffset, &ui32CCSize))
4592  {
4593  p_frame->sei_user_data_unreg_len = ui32CCSize;
4594  p_frame->sei_user_data_unreg_offset =
4595  video_data_size + metadata_size + ui32CCOffset;
4596  p_frame->sei_total_len += ui32CCSize;
4597  ni_log(NI_LOG_TRACE, "User Data Unreg size = %u, offset %u\n",
4598  ui32CCSize, ui32CCOffset);
4599  }
4600 
4601  if (find_sei(p_meta->sei_header, pEntry,
4602  NI_LOGAN_H265_USERDATA_FLAG_VUI, &ui32CCOffset, &ui32CCSize))
4603  {
4604  p_frame->vui_len = ui32CCSize;
4605  p_frame->vui_offset = video_data_size + metadata_size + ui32CCOffset;
4606 
4607  p_frame->sei_total_len += ui32CCSize;
4608 
4609  ni_log(NI_LOG_TRACE, "VUI size=%u\n", ui32CCSize);
4610  }
4611 
4612  if (find_sei(p_meta->sei_header, pEntry,
4614  &ui32CCOffset, &ui32CCSize))
4615  {
4616  p_frame->sei_alt_transfer_characteristics_len = ui32CCSize;
4618  video_data_size + metadata_size + ui32CCOffset;
4619 
4620  p_frame->sei_total_len += ui32CCSize;
4621 
4622  ni_log(NI_LOG_TRACE, "alternative transfer characteristics=%u %u "
4623  "bytes\n", *((uint8_t*)pEntry + ui32CCOffset), ui32CCSize);
4624  }
4625 
4626  if (0 == p_frame->sei_total_len)
4627  {
4628  ni_log(NI_LOG_DEBUG, "retrieved 0 supported SEI !");
4629  }
4630  }
4631  }
4632 
4633  p_frame->dts = NI_LOGAN_NOPTS_VALUE;
4634  p_frame->pts = NI_LOGAN_NOPTS_VALUE;
4635  //p_frame->end_of_stream = isEndOfStream;
4636  p_frame->start_of_stream = 0;
4637 
4638  if (rx_size == 0)
4639  {
4640  p_frame->data_len[0] = 0;
4641  p_frame->data_len[1] = 0;
4642  p_frame->data_len[2] = 0;
4643  p_frame->data_len[3] = 0;
4644  }
4645 
4646  ni_log(NI_LOG_TRACE, "received [0x%08x] data size: %d, end of stream=%d\n",
4647  read_length, rx_size, p_frame->end_of_stream);
4648 
4649  return rx_size;
4650 }
4651 
4652 /*!******************************************************************************
4653  * \brief Get info from received xcoder capability
4654  *
4655  * \param
4656  *
4657  * \return
4658  *******************************************************************************/
4660 {
4661  int i, total_modules;
4662  ni_logan_nvme_identity_t* p_id_data = (ni_logan_nvme_identity_t*)p_data;
4663 
4664  if ( (!p_cap) || (!p_data) )
4665  {
4666  ni_log(NI_LOG_TRACE, "ERROR: %s(): Null pointer parameters passed\n", __FUNCTION__);
4667  LRETURN;
4668  }
4669 
4670  if ((p_id_data->ui16Vid != NETINT_PCI_VENDOR_ID) ||
4671  (p_id_data->ui16Ssvid != NETINT_PCI_VENDOR_ID))
4672  {
4673  LRETURN;
4674  }
4675 
4676  memset(p_cap->fw_rev, 0, sizeof(p_cap->fw_rev));
4677  memcpy(p_cap->fw_rev, p_id_data->ai8Fr, sizeof(p_cap->fw_rev));
4678  ni_log(NI_LOG_TRACE, "F/W rev: %2.*s\n", (int)sizeof(p_cap->fw_rev),
4679  p_cap->fw_rev);
4680 
4681  p_cap->device_is_xcoder = p_id_data->device_is_xcoder;
4682  ni_log(NI_LOG_TRACE, "device_is_xcoder: %d\n", p_cap->device_is_xcoder);
4683  if (0 == p_cap->device_is_xcoder)
4684  {
4685  LRETURN;
4686  }
4687 
4688  p_cap->hw_elements_cnt = p_id_data->xcoder_num_hw;
4689  if (3 == p_cap->hw_elements_cnt)
4690  {
4691  ni_log(NI_LOG_ERROR, "hw_elements_cnt is 3, Rev A NOT supported !\n");
4692  LRETURN;
4693  }
4694 
4695  p_cap->h264_decoders_cnt = p_id_data->xcoder_num_h264_decoder_hw;
4696  p_cap->h264_encoders_cnt = p_id_data->xcoder_num_h264_encoder_hw;
4697  p_cap->h265_decoders_cnt = p_id_data->xcoder_num_h265_decoder_hw;
4698  p_cap->h265_encoders_cnt = p_id_data->xcoder_num_h265_encoder_hw;
4699  ni_log(NI_LOG_TRACE, "hw_elements_cnt: %d\n", p_cap->hw_elements_cnt);
4700  ni_log(NI_LOG_TRACE, "h264_decoders_cnt: %d\n", p_cap->h264_decoders_cnt);
4701  ni_log(NI_LOG_TRACE, "h264_encoders_cnt: %d\n", p_cap->h264_encoders_cnt);
4702  ni_log(NI_LOG_TRACE, "h265_decoders_cnt: %d\n", p_cap->h265_decoders_cnt);
4703  ni_log(NI_LOG_TRACE, "h265_encoders_cnt: %d\n", p_cap->h265_encoders_cnt);
4704 
4705  total_modules = p_cap->h264_decoders_cnt + p_cap->h264_encoders_cnt +
4706  p_cap->h265_decoders_cnt + p_cap->h265_encoders_cnt;
4707 
4708  if (total_modules >= 1)
4709  {
4710  p_cap->xcoder_devices[0].hw_id = p_id_data->hw0_id;
4714  p_cap->xcoder_devices[0].codec_format = p_id_data->hw0_codec_format;
4715  p_cap->xcoder_devices[0].codec_type = p_id_data->hw0_codec_type;
4720  p_cap->xcoder_devices[0].video_profile = p_id_data->hw0_video_profile;
4721  p_cap->xcoder_devices[0].video_level = p_id_data->hw0_video_level;
4722  }
4723  if (total_modules >= 2)
4724  {
4725  p_cap->xcoder_devices[1].hw_id = p_id_data->hw1_id;
4729  p_cap->xcoder_devices[1].codec_format = p_id_data->hw1_codec_format;
4730  p_cap->xcoder_devices[1].codec_type = p_id_data->hw1_codec_type;
4735  p_cap->xcoder_devices[1].video_profile = p_id_data->hw1_video_profile;
4736  p_cap->xcoder_devices[1].video_level = p_id_data->hw1_video_level;
4737  }
4738  if (total_modules >= 3)
4739  {
4740  p_cap->xcoder_devices[2].hw_id = p_id_data->hw2_id;
4744  p_cap->xcoder_devices[2].codec_format = p_id_data->hw2_codec_format;
4745  p_cap->xcoder_devices[2].codec_type = p_id_data->hw2_codec_type;
4750  p_cap->xcoder_devices[2].video_profile = p_id_data->hw2_video_profile;
4751  p_cap->xcoder_devices[2].video_level = p_id_data->hw2_video_level;
4752  }
4753  if (total_modules >= 4)
4754  {
4755  p_cap->xcoder_devices[3].hw_id = p_id_data->hw3_id;
4759  p_cap->xcoder_devices[3].codec_format = p_id_data->hw3_codec_format;
4760  p_cap->xcoder_devices[3].codec_type = p_id_data->hw3_codec_type;
4765  p_cap->xcoder_devices[3].video_profile = p_id_data->hw3_video_profile;
4766  p_cap->xcoder_devices[3].video_level = p_id_data->hw3_video_level;
4767  }
4768 
4769  for (i = 0; i < NI_LOGAN_MAX_DEVICES_PER_HW_INSTANCE; i++)
4770  {
4771  ni_log(NI_LOG_TRACE, "HW%d hw_id: %d\n", i, p_cap->xcoder_devices[i].hw_id);
4772  ni_log(NI_LOG_TRACE, "HW%d max_number_of_contexts: %d\n", i, p_cap->xcoder_devices[i].max_number_of_contexts);
4773  ni_log(NI_LOG_TRACE, "HW%d max_1080p_fps: %d\n", i, p_cap->xcoder_devices[i].max_1080p_fps);
4774  ni_log(NI_LOG_TRACE, "HW%d codec_format: %d\n", i, p_cap->xcoder_devices[i].codec_format);
4775  ni_log(NI_LOG_TRACE, "HW%d codec_type: %d\n", i, p_cap->xcoder_devices[i].codec_type);
4776  ni_log(NI_LOG_TRACE, "HW%d max_video_width: %d\n", i, p_cap->xcoder_devices[i].max_video_width);
4777  ni_log(NI_LOG_TRACE, "HW%d max_video_height: %d\n", i, p_cap->xcoder_devices[i].max_video_height);
4778  ni_log(NI_LOG_TRACE, "HW%d min_video_width: %d\n", i, p_cap->xcoder_devices[i].min_video_width);
4779  ni_log(NI_LOG_TRACE, "HW%d min_video_height: %d\n", i, p_cap->xcoder_devices[i].min_video_height);
4780  ni_log(NI_LOG_TRACE, "HW%d video_profile: %d\n", i, p_cap->xcoder_devices[i].video_profile);
4781  ni_log(NI_LOG_TRACE, "HW%d video_level: %d\n", i, p_cap->xcoder_devices[i].video_level);
4782  }
4783 
4784  memset(p_cap->fw_commit_hash, 0, sizeof(p_cap->fw_commit_hash));
4785  memcpy(p_cap->fw_commit_hash, p_id_data->fw_commit_hash, sizeof(p_cap->fw_commit_hash) - 1);
4786  ni_log(NI_LOG_TRACE, "F/W commit hash: %s\n", p_cap->fw_commit_hash);
4787  memset(p_cap->fw_commit_time, 0, sizeof(p_cap->fw_commit_time));
4788  memcpy(p_cap->fw_commit_time, p_id_data->fw_commit_time, sizeof(p_cap->fw_commit_time) - 1);
4789  ni_log(NI_LOG_TRACE, "F/W commit hash: %s\n", p_cap->fw_commit_time);
4790  memset(p_cap->fw_branch_name, 0, sizeof(p_cap->fw_branch_name));
4791  memcpy(p_cap->fw_branch_name, p_id_data->fw_branch_name, sizeof(p_cap->fw_branch_name) - 1);
4792  ni_log(NI_LOG_TRACE, "F/W commit hash: %s\n", p_cap->fw_branch_name);
4793 
4794  END:
4795  return;
4796 }
4797 
4798 static uint32_t presetGopSize[] = {
4799  1,
4800  1,
4801  1,
4802  1,
4803  2,
4804  4,
4805  4,
4806  4,
4807  8 };
4808 
4809 static uint32_t presetGopKeyFrameFactor[] = {
4810  1,
4811  1,
4812  1,
4813  1,
4814  2,
4815  4,
4816  1,
4817  1,
4818  1 };
4819 
4820 /*!******************************************************************************
4821  * \brief Setup all xcoder configurations with custom parameters (Rev. B)
4822  *
4823  * \param
4824  *
4825  * \return
4826  ******************************************************************************/
4830 {
4831 
4832  ni_logan_t408_config_t* p_t408 = &(p_cfg->niParamT408);
4834  int i = 0;
4835 
4836  if ( (!p_ctx) || (!p_cfg) || (!p_src) )
4837  {
4838  ni_log(NI_LOG_TRACE, "ERROR: %s() Null pointer parameters passed\n",
4839  __FUNCTION__);
4840  return;
4841  }
4842 
4843  ni_logan_set_default_template(p_ctx, p_cfg);
4844 
4845  if (p_cfg->i32picWidth != p_src->source_width)
4846  {
4847  p_cfg->i32picWidth = p_src->source_width;
4848  }
4849 
4850  if (p_cfg->i32picHeight != p_src->source_height)
4851  {
4852  p_cfg->i32picHeight = p_src->source_height;
4853  }
4854 
4855  if (p_t408->gop_preset_index != p_enc->gop_preset_index)
4856  {
4857  p_t408->gop_preset_index = p_enc->gop_preset_index;
4858  }
4859 
4860  if (p_t408->use_recommend_enc_params != p_enc->use_recommend_enc_params)
4861  {
4863  }
4864 
4865  // trans_rate, enable_hvs_qp_scale:
4866  // are not present in Rev B p_config
4867 
4868  if (p_cfg->ui8rcEnable != p_enc->rc.enable_rate_control)
4869  {
4870  p_cfg->ui8rcEnable = p_enc->rc.enable_rate_control;
4871  }
4872 
4873  if (p_src->bitrate != 0)
4874  {
4875  p_cfg->i32bitRate = p_src->bitrate;
4876  }
4877 
4879  {
4881  }
4882 
4883  if (p_t408->enable_hvs_qp != p_enc->rc.enable_hvs_qp)
4884  {
4885  p_t408->enable_hvs_qp = p_enc->rc.enable_hvs_qp;
4886  }
4887 
4888  if (p_t408->hvs_qp_scale != p_enc->rc.hvs_qp_scale)
4889  {
4890  p_t408->hvs_qp_scale = p_enc->rc.hvs_qp_scale;
4891  }
4892 
4893  if (p_t408->minQpI != p_enc->rc.min_qp)
4894  {
4895  p_t408->minQpI = p_enc->rc.min_qp;
4896  }
4897 
4898  if (p_t408->minQpP != p_enc->rc.min_qp)
4899  {
4900  p_t408->minQpP = p_enc->rc.min_qp;
4901  }
4902 
4903  if (p_t408->minQpB != p_enc->rc.min_qp)
4904  {
4905  p_t408->minQpB = p_enc->rc.min_qp;
4906  }
4907 
4908  if (p_t408->maxQpI != p_enc->rc.max_qp)
4909  {
4910  p_t408->maxQpI = p_enc->rc.max_qp;
4911  }
4912 
4913  if (p_t408->maxQpP != p_enc->rc.max_qp)
4914  {
4915  p_t408->maxQpP = p_enc->rc.max_qp;
4916  }
4917 
4918  if (p_t408->maxQpB != p_enc->rc.max_qp)
4919  {
4920  p_t408->maxQpB = p_enc->rc.max_qp;
4921  }
4922  // TBD intraMinQp and intraMaxQp are not configurable in Rev A; should it
4923  // be in Rev B?
4924 
4925  if (p_t408->max_delta_qp != p_enc->rc.max_delta_qp)
4926  {
4927  p_t408->max_delta_qp = p_enc->rc.max_delta_qp;
4928  }
4929 
4930  if (p_cfg->i32vbvBufferSize != p_enc->rc.rc_init_delay)
4931  {
4932  p_cfg->i32vbvBufferSize = p_enc->rc.rc_init_delay;
4933  }
4934 
4935  if (p_enc->rc.max_frame_ratio)
4936  {
4937  p_cfg->maxFrameMode = 1;
4938  p_cfg->maxFrameArg = p_enc->rc.max_frame_ratio;
4939  }
4940  if (p_enc->rc.max_frame_size)
4941  {
4942  p_cfg->maxFrameMode = 0;
4943  p_cfg->maxFrameArg = p_enc->rc.max_frame_size;
4944  }
4945 
4946  if (p_t408->intra_period != p_enc->intra_period)
4947  {
4948  p_t408->intra_period = p_enc->intra_period;
4949  }
4950 
4951  if (p_t408->roiEnable != p_enc->roi_enable)
4952  {
4953  p_t408->roiEnable = p_enc->roi_enable;
4954  }
4955 
4956  if (p_t408->useLongTerm != p_enc->long_term_ref_enable)
4957  {
4958  p_t408->useLongTerm = p_enc->long_term_ref_enable;
4959  }
4960 
4961  if (p_t408->losslessEnable != p_enc->lossless_enable)
4962  {
4963  p_t408->losslessEnable = p_enc->lossless_enable;
4964  }
4965 
4966  if (p_t408->conf_win_top != p_enc->conf_win_top)
4967  {
4968  p_t408->conf_win_top = p_enc->conf_win_top;
4969  }
4970 
4971  if (p_t408->conf_win_bottom != p_enc->conf_win_bottom)
4972  {
4973  p_t408->conf_win_bottom = p_enc->conf_win_bottom;
4974  }
4975 
4976  if (p_t408->conf_win_left != p_enc->conf_win_left)
4977  {
4978  p_t408->conf_win_left = p_enc->conf_win_left;
4979  }
4980 
4981  if (p_t408->conf_win_right != p_enc->conf_win_right)
4982  {
4983  p_t408->conf_win_right = p_enc->conf_win_right;
4984  }
4985 
4986  if (p_t408->avcIdrPeriod != p_enc->intra_period)
4987  {
4988  p_t408->avcIdrPeriod = p_enc->intra_period;
4989  }
4990 
4991  if ((p_cfg->i32frameRateInfo != p_enc->frame_rate) && (!p_src->enable_vfr))
4992  {
4993  p_cfg->i32frameRateInfo = p_enc->frame_rate;
4994  p_t408->numUnitsInTick = 1000;
4995  if (p_src->fps_denominator != 0 &&
4996  (p_src->fps_number % p_src->fps_denominator) != 0)
4997  {
4998  p_t408->numUnitsInTick += 1;
4999  p_cfg->i32frameRateInfo += 1;
5000  }
5001  p_t408->timeScale = p_cfg->i32frameRateInfo * 1000;
5003  {
5004  p_t408->timeScale *= 2;
5005  }
5006  }
5007  else if (p_src->enable_vfr)
5008  {
5010  {
5011  p_t408->timeScale = p_ctx->ui32timing_scale * 2;
5012  }
5013  else
5014  {
5015  p_t408->timeScale = p_ctx->ui32timing_scale;
5016  }
5017  p_t408->numUnitsInTick = p_ctx->ui32num_unit_in_tick;
5018  p_cfg->i32frameRateInfo = p_enc->frame_rate;
5019  }
5020 
5021  if (p_src->disable_timing_info)
5022  {
5023  p_t408->numUnitsInTick = 0;
5024  p_t408->timeScale = 0;
5025  }
5026 
5027  if (p_t408->intra_qp != p_enc->rc.intra_qp)
5028  {
5029  p_t408->intra_qp = p_enc->rc.intra_qp;
5030  }
5031 
5032  // "repeatHeaders" value 1 (all Key frames) and value 2 (all I frames)
5033  // map to forcedHeaderEnable value 2; all other values are ignored
5034  if (p_t408->forcedHeaderEnable != p_enc->forced_header_enable &&
5037  p_t408->forcedHeaderEnable = 2;
5038 
5039  if (p_t408->decoding_refresh_type != p_enc->decoding_refresh_type)
5040  {
5042  }
5043 
5044  if (p_t408->independSliceMode != p_enc->slice_mode)
5045  p_t408->independSliceMode = p_enc->slice_mode;
5046 
5047  if (p_t408->dependSliceMode != p_enc->slice_mode)
5048  p_t408->dependSliceMode = p_enc->slice_mode;
5049 
5050  if (p_t408->independSliceModeArg != p_enc->slice_arg)
5051  p_t408->independSliceModeArg = p_enc->slice_arg;
5052 
5053  if (p_t408->dependSliceModeArg != p_enc->slice_arg)
5054  p_t408->dependSliceModeArg = p_enc->slice_arg;
5055 
5056 
5057  // Rev. B: H.264 only parameters.
5058  if (p_t408->enable_transform_8x8 != p_enc->enable_transform_8x8)
5059  {
5060  p_t408->enable_transform_8x8 = p_enc->enable_transform_8x8;
5061  }
5062 
5063  if (p_t408->avc_slice_mode != p_enc->avc_slice_mode)
5064  {
5065  p_t408->avc_slice_mode = p_enc->avc_slice_mode;
5066  }
5067 
5068  if (p_t408->avc_slice_arg != p_enc->avc_slice_arg)
5069  {
5070  p_t408->avc_slice_arg = p_enc->avc_slice_arg;
5071  }
5072 
5073  if (p_t408->entropy_coding_mode != p_enc->entropy_coding_mode)
5074  {
5075  p_t408->entropy_coding_mode = p_enc->entropy_coding_mode;
5076  }
5077 
5078  // Rev. B: shared between HEVC and H.264
5079  if (p_t408->intra_mb_refresh_mode != p_enc->intra_mb_refresh_mode)
5080  {
5081  p_t408->intraRefreshMode = p_t408->intra_mb_refresh_mode =
5082  p_enc->intra_mb_refresh_mode;
5083  }
5084 
5085  if (p_t408->intra_mb_refresh_arg != p_enc->intra_mb_refresh_arg)
5086  {
5087  p_t408->intraRefreshArg = p_t408->intra_mb_refresh_arg =
5088  p_enc->intra_mb_refresh_arg;
5089  }
5090 
5091  // TBD Rev. B: could be shared for HEVC and H.264
5092  if (p_t408->enable_mb_level_rc != p_enc->rc.enable_mb_level_rc)
5093  {
5094  p_t408->enable_mb_level_rc = p_enc->rc.enable_mb_level_rc;
5095  }
5096 
5097  // profile setting: if user specified profile
5098  if (0 != p_enc->profile)
5099  {
5100  p_t408->profile = p_enc->profile;
5101  }
5102 
5103  if (p_t408->level != p_enc->level_idc)
5104  {
5105  p_t408->level = p_enc->level_idc;
5106  }
5107 
5108  // main, extended or baseline profile of 8 bit H.264 requires the following:
5109  // main: profile = 2 transform8x8Enable = 0
5110  // extended: profile = 3 entropyCodingMode = 0, transform8x8Enable = 0
5111  // baseline: profile = 1 entropyCodingMode = 0, transform8x8Enable = 0 and
5112  // gop with no B frames (gopPresetIdx=1, 2, 6, or 0
5113  // (custom with no B frames)
5114  if (STD_AVC == p_cfg->ui8bitstreamFormat && 8 == p_ctx->src_bit_depth)
5115  {
5116  if (2 == p_t408->profile)
5117  {
5118  p_t408->enable_transform_8x8 = 0;
5119  ni_log(NI_LOG_TRACE, "enable_transform_8x8 set to 0 for profile 2 (main)\n");
5120  }
5121  else if (3 == p_t408->profile || 1 == p_t408->profile)
5122  {
5123  p_t408->entropy_coding_mode = p_t408->enable_transform_8x8 = 0;
5124  ni_log(NI_LOG_TRACE, "entropy_coding_mode and enable_transform_8x8 set to 0 "
5125  "for profile 3 (extended) or 1 (baseline)\n");
5126  }
5127  }
5128 
5129  if (GOP_PRESET_IDX_CUSTOM == p_t408->gop_preset_index)
5130  {
5132  for (i = 0; i < p_t408->custom_gop_params.custom_gop_size; i++)
5133  {
5136  p_t408->custom_gop_params.pic_param[i].pic_qp = p_enc->custom_gop_params.pic_param[i].pic_qp + p_t408->intra_qp;
5141  }
5142  }
5143 
5144  p_ctx->key_frame_type = p_t408->decoding_refresh_type; //Store to use when force key p_frame
5145 
5146  // forceFrameType=1 requires intraPeriod=0 and avcIdrPeriod=0 and gopPresetIdx=8
5147  if (1 == p_src->force_frame_type)
5148  {
5149  p_t408->intra_period = 0;
5150  p_t408->avcIdrPeriod = 0;
5151  p_t408->gop_preset_index = 8;
5152  p_ctx->force_frame_type = 1;
5153  }
5154 
5155  if (p_cfg->hdrEnableVUI != p_src->hdrEnableVUI)
5156  {
5157  p_cfg->hdrEnableVUI = p_src->hdrEnableVUI;
5158  }
5159 
5160  // check auto_dl_handle and hwframes to determine if enable hw yuvbypass here.
5161  // if the encoder device is different from decoder/uploader, disable yuvbypass.
5162  // if default config value is different from setting value, update it.
5163  if (p_cfg->ui8hwframes != p_src->hwframes)
5164  {
5165  if (p_src->hwframes && p_ctx->auto_dl_handle == NI_INVALID_DEVICE_HANDLE)
5166  {
5167  p_cfg->ui8hwframes = p_src->hwframes;
5168  }
5169  else
5170  {
5171  p_cfg->ui8hwframes = 0;
5172  }
5173  }
5174 
5175  if (p_cfg->ui8explicitRefListEnable != p_src->enable_explicit_rpl)
5176  {
5178  }
5179 
5180  if (p_cfg->ui8EnableAUD != p_src->enable_aud)
5181  {
5182  p_cfg->ui8EnableAUD = p_src->enable_aud;
5183  }
5184 
5186  {
5188  }
5189 
5190  // set VUI info
5191  p_cfg->ui32VuiDataSizeBits = p_src->ui32VuiDataSizeBits;
5193  memcpy(p_cfg->ui8VuiRbsp, p_src->ui8VuiRbsp, NI_LOGAN_MAX_VUI_SIZE);
5194  if (!p_src->disable_timing_info)
5195  {
5196  if (p_src->pos_num_units_in_tick > p_src->ui32VuiDataSizeBits ||
5197  p_src->pos_time_scale > p_src->ui32VuiDataSizeBits)
5198  {
5199  ni_log(NI_LOG_ERROR, "ERROR: %s() VUI filling error\n", __FUNCTION__);
5200  return;
5201  }
5202  else
5203  {
5204  if (!p_src->enable_vui_info_passthru)
5205  {
5208  }
5209  }
5210  }
5211 
5212  // CRF mode forces the following setting:
5213  if (p_src->crf >= 0)
5214  {
5215  p_cfg->ui8crf = 1;
5216  p_t408->intra_qp = (int32_t)p_src->crf;
5217  p_cfg->ui8CrfQpFraction = (int32_t)((p_src->crf - p_t408->intra_qp) * 100);
5218  p_cfg->ui8CrfIpRatioInt = (int32_t)p_src->crfIpRatio;
5219  p_cfg->ui8CrfIpRatioFraction = (int32_t)((p_src->crfIpRatio - p_cfg->ui8CrfIpRatioInt) * 100);
5220  p_cfg->ui8CrfPbRatioInt = (int32_t)p_src->crfPbRatio;
5221  p_cfg->ui8CrfPbRatioFraction = (int32_t)((p_src->crfPbRatio - p_cfg->ui8CrfPbRatioInt) * 100);
5222  #if 0
5223  p_cfg->ui8rcEnable = 0;
5224  p_t408->intra_qp = p_src->crf;
5225  p_t408->enable_hvs_qp = 1;
5226  p_t408->hvs_qp_scale = 2;
5227  p_t408->max_delta_qp = 51;
5228  ni_log(NI_LOG_TRACE, "crf=%d forces the setting of: rcEnable=0, intraQP=%d,"
5229  " hvsQPEnable=1, hvsQPScale=2, maxDeltaQP=51.\n",
5230  p_src->crf, p_t408->intra_qp);
5231  #endif
5232  }
5233  else
5234  {
5235  p_cfg->ui8crf = 0;
5236  p_cfg->ui8CrfQpFraction = 0;
5237  p_cfg->ui8CrfIpRatioInt = 0;
5238  p_cfg->ui8CrfIpRatioFraction = 0;
5239  p_cfg->ui8CrfPbRatioInt = 0;
5240  p_cfg->ui8CrfPbRatioFraction = 0;
5241  }
5242 
5243  // CBR mode
5244  if ((p_cfg->ui32fillerEnable != p_src->cbr) && (p_cfg->ui8crf == 0))
5245  {
5246  p_cfg->ui32fillerEnable = p_src->cbr;
5247  }
5248 
5249  // GOP flush
5250  if (p_cfg->ui32flushGop != p_src->ui32flushGop)
5251  {
5252  p_cfg->ui32flushGop = p_src->ui32flushGop;
5253  }
5254 
5255  // cbr qp offset control
5256  if (p_t408->chromaCbQpOffset != p_src->chromaQpOffset || p_t408->chromaCrQpOffset != p_src->chromaQpOffset) {
5257  p_t408->chromaCbQpOffset = p_src->chromaQpOffset;
5258  p_t408->chromaCrQpOffset = p_src->chromaQpOffset;
5259  }
5260 
5261  ni_log(NI_LOG_DEBUG, "lowDelay=%d\n", p_src->low_delay_mode);
5262  ni_log(NI_LOG_DEBUG, "strictTimeout=%d\n", p_src->strict_timeout_mode);
5263  ni_log(NI_LOG_DEBUG, "crf=%lf\n", p_src->crf);
5264  ni_log(NI_LOG_DEBUG, "cbr=%u\n", p_src->cbr);
5265  ni_log(NI_LOG_DEBUG, "ui32flushGop=%u\n", p_src->ui32flushGop);
5266  ni_log(NI_LOG_DEBUG, "ui8bitstreamFormat=%d\n", p_cfg->ui8bitstreamFormat);
5267  ni_log(NI_LOG_DEBUG, "i32picWidth=%d\n", p_cfg->i32picWidth);
5268  ni_log(NI_LOG_DEBUG, "i32picHeight=%d\n", p_cfg->i32picHeight);
5269  ni_log(NI_LOG_DEBUG, "i32meBlkMode=%d\n", p_cfg->i32meBlkMode);
5270  ni_log(NI_LOG_DEBUG, "ui8sliceMode=%d\n", p_cfg->ui8sliceMode);
5271  ni_log(NI_LOG_DEBUG, "i32frameRateInfo=%d\n", p_cfg->i32frameRateInfo);
5272  ni_log(NI_LOG_DEBUG, "i32vbvBufferSize=%d\n", p_cfg->i32vbvBufferSize);
5273  ni_log(NI_LOG_DEBUG, "i32userQpMax=%d\n", p_cfg->i32userQpMax);
5274 
5275  ni_log(NI_LOG_DEBUG, "i32maxIntraSize=%d\n", p_cfg->i32maxIntraSize);
5276  ni_log(NI_LOG_DEBUG, "i32userMaxDeltaQp=%d\n", p_cfg->i32userMaxDeltaQp);
5277  ni_log(NI_LOG_DEBUG, "i32userMinDeltaQp=%d\n", p_cfg->i32userMinDeltaQp);
5278  ni_log(NI_LOG_DEBUG, "i32userQpMin=%d\n", p_cfg->i32userQpMin);
5279  ni_log(NI_LOG_DEBUG, "i32bitRate=%d\n", p_cfg->i32bitRate);
5280  ni_log(NI_LOG_DEBUG, "i32bitRateBL=%d\n", p_cfg->i32bitRateBL);
5281  ni_log(NI_LOG_DEBUG, "ui8rcEnable=%d\n", p_cfg->ui8rcEnable);
5282  ni_log(NI_LOG_DEBUG, "i32srcBitDepth=%d\n", p_cfg->i32srcBitDepth);
5283  ni_log(NI_LOG_DEBUG, "ui8enablePTS=%d\n", p_cfg->ui8enablePTS);
5284  ni_log(NI_LOG_DEBUG, "ui8lowLatencyMode=%d\n", p_cfg->ui8lowLatencyMode);
5285  ni_log(NI_LOG_DEBUG, "ui32sourceEndian=%d\n", p_cfg->ui32sourceEndian);
5286  ni_log(NI_LOG_DEBUG, "hdrEnableVUI=%u\n", p_cfg->hdrEnableVUI);
5287  ni_log(NI_LOG_DEBUG, "ui32minIntraRefreshCycle=%u\n",
5288  p_cfg->ui32minIntraRefreshCycle);
5289  ni_log(NI_LOG_DEBUG, "ui32fillerEnable=%u\n", p_cfg->ui32fillerEnable);
5290  ni_log(NI_LOG_DEBUG, "ui8crf=%u\n", p_cfg->ui8crf);
5291  ni_log(NI_LOG_DEBUG, "ui8CrfQpFraction=%u\n", p_cfg->ui8CrfQpFraction);
5292  ni_log(NI_LOG_DEBUG, "ui8CrfIpRatioInt=%u\n", p_cfg->ui8CrfIpRatioInt);
5293  ni_log(NI_LOG_DEBUG, "ui8CrfIpRatioFraction=%u\n", p_cfg->ui8CrfIpRatioFraction);
5294  ni_log(NI_LOG_DEBUG, "ui8CrfPbRatioInt=%u\n", p_cfg->ui8CrfPbRatioInt);
5295  ni_log(NI_LOG_DEBUG, "ui8CrfPbRatioFraction=%u\n", p_cfg->ui8CrfPbRatioFraction);
5296  ni_log(NI_LOG_DEBUG, "ui8hwframes=%u\n", p_cfg->ui8hwframes);
5297  ni_log(NI_LOG_DEBUG, "ui8explicitRefListEnable=%u\n", p_cfg->ui8explicitRefListEnable);
5298 
5299  ni_log(NI_LOG_DEBUG, "** ni_logan_t408_config_t: \n");
5300  ni_log(NI_LOG_DEBUG, "profile=%d\n", p_t408->profile);
5301  ni_log(NI_LOG_DEBUG, "level=%d\n", p_t408->level);
5302  ni_log(NI_LOG_DEBUG, "tier=%d\n", p_t408->tier);
5303 
5304  ni_log(NI_LOG_DEBUG, "internalBitDepth=%d\n", p_t408->internalBitDepth);
5305  ni_log(NI_LOG_DEBUG, "losslessEnable=%d\n", p_t408->losslessEnable);
5306  ni_log(NI_LOG_DEBUG, "constIntraPredFlag=%d\n", p_t408->constIntraPredFlag);
5307 
5308  ni_log(NI_LOG_DEBUG, "decoding_refresh_type=%d\n", p_t408->decoding_refresh_type);
5309  ni_log(NI_LOG_DEBUG, "intra_qp=%d\n", p_t408->intra_qp);
5310  ni_log(NI_LOG_DEBUG, "intra_period=%d\n", p_t408->intra_period);
5311  ni_log(NI_LOG_DEBUG, "roi_enable=%d\n", p_t408->roiEnable);
5312  ni_log(NI_LOG_DEBUG, "useLongTerm=%u\n", p_t408->useLongTerm);
5313 
5314  ni_log(NI_LOG_DEBUG, "conf_win_top=%d\n", p_t408->conf_win_top);
5315  ni_log(NI_LOG_DEBUG, "conf_win_bottom=%d\n", p_t408->conf_win_bottom);
5316  ni_log(NI_LOG_DEBUG, "conf_win_left=%d\n", p_t408->conf_win_left);
5317  ni_log(NI_LOG_DEBUG, "conf_win_right=%d\n", p_t408->conf_win_right);
5318 
5319  ni_log(NI_LOG_DEBUG, "independSliceMode=%d\n", p_t408->independSliceMode);
5320  ni_log(NI_LOG_DEBUG, "independSliceModeArg=%d\n", p_t408->independSliceModeArg);
5321 
5322  ni_log(NI_LOG_DEBUG, "dependSliceMode=%d\n", p_t408->dependSliceMode);
5323  ni_log(NI_LOG_DEBUG, "dependSliceModeArg=%d\n", p_t408->dependSliceModeArg);
5324 
5325  ni_log(NI_LOG_DEBUG, "intraRefreshMode=%d\n", p_t408->intraRefreshMode);
5326 
5327  ni_log(NI_LOG_DEBUG, "intraRefreshArg=%d\n", p_t408->intraRefreshArg);
5328 
5329  ni_log(NI_LOG_DEBUG, "use_recommend_enc_params=%d\n", p_t408->use_recommend_enc_params);
5330  ni_log(NI_LOG_DEBUG, "scalingListEnable=%d\n", p_t408->scalingListEnable);
5331 
5332  ni_log(NI_LOG_DEBUG, "cu_size_mode=%d\n", p_t408->cu_size_mode);
5333  ni_log(NI_LOG_DEBUG, "tmvpEnable=%d\n", p_t408->tmvpEnable);
5334  ni_log(NI_LOG_DEBUG, "wppEnable=%d\n", p_t408->wppEnable);
5335  ni_log(NI_LOG_DEBUG, "max_num_merge=%d\n", p_t408->max_num_merge);
5336  ni_log(NI_LOG_DEBUG, "disableDeblk=%d\n", p_t408->disableDeblk);
5337  ni_log(NI_LOG_DEBUG, "lfCrossSliceBoundaryEnable=%d\n", p_t408->lfCrossSliceBoundaryEnable);
5338  ni_log(NI_LOG_DEBUG, "betaOffsetDiv2=%d\n", p_t408->betaOffsetDiv2);
5339  ni_log(NI_LOG_DEBUG, "tcOffsetDiv2=%d\n", p_t408->tcOffsetDiv2);
5340  ni_log(NI_LOG_DEBUG, "skipIntraTrans=%d\n", p_t408->skipIntraTrans);
5341  ni_log(NI_LOG_DEBUG, "saoEnable=%d\n", p_t408->saoEnable);
5342  ni_log(NI_LOG_DEBUG, "intraNxNEnable=%d\n", p_t408->intraNxNEnable);
5343  ni_log(NI_LOG_DEBUG, "bitAllocMode=%d\n", p_t408->bitAllocMode);
5344 
5345  ni_log(NI_LOG_DEBUG, "enable_cu_level_rate_control=%d\n", p_t408->enable_cu_level_rate_control);
5346 
5347  ni_log(NI_LOG_DEBUG, "enable_hvs_qp=%d\n", p_t408->enable_hvs_qp);
5348 
5349  ni_log(NI_LOG_DEBUG, "hvs_qp_scale=%d\n", p_t408->hvs_qp_scale);
5350 
5351  ni_log(NI_LOG_DEBUG, "max_delta_qp=%d\n", p_t408->max_delta_qp);
5352 
5353  ni_log(NI_LOG_DEBUG, "maxFrameMode=%d\n", p_cfg->maxFrameMode);
5354  ni_log(NI_LOG_DEBUG, "maxFrameArg=%d\n", p_cfg->maxFrameArg);
5355 
5356  // CUSTOM_GOP
5357  ni_log(NI_LOG_DEBUG, "gop_preset_index=%d\n", p_t408->gop_preset_index);
5358  if (p_t408->gop_preset_index == GOP_PRESET_IDX_CUSTOM)
5359  {
5360  ni_log(NI_LOG_DEBUG, "custom_gop_params.custom_gop_size=%d\n", p_t408->custom_gop_params.custom_gop_size);
5361  for (i = 0; i < 8; i++)
5362  //for (i = 0; i < p_t408->custom_gop_params.custom_gop_size; i++)
5363  {
5364  ni_log(NI_LOG_DEBUG, "custom_gop_params.pic_param[%d].pic_type=%d\n",
5365  i, p_t408->custom_gop_params.pic_param[i].pic_type);
5366  ni_log(NI_LOG_DEBUG, "custom_gop_params.pic_param[%d].poc_offset=%d\n",
5367  i, p_t408->custom_gop_params.pic_param[i].poc_offset);
5368  ni_log(NI_LOG_DEBUG, "custom_gop_params.pic_param[%d].pic_qp=%d\n",
5369  i, p_t408->custom_gop_params.pic_param[i].pic_qp);
5370  ni_log(NI_LOG_DEBUG, "custom_gop_params.pic_param[%d].num_ref_pic_L0=%d\n",
5372  ni_log(NI_LOG_DEBUG, "custom_gop_params.pic_param[%d].ref_poc_L0=%d\n",
5373  i, p_t408->custom_gop_params.pic_param[i].ref_poc_L0);
5374  ni_log(NI_LOG_DEBUG, "custom_gop_params.pic_param[%d].ref_poc_L1=%d\n",
5375  i, p_t408->custom_gop_params.pic_param[i].ref_poc_L1);
5376  ni_log(NI_LOG_DEBUG, "custom_gop_params.pic_param[%d].temporal_id=%d\n",
5377  i, p_t408->custom_gop_params.pic_param[i].temporal_id);
5378  }
5379  }
5380 
5381  ni_log(NI_LOG_DEBUG, "roiEnable=%d\n", p_t408->roiEnable);
5382 
5383  ni_log(NI_LOG_DEBUG, "numUnitsInTick=%d\n", p_t408->numUnitsInTick);
5384  ni_log(NI_LOG_DEBUG, "timeScale=%d\n", p_t408->timeScale);
5385  ni_log(NI_LOG_DEBUG, "numTicksPocDiffOne=%d\n", p_t408->numTicksPocDiffOne);
5386 
5387  ni_log(NI_LOG_DEBUG, "chromaCbQpOffset=%d\n", p_t408->chromaCbQpOffset);
5388  ni_log(NI_LOG_DEBUG, "chromaCrQpOffset=%d\n", p_t408->chromaCrQpOffset);
5389 
5390  ni_log(NI_LOG_DEBUG, "initialRcQp=%d\n", p_t408->initialRcQp);
5391 
5392  ni_log(NI_LOG_DEBUG, "nrYEnable=%d\n", p_t408->nrYEnable);
5393  ni_log(NI_LOG_DEBUG, "nrCbEnable=%d\n", p_t408->nrCbEnable);
5394  ni_log(NI_LOG_DEBUG, "nrCrEnable=%d\n", p_t408->nrCrEnable);
5395 
5396  // ENC_NR_WEIGHT
5397  ni_log(NI_LOG_DEBUG, "nrIntraWeightY=%d\n", p_t408->nrIntraWeightY);
5398  ni_log(NI_LOG_DEBUG, "nrIntraWeightCb=%d\n", p_t408->nrIntraWeightCb);
5399  ni_log(NI_LOG_DEBUG, "nrIntraWeightCr=%d\n", p_t408->nrIntraWeightCr);
5400  ni_log(NI_LOG_DEBUG, "nrInterWeightY=%d\n", p_t408->nrInterWeightY);
5401  ni_log(NI_LOG_DEBUG, "nrInterWeightCb=%d\n", p_t408->nrInterWeightCb);
5402  ni_log(NI_LOG_DEBUG, "nrInterWeightCr=%d\n", p_t408->nrInterWeightCr);
5403 
5404  ni_log(NI_LOG_DEBUG, "nrNoiseEstEnable=%d\n", p_t408->nrNoiseEstEnable);
5405  ni_log(NI_LOG_DEBUG, "nrNoiseSigmaY=%d\n", p_t408->nrNoiseSigmaY);
5406  ni_log(NI_LOG_DEBUG, "nrNoiseSigmaCb=%d\n", p_t408->nrNoiseSigmaCb);
5407  ni_log(NI_LOG_DEBUG, "nrNoiseSigmaCr=%d\n", p_t408->nrNoiseSigmaCr);
5408 
5409  ni_log(NI_LOG_DEBUG, "useLongTerm=%d\n", p_t408->useLongTerm);
5410 
5411  // newly added for T408_520
5412  ni_log(NI_LOG_DEBUG, "monochromeEnable=%d\n", p_t408->monochromeEnable);
5413  ni_log(NI_LOG_DEBUG, "strongIntraSmoothEnable=%d\n", p_t408->strongIntraSmoothEnable);
5414 
5415  ni_log(NI_LOG_DEBUG, "weightPredEnable=%d\n", p_t408->weightPredEnable);
5416  ni_log(NI_LOG_DEBUG, "bgDetectEnable=%d\n", p_t408->bgDetectEnable);
5417  ni_log(NI_LOG_DEBUG, "bgThrDiff=%d\n", p_t408->bgThrDiff);
5418  ni_log(NI_LOG_DEBUG, "bgThrMeanDiff=%d\n", p_t408->bgThrMeanDiff);
5419  ni_log(NI_LOG_DEBUG, "bgLambdaQp=%d\n", p_t408->bgLambdaQp);
5420  ni_log(NI_LOG_DEBUG, "bgDeltaQp=%d\n", p_t408->bgDeltaQp);
5421 
5422  ni_log(NI_LOG_DEBUG, "customLambdaEnable=%d\n", p_t408->customLambdaEnable);
5423  ni_log(NI_LOG_DEBUG, "customMDEnable=%d\n", p_t408->customMDEnable);
5424  ni_log(NI_LOG_DEBUG, "pu04DeltaRate=%d\n", p_t408->pu04DeltaRate);
5425  ni_log(NI_LOG_DEBUG, "pu08DeltaRate=%d\n", p_t408->pu08DeltaRate);
5426  ni_log(NI_LOG_DEBUG, "pu16DeltaRate=%d\n", p_t408->pu16DeltaRate);
5427  ni_log(NI_LOG_DEBUG, "pu32DeltaRate=%d\n", p_t408->pu32DeltaRate);
5428  ni_log(NI_LOG_DEBUG, "pu04IntraPlanarDeltaRate=%d\n", p_t408->pu04IntraPlanarDeltaRate);
5429  ni_log(NI_LOG_DEBUG, "pu04IntraDcDeltaRate=%d\n", p_t408->pu04IntraDcDeltaRate);
5430  ni_log(NI_LOG_DEBUG, "pu04IntraAngleDeltaRate=%d\n", p_t408->pu04IntraAngleDeltaRate);
5431  ni_log(NI_LOG_DEBUG, "pu08IntraPlanarDeltaRate=%d\n", p_t408->pu08IntraPlanarDeltaRate);
5432  ni_log(NI_LOG_DEBUG, "pu08IntraDcDeltaRate=%d\n", p_t408->pu08IntraDcDeltaRate);
5433  ni_log(NI_LOG_DEBUG, "pu08IntraAngleDeltaRate=%d\n", p_t408->pu08IntraAngleDeltaRate);
5434  ni_log(NI_LOG_DEBUG, "pu16IntraPlanarDeltaRate=%d\n", p_t408->pu16IntraPlanarDeltaRate);
5435  ni_log(NI_LOG_DEBUG, "pu16IntraDcDeltaRate=%d\n", p_t408->pu16IntraDcDeltaRate);
5436  ni_log(NI_LOG_DEBUG, "pu16IntraAngleDeltaRate=%d\n", p_t408->pu16IntraAngleDeltaRate);
5437  ni_log(NI_LOG_DEBUG, "pu32IntraPlanarDeltaRate=%d\n", p_t408->pu32IntraPlanarDeltaRate);
5438  ni_log(NI_LOG_DEBUG, "pu32IntraDcDeltaRate=%d\n", p_t408->pu32IntraDcDeltaRate);
5439  ni_log(NI_LOG_DEBUG, "pu32IntraAngleDeltaRate=%d\n", p_t408->pu32IntraAngleDeltaRate);
5440  ni_log(NI_LOG_DEBUG, "cu08IntraDeltaRate=%d\n", p_t408->cu08IntraDeltaRate);
5441  ni_log(NI_LOG_DEBUG, "cu08InterDeltaRate=%d\n", p_t408->cu08InterDeltaRate);
5442  ni_log(NI_LOG_DEBUG, "cu08MergeDeltaRate=%d\n", p_t408->cu08MergeDeltaRate);
5443  ni_log(NI_LOG_DEBUG, "cu16IntraDeltaRate=%d\n", p_t408->cu16IntraDeltaRate);
5444  ni_log(NI_LOG_DEBUG, "cu16InterDeltaRate=%d\n", p_t408->cu16InterDeltaRate);
5445  ni_log(NI_LOG_DEBUG, "cu16MergeDeltaRate=%d\n", p_t408->cu16MergeDeltaRate);
5446  ni_log(NI_LOG_DEBUG, "cu32IntraDeltaRate=%d\n", p_t408->cu32IntraDeltaRate);
5447  ni_log(NI_LOG_DEBUG, "cu32InterDeltaRate=%d\n", p_t408->cu32InterDeltaRate);
5448  ni_log(NI_LOG_DEBUG, "cu32MergeDeltaRate=%d\n", p_t408->cu32MergeDeltaRate);
5449  ni_log(NI_LOG_DEBUG, "coefClearDisable=%d\n", p_t408->coefClearDisable);
5450  ni_log(NI_LOG_DEBUG, "minQpI=%d\n", p_t408->minQpI);
5451  ni_log(NI_LOG_DEBUG, "maxQpI=%d\n", p_t408->maxQpI);
5452  ni_log(NI_LOG_DEBUG, "minQpP=%d\n", p_t408->minQpP);
5453  ni_log(NI_LOG_DEBUG, "maxQpP=%d\n", p_t408->maxQpP);
5454  ni_log(NI_LOG_DEBUG, "minQpB=%d\n", p_t408->minQpB);
5455  ni_log(NI_LOG_DEBUG, "maxQpB=%d\n", p_t408->maxQpB);
5456 
5457  // for H.264 on T408
5458  ni_log(NI_LOG_DEBUG, "avcIdrPeriod=%d\n", p_t408->avcIdrPeriod);
5459  ni_log(NI_LOG_DEBUG, "rdoSkip=%d\n", p_t408->rdoSkip);
5460  ni_log(NI_LOG_DEBUG, "lambdaScalingEnable=%d\n", p_t408->lambdaScalingEnable);
5461  ni_log(NI_LOG_DEBUG, "enable_transform_8x8=%d\n", p_t408->enable_transform_8x8);
5462  ni_log(NI_LOG_DEBUG, "avc_slice_mode=%d\n", p_t408->avc_slice_mode);
5463  ni_log(NI_LOG_DEBUG, "avc_slice_arg=%d\n", p_t408->avc_slice_arg);
5464  ni_log(NI_LOG_DEBUG, "intra_mb_refresh_mode=%d\n", p_t408->intra_mb_refresh_mode);
5465  ni_log(NI_LOG_DEBUG, "intra_mb_refresh_arg=%d\n", p_t408->intra_mb_refresh_arg);
5466  ni_log(NI_LOG_DEBUG, "enable_mb_level_rc=%d\n", p_t408->enable_mb_level_rc);
5467  ni_log(NI_LOG_DEBUG, "entropy_coding_mode=%d\n", p_t408->entropy_coding_mode);
5468  ni_log(NI_LOG_DEBUG, "forcedHeaderEnable=%d\n", p_t408->forcedHeaderEnable);
5469 }
5470 
5471 /*!******************************************************************************
5472  * \brief Setup and initialize all xcoder configuration to default (Rev. B)
5473  *
5474  * \param
5475  *
5476  * \return
5477  ******************************************************************************/
5479 {
5480  uint8_t i = 0;
5481 
5482  if (!p_ctx || !p_config)
5483  {
5484  ni_log(NI_LOG_TRACE, "ERROR: %s() Null pointer parameters passed\n", __FUNCTION__);
5485  return;
5486  }
5487 
5488  memset(p_config, 0, sizeof(ni_logan_encoder_config_t));
5489 
5490  // fill in common attributes values
5491  p_config->i32picWidth = 720;
5492  p_config->i32picHeight = 480;
5493  p_config->i32meBlkMode = 0; // (AVC ONLY) syed: 0 means use all possible block partitions
5494  p_config->ui8sliceMode = 0; // syed: 0 means 1 slice per picture
5495  p_config->i32frameRateInfo = 30;
5496  p_config->i32vbvBufferSize = 3000; //0; // syed: parameter is ignored if rate control is off,
5497  //if rate control is on, 0 means do not check vbv constraints
5498  p_config->i32userQpMax = 51; // syed todo: this should also be h264-only parameter
5499 
5500  // AVC only
5502  {
5503  p_config->i32maxIntraSize = 8000000; // syed: how big an intra p_frame can get?
5504  p_config->i32userMaxDeltaQp = 51;
5505  p_config->i32userMinDeltaQp = 51;
5506  p_config->i32userQpMin = 8;
5507  }
5508 
5509  p_config->i32bitRate = 0; //1000000; // syed todo: check if this is applicable (could be coda9 only)
5510  p_config->i32bitRateBL = 0; // syed todo: no documentation on this parameter in documents
5511  p_config->ui8rcEnable = 0;
5512  p_config->i32srcBitDepth = p_ctx->src_bit_depth;
5513  p_config->ui8enablePTS = 0;
5514  p_config->ui8lowLatencyMode = 0;
5515 
5516  // profiles for H.264: 1 = baseline, 2 = main, 3 = extended, 4 = high
5517  // 5 = high10 (default 8 bit: 4, 10 bit: 5)
5518  // profiles for HEVC: 1 = main, 2 = main10 (default 8 bit: 1, 10 bit: 2)
5519 
5520  // bitstream type: H.264 or HEVC
5522  {
5523  p_config->ui8bitstreamFormat = STD_AVC;
5524 
5525  p_config->niParamT408.profile = 4;
5526  if (10 == p_ctx->src_bit_depth)
5527  {
5528  p_config->niParamT408.profile = 5;
5529  }
5530  }
5531  else
5532  {
5534 
5535  p_config->ui8bitstreamFormat = STD_HEVC;
5536 
5537  p_config->niParamT408.profile = 1;
5538  if (10 == p_ctx->src_bit_depth)
5539  {
5540  p_config->niParamT408.profile = 2;
5541  }
5542  }
5543 
5544  p_config->ui32fillerEnable = 0;
5545  p_config->hdrEnableVUI = 0;
5546  p_config->ui8EnableAUD = 0;
5547  p_config->ui32flushGop = 0;
5548  p_config->ui32minIntraRefreshCycle = 0;
5549  p_config->ui32sourceEndian = p_ctx->src_endian;
5550  p_config->ui8explicitRefListEnable = 0;
5551 
5552  p_config->niParamT408.level = 0; // TBD
5553  p_config->niParamT408.tier = 0; // syed 0 means main tier
5554 
5555  p_config->niParamT408.internalBitDepth = p_ctx->src_bit_depth;
5556  p_config->niParamT408.losslessEnable = 0;
5557  p_config->niParamT408.constIntraPredFlag = 0;
5558 
5560 
5561  p_config->niParamT408.decoding_refresh_type = 2;
5563  // avcIdrPeriod (H.264 on T408), NOT shared with intra_period
5564  p_config->niParamT408.intra_period = 92;
5565  p_config->niParamT408.avcIdrPeriod = 92;
5566 
5567  p_config->niParamT408.conf_win_top = 0;
5568  p_config->niParamT408.conf_win_bottom = 0;
5569  p_config->niParamT408.conf_win_left = 0;
5570  p_config->niParamT408.conf_win_right = 0;
5571 
5572  p_config->niParamT408.independSliceMode = 0;
5573  p_config->niParamT408.independSliceModeArg = 0;
5574  p_config->niParamT408.dependSliceMode = 0;
5575  p_config->niParamT408.dependSliceModeArg = 0;
5576  p_config->niParamT408.intraRefreshMode = 0;
5577  p_config->niParamT408.intraRefreshArg = 0;
5578 
5579  p_config->niParamT408.use_recommend_enc_params = 0; //1;
5580  p_config->niParamT408.scalingListEnable = 0;
5581 
5582  //It is hardcode the default value is 7 which enable 8x8, 16x16, 32x32 coding unit size
5584 
5585  p_config->niParamT408.tmvpEnable = 1;
5586  p_config->niParamT408.wppEnable = 0;
5587  p_config->niParamT408.max_num_merge = 2; // It is hardcode the max merge candidates default 2
5588  p_config->niParamT408.disableDeblk = 0;
5590  p_config->niParamT408.betaOffsetDiv2 = 0;
5591  p_config->niParamT408.tcOffsetDiv2 = 0;
5592  p_config->niParamT408.skipIntraTrans = 1; // syed todo: do more investigation
5593  p_config->niParamT408.saoEnable = 1;
5594  p_config->niParamT408.intraNxNEnable = 1;
5595 
5596  p_config->niParamT408.bitAllocMode = 0;
5597 
5598  for (i = 0; i < NI_LOGAN_MAX_GOP_NUM; i++)
5599  {
5600  p_config->niParamT408.fixedBitRatio[i] = 1;
5601  }
5602 
5603  p_config->niParamT408.enable_cu_level_rate_control = 1; //0;
5604 
5605  p_config->niParamT408.enable_hvs_qp = 0;
5606  p_config->niParamT408.hvs_qp_scale = 2; // syed todo: do more investigation
5607 
5609 
5610  p_config->maxFrameMode = 0;
5611  p_config->maxFrameArg = 0;
5612 
5613  // CUSTOM_GOP
5615  for (i = 0; i < p_config->niParamT408.custom_gop_params.custom_gop_size; i++)
5616  {
5619  p_config->niParamT408.custom_gop_params.pic_param[i].pic_qp = 0;
5620  // ToDo: value of added num_ref_pic_L0 ???
5625  }
5626 
5627  p_config->niParamT408.roiEnable = 0;
5628 
5629  p_config->niParamT408.numUnitsInTick = 1000;
5630  p_config->niParamT408.timeScale = p_config->i32frameRateInfo * 1000;
5632  {
5633  p_config->niParamT408.timeScale *= 2;
5634  }
5635 
5636  p_config->niParamT408.numTicksPocDiffOne = 0; // syed todo: verify, set to zero to try to match the model's output encoding
5637 
5638  p_config->niParamT408.chromaCbQpOffset = 0;
5639  p_config->niParamT408.chromaCrQpOffset = 0;
5640 
5641  p_config->niParamT408.initialRcQp = 63; //-1;
5642 
5643  p_config->niParamT408.nrYEnable = 0;
5644  p_config->niParamT408.nrCbEnable = 0;
5645  p_config->niParamT408.nrCrEnable = 0;
5646 
5647  // ENC_NR_WEIGHT
5648  p_config->niParamT408.nrIntraWeightY = 7;
5649  p_config->niParamT408.nrIntraWeightCb = 7;
5650  p_config->niParamT408.nrIntraWeightCr = 7;
5651  p_config->niParamT408.nrInterWeightY = 4;
5652  p_config->niParamT408.nrInterWeightCb = 4;
5653  p_config->niParamT408.nrInterWeightCr = 4;
5654 
5655  p_config->niParamT408.nrNoiseEstEnable = 0;
5656  p_config->niParamT408.nrNoiseSigmaY = 0;
5657  p_config->niParamT408.nrNoiseSigmaCb = 0;
5658  p_config->niParamT408.nrNoiseSigmaCr = 0;
5659 
5660  p_config->niParamT408.useLongTerm = 0; // syed: keep disabled for now, need to experiment later
5661 
5662  // newly added for T408_520
5663  p_config->niParamT408.monochromeEnable = 0; // syed: do we expect monochrome input?
5664  p_config->niParamT408.strongIntraSmoothEnable = 1;
5665 
5666  p_config->niParamT408.weightPredEnable = 0; //1; // syed: enabling for better quality
5667  // but need to keep an eye on performance penalty
5668  p_config->niParamT408.bgDetectEnable = 0;
5669  p_config->niParamT408.bgThrDiff = 8; // syed: matching the C-model
5670  p_config->niParamT408.bgThrMeanDiff = 1; // syed: matching the C-model
5671  p_config->niParamT408.bgLambdaQp = 32; // syed: matching the C-model
5672  p_config->niParamT408.bgDeltaQp = 3; // syed: matching the C-model
5673 
5674  p_config->niParamT408.customLambdaEnable = 0;
5675  p_config->niParamT408.customMDEnable = 0;
5676  p_config->niParamT408.pu04DeltaRate = 0;
5677  p_config->niParamT408.pu08DeltaRate = 0;
5678  p_config->niParamT408.pu16DeltaRate = 0;
5679  p_config->niParamT408.pu32DeltaRate = 0;
5680  p_config->niParamT408.pu04IntraPlanarDeltaRate = 0;
5681  p_config->niParamT408.pu04IntraDcDeltaRate = 0;
5682  p_config->niParamT408.pu04IntraAngleDeltaRate = 0;
5683  p_config->niParamT408.pu08IntraPlanarDeltaRate = 0;
5684  p_config->niParamT408.pu08IntraDcDeltaRate = 0;
5685  p_config->niParamT408.pu08IntraAngleDeltaRate = 0;
5686  p_config->niParamT408.pu16IntraPlanarDeltaRate = 0;
5687  p_config->niParamT408.pu16IntraDcDeltaRate = 0;
5688  p_config->niParamT408.pu16IntraAngleDeltaRate = 0;
5689  p_config->niParamT408.pu32IntraPlanarDeltaRate = 0;
5690  p_config->niParamT408.pu32IntraDcDeltaRate = 0;
5691  p_config->niParamT408.pu32IntraAngleDeltaRate = 0;
5692  p_config->niParamT408.cu08IntraDeltaRate = 0;
5693  p_config->niParamT408.cu08InterDeltaRate = 0;
5694  p_config->niParamT408.cu08MergeDeltaRate = 0;
5695  p_config->niParamT408.cu16IntraDeltaRate = 0;
5696  p_config->niParamT408.cu16InterDeltaRate = 0;
5697  p_config->niParamT408.cu16MergeDeltaRate = 0;
5698  p_config->niParamT408.cu32IntraDeltaRate = 0;
5699  p_config->niParamT408.cu32InterDeltaRate = 0;
5700  p_config->niParamT408.cu32MergeDeltaRate = 0;
5701  p_config->niParamT408.coefClearDisable = 0;
5702  p_config->niParamT408.minQpI = 8;
5703  p_config->niParamT408.maxQpI = 51;
5704  p_config->niParamT408.minQpP = 8;
5705  p_config->niParamT408.maxQpP = 51;
5706  p_config->niParamT408.minQpB = 8;
5707  p_config->niParamT408.maxQpB = 51;
5708 
5709  // for H.264 on T408
5710  p_config->niParamT408.avcIdrPeriod = 92; // syed todo: check that 0 means encoder decides
5711  p_config->niParamT408.rdoSkip = 0;
5712  p_config->niParamT408.lambdaScalingEnable = 0;
5713  p_config->niParamT408.enable_transform_8x8 = 1;
5714  p_config->niParamT408.avc_slice_mode = 0;
5715  p_config->niParamT408.avc_slice_arg = 0;
5716  p_config->niParamT408.intra_mb_refresh_mode = 0;
5717  p_config->niParamT408.intra_mb_refresh_arg = 0;
5718  p_config->niParamT408.enable_mb_level_rc = 1;
5719  p_config->niParamT408.entropy_coding_mode = 1; // syed: 1 means CABAC, make sure profile is main or above,
5720  // can't have CABAC in baseline
5721  p_config->niParamT408.forcedHeaderEnable = 0; // first IDR frame
5722 }
5723 
5724 /*!******************************************************************************
5725  * \brief Perform validation on custom parameters (Rev. B)
5726  *
5727  * \param
5728  *
5729  * \return
5730  ******************************************************************************/
5734  char* p_param_err,
5735  uint32_t max_err_len)
5736 {
5738  int i;
5739 
5740  if ( (!p_ctx) || (!p_cfg) || (!p_src) || (!p_param_err) )
5741  {
5742  ni_log(NI_LOG_TRACE, "ERROR: %s() Null pointer parameters passed\n", __FUNCTION__);
5744  }
5745 
5746  //Zero out the error buffer
5747  memset(p_param_err, 0, max_err_len);
5748 
5749  if (0 == p_cfg->i32frameRateInfo)
5750  {
5751  strncpy(p_param_err, "Invalid frame_rate of 0 value", max_err_len);
5753  LRETURN;
5754  }
5755 
5756  if (p_cfg->i32bitRate <= p_cfg->i32frameRateInfo)
5757  {
5758  strncpy(p_param_err, "Invalid i32bitRate: smaller than or equal to frame rate", max_err_len);
5760  LRETURN;
5761  }
5762 
5763  if (p_cfg->i32bitRate > 700000000)
5764  {
5765  strncpy(p_param_err, "Invalid i32bitRate: too big", max_err_len);
5767  LRETURN;
5768  }
5769 
5770  if (p_cfg->i32bitRate < 0)
5771  {
5772  strncpy(p_param_err, "Invalid i32bitRate of 0 value", max_err_len);
5774  LRETURN;
5775  }
5776 
5778  {
5779  strncpy(p_param_err, "Invalid Picture Width: too small", max_err_len);
5781  LRETURN;
5782  }
5783 
5785  {
5786  strncpy(p_param_err, "Invalid Picture Width: too big", max_err_len);
5788  LRETURN;
5789  }
5790 
5792  {
5793  strncpy(p_param_err, "Invalid Picture Height: too small", max_err_len);
5795  LRETURN;
5796  }
5797 
5799  {
5800  strncpy(p_param_err, "Invalid Picture Height: too big", max_err_len);
5802  LRETURN;
5803  }
5804 
5805  // HRD is only applicable to H.265
5806  // Cannot disable timing_info and enable HRD at the same time
5807  if ((NI_LOGAN_CODEC_FORMAT_H265 == p_ctx->codec_format) &&
5808  p_src->disable_timing_info && p_src->hrd_enable)
5809  {
5810  strncpy(p_param_err, "Invalid cannot disable timing_info and "
5811  "enable hrd at the same time", max_err_len);
5812  param_ret = NI_LOGAN_RETCODE_INVALID_PARAM;
5813  LRETURN;
5814  }
5815 
5816  // number of MB (AVC, default) or CTU (HEVC) per row/column
5817  int32_t num_mb_or_ctu_row = (p_src->source_height + 16 - 1) / 16;
5818  int32_t num_mb_or_ctu_col = (p_src->source_width + 16 - 1) / 16;
5820  {
5821  num_mb_or_ctu_row = (p_src->source_height + 64 - 1) / 64;
5822  num_mb_or_ctu_col = (p_src->source_width + 64 - 1) / 64;
5823  }
5824 
5825  if (4 == p_cfg->niParamT408.intra_mb_refresh_mode &&
5827  {
5828  strncpy(p_param_err, "Invalid intraRefreshMode: 4 not supported for AVC",
5829  max_err_len);
5831  }
5832 
5833  if ((p_cfg->ui8crf==1) && (p_ctx->codec_format==NI_LOGAN_CODEC_FORMAT_H264))
5834  {
5835  strncpy(p_param_err, "Invalid crf not supported for AVC",
5836  max_err_len);
5838  }
5839 
5840  if (p_cfg->niParamT408.intra_mb_refresh_mode &&
5841  p_cfg->niParamT408.intra_mb_refresh_arg <= 0)
5842  {
5843  strncpy(p_param_err, "Invalid intraRefreshArg: should be greater than 0",
5844  max_err_len);
5846  }
5847  if (1 == p_cfg->niParamT408.intra_mb_refresh_mode &&
5848  p_cfg->niParamT408.intra_mb_refresh_arg > num_mb_or_ctu_row)
5849  {
5850  strncpy(p_param_err, "Invalid intraRefreshArg: should not be greater than "
5851  "number of MB/CTU of height when intraRefreshMode=1", max_err_len);
5853  }
5854  if (2 == p_cfg->niParamT408.intra_mb_refresh_mode &&
5855  p_cfg->niParamT408.intra_mb_refresh_arg > num_mb_or_ctu_col)
5856  {
5857  strncpy(p_param_err, "Invalid intraRefreshArg: should not be greater than "
5858  "number of MB/CTU of width when intraRefreshMode=2", max_err_len);
5860  }
5861  if ((3 == p_cfg->niParamT408.intra_mb_refresh_mode ||
5862  4 == p_cfg->niParamT408.intra_mb_refresh_mode) &&
5864  num_mb_or_ctu_row * num_mb_or_ctu_col))
5865  {
5866  strncpy(p_param_err, "Invalid intraRefreshArg: should not be greater than "
5867  "number of MB/CTU of frame when intraRefreshMode=3/4", max_err_len);
5869  }
5870  if (4 == p_cfg->niParamT408.intra_mb_refresh_mode &&
5871  p_cfg->niParamT408.losslessEnable)
5872  {
5873  strncpy(p_param_err, "Error: lossless coding should be disabled when "
5874  "intraRefreshMode=4", max_err_len);
5876  }
5877  if (4 == p_cfg->niParamT408.intra_mb_refresh_mode &&
5878  p_cfg->niParamT408.roiEnable)
5879  {
5880  strncpy(p_param_err, "Error: ROI should be disabled when "
5881  "intraRefreshMode=4", max_err_len);
5883  }
5884 
5886  {
5887  if (10 == p_ctx->src_bit_depth)
5888  {
5889  if (p_cfg->niParamT408.profile != 5)
5890  {
5891  strncpy(p_param_err, "Invalid profile: must be 5 (high10)",
5892  max_err_len);
5894  }
5895  }
5896  else
5897  {
5898  if (p_cfg->niParamT408.profile < 1 || p_cfg->niParamT408.profile > 5)
5899  {
5900  strncpy(p_param_err, "Invalid profile: must be 1 (baseline), 2 (main),"
5901  " 3 (extended), 4 (high), or 5 (high10)", max_err_len);
5903  }
5904 
5905  if (1 == p_cfg->niParamT408.profile &&
5906  ! (0 == p_cfg->niParamT408.gop_preset_index ||
5907  1 == p_cfg->niParamT408.gop_preset_index ||
5908  2 == p_cfg->niParamT408.gop_preset_index ||
5909  6 == p_cfg->niParamT408.gop_preset_index ||
5910  9 == p_cfg->niParamT408.gop_preset_index))
5911  {
5912  strncpy(p_param_err, "Invalid gopPresetIdx for H.264 baseline profile:"
5913  " must be 1, 2, 6, 9 or 0 (custom with no B frames)", max_err_len);
5915  }
5916 
5917  if (1 == p_cfg->niParamT408.profile &&
5919  {
5920  for (i = 0; i < p_cfg->niParamT408.custom_gop_params.custom_gop_size; i++)
5921  {
5922  if (2 == p_cfg->niParamT408.custom_gop_params.pic_param[i].pic_type)
5923  {
5924  strncpy(p_param_err, "H.264 baseline profile: custom GOP can not "
5925  "have B frames", max_err_len);
5927  }
5928  }
5929  }
5930  }
5931 
5932  if (1 == p_cfg->niParamT408.avc_slice_mode)
5933  {
5934  // validate range of avcSliceArg: 1 - number-of-MBs-in-frame
5935  int32_t numMbs = ((p_cfg->i32picWidth + 16 - 1) >> 4) *
5936  ((p_cfg->i32picHeight + 16 - 1) >> 4);
5937  if (p_cfg->niParamT408.avc_slice_arg < 1 ||
5938  p_cfg->niParamT408.avc_slice_arg > numMbs)
5939  {
5940  strncpy(p_param_err, "Invalid avcSliceArg: must be between 1 and number"
5941  " of 16x16 pixel MBs in a frame", max_err_len);
5943  }
5944  }
5945  if (1 == p_cfg->niParamT408.independSliceMode)
5946  {
5947  // validate range of sliceArg: 1 - number-of-MBs-in-frame
5948  int32_t numMbs = ((p_cfg->i32picWidth + 16 - 1) >> 4) *
5949  ((p_cfg->i32picHeight + 16 - 1) >> 4);
5950  if (p_cfg->niParamT408.independSliceModeArg < 1 ||
5951  p_cfg->niParamT408.independSliceModeArg > numMbs)
5952  {
5953  strncpy(p_param_err, "Invalid sliceArg: must be between 1 and number"
5954  " of 16x16 pixel MBs in a frame", max_err_len);
5956  }
5957  }
5958  }
5959  else if (NI_LOGAN_CODEC_FORMAT_H265 == p_ctx->codec_format)
5960  {
5961  if (10 == p_ctx->src_bit_depth)
5962  {
5963  if (p_cfg->niParamT408.profile != 2)
5964  {
5965  strncpy(p_param_err, "Invalid profile: must be 2 (main10)",
5966  max_err_len);
5968  }
5969  }
5970  else
5971  {
5972  if (p_cfg->niParamT408.profile < 1 || p_cfg->niParamT408.profile > 2)
5973  {
5974  strncpy(p_param_err, "Invalid profile: must be 1 (main) or 2 (main10)",
5975  max_err_len);
5977  }
5978  }
5979  }
5980 
5981  if (1 == p_cfg->niParamT408.independSliceMode)
5982  {
5983  // validate range of sliceArg: 1 - number-of-CTUs-in-frame
5984  int32_t numCtus = ((p_cfg->i32picWidth + 64 - 1) >> 6) *
5985  ((p_cfg->i32picHeight + 64 - 1) >> 6);
5986  if (p_cfg->niParamT408.independSliceModeArg < 1 ||
5987  p_cfg->niParamT408.independSliceModeArg > numCtus)
5988  {
5989  strncpy(p_param_err, "Invalid sliceArg: must be between 1 and number"
5990  " of 64x64 pixel CTUs in a frame", max_err_len);
5992  }
5993  }
5994 
5995  if (p_src->force_frame_type != 0 && p_src->force_frame_type != 1)
5996  {
5997  strncpy(p_param_err, "Invalid forceFrameType: out of range",
5998  max_err_len);
6000  }
6001 
6002  if (p_cfg->niParamT408.forcedHeaderEnable < 0 ||
6003  p_cfg->niParamT408.forcedHeaderEnable > 2)
6004  {
6005  strncpy(p_param_err, "Invalid forcedHeaderEnable: out of range",
6006  max_err_len);
6008  LRETURN;
6009  }
6010 
6011  if (p_cfg->niParamT408.decoding_refresh_type < 0 ||
6013  {
6014  strncpy(p_param_err, "Invalid decoding_refresh_type: out of range", max_err_len);
6016  LRETURN;
6017  }
6018 
6021  {
6022  snprintf(p_param_err, max_err_len, "Invalid gop_preset_index: out of range");
6024  LRETURN;
6025  }
6026 
6028  {
6030  {
6031  strncpy(p_param_err, "Invalid custom GOP paramaters: custom_gop_size too small", max_err_len);
6033  LRETURN;
6034  }
6037  {
6038  strncpy(p_param_err, "Invalid custom GOP paramaters: custom_gop_size too big", max_err_len);
6040  LRETURN;
6041  }
6042  }
6043 
6044  if (p_cfg->niParamT408.use_recommend_enc_params < 0 ||
6046  {
6047  strncpy(p_param_err, "Invalid use_recommend_enc_params: out of range", max_err_len);
6049  LRETURN;
6050  }
6051 
6052  switch (p_cfg->niParamT408.use_recommend_enc_params)
6053  {
6054  case 0:
6055  case 2:
6056  case 3:
6057  {
6058  if (p_cfg->niParamT408.use_recommend_enc_params != 3)
6059  {
6060  // in FAST mode (recommendEncParam==3), max_num_merge value will be
6061  // decided in FW
6062  if (p_cfg->niParamT408.max_num_merge < 0 ||
6063  p_cfg->niParamT408.max_num_merge > 3)
6064  {
6065  strncpy(p_param_err, "Invalid max_num_merge: out of range", max_err_len);
6067  LRETURN;
6068  }
6069  }
6070  break;
6071  }
6072 
6073  default: break;
6074  }
6075 
6076  if ( p_cfg->niParamT408.intra_qp < NI_LOGAN_MIN_INTRA_QP ||
6078  {
6079  strncpy(p_param_err, "Invalid intra_qp: out of range", max_err_len);
6081  LRETURN;
6082  }
6083 
6084  if ( p_cfg->niParamT408.enable_mb_level_rc != 1 &&
6085  p_cfg->niParamT408.enable_mb_level_rc != 0 )
6086  {
6087  strncpy(p_param_err, "Invalid enable_mb_level_rc: out of range", max_err_len);
6089  LRETURN;
6090  }
6091 
6092  if (1 == p_cfg->niParamT408.enable_mb_level_rc)
6093  {
6094  if ( p_cfg->niParamT408.minQpI < 0 ||
6095  p_cfg->niParamT408.minQpI > 51 )
6096  {
6097  strncpy(p_param_err, "Invalid min_qp: out of range", max_err_len);
6099  LRETURN;
6100  }
6101 
6102  if ( p_cfg->niParamT408.maxQpI < 0 ||
6103  p_cfg->niParamT408.maxQpI > 51 )
6104  {
6105  strncpy(p_param_err, "Invalid max_qp: out of range", max_err_len);
6107  LRETURN;
6108  }
6109  // TBD minQpP minQpB maxQpP maxQpB
6110 
6111  if ( p_cfg->niParamT408.enable_cu_level_rate_control != 1 &&
6113  {
6114  strncpy(p_param_err, "Invalid enable_cu_level_rate_control: out of range", max_err_len);
6116  LRETURN;
6117  }
6118 
6119  if (p_cfg->niParamT408.enable_cu_level_rate_control == 1)
6120  {
6121  if ( p_cfg->niParamT408.enable_hvs_qp != 1 &&
6122  p_cfg->niParamT408.enable_hvs_qp != 0 )
6123  {
6124  strncpy(p_param_err, "Invalid enable_hvs_qp: out of range", max_err_len);
6126  LRETURN;
6127  }
6128 
6129  if (p_cfg->niParamT408.enable_hvs_qp)
6130  {
6133  {
6134  strncpy(p_param_err, "Invalid max_delta_qp: out of range", max_err_len);
6136  LRETURN;
6137  }
6138 #if 0
6139  // TBD missing enable_hvs_qp_scale?
6140  if ( p_cfg->niParamT408.enable_hvs_qp_scale != 1 &&
6141  p_cfg->niParamT408.enable_hvs_qp_scale != 0 )
6142  {
6143  snprintf(p_param_err, max_err_len,
6144  "Invalid enable_hvs_qp_scale: out of range");
6146  }
6147 
6148  if (p_cfg->niParamT408.enable_hvs_qp_scale == 1)
6149  {
6150  if ( p_cfg->niParamT408.hvs_qp_scale < 0 ||
6151  p_cfg->niParamT408.hvs_qp_scale > 4 )
6152  {
6153  snprintf(p_param_err, max_err_len, "Invalid hvs_qp_scale: out of range");
6155  }
6156  }
6157 #endif
6158  }
6159  }
6160  // TBD rc_init_delay/i32vbvBufferSize same thing in Rev. B ?
6161  if (p_cfg->i32vbvBufferSize < 10 || p_cfg->i32vbvBufferSize > 3000)
6162  {
6163  strncpy(p_param_err, "Invalid i32vbvBufferSize: out of range", max_err_len);
6165  LRETURN;
6166  }
6167  }
6168 
6169  // check compatibility between GOP size and Intra period
6171  (p_cfg->niParamT408.intra_period % 2) != 0) ||
6175  (p_cfg->niParamT408.intra_period % 4) != 0) ||
6177  (p_cfg->niParamT408.intra_period % 8) != 0)))
6178  {
6179  strncpy(p_param_err, "Error: intra_period and gop_preset_index are "
6180  "incompatible", max_err_len);
6182  LRETURN;
6183  }
6184 
6185  // check valid for common param
6186  param_ret = ni_logan_check_common_params(&p_cfg->niParamT408, p_src, p_param_err, max_err_len);
6187  if (param_ret != NI_LOGAN_RETCODE_SUCCESS)
6188  {
6189  LRETURN;
6190  }
6191 
6192  // check valid for RC param
6193  param_ret = ni_logan_check_ratecontrol_params(p_cfg, p_param_err, max_err_len);
6194  if (param_ret != NI_LOGAN_RETCODE_SUCCESS)
6195  {
6196  LRETURN;
6197  }
6198 
6199  // after validation adjust intra_period/avcIdrPeriod values for internal usage
6200  if (STD_AVC == p_cfg->ui8bitstreamFormat)
6201  {
6202  switch (p_cfg->niParamT408.decoding_refresh_type)
6203  {
6204  case 0: // Non-IRAP I-p_frame
6205  {
6206  // intra_period set to user-configured (above), avcIdrPeriod set to 0
6207  p_cfg->niParamT408.avcIdrPeriod = 0;
6208  break;
6209  }
6210  case 1: // CRA
6211  case 2: // IDR
6212  {
6213  // intra_period set to 0, avcIdrPeriod set to user-configured (above)
6214  p_cfg->niParamT408.intra_period = 0;
6215  break;
6216  }
6217  default:
6218  {
6219  ni_log(NI_LOG_TRACE, "ERROR: %s() unknown value for niParamT408.decoding_refresh_type: %d\n",
6220  __FUNCTION__, p_cfg->niParamT408.decoding_refresh_type);
6221  }
6222  }
6223  }
6224  else if (STD_HEVC == p_cfg->ui8bitstreamFormat)
6225  {
6226  p_cfg->niParamT408.avcIdrPeriod = 0;
6227  }
6228 
6230  {
6231  p_ctx->keyframe_factor =
6232  presetGopKeyFrameFactor[p_cfg->niParamT408.gop_preset_index];
6233  }
6234 
6235  param_ret = NI_LOGAN_RETCODE_SUCCESS;
6236 
6237  ni_log(NI_LOG_DEBUG, "useLowDelayPocType=%d\n", p_src->use_low_delay_poc_type);
6238  // after validation, convert gopPresetIdx based on useLowDelayPocType flag
6239  // for H.264 to enable poc_type = 2
6240  if (NI_LOGAN_CODEC_FORMAT_H264 == p_ctx->codec_format &&
6241  p_src->use_low_delay_poc_type)
6242  {
6243  switch (p_cfg->niParamT408.gop_preset_index)
6244  {
6245  case GOP_PRESET_IDX_ALL_I:
6247  break;
6248  case GOP_PRESET_IDX_IPP:
6250  break;
6251  case GOP_PRESET_IDX_IBBB:
6253  break;
6254  case GOP_PRESET_IDX_IPPPP:
6256  break;
6257  case GOP_PRESET_IDX_IBBBB:
6259  break;
6260  case GOP_PRESET_IDX_SP:
6262  break;
6263  }
6264  ni_log(NI_LOG_DEBUG, "final gop_preset_index=%d\n",
6265  p_cfg->niParamT408.gop_preset_index);
6266  }
6267 
6268  END:
6269 
6270  return param_ret;
6271 }
6272 
6275  char* p_param_err,
6276  uint32_t max_err_len)
6277 {
6279  int32_t low_delay = 0;
6280  int32_t intra_period_gop_step_size;
6281  int32_t i, j;
6282 
6283  if (!p_param || !p_src || !p_param_err)
6284  {
6285  ni_log(NI_LOG_TRACE, "ERROR: %s() Null pointer parameters passed\n", __FUNCTION__);
6287  LRETURN;
6288  }
6289 
6290  //Zero out the error buffer
6291  memset(p_param_err, 0, max_err_len);
6292 
6293  // check low-delay gop structure
6294  if (0 == p_param->gop_preset_index) // custom gop
6295  {
6296  int32_t minVal = 0;
6297  low_delay = (p_param->custom_gop_params.custom_gop_size == 1);
6298 
6299  if (p_param->custom_gop_params.custom_gop_size > 1)
6300  {
6301  minVal = p_param->custom_gop_params.pic_param[0].poc_offset;
6302  low_delay = 1;
6303  for (i = 1; i < p_param->custom_gop_params.custom_gop_size; i++)
6304  {
6305  if (minVal > p_param->custom_gop_params.pic_param[i].poc_offset)
6306  {
6307  low_delay = 0;
6308  break;
6309  }
6310  else
6311  {
6312  minVal = p_param->custom_gop_params.pic_param[i].poc_offset;
6313  }
6314  }
6315  }
6316  }
6317  else if (1 == p_param->gop_preset_index || 2 == p_param->gop_preset_index ||
6318  3 == p_param->gop_preset_index || 6 == p_param->gop_preset_index ||
6319  7 == p_param->gop_preset_index || 9 == p_param->gop_preset_index)
6320  {
6321  low_delay = 1;
6322  }
6323 
6324  if (p_src->low_delay_mode == 1 && ! low_delay)
6325  {
6326  strncpy(p_param_err, "GOP size must be 1 or frames must be in sequence "
6327  "when lowDelay is enabled", max_err_len);
6329  LRETURN;
6330  }
6331 
6332  if (low_delay)
6333  {
6334  intra_period_gop_step_size = 1;
6335  }
6336  else
6337  {
6338  if (p_param->gop_preset_index == GOP_PRESET_IDX_CUSTOM)
6339  {
6340  intra_period_gop_step_size = p_param->custom_gop_params.custom_gop_size;
6341  }
6342  else
6343  {
6344  intra_period_gop_step_size = presetGopSize[p_param->gop_preset_index];
6345  }
6346  }
6347 
6348  if (((p_param->intra_period != 0) && ((p_param->intra_period < intra_period_gop_step_size+1) == 1)) ||
6349  ((p_param->avcIdrPeriod != 0) && ((p_param->avcIdrPeriod < intra_period_gop_step_size+1) == 1)))
6350  {
6351  strncpy(p_param_err, "Invalid intra_period and gop_preset_index: gop structure is larger than intra period",
6352  max_err_len);
6354  LRETURN;
6355  }
6356 
6357  if (((!low_delay) && (p_param->intra_period != 0) && ((p_param->intra_period % intra_period_gop_step_size) != 0)) ||
6358  ((!low_delay) && (p_param->avcIdrPeriod != 0) && ((p_param->avcIdrPeriod % intra_period_gop_step_size) != 0)))
6359  {
6360  strncpy(p_param_err, "Invalid intra_period and gop_preset_index: intra period is not a multiple of gop structure size",
6361  max_err_len);
6363  LRETURN;
6364  }
6365 
6366  // TODO: this error check will never get triggered. remove? (SZ)
6367  if (((!low_delay) && (p_param->intra_period != 0) && ((p_param->intra_period % intra_period_gop_step_size) == 1) &&
6368  p_param->decoding_refresh_type == 0) ||
6369  ((!low_delay) && (p_param->avcIdrPeriod != 0) && ((p_param->avcIdrPeriod % intra_period_gop_step_size) == 1) &&
6370  p_param->decoding_refresh_type == 0))
6371  {
6372  strncpy(p_param_err, "Invalid decoding_refresh_type: not support decoding refresh type I p_frame for closed gop structure",
6373  max_err_len);
6375  LRETURN;
6376  }
6377 
6378  if (p_param->gop_preset_index == GOP_PRESET_IDX_CUSTOM)
6379  {
6380  int temp_poc[NI_LOGAN_MAX_GOP_NUM];
6381  int min_poc = p_param->custom_gop_params.pic_param[0].poc_offset;
6382  for (i = 0; i < p_param->custom_gop_params.custom_gop_size; i++)
6383  {
6384  if (p_param->custom_gop_params.pic_param[i].poc_offset >
6386  {
6387  strncpy(p_param_err, "Invalid custom gop parameters: poc_offset larger"
6388  " than GOP size", max_err_len);
6390  LRETURN;
6391  }
6392 
6394  {
6395  strncpy(p_param_err, "Invalid custom gop parameters: temporal_id larger than 7", max_err_len);
6397  LRETURN;
6398  }
6399 
6400  if (p_param->custom_gop_params.pic_param[i].temporal_id < 0)
6401  {
6402  strncpy(p_param_err, "Invalid custom gop parameters: temporal_id is zero or negative", max_err_len);
6404  LRETURN;
6405  }
6406  temp_poc[i] = p_param->custom_gop_params.pic_param[i].poc_offset;
6407  if (min_poc > temp_poc[i])
6408  {
6409  min_poc = temp_poc[i];
6410  }
6411  }
6412  int count_pos = 0;
6413  for (i = 0; i < p_param->custom_gop_params.custom_gop_size; i++)
6414  {
6415  for (j = 0; j < p_param->custom_gop_params.custom_gop_size; j++)
6416  {
6417  if (temp_poc[j] == min_poc)
6418  {
6419  count_pos++;
6420  min_poc++;
6421  }
6422  }
6423  }
6424  if (count_pos != p_param->custom_gop_params.custom_gop_size)
6425  {
6426  strncpy(p_param_err, "Invalid custom gop parameters: poc_offset is invalid", max_err_len);
6428  LRETURN;
6429  }
6430  }
6431 
6432  if (0 == p_param->use_recommend_enc_params)
6433  {
6434  // RDO
6435  {
6436  int align_32_width_flag = p_src->source_width % 32;
6437  int align_16_width_flag = p_src->source_width % 16;
6438  int align_8_width_flag = p_src->source_width % 8;
6439  int align_32_height_flag = p_src->source_height % 32;
6440  int align_16_height_flag = p_src->source_height % 16;
6441  int align_8_height_flag = p_src->source_height % 8;
6442 
6443  if (((p_param->cu_size_mode & 0x1) == 0) && ((align_8_width_flag != 0) || (align_8_height_flag != 0)))
6444  {
6445  strncpy(p_param_err, "Invalid use_recommend_enc_params and cu_size_mode: picture width and height must be "
6446  "aligned with 8 pixels when enable CU8x8 of cu_size_mode. Recommend to set cu_size_mode |= 0x1 (CU8x8)",
6447  max_err_len);
6449  LRETURN;
6450  }
6451  else if (((p_param->cu_size_mode & 0x1) == 0) && ((p_param->cu_size_mode & 0x2) == 0) &&
6452  ((align_16_width_flag != 0) || (align_16_height_flag != 0)))
6453  {
6454  strncpy(p_param_err, "Invalid use_recommend_enc_params and cu_size_mode: picture width and height must be "
6455  "aligned with 16 pixels when enable CU16x16 of cu_size_mode. Recommend to set cu_size_mode |= 0x2 (CU16x16)",
6456  max_err_len);
6458  LRETURN;
6459  }
6460  else if (((p_param->cu_size_mode & 0x1) == 0) && ((p_param->cu_size_mode & 0x2) == 0) &&
6461  ((p_param->cu_size_mode & 0x4) == 0) && ((align_32_width_flag != 0) || (align_32_height_flag != 0)))
6462  {
6463  strncpy(p_param_err, "Invalid use_recommend_enc_params and cu_size_mode: picture width and height must be "
6464  "aligned with 32 pixels when enable CU32x32 of cu_size_mode. Recommend to set cu_size_mode |= 0x4 (CU32x32)",
6465  max_err_len);
6467  LRETURN;
6468  }
6469  }
6470  }
6471 
6472  if ((p_param->conf_win_top < 0) || (p_param->conf_win_top > 8192))
6473  {
6474  strncpy(p_param_err, "Invalid conf_win_top: out of range", max_err_len);
6476  LRETURN;
6477  }
6478  if (p_param->conf_win_top % 2)
6479  {
6480  strncpy(p_param_err, "Invalid conf_win_top: not multiple of 2", max_err_len);
6482  LRETURN;
6483  }
6484 
6485  if ((p_param->conf_win_bottom < 0) || (p_param->conf_win_bottom > 8192))
6486  {
6487  strncpy(p_param_err, "Invalid conf_win_bottom: out of range", max_err_len);
6489  LRETURN;
6490  }
6491  if (p_param->conf_win_bottom % 2)
6492  {
6493  strncpy(p_param_err, "Invalid conf_win_bottom: not multiple of 2", max_err_len);
6495  LRETURN;
6496  }
6497 
6498  if ((p_param->conf_win_left < 0) || (p_param->conf_win_left > 8192))
6499  {
6500  strncpy(p_param_err, "Invalid conf_win_left: out of range", max_err_len);
6502  LRETURN;
6503  }
6504  if (p_param->conf_win_left % 2)
6505  {
6506  strncpy(p_param_err, "Invalid conf_win_left: not multiple of 2", max_err_len);
6508  LRETURN;
6509  }
6510 
6511  if (p_param->conf_win_right < 0 || p_param->conf_win_right > 8192)
6512  {
6513  strncpy(p_param_err, "Invalid conf_win_right: out of range", max_err_len);
6515  LRETURN;
6516  }
6517  if (p_param->conf_win_right % 2)
6518  {
6519  strncpy(p_param_err, "Invalid conf_win_right: not multiple of 2", max_err_len);
6521  }
6522 
6523  END:
6524 
6525  return ret;
6526 }
6527 
6529  char* p_param_err,
6530  uint32_t max_err_len)
6531 {
6533  ni_logan_t408_config_t* p_param = &p_cfg->niParamT408;
6534 
6535  if (!p_cfg || !p_param_err)
6536  {
6537  ni_log(NI_LOG_TRACE, "ERROR: %s() Null pointer parameters passed\n", __FUNCTION__);
6539  LRETURN;
6540  }
6541 
6542  //Zero out the error buffer
6543  memset(p_param_err, 0, max_err_len);
6544 
6545  if (p_param->roiEnable != 0 && p_param->roiEnable != 1)
6546  {
6547  strncpy(p_param_err, "Invalid roiEnable: out of range", max_err_len);
6549  LRETURN;
6550  }
6551 
6552  // RevB
6553  if (p_cfg->ui8rcEnable == 1)
6554  {
6555  if (p_param->minQpP > p_param->maxQpP || p_param->minQpB > p_param->maxQpB)
6556  {
6557  strncpy(p_param_err, "Invalid min_qp(P/B) and max_qp(P/B): min_qp cannot be larger than max_qp", max_err_len);
6559  LRETURN;
6560  }
6561  }
6562 
6563  END:
6564 
6565  return ret;
6566 }
6567 
6568 
6569 /*!******************************************************************************
6570  * \brief Print xcoder user configurations
6571  *
6572  * \param
6573  *
6574  * \return
6575  *******************************************************************************/
6576 void ni_logan_params_print(void* const p_codec_params, ni_logan_device_type_t device_type)
6577 {
6578  if (!p_codec_params)
6579  {
6580  return;
6581  }
6582 
6583  if (NI_LOGAN_DEVICE_TYPE_DECODER == device_type)
6584  {
6585  ni_logan_decoder_params_t* p_dec_params = (ni_logan_decoder_params_t*)p_codec_params;
6586  ni_logan_decoder_input_params_t* p_dec = &p_dec_params->dec_input_params;
6587 
6588  ni_log(NI_LOG_TRACE, "XCoder Decoder Params:\n");
6589 
6590  ni_log(NI_LOG_TRACE, "fps_number / fps_denominator=%d / %d\n", p_dec_params->fps_number, p_dec_params->fps_denominator);
6591  ni_log(NI_LOG_TRACE, "source_width x source_height=%dx%d\n", p_dec_params->source_width, p_dec_params->source_height);
6592  ni_log(NI_LOG_TRACE, "bitrate=%d\n", p_dec_params->bitrate);
6593 
6594  ni_log(NI_LOG_TRACE, "hwframes=%d\n", p_dec->hwframes);
6595  ni_log(NI_LOG_TRACE, "set_high_priority=%d\n", p_dec->set_high_priority);
6596  ni_log(NI_LOG_TRACE, "keep_alive_timeout=%d\n", p_dec->keep_alive_timeout);
6597  ni_log(NI_LOG_TRACE, "enable_user_data_sei_passthru=%d\n", p_dec->enable_user_data_sei_passthru);
6598  ni_log(NI_LOG_TRACE, "check_packet=%d\n", p_dec->check_packet);
6599  ni_log(NI_LOG_TRACE, "custom_sei_passthru=%d\n", p_dec->custom_sei_passthru);
6600  ni_log(NI_LOG_TRACE, "lowdelay=%d\n", p_dec->lowdelay);
6601  }
6602  else if (NI_LOGAN_DEVICE_TYPE_ENCODER == device_type)
6603  {
6604  ni_logan_encoder_params_t* p_enc_params = (ni_logan_encoder_params_t*)p_codec_params;
6605  ni_logan_encoder_input_params_t* p_enc = &p_enc_params->enc_input_params;
6606 
6607  ni_log(NI_LOG_TRACE, "XCoder Encoder Params:\n");
6608 
6609  ni_log(NI_LOG_TRACE, "preset=%d\n", p_enc_params->preset);
6610  ni_log(NI_LOG_TRACE, "fps_number / fps_denominator=%d / %d\n",
6611  p_enc_params->fps_number, p_enc_params->fps_denominator);
6612 
6613  ni_log(NI_LOG_TRACE, "source_width x source_height=%dx%d\n",
6614  p_enc_params->source_width, p_enc_params->source_height);
6615  ni_log(NI_LOG_TRACE, "bitrate=%d\n", p_enc_params->bitrate);
6616 
6617  ni_log(NI_LOG_TRACE, "profile=%d\n", p_enc->profile);
6618  ni_log(NI_LOG_TRACE, "level_idc=%d\n", p_enc->level_idc);
6619  ni_log(NI_LOG_TRACE, "high_tier=%d\n", p_enc->high_tier);
6620 
6621  ni_log(NI_LOG_TRACE, "frame_rate=%d\n", p_enc->frame_rate);
6622 
6623  ni_log(NI_LOG_TRACE, "use_recommend_enc_params=%d\n", p_enc->use_recommend_enc_params);
6624 
6625  // trans_rate not available in Rev B
6626  ni_log(NI_LOG_TRACE, "enable_rate_control=%d\n", p_enc->rc.enable_rate_control);
6627  ni_log(NI_LOG_TRACE, "enable_cu_level_rate_control=%d\n", p_enc->rc.enable_cu_level_rate_control);
6628  ni_log(NI_LOG_TRACE, "enable_hvs_qp=%d\n", p_enc->rc.enable_hvs_qp);
6629  ni_log(NI_LOG_TRACE, "enable_hvs_qp_scale=%d\n", p_enc->rc.enable_hvs_qp_scale);
6630  ni_log(NI_LOG_TRACE, "hvs_qp_scale=%d\n", p_enc->rc.hvs_qp_scale);
6631  ni_log(NI_LOG_TRACE, "min_qp=%d\n", p_enc->rc.min_qp);
6632  ni_log(NI_LOG_TRACE, "max_qp=%d\n", p_enc->rc.max_qp);
6633  ni_log(NI_LOG_TRACE, "max_delta_qp=%d\n", p_enc->rc.max_delta_qp);
6634  ni_log(NI_LOG_TRACE, "rc_init_delay=%d\n", p_enc->rc.rc_init_delay);
6635 
6636  ni_log(NI_LOG_TRACE, "forcedHeaderEnable=%d\n", p_enc->forced_header_enable);
6637  ni_log(NI_LOG_TRACE, "roi_enable=%d\n", p_enc->roi_enable);
6638  ni_log(NI_LOG_TRACE, "long_term_ref_enable=%d\n", p_enc->long_term_ref_enable);
6639  ni_log(NI_LOG_TRACE, "conf_win_top=%d\n", p_enc->conf_win_top);
6640  ni_log(NI_LOG_TRACE, "conf_win_bottom=%d\n", p_enc->conf_win_bottom);
6641  ni_log(NI_LOG_TRACE, "conf_win_left=%d\n", p_enc->conf_win_left);
6642  ni_log(NI_LOG_TRACE, "conf_win_right=%d\n", p_enc->conf_win_right);
6643 
6644  ni_log(NI_LOG_TRACE, "intra_qp=%d\n", p_enc->rc.intra_qp);
6645  ni_log(NI_LOG_TRACE, "enable_mb_level_rc=%d\n", p_enc->rc.enable_mb_level_rc);
6646 
6647  ni_log(NI_LOG_TRACE, "intra_period=%d\n", p_enc->intra_period);
6648  ni_log(NI_LOG_TRACE, "decoding_refresh_type=%d\n", p_enc->decoding_refresh_type);
6649 
6650  // Rev. B: H.264 only or HEVC-shared parameters, in ni_logan_t408_config_t
6651  ni_log(NI_LOG_TRACE, "enable_transform_8x8=%d\n", p_enc->enable_transform_8x8);
6652  ni_log(NI_LOG_TRACE, "avc_slice_mode=%d\n", p_enc->avc_slice_mode);
6653  ni_log(NI_LOG_TRACE, "avc_slice_arg=%d\n", p_enc->avc_slice_arg);
6654  ni_log(NI_LOG_TRACE, "entropy_coding_mode=%d\n", p_enc->entropy_coding_mode);
6655  ni_log(NI_LOG_TRACE, "intra_mb_refresh_mode=%d\n", p_enc->intra_mb_refresh_mode);
6656  ni_log(NI_LOG_TRACE, "intra_mb_refresh_arg=%d\n", p_enc->intra_mb_refresh_arg);
6657 
6658  ni_log(NI_LOG_TRACE, "gop_preset_index=%d\n", p_enc->gop_preset_index);
6660  {
6661  int i;
6662  ni_log(NI_LOG_TRACE, "custom_gop_params.custom_gop_size=%d\n", p_enc->custom_gop_params.custom_gop_size);
6663  for (i = 0; i < p_enc->custom_gop_params.custom_gop_size; i++)
6664  {
6665  ni_log(NI_LOG_TRACE, "custom_gop_params.pic_param[%d].pic_type=%d\n",
6666  i, p_enc->custom_gop_params.pic_param[i].pic_type);
6667  ni_log(NI_LOG_TRACE, "custom_gop_params.pic_param[%d].poc_offset=%d\n",
6668  i, p_enc->custom_gop_params.pic_param[i].poc_offset);
6669  ni_log(NI_LOG_TRACE, "custom_gop_params.pic_param[%d].pic_qp=%d\n",
6670  i, p_enc->custom_gop_params.pic_param[i].pic_qp);
6671  ni_log(NI_LOG_TRACE, "custom_gop_params.pic_param[%d].num_ref_pic_L0=%d\n",
6673  ni_log(NI_LOG_TRACE, "custom_gop_params.pic_param[%d].ref_poc_L0=%d\n",
6674  i, p_enc->custom_gop_params.pic_param[i].ref_poc_L0);
6675  ni_log(NI_LOG_TRACE, "custom_gop_params.pic_param[%d].ref_poc_L1=%d\n",
6676  i, p_enc->custom_gop_params.pic_param[i].ref_poc_L1);
6677  ni_log(NI_LOG_TRACE, "custom_gop_params.pic_param[%d].temporal_id=%d\n",
6678  i, p_enc->custom_gop_params.pic_param[i].temporal_id);
6679  }
6680  }
6681  }
6682  else if (NI_LOGAN_DEVICE_TYPE_UPLOAD == device_type)
6683  {
6684  ni_logan_decoder_params_t* p_dec_params = (ni_logan_decoder_params_t*)p_codec_params;
6685  ni_logan_decoder_input_params_t* p_dec = &p_dec_params->dec_input_params;
6686 
6687  ni_log(NI_LOG_TRACE, "XCoder Uploader Params:\n");
6688 
6689  ni_log(NI_LOG_TRACE, "hwframes=%d\n", p_dec->hwframes);
6690  }
6691  else
6692  {
6693  ni_log(NI_LOG_ERROR, "XCoder not supported device type:%d\n", device_type);
6694  }
6695 
6696  return;
6697 }
6698 
6699 /*!******************************************************************************
6700  * \brief decoder keep alive thread function triggers every 1 second
6701  *
6702  * \param void thread args
6703  *
6704  * \return void
6705  *******************************************************************************/
6707 {
6710  ni_logan_instance_status_info_t inst_info = { 0 };
6711  ni_logan_session_context_t ctx = {0};
6712  uint32_t loop = 0;
6713  uint64_t endtime = ni_logan_gettime_ns();
6714  //interval(nanoseconds) is equals to ctx.keep_alive_timeout/3(330,000,000ns approximately equal to 1/3 second).
6715  uint64_t interval = args->keep_alive_timeout * 330000000LL;
6716 #ifdef __linux__
6717 
6718 #ifndef __ANDROID__
6719  struct sched_param sched_param;
6720  // Linux has a wide variety of signals, Windows has a few.
6721  // A large number of signals will interrupt the thread, which will cause heartbeat command interval more than 1 second.
6722  // So just mask the unuseful signals in Linux
6723  sigset_t signal;
6724  sigfillset(&signal);
6725  ni_logan_pthread_sigmask(SIG_BLOCK, &signal, NULL);
6726 
6727  /* set up schedule priority
6728  * first try to run with RR mode.
6729  * if fails, try to set nice value.
6730  * if fails either, ignore it and run with default priority.
6731  */
6732  if (((sched_param.sched_priority = sched_get_priority_max(SCHED_RR)) == -1) ||
6733  sched_setscheduler(syscall(SYS_gettid), SCHED_RR, &sched_param) < 0)
6734  {
6735  ni_log(NI_LOG_TRACE, "%s cannot set scheduler: %s\n",
6736  __FUNCTION__, strerror(errno));
6737  if (setpriority(PRIO_PROCESS, 0, -20) != 0)
6738  {
6739  ni_log(NI_LOG_TRACE, "%s cannot set nice value: %s\n",
6740  __FUNCTION__, strerror(errno));
6741  }
6742  }
6743 
6744 #elif defined(_WIN32)
6745  /* set up schedule priority.
6746  * try to set the current thread to time critical level which is the highest prioriy
6747  * level.
6748  */
6749  if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL) == 0)
6750  {
6751  ni_log(NI_LOG_TRACE, "%s cannot set priority: %d.\n",
6752  __FUNCTION__, GetLastError());
6753  }
6754 #endif
6755 
6756 #endif
6757  // Initializes the session context variables that keep alive command and query status command need.
6759  ctx.hw_id = args->hw_id;
6760  ctx.session_id = args->session_id;
6762  ctx.device_type = args->device_type;
6763  ctx.blk_io_handle = args->device_handle;
6764  ctx.event_handle = args->thread_event_handle;
6765  ctx.p_all_zero_buf = args->p_buffer;
6767  ni_log(NI_LOG_TRACE, "%s ctx.keep_alive_timeout: %d.\n", __FUNCTION__,
6768  ctx.keep_alive_timeout);
6769 
6770  for (; ;)// condition TBD
6771  {
6773  retval = ni_logan_query_status_info(&ctx, ctx.device_type, &inst_info, retval, nvme_admin_cmd_xcoder_config);
6774  CHECK_ERR_RC2((&ctx), retval, inst_info, nvme_admin_cmd_xcoder_config,
6775  ctx.device_type, ctx.hw_id, &(ctx.session_id));
6776 
6777  // 1. If received failure, set the close_thread flag to TRUE, and exit,
6778  // then main thread will check this flag and return failure directly;
6779  // 2. skip checking VPU recovery.
6780  // If keep_alive thread detect the VPU RECOVERY before main thread,
6781  // the close_thread flag may damage the vpu recovery handling process.
6782  if ((NI_LOGAN_RETCODE_SUCCESS != retval) &&
6784  {
6785  LRETURN;
6786  }
6787 
6788  endtime += interval;
6789  while (ni_logan_gettime_ns() < endtime)
6790  {
6791  if (args->close_thread)
6792  {
6793  LRETURN;
6794  }
6795  ni_logan_usleep(10000); // 10ms per loop
6796  }
6797  }
6798 
6799  END:
6800  if (NI_LOGAN_RETCODE_SUCCESS != retval)
6801  {
6802  ni_log(NI_LOG_ERROR, "%s abormal closed:%d\n", __FUNCTION__, retval);
6803  args->close_thread = true; // changing the value to be True here means the thread has been closed.
6804  }
6805 
6807 
6808  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
6809 
6810  return NULL;
6811 }
6812 
6813 /*!******************************************************************************
6814 * \brief Open a xcoder uploader instance
6815 *
6816 * \param ni_logan_session_context_t p_ctx - xcoder Context
6817 *
6818 * \return NI_LOGAN_RETCODE_SUCCESS on success,
6819 * negative value like NI_LOGAN_RETCODE_FAILURE in ni_logan_retcode_t on failure
6820 * \return
6821 *******************************************************************************/
6823 {
6825  void * p_buffer = NULL;
6826  uint32_t ui32LBA = 0;
6827  uint32_t model_load = 0;
6828  uint32_t low_delay_mode = 0;
6829  uint32_t buffer_size = 0;
6830  ni_logan_decoder_session_open_info_t session_info = { 0 };
6831 
6832  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
6833 
6834  if (!p_ctx)
6835  {
6836  ni_log(NI_LOG_ERROR, "ERROR %s(): passed parameters are null! return\n",
6837  __FUNCTION__);
6839  LRETURN;
6840  }
6841 
6842  //Create the session if the create session flag is set
6844  {
6845  p_ctx->device_type = NI_LOGAN_DEVICE_TYPE_DECODER;//NI_LOGAN_DEVICE_TYPE_UPLOAD;
6846  p_ctx->pts_table = NULL;
6847  p_ctx->dts_queue = NULL;
6848  p_ctx->p_leftover = NULL;
6849  p_ctx->buffer_pool = NULL;
6850  p_ctx->prev_size = 0;
6851  p_ctx->sent_size = 0;
6852  p_ctx->status = 0;
6853  p_ctx->key_frame_type = 0;
6854  p_ctx->ready_to_close = 0;
6855  p_ctx->rc_error_count = 0;
6856  p_ctx->frame_num = 0;
6857  p_ctx->pkt_num = 0;
6858  p_ctx->pkt_index = 0;
6859  p_ctx->codec_start_time = 0;
6860  p_ctx->codec_total_ticks = 0;
6861  p_ctx->p_all_zero_buf = NULL;
6862  p_ctx->p_dec_packet_inf_buf = NULL;
6863 
6864 #ifdef _WIN32
6866  if (p_ctx->event_handle == NI_INVALID_EVENT_HANDLE)
6867  {
6869  LRETURN;
6870  }
6871 
6873  if (p_ctx->thread_event_handle == NI_INVALID_EVENT_HANDLE)
6874  {
6876  LRETURN;
6877  }
6878 #endif
6879 
6880  //malloc zero data buffer
6881  if(ni_logan_posix_memalign(&p_ctx->p_all_zero_buf, sysconf(_SC_PAGESIZE), NI_LOGAN_DATA_BUFFER_LEN))
6882  {
6883  ni_log(NI_LOG_ERROR, "ERROR: %s() alloc all zero buffer failed\n", __FUNCTION__);
6885  LRETURN;
6886  }
6887  memset(p_ctx->p_all_zero_buf, 0, NI_LOGAN_DATA_BUFFER_LEN);
6888 
6889  //malloc decoder packet info buffer
6890  if(ni_logan_posix_memalign(&p_ctx->p_dec_packet_inf_buf, sysconf(_SC_PAGESIZE), NI_LOGAN_DATA_BUFFER_LEN))
6891  {
6892  ni_log(NI_LOG_ERROR, "ERROR %s(): alloc decoder packet info buffer failed\n", __FUNCTION__);
6894  LRETURN;
6895  }
6897 
6898  //malloc data buffer
6899  if(ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), NI_LOGAN_DATA_BUFFER_LEN))
6900  {
6901  ni_log(NI_LOG_ERROR, "ERROR: %s() alloc data buffer failed\n", __FUNCTION__);
6903  LRETURN;
6904  }
6905  memset(p_buffer, 0, NI_LOGAN_DATA_BUFFER_LEN);
6906 
6907  //Set session ID to be invalid. In case we cannot open session, the session id wold remain invalid.
6908  //In case we can open sesison, the session id would become valid.
6909  ((ni_logan_get_session_id_t *)p_buffer)->session_id = NI_LOGAN_INVALID_SESSION_ID;
6910 
6911  // Get session ID
6913  retval = ni_logan_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle,
6914  p_buffer, NI_LOGAN_DATA_BUFFER_LEN, ui32LBA);
6915 
6916  //Open will return a session status structure with a valid session id if it worked.
6917  //Otherwise the invalid session id set before the open command will stay
6918  p_ctx->session_id = ni_logan_ntohl(((ni_logan_get_session_id_t *)p_buffer)->session_id);
6920  {
6921  ni_log(NI_LOG_ERROR, "ERROR %s(): p_ctx->device_handle=%" PRIx64 ", "
6922  "p_ctx->hw_id=%d, p_ctx->session_id=%d\n", __FUNCTION__,
6923  (int64_t)p_ctx->device_handle, p_ctx->hw_id, p_ctx->session_id);
6926  LRETURN;
6927  }
6928  //Send session Info
6929  memset(p_buffer, 0, NI_LOGAN_DATA_BUFFER_LEN);
6930  session_info.codec_format = ni_logan_htonl(p_ctx->codec_format);
6931  session_info.model_load = ni_logan_htonl(model_load);
6932  session_info.hw_desc_mode = ni_logan_htonl(NI_LOGAN_CODEC_HW_UPLOAD);
6933 
6934  memcpy(p_buffer, &session_info, sizeof(ni_logan_decoder_session_open_info_t));
6937  p_buffer, NI_LOGAN_DATA_BUFFER_LEN, ui32LBA);
6938  CHECK_ERR_RC(p_ctx, retval, NI_LOGAN_NO_CHECK_TS_NVME_CMD_OP,
6939  p_ctx->device_type, p_ctx->hw_id,
6940  &(p_ctx->session_id));
6941  CHECK_VPU_RECOVERY(retval);
6942 
6943  if (NI_LOGAN_RETCODE_SUCCESS != retval)
6944  {
6945  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme write command failed blk_io_handle"
6946  ": %" PRIx64 " hw_id %d\n", __FUNCTION__,
6947  (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id);
6949  LRETURN;
6950  }
6951 
6952  ni_log(NI_LOG_TRACE, "%s ID:0x%x\n", __FUNCTION__, p_ctx->session_id);
6953  ni_logan_aligned_free(p_buffer);
6954  }
6955 
6956  // init for frame pts calculation
6957  p_ctx->last_pts = NI_LOGAN_NOPTS_VALUE;
6958  p_ctx->last_dts = NI_LOGAN_NOPTS_VALUE;
6959  p_ctx->last_dts_interval = 0;
6960  p_ctx->pts_correction_num_faulty_dts = 0;
6961  p_ctx->pts_correction_last_dts = INT64_MIN;
6962  p_ctx->pts_correction_num_faulty_pts = 0;
6963  p_ctx->pts_correction_last_pts = INT64_MIN;
6964 
6965 // ni_logan_timestamp_init(p_ctx, (ni_logan_timestamp_table_t * *) & (p_ctx->pts_table), "dec_pts");
6966 // ni_logan_timestamp_init(p_ctx, (ni_logan_timestamp_table_t * *) & (p_ctx->dts_queue), "dec_dts");
6967 
6968  ni_log(NI_LOG_TRACE, "%s(): p_ctx->device_handle=%" PRIx64 ", p_ctx->hw_id=%d"
6969  " p_ctx->session_id=%d\n", __FUNCTION__, (int64_t)p_ctx->device_handle,
6970  p_ctx->hw_id, p_ctx->session_id);
6972 
6973 #ifndef _WIN32
6974  // If this is a P2P upload session, open the Netint kernel driver
6975  if (p_ctx->isP2P)
6976  {
6977  int ret;
6978  char line[256];
6979  char syspath[256];
6980  char number[3];
6981  struct stat bstat;
6982  char *block_dev;
6983  char *dom, *bus, *dev, *fnc;
6984  FILE *fp;
6985 
6986  p_ctx->netint_fd = open("/dev/netint", O_RDWR);
6987  if (p_ctx->netint_fd < 0)
6988  {
6989  ni_log(NI_LOG_ERROR, "ERROR: %s() Can't open device: %s\n", __func__,
6990  strerror(NI_ERRNO));
6991  retval = NI_LOGAN_RETCODE_FAILURE;
6992  LRETURN;
6993  }
6994 
6995  // find the PCI domain:bus:device:function
6996  block_dev = &p_ctx->blk_xcoder_name[0];
6997  if (stat(block_dev, &bstat) < 0)
6998  {
6999  ni_log(NI_LOG_ERROR, "failed to get stat of file %s\n", block_dev);
7000  retval = NI_LOGAN_RETCODE_FAILURE;
7001  LRETURN;
7002  }
7003 
7004  if ((bstat.st_mode & S_IFMT) != S_IFBLK)
7005  {
7006  ni_log(NI_LOG_ERROR, "%s is not a block device\n", block_dev);
7007  retval = NI_LOGAN_RETCODE_FAILURE;
7008  LRETURN;
7009  }
7010 
7011  ret = snprintf(syspath, sizeof(syspath) - 1, "/sys/block/%s/device/address", block_dev + 5);
7012  syspath[ret] = '\0';
7013  fp = fopen(syspath, "r");
7014  if (fp == NULL)
7015  {
7016  number[0] = block_dev[9];
7017  if('0' <= block_dev[10] && block_dev[10] <= '9')
7018  {
7019  number[1] = block_dev[10];
7020  number[2] = '\0';
7021  }
7022  else
7023  number[1] = '\0';
7024  ret = snprintf(syspath, sizeof(syspath) - 1, "/sys/block/%s/device/nvme%s/address", block_dev + 5, number);
7025  syspath[ret] = '\0';
7026  fp = fopen(syspath, "r");
7027  if (fp == NULL)
7028  {
7029  ni_log(NI_LOG_ERROR, "Failed to read address\n");
7030  retval = NI_LOGAN_RETCODE_FAILURE;
7031  LRETURN;
7032  }
7033  }
7034 
7035  if (fgets(line, 256, fp) == NULL)
7036  {
7037  ni_log(NI_LOG_ERROR, "Failed to read line from address\n");
7038  pclose(fp);
7039  retval = NI_LOGAN_RETCODE_FAILURE;
7040  LRETURN;
7041  }
7042 
7043  pclose(fp);
7044 
7045  errno = 0;
7046  p_ctx->domain = strtoul(line, &dom, 16);
7047 
7048  if (errno < 0)
7049  {
7050  ni_log(NI_LOG_ERROR, "Failed to read PCI domain\n");
7051  retval = NI_LOGAN_RETCODE_FAILURE;
7052  LRETURN;
7053  }
7054 
7055  errno = 0;
7056  p_ctx->bus = strtoul(dom + 1, &bus, 16);
7057 
7058  if (errno < 0)
7059  {
7060  ni_log(NI_LOG_ERROR, "Failed to read PCI bus\n");
7061  retval = NI_LOGAN_RETCODE_FAILURE;
7062  LRETURN;
7063  }
7064 
7065  errno = 0;
7066  p_ctx->dev = strtoul(bus + 1, &dev, 16);
7067 
7068  if (errno < 0)
7069  {
7070  ni_log(NI_LOG_ERROR, "Failed to read PCI device\n");
7071  retval = NI_LOGAN_RETCODE_FAILURE;
7072  LRETURN;
7073  }
7074 
7075  errno = 0;
7076  p_ctx->fn = strtoul(dev + 1, &fnc, 16);
7077 
7078  if (errno < 0)
7079  {
7080  ni_log(NI_LOG_ERROR, "Failed to read PCI function\n");
7081  retval = NI_LOGAN_RETCODE_FAILURE;
7082  LRETURN;
7083  }
7084 
7085  ni_log(NI_LOG_DEBUG, "PCI slot = %d:%d:%d:%d\n", p_ctx->domain, p_ctx->bus,
7086  p_ctx->dev, p_ctx->fn);
7087  }
7088 #endif
7089 
7090 #ifdef XCODER_DUMP_ENABLED
7091  char dump_file[256] = { 0 };
7092 
7093  snprintf(dump_file, sizeof dump_file, "%s%d%s", "decoder_in_id", p_ctx->session_id, ".264");
7094  p_ctx->p_dump[0] = fopen(dump_file, "wb");
7095  ni_log(NI_LOG_TRACE, "dump_file = %s\n", dump_file);
7096 
7097  snprintf(dump_file, sizeof dump_file, "%s%d%s", "decoder_out_id", p_ctx->session_id, ".yuv");
7098  p_ctx->p_dump[1] = fopen(dump_file, "wb");
7099  ni_log(NI_LOG_TRACE, "dump_file = %s\n", dump_file);
7100 
7101  if (!p_ctx->p_dump[0] || !p_ctx->p_dump[1])
7102  {
7103  ni_log(NI_LOG_ERROR, "ERROR: %s(): Cannot open dump file\n", __FUNCTION__);
7104  }
7105 #endif
7106 
7107  END:
7108 
7109  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
7110  return retval;
7111 }
7112 
7113 /*!******************************************************************************
7114 * \brief Copy a xcoder decoder card info and create worker thread
7115 *
7116 * \param ni_logan_session_context_t p_ctx - source xcoder Context
7117 * \param ni_logan_session_context_t p_ctx - destination xcoder Context
7118 *
7119 * \return NI_LOGAN_RETCODE_SUCCESS on success,
7120 * NI_LOGAN_RETCODE_INVALID_PARAM on failure
7121 *******************************************************************************/
7123  ni_logan_session_context_t *dst_p_ctx)
7124 {
7125  if (!src_p_ctx || !dst_p_ctx)
7126  {
7127  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
7129  }
7130 
7131  dst_p_ctx->max_nvme_io_size = src_p_ctx->max_nvme_io_size;
7132  dst_p_ctx->device_handle = src_p_ctx->device_handle;
7133  dst_p_ctx->blk_io_handle = src_p_ctx->blk_io_handle;
7134  dst_p_ctx->hw_id = src_p_ctx->hw_id;
7135 
7136  return NI_LOGAN_RETCODE_SUCCESS;
7137 }
7138 
7139 /*!******************************************************************************
7140 * \brief Send a YUV to hardware, hardware will store it.
7141 *
7142 *
7143 * \param ni_logan_session_context_t p_ctx - xcoder Context
7144 * \param ni_logan_frame_t* p_frame - xcoder frame
7145 *
7146 * \return NI_LOGAN_RETCODE_SUCCESS on success,
7147 * negative value like NI_LOGAN_RETCODE_FAILURE in ni_logan_retcode_t on failure
7148 *******************************************************************************/
7150  ni_logan_frame_t* p_frame)
7151 {
7152  int retval = NI_LOGAN_RETCODE_SUCCESS;
7153  uint32_t size = 0;
7154  uint32_t i = 0;
7155  uint32_t tx_size = 0, aligned_tx_size = 0;
7156  uint32_t sent_size = 0;
7157  uint32_t frame_size_bytes = 0;
7158  ni_logan_instance_buf_info_t buf_info = { 0 };
7159 
7160  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
7161 
7162  if (!p_ctx || !p_frame)
7163  {
7164  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
7166  LRETURN;
7167  }
7168 
7170  {
7171  ni_log(NI_LOG_ERROR, "ERROR: Invlid session ID, return\n");
7173  LRETURN;
7174  }
7175 
7176  frame_size_bytes = p_frame->data_len[0] + p_frame->data_len[1] + p_frame->data_len[2];
7177  ni_log(NI_LOG_TRACE, "%s(): frame size bytes =%d %d is metadata!\n",
7178  __FUNCTION__, frame_size_bytes, 0);
7179 
7181  NI_LOGAN_DEVICE_TYPE_DECODER, &buf_info, 1);
7182  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_query,
7183  p_ctx->device_type, p_ctx->hw_id,
7184  &(p_ctx->session_id));
7185 
7186  if (NI_LOGAN_RETCODE_SUCCESS != retval ||
7187  buf_info.buf_avail_size == 0)
7188  {
7189  ni_log(NI_LOG_ERROR, "Warning upload write query fail rc %d or available "
7190  "buf size %u < frame size %u !\n", retval,
7191  buf_info.buf_avail_size, frame_size_bytes);
7193  LRETURN;
7194  }
7195 
7196  ni_log(NI_LOG_TRACE, "Info hwupload write query success, available buf "
7197  "size %u >= frame size %u !\n",
7198  buf_info.buf_avail_size, frame_size_bytes);
7199 
7200  if (!p_ctx->frame_num)
7201  {
7203  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config,
7204  p_ctx->device_type, p_ctx->hw_id,
7205  &(p_ctx->session_id));
7206  CHECK_VPU_RECOVERY(retval);
7207  if (NI_LOGAN_RETCODE_SUCCESS != retval)
7208  {
7209  ni_log(NI_LOG_TRACE, "ERROR %s(): Failed to send SOS.\n", __FUNCTION__);
7210  LRETURN;
7211  }
7212  }
7213 
7214  if (p_frame->p_data)
7215  {
7216  ni_logan_instance_dec_packet_info_t *p_dec_packet_info;
7217  p_dec_packet_info = (ni_logan_instance_dec_packet_info_t *)p_ctx->p_dec_packet_inf_buf;
7218  p_dec_packet_info->packet_size = frame_size_bytes;
7220  p_ctx->blk_io_handle, p_ctx->event_handle, p_ctx->p_dec_packet_inf_buf,
7223  CHECK_ERR_RC(p_ctx, retval, nvme_cmd_xcoder_write,
7224  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
7225  CHECK_VPU_RECOVERY(retval);
7226  if (retval < 0)
7227  {
7228  ni_log(NI_LOG_ERROR, "ERROR %s(): config pkt size command failed\n",
7229  __FUNCTION__);
7231  LRETURN;
7232  }
7233 
7234  uint32_t ui32LBA = WRITE_INSTANCE_W(1, p_ctx->session_id, NI_LOGAN_DEVICE_TYPE_DECODER);
7235  ni_log(NI_LOG_TRACE, "%s: p_data=%p, p_frame->buffer_size=%u "
7236  "p_ctx->frame_num=%" PRIu64 ", LBA=0x%x, Session ID=%d\n",
7237  __FUNCTION__, p_frame->p_data, p_frame->buffer_size,
7238  p_ctx->frame_num, ui32LBA, p_ctx->session_id);
7239  sent_size = frame_size_bytes;
7240  if (sent_size % NI_LOGAN_MEM_PAGE_ALIGNMENT)
7241  {
7243  }
7244 
7246  p_frame->p_buffer, sent_size, ui32LBA);
7247  CHECK_ERR_RC(p_ctx, retval, nvme_cmd_xcoder_write,
7248  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
7249  CHECK_VPU_RECOVERY(retval);
7250  if (retval < 0)
7251  {
7252  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme command failed\n", __FUNCTION__);
7254  LRETURN;
7255  }
7256 
7257  p_ctx->frame_num++;
7258  size = frame_size_bytes;
7259 
7260 #ifdef XCODER_DUMP_DATA
7261  char dump_file[128];
7262  snprintf(dump_file, sizeof(dump_file), "%ld-%u-hwup-fme/fme-%04ld.yuv",
7263  (long)getpid(), p_ctx->session_id, (long)p_ctx->frame_num);
7264 
7265  FILE *f = fopen(dump_file, "wb");
7266  fwrite(p_frame->p_buffer, p_frame->data_len[0] + p_frame->data_len[1] +
7267  p_frame->data_len[2], 1, f);
7268  fflush(f);
7269  fclose(f);
7270 #endif
7271  }
7272 
7273  retval = size;
7274 
7275  END:
7276 
7277  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
7278  return retval;
7279 }
7280 
7281 /*!******************************************************************************
7282 * \brief Retrieve a HW descriptor of uploaded frame
7283 * The HW descriptor will contain the YUV frame index,
7284 * which stored in HW through ni_logan_hwupload_session_write().
7285 *
7286 * \param ni_logan_session_context_t p_ctx - xcoder Context
7287 * \param ni_logan_hwframe_surface_t* hwdesc - xcoder hardware descriptor
7288 *
7289 * \return NI_LOGAN_RETCODE_SUCCESS on success,
7290 * negative value like NI_LOGAN_RETCODE_FAILURE in ni_logan_retcode_t on failure
7291 *******************************************************************************/
7293  ni_logan_hwframe_surface_t* hwdesc, unsigned int *hwaddress)
7294 {
7295  int retval = NI_LOGAN_RETCODE_SUCCESS;
7296  ni_logan_instance_buf_info_t hwdesc_info = { 0 };
7297  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
7298 
7299  if (!p_ctx || !hwdesc)
7300  {
7301  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
7303  LRETURN;
7304  }
7305 
7307  {
7308  ni_log(NI_LOG_ERROR, "ERROR: Invlid session ID, return\n");
7310  LRETURN;
7311  }
7312 if(p_ctx->isP2P)
7314  NI_LOGAN_DEVICE_TYPE_DECODER, &hwdesc_info, 1);
7315 else
7317  NI_LOGAN_DEVICE_TYPE_DECODER, &hwdesc_info, 1);
7318 
7319  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_query,
7320  p_ctx->device_type, p_ctx->hw_id,
7321  &(p_ctx->session_id));
7322 
7323  if (NI_LOGAN_RETCODE_SUCCESS != retval)
7324  {
7325  ni_log(NI_LOG_ERROR, "Warning upload read hwdesc fail rc %d or ind "
7326  "!\n", retval);
7327  retval = NI_LOGAN_RETCODE_FAILURE;
7328  }
7329  else
7330  {
7331  ni_log(NI_LOG_TRACE, "Info hwupload read hwdesc success, FrameIndex=%d !\n",
7332  hwdesc_info.hw_inst_ind.frame_index);
7333  hwdesc->i8InstID = (int8_t) hwdesc_info.hw_inst_ind.inst_id;
7334  hwdesc->i8FrameIdx = (int8_t) hwdesc_info.hw_inst_ind.frame_index;
7335  *hwaddress = hwdesc_info.hw_inst_ind.hw_address;
7336  hwdesc->ui16SessionID = p_ctx->session_id;
7337  hwdesc->encoding_type = (int8_t)p_ctx->codec_format;
7338 
7339 #ifdef _WIN32
7340  int64_t handle = (int64_t) p_ctx->blk_io_handle;
7341  hwdesc->device_handle = (int32_t) (handle & 0xFFFFFFFF);
7342  hwdesc->device_handle_ext = (int32_t) (handle >> 32);
7343 #else
7344  hwdesc->device_handle = p_ctx->blk_io_handle;
7345 #endif
7346 
7347  hwdesc->bit_depth = p_ctx->bit_depth_factor;
7348  assert(hwdesc->i8FrameIdx >= 0);
7349  }
7350  END:
7351  return retval;
7352 }
7353 
7354 /*!*****************************************************************************
7355 * \brief clear a particular xcoder instance buffer/data
7356 * The device handle is got from decoder or uploader,
7357 * Sent clear HW frame buffer command here to recycle it.
7358 *
7359 * \param ni_logan_hwframe_surface_t* hwdesc - xcoder hardware descriptor
7360 * \param ni_device_handle_t device_handle - device handle
7361 * \param ni_event_handle_t event_handle - event handle
7362 *
7363 * \return - NI_LOGAN_RETCODE_SUCCESS on success, NI_LOGAN_RETCODE_ERROR_INVALID_SESSION,
7364 * NI_LOGAN_RETCODE_ERROR_MEM_ALOC or NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED on
7365 * failure
7366 ******************************************************************************/
7368  ni_device_handle_t device_handle,
7369  ni_event_handle_t event_handle)
7370 {
7371  void* p_buffer = NULL;
7373  uint32_t dataLen = 0;
7374  uint32_t ui32LBA = 0;
7375 
7376  ni_log(NI_LOG_TRACE, "%s(): enter - device_handle %d\n",
7377  __FUNCTION__, device_handle);
7378 
7380  {
7381  ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n");
7383  LRETURN;
7384  }
7385 
7386  //malloc data buffer
7387  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), NI_LOGAN_DATA_BUFFER_LEN))
7388  {
7389  ni_log(NI_LOG_ERROR, "ERROR: %s() alloc data buffer failed\n", __FUNCTION__);
7391  LRETURN;
7392  }
7393  memset(p_buffer, 0, NI_LOGAN_DATA_BUFFER_LEN);
7394 
7395  ((ni_logan_recycle_buffer_t *)p_buffer)->i8FrameIdx = surface->i8FrameIdx;
7396  ((ni_logan_recycle_buffer_t *)p_buffer)->i8InstID = surface->i8InstID;
7397  //maybe just set 13 aqs inst id again?
7398  ni_log(NI_LOG_TRACE, "%s():i8FrameIdx = %d, i8InstID = %d\n",
7399  __FUNCTION__, surface->i8FrameIdx, surface->i8InstID);
7400 
7402  retval = ni_logan_nvme_send_write_cmd(device_handle, event_handle,
7403  p_buffer, NI_LOGAN_DATA_BUFFER_LEN, ui32LBA);
7404  //Cannot check sessio stats here since this isn't a session command.
7405  if(retval < 0)
7406  {
7407  ni_log(NI_LOG_ERROR, " %s(): NVME command Failed\n", __FUNCTION__);
7409  LRETURN;
7410  }
7411 
7412  END:
7413 
7414  ni_logan_aligned_free(p_buffer);
7415 
7416  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
7417 
7418  return retval;
7419 }
7420 
7421 /*!******************************************************************************
7422 * \brief Get Card Serial Number from received Nvme Indentify info
7423 *
7424 * \param
7425 *
7426 * \return
7427 *******************************************************************************/
7429 {
7430  ni_logan_nvme_identity_t* p_id_data = (ni_logan_nvme_identity_t*)p_data;
7431 
7432  if ((!p_serial_num) || (!p_data))
7433  {
7434  ni_log(NI_LOG_ERROR, "ERROR: %s(): Null pointer parameters passed\n",
7435  __FUNCTION__);
7436  LRETURN;
7437  }
7438 
7439  if ((p_id_data->ui16Vid != NETINT_PCI_VENDOR_ID) ||
7440  (p_id_data->ui16Ssvid != NETINT_PCI_VENDOR_ID))
7441  {
7442  LRETURN;
7443  }
7444 
7445  memset(p_serial_num->ai8Sn, 0, sizeof(p_serial_num->ai8Sn));
7446  memcpy(p_serial_num->ai8Sn, p_id_data->ai8Sn, sizeof(p_serial_num->ai8Sn));
7447 
7448  ni_log(NI_LOG_TRACE, "F/W SerialNum: %.20s\n", p_serial_num->ai8Sn);
7449 
7450  END:
7451  return;
7452 }
7453 
7454 /*!******************************************************************************
7455 * \brief Retrieve a hw desc p_frame from decoder
7456 * When yuvbypass enabled, this is used for decoder
7457 * to read hardware frame index, extra data and meta data
7458 *
7459 * \param ni_logan_session_context_t p_ctx - xcoder Context
7460 * \param ni_logan_frame_t* p_frame - xcoder frame
7461 *
7462 * \return rx_size on success,
7463 * negative value like NI_LOGAN_RETCODE_FAILURE in ni_logan_retcode_t on failure
7464 *******************************************************************************/
7466  ni_logan_frame_t* p_frame)
7467 {
7468  //Needs serious editing to support hwdesc read again, this is currently vanilla read
7470  int rx_size = 0;
7471  uint64_t frame_offset = 0;
7472  uint16_t yuvW = 0;
7473  uint16_t yuvH = 0;
7474  uint8_t* p_data_buffer = (uint8_t*)p_frame->p_buffer;
7475  uint32_t data_buffer_size = p_frame->buffer_size;
7476  int i = 0;
7477  int retval = NI_LOGAN_RETCODE_SUCCESS;
7478  int metadata_hdr_size = NI_LOGAN_FW_META_DATA_SZ;
7479  int sei_size = 0;
7480  int frame_cycle = 0;
7481  uint32_t total_bytes_to_read = 0;
7482  uint32_t total_yuv_met_size = 0;
7483  uint32_t read_size_bytes = 0;
7484  uint32_t actual_read_size = 0;
7485  int keep_processing = 1;
7486  ni_logan_instance_status_info_t buf_info = { 0 };
7487  int query_retry = 0;
7488  uint32_t ui32LBA = 0;
7489  int64_t drop_dts = 0;
7490 
7491  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
7492 
7493  if (!p_ctx || !p_frame)
7494  {
7495  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
7497  }
7498 
7500  {
7501  ni_log(NI_LOG_ERROR, "ERROR %s(): xcoder instance id < 0, return\n", __FUNCTION__);
7503  LRETURN;
7504  }
7505 
7506  // p_frame->p_data[] can be NULL before actual resolution is returned by
7507  // decoder and buffer pool is allocated, so no checking here.
7508 
7509  total_bytes_to_read = p_frame->data_len[3] + metadata_hdr_size;
7510  total_yuv_met_size = p_frame->data_len[0] + p_frame->data_len[1] + p_frame->data_len[2] + metadata_hdr_size;
7511  ni_log(NI_LOG_TRACE, "Total bytes to read %d total_yuv_met_size %d \n", total_bytes_to_read, total_yuv_met_size);
7512  while (1)
7513  {
7514  query_retry++;
7515  retval = ni_logan_query_status_info(p_ctx, p_ctx->device_type, &buf_info, retval, nvme_admin_cmd_xcoder_query);
7516  CHECK_ERR_RC2(p_ctx, retval, buf_info, nvme_admin_cmd_xcoder_query,
7517  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
7518  CHECK_VPU_RECOVERY(retval);
7519 
7520  ni_log(NI_LOG_TRACE, "Info query buf_info.rd_buf_avail_size = %u\n",
7521  buf_info.rd_buf_avail_size);
7522 
7523  if (NI_LOGAN_RETCODE_SUCCESS != retval)
7524  {
7525  ni_log(NI_LOG_TRACE, "Warning dec read query fail rc %d retry %d\n",
7526  retval, query_retry);
7527 
7528  if (query_retry >= 1000)
7529  {
7530  retval = NI_LOGAN_RETCODE_SUCCESS;
7531  LRETURN;
7532  }
7533  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
7534  ni_logan_usleep(100);
7535  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
7536  }
7537  else if (buf_info.rd_buf_avail_size == (metadata_hdr_size - sizeof(ni_logan_hwframe_surface_t)))
7538  {
7539  ni_log(NI_LOG_TRACE, "Info only metadata hdr is available, seq change?\n");
7541  total_bytes_to_read = metadata_hdr_size;
7542  break;
7543  }
7544  else if (buf_info.rd_buf_avail_size < total_yuv_met_size)
7545  {
7546  // query to see if it is eos now, if we have sent it
7548  {
7549  ni_log(NI_LOG_TRACE, "Info dec query, ready_to_close %u, ready_to_flush %u, query eos\n",
7550  p_ctx->ready_to_close, p_ctx->ready_to_flush);
7551  retval = ni_logan_query_stream_info(p_ctx, NI_LOGAN_DEVICE_TYPE_DECODER, &data, 1);
7552  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_query,
7553  p_ctx->device_type, p_ctx->hw_id,
7554  &(p_ctx->session_id));
7555  CHECK_VPU_RECOVERY(retval);
7556 
7557  if (data.is_flushed ||
7559  {
7560  ni_log(NI_LOG_TRACE, "Info eos or fulsh buffers reached.\n");
7561  if (query_retry >= NI_LOGAN_MAX_DEC_SESSION_READ_QUERY_EOS_RETRIES) //15000 retries
7562  {
7563  ni_log(NI_LOG_INFO, "Info eos reached or flush buffers exceeding max retries: is_flushed %u try %d.\n",
7564  data.is_flushed, query_retry);
7565  }
7566  if (p_ctx->ready_to_close)
7567  {
7568  p_frame->end_of_stream = 1;
7569  }
7570  else
7571  {
7573  }
7574  retval = NI_LOGAN_RETCODE_SUCCESS;
7575  LRETURN;
7576  }
7577  else
7578  {
7579  ni_log(NI_LOG_TRACE, "Dec read available buf size == 0, query try %d,"
7580  " retrying ..\n", query_retry);
7581  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
7583  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
7584  continue;
7585  }
7586  }
7587 
7588  ni_log(NI_LOG_TRACE, "Warning dec read available buf size == 0 "
7589  "eos %u nb try %d\n", p_frame->end_of_stream, query_retry);
7590 
7592  query_retry < 1000)
7593  {
7594  ni_logan_pthread_mutex_unlock(&p_ctx->mutex);
7595  ni_logan_usleep(100);
7596  ni_logan_pthread_mutex_lock(&p_ctx->mutex);
7597  continue;
7598  }
7599  retval = NI_LOGAN_RETCODE_SUCCESS;
7600  LRETURN;
7601  }
7602  else
7603  {
7604  // We have to ensure there are adequate number of DTS for picture
7605  // reorder delay otherwise wait for more packets to be sent to decoder.
7606  ni_logan_timestamp_table_t* p_dts_queue = p_ctx->dts_queue;
7607  if ((int)p_dts_queue->list.count < p_ctx->pic_reorder_delay + 1 &&
7608  !p_ctx->ready_to_close &&
7611  {
7612  retval = NI_LOGAN_RETCODE_SUCCESS;
7613  LRETURN;
7614  }
7615 
7616  // get actual YUV transfer size if this is the stream's very first read
7617  if (0 == p_ctx->active_video_width || 0 == p_ctx->active_video_height)
7618  {
7619  retval = ni_logan_query_stream_info(p_ctx, NI_LOGAN_DEVICE_TYPE_DECODER, &data, 1);
7620  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_query,
7621  p_ctx->device_type, p_ctx->hw_id,
7622  &(p_ctx->session_id));
7623  CHECK_VPU_RECOVERY(retval);
7624 
7625  ni_log(NI_LOG_TRACE, "Info dec YUV query, pic size %ux%u xfer frame size "
7626  "%ux%u frame-rate %u is_flushed %u\n",
7627  data.picture_width, data.picture_height,
7628  data.transfer_frame_stride, data.transfer_frame_height,
7629  data.frame_rate, data.is_flushed);
7630  p_ctx->active_video_width = data.transfer_frame_stride;
7631  p_ctx->active_video_height = data.transfer_frame_height;
7632  p_ctx->active_bit_depth = (p_ctx->bit_depth_factor==2)?10:8;
7633  p_ctx->is_sequence_change = 1;
7634 
7635  ni_log(NI_LOG_TRACE, "Info dec YUV, adjust frame size from %ux%u %dbits to %ux%u\n",
7636  p_frame->video_width, p_frame->video_height, p_ctx->active_bit_depth,
7637  p_ctx->active_video_width, p_ctx->active_video_height);
7638 
7639  retval = ni_logan_frame_buffer_alloc(p_frame,
7640  p_ctx->active_video_width,
7641  p_ctx->active_video_height,
7643  1,
7644  p_ctx->bit_depth_factor,
7645  1); //Alloc space for write to data[3] and metadata
7646 
7647  if (NI_LOGAN_RETCODE_SUCCESS != retval)
7648  {
7649  LRETURN;
7650  }
7651  total_bytes_to_read = p_frame->data_len[3] + metadata_hdr_size;
7652 
7653  p_data_buffer = (uint8_t*)p_frame->p_buffer;
7654 
7655  // make sure we don't read more than available
7656  ni_log(NI_LOG_TRACE, "Info dec buf size: %u YUV frame + meta-hdr size: %u "
7657  "available: %u\n", p_frame->buffer_size, total_bytes_to_read,
7658  buf_info.rd_buf_avail_size);
7659  }
7660  break;
7661  }
7662  }// end while1 query retry
7663  unsigned int bytes_read_so_far = 0;
7664 
7665  ni_log(NI_LOG_TRACE, "total_bytes_to_read %d max_nvme_io_size %d ylen %d "
7666  "cr len %d cb len %d hwdes len %d hdr %d\n", total_bytes_to_read,
7667  p_ctx->max_nvme_io_size, p_frame->data_len[0], p_frame->data_len[1],
7668  p_frame->data_len[2], p_frame->data_len[3], metadata_hdr_size);
7669 
7670 
7671  if (p_ctx->decoder_last_drop_frame_num < buf_info.frames_dropped) {
7672  for (i = p_ctx->decoder_last_drop_frame_num; i < buf_info.frames_dropped; i++)
7673  {
7674  ni_logan_timestamp_get_with_threshold(p_ctx->dts_queue, 0, &drop_dts,
7675  LOGAN_XCODER_FRAME_OFFSET_DIFF_THRES, (p_ctx->frame_num % 500 == 0),
7676  p_ctx->buffer_pool);
7677  }
7678  p_ctx->decoder_last_drop_frame_num = buf_info.frames_dropped;
7679  ni_log(NI_LOG_DEBUG, "drop total %d dts in queue\n", p_ctx->decoder_last_drop_frame_num);
7680  }
7681 
7682  if (total_bytes_to_read == metadata_hdr_size) // metadata alone, seqchange?
7683  {
7684  buf_info.rd_buf_avail_size = buf_info.rd_buf_avail_size + sizeof(ni_logan_hwframe_surface_t);
7685  }
7686  else
7687  {
7688  buf_info.rd_buf_avail_size = buf_info.rd_buf_avail_size + 2 * sizeof(ni_logan_hwframe_surface_t) -
7689  (p_ctx->active_video_width * p_ctx->active_video_height * 3 / 2) * p_ctx->bit_depth_factor;
7690  }
7691  ni_log(NI_LOG_TRACE, "buf_avail_size = %d \n", buf_info.rd_buf_avail_size);
7692  if (buf_info.rd_buf_avail_size < total_bytes_to_read)
7693  {
7694  ni_log(NI_LOG_ERROR, "ERROR %s() avaliable size(%u) less than needed (%u)\n",
7695  __FUNCTION__, buf_info.rd_buf_avail_size, total_bytes_to_read);
7696  ni_logan_assert(0);
7697  }
7698 
7699  read_size_bytes = buf_info.rd_buf_avail_size;
7701  if (read_size_bytes % NI_LOGAN_MEM_PAGE_ALIGNMENT)
7702  {
7703  read_size_bytes = ( (read_size_bytes / NI_LOGAN_MEM_PAGE_ALIGNMENT) * NI_LOGAN_MEM_PAGE_ALIGNMENT) + NI_LOGAN_MEM_PAGE_ALIGNMENT;
7704  }
7705 
7706  retval = ni_logan_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle,
7707  p_data_buffer, read_size_bytes, ui32LBA);
7708  CHECK_ERR_RC(p_ctx, retval, nvme_cmd_xcoder_read,
7709  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
7710  CHECK_VPU_RECOVERY(retval);
7711  if (retval < 0)
7712  {
7713  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme command failed\n", __FUNCTION__);
7715  LRETURN;
7716  }
7717  else
7718  {
7719  // command issued successfully, now exit
7721  (ni_logan_metadata_dec_frame_t*)((uint8_t*)p_frame->p_buffer
7722  + p_frame->data_len[0] + p_frame->data_len[1]
7723  + p_frame->data_len[2] + p_frame->data_len[3]);
7724 
7725  if (buf_info.rd_buf_avail_size != metadata_hdr_size)
7726  {
7727  sei_size = p_meta->sei_size;
7728  frame_cycle = p_meta->frame_cycle;
7729 
7730  ni_logan_hwframe_surface_t* p_data3 = (ni_logan_hwframe_surface_t*)((uint8_t*)p_frame->p_buffer + p_frame->data_len[0]
7731  + p_frame->data_len[1] + p_frame->data_len[2]);
7732 
7733  // Zhong: manually set bit_depth based on known; should this be set by fw ?
7734  p_data3->bit_depth = p_ctx->bit_depth_factor;
7735 
7736 
7737  ni_log(NI_LOG_TRACE, "%s(): i8FrameIdx:%d, %d\n", __FUNCTION__,
7738  p_data3->i8FrameIdx, p_meta->hwdesc.i8FrameIdx);
7739 #ifdef _WIN32
7740  int64_t handle = (int64_t) p_ctx->blk_io_handle;
7741  p_data3->device_handle = (int32_t) (handle & 0xFFFFFFFF);
7742  p_data3->device_handle_ext = (int32_t) (handle >> 32);
7743 #else
7744  p_data3->device_handle = p_ctx->blk_io_handle; //Libxcoder knows the handle so overwrite here
7745 #endif
7746  p_data3->ui16SessionID = (uint16_t)p_ctx->session_id;
7747  p_data3->encoding_type = (int8_t)p_ctx->codec_format;
7748 
7749  ni_log(NI_LOG_TRACE, "%s:sei_size=%d device_handle=%d == hw_id=%d "
7750  "ses_id=%d\n", __FUNCTION__, sei_size, p_data3->device_handle,
7751  p_ctx->hw_id, p_data3->ui16SessionID);
7752  ni_log(NI_LOG_TRACE, "%s: ui16FrameIdx=%d, bit_depth(in data3)=%d, "
7753  "bit_depth(in meta)=%d\n", __FUNCTION__, p_data3->i8FrameIdx,
7754  p_data3->bit_depth, p_meta->hwdesc.bit_depth);
7755 
7756  // set seq_change when received first sequence changed frame.
7758  {
7759  ni_log(NI_LOG_TRACE, "%s: sequence change first frame, set seq_change\n", __FUNCTION__);
7760  p_data3->seq_change = 1;
7762  }
7763  }
7764  p_ctx->codec_total_ticks += frame_cycle;
7765  total_bytes_to_read = total_bytes_to_read + sei_size;
7766 
7767  ni_log(NI_LOG_TRACE, "%s success, retval %d total_bytes_to_read include "
7768  "sei %d sei_size %d frame_cycle %d\n", __FUNCTION__, retval,
7769  total_bytes_to_read, sei_size, frame_cycle);
7770  }
7771 
7772 
7773  // Note: session status is NOT reset but tracked between send
7774  // and recv to catch and recover from a loop condition
7775  bytes_read_so_far = total_bytes_to_read;
7776  p_frame->src_codec = p_ctx->codec_format;
7777  rx_size = ni_logan_create_frame(p_frame, bytes_read_so_far, &frame_offset, true);
7778  p_ctx->frame_pkt_offset = frame_offset;
7779 
7780  // if using old firmware, bit_depth=0 so use bit_depth_factor
7781  if (!p_frame->bit_depth)
7782  p_frame->bit_depth = (p_ctx->bit_depth_factor==2)?10:8;
7783 
7784  // if sequence change, update bit depth factor
7785  if ((rx_size == 0))
7786  p_ctx->bit_depth_factor = (p_frame->bit_depth==10) ? 2: 1;
7787 
7788  if (rx_size > 0 && total_bytes_to_read != metadata_hdr_size)
7789  {
7790  ni_log(NI_LOG_TRACE, "%s(): s-state %d seq change %d\n", __FUNCTION__,
7791  p_ctx->session_run_state, p_ctx->is_sequence_change);
7792  if (ni_logan_timestamp_get_with_threshold(p_ctx->dts_queue, 0, (int64_t*)&p_frame->dts,
7793  LOGAN_XCODER_FRAME_OFFSET_DIFF_THRES, (p_ctx->frame_num % 500 == 0),
7795  {
7796  if (p_ctx->last_dts != NI_LOGAN_NOPTS_VALUE && !p_ctx->ready_to_close &&
7798  {
7799  // Mark as DTS padding for offset compensation
7800  p_ctx->pic_reorder_delay++;
7801  p_frame->dts = p_ctx->last_dts + p_ctx->last_dts_interval;
7802  ni_log(NI_LOG_ERROR, "Padding DTS:%ld.\n", p_frame->dts);
7803  }
7804  else
7805  {
7806  p_frame->dts = NI_LOGAN_NOPTS_VALUE;
7807  }
7808  }
7809 
7810  // Read the following DTS for picture reorder delay
7811  if (p_ctx->is_sequence_change)
7812  {
7813  for (i = 0; i < p_ctx->pic_reorder_delay; i++)
7814  {
7815  if (p_ctx->last_pts == NI_LOGAN_NOPTS_VALUE && p_ctx->last_dts == NI_LOGAN_NOPTS_VALUE)
7816  {
7817  // If the p_frame->pts is unknown in the very beginning of the stream
7818  // (video stream only) we assume p_frame->pts == 0 as well as DTS less
7819  // than PTS by 1000 * 1/timebase
7820  if (p_frame->pts >= p_frame->dts && p_frame->pts - p_frame->dts < 1000)
7821  {
7822  break;
7823  }
7824  }
7825 
7826  if (ni_logan_timestamp_get_with_threshold(p_ctx->dts_queue, 0, (int64_t*)&p_frame->dts,
7827  LOGAN_XCODER_FRAME_OFFSET_DIFF_THRES, (p_ctx->frame_num % 500 == 0),
7829  {
7830  p_frame->dts = NI_LOGAN_NOPTS_VALUE;
7831  }
7832  }
7833  // Reset for DTS padding counting
7834  p_ctx->pic_reorder_delay = 0;
7835  }
7836 
7837  // Handle PTS
7838  i = rotated_array_binary_search(p_ctx->pkt_offsets_index_min,
7839  p_ctx->pkt_offsets_index,
7840  NI_LOGAN_FIFO_SZ, frame_offset);
7841  if (i >= 0)
7842  {
7843  // According to LGXCOD-3099 the frame_offset would be less than
7844  // expected by the size of SEI unit when there is malformed SEI
7845  // being sent into decoder. That will lead to mismatch of the
7846  // true PTS offset with the decoded frame. So we need to correct
7847  // the offset range when there is suspicious frame_offset for
7848  // decoded frames.
7849  uint64_t d1 = frame_offset - p_ctx->pkt_offsets_index_min[i];
7850  uint64_t d2 = p_ctx->pkt_offsets_index[i] - frame_offset;
7851  if (d1 > d2)
7852  {
7853  // When the frame_offset is closer to the right boundary, the
7854  // right margin is caused by the missing SEI size.
7855  i++;
7856  }
7857 
7858  p_frame->pts = p_ctx->pts_offsets[i];
7859  p_frame->flags = p_ctx->flags_array[i];
7860  p_frame->p_custom_sei = (uint8_t *)p_ctx->pkt_custom_sei[i % NI_LOGAN_FIFO_SZ];
7861  p_ctx->pkt_custom_sei[i % NI_LOGAN_FIFO_SZ] = NULL;
7862  }
7863  else
7864  {
7865  //backup solution pts
7866  p_frame->pts = p_ctx->last_pts + p_ctx->last_dts_interval;
7867  ni_log(NI_LOG_ERROR, "ERROR: NO pts found consider increasing NI_LOGAN_FIFO_SZ!\n");
7868  }
7869 
7870  p_frame->pts = guess_correct_pts(p_ctx, p_frame->pts, p_frame->dts, p_ctx->last_pts);
7871  p_ctx->last_pts = p_frame->pts;
7872  if ((0 == p_ctx->is_sequence_change) && (NI_LOGAN_NOPTS_VALUE != p_frame->dts) && (NI_LOGAN_NOPTS_VALUE != p_ctx->last_dts))
7873  {
7874  p_ctx->last_dts_interval = p_frame->dts - p_ctx->last_dts;
7875  }
7876  p_ctx->last_dts = p_frame->dts;
7877  p_ctx->is_sequence_change = 0;
7878  p_ctx->frame_num++;
7879  }
7880 
7881 #ifdef XCODER_DUMP_ENABLED
7882  fwrite(p_frame->data[0], rx_size, 1, p_ctx->p_dump[1]);
7883 #endif
7884 
7885  ni_log(NI_LOG_TRACE, "%s(): received data: [0x%08x]\n", __FUNCTION__, rx_size);
7886  ni_log(NI_LOG_TRACE, "%s(): p_frame->start_of_stream=%d, p_frame->end_of_stream=%d, "
7887  "p_frame->video_width=%d, p_frame->""video_height=%d\n", __FUNCTION__,
7888  p_frame->start_of_stream, p_frame->end_of_stream,
7889  p_frame->video_width, p_frame->video_height);
7890  ni_log(NI_LOG_TRACE, "%s(): p_frame->data_len[0/1/2]=%d/%d/%d\n", __FUNCTION__,
7891  p_frame->data_len[0], p_frame->data_len[1], p_frame->data_len[2]);
7892 
7893  if (p_ctx->frame_num % 500 == 0)
7894  {
7895  ni_log(NI_LOG_TRACE, "Decoder pts queue size = %d dts queue size = %d\n\n",
7896  ((ni_logan_timestamp_table_t*)p_ctx->pts_table)->list.count,
7897  ((ni_logan_timestamp_table_t*)p_ctx->dts_queue)->list.count);
7898  // scan and clean up
7900  }
7901 
7902  END:
7903 
7904  if (NI_LOGAN_RETCODE_SUCCESS != retval)
7905  {
7906  ni_log(NI_LOG_ERROR, "%s(): bad exit, retval = %d\n", __FUNCTION__, retval);
7907  return retval;
7908  }
7909  else
7910  {
7911  ni_log(NI_LOG_TRACE, "%s(): exit, rx_size = %d\n", __FUNCTION__, rx_size);
7912  return rx_size;
7913  }
7914 }
7915 
7916 /*!******************************************************************************
7917 * \brief Retrieve a YUV through HW descriptor from decoder
7918 *
7919 * \param ni_logan_session_context_t p_ctx - xcoder Context
7920 * \param ni_logan_frame_t* p_frame - xcoder frame
7921 * \param ni_logan_hwframe_surface_t* hwdesc - xcoder hardware descriptor
7922 *
7923 * \return rx_size on success,
7924 * negative value like NI_LOGAN_RETCODE_FAILURE in ni_logan_retcode_t on failure
7925 *******************************************************************************/
7927  ni_logan_frame_t* p_frame,
7929 {
7930  int retval = NI_LOGAN_RETCODE_SUCCESS;
7931  int rx_size = 0;
7933  uint64_t frame_offset = 0;
7934  uint16_t yuvW = 0;
7935  uint16_t yuvH = 0;
7936  uint8_t* p_data_buffer = (uint8_t*)p_frame->p_buffer;
7937  uint32_t data_buffer_size = p_frame->buffer_size;
7938  int i = 0;
7939  int metadata_hdr_size = NI_LOGAN_FW_META_DATA_SZ;
7940  int sei_size = 0;
7941  uint32_t total_bytes_to_read = 0;
7942  uint32_t read_size_bytes = 0;
7943  uint32_t actual_read_size = 0;
7944  int keep_processing = 1;
7945  ni_logan_instance_buf_info_t buf_info = { 0 };
7946  int query_retry = 0;
7947  uint32_t ui32LBA = 0;
7948  unsigned int bytes_read_so_far = 0;
7949 
7950  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
7951 
7952  if (!p_ctx || !p_frame)
7953  {
7954  ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n");
7956  }
7957 
7959  {
7960  ni_log(NI_LOG_ERROR, "ERROR %s(): xcoder instance id < 0, return\n", __FUNCTION__);
7962  LRETURN;
7963  }
7964 
7965  for (i = 0; i < NI_LOGAN_MAX_NUM_DATA_POINTERS - 1; i++) //discount the hwdesc
7966  {
7967  if (!p_frame->p_data[i])
7968  {
7969  ni_log(NI_LOG_ERROR, "ERROR %s(): No receive buffer allocated.\n", __FUNCTION__);
7971  LRETURN;
7972  }
7973  }
7974 
7975  if (0 == p_frame->data_len[0])
7976  {
7977  ni_log(NI_LOG_ERROR, "ERROR %s(): p_frame->data_len[0] = 0!.\n", __FUNCTION__);
7979  LRETURN;
7980  }
7981 
7982  total_bytes_to_read = p_frame->data_len[0] + p_frame->data_len[1] + p_frame->data_len[2];// +metadata_hdr_size;
7983 
7984  ni_log(NI_LOG_TRACE, "%s total_bytes_to_read %d max_nvme_io_size %d ylen %d "
7985  "cr len %d cb len %d hdr %d\n", __FUNCTION__, total_bytes_to_read,
7986  p_ctx->max_nvme_io_size, p_frame->data_len[0], p_frame->data_len[1],
7987  p_frame->data_len[2], metadata_hdr_size);
7988 
7989  //Apply read configuration here
7991  1,
7993  hwdesc->i8FrameIdx);
7994  CHECK_ERR_RC(p_ctx, retval, NI_LOGAN_NO_CHECK_TS_NVME_CMD_OP,
7995  p_ctx->device_type, p_ctx->hw_id,
7996  &(p_ctx->session_id));
7997  CHECK_VPU_RECOVERY(retval);
7998 
7999  read_size_bytes = total_bytes_to_read;
8001 
8002  if (read_size_bytes % NI_LOGAN_MEM_PAGE_ALIGNMENT)
8003  {
8004  read_size_bytes = ((read_size_bytes / NI_LOGAN_MEM_PAGE_ALIGNMENT) * NI_LOGAN_MEM_PAGE_ALIGNMENT) + NI_LOGAN_MEM_PAGE_ALIGNMENT;
8005  }
8006 
8007 #ifdef _WIN32
8008  int64_t handle = (((int64_t) hwdesc->device_handle_ext) << 32) | hwdesc->device_handle;
8009  retval = ni_logan_nvme_send_read_cmd((ni_device_handle_t) handle, p_ctx->event_handle,
8010  p_data_buffer, read_size_bytes, ui32LBA);
8011 #else
8012  retval = ni_logan_nvme_send_read_cmd((ni_device_handle_t) hwdesc->device_handle, p_ctx->event_handle,
8013  p_data_buffer, read_size_bytes, ui32LBA);
8014 #endif
8015  CHECK_ERR_RC(p_ctx, retval, NI_LOGAN_NO_CHECK_TS_NVME_CMD_OP,
8016  p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id));
8017  CHECK_VPU_RECOVERY(retval);
8018  if (retval < 0)
8019  {
8020  ni_log(NI_LOG_ERROR, "ERROR %s(): nvme command failed\n", __FUNCTION__);
8022  LRETURN;
8023  }
8024  else
8025  {
8026  ni_log(NI_LOG_TRACE, "%s success, retval %d total_bytes_to_read include "
8027  "sei %d sei_size %d\n", __FUNCTION__, retval, total_bytes_to_read, sei_size);
8028  }
8029 
8030  ni_log(NI_LOG_TRACE, "%s total_bytes_to_read %d ylen %d cr len %d cb len %d data0 0x%x data_end 0x%x idx %d\n", \
8031  __FUNCTION__, total_bytes_to_read, p_frame->data_len[0],
8032  p_frame->data_len[1], p_frame->data_len[2], p_data_buffer[0],
8033  p_data_buffer[total_bytes_to_read-1], total_bytes_to_read -1);
8034 
8035  bytes_read_so_far = total_bytes_to_read;
8036  // Note: session status is NOT reset but tracked between send
8037  // and recv to catch and recover from a loop condition
8038 
8039  rx_size = ni_logan_create_frame(p_frame, bytes_read_so_far, &frame_offset, false);
8040  p_ctx->frame_pkt_offset = frame_offset;
8041 
8042  ni_log(NI_LOG_TRACE, "%s(): received data:[0x%08x]\n", __FUNCTION__, rx_size);
8043  ni_log(NI_LOG_TRACE, "%s(): p_frame->start_of_stream=%d, "
8044  "p_frame->end_of_stream=%d, p_frame->video_width=%d, "
8045  "p_frame->video_height=%d\n", __FUNCTION__, p_frame->start_of_stream,
8046  p_frame->end_of_stream, p_frame->video_width, p_frame->video_height);
8047  ni_log(NI_LOG_TRACE, "%s(): p_ctx->frame_num%ld, p_frame->data_len[0/1/2]=%d/%d/%d\n",
8048  __FUNCTION__, p_ctx->frame_num, p_frame->data_len[0],
8049  p_frame->data_len[1], p_frame->data_len[2]);
8050 
8051  END:
8052 
8053  if (NI_LOGAN_RETCODE_SUCCESS != retval)
8054  {
8055  ni_log(NI_LOG_ERROR, "%s(): bad exit, retval = %d\n", __FUNCTION__, retval);
8056  return retval;
8057  }
8058  else
8059  {
8060  ni_log(NI_LOG_TRACE, "%s(): exit, rx_size = %d\n", __FUNCTION__, rx_size);
8061  return rx_size;
8062  }
8063 }
8064 
8065 /*!******************************************************************************
8066 * \brief Close an xcoder upload instance
8067 *
8068 * \param ni_logan_session_context_t p_ctx - xcoder Context
8069 *
8070 * \return
8071 *******************************************************************************/
8073 {
8074  return 0;
8075 }
8076 
8077 /*!******************************************************************************
8078 * \brief Setup framepool for hwupload. Uses decoder framepool
8079 *
8080 * \param ni_logan_session_context_t p_ctx - xcoder Context
8081 * \param uint32_t pool_size - buffer pool in HW
8082 *
8083 * \return NI_LOGAN_RETCODE_SUCCESS on success,
8084 * negative value like NI_LOGAN_RETCODE_FAILURE in ni_logan_retcode_t on failure
8085 *******************************************************************************/
8087  uint32_t pool_size, uint32_t p2p_pool)
8088 {
8089  ni_logan_init_frames_params_t* p_init_frames_param = NULL;
8090  uint32_t buffer_size = sizeof(ni_logan_encoder_config_t);
8092  uint32_t ui32LBA = 0;
8093  int i = 0;
8094  ni_log(NI_LOG_TRACE, "%s(): enter\n", __FUNCTION__);
8095 
8096  if (!p_ctx)
8097  {
8098  ni_log(NI_LOG_ERROR, "ERROR: %s(): NULL pointer p_config passed\n",
8099  __FUNCTION__);
8101  LRETURN;
8102  }
8103 
8105  {
8106  ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n");
8108  LRETURN;
8109  }
8110 
8112  if (ni_logan_posix_memalign((void **)&p_init_frames_param, sysconf(_SC_PAGESIZE), buffer_size))
8113  {
8114  ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate encConf buffer.\n");
8116  LRETURN;
8117  }
8118  memset((void *)p_init_frames_param, 0, buffer_size);
8119 
8120  p_init_frames_param->width = ni_logan_ntohs(p_ctx->active_video_width);
8121  p_init_frames_param->height = ni_logan_ntohs(p_ctx->active_video_height);
8122  p_init_frames_param->bit_depth_factor = ni_logan_ntohs(p_ctx->bit_depth_factor);
8123  p_init_frames_param->pool_size = ni_logan_ntohs(pool_size);
8124  p_init_frames_param->p2p_pool = ni_logan_ntohs(p2p_pool);
8125 
8126  ni_log(NI_LOG_TRACE, "%s():%d x %d x bitdepth %d with %d framepool \n",
8127  __FUNCTION__, p_init_frames_param->width, p_init_frames_param->height,
8128  p_init_frames_param->bit_depth_factor, p_init_frames_param->pool_size);
8129 
8131 
8133  p_init_frames_param, buffer_size, ui32LBA);
8134  CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config,
8135  p_ctx->device_type, p_ctx->hw_id,
8136  &(p_ctx->session_id));
8137  if (NI_LOGAN_RETCODE_SUCCESS != retval)
8138  {
8139  ni_log(NI_LOG_ERROR, "ERROR: ni_logan_nvme_send_write_cmd failed: blk_io_handle: %" PRIx64 ", hw_id, %u, xcoder_inst_id: %d\n", (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id, p_ctx->session_id);
8140  //Close the session since we can't configure it
8141  retval = ni_logan_decoder_session_close(p_ctx, 0);
8142  if (NI_LOGAN_RETCODE_SUCCESS != retval)
8143  {
8144  ni_log(NI_LOG_ERROR, "ERROR: ni_logan_encoder_session_close failed: blk_io_handle: %" PRIx64 ", hw_id, %u, xcoder_inst_id: %d\n", (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id, p_ctx->session_id);
8145  }
8146 
8148  }
8149 
8150  END:
8151  ni_logan_aligned_free(p_init_frames_param);
8152 
8153  ni_log(NI_LOG_TRACE, "%s(): exit\n", __FUNCTION__);
8154 
8155  return retval;
8156 }
8157 
8159 {
8160 #ifdef __linux__
8161  struct sched_param sched_param;
8162 
8163  //struct sched_param sched_param;
8164  // Linux has a wide variety of signals, Windows has a few.
8165  // A large number of signals will interrupt the thread, which will cause heartbeat command interval more than 1 second.
8166  // So just mask the unuseful signals in Linux
8167  //sigset_t signal;
8168  //sigfillset(&signal);
8169  //ni_logan_pthread_sigmask(SIG_BLOCK, &signal, NULL);
8170 
8171  /* set up schedule priority
8172  * first try to run with RR mode.
8173  * if fails, try to set nice value.
8174  * if fails either, ignore it and run with default priority.
8175  */
8176  if (((sched_param.sched_priority = sched_get_priority_max(SCHED_RR)) == -1) ||
8177  sched_setscheduler(syscall(SYS_gettid), SCHED_RR, &sched_param) < 0)
8178  {
8179  ni_log(NI_LOG_TRACE, "%s cannot set scheduler: %s\n",
8180  __FUNCTION__, strerror(errno));
8181  if (setpriority(PRIO_PROCESS, 0, -20) != 0)
8182  {
8183  ni_log(NI_LOG_TRACE, "%s cannot set nice value: %s\n",
8184  __FUNCTION__, strerror(errno));
8185  }
8186  }
8187 #endif
8188 }
8189 
8190 #ifndef _WIN32
8191 /*!*****************************************************************************
8192  * \brief Get an address offset from a hw descriptor
8193  *
8194  * \param[in] p_ctx ni_session_context_t to be referenced
8195  * \param[in] hwdesc Pointer to caller allocated niFrameSurface1_t
8196  * \param[in] hwaddress DDR address in FW
8197  * \param[out] p_offset Value of offset
8198  *
8199  * \return On success NI_RETCODE_SUCCESS
8200  * On failure NI_RETCODE_INVALID_PARAM
8201  ******************************************************************************/
8203  unsigned int *p_offset, unsigned int hwaddress)
8204 {
8205  if (!hwdesc)
8206  {
8207  ni_log(NI_LOG_ERROR, "ERROR: %s() passed null parameter\n", __func__);
8209  }
8210 
8211  *p_offset = hwaddress - 0xD0000000;
8212 
8213  return NI_LOGAN_RETCODE_SUCCESS;
8214 }
8215 #endif
8216 
8217 /*!******************************************************************************
8218 * \brief Dump firmware logs
8219 *
8220 * \param ni_logan_session_context_t p_ctx - xcoder Context
8221 * void* p_data - log data
8222 * gen_log_file - generate log files
8223 *
8224 * \return - NI_LOGAN_RETCODE_SUCCESS on success,
8225 * NI_LOGAN_RETCODE_FAILURE, NI_LOGAN_RETCODE_INVALID_PARAM,
8226 * NI_LOGAN_RETCODE_ERROR_NVME_CMD_FAILED on failure
8227 *******************************************************************************/
8229  void* p_data,
8230  bool gen_log_file)
8231 {
8233  uint32_t ui32LBA = GET_CPU_LOGS_IN_4K;
8234  uint32_t data_len = NI_LOGAN_CPU_LOG_BUFFER_SIZE;
8235  FILE *p_file = NULL;
8236 
8237  if (!p_ctx || !p_data)
8238  {
8239  ni_log(NI_LOG_ERROR, "%s:():%d: ERROR invalid pointer p_ctx %p p_data %p\n",
8240  __func__, __LINE__, p_ctx, p_data);
8242  }
8243 
8244  memset(p_data, 0, data_len);
8245  *(uint8_t *)p_data = 0x55;
8246 
8247  retval = ni_logan_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle,
8248  p_data, NI_LOGAN_CPU_LOG_BUFFER_SIZE, ui32LBA);
8249 
8250  if (NI_LOGAN_RETCODE_SUCCESS != retval)
8251  {
8252  ni_log(NI_LOG_ERROR, "ERROR ni_dump_logs(): nvme read command failed, blk_io_handle:"
8253  "%" PRIx64 ", hw_id, %d\n", (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id);
8255  }
8256  else if (gen_log_file)
8257  {
8258  //generate log file e.g. nvme_slot_0.bin
8259  char filename[32] = "nvme_slot_";
8260  bool pcie_id_name = false;
8261  char devFilePath[1024] = {0};
8262 #ifdef __linux__
8263  char devFDPath[1024] = {0};
8264  char pcie[64] = {0};
8265  char domain[5] = {0}, slot[3] = {0}, dev[3] = {0}, func[2] = {0};
8266  //p_ctx->blk_dev_name might be empty so look up the file name
8267  snprintf(devFDPath, sizeof(devFDPath), "/proc/self/fd/%d", p_ctx->blk_io_handle);
8268  ssize_t len = readlink(devFDPath, devFilePath, sizeof(devFilePath)-1);
8269  if (len != -1) {
8270  devFilePath[len] = '\0';
8271  }
8272  if (strstr(devFilePath, "/dev/nvme") != NULL)
8273  {
8274  ni_logan_get_dev_pcie_addr(devFilePath, pcie, domain, slot, dev, func);
8275  if (strlen(pcie) > 0 && strlen(slot) > 0 && strlen(domain) > 0)
8276  {
8277  strcat(filename, slot);
8278  pcie_id_name = true;
8279  }
8280  }
8281 #endif
8282  if (!pcie_id_name)
8283  {
8284  ni_log(NI_LOG_INFO, "%s:():%d: For dev %d can't look up PCI domain and slot info. Defaulting to slot=hw_id\n",
8285  __func__, __LINE__, p_ctx->blk_io_handle);
8286  char num[4] = {0};
8287  snprintf(num, 4, "%d", p_ctx->hw_id);
8288  strcat(filename, num);
8289  }
8290  strcat(filename, ".log");
8291  ni_log(NI_LOG_INFO, "For dev %d %s creating file %s\n",
8292  p_ctx->blk_io_handle, devFilePath, filename);
8293  p_file = fopen(filename, "wb");
8294  if (p_file)
8295  {
8296  /* Write out the stream header */
8297  if (fwrite((uint8_t *)p_data ,
8298  data_len, 1, p_file) != 1)
8299  {
8300  ni_log(NI_LOG_ERROR, "%s:():%d: Error: writing data %u bytes error!\n",
8301  __func__, __LINE__, data_len);
8302  ni_log(NI_LOG_ERROR, "Error: ferror rc = %d\n", ferror(p_file));
8303  retval = NI_LOGAN_RETCODE_FAILURE;
8304  }
8305  if (fflush(p_file))
8306  {
8307  ni_log(NI_LOG_ERROR, "Error: writing data frame flush failed! errno %d\n",
8308  ferror(p_file));
8309  retval = NI_LOGAN_RETCODE_FAILURE;
8310  }
8311  fclose(p_file);
8312  }
8313  else
8314  {
8315  ni_log(NI_LOG_ERROR, "%s:():%d: Error: cannot open %s\n",
8316  __func__, __LINE__, filename);
8317  retval = NI_LOGAN_RETCODE_FAILURE;
8318  }
8319  }
8320  return retval;
8321 }
NETINT audio/video related utility functions.
#define NI_LOGAN_MAX_1080P_FPS
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_ERROR_INVALID_SESSION
@ NI_LOGAN_RETCODE_PARAM_ERROR_FRATE
@ NI_LOGAN_RETCODE_PARAM_INVALID_VALUE
@ NI_LOGAN_RETCODE_PARAM_ERROR_CONF_WIN_TOP
@ NI_LOGAN_RETCODE_PARAM_ERROR_USR_RMD_ENC_PARAM
@ NI_LOGAN_RETCODE_PARAM_ERROR_GOP_PRESET
@ NI_LOGAN_RETCODE_PARAM_ERROR_RCENABLE
@ 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_ERROR_RESOURCE_UNAVAILABLE
@ NI_LOGAN_RETCODE_PARAM_ERROR_MX_QP
@ NI_LOGAN_RETCODE_PARAM_ERROR_CUSIZE_MODE_8X8_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_PIC_HEIGHT
@ NI_LOGAN_RETCODE_PARAM_ERROR_INTRA_PERIOD
@ NI_LOGAN_RETCODE_ERROR_VPU_RECOVERY
@ NI_LOGAN_RETCODE_PARAM_ERROR_BRATE
@ 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_MX_DELTA_QP
@ 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_NVME_SC_VPU_RSRC_INSUFFICIENT
struct _ni_logan_instance_status_info ni_logan_instance_status_info_t
#define END
#define NI_LOGAN_APP_ENC_FRAME_META_DATA_SIZE
@ nvme_cmd_xcoder_write
@ nvme_cmd_xcoder_read
#define NI_LOGAN_MAX_NUM_DATA_POINTERS
#define NI_LOGAN_MAX_CONTEXTS_PER_HW_INSTANCE
#define ni_logan_assert(expression)
#define NI_LOGAN_CPU_LOG_BUFFER_SIZE
#define NI_ERRNO
#define NI_LOGAN_FIFO_SZ
#define NI_LOGAN_MAX_FORCE_FRAME_TABLE_SIZE
#define NI_LOGAN_MEM_PAGE_ALIGNMENT
#define NETINT_PCI_VENDOR_ID
Definition: ni_defs_logan.h:80
ni_logan_device_type_t
@ NI_LOGAN_DEVICE_TYPE_UPLOAD
@ NI_LOGAN_DEVICE_TYPE_ENCODER
@ NI_LOGAN_DEVICE_TYPE_DECODER
#define LRETURN
#define NI_LOGAN_FW_META_DATA_SZ
@ NI_LOGAN_DECODE_BUFFERS_FLUSHING
@ NI_LOGAN_DECODE_FLUSH_BUFFER_OFF
#define NI_LOGAN_MAX_DEVICES_PER_HW_INSTANCE
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...
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.
#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.
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_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_event_handle_t ni_logan_create_event(void)
Create event and returnes event handle if successful.
Main NETINT device API header file provides the ability to communicate with NI T-408 type hardware tr...
#define NI_LOGAN_DEFAULT_CU_SIZE_MODE
#define NI_LOGAN_MAX_INTRA_QP
#define NI_LOGAN_DEFAULT_INTRA_QP
#define NI_CC_SEI_BYTE5
#define NI_LOGAN_RETRY_INTERVAL_200US
#define NI_LOGAN_MIN_MAX_DELTA_QP
struct _ni_logan_hwframe_surface ni_logan_hwframe_surface_t
#define NI_CC_SEI_TRAILER_LEN
#define NI_HDR10P_SEI_BYTE2
#define NI_CC_SEI_BYTE6
#define NI_LOGAN_MAX_GOP_PRESET_IDX
#define NI_LOGAN_MAX_VUI_SIZE
#define NI_HDR10P_SEI_BYTE6
#define NI_LOGAN_PARAM_MAX_HEIGHT
#define NI_LOGAN_MAX_ENC_SESSION_OPEN_QUERY_RETRIES
@ NI_LOGAN_CODEC_HW_UPLOAD
@ NI_LOGAN_CODEC_HW_ENABLE
@ NI_LOGAN_CODEC_HW_DOWNLOAD
@ NI_LOGAN_CODEC_HW_NONE
#define NI_CC_SEI_HDR_H264_LEN
#define NI_HDR10P_SEI_BYTE0
#define NI_LOGAN_MIN_INTRA_QP
#define NI_LOGAN_PARAM_MAX_WIDTH
ni_logan_h265_sei_user_data_type_t
@ NI_LOGAN_H265_USERDATA_FLAG_UNREGISTERED_SUF
@ NI_LOGAN_H265_USERDATA_FLAG_ITU_T_T35_SUF_1
@ NI_LOGAN_H265_USERDATA_FLAG_MASTERING_COLOR_VOL
@ NI_LOGAN_H265_USERDATA_FLAG_VUI
@ NI_LOGAN_H265_USERDATA_FLAG_ITU_T_T35_SUF_2
@ NI_LOGAN_H265_USERDATA_FLAG_UNREGISTERED_PRE
@ NI_LOGAN_H265_USERDATA_FLAG_ITU_T_T35_PRE_2
@ NI_LOGAN_H265_USERDATA_FLAG_ALTERNATIVE_TRANSFER_CHARACTERISTICS
@ NI_LOGAN_H265_USERDATA_FLAG_ITU_T_T35_SUF
@ NI_LOGAN_H265_USERDATA_FLAG_ITU_T_T35_PRE_1
@ NI_LOGAN_H265_USERDATA_FLAG_ITU_T_T35_PRE
@ NI_LOGAN_H265_USER_DATA_FLAG_CONTENT_LIGHT_LEVEL_INFO
#define NI_LOGAN_MAX_ENC_SESSION_READ_QUERY_RETRIES
#define NI_LOGAN_MAX_SESSION_CLOSE_RETRIES
#define NI_LOGAN_MAX_DEC_SESSION_READ_QUERY_EOS_RETRIES
#define NI_CC_SEI_BYTE2
#define NI_LOGAN_SESSION_CLOSE_RETRY_INTERVAL_US
#define NI_LOGAN_RETRY_INTERVAL_100US
#define NI_LOGAN_ENC_SESSION_OPEN_RETRY_INTERVAL_US
#define NI_HDR10P_SEI_HDR_H264_LEN
#define NI_LOGAN_ENC_REPEAT_HEADERS_ALL_I_FRAMES
@ LOGAN_PIC_TYPE_I
#define NI_CC_SEI_BYTE1
#define NI_LOGAN_PARAM_MIN_WIDTH
#define NI_HDR10P_SEI_BYTE1
#define NI_LOGAN_MAX_DEC_SESSION_READ_QUERY_RETRIES
#define NI_LOGAN_NOPTS_VALUE
#define NI_CC_SEI_BYTE4
#define NI_CC_SEI_BYTE7
#define NI_LOGAN_MAX_MAX_DELTA_QP
#define NI_HDR10P_SEI_HDR_HEVC_LEN
#define NI_CC_SEI_BYTE0
#define NI_LOGAN_MAX_ENC_SESSION_WRITE_QUERY_RETRIES
#define NI_HDR10P_SEI_BYTE5
#define NI_LOGAN_MAX_GOP_NUM
@ LOGAN_SESSION_RUN_STATE_SEQ_CHANGE_DRAINING
@ LOGAN_SESSION_RUN_STATE_NORMAL
#define NI_LOGAN_MAX_DEC_SESSION_WRITE_QUERY_RETRIES
#define NI_LOGAN_DEFAULT_MAX_DELTA_QP
#define NI_CC_SEI_BYTE3
#define NI_HDR10P_SEI_BYTE3
#define NI_LOGAN_ENC_REPEAT_HEADERS_ALL_KEY_FRAMES
@ NI_LOGAN_CODEC_FORMAT_H265
@ NI_LOGAN_CODEC_FORMAT_H264
#define NI_LOGAN_INVALID_SESSION_ID
#define NI_LOGAN_PARAM_MIN_HEIGHT
#define NI_HDR10P_SEI_BYTE4
#define NI_CC_SEI_HDR_HEVC_LEN
#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.
ni_logan_retcode_t ni_logan_check_ratecontrol_params(ni_logan_encoder_config_t *p_cfg, char *p_param_err, uint32_t max_err_len)
check the range of rate control parameters
int ni_logan_encoder_session_read(ni_logan_session_context_t *p_ctx, ni_logan_packet_t *p_packet)
Retrieve an encoded packet from encoder.
ni_logan_retcode_t ni_logan_query_stream_info(ni_logan_session_context_t *p_ctx, ni_logan_device_type_t device_type, ni_logan_instance_mgr_stream_info_t *p_stream_info, bool is_hw)
Query a particular xcoder instance to get Stream Info data.
ni_logan_retcode_t ni_logan_config_instance_set_encoder_params(ni_logan_session_context_t *p_ctx)
Send a p_config command to configure encoding parameters.
_ni_logan_t35_sei_mesg_type
@ NI_LOGAN_T35_SEI_HDR10_PLUS
@ NI_LOGAN_T35_SEI_CLOSED_CAPTION
ni_logan_retcode_t ni_logan_get_memory_offset(ni_logan_session_context_t *p_ctx, const ni_logan_hwframe_surface_t *hwdesc, unsigned int *p_offset, unsigned int hwaddress)
Get an address offset from a hw descriptor.
ni_logan_retcode_t ni_logan_config_instance_sos(ni_logan_session_context_t *p_ctx, ni_logan_device_type_t device_type)
Send a p_config command for Start Of Stream.
void ni_logan_params_print(void *const p_codec_params, ni_logan_device_type_t device_type)
Print xcoder user configurations.
ni_logan_retcode_t ni_logan_query_status_info(ni_logan_session_context_t *p_ctx, ni_logan_device_type_t device_type, ni_logan_instance_status_info_t *p_status_info, int rc, int opcode)
Query a particular xcoder instance to get status Info data.
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.
ni_logan_retcode_t ni_logan_validate_custom_template(ni_logan_session_context_t *p_ctx, ni_logan_encoder_config_t *p_cfg, ni_logan_encoder_params_t *p_src, char *p_param_err, uint32_t max_err_len)
Perform validation on custom parameters (Rev. B)
ni_logan_retcode_t ni_logan_config_instance_rw(ni_logan_session_context_t *p_ctx, ni_logan_inst_config_rw_type_t rw_type, uint8_t enable, uint8_t hw_action, uint16_t frame_id)
Configure the read/write pipe for a session Use HW frame index to read/write the YUV from/to HW.
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.
void ni_logan_set_default_template(ni_logan_session_context_t *p_ctx, ni_logan_encoder_config_t *p_config)
Setup and initialize all xcoder configuration to default (Rev. B)
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_query_instance_buf_info(ni_logan_session_context_t *p_ctx, ni_logan_instance_buf_info_rw_type_t rw_type, ni_logan_device_type_t device_type, ni_logan_instance_buf_info_t *p_inst_buf_info, bool is_hw)
Query a particular xcoder instance to get buffer/data Info data.
ni_logan_retcode_t ni_logan_dump_logs(ni_logan_session_context_t *p_ctx, void *p_data, bool gen_log_file)
Dump firmware logs.
int ni_logan_create_frame(ni_logan_frame_t *p_frame, uint32_t read_length, uint64_t *p_frame_offset, bool is_hw_frame)
Get info from received p_frame.
ni_logan_retcode_t ni_logan_uplosader_session_close(ni_logan_session_context_t *p_ctx)
Close an xcoder upload instance.
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.
ni_logan_retcode_t ni_logan_send_session_keep_alive(uint32_t session_id, ni_device_handle_t device_handle, ni_event_handle_t event_handle, void *p_data)
send a keep alive message to firmware
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
#define CHECK_VPU_RECOVERY(ret)
ni_logan_retcode_t ni_logan_decoder_session_close(ni_logan_session_context_t *p_ctx, int eos_recieved)
Close a xcoder decoder instance.
enum _ni_logan_t35_sei_mesg_type ni_logan_t35_sei_mesg_type_t
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.
int ni_logan_query_general_status(ni_logan_session_context_t *p_ctx, ni_logan_device_type_t device_type, ni_logan_instance_mgr_general_status_t *p_gen_status)
Query a particular xcoder instance to get GeneralStatus data.
ni_logan_retcode_t ni_logan_check_common_params(ni_logan_t408_config_t *p_param, ni_logan_encoder_params_t *p_src, char *p_param_err, uint32_t max_err_len)
check the range of common parameters
ni_logan_retcode_t ni_logan_config_instance_eos(ni_logan_session_context_t *p_ctx, ni_logan_device_type_t device_type)
Send a p_config command for End Of Stream.
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.
ni_logan_retcode_t ni_logan_config_instance_flush(ni_logan_session_context_t *p_ctx, ni_logan_device_type_t device_type)
Send a p_config command for Flush Of Stream.
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.
void ni_logan_set_custom_template(ni_logan_session_context_t *p_ctx, ni_logan_encoder_config_t *p_cfg, ni_logan_encoder_params_t *p_src)
Setup all xcoder configurations with custom parameters (Rev. B)
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.
struct _ni_logan_inst_config_rw ni_logan_inst_config_rw_t
ni_logan_inst_config_rw_type_t
@ INST_WRITE_CONFIG
@ INST_READ_CONFIG
struct _ni_logan_metadata_enc_bstream ni_logan_metadata_enc_bstream_t
@ 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
struct _ni_logan_instance_debugInfo ni_logan_instance_debugInfo_t
@ ni_logan_xcoder_general_error
@ ni_logan_xcoder_resource_insufficient
@ ni_logan_xcoder_resource_recovery
@ ni_logan_xcoder_request_success
@ ni_logan_xcoder_request_pending
struct _ni_logan_instance_buf_info ni_logan_instance_buf_info_t
struct _ni_logan_instance_mgr_general_status ni_logan_instance_mgr_general_status_t
ni_logan_instance_buf_info_rw_type_t
@ INST_BUF_INFO_RW_WRITE
@ INST_BUF_INFO_RW_READ
@ INST_BUF_INFO_R_ACQUIRE
@ INST_BUF_INFO_RW_UPLOAD
struct _ni_logan_encoder_config_t ni_logan_encoder_config_t
struct _ni_logan_instance_mgr_stream_info ni_logan_instance_mgr_stream_info_t
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
int32_t ni_logan_nvme_send_write_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 write command.
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 WRITE_INSTANCE_W(hw, sid, instance)
@ nvme_admin_cmd_xcoder_config
@ nvme_admin_cmd_xcoder_query
#define QUERY_INSTANCE_DEBUG_DATA_R(sid, instance)
#define CONFIG_INSTANCE_SetEOS_W(sid, instance)
#define CONFIG_INSTANCE_InitFramePool_W(sid, instance)
#define QUERY_INSTANCE_UPLOAD_ID_R(hw, sid, instance)
#define NI_LOGAN_NO_CHECK_TS_NVME_CMD_OP
#define CLOSE_SESSION_R(sid, instance)
#define QUERY_GENERAL_GET_STATUS_R(instance)
#define CONFIG_INSTANCE_SetFlush_W(sid, instance)
#define GET_CPU_LOGS_IN_4K
#define WRITE_METADATA_W(hw, sid, instance)
#define OPEN_GET_SID_R(hw, instance)
#define CONFIG_INSTANCE_FrameIdx_W(sid, instance)
#define QUERY_INSTANCE_RBUFF_SIZE_R(hw, sid, instance)
#define QUERY_INSTANCE_STREAM_INFO_R(hw, sid, instance)
#define CONFIG_SESSION_KeepAlive_W(sid)
#define QUERY_INSTANCE_CUR_STATUS_INFO_R(sid, instance)
#define OPEN_SESSION_W(hw, sid, instance)
#define QUERY_INSTANCE_ACQUIRE_BUF(hw, sid, instance)
#define CONFIG_SESSION_KeepAliveTimeout_W(sid)
#define CONFIG_INSTANCE_SetEncPara_W(sid, instance)
#define CONFIG_INSTANCE_SetPktSize_W(hw, sid, instance)
#define READ_INSTANCE_R(hw, sid, instance)
#define QUERY_INSTANCE_DEBUG_INFO_R(sid, instance)
#define CONFIG_SESSION_Write_W(sid)
#define CONFIG_INSTANCE_RecycleBuf_W(sid, instance)
#define CONFIG_INSTANCE_SetSOS_W(hw, sid, instance)
#define QUERY_INSTANCE_WBUFF_SIZE_R(hw, sid, instance)
#define NI_LOGAN_DATA_BUFFER_LEN
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_context(ni_logan_device_context_t *p_device_context)
Free previously allocated device context.
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_get_dev_pcie_addr(char *device_name, char *pcie, char *domain, char *slot, char *dev, char *func)
get PCIe address information from device name
void ni_logan_timestamp_scan_cleanup(ni_logan_timestamp_table_t *pts_list, ni_logan_timestamp_table_t *dts_list, ni_logan_queue_buffer_pool_t *p_buffer_pool)
Timestamp queue clean up.
int32_t ni_logan_dec_fme_buffer_pool_initialize(ni_logan_session_context_t *p_ctx, int32_t number_of_buffers, int width, int height, int height_align, int factor)
decoder frame buffer pool init & free
int32_t ni_logan_posix_memalign(void **pp_memptr, size_t alignment, size_t size)
ni_logan_retcode_t ni_logan_queue_free(ni_logan_queue_t *p_queue, ni_logan_queue_buffer_pool_t *p_buffer_pool)
Free xcoder queue.
void ni_logan_buffer_pool_free(ni_logan_queue_buffer_pool_t *p_buffer_pool)
free buffer memory pool
uint64_t ni_logan_gettime_ns(void)
Definition: ni_util_logan.c:81
ni_logan_retcode_t ni_logan_timestamp_register(ni_logan_queue_buffer_pool_t *p_buffer_pool, ni_logan_timestamp_table_t *p_table, int64_t timestamp, uint64_t data_info)
Register timestamp in timestamp/frameoffset table.
void ni_logan_usleep(int64_t usec)
ni_logan_retcode_t ni_logan_timestamp_init(ni_logan_session_context_t *p_ctx, ni_logan_timestamp_table_t **pp_table, const char *name)
Initialize timestamp handling.
void ni_logan_dec_fme_buffer_pool_free(ni_logan_buf_pool_t *p_buffer_pool)
free decoder frame buffer pool
void ni_logan_overwrite_specified_pos(uint8_t *buf, int pos, int value)
overwrite the 32 bits of integer value at bit position pos
int32_t ni_logan_gettimeofday(struct timeval *p_tp, void *p_tzp)
Definition: ni_util_logan.c:56
ni_logan_retcode_t ni_logan_timestamp_get_with_threshold(ni_logan_timestamp_table_t *p_table, uint64_t frame_info, int64_t *p_timestamp, int32_t threshold, int32_t print, ni_logan_queue_buffer_pool_t *p_buffer_pool)
Retrieve timestamp from table based on frame offset info with respect to threshold.
Exported utility routines definition.
#define LOGAN_XCODER_MAX_ENC_PIC_WIDTH
Definition: ni_util_logan.h:68
#define NI_LOGAN_DEC_FRAME_BUF_POOL_SIZE_INIT
Definition: ni_util_logan.h:71
#define LOGAN_XCODER_MAX_ENC_PIC_HEIGHT
Definition: ni_util_logan.h:69
#define LOGAN_XCODER_MIN_ENC_PIC_WIDTH
Definition: ni_util_logan.h:66
#define ni_logan_aligned_free(p_memptr)
#define LOGAN_XCODER_MIN_ENC_PIC_HEIGHT
Definition: ni_util_logan.h:67
#define LOGAN_XCODER_MAX_NUM_TEMPORAL_LAYER
Definition: ni_util_logan.h:62
#define NI_LOGAN_VPU_FREQ
Definition: ni_util_logan.h:76
#define LOGAN_XCODER_FRAME_OFFSET_DIFF_THRES
Definition: ni_util_logan.h:59
payload format of HDR SEI content light level info
ni_logan_gop_params_t pic_param[NI_LOGAN_MAX_GOP_NUM]
decoded payload format of HDR SEI mastering display colour volume
ni_logan_decoder_input_params_t dec_input_params
ni_logan_hw_capability_t xcoder_devices[NI_LOGAN_MAX_DEVICES_PER_HW_INSTANCE]
uint8_t ui8VuiRbsp[NI_LOGAN_MAX_VUI_SIZE]
ni_logan_t408_config_t niParamT408
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
uint8_t ui8VuiRbsp[NI_LOGAN_MAX_VUI_SIZE]
unsigned int sei_hdr_mastering_display_color_vol_offset
unsigned int sei_hdr_content_light_level_info_offset
unsigned int sei_hdr_plus_len
uint32_t data_len[NI_LOGAN_MAX_NUM_DATA_POINTERS]
unsigned int sei_hdr_plus_offset
unsigned int extra_data_len
unsigned int sei_total_len
unsigned int sei_cc_offset
unsigned int sei_user_data_unreg_len
ni_logan_pic_type_t ni_logan_pict_type
uint8_t use_cur_src_as_long_term_pic
ni_logan_codec_format_t src_codec
unsigned int sei_hdr_content_light_level_info_len
void * p_data[NI_LOGAN_MAX_NUM_DATA_POINTERS]
unsigned int sei_hdr_mastering_display_color_vol_len
unsigned int sei_user_data_unreg_offset
unsigned int sei_alt_transfer_characteristics_len
unsigned int sei_alt_transfer_characteristics_offset
union _ni_logan_inst_config_rw::@5 uHWAccessField
ni_logan_instance_upload_ret_hwdesc_t hw_inst_ind
union _ni_logan_metadata_common::@8 ui64_data
ni_logan_hwframe_surface_t hwdesc
ni_logan_metadata_common_t metadata_common
ni_logan_metadata_common_t metadata_common
uint8_t fw_branch_name[256]
ni_logan_all_custom_sei_t * p_all_custom_sei
uint32_t offset
uint32_t size
uint8_t itu_t_t35_hdr10p_sei_hdr_hevc[NI_HDR10P_SEI_HDR_HEVC_LEN]
int64_t pts_offsets[NI_LOGAN_FIFO_SZ]
ni_logan_load_query_t load_query
ni_event_handle_t thread_event_handle
ni_logan_serial_num_t d_serial_number
ni_device_handle_t sender_handle
ni_device_handle_t device_handle
uint64_t pkt_offsets_index_min[NI_LOGAN_FIFO_SZ]
ni_logan_lat_meas_q_t * frame_time_q
ni_device_handle_t auto_dl_handle
uint64_t pkt_offsets_index[NI_LOGAN_FIFO_SZ]
uint8_t sei_trailer[NI_CC_SEI_TRAILER_LEN]
int flags_array[NI_LOGAN_FIFO_SZ]
uint8_t itu_t_t35_cc_sei_hdr_hevc[NI_CC_SEI_HDR_HEVC_LEN]
ni_logan_session_run_state_t session_run_state
uint8_t itu_t_t35_cc_sei_hdr_h264[NI_CC_SEI_HDR_H264_LEN]
char blk_xcoder_name[LOGAN_MAX_CHAR_IN_DEVICE_NAME]
ni_device_handle_t blk_io_handle
ni_logan_queue_buffer_pool_t * buffer_pool
uint64_t frame_pkt_offset
Params used in VFR mode Done///.
ni_logan_buf_pool_t * dec_fme_buf_pool
int64_t force_frame_pts_table[NI_LOGAN_MAX_FORCE_FRAME_TABLE_SIZE]
uint8_t itu_t_t35_hdr10p_sei_hdr_h264[NI_HDR10P_SEI_HDR_H264_LEN]
ni_logan_instance_status_info_t session_stats
ni_logan_all_custom_sei_t * pkt_custom_sei[NI_LOGAN_FIFO_SZ]
char dev_xcoder_name[LOGAN_MAX_CHAR_IN_DEVICE_NAME]
ni_logan_serial_num_t e_serial_number
int32_t fixedBitRatio[NI_LOGAN_MAX_GOP_NUM]
ni_logan_custom_gop_params_t custom_gop_params