35 #elif __linux__ || __APPLE__
43 "Video encoding demo application directly using Netint Libxcoder version %s\n"
44 "Usage: ni_xcoder_encode [options]\n"
47 "-h | --help Show this message.\n"
48 "-v | --version Print version info.\n"
49 "-i | --input (Required) Input file path.\n"
50 " Can be specified multiple (max %d) times\n"
51 " to concatenate inputs with different resolution together (sequence change)\n"
52 "-o | --output (Required) Output file path.\n"
53 " Can be specified multiple (max %d) times\n"
54 " to run multiple encoding instances simultaneously.\n"
55 "-m | --enc-codec (Required) Encoder codec format.\n"
56 " [a|avc, h|hevc, x|av1, o|obu]\n"
57 " (x is in ivf container format, o is output raw AV1 OBU only)\n"
58 "-l | --loglevel Set loglevel of this application and libxcoder API.\n"
59 " [none, fatal, error, info, debug, trace]\n"
61 "-c | --card Set card index to use.\n"
62 " See `ni_rsrc_mon` for info of cards on system.\n"
64 "-r | --repeat To loop input X times. Must be a positive integer\n"
66 "-k | --readframerate Read input at specified frame rate.\n"
67 "-p | --pix_fmt Indicate the pixel format of the input.\n"
68 " [yuv420p, yuv420p10le, nv12, p010le, rgba, gbra, argb, abgr, bgr0, yuv444p]\n"
69 " (Default: yuv420p)\n"
70 "-s | --size (Required) Resolution of input file in format WIDTHxHEIGHT.\n"
71 " (eg. '1920x1080')\n"
72 "-e | --encoder-params Encoding params. See \"Encoding Parameters\" chapter in\n"
73 " QuadraIntegration&ProgrammingGuide*.pdf for help.\n"
74 " Can be specified multiple (max %d) times,\n"
75 " must match the number of -o specified.\n"
77 "-g | --encoder-gop Custom GOP for encoding. See \"Custom Gop Structure\" chapter in\n"
78 " QuadraIntegration&ProgrammingGuide*.pdf for help.\n"
79 " gopPresetIdx must be set to 0 to be in effect.\n"
81 "-u | --hwupload (No argument) When enabled, upload raw frame to device first before encoding\n"
82 " Multiple input files and yuv444p format input are not supported in this mode\n"
86 int main(
int argc,
char *argv[])
94 int i_index = 0, s_index = 0, o_index = 0, e_index = 0, g_index = 0;
95 int input_total = 0, output_total = 0;
96 int enc_codec_format = -1;
108 int first_frame_uploaded = 0;
109 void *yuv_buf = NULL;
121 int end_of_all_streams = 0, read_size = 0, eos = 0;
126 const char *opt_string =
"hvi:o:m:l:c:r:k:p:s:e:g:u";
127 static struct option long_options[] = {
145 while ((opt =
getopt_long(argc, argv, opt_string, long_options, &opt_index)) != -1)
164 strcpy(in_filename[i_index],
optarg);
175 for (i = 0; i < o_index; i++)
177 if (0 == strcmp(out_filename[i],
optarg))
185 strcpy(out_filename[o_index],
optarg);
190 for (i = 0; i < strlen(
optarg); i++)
194 if (strcmp(
optarg,
"a") == 0 || strcmp(
optarg,
"avc") == 0)
198 else if (strcmp(
optarg,
"h") == 0 || strcmp(
optarg,
"hevc") == 0)
202 else if (strcmp(
optarg,
"x") == 0 || strcmp(
optarg,
"av1") == 0)
206 else if (strcmp(
optarg,
"o") == 0 || strcmp(
optarg,
"obu") == 0)
214 "Must be one of [a|avc, h|hevc, x|av1, o|obu]\n",
optarg);
228 "Must be one of [none, fatal, error, info, debug, trace]\n",
optarg);
234 xcoderGUID = (int)strtol(
optarg, &n, 10);
235 if (n ==
optarg || *n !=
'\0' || xcoderGUID < 0)
238 "Must be a non-negative integer\n",
optarg);
248 "Must be a positive integer\n",
optarg);
258 "Must be a non-negative integer\n",
optarg);
267 if (!strcmp(
optarg,
"yuv444p"))
274 "Must be one of [yuv420p, yuv420p10le, nv12, p010le, rgba, gbra, argb, abgr, bgr0, yuv444p]\n",
288 video_width[s_index] = (int)strtol(
optarg, &n, 10);
289 video_height[s_index] =
atoi(n + 1);
290 if ((*n !=
'x') || (video_width[s_index] <= 0 || video_height[s_index] <= 0))
293 "Must be in format [WIDTHxHEIGHT] (e.g. 1920x1080)\n",
optarg);
306 strcpy(enc_conf_params[e_index],
optarg);
316 strcpy(enc_gop_params[g_index],
optarg);
341 if (s_index != i_index) {
342 ni_log(
NI_LOG_ERROR,
"Error: Number of input resolution specified does not match number of input files\n");
347 if (enc_codec_format == -1) {
353 input_total = i_index;
362 output_total = o_index;
373 ni_log(
NI_LOG_ERROR,
"Error: -k | --readframerate option is not supported in hwupload mode\n");
377 if (hwupload && input_total > 1)
379 ni_log(
NI_LOG_ERROR,
"Error: multiple input (sequence change) is not supported in hwupload mode\n");
397 for (i = 0; i < input_total; i++)
399 if (!in_filename[i][0])
406 input_fp[i] = fopen(in_filename[i],
"rb");
420 for (i = 0; i < output_total; i++)
422 if (strcmp(out_filename[i],
"null") != 0 &&
423 strcmp(out_filename[i],
"/dev/null") != 0)
425 output_fp[i] = fopen(out_filename[i],
"wb");
436 ni_log(
NI_LOG_INFO,
"Note: Requested NULL output for index %d, no output file will be generated\n", i);
441 if (!p_enc_api_param)
448 for (i = 0; i < output_total; i++)
458 for (i = 0; i < output_total; i++)
482 ni_log(
NI_LOG_INFO,
"Starting hwupload + encoding mode: video resolution %dx%d\n",
483 video_width[0], video_height[0]);
492 p_hwframe =
hwupload_frame(&ctx, &upl_ctx, &sca_ctx, &swin_frame, &in_frame, &scale_frame, pix_fmt,
493 video_width[0], video_height[0], input_fp[0], yuv_buf, &eos);
494 if (p_hwframe == NULL)
500 ret =
encoder_open(&enc_ctx[0], p_enc_api_param, output_total, enc_conf_params, enc_gop_params,
501 NULL, video_width[0], video_height[0], 30, 1, 200000, enc_codec_format,
503 0, xcoderGUID, p_hwframe, 0,
false);
509 while (!end_of_all_streams &&
513 if (first_frame_uploaded && !eos)
515 p_hwframe =
hwupload_frame(&ctx, &upl_ctx, &sca_ctx, &swin_frame, &in_frame, &scale_frame, pix_fmt,
516 video_width[0], video_height[0], input_fp[0], yuv_buf, &eos);
520 p_in_frame = &in_frame;
522 }
else if (p_hwframe == NULL)
531 for (i = 0; i < output_total; i++)
534 send_rc =
encoder_send_data3(&ctx, &enc_ctx[i], p_in_frame, video_width[0], video_height[0], eos);
535 first_frame_uploaded = 1;
540 end_of_all_streams = 1;
558 if (end_of_all_streams)
563 video_width[0], video_height[0], output_total, output_fp);
564 for (i = 0; receive_rc >= 0 && i < output_total; i++)
569 end_of_all_streams = 0;
574 end_of_all_streams = 1;
580 for (i = 0; i < output_total; i++)
582 ni_log(
NI_LOG_INFO,
"Encoder %d stats: received %u packets, fps %.2f, total bytes %u\n",
600 ret =
encoder_open(enc_ctx, p_enc_api_param, output_total,
601 enc_conf_params, enc_gop_params, NULL, video_width[0],
602 video_height[0], 30, 1, 200000,
603 enc_codec_format, pix_fmt, 0, xcoderGUID, NULL,
611 ni_log(
NI_LOG_INFO,
"Starting to encode: video resolution %dx%d\n", video_width[0], video_height[0]);
613 while (!end_of_all_streams &&
618 video_width[i_index], video_height[i_index],
619 pix_fmt, sw_pix_fmt, &eos,
620 enc_ctx[0].session_run_state);
630 video_width[i_index], video_height[i_index],
631 sw_pix_fmt, 0, enc_codec_format);
638 for (i = 0; i < output_total; i++)
644 video_width[i_index], video_height[i_index], eos);
649 &in_frame, eos ? NULL : yuv_buf,
650 video_width[i_index], video_height[i_index],
651 i_index == input_total - 1);
669 video_width[0], video_height[0], output_total, output_fp);
670 for (i = 0; receive_rc >= 0 && i < output_total; i++)
675 end_of_all_streams = 0;
680 end_of_all_streams = 1;
686 for (i = 0; i < output_total; i++)
688 ni_log(
NI_LOG_INFO,
"Encoder %d stats: received %u packets, fps %.2f, total bytes %u\n",
703 for (i = 0; i < output_total; i++)
714 for (i = 0; i < output_total; i++)
717 if (output_fp[i] != NULL)
719 fclose(output_fp[i]);
723 for (i = 0; i < input_total; i++)
732 free(p_enc_api_param);