38 #elif __linux__ || __APPLE__
43 static void print_usage(
void)
46 "Video transcoding demo application directly using Netint Libxcoder version %s\n"
47 "Usage: ni_xcoder_transcode_filter [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"
63 "-c | --card Set card index to use.\n"
64 " See `ni_rsrc_mon` for info of cards on system.\n"
66 "-r | --repeat To loop input X times. Must be a positive integer\n"
68 "-d | --decoder-params Decoding params. See \"Decoding Parameters\" chapter in\n"
69 " QuadraIntegration&ProgrammingGuide*.pdf for help.\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"
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"
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"
90 int main(
int argc,
char *argv[])
97 int o_index = 0, e_index = 0, g_index = 0, f_index = 0;
99 int input_width = 0, input_height = 0, bit_depth = 8;
102 int dec_codec_format = -1, enc_codec_format = -1;
106 char dec_conf_params[2048] = {0};
110 int user_data_sei_passthru = 0;
124 void *p_stream_info = NULL;
125 int fps_num = 30, fps_den = 1, bitrate = 200000;
135 int encoder_opened = 0, end_of_all_streams = 0;
139 int hw_frame_ref_flag = 0;
140 int recycle_hw_frame_for_scaler = 0;
144 const char *opt_string =
"hvi:o:m:n:l:c:r:d:e:g:uf:";
145 static struct option long_options[] = {
158 {
"user-data-sei-passthru",
no_argument, NULL,
'u'},
163 while ((opt =
getopt_long(argc, argv, opt_string, long_options, &opt_index)) != -1)
186 for (i = 0; i < o_index; i++)
188 if (0 == strcmp(out_filename[i],
optarg))
201 for (i = 0; i < strlen(
optarg); i++)
205 if (strcmp(
optarg,
"a") == 0 || strcmp(
optarg,
"avc") == 0)
209 else if (strcmp(
optarg,
"h") == 0 || strcmp(
optarg,
"hevc") == 0)
213 else if (strcmp(
optarg,
"v") == 0 || strcmp(
optarg,
"vp9") == 0)
220 "Must be one of [a|avc, h|hevc, v|vp9]\n",
optarg);
227 for (i = 0; i < strlen(
optarg); i++)
231 if (strcmp(
optarg,
"a") == 0 || strcmp(
optarg,
"avc") == 0)
235 else if (strcmp(
optarg,
"h") == 0 || strcmp(
optarg,
"hevc") == 0)
239 else if (strcmp(
optarg,
"x") == 0 || strcmp(
optarg,
"av1") == 0)
246 "Must be one of [a|avc, h|hevc, x|av1]\n",
optarg);
260 "Must be one of [none, fatal, error, info, debug, trace]\n",
optarg);
266 xcoderGUID = (int)strtol(
optarg, &n, 10);
267 if (n ==
optarg || *n !=
'\0' || xcoderGUID < 0)
270 "Must be a non-negative integer\n",
optarg);
280 "Must be a positive integer\n",
optarg);
295 ni_strcpy(enc_conf_params[e_index],
sizeof(enc_conf_params[e_index]),
optarg);
305 ni_strcpy(enc_gop_params[g_index],
sizeof(enc_gop_params[g_index]),
optarg);
309 user_data_sei_passthru = 1;
318 ni_strcpy(filter_conf_params[f_index],
sizeof(filter_conf_params[f_index]),
optarg);
328 if (!in_filename[0]) {
340 if (dec_codec_format == -1) {
346 if (enc_codec_format == -1) {
359 output_total = o_index;
360 for (i = 0; i < output_total; i++)
362 if (strcmp(out_filename[i],
"null") != 0 &&
363 strcmp(out_filename[i],
"/dev/null") != 0)
366 ni_fopen(&(output_fp[i]), out_filename[i],
"wb");
377 ni_log(
NI_LOG_INFO,
"Note: Requested NULL output for index %d, no output file will be generated\n", i);
380 frame_to_enc[i] = NULL;
382 p_hwframe2[i] = NULL;
386 if (!p_dec_api_param)
394 if (!p_enc_api_param)
407 "ERROR: Failed to probe input file as H.264, file format not supported!\n");
412 input_width = avc_sps.
width;
413 input_height = avc_sps.
height;
415 bit_depth, input_width, input_height);
422 "ERROR: Failed to probe input file as H.265, file format not supported!\n");
426 input_width = (int)(hevc_sps.
width -
429 input_height = (int)(hevc_sps.
height -
432 ni_log(
NI_LOG_INFO,
"Using probed H.265 source info: %d bits, resolution %dx%d\n",
433 bit_depth, input_width, input_height);
440 "ERROR: Failed to probe input file as VP9, file format not supported!\n");
443 bit_depth = vp9_info.
profile ? 10 : 8;
444 input_width = vp9_info.
width;
445 input_height = vp9_info.
height;
447 "Using probed VP9 source info: %d bits, resolution %dx%d, timebase %u/%u\n",
448 bit_depth, input_width, input_height,
493 for (i = 0; i < output_total; i++)
503 for (i = 0; i < output_total; i++)
506 output_width[i] = input_width;
507 output_height[i] = input_height;
511 p_stream_info = &avc_sps;
513 p_stream_info = &hevc_sps;
516 p_stream_info = &vp9_info;
521 for (i = 0; i < output_total; i++)
523 if (filter_conf_params[i][0])
526 ni_log(
NI_LOG_ERROR,
"Error: filters are only supported when hwframe is enabled (out=hw)\n");
534 ni_log(
NI_LOG_ERROR,
"Error: failed to parse filter parameters: %s\n", filter_conf_params[i]);
539 if (scale_params[i].enabled)
547 output_width[i] = scale_params[i].
width;
548 output_height[i] = scale_params[i].
height;
550 else if ((drawbox_params.
enabled))
580 for (i = 0; i < output_total; i++)
583 ni_log(
NI_LOG_ERROR,
"Error: Mixing scale and drawbox filter is not supported in this demo\n");
586 ni_log(
NI_LOG_INFO,
"(Task %d) Starting to transcode: HWFrames %d, video resolution %dx%d -> %dx%d\n",
587 i, dec_ctx.
hw_action, input_width, input_height, output_width[i], output_height[i]);
593 while (!end_of_all_streams &&
599 send_rc =
decoder_send_data(&ctx, &dec_ctx, &in_pkt, input_width, input_height, p_stream_info);
609 input_height, NULL, 0, &rx_size);
611 for (i = 0; i < output_total; i++)
613 frame_to_enc[i] = &out_frame;
633 if (p_enc_api_param[0].low_delay_mode <= 0 && encoder_opened)
647 recycle_hw_frame_for_scaler = 1;
648 for (i = 0; i < output_total; i++)
650 if (scale_params[i].enabled)
652 if(!hw_frame_ref_flag)
654 hw_frame_ref_flag = 1;
660 frame_to_enc[i] = &filter_out_frame[i];
662 else if (drawbox_params.
enabled)
664 if(!hw_frame_ref_flag)
666 hw_frame_ref_flag = 1;
672 for (i = 0; i < output_total; i++)
674 frame_to_enc[i] = &filter_out_frame[0];
679 if (!scale_params[i].enabled)
680 recycle_hw_frame_for_scaler = 0;
689 if((hw_frame_ref_flag) && (recycle_hw_frame_for_scaler))
691 hw_frame_ref_flag = 0;
697 for (i = 0; i < output_total; i++)
702 if (scale_params[i].enabled)
704 else if (drawbox_params.
enabled)
710 ret =
encoder_open2(&ctx, enc_ctx, p_enc_api_param, output_total, enc_conf_params,
711 enc_gop_params, &out_frame.
data.
frame, output_width, output_height,
712 fps_num, fps_den, bitrate, enc_codec_format, enc_pix_fmt,
723 output_width, output_height, output_total, output_fp);
733 ni_log(
NI_LOG_ERROR,
"Failed to get encoded sequence header packet, retcode %d\n", receive_rc);
741 for (i = 0; i < output_total; i++)
745 send_rc =
encoder_send_data2(&ctx, &enc_ctx[i], frame_to_enc[i], &enc_in_frame, output_width[i], output_height[i]);
786 output_width, output_height, output_total, output_fp);
788 for (i = 0; receive_rc >= 0 && i < output_total; i++)
793 end_of_all_streams = 0;
798 end_of_all_streams = 1;
804 ni_log(
NI_LOG_INFO,
"Decoder stats: received %u frames, fps %.2f, total bytes %u\n",
808 for (i = 0; i < output_total; i++)
810 ni_log(
NI_LOG_INFO,
"Encoder %d stats: received %u packets, fps %.2f, total bytes %u\n",
831 for (i = 0; i < output_total; i++)
837 for (i = 0; i < output_total; i++)
843 for (i = 0; i < output_total; i++)
846 if (output_fp[i] != NULL)
848 fclose(output_fp[i]);
850 if (scale_params[i].enabled)
871 free(p_dec_api_param);
872 free(p_enc_api_param);