libxcoder  5.2.0
ni_xcoder_multithread_transcode.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_xcoder_multithread_transcode.c
24  *
25  * \brief Multi-threaded video transcoding and filtering demo application
26  * directly using Netint Libxcoder API
27  ******************************************************************************/
28 
29 #include "ni_generic_utils.h"
30 #include "ni_decode_utils.h"
31 #include "ni_encode_utils.h"
32 #include "ni_filter_utils.h"
33 #include "ni_log.h"
34 #include "ni_util.h"
35 
36 #ifdef _WIN32
37 #include "ni_getopt.h"
38 #elif __linux__ || __APPLE__
39 #include <getopt.h>
40 #include <unistd.h>
41 #endif
42 
43 static void print_usage(void)
44 {
46  "Multi-threaded video transcoding demo application directly using Netint Libxcoder version %s\n"
47  "Usage: ni_xcoder_multithread_transcode [options]\n"
48  "\n"
49  "options:\n"
50  "-h | --help Show this message.\n"
51  "-v | --version Print version info.\n"
52  "-i | --input (Required) Input file path.\n"
53  "-o | --output (Required) Output file path.\n"
54  " Can be specified multiple (max %d) times\n"
55  " to run multiple encoding instances simultaneously.\n"
56  "-m | --dec-codec (Required) Decoder codec format. Must match the codec of input file.\n"
57  " [a|avc, h|hevc, v|vp9]\n"
58  "-n | --enc-codec (Required) Encoder codec format.\n"
59  " [a|avc, h|hevc, x|av1] (x is in ivf container format)\n"
60  "-l | --loglevel Set loglevel of this application and libxcoder API.\n"
61  " [none, fatal, error, info, debug, trace]\n"
62  " (Default: info)\n"
63  "-c | --card Set card index to use.\n"
64  " See `ni_rsrc_mon` for info of cards on system.\n"
65  " (Default: 0)\n"
66  "-r | --repeat To loop input X times. Must be a positive integer\n"
67  " (Default: 1)\n"
68  "-d | --decoder-params Decoding params. See \"Decoding Parameters\" chapter in\n"
69  " QuadraIntegration&ProgrammingGuide*.pdf for help.\n"
70  " (Default: \"\")\n"
71  "-e | --encoder-params Encoding params. See \"Encoding Parameters\" chapter in\n"
72  " QuadraIntegration&ProgrammingGuide*.pdf for help.\n"
73  " Can be specified multiple (max %d) times,\n"
74  " must match the number of -o specified.\n"
75  " (Default: \"\")\n"
76  "-g | --encoder-gop Custom GOP for encoding. See \"Custom Gop Structure\" chapter in\n"
77  " QuadraIntegration&ProgrammingGuide*.pdf for help.\n"
78  " gopPresetIdx must be set to 0 to be in effect.\n"
79  " (Default: \"\")\n"
80  "-u | --user-data-sei-passthru (No argument) Enable user data unregistered SEI passthrough when specified\n"
81  "-f | --vf Video filter params. The only supported filters in this demo are:\n"
82  " ni_quadra_scale - supported params [width, height, format]\n"
83  " e.g. ni_quadra_scale=width=1280:height=720:format=yuv420p\n"
84  " ni_quadra_drawbox - supported params [x, y, width, height]\n"
85  " e.g. ni_quadra_drawbox=x=300:y=150:width=600:height=400\n"
86  " (Default: \"\")\n"
88 }
89 
90 int main(int argc, char *argv[])
91 {
92  int i, ret = 0;
93  ni_demo_context_t ctx = {0};
94  char in_filename[FILE_NAME_LEN] = {0};
95  char out_filename[MAX_OUTPUT_FILES][FILE_NAME_LEN] = {0};
96  FILE *output_fp[MAX_OUTPUT_FILES] = {0};
97  int o_index = 0, e_index = 0, g_index = 0;
98  int output_total = 0;
99  int input_width = 0, input_height = 0, output_width = 0, output_height = 0, bit_depth = 8;
100  int dec_codec_format = -1, enc_codec_format = -1;
101  ni_log_level_t log_level;
102  int xcoderGUID = 0;
103  char *n;
104  char dec_conf_params[2048] = {0};
105  char filter_conf_params[2048] = {0};
106  char enc_conf_params[MAX_OUTPUT_FILES][2048] = {0};
107  char enc_gop_params[MAX_OUTPUT_FILES][2048] = {0};
108  int user_data_sei_passthru = 0;
109  ni_h264_sps_t avc_sps = {0};
110  ni_h265_sps_t hevc_sps = {0};
111  ni_vp9_header_info_t vp9_info = {0};
112  ni_xcoder_params_t *p_dec_api_param = NULL;
113  ni_xcoder_params_t *p_enc_api_param = NULL;
114  ni_session_context_t dec_ctx = {0};
115  ni_session_context_t enc_ctx[MAX_OUTPUT_FILES] = {0};
116  ni_session_context_t sca_ctx = {0};
117  ni_session_context_t crop_ctx = {0};
118  ni_session_context_t pad_ctx = {0};
119  ni_session_context_t ovly_ctx = {0};
120  ni_session_context_t fmt_ctx = {0};
121  void *p_stream_info = NULL;
122  int fps_num = 30, fps_den = 1, bitrate = 200000;
123  ni_frame_t *p_ni_frame = NULL;
124  niFrameSurface1_t *p_hwframe = NULL;
125  ni_scale_params_t scale_params = {0};
126  ni_drawbox_params_t drawbox_params = {0};
127  ni_test_frame_list_t frame_list = {0};
128  ni_pthread_t dec_send_tid, dec_recv_tid, enc_send_tid, enc_recv_tid;
133  ni_pix_fmt_t enc_pix_fmt = NI_PIX_FMT_YUV420P;
134 
135  int opt;
136  int opt_index;
137  const char *opt_string = "hvi:o:m:n:l:c:r:d:e:g:uf:";
138  static struct option long_options[] = {
139  {"help", no_argument, NULL, 'h'},
140  {"version", no_argument, NULL, 'v'},
141  {"input", required_argument, NULL, 'i'},
142  {"output", required_argument, NULL, 'o'},
143  {"dec-codec", required_argument, NULL, 'n'},
144  {"enc-codec", required_argument, NULL, 'm'},
145  {"loglevel", required_argument, NULL, 'l'},
146  {"card", required_argument, NULL, 'c'},
147  {"repeat", required_argument, NULL, 'r'},
148  {"decoder-params", required_argument, NULL, 'd'},
149  {"encoder-params", required_argument, NULL, 'e'},
150  {"encoder-gop", required_argument, NULL, 'g'},
151  {"user-data-sei-passthru", no_argument, NULL, 'u'},
152  {"vf", required_argument, NULL, 'f'},
153  {NULL, 0, NULL, 0},
154  };
155 
156  while ((opt = getopt_long(argc, argv, opt_string, long_options, &opt_index)) != -1)
157  {
158  switch (opt)
159  {
160  case 'h':
161  print_usage();
162  ret = 0;
163  goto end;
164  case 'v':
165  print_version();
166  ret = 0;
167  goto end;
168  case 'i':
169  strcpy(in_filename, optarg);
170  break;
171  case 'o':
172  if (o_index == MAX_OUTPUT_FILES)
173  {
174  ni_log(NI_LOG_ERROR, "Error: number of output files cannot exceed %d\n", MAX_OUTPUT_FILES);
175  ret = -1;
176  goto end;
177  }
178 
179  for (i = 0; i < o_index; i++)
180  {
181  if (0 == strcmp(out_filename[i], optarg))
182  {
183  ni_log(NI_LOG_ERROR, "Error: output file names must be unique: %s\n", optarg);
184  ret = -1;
185  goto end;
186  }
187  }
188 
189  strcpy(out_filename[o_index], optarg);
190  o_index++;
191  break;
192  case 'm':
193  // Accept both upper and lower case
194  for (i = 0; i < strlen(optarg); i++)
195  {
196  optarg[i] = (char)tolower((unsigned char)optarg[i]);
197  }
198  if (strcmp(optarg, "a") == 0 || strcmp(optarg, "avc") == 0)
199  {
200  dec_codec_format = NI_CODEC_FORMAT_H264;
201  }
202  else if (strcmp(optarg, "h") == 0 || strcmp(optarg, "hevc") == 0)
203  {
204  dec_codec_format = NI_CODEC_FORMAT_H265;
205  }
206  else if (strcmp(optarg, "v") == 0 || strcmp(optarg, "vp9") == 0)
207  {
208  dec_codec_format = NI_CODEC_FORMAT_VP9;
209  }
210  else
211  {
212  ni_log(NI_LOG_ERROR, "Error: Invalid value \"%s\" for -m | --dec-codec option\n"
213  "Must be one of [a|avc, h|hevc, v|vp9]\n", optarg);
214  ret = -1;
215  goto end;
216  }
217  break;
218  case 'n':
219  // Accept both upper and lower case
220  for (i = 0; i < strlen(optarg); i++)
221  {
222  optarg[i] = (char)tolower((unsigned char)optarg[i]);
223  }
224  if (strcmp(optarg, "a") == 0 || strcmp(optarg, "avc") == 0)
225  {
226  enc_codec_format = NI_CODEC_FORMAT_H264;
227  }
228  else if (strcmp(optarg, "h") == 0 || strcmp(optarg, "hevc") == 0)
229  {
230  enc_codec_format = NI_CODEC_FORMAT_H265;
231  }
232  else if (strcmp(optarg, "x") == 0 || strcmp(optarg, "av1") == 0)
233  {
234  enc_codec_format = NI_CODEC_FORMAT_AV1;
235  }
236  else
237  {
238  ni_log(NI_LOG_ERROR, "Error: Invalid value \"%s\" for -n | --enc-codec option\n"
239  "Must be one of [a|avc, h|hevc, x|av1]\n", optarg);
240  ret = -1;
241  goto end;
242  }
243  break;
244  case 'l':
245  log_level = arg_to_ni_log_level(optarg);
246  if (log_level != NI_LOG_INVALID)
247  {
248  ni_log_set_level(log_level);
249  }
250  else
251  {
252  ni_log(NI_LOG_ERROR, "Error: Invalid value \"%s\" for -l | --loglevel option\n"
253  "Must be one of [none, fatal, error, info, debug, trace]\n", optarg);
254  ret = -1;
255  goto end;
256  }
257  break;
258  case 'c':
259  xcoderGUID = (int)strtol(optarg, &n, 10);
260  if (n == optarg || *n != '\0' || xcoderGUID < 0)
261  {
262  ni_log(NI_LOG_ERROR, "Error: Invalid value \"%s\" for -c | --card option\n"
263  "Must be a non-negative integer\n", optarg);
264  ret = -1;
265  goto end;
266  }
267  break;
268  case 'r':
269  ctx.loops_left = strtol(optarg, &n, 10);
270  if (n == optarg || *n != '\0' || ctx.loops_left <= 0)
271  {
272  ni_log(NI_LOG_ERROR, "Error: Invalid value \"%s\" for -r | --repeat option\n"
273  "Must be a positive integer\n", optarg);
274  ret = -1;
275  goto end;
276  }
277  break;
278  case 'd':
279  strcpy(dec_conf_params, optarg);
280  break;
281  case 'e':
282  if (e_index == MAX_OUTPUT_FILES)
283  {
284  ni_log(NI_LOG_ERROR, "Error: number of encoder config cannot exceed %d\n", MAX_OUTPUT_FILES);
285  ret = -1;
286  goto end;
287  }
288  strcpy(enc_conf_params[e_index], optarg);
289  e_index++;
290  break;
291  case 'g':
292  if (g_index == MAX_OUTPUT_FILES)
293  {
294  ni_log(NI_LOG_ERROR, "Error: number of encoder gop settings cannot exceed %d\n", MAX_OUTPUT_FILES);
295  ret = -1;
296  goto end;
297  }
298  strcpy(enc_gop_params[g_index], optarg);
299  g_index++;
300  break;
301  case 'u':
302  user_data_sei_passthru = 1;
303  break;
304  case 'f':
305  strcpy(filter_conf_params, optarg);
306  break;
307  default:
308  print_usage();
309  ret = -1;
310  goto end;
311  }
312  }
313 
314  if (!in_filename[0]) {
315  ni_log(NI_LOG_ERROR, "Error: Missing input file argument (-i | --input)\n");
316  ret = -1;
317  goto end;
318  }
319 
320  if (o_index == 0) {
321  ni_log(NI_LOG_ERROR, "Error: Missing output file argument (-o | --output)\n");
322  ret = -1;
323  goto end;
324  }
325 
326  if (dec_codec_format == -1) {
327  ni_log(NI_LOG_ERROR, "Error: Missing decoder codec argument (-m | --dec-codec)\n");
328  ret = -1;
329  goto end;
330  }
331 
332  if (enc_codec_format == -1) {
333  ni_log(NI_LOG_ERROR, "Error: Missing encoder codec argument (-n | --enc-codec)\n");
334  ret = -1;
335  goto end;
336  }
337 
338  ret = read_and_cache_file(&ctx, in_filename);
339  if (ret)
340  {
341  ni_log(NI_LOG_ERROR, "Error: Read input file failure\n");
342  goto end;
343  }
344 
345  output_total = o_index;
346  for (i = 0; i < output_total; i++)
347  {
348  if (strcmp(out_filename[i], "null") != 0 &&
349  strcmp(out_filename[i], "/dev/null") != 0)
350  {
351  output_fp[i] = fopen(out_filename[i], "wb");
352  if (!output_fp[i])
353  {
354  ni_log(NI_LOG_ERROR, "Error: Failed to open %s\n", out_filename[i]);
355  ret = -1;
356  goto end;
357  }
358  ni_log(NI_LOG_INFO, "Opened output file: %s\n", out_filename[i]);
359  } else
360  {
361  output_fp[i] = NULL;
362  ni_log(NI_LOG_INFO, "Note: Requested NULL output for index %d, no output file will be generated\n", i);
363  }
364  }
365 
366  p_dec_api_param = malloc(sizeof(ni_xcoder_params_t));
367  if (!p_dec_api_param)
368  {
369  ni_log(NI_LOG_ERROR, "Error: failed to allocate p_dec_api_param\n");
370  ret = -1;
371  goto end;
372  }
373 
374  p_enc_api_param = calloc(output_total, sizeof(ni_xcoder_params_t));
375  if (!p_enc_api_param)
376  {
377  ni_log(NI_LOG_ERROR, "Error: Failed to allocate memory for p_enc_api_param\n");
378  ret = -1;
379  goto end;
380  }
381 
382  if (dec_codec_format == NI_CODEC_FORMAT_H264)
383  {
384  ret = probe_h264_stream_info(&ctx, &avc_sps);
385  if (ret)
386  {
388  "ERROR: Failed to probe input file as H.264, file format not supported!\n");
389  goto end;
390  }
391 
392  bit_depth = avc_sps.bit_depth_luma;
393  input_width = avc_sps.width;
394  input_height = avc_sps.height;
395  ni_log(NI_LOG_DEBUG, "Using probed H.264 source info: %d bits, resolution %dx%d\n",
396  bit_depth, input_width, input_height);
397  } else if (dec_codec_format == NI_CODEC_FORMAT_H265)
398  {
399  ret = probe_h265_stream_info(&ctx, &hevc_sps);
400  if (ret)
401  {
403  "ERROR: Failed to probe input file as H.265, file format not supported!\n");
404  goto end;
405  }
406  bit_depth = hevc_sps.bit_depth_chroma;
407  input_width = (int)(hevc_sps.width -
408  (hevc_sps.pic_conf_win.left_offset +
409  hevc_sps.pic_conf_win.right_offset));
410  input_height = (int)(hevc_sps.height -
411  (hevc_sps.pic_conf_win.top_offset +
412  hevc_sps.pic_conf_win.bottom_offset));
413  ni_log(NI_LOG_INFO, "Using probed H.265 source info: %d bits, resolution %dx%d\n",
414  bit_depth, input_width, input_height);
415  } else if (dec_codec_format == NI_CODEC_FORMAT_VP9)
416  {
417  ret = probe_vp9_stream_info(&ctx, &vp9_info);
418  if (ret)
419  {
421  "ERROR: Failed to probe input file as VP9, file format not supported!\n");
422  goto end;
423  }
424  bit_depth = vp9_info.profile ? 10 : 8;
425  input_width = vp9_info.width;
426  input_height = vp9_info.height;
428  "Using probed VP9 source info: %d bits, resolution %dx%d, timebase %u/%u\n",
429  bit_depth, input_width, input_height,
430  vp9_info.timebase.den, vp9_info.timebase.num);
431  }
432 
433  // set up decoder config params with some hard-coded values
434  ret = ni_decoder_init_default_params(p_dec_api_param, 25, 1, 200000, input_width, input_height);
435  if (ret)
436  {
437  ni_log(NI_LOG_ERROR, "Error: Failed to init default decoder config\n");
438  goto end;
439  }
440 
441  ret = ni_device_session_context_init(&dec_ctx);
442  if (ret)
443  {
444  ni_log(NI_LOG_ERROR, "Error: Failed to init decoder context\n");
445  goto end;
446  }
447 
448  dec_ctx.codec_format = dec_codec_format;
449  dec_ctx.src_bit_depth = bit_depth;
450  dec_ctx.bit_depth_factor = 1;
451  if (10 == dec_ctx.src_bit_depth)
452  {
453  dec_ctx.bit_depth_factor = 2;
454  }
455  if ((NI_CODEC_FORMAT_H264 == dec_codec_format) || (NI_CODEC_FORMAT_H265 == dec_codec_format))
456  dec_ctx.enable_user_data_sei_passthru = user_data_sei_passthru;
457 
458  // check and set ni_decoder_params from --xcoder-params
459  ret = ni_retrieve_decoder_params(dec_conf_params, p_dec_api_param, &dec_ctx);
460  if (ret)
461  {
462  ni_log(NI_LOG_ERROR, "Error: decoder config params parsing error\n");
463  goto end;
464  }
465 
466  // Decode, use all the parameters specified by user
467  ret = decoder_open_session(&dec_ctx, xcoderGUID, p_dec_api_param);
468  if (ret)
469  {
470  ni_log(NI_LOG_ERROR, "Error: Failed to open decoder session\n");
471  goto end;
472  }
473 
474  for (i = 0; i < output_total; i++)
475  {
476  if (ni_device_session_context_init(&enc_ctx[i]) < 0)
477  {
478  ni_log(NI_LOG_ERROR, "Error: init encoder %d context error\n", i);
479  ret = -1;
480  goto end;
481  }
482  }
483 
484  for (i = 0; i < output_total; i++)
485  {
486  enc_ctx[i].codec_format = enc_codec_format;
487  }
488 
489  if (dec_codec_format == NI_CODEC_FORMAT_H264)
490  p_stream_info = &avc_sps;
491  else if (dec_codec_format == NI_CODEC_FORMAT_H265)
492  p_stream_info = &hevc_sps;
493  else if (dec_codec_format == NI_CODEC_FORMAT_VP9)
494  {
495  p_stream_info = &vp9_info;
496  fps_num = vp9_info.timebase.den;
497  fps_den = vp9_info.timebase.num;
498  }
499 
500  output_width = input_width;
501  output_height = input_height;
502 
503  if (filter_conf_params[0])
504  {
505  if (!dec_ctx.hw_action) {
506  ni_log(NI_LOG_ERROR, "Error: filters are only supported when hwframe is enabled (out=hw)\n");
507  ret = -1;
508  goto end;
509  }
510  ret = retrieve_filter_params(filter_conf_params, &scale_params, &drawbox_params);
511  if (ret)
512  {
513  ni_log(NI_LOG_ERROR, "Error: failed to parse filter parameters: %s\n", filter_conf_params);
514  goto end;
515  }
516  }
517 
518  if (scale_params.enabled)
519  {
520  ret = ni_device_session_context_init(&sca_ctx);
521  if (ret)
522  {
523  ni_log(NI_LOG_ERROR, "Error: Failed to init scale context\n");
524  goto end;
525  }
526  output_width = scale_params.width;
527  output_height = scale_params.height;
528  }
529  else if (drawbox_params.enabled)
530  {
531  ret = ni_device_session_context_init(&crop_ctx);
532  if (ret)
533  {
534  ni_log(NI_LOG_ERROR, "Error: Failed to init crop context\n");
535  goto end;
536  }
537  ret = ni_device_session_context_init(&pad_ctx);
538  if (ret)
539  {
540  ni_log(NI_LOG_ERROR, "Error: Failed to init pad context\n");
541  goto end;
542  }
543  ret = ni_device_session_context_init(&ovly_ctx);
544  if (ret)
545  {
546  ni_log(NI_LOG_ERROR, "Error: Failed to init overlay context\n");
547  goto end;
548  }
549  ret = ni_device_session_context_init(&fmt_ctx);
550  if (ret)
551  {
552  ni_log(NI_LOG_ERROR, "Error: Failed to init format context\n");
553  goto end;
554  }
555  }
556 
557  ni_log(NI_LOG_INFO, "Starting to transcode: HWFrames %d, video resolution %dx%d -> %dx%d\n",
558  dec_ctx.hw_action, input_width, input_height, output_width, output_height);
559 
560  ctx.start_time = ni_gettime_ns();
561 
562  // init and create decoding thread
563  dec_send_param.p_ctx = &ctx;
564  dec_send_param.p_dec_ctx = &dec_ctx;
565  dec_send_param.input_width = input_width;
566  dec_send_param.input_height = input_height;
567  dec_send_param.p_stream_info = p_stream_info;
568  dec_send_param.frame_list = &frame_list;
569 
570  dec_recv_param.p_ctx = &ctx;
571  dec_recv_param.p_dec_ctx = &dec_ctx;
572  dec_recv_param.p_sca_ctx = &sca_ctx;
573  dec_recv_param.p_crop_ctx = &crop_ctx;
574  dec_recv_param.p_pad_ctx = &pad_ctx;
575  dec_recv_param.p_ovly_ctx = &ovly_ctx;
576  dec_recv_param.p_fmt_ctx = &fmt_ctx;
577  dec_recv_param.xcoderGUID = xcoderGUID;
578  dec_recv_param.input_width = input_width;
579  dec_recv_param.input_height = input_height;
580  dec_recv_param.frame_list = &frame_list;
581  dec_recv_param.scale_params = &scale_params;
582  dec_recv_param.drawbox_params = &drawbox_params;
583 
584  if (ni_pthread_create(&dec_send_tid, NULL, decoder_send_thread,
585  &dec_send_param))
586  {
588  "Error: create decoder send thread failed in transcode "
589  "mode\n");
590  return -1;
591  }
592  if (ni_pthread_create(&dec_recv_tid, NULL, decoder_receive_thread,
593  &dec_recv_param))
594  {
596  "Error: create decoder receive thread failed in "
597  "transcode mode\n");
598  return -1;
599  }
600 
601  // polling the first received decoded frame
602  while (frame_list_is_empty(&frame_list) && !ctx.end_all_threads)
603  {
604  ni_usleep(100);
605  }
606 
607  if (!ctx.end_all_threads)
608  {
609  p_ni_frame = &frame_list.frames[frame_list.head].data.frame;
610  p_hwframe = dec_ctx.hw_action == NI_CODEC_HW_ENABLE ?
611  (niFrameSurface1_t *)p_ni_frame->p_data[3] : NULL;
612 
613  if (scale_params.enabled)
614  enc_pix_fmt = gc620_to_ni_pix_fmt(scale_params.format);
615  else if (drawbox_params.enabled)
616  enc_pix_fmt = NI_PIX_FMT_YUV420P;
617  else
618  enc_pix_fmt = dec_ctx.pixel_format;
619 
620  ret = encoder_open(enc_ctx, p_enc_api_param, output_total, enc_conf_params, enc_gop_params,
621  p_ni_frame, output_width, output_height, fps_num, fps_den, bitrate,
622  enc_codec_format, enc_pix_fmt, p_ni_frame->aspect_ratio_idc,
623  xcoderGUID, p_hwframe, 1, false);
624  if (ret != 0)
625  {
626  goto end;
627  }
628 
629  // init and create encoding thread
630  enc_send_param.p_ctx = &ctx;
631  enc_send_param.p_enc_ctx = enc_ctx;
632  enc_send_param.output_width = output_width;
633  enc_send_param.output_height = output_height;
634  enc_send_param.output_total = output_total;
635  enc_send_param.frame_list = &frame_list;
636 
637  enc_recv_param.p_ctx = &ctx;
638  enc_recv_param.p_enc_ctx = enc_ctx;
639  enc_recv_param.output_width = output_width;
640  enc_recv_param.output_height = output_height;
641  enc_recv_param.p_file = output_fp;
642  enc_recv_param.output_total = output_total;
643  enc_recv_param.frame_list = &frame_list;
644 
645  if (ni_pthread_create(&enc_send_tid, NULL, encoder_send_thread,
646  &enc_send_param))
647  {
648  ni_log(NI_LOG_ERROR, "Error: create encoder send thread failed "
649  "in transcode mode\n");
650  return -1;
651  }
652  if (ni_pthread_create(&enc_recv_tid, NULL, encoder_receive_thread,
653  &enc_recv_param))
654  {
655  ni_log(NI_LOG_ERROR, "Error: create encoder recieve thread "
656  "failed in transcode mode\n");
657  return -1;
658  }
659 
660  ni_pthread_join(enc_send_tid, NULL);
661  ni_pthread_join(enc_recv_tid, NULL);
662  }
663  ni_pthread_join(dec_send_tid, NULL);
664  ni_pthread_join(dec_recv_tid, NULL);
665 
666  decoder_stat_report_and_close(&ctx, &dec_ctx);
667  encoder_stat_report_and_close(&ctx, enc_ctx, output_total);
668 
669 end:
670  hwframe_list_release(&frame_list);
671 
673  for (i = 0; i < output_total; i++)
674  {
675  ni_device_session_context_clear(&enc_ctx[i]);
676  if (output_fp[i] != NULL)
677  {
678  fclose(output_fp[i]);
679  }
680  }
681  if (scale_params.enabled)
682  {
684  }
685  if (drawbox_params.enabled)
686  {
691  }
692 
693  free(ctx.file_cache);
694  free(p_dec_api_param);
695  free(p_enc_api_param);
696 
697  return ret;
698 }
_ni_scale_params::height
int height
Definition: ni_filter_utils.h:37
ni_decode_utils.h
dec_recv_param::frame_list
ni_test_frame_list_t * frame_list
Definition: ni_decode_utils.h:62
dec_recv_param::scale_params
ni_scale_params_t * scale_params
Definition: ni_decode_utils.h:63
ni_log_level_t
ni_log_level_t
Definition: ni_log.h:55
gc620_to_ni_pix_fmt
ni_pix_fmt_t gc620_to_ni_pix_fmt(int pix_fmt)
Definition: ni_generic_utils.c:132
dec_recv_param::p_sca_ctx
ni_session_context_t * p_sca_ctx
Definition: ni_decode_utils.h:54
_ni_demo_context::loops_left
uint64_t loops_left
Definition: ni_generic_utils.h:117
ni_pix_fmt_t
ni_pix_fmt_t
Definition: ni_device_api.h:260
_ni_h265_sps_t::bit_depth_chroma
int bit_depth_chroma
Definition: ni_decode_utils.h:251
_ni_vp9_header_info::den
uint32_t den
Definition: ni_decode_utils.h:347
main
int main(int argc, char *argv[])
Definition: ni_xcoder_multithread_transcode.c:90
encoder_stat_report_and_close
void encoder_stat_report_and_close(ni_demo_context_t *p_ctx, ni_session_context_t *p_enc_ctx_list, int output_total)
Definition: ni_encode_utils.c:2252
dec_send_param::input_width
int input_width
Definition: ni_decode_utils.h:44
_ni_frame::aspect_ratio_idc
uint8_t aspect_ratio_idc
Definition: ni_device_api.h:2686
enc_recv_param::p_file
FILE ** p_file
Definition: ni_encode_utils.h:53
encoder_send_thread
void * encoder_send_thread(void *args)
Definition: ni_encode_utils.c:2276
probe_h264_stream_info
int probe_h264_stream_info(ni_demo_context_t *p_ctx, ni_h264_sps_t *sps)
Definition: ni_decode_utils.c:715
ni_generic_utils.h
print_version
void print_version(void)
Definition: ni_generic_utils.c:70
retrieve_filter_params
int retrieve_filter_params(char filter_params[], ni_scale_params_t *scale_params, ni_drawbox_params_t *drawbox_params)
Definition: ni_filter_utils.c:104
NI_PIX_FMT_YUV420P
@ NI_PIX_FMT_YUV420P
Definition: ni_device_api.h:262
dec_recv_param::xcoderGUID
int xcoderGUID
Definition: ni_decode_utils.h:59
ni_encode_utils.h
ni_log_set_level
void ni_log_set_level(ni_log_level_t level)
Set ni_log_level.
Definition: ni_log.c:202
ni_gettime_ns
uint64_t ni_gettime_ns(void)
Definition: ni_util.c:1998
MAX_OUTPUT_FILES
#define MAX_OUTPUT_FILES
Definition: ni_generic_utils.h:48
_ni_h265_window_t::bottom_offset
unsigned int bottom_offset
Definition: ni_decode_utils.h:141
required_argument
#define required_argument
Definition: ni_getopt.h:86
NI_XCODER_REVISION
#define NI_XCODER_REVISION
Definition: ni_defs.h:95
probe_h265_stream_info
int probe_h265_stream_info(ni_demo_context_t *p_ctx, ni_h265_sps_t *sps)
Definition: ni_decode_utils.c:1994
enc_recv_param::p_ctx
ni_demo_context_t * p_ctx
Definition: ni_encode_utils.h:49
_ni_h265_window_t::left_offset
unsigned int left_offset
Definition: ni_decode_utils.h:138
no_argument
#define no_argument
Definition: ni_getopt.h:85
_ni_demo_context::end_all_threads
uint8_t end_all_threads
Definition: ni_generic_utils.h:111
dec_send_param::frame_list
ni_test_frame_list_t * frame_list
Definition: ni_decode_utils.h:47
decoder_receive_thread
void * decoder_receive_thread(void *args)
Definition: ni_decode_utils.c:2678
_ni_session_context::bit_depth_factor
int bit_depth_factor
Definition: ni_device_api.h:1494
dec_send_param::p_stream_info
void * p_stream_info
Definition: ni_decode_utils.h:46
_ni_h265_sps_t::width
int width
Definition: ni_decode_utils.h:317
dec_recv_param::p_fmt_ctx
ni_session_context_t * p_fmt_ctx
Definition: ni_decode_utils.h:58
dec_recv_param::input_width
int input_width
Definition: ni_decode_utils.h:60
enc_send_param::p_ctx
ni_demo_context_t * p_ctx
Definition: ni_encode_utils.h:39
_ni_test_frame_list
Definition: ni_generic_utils.h:102
ni_pthread_join
int ni_pthread_join(ni_pthread_t thread, void **value_ptr)
join with a terminated thread
Definition: ni_util.c:4148
frame_list_is_empty
bool frame_list_is_empty(ni_test_frame_list_t *list)
Definition: ni_generic_utils.c:175
FILE_NAME_LEN
#define FILE_NAME_LEN
Definition: ni_generic_utils.h:46
probe_vp9_stream_info
int probe_vp9_stream_info(ni_demo_context_t *p_ctx, ni_vp9_header_info_t *vp9_info)
Definition: ni_decode_utils.c:2180
ni_log.h
Logging definitions.
_ni_scale_params::format
int format
Definition: ni_filter_utils.h:38
enc_send_param
Definition: ni_encode_utils.h:37
enc_send_param::p_enc_ctx
ni_session_context_t * p_enc_ctx
Definition: ni_encode_utils.h:40
_ni_demo_context
Definition: ni_generic_utils.h:109
_ni_vp9_header_info
Definition: ni_decode_utils.h:339
NI_LOG_INFO
@ NI_LOG_INFO
Definition: ni_log.h:61
arg_to_ni_log_level
ni_log_level_t arg_to_ni_log_level(const char *arg_str)
Convert terminal arg string to ni_log_level_t.
Definition: ni_log.c:262
decoder_stat_report_and_close
void decoder_stat_report_and_close(ni_demo_context_t *p_ctx, ni_session_context_t *p_dec_ctx)
Definition: ni_decode_utils.c:2612
NI_LOG_ERROR
@ NI_LOG_ERROR
Definition: ni_log.h:60
_ni_session_context::src_bit_depth
int src_bit_depth
Definition: ni_device_api.h:1492
read_and_cache_file
int read_and_cache_file(ni_demo_context_t *ctx, char *filename)
Definition: ni_generic_utils.c:259
_ni_vp9_header_info::timebase
struct _ni_vp9_header_info::@3 timebase
ni_filter_utils.h
_ni_h264_sps_t
Definition: ni_decode_utils.h:70
_ni_vp9_header_info::num
uint32_t num
Definition: ni_decode_utils.h:348
_ni_test_frame_list::head
int head
Definition: ni_generic_utils.h:105
enc_send_param::output_total
int output_total
Definition: ni_encode_utils.h:43
decoder_open_session
int decoder_open_session(ni_session_context_t *p_dec_ctx, int iXcoderGUID, ni_xcoder_params_t *p_dec_params)
decoder session open
Definition: ni_decode_utils.c:2575
_ni_h265_sps_t::height
int height
Definition: ni_decode_utils.h:318
dec_recv_param::p_ovly_ctx
ni_session_context_t * p_ovly_ctx
Definition: ni_decode_utils.h:57
_ni_scale_params::width
int width
Definition: ni_filter_utils.h:36
_ni_h265_sps_t::pic_conf_win
ni_h265_window_t pic_conf_win
Definition: ni_decode_utils.h:248
NI_CODEC_FORMAT_AV1
@ NI_CODEC_FORMAT_AV1
Definition: ni_device_api.h:915
hwframe_list_release
void hwframe_list_release(ni_test_frame_list_t *list)
Definition: ni_generic_utils.c:231
_ni_h265_window_t::right_offset
unsigned int right_offset
Definition: ni_decode_utils.h:139
_ni_h265_sps_t
Definition: ni_decode_utils.h:241
encoder_receive_thread
void * encoder_receive_thread(void *args)
Definition: ni_encode_utils.c:2368
dec_recv_param::drawbox_params
ni_drawbox_params_t * drawbox_params
Definition: ni_decode_utils.h:64
ni_log
void ni_log(ni_log_level_t level, const char *fmt,...)
print log message using ni_log_callback
Definition: ni_log.c:183
NI_LOG_INVALID
@ NI_LOG_INVALID
Definition: ni_log.h:57
_ni_h264_sps_t::width
int width
Definition: ni_decode_utils.h:72
enc_recv_param::p_enc_ctx
ni_session_context_t * p_enc_ctx
Definition: ni_encode_utils.h:50
decoder_send_thread
void * decoder_send_thread(void *args)
Definition: ni_decode_utils.c:2626
getopt_long
int getopt_long(int argc, char *argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: ni_getopt.c:99
ni_usleep
void ni_usleep(int64_t usec)
Definition: ni_util.c:358
_ni_h264_sps_t::bit_depth_luma
int bit_depth_luma
bit_depth_luma_minus8 + 8
Definition: ni_decode_utils.h:128
dec_send_param
Definition: ni_decode_utils.h:40
_ni_vp9_header_info::profile
int profile
Definition: ni_decode_utils.h:341
enc_recv_param::frame_list
ni_test_frame_list_t * frame_list
Definition: ni_encode_utils.h:55
dec_recv_param::input_height
int input_height
Definition: ni_decode_utils.h:61
_ni_test_frame_list::frames
ni_session_data_io_t frames[NI_MAX_BUFFERED_FRAME]
Definition: ni_generic_utils.h:104
_ni_h265_window_t::top_offset
unsigned int top_offset
Definition: ni_decode_utils.h:140
ni_device_session_context_clear
void ni_device_session_context_clear(ni_session_context_t *p_ctx)
Clear already allocated session context.
Definition: ni_device_api.c:249
dec_send_param::input_height
int input_height
Definition: ni_decode_utils.h:45
_ni_frame::p_data
uint8_t * p_data[NI_MAX_NUM_DATA_POINTERS]
Definition: ni_device_api.h:2663
ni_pthread_create
int ni_pthread_create(ni_pthread_t *thread, const ni_pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
create a new thread
Definition: ni_util.c:4121
optarg
char * optarg
Definition: ni_getopt.c:33
NI_CODEC_FORMAT_VP9
@ NI_CODEC_FORMAT_VP9
Definition: ni_device_api.h:913
_ni_vp9_header_info::height
uint16_t height
Definition: ni_decode_utils.h:344
ni_decoder_init_default_params
ni_retcode_t ni_decoder_init_default_params(ni_xcoder_params_t *p_param, int fps_num, int fps_denom, long bit_rate, int width, int height)
Initialize default decoder parameters.
Definition: ni_device_api.c:4546
_ni_vp9_header_info::width
uint16_t width
Definition: ni_decode_utils.h:343
encoder_open
int encoder_open(ni_session_context_t *enc_ctx_list, ni_xcoder_params_t *p_api_param_list, int output_total, char p_enc_conf_params[][2048], char p_enc_conf_gop[][2048], ni_frame_t *p_ni_frame, int width, int height, int fps_num, int fps_den, int bitrate, int codec_format, ni_pix_fmt_t pix_fmt, int aspect_ratio_idc, int xcoder_guid, niFrameSurface1_t *p_surface, int multi_thread, bool check_zerocopy)
Definition: ni_encode_utils.c:1999
_ni_session_context::hw_action
int hw_action
Definition: ni_device_api.h:1609
_ni_scale_params
Definition: ni_filter_utils.h:33
_ni_session_context
Definition: ni_device_api.h:1408
_niFrameSurface1
Definition: ni_device_api.h:2793
NI_CODEC_HW_ENABLE
@ NI_CODEC_HW_ENABLE
Definition: ni_device_api.h:940
_ni_session_data_io::data
union _ni_session_data_io::@19 data
_ni_frame
Definition: ni_device_api.h:2601
enc_recv_param::output_height
int output_height
Definition: ni_encode_utils.h:52
_ni_demo_context::start_time
uint64_t start_time
Definition: ni_generic_utils.h:132
_ni_xcoder_params
Definition: ni_device_api.h:2713
option
Definition: ni_getopt.h:73
enc_recv_param::output_width
int output_width
Definition: ni_encode_utils.h:51
_ni_demo_context::file_cache
uint8_t * file_cache
Definition: ni_generic_utils.h:114
dec_send_param::p_ctx
ni_demo_context_t * p_ctx
Definition: ni_decode_utils.h:42
_ni_session_context::codec_format
uint32_t codec_format
Definition: ni_device_api.h:1486
_ni_session_data_io::frame
ni_frame_t frame
Definition: ni_device_api.h:2870
enc_send_param::output_width
int output_width
Definition: ni_encode_utils.h:41
_ni_scale_params::enabled
int enabled
Definition: ni_filter_utils.h:35
_ni_drawbox_params::enabled
int enabled
Definition: ni_filter_utils.h:43
_ni_session_context::enable_user_data_sei_passthru
int enable_user_data_sei_passthru
Definition: ni_device_api.h:1614
dec_recv_param::p_ctx
ni_demo_context_t * p_ctx
Definition: ni_decode_utils.h:52
enc_send_param::frame_list
ni_test_frame_list_t * frame_list
Definition: ni_encode_utils.h:44
enc_recv_param::output_total
int output_total
Definition: ni_encode_utils.h:54
ni_util.h
Utility definitions.
dec_recv_param::p_pad_ctx
ni_session_context_t * p_pad_ctx
Definition: ni_decode_utils.h:56
dec_recv_param::p_dec_ctx
ni_session_context_t * p_dec_ctx
Definition: ni_decode_utils.h:53
dec_send_param::p_dec_ctx
ni_session_context_t * p_dec_ctx
Definition: ni_decode_utils.h:43
dec_recv_param::p_crop_ctx
ni_session_context_t * p_crop_ctx
Definition: ni_decode_utils.h:55
dec_recv_param
Definition: ni_decode_utils.h:50
NI_CODEC_FORMAT_H264
@ NI_CODEC_FORMAT_H264
Definition: ni_device_api.h:911
_ni_h264_sps_t::height
int height
Definition: ni_decode_utils.h:73
enc_send_param::output_height
int output_height
Definition: ni_encode_utils.h:42
ni_device_session_context_init
ni_retcode_t ni_device_session_context_init(ni_session_context_t *p_ctx)
Initialize already allocated session context to a known state.
Definition: ni_device_api.c:156
_ni_session_context::pixel_format
int pixel_format
Definition: ni_device_api.h:1616
ni_retrieve_decoder_params
int ni_retrieve_decoder_params(char xcoderParams[], ni_xcoder_params_t *params, ni_session_context_t *ctx)
retrieve decoder config parameter values from –decoder-params
Definition: ni_util.c:3931
NI_LOG_DEBUG
@ NI_LOG_DEBUG
Definition: ni_log.h:62
ni_getopt.h
Implementation of getopt() and getopt_long() for Windows environment.
_ni_drawbox_params
Definition: ni_filter_utils.h:41
enc_recv_param
Definition: ni_encode_utils.h:47
NI_CODEC_FORMAT_H265
@ NI_CODEC_FORMAT_H265
Definition: ni_device_api.h:912