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