libxcoder  5.2.0
ni_xcoder_transcode_filter.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_transcode_filter.c
24  *
25  * \brief Video transcoding and filtering demo application directly using
26  * 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  "Video transcoding demo application directly using Netint Libxcoder version %s\n"
47  "Usage: ni_xcoder_transcode_filter [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  int send_rc = NI_TEST_RETCODE_SUCCESS, receive_rc = NI_TEST_RETCODE_SUCCESS, rx_size = 0;
122  void *p_stream_info = NULL;
123  int fps_num = 30, fps_den = 1, bitrate = 200000;
124  uint64_t current_time, previous_time;
125  ni_session_data_io_t in_pkt = {0};
126  ni_session_data_io_t out_frame = {0};
127  ni_session_data_io_t filter_out_frame = {0};
128  ni_session_data_io_t *frame_to_enc = NULL;
129  ni_session_data_io_t enc_in_frame = {0};
130  ni_session_data_io_t out_packet[MAX_OUTPUT_FILES] = {0};
131  niFrameSurface1_t *p_hwframe = NULL;
132  int encoder_opened = 0, end_of_all_streams = 0;
133  ni_scale_params_t scale_params = {0};
134  ni_drawbox_params_t drawbox_params = {0};
135  ni_pix_fmt_t enc_pix_fmt = NI_PIX_FMT_YUV420P;
136 
137  int opt;
138  int opt_index;
139  const char *opt_string = "hvi:o:m:n:l:c:r:d:e:g:uf:";
140  static struct option long_options[] = {
141  {"help", no_argument, NULL, 'h'},
142  {"version", no_argument, NULL, 'v'},
143  {"input", required_argument, NULL, 'i'},
144  {"output", required_argument, NULL, 'o'},
145  {"dec-codec", required_argument, NULL, 'n'},
146  {"enc-codec", required_argument, NULL, 'm'},
147  {"loglevel", required_argument, NULL, 'l'},
148  {"card", required_argument, NULL, 'c'},
149  {"repeat", required_argument, NULL, 'r'},
150  {"decoder-params", required_argument, NULL, 'd'},
151  {"encoder-params", required_argument, NULL, 'e'},
152  {"encoder-gop", required_argument, NULL, 'g'},
153  {"user-data-sei-passthru", no_argument, NULL, 'u'},
154  {"vf", required_argument, NULL, 'f'},
155  {NULL, 0, NULL, 0},
156  };
157 
158  while ((opt = getopt_long(argc, argv, opt_string, long_options, &opt_index)) != -1)
159  {
160  switch (opt)
161  {
162  case 'h':
163  print_usage();
164  ret = 0;
165  goto end;
166  case 'v':
167  print_version();
168  ret = 0;
169  goto end;
170  case 'i':
171  strcpy(in_filename, optarg);
172  break;
173  case 'o':
174  if (o_index == MAX_OUTPUT_FILES)
175  {
176  ni_log(NI_LOG_ERROR, "Error: number of output files cannot exceed %d\n", MAX_OUTPUT_FILES);
177  ret = -1;
178  goto end;
179  }
180 
181  for (i = 0; i < o_index; i++)
182  {
183  if (0 == strcmp(out_filename[i], optarg))
184  {
185  ni_log(NI_LOG_ERROR, "Error: output file names must be unique: %s\n", optarg);
186  ret = -1;
187  goto end;
188  }
189  }
190 
191  strcpy(out_filename[o_index], optarg);
192  o_index++;
193  break;
194  case 'm':
195  // Accept both upper and lower case
196  for (i = 0; i < strlen(optarg); i++)
197  {
198  optarg[i] = (char)tolower((unsigned char)optarg[i]);
199  }
200  if (strcmp(optarg, "a") == 0 || strcmp(optarg, "avc") == 0)
201  {
202  dec_codec_format = NI_CODEC_FORMAT_H264;
203  }
204  else if (strcmp(optarg, "h") == 0 || strcmp(optarg, "hevc") == 0)
205  {
206  dec_codec_format = NI_CODEC_FORMAT_H265;
207  }
208  else if (strcmp(optarg, "v") == 0 || strcmp(optarg, "vp9") == 0)
209  {
210  dec_codec_format = NI_CODEC_FORMAT_VP9;
211  }
212  else
213  {
214  ni_log(NI_LOG_ERROR, "Error: Invalid value \"%s\" for -m | --dec-codec option\n"
215  "Must be one of [a|avc, h|hevc, v|vp9]\n", optarg);
216  ret = -1;
217  goto end;
218  }
219  break;
220  case 'n':
221  // Accept both upper and lower case
222  for (i = 0; i < strlen(optarg); i++)
223  {
224  optarg[i] = (char)tolower((unsigned char)optarg[i]);
225  }
226  if (strcmp(optarg, "a") == 0 || strcmp(optarg, "avc") == 0)
227  {
228  enc_codec_format = NI_CODEC_FORMAT_H264;
229  }
230  else if (strcmp(optarg, "h") == 0 || strcmp(optarg, "hevc") == 0)
231  {
232  enc_codec_format = NI_CODEC_FORMAT_H265;
233  }
234  else if (strcmp(optarg, "x") == 0 || strcmp(optarg, "av1") == 0)
235  {
236  enc_codec_format = NI_CODEC_FORMAT_AV1;
237  }
238  else
239  {
240  ni_log(NI_LOG_ERROR, "Error: Invalid value \"%s\" for -n | --enc-codec option\n"
241  "Must be one of [a|avc, h|hevc, x|av1]\n", optarg);
242  ret = -1;
243  goto end;
244  }
245  break;
246  case 'l':
247  log_level = arg_to_ni_log_level(optarg);
248  if (log_level != NI_LOG_INVALID)
249  {
250  ni_log_set_level(log_level);
251  }
252  else
253  {
254  ni_log(NI_LOG_ERROR, "Error: Invalid value \"%s\" for -l | --loglevel option\n"
255  "Must be one of [none, fatal, error, info, debug, trace]\n", optarg);
256  ret = -1;
257  goto end;
258  }
259  break;
260  case 'c':
261  xcoderGUID = (int)strtol(optarg, &n, 10);
262  if (n == optarg || *n != '\0' || xcoderGUID < 0)
263  {
264  ni_log(NI_LOG_ERROR, "Error: Invalid value \"%s\" for -c | --card option\n"
265  "Must be a non-negative integer\n", optarg);
266  ret = -1;
267  goto end;
268  }
269  break;
270  case 'r':
271  ctx.loops_left = strtol(optarg, &n, 10);
272  if (n == optarg || *n != '\0' || ctx.loops_left <= 0)
273  {
274  ni_log(NI_LOG_ERROR, "Error: Invalid value \"%s\" for -r | --repeat option\n"
275  "Must be a positive integer\n", optarg);
276  ret = -1;
277  goto end;
278  }
279  break;
280  case 'd':
281  strcpy(dec_conf_params, optarg);
282  break;
283  case 'e':
284  if (e_index == MAX_OUTPUT_FILES)
285  {
286  ni_log(NI_LOG_ERROR, "Error: number of encoder config cannot exceed %d\n", MAX_OUTPUT_FILES);
287  ret = -1;
288  goto end;
289  }
290  strcpy(enc_conf_params[e_index], optarg);
291  e_index++;
292  break;
293  case 'g':
294  if (g_index == MAX_OUTPUT_FILES)
295  {
296  ni_log(NI_LOG_ERROR, "Error: number of encoder gop settings cannot exceed %d\n", MAX_OUTPUT_FILES);
297  ret = -1;
298  goto end;
299  }
300  strcpy(enc_gop_params[g_index], optarg);
301  g_index++;
302  break;
303  case 'u':
304  user_data_sei_passthru = 1;
305  break;
306  case 'f':
307  strcpy(filter_conf_params, optarg);
308  break;
309  default:
310  print_usage();
311  ret = -1;
312  goto end;
313  }
314  }
315 
316  if (!in_filename[0]) {
317  ni_log(NI_LOG_ERROR, "Error: Missing input file argument (-i | --input)\n");
318  ret = -1;
319  goto end;
320  }
321 
322  if (o_index == 0) {
323  ni_log(NI_LOG_ERROR, "Error: Missing output file argument (-o | --output)\n");
324  ret = -1;
325  goto end;
326  }
327 
328  if (dec_codec_format == -1) {
329  ni_log(NI_LOG_ERROR, "Error: Missing decoder codec argument (-m | --dec-codec)\n");
330  ret = -1;
331  goto end;
332  }
333 
334  if (enc_codec_format == -1) {
335  ni_log(NI_LOG_ERROR, "Error: Missing encoder codec argument (-n | --enc-codec)\n");
336  ret = -1;
337  goto end;
338  }
339 
340  ret = read_and_cache_file(&ctx, in_filename);
341  if (ret)
342  {
343  ni_log(NI_LOG_ERROR, "Error: Read input file failure\n");
344  goto end;
345  }
346 
347  output_total = o_index;
348  for (i = 0; i < output_total; i++)
349  {
350  if (strcmp(out_filename[i], "null") != 0 &&
351  strcmp(out_filename[i], "/dev/null") != 0)
352  {
353  output_fp[i] = fopen(out_filename[i], "wb");
354  if (!output_fp[i])
355  {
356  ni_log(NI_LOG_ERROR, "Error: Failed to open %s\n", out_filename[i]);
357  ret = -1;
358  goto end;
359  }
360  ni_log(NI_LOG_INFO, "Opened output file: %s\n", out_filename[i]);
361  } else
362  {
363  output_fp[i] = NULL;
364  ni_log(NI_LOG_INFO, "Note: Requested NULL output for index %d, no output file will be generated\n", i);
365  }
366  }
367 
368  p_dec_api_param = malloc(sizeof(ni_xcoder_params_t));
369  if (!p_dec_api_param)
370  {
371  ni_log(NI_LOG_ERROR, "Error: failed to allocate p_dec_api_param\n");
372  ret = -1;
373  goto end;
374  }
375 
376  p_enc_api_param = calloc(output_total, sizeof(ni_xcoder_params_t));
377  if (!p_enc_api_param)
378  {
379  ni_log(NI_LOG_ERROR, "Error: Failed to allocate memory for p_enc_api_param\n");
380  ret = -1;
381  goto end;
382  }
383 
384  if (dec_codec_format == NI_CODEC_FORMAT_H264)
385  {
386  ret = probe_h264_stream_info(&ctx, &avc_sps);
387  if (ret)
388  {
390  "ERROR: Failed to probe input file as H.264, file format not supported!\n");
391  goto end;
392  }
393 
394  bit_depth = avc_sps.bit_depth_luma;
395  input_width = avc_sps.width;
396  input_height = avc_sps.height;
397  ni_log(NI_LOG_DEBUG, "Using probed H.264 source info: %d bits, resolution %dx%d\n",
398  bit_depth, input_width, input_height);
399  } else if (dec_codec_format == NI_CODEC_FORMAT_H265)
400  {
401  ret = probe_h265_stream_info(&ctx, &hevc_sps);
402  if (ret)
403  {
405  "ERROR: Failed to probe input file as H.265, file format not supported!\n");
406  goto end;
407  }
408  bit_depth = hevc_sps.bit_depth_chroma;
409  input_width = (int)(hevc_sps.width -
410  (hevc_sps.pic_conf_win.left_offset +
411  hevc_sps.pic_conf_win.right_offset));
412  input_height = (int)(hevc_sps.height -
413  (hevc_sps.pic_conf_win.top_offset +
414  hevc_sps.pic_conf_win.bottom_offset));
415  ni_log(NI_LOG_INFO, "Using probed H.265 source info: %d bits, resolution %dx%d\n",
416  bit_depth, input_width, input_height);
417  } else if (dec_codec_format == NI_CODEC_FORMAT_VP9)
418  {
419  ret = probe_vp9_stream_info(&ctx, &vp9_info);
420  if (ret)
421  {
423  "ERROR: Failed to probe input file as VP9, file format not supported!\n");
424  goto end;
425  }
426  bit_depth = vp9_info.profile ? 10 : 8;
427  input_width = vp9_info.width;
428  input_height = vp9_info.height;
430  "Using probed VP9 source info: %d bits, resolution %dx%d, timebase %u/%u\n",
431  bit_depth, input_width, input_height,
432  vp9_info.timebase.den, vp9_info.timebase.num);
433  }
434 
435  // set up decoder config params with some hard-coded values
436  ret = ni_decoder_init_default_params(p_dec_api_param, 25, 1, 200000, input_width, input_height);
437  if (ret)
438  {
439  ni_log(NI_LOG_ERROR, "Error: Failed to init default decoder config\n");
440  goto end;
441  }
442 
443  ret = ni_device_session_context_init(&dec_ctx);
444  if (ret)
445  {
446  ni_log(NI_LOG_ERROR, "Error: Failed to init decoder context\n");
447  goto end;
448  }
449 
450  dec_ctx.codec_format = dec_codec_format;
451  dec_ctx.src_bit_depth = bit_depth;
452  dec_ctx.bit_depth_factor = 1;
453  if (10 == dec_ctx.src_bit_depth)
454  {
455  dec_ctx.bit_depth_factor = 2;
456  }
457  if ((NI_CODEC_FORMAT_H264 == dec_codec_format) || (NI_CODEC_FORMAT_H265 == dec_codec_format))
458  dec_ctx.enable_user_data_sei_passthru = user_data_sei_passthru;
459 
460  // check and set ni_decoder_params from --xcoder-params
461  ret = ni_retrieve_decoder_params(dec_conf_params, p_dec_api_param, &dec_ctx);
462  if (ret)
463  {
464  ni_log(NI_LOG_ERROR, "Error: decoder config params parsing error\n");
465  goto end;
466  }
467 
468  // Decode, use all the parameters specified by user
469  ret = decoder_open_session(&dec_ctx, xcoderGUID, p_dec_api_param);
470  if (ret)
471  {
472  ni_log(NI_LOG_ERROR, "Error: Failed to open decoder session\n");
473  goto end;
474  }
475 
476  for (i = 0; i < output_total; i++)
477  {
478  if (ni_device_session_context_init(&enc_ctx[i]) < 0)
479  {
480  ni_log(NI_LOG_ERROR, "Error: init encoder %d context error\n", i);
481  ret = -1;
482  goto end;
483  }
484  }
485 
486  for (i = 0; i < output_total; i++)
487  {
488  enc_ctx[i].codec_format = enc_codec_format;
489  }
490 
491  if (dec_codec_format == NI_CODEC_FORMAT_H264)
492  p_stream_info = &avc_sps;
493  else if (dec_codec_format == NI_CODEC_FORMAT_H265)
494  p_stream_info = &hevc_sps;
495  else if (dec_codec_format == NI_CODEC_FORMAT_VP9)
496  {
497  p_stream_info = &vp9_info;
498  fps_num = vp9_info.timebase.den;
499  fps_den = vp9_info.timebase.num;
500  }
501 
502  output_width = input_width;
503  output_height = input_height;
504 
505  if (filter_conf_params[0])
506  {
507  if (!dec_ctx.hw_action) {
508  ni_log(NI_LOG_ERROR, "Error: filters are only supported when hwframe is enabled (out=hw)\n");
509  ret = -1;
510  goto end;
511  }
512  ret = retrieve_filter_params(filter_conf_params, &scale_params, &drawbox_params);
513  if (ret)
514  {
515  ni_log(NI_LOG_ERROR, "Error: failed to parse filter parameters: %s\n", filter_conf_params);
516  goto end;
517  }
518  }
519 
520  if (scale_params.enabled)
521  {
522  ret = ni_device_session_context_init(&sca_ctx);
523  if (ret)
524  {
525  ni_log(NI_LOG_ERROR, "Error: Failed to init scale context\n");
526  goto end;
527  }
528  output_width = scale_params.width;
529  output_height = scale_params.height;
530  }
531  else if (drawbox_params.enabled)
532  {
533  ret = ni_device_session_context_init(&crop_ctx);
534  if (ret)
535  {
536  ni_log(NI_LOG_ERROR, "Error: Failed to init crop context\n");
537  goto end;
538  }
539  ret = ni_device_session_context_init(&pad_ctx);
540  if (ret)
541  {
542  ni_log(NI_LOG_ERROR, "Error: Failed to init pad context\n");
543  goto end;
544  }
545  ret = ni_device_session_context_init(&ovly_ctx);
546  if (ret)
547  {
548  ni_log(NI_LOG_ERROR, "Error: Failed to init overlay context\n");
549  goto end;
550  }
551  ret = ni_device_session_context_init(&fmt_ctx);
552  if (ret)
553  {
554  ni_log(NI_LOG_ERROR, "Error: Failed to init format context\n");
555  goto end;
556  }
557  }
558 
559  ni_log(NI_LOG_INFO, "Starting to transcode: HWFrames %d, video resolution %dx%d -> %dx%d\n",
560  dec_ctx.hw_action, input_width, input_height, output_width, output_height);
561 
562  ctx.start_time = ni_gettime_ns();
564 
565  while (!end_of_all_streams &&
566  (send_rc == NI_TEST_RETCODE_SUCCESS || receive_rc == NI_TEST_RETCODE_SUCCESS ||
567  (send_rc == NI_TEST_RETCODE_EAGAIN && receive_rc == NI_TEST_RETCODE_EAGAIN)))
568  {
569  // bitstream Sending
570 decode_send:
571  send_rc = decoder_send_data(&ctx, &dec_ctx, &in_pkt, input_width, input_height, p_stream_info);
572  if (send_rc < 0)
573  {
574  ni_log(NI_LOG_ERROR, "Error: decoder send packet failed\n");
575  ret = send_rc;
576  break;
577  }
578 
579  // YUV Receiving: not writing to file
580  receive_rc = decoder_receive_data(&ctx, &dec_ctx, &out_frame, input_width,
581  input_height, NULL, 0, &rx_size);
582  frame_to_enc = &out_frame;
583  if (receive_rc < 0)
584  {
585  ni_log(NI_LOG_ERROR, "Error: decoder receive frame failed\n");
586  ret = receive_rc;
587  break;
588  }
589  else if (receive_rc == NI_TEST_RETCODE_EAGAIN)
590  {
591  if (!dec_ctx.hw_action)
592  {
594  } else
595  {
596  ni_frame_buffer_free(&(out_frame.data.frame));
597  }
598 
599  // use first encode config low delay flag for call flow
600  if (p_enc_api_param[0].low_delay_mode <= 0 && encoder_opened)
601  {
602  ni_log(NI_LOG_DEBUG, "no decoder output, jump to encoder receive!\n");
603  goto encode_recv;
604  } else
605  {
606  ni_log(NI_LOG_DEBUG, "no decoder output, encode low_delay, jump to decoder send!\n");
607  goto decode_send;
608  }
609  }
610  else if (receive_rc != NI_TEST_RETCODE_END_OF_STREAM)
611  {
612  if (scale_params.enabled)
613  {
614  p_hwframe = (niFrameSurface1_t *)out_frame.data.frame.p_data[3];
615  ni_hw_frame_ref(p_hwframe);
616  scale_filter(&sca_ctx, &out_frame.data.frame, &filter_out_frame, xcoderGUID, scale_params.width,
617  scale_params.height, ni_to_gc620_pix_fmt(dec_ctx.pixel_format), scale_params.format);
618  ni_hw_frame_unref(p_hwframe->ui16FrameIdx);
619  frame_to_enc = &filter_out_frame;
620  }
621  else if (drawbox_params.enabled)
622  {
623  p_hwframe = (niFrameSurface1_t *)out_frame.data.frame.p_data[3];
624  ni_hw_frame_ref(p_hwframe);
625  drawbox_filter(&crop_ctx, &pad_ctx, &ovly_ctx, &fmt_ctx, &out_frame.data.frame, &filter_out_frame,
626  &drawbox_params, xcoderGUID, ni_to_gc620_pix_fmt(dec_ctx.pixel_format), GC620_I420);
627  ni_hw_frame_unref(p_hwframe->ui16FrameIdx);
628  frame_to_enc = &filter_out_frame;
629  }
630 
631  if (!encoder_opened)
632  {
633  p_hwframe = dec_ctx.hw_action == NI_CODEC_HW_ENABLE ?
634  (niFrameSurface1_t *)frame_to_enc->data.frame.p_data[3] : NULL;
635 
636  if (scale_params.enabled)
637  enc_pix_fmt = gc620_to_ni_pix_fmt(scale_params.format);
638  else if (drawbox_params.enabled)
639  enc_pix_fmt = NI_PIX_FMT_YUV420P;
640  else
641  enc_pix_fmt = dec_ctx.pixel_format;
642 
643  ret = encoder_open(enc_ctx, p_enc_api_param, output_total, enc_conf_params,
644  enc_gop_params, &out_frame.data.frame, output_width, output_height,
645  fps_num, fps_den, bitrate, enc_codec_format, enc_pix_fmt,
646  out_frame.data.frame.aspect_ratio_idc, xcoderGUID, p_hwframe, 0, false);
647  if (ret != 0)
648  {
649  break;
650  }
651  encoder_opened = 1;
652  }
653  }
654 
655  //encode_send
656  for (i = 0; i < output_total; i++)
657  {
658  ctx.curr_enc_index = i;
659  // YUV Sending
660  send_rc = encoder_send_data2(&ctx, &enc_ctx[i], frame_to_enc, &enc_in_frame, output_width, output_height);
661  if (send_rc < 0) //Error
662  {
663  if (dec_ctx.hw_action)
664  {
665  p_hwframe = (niFrameSurface1_t *)frame_to_enc->data.frame.p_data[3];
666  ni_hw_frame_ref(p_hwframe);
667  } else
668  {
669  ni_decoder_frame_buffer_free(&frame_to_enc->data.frame);
670  }
671  break;
672  } else if (send_rc == NI_TEST_RETCODE_EAGAIN)
673  {
674  // need to resend
675  i--;
676  continue;
677  } else if (dec_ctx.hw_action && !ctx.enc_eos_sent[i])
678  {
679  p_hwframe = (niFrameSurface1_t *)frame_to_enc->data.frame.p_data[3];
680  ni_hw_frame_ref(p_hwframe);
681  }
682  }
683 
684  // encoder send handling
685  if (send_rc < 0)
686  {
687  break;
688  } else if (dec_ctx.hw_action)
689  {
690  ni_frame_wipe_aux_data(&frame_to_enc->data.frame);
691  } else
692  {
693  ni_decoder_frame_buffer_free(&frame_to_enc->data.frame);
694  }
695 
696 encode_recv:
697  receive_rc = encoder_receive(&ctx, enc_ctx, &enc_in_frame, out_packet,
698  output_width, output_height, output_total, output_fp);
699  for (i = 0; receive_rc >= 0 && i < output_total; i++)
700  {
701  if (!ctx.enc_eos_received[i])
702  {
703  ni_log(NI_LOG_DEBUG, "enc %d continues to read!\n", i);
704  end_of_all_streams = 0;
705  break;
706  } else
707  {
708  ni_log(NI_LOG_DEBUG, "enc %d eos !\n", i);
709  end_of_all_streams = 1;
710  }
711  }
712 
714  if (current_time - previous_time >= (uint64_t)1000000000) {
715  ni_log(NI_LOG_INFO, "Decoder stats: received %u frames, fps %.2f, total bytes %u\n",
716  ctx.num_frames_received,
717  (float)ctx.num_frames_received / (float)(current_time - ctx.start_time) * (float)1000000000,
719  for (i = 0; i < output_total; i++)
720  {
721  ni_log(NI_LOG_INFO, "Encoder %d stats: received %u packets, fps %.2f, total bytes %u\n",
722  i, ctx.num_packets_received[i],
723  (float)enc_ctx[i].frame_num / (float)(current_time - ctx.start_time) * (float)1000000000,
724  ctx.enc_total_bytes_received[i]);
725  }
727  }
728  }
729 
730  decoder_stat_report_and_close(&ctx, &dec_ctx);
731  encoder_stat_report_and_close(&ctx, enc_ctx, output_total);
732 
733 end:
735  if (dec_ctx.hw_action == NI_CODEC_HW_ENABLE)
736  {
737  ni_frame_buffer_free(&out_frame.data.frame);
738  } else
739  {
741  }
742  ni_frame_buffer_free(&filter_out_frame.data.frame);
743  ni_frame_buffer_free(&enc_in_frame.data.frame);
744  for (i = 0; i < output_total; i++)
745  {
746  ni_packet_buffer_free(&out_packet[i].data.packet);
747  }
748 
750  for (i = 0; i < output_total; i++)
751  {
752  ni_device_session_context_clear(&enc_ctx[i]);
753  if (output_fp[i] != NULL)
754  {
755  fclose(output_fp[i]);
756  }
757  }
758  if (scale_params.enabled)
759  {
761  }
762  if (drawbox_params.enabled)
763  {
768  }
769 
770  free(ctx.file_cache);
771  free(p_dec_api_param);
772  free(p_enc_api_param);
773 
774  return ret;
775 }
_ni_scale_params::height
int height
Definition: ni_filter_utils.h:37
ni_decode_utils.h
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
_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_frame_buffer_free
ni_retcode_t ni_frame_buffer_free(ni_frame_t *p_frame)
Free frame buffer that was previously allocated with either ni_frame_buffer_alloc or ni_encoder_frame...
Definition: ni_device_api.c:3561
ni_hw_frame_ref
void ni_hw_frame_ref(const niFrameSurface1_t *p_surface)
Definition: ni_generic_utils.c:658
_ni_vp9_header_info::den
uint32_t den
Definition: ni_decode_utils.h:347
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
_ni_frame::aspect_ratio_idc
uint8_t aspect_ratio_idc
Definition: ni_device_api.h:2686
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_hw_frame_unref
void ni_hw_frame_unref(uint16_t hwframe_index)
Definition: ni_generic_utils.c:679
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
_ni_session_data_io::packet
ni_packet_t packet
Definition: ni_device_api.h:2871
ni_encode_utils.h
current_time
struct timeval current_time
Definition: ni_p2p_read_test.c:80
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
ni_packet_buffer_free
ni_retcode_t ni_packet_buffer_free(ni_packet_t *p_packet)
Free packet buffer that was previously allocated with ni_packet_buffer_alloc.
Definition: ni_device_api.c:3843
_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
drawbox_filter
int drawbox_filter(ni_session_context_t *p_crop_ctx, ni_session_context_t *p_pad_ctx, ni_session_context_t *p_overlay_ctx, ni_session_context_t *p_fmt_ctx, ni_frame_t *p_frame_in, ni_session_data_io_t *p_data_out, ni_drawbox_params_t *p_box_params, int iXcoderGUID, int input_format, int output_format)
Use crop->pad->overlay to simulate a drawbox filter.
Definition: ni_filter_utils.c:375
_ni_session_context::bit_depth_factor
int bit_depth_factor
Definition: ni_device_api.h:1494
_ni_h265_sps_t::width
int width
Definition: ni_decode_utils.h:317
decoder_receive_data
int decoder_receive_data(ni_demo_context_t *p_ctx, ni_session_context_t *p_dec_ctx, ni_session_data_io_t *p_out_data, int output_video_width, int output_video_height, FILE *p_file, int write_to_file, int *p_rx_size)
Receive decoded output data from decoder.
Definition: ni_decode_utils.c:2416
previous_time
struct timeval previous_time
Definition: ni_p2p_read_test.c:79
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
_niFrameSurface1::ui16FrameIdx
uint16_t ui16FrameIdx
Definition: ni_device_api.h:2795
_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_to_gc620_pix_fmt
int ni_to_gc620_pix_fmt(ni_pix_fmt_t pix_fmt)
Definition: ni_generic_utils.c:117
_ni_session_context::src_bit_depth
int src_bit_depth
Definition: ni_device_api.h:1492
NI_TEST_RETCODE_END_OF_STREAM
#define NI_TEST_RETCODE_END_OF_STREAM
Definition: ni_generic_utils.h:52
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_demo_context::num_frames_received
uint64_t num_frames_received
Definition: ni_generic_utils.h:128
_ni_h264_sps_t
Definition: ni_decode_utils.h:70
_ni_demo_context::enc_eos_sent
int enc_eos_sent[MAX_OUTPUT_FILES]
Definition: ni_generic_utils.h:147
_ni_vp9_header_info::num
uint32_t num
Definition: ni_decode_utils.h:348
NI_TEST_RETCODE_EAGAIN
#define NI_TEST_RETCODE_EAGAIN
Definition: ni_generic_utils.h:53
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
encoder_receive
int encoder_receive(ni_demo_context_t *p_ctx, ni_session_context_t *enc_ctx_list, ni_session_data_io_t *in_frame, ni_session_data_io_t *pkt, int width, int height, int output_total, FILE **pfs_list)
Definition: ni_encode_utils.c:2181
_ni_h265_sps_t::height
int height
Definition: ni_decode_utils.h:318
_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
_ni_h265_window_t::right_offset
unsigned int right_offset
Definition: ni_decode_utils.h:139
_ni_session_data_io
Definition: ni_device_api.h:2866
_ni_h265_sps_t
Definition: ni_decode_utils.h:241
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_TEST_RETCODE_SUCCESS
#define NI_TEST_RETCODE_SUCCESS
Definition: ni_generic_utils.h:51
_ni_h264_sps_t::width
int width
Definition: ni_decode_utils.h:72
main
int main(int argc, char *argv[])
Definition: ni_xcoder_transcode_filter.c:90
getopt_long
int getopt_long(int argc, char *argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: ni_getopt.c:99
_ni_h264_sps_t::bit_depth_luma
int bit_depth_luma
bit_depth_luma_minus8 + 8
Definition: ni_decode_utils.h:128
GC620_I420
#define GC620_I420
Definition: ni_device_api.h:193
_ni_vp9_header_info::profile
int profile
Definition: ni_decode_utils.h:341
decoder_send_data
int decoder_send_data(ni_demo_context_t *p_ctx, ni_session_context_t *p_dec_ctx, ni_session_data_io_t *p_in_data, int input_video_width, int input_video_height, void *stream_info)
Send decoder input data.
Definition: ni_decode_utils.c:2228
_ni_h265_window_t::top_offset
unsigned int top_offset
Definition: ni_decode_utils.h:140
_ni_session_context::frame_num
uint64_t frame_num
Definition: ni_device_api.h:1531
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
_ni_frame::p_data
uint8_t * p_data[NI_MAX_NUM_DATA_POINTERS]
Definition: ni_device_api.h:2663
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_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
_ni_demo_context::file_cache
uint8_t * file_cache
Definition: ni_generic_utils.h:114
_ni_session_context::codec_format
uint32_t codec_format
Definition: ni_device_api.h:1486
scale_filter
int scale_filter(ni_session_context_t *p_ctx, ni_frame_t *p_frame_in, ni_session_data_io_t *p_data_out, int iXcoderGUID, int scale_width, int scale_height, int in_format, int out_format)
Do a scale and/or format-change operation.
Definition: ni_filter_utils.c:513
_ni_demo_context::dec_total_bytes_received
uint64_t dec_total_bytes_received
Definition: ni_generic_utils.h:125
_ni_session_data_io::frame
ni_frame_t frame
Definition: ni_device_api.h:2870
_ni_demo_context::num_packets_received
uint64_t num_packets_received[MAX_OUTPUT_FILES]
Definition: ni_generic_utils.h:130
_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_demo_context::enc_eos_received
int enc_eos_received[MAX_OUTPUT_FILES]
Definition: ni_generic_utils.h:148
_ni_session_context::enable_user_data_sei_passthru
int enable_user_data_sei_passthru
Definition: ni_device_api.h:1614
ni_util.h
Utility definitions.
encoder_send_data2
int encoder_send_data2(ni_demo_context_t *p_ctx, ni_session_context_t *p_enc_ctx, ni_session_data_io_t *p_dec_out_data, ni_session_data_io_t *p_enc_in_data, int input_video_width, int input_video_height)
Definition: ni_encode_utils.c:876
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
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_demo_context::enc_total_bytes_received
uint64_t enc_total_bytes_received[MAX_OUTPUT_FILES]
Definition: ni_generic_utils.h:127
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_demo_context::curr_enc_index
uint8_t curr_enc_index
Definition: ni_generic_utils.h:123
ni_getopt.h
Implementation of getopt() and getopt_long() for Windows environment.
_ni_drawbox_params
Definition: ni_filter_utils.h:41
ni_decoder_frame_buffer_free
ni_retcode_t ni_decoder_frame_buffer_free(ni_frame_t *p_frame)
Free decoder frame buffer that was previously allocated with ni_decoder_frame_buffer_alloc,...
Definition: ni_device_api.c:3644
NI_CODEC_FORMAT_H265
@ NI_CODEC_FORMAT_H265
Definition: ni_device_api.h:912
ni_frame_wipe_aux_data
void ni_frame_wipe_aux_data(ni_frame_t *frame)
Free and remove all auxiliary data from the frame.
Definition: ni_device_api.c:4115