libxcoder  3.5.1
ni_logan_p2p_test.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_p2p_test.c
24  *
25  * \brief Application for performing video processing using libxcoder API and
26  * P2P DMA. Its code provides examples on how to programatically use
27  * libxcoder API in conjunction with P2P DMA.
28  ******************************************************************************/
29 
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <stdint.h>
34 
35 #define _POSIX_C_SOURCE 200809L
36 #include <getopt.h>
37 #include <unistd.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <sys/time.h>
42 #include <time.h>
43 
44 #include "ni_device_api_logan.h"
45 #include "ni_util_logan.h"
46 #include "ni_av_codec_logan.h"
47 
48 // max YUV frame size
49 #define MAX_YUV_FRAME_SIZE (7680 * 4320 * 3 / 2)
50 #define POOL_SIZE 2
51 #define FILE_NAME_LEN 256
52 
53 int send_fin_flag = 0;
55 int enc_eos_sent = 0;
56 
57 uint32_t number_of_frames = 0;
58 uint32_t number_of_packets = 0;
59 uint64_t data_left_size = 0;
60 int g_repeat = 1;
61 
62 struct timeval start_time;
63 struct timeval previous_time;
64 struct timeval current_time;
65 
66 time_t start_timestamp = 0;
67 time_t previous_timestamp = 0;
68 time_t current_timestamp = 0;
69 
70 unsigned long total_file_size = 0;
71 
72 uint8_t *g_curr_cache_pos = NULL;
73 uint8_t *g_yuv_frame[POOL_SIZE] = {NULL, NULL};
74 
75 /* Convert string of log_level to log_level integer */
76 static int32_t log_str_to_level(char *log_str)
77 {
78  ni_log_level_t converted_log_level;
79  size_t i;
80  for (i = 0; i < strlen(log_str); i++)
81  log_str[i] = tolower((unsigned char) log_str[i]);
82 
83  if (strcmp(log_str, "none") == 0)
84  converted_log_level = NI_LOG_NONE;
85  else if (strcmp(log_str, "fatal") == 0)
86  converted_log_level = NI_LOG_FATAL;
87  else if (strcmp(log_str, "error") == 0)
88  converted_log_level = NI_LOG_ERROR;
89  else if (strcmp(log_str, "info") == 0)
90  converted_log_level = NI_LOG_INFO;
91  else if (strcmp(log_str, "debug") == 0)
92  converted_log_level = NI_LOG_DEBUG;
93  else if (strcmp(log_str, "trace") == 0)
94  converted_log_level = NI_LOG_TRACE;
95  else
96  converted_log_level = -16;
97  return converted_log_level;
98 }
99 
100 
101 /*!****************************************************************************
102  * \brief Exit on argument error
103  *
104  * \param[in] arg_name pointer to argument name
105  * [in] param pointer to provided parameter
106  *
107  * \return None program exit
108  ******************************************************************************/
109 void arg_error_exit(char *arg_name, char *param)
110 {
111  fprintf(stderr, "Error: unrecognized argument for %s, \"%s\"\n", arg_name,
112  param);
113  exit(-1);
114 }
115 
116 /*!****************************************************************************
117  * \brief Read the next frame
118  *
119  * \param[in] fd file descriptor of input file
120  * \param[out] p_dst pointer to place the frame
121  * \param[in] to_read number of bytes to copy to the pointer
122  *
123  * \return bytes copied
124  ******************************************************************************/
125 int read_next_chunk_from_file(int fd, uint8_t *p_dst, uint32_t to_read)
126 {
127  uint8_t *tmp_dst = p_dst;
129  "read_next_chunk_from_file:p_dst %p len %u totalSize %llu left %llu\n",
130  tmp_dst, to_read, (unsigned long long)total_file_size, (unsigned long long)data_left_size);
131  int to_copy = to_read;
132  unsigned long tmpFileSize = to_read;
133  if (data_left_size == 0)
134  {
135  if (g_repeat > 1)
136  {
138  g_repeat--;
139  ni_log(NI_LOG_DEBUG, "input processed %d left\n", g_repeat);
140  lseek(fd, 0, SEEK_SET); //back to beginning
141  } else
142  {
143  return 0;
144  }
145  } else if (data_left_size < to_read)
146  {
147  tmpFileSize = data_left_size;
148  to_copy = data_left_size;
149  }
150 
151  int one_read_size = read(fd, tmp_dst, to_copy);
152  if (one_read_size == -1)
153  {
154  fprintf(stderr, "Error: reading file, quit! left-to-read %lu\n",
155  tmpFileSize);
156  fprintf(stderr, "Error: input file read error\n");
157  return -1;
158  }
159  data_left_size -= one_read_size;
160 
161  return to_copy;
162 }
163 
164 /*!****************************************************************************
165  * \brief Load the input file into memory
166  *
167  * \param [in] filename name of input file
168  * [out] bytes_read number of bytes read from file
169  *
170  * \return 0 on success
171  * < 0 on error
172  ******************************************************************************/
173 int load_input_file(const char *filename, unsigned long *bytes_read)
174 {
175  struct stat info;
176 
177  /* Get information on the file */
178  if (stat(filename, &info) < 0)
179  {
180  fprintf(stderr, "Can't stat %s\n", filename);
181  return -1;
182  }
183 
184  /* Check the file size */
185  if (info.st_size <= 0)
186  {
187  fprintf(stderr, "File %s is empty\n", filename);
188  return -1;
189  }
190 
191  *bytes_read = info.st_size;
192 
193  return 0;
194 }
195 
196 /*!****************************************************************************
197 * \brief Recycle hw frames back to T408
198 *
199 * \param [in] p2p_frame - array of hw frames to recycle
200 *
201 * \return Returns the number of hw frames that have been recycled
202 *******************************************************************************/
203 #if 0
204 int recycle_frames(ni_logan_frame_t p2p_frame[])
205 {
206  int i;
207  int cnt = 0;
209 
210  for (i = 0; i < POOL_SIZE; i++)
211  {
212  rc = ni_hwframe_p2p_buffer_recycle(&p2p_frame[i]);
213 
214  if (rc != NI_RETCODE_SUCCESS)
215  {
216  fprintf(stderr, "Recycle failed\n");
217  }
218 
219  cnt += (rc == NI_RETCODE_SUCCESS) ? 1 : 0;
220  }
221 
222  return cnt;
223 }
224 #endif
225 /*!****************************************************************************
226  * \brief Reads YUV data from input file then calls a special libxcoder API
227  * function to transfer the YUV data into the hardware frame on
228  * the Quadra device.
229  *
230  * \param [in] p_upl_ctx pointer to upload session context
231  * [in] fd file descriptor of input file
232  * [in] p_yuv420p_frame address of pointer to YUV data
233  * [in] p_in_frame pointer to hardware frame
234  * [in] input_video_width video width
235  * [in] input_video_height video height
236  * [out] bytes_sent updated byte count of total data read
237  * [out] input_exhausted set to 1 when we reach end-of-file
238  *
239  * \return 0 on success
240  * -1 on error
241  ******************************************************************************/
243  uint8_t **p_yuv420p_frame, ni_logan_frame_t *p_in_frame,
244  int input_video_width, int input_video_height,
245  unsigned long *bytes_sent, int *input_exhausted)
246 {
247  static uint8_t tmp_buf[MAX_YUV_FRAME_SIZE];
248  void *p_buffer;
249  uint8_t *p_src[NI_LOGAN_MAX_NUM_DATA_POINTERS];
250  uint8_t *p_dst[NI_LOGAN_MAX_NUM_DATA_POINTERS];
251  int src_stride[NI_LOGAN_MAX_NUM_DATA_POINTERS];
252  int src_height[NI_LOGAN_MAX_NUM_DATA_POINTERS];
253  int dst_stride[NI_LOGAN_MAX_NUM_DATA_POINTERS] = {0, 0, 0, 0};
254  int dst_height[NI_LOGAN_MAX_NUM_DATA_POINTERS] = {0, 0, 0, 0};
255  int frame_size;
256  int chunk_size;
257  int Ysize;
258  int Usize;
259  int Vsize;
260  int total_size;
261 
262  ni_log(NI_LOG_DEBUG, "===> p2p upload_send_data <===\n");
263 
264  /* An 8-bit YUV420 planar frame occupies [(width x height x 3)/2] bytes */
265  frame_size = input_video_height * input_video_width * 3 / 2;
266 
267  chunk_size = read_next_chunk_from_file(fd, tmp_buf, frame_size);
268 
269  if (chunk_size == 0)
270  {
271  ni_log(NI_LOG_DEBUG, "p2p_upload_send_data: read chunk size 0, eos!\n");
272  *input_exhausted = 1;
273  }
274 
275  p_in_frame->video_width = input_video_width;
276  p_in_frame->video_height = input_video_height;
277  p_in_frame->extra_data_len = 0;
278 
279  ni_logan_get_hw_yuv420p_dim(input_video_width, input_video_height,
280  p_upl_ctx->bit_depth_factor, 1, dst_stride,
281  dst_height);
282 
283  ni_log(NI_LOG_DEBUG, "p_dst alloc linesize = %d/%d/%d src height=%d "
284  "dst height aligned = %d/%d/%d \n",
285  dst_stride[0], dst_stride[1], dst_stride[2],
286  input_video_height, dst_height[0], dst_height[1],
287  dst_height[2]);
288 
289  src_stride[0] = input_video_width * p_upl_ctx->bit_depth_factor;
290  src_stride[1] = src_stride[2] = src_stride[0] / 2;
291 
292  src_height[0] = input_video_height;
293  src_height[1] = src_height[0] / 2;
294  src_height[2] = src_height[1];
295 
296  p_src[0] = tmp_buf;
297  p_src[1] = tmp_buf + src_stride[0] * src_height[0];
298  p_src[2] = p_src[1] + src_stride[1] * src_height[1];
299 
300  Ysize = dst_stride[0] * dst_height[0];
301  Usize = dst_stride[1] * dst_height[1];
302  Vsize = dst_stride[2] * dst_height[2];
303 
304  total_size = Ysize + Usize + Vsize;
305  total_size = ((total_size + 4095) & ~4095);
306 
307  if (*p_yuv420p_frame == NULL)
308  {
309  if (ni_logan_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), total_size))
310  {
311  fprintf(stderr, "Can't alloc memory\n");
312  return -1;
313  }
314 
315  *p_yuv420p_frame = p_buffer;
316  }
317 
318  p_dst[0] = *p_yuv420p_frame;
319  p_dst[1] = *p_yuv420p_frame + Ysize;
320  p_dst[2] = *p_yuv420p_frame + Ysize + Usize;
321  p_dst[3] = NULL;
322 
323  ni_logan_copy_hw_yuv420p(p_dst, p_src, input_video_width, input_video_height, 1,
324  dst_stride, dst_height, src_stride, src_height);
325 #ifndef _WIN32
326  if (ni_logan_uploader_p2p_test_send(p_upl_ctx, *p_yuv420p_frame, total_size,
327  p_in_frame))
328  {
329  fprintf(stderr, "Error: failed ni_uploader_p2p_test_send()\n");
330  return -1;
331  } else
332 #endif
333  {
334  *bytes_sent = total_size;
335  }
336 
337  return 0;
338 }
339 
340 /*!****************************************************************************
341  * \brief Prepare frames to simulate P2P transfers
342  *
343  * \param [in] p_upl_ctx pointer to caller allocated uploader
344  * session context
345  * [in] input_video_width video width
346  * [in] input_video_height video height
347  * [out] p2p_frame array of hw frames
348  *
349  * \return 0 on success
350  * -1 on error
351  ******************************************************************************/
352 int p2p_prepare_frames(ni_logan_session_context_t *p_upl_ctx, int input_video_width,
353  int input_video_height, ni_logan_frame_t p2p_frame[])
354 {
355  int i;
356  int ret = 0;
357  int dst_stride[NI_LOGAN_MAX_NUM_DATA_POINTERS] = {0, 0, 0, 0};
358  int dst_height[NI_LOGAN_MAX_NUM_DATA_POINTERS] = {0, 0, 0, 0};
359  ni_logan_frame_t *p_in_frame;
360 
361  // Allocate memory for two hardware frames
362  for (i = 0; i < POOL_SIZE; i++)
363  {
364  p_in_frame = &p2p_frame[i];
365 
366  p_in_frame->start_of_stream = 0;
367  p_in_frame->end_of_stream = 0;
368  p_in_frame->force_key_frame = 0;
369  p_in_frame->extra_data_len = 0;
370 
371  ni_logan_get_hw_yuv420p_dim(input_video_width, input_video_height,
372  p_upl_ctx->bit_depth_factor, 1, dst_stride,
373  dst_height);
374 
375  // Allocate a hardware ni_frame structure for the encoder
377  p_in_frame, input_video_width, input_video_height,
378  (int)p_in_frame->extra_data_len) != NI_LOGAN_RETCODE_SUCCESS)
379  {
380  fprintf(stderr, "Error: could not allocate hw frame buffer!");
381  ret = -1;
382  goto fail_out;
383  }
384  // Acquire a hw frame from the upload session. This obtains a handle
385  // to Quadra memory from the previously created frame pool.
386 #ifndef _WIN32
387  if (ni_logan_device_session_acquire(p_upl_ctx, p_in_frame))
388  {
389  fprintf(stderr, "Error: failed ni_device_session_acquire()\n");
390  ret = -1;
391  goto fail_out;
392  }
393 #endif
394  }
395 
396  return ret;
397 
398 fail_out:
399  for (i = 0; i < POOL_SIZE; i++)
400  {
401  ni_logan_frame_buffer_free(&(p2p_frame[i]));
402  }
403 
404  return ret;
405 }
406 
407 /*!****************************************************************************
408  * \brief Send the Quadra encoder a hardware frame which triggers
409  * Quadra to encode the frame
410  *
411  * \param [in] p_enc_ctx pointer to encoder context
412  * [in] p_in_frame pointer to hw frame
413  * [in] input_exhausted flag indicating this is the last frame
414  * [in/out] need_to_resend flag indicating need to re-send
415  *
416  * \return 0 on success
417  * -1 on failure
418  ******************************************************************************/
420  ni_logan_frame_t *p_in_frame, int input_exhausted,
421  int *need_to_resend)
422 {
423  static int started = 0;
424  int oneSent;
426 
427  ni_log(NI_LOG_DEBUG, "===> encoder_encode_frame <===\n");
428 
429  if (enc_eos_sent == 1)
430  {
431  ni_log(NI_LOG_DEBUG, "encoder_encode_frame: ALL data (incl. eos) sent "
432  "already!\n");
433  return 0;
434  }
435 
436  if (*need_to_resend)
437  {
438  goto send_frame;
439  }
440 
441  p_in_frame->start_of_stream = 0;
442 
443  // If this is the first frame, mark the frame as start-of-stream
444  if (!started)
445  {
446  started = 1;
447  p_in_frame->start_of_stream = 1;
448  }
449 
450  // If this is the last frame, mark the frame as end-of-stream
451  p_in_frame->end_of_stream = input_exhausted ? 1 : 0;
452  p_in_frame->force_key_frame = 0;
453 
454 send_frame:
455 
456  in_data.data.frame = *p_in_frame;
457  oneSent =
459 
460  if (oneSent < 0)
461  {
462  fprintf(stderr,
463  "Error: failed ni_device_session_write() for encoder\n");
464  *need_to_resend = 1;
465  return -1;
466  } else if (oneSent == 0 && !p_enc_ctx->ready_to_close)
467  {
468  *need_to_resend = 1;
469  ni_log(NI_LOG_DEBUG, "NEEDED TO RESEND");
470  } else
471  {
472  *need_to_resend = 0;
473 
474  ni_log(NI_LOG_DEBUG, "encoder_encode_frame: total sent data size=%u\n",
475  p_in_frame->data_len[3]);
476 
477  ni_log(NI_LOG_DEBUG, "encoder_encode_frame: success\n");
478 
479  if (p_enc_ctx->ready_to_close)
480  {
481  enc_eos_sent = 1;
482  }
483  }
484 
485  return 0;
486 }
487 
488 /*!****************************************************************************
489  * \brief Receive output packet data from the Quadra encoder
490  *
491  * \param [in] p_enc_ctx pointer to encoder session context
492  * [in] p_out_data pointer to output data session
493  * [in] p_file pointer to file to write the packet
494  * [out] total_bytes_received running counter of bytes read
495  * [in] print_time 1 = print the time
496  *
497  * \return 0 - success got packet
498  * 1 - received eos
499  * 2 - got nothing, need retry
500  * -1 - failure
501  ******************************************************************************/
503  ni_logan_session_data_io_t *p_out_data, FILE *p_file,
504  unsigned long long *total_bytes_received,
505  int print_time)
506 {
507  int packet_size = NI_LOGAN_MAX_TX_SZ;
508  int rc = 0;
509  int end_flag = 0;
510  int rx_size = 0;
512  ni_logan_packet_t *p_out_pkt = &(p_out_data->data.packet);
513  static int received_stream_header = 0;
514 
515  ni_log(NI_LOG_DEBUG, "===> encoder_receive_data <===\n");
516 
517  if (NI_LOGAN_INVALID_SESSION_ID == p_enc_ctx->session_id ||
518  NI_INVALID_DEVICE_HANDLE == p_enc_ctx->blk_io_handle)
519  {
520  ni_log(NI_LOG_DEBUG, "encode session not opened yet, return\n");
521  return 0;
522  }
523 
524  if (p_file == NULL)
525  {
526  ni_log(NI_LOG_ERROR, "Bad file pointer, return\n");
527  return -1;
528  }
529 
530  rc = ni_logan_packet_buffer_alloc(p_out_pkt, packet_size);
531  if (rc != NI_LOGAN_RETCODE_SUCCESS)
532  {
533  fprintf(stderr, "Error: malloc packet failed, ret = %d!\n", rc);
534  return -1;
535  }
536 
537  /*
538  * The first data read from the encoder session context
539  * is a stream header read.
540  */
541  if (!received_stream_header)
542  {
543  /* Read the encoded stream header */
544  rc = ni_logan_device_session_read(p_enc_ctx, p_out_data, NI_LOGAN_DEVICE_TYPE_ENCODER);
545 
546  if (rc > 0)
547  {
548  /* Write out the stream header */
549  if (fwrite((uint8_t *)p_out_pkt->p_data + meta_size,
550  p_out_pkt->data_len - meta_size, 1, p_file) != 1)
551  {
552  fprintf(stderr, "Error: writing data %u bytes error!\n",
553  p_out_pkt->data_len - meta_size);
554  fprintf(stderr, "Error: ferror rc = %d\n", ferror(p_file));
555  }
556 
557  *total_bytes_received += (rx_size - meta_size);
559  received_stream_header = 1;
560  } else if (rc != 0)
561  {
562  fprintf(stderr, "Error: reading header %d\n", rc);
563  return -1;
564  }
565 
566  if (print_time)
567  {
568  int timeDiff = (int)(current_time.tv_sec - start_time.tv_sec);
569  if (timeDiff == 0)
570  {
571  timeDiff = 1;
572  }
573  printf("[R] Got:%d Packets= %u fps=%u Total bytes %llu\n",
574  rx_size, number_of_packets, number_of_packets / timeDiff,
575  *total_bytes_received);
576  }
577 
578  /* This shouldn't happen */
579  if (p_out_pkt->end_of_stream)
580  {
581  return 1;
582  } else if (rc == 0)
583  {
584  return 2;
585  }
586  }
587 
588 receive_data:
589  rc = ni_logan_device_session_read(p_enc_ctx, p_out_data, NI_LOGAN_DEVICE_TYPE_ENCODER);
590 
591  end_flag = p_out_pkt->end_of_stream;
592  rx_size = rc;
593 
594  ni_log(NI_LOG_DEBUG, "encoder_receive_data: received data size=%d\n", rx_size);
595 
596  if (rx_size > meta_size)
597  {
598  if (fwrite((uint8_t *)p_out_pkt->p_data + meta_size,
599  p_out_pkt->data_len - meta_size, 1, p_file) != 1)
600  {
601  fprintf(stderr, "Error: writing data %u bytes error!\n",
602  p_out_pkt->data_len - meta_size);
603  fprintf(stderr, "Error: ferror rc = %d\n", ferror(p_file));
604  }
605 
606  *total_bytes_received += rx_size - meta_size;
608 
609  ni_log(NI_LOG_DEBUG, "Got: Packets= %u\n", number_of_packets);
610  } else if (rx_size != 0)
611  {
612  fprintf(stderr, "Error: received %d bytes, <= metadata size %d!\n",
613  rx_size, meta_size);
614  return -1;
615  } else if (!end_flag &&
617  ->low_delay_mode)
618  {
619  ni_log(NI_LOG_DEBUG, "low delay mode and NO pkt, keep reading...\n");
620  goto receive_data;
621  }
622 
623  if (print_time)
624  {
625  int timeDiff = (int)(current_time.tv_sec - start_time.tv_sec);
626  if (timeDiff == 0)
627  {
628  timeDiff = 1;
629  }
630  printf("[R] Got:%d Packets= %u fps=%u Total bytes %llu\n", rx_size,
632  *total_bytes_received);
633  }
634 
635  if (end_flag)
636  {
637  printf("Encoder Receiving done\n");
638  return 1;
639  } else if (0 == rx_size)
640  {
641  return 2;
642  }
643 
644  ni_log(NI_LOG_DEBUG, "encoder_receive_data: success\n");
645 
646  return 0;
647 }
648 
649  /*!*****************************************************************************
650  * \brief Encoder session open
651  *
652  * \param
653  *
654  * \return 0 if successful, < 0 otherwise
655  ******************************************************************************/
657  int dst_codec_format, int xcoder_id,
658  const char *xcoder_name,
659  ni_logan_encoder_params_t *p_enc_params,
660  int src_bit_depth, int width, int height,
661  ni_color_primaries_t color_primaries,
663  ni_color_space_t color_space,
664  int video_full_range_flag,
665  int sar_num, int sar_den,
666  ni_logan_frame_t *p_frame)
667 {
668  int ret = 0;
669 
670  p_enc_ctx->hw_action = NI_LOGAN_CODEC_HW_ENABLE;
671  p_enc_params->hwframes = 1;
672 
673  p_enc_params->p_first_frame = p_frame;
674 
675  p_enc_ctx->p_session_config = p_enc_params;
677  p_enc_ctx->codec_format = dst_codec_format;
678 
679  // assign the card GUID in the encoder context and let session open
680  // take care of the rest
681  p_enc_ctx->device_handle = NI_INVALID_DEVICE_HANDLE;
682  p_enc_ctx->blk_io_handle = NI_INVALID_DEVICE_HANDLE;
683  p_enc_ctx->hw_id = xcoder_id;
684  p_enc_ctx->hw_name = xcoder_name;
685 
686  // default: little endian
687  p_enc_ctx->src_bit_depth = src_bit_depth;
689  p_enc_ctx->bit_depth_factor = 1;
690  if (10 == p_enc_ctx->src_bit_depth)
691  {
692  p_enc_ctx->bit_depth_factor = 2;
693  }
694 
695  int linesize_aligned = ((width + 7) / 8) * 8;
696  if (p_enc_ctx->codec_format == NI_LOGAN_CODEC_FORMAT_H264)
697  {
698  linesize_aligned = ((width + 15) / 16) * 16;
699  }
700  if (linesize_aligned < NI_LOGAN_MIN_WIDTH)
701  {
702  p_enc_params->enc_input_params.conf_win_right += NI_LOGAN_MIN_WIDTH - width;
703  linesize_aligned = NI_LOGAN_MIN_WIDTH;
704  }
705  else if (linesize_aligned > width)
706  {
707  p_enc_params->enc_input_params.conf_win_right += linesize_aligned - width;
708  }
709  p_enc_params->source_width = linesize_aligned;
710 
711  int height_aligned = ((height + 7) / 8) * 8;
712  if (p_enc_ctx->codec_format == NI_LOGAN_CODEC_FORMAT_H264)
713  {
714  height_aligned = ((height + 15) / 16) * 16;
715  }
716  if (height_aligned < NI_LOGAN_MIN_HEIGHT)
717  {
718  p_enc_params->enc_input_params.conf_win_bottom += NI_LOGAN_MIN_HEIGHT - height;
719  height_aligned = NI_LOGAN_MIN_HEIGHT;
720  }
721  else if (height_aligned > height)
722  {
723  p_enc_params->enc_input_params.conf_win_bottom += height_aligned - height;
724  }
725  p_enc_params->source_height = height_aligned;
726 
727  // VUI setting including color setting
728  ni_logan_set_vui(p_enc_params, p_enc_ctx, color_primaries, color_trc, color_space,
729  video_full_range_flag, sar_num, sar_den, dst_codec_format);
730 
732  if (ret < 0)
733  {
734  fprintf(stderr, "Error: %s failure!\n", __FUNCTION__);
735  }
736  else
737  {
738  if (xcoder_name != NULL)
739  {
740  printf("Encoder device %s session open successful.\n", xcoder_name);
741  }
742  else
743  {
744  printf("Encoder device %d session open successful.\n", xcoder_id);
745  }
746  }
747 
748  return ret;
749 }
750 
751 
752 /*!****************************************************************************
753  * \brief Open an upload session to T408
754  *
755  * \param [out] p_upl_ctx pointer to an upload context of the open session
756  * [in] iXcoderGUID pointer to T408 card hw id
757  * [in] width width of the frames
758  * [in] height height of the frames
759  *
760  * \return 0 if successful, < 0 otherwise
761  ******************************************************************************/
762 int uploader_open_session(ni_logan_session_context_t *p_upl_ctx, int *iXcoderGUID,
763  int width, int height)
764 {
765  int ret = 0;
766 
768 
769  // Assign the card GUID in the encoder context
770  p_upl_ctx->device_handle = NI_INVALID_DEVICE_HANDLE;
771  p_upl_ctx->blk_io_handle = NI_INVALID_DEVICE_HANDLE;
772 
773  // Assign the card id to specify the specific T408 device
774  p_upl_ctx->hw_id = *iXcoderGUID;
775 
776  // Set the input frame format of the upload session
777  p_upl_ctx->active_video_width = width;
778  p_upl_ctx->active_video_height = height;
779  p_upl_ctx->bit_depth_factor = 1;
780  p_upl_ctx->src_bit_depth = 8;
782  p_upl_ctx->isP2P = 1;
783 
785  if (ret != NI_LOGAN_RETCODE_SUCCESS)
786  {
787  fprintf(stderr, "Error: uploader_open_session failure!\n");
788  return ret;
789  } else
790  {
791  printf("Uploader device %d session opened successfully\n",
792  *iXcoderGUID);
793  *iXcoderGUID = p_upl_ctx->hw_id;
794  }
795 
796  // Create a P2P frame pool for the uploader sesson of pool size 2
797  ret = ni_logan_device_session_init_framepool(p_upl_ctx, POOL_SIZE, p_upl_ctx->isP2P);
798  if (ret < 0)
799  {
800  fprintf(stderr, "Error: Can't create frame pool\n");
802  } else
803  {
804  printf("Uploader device %d configured successfully\n", *iXcoderGUID);
805  }
806 
807  return ret;
808 }
809 
810 /*!****************************************************************************
811  * \brief Print usage information
812  *
813  * \param none
814  *
815  * \return none
816  ******************************************************************************/
817 void print_usage(void)
818 {
819  printf("Video encoder/P2P application directly using Netint "
820  "Libxcoder release v%s\n"
821  "Usage: xcoderp2p [options]\n"
822  "\n"
823  "options:\n"
824  "--------------------------------------------------------------------------------"
825  " -h | --help Show help.\n"
826  " -v | --version Print version info.\n"
827  " -l | --loglevel Set loglevel of libxcoder API.\n"
828  " [none, fatal, error, info, debug, trace]\n"
829  " Default: info\n"
830  " -c | --card Set card index to use.\n"
831  " See `ni_rsrc_mon_logan` for cards on system.\n"
832  " (Default: 0)\n"
833  " -i | --input Input file path.\n"
834  " -r | --repeat (Positive integer) to Repeat input X times "
835  "for performance \n"
836  " test. (Default: 1)\n"
837  " -s | --size Resolution of input file in format "
838  "WIDTHxHEIGHT.\n"
839  " (eg. '1920x1080')\n"
840  " -m | --mode Input to output codec processing mode in "
841  "format:\n"
842  " INTYPE2OUTTYPE. [p2a, p2h]\n"
843  " Type notation: p=P2P, a=AVC, h=HEVC\n"
844  " -o | --output Output file path.\n",
846 }
847 
848 /*!****************************************************************************
849  * \brief Parse user command line arguments
850  *
851  * \param [in] argc argument count
852  * [in] argv argument vector
853  * [out] input_filename input filename
854  * [out] output_filename output filename
855  * [out] iXcoderGUID T408 device
856  * [out] arg_width resolution width
857  * [out] arg_height resolution height
858  * [out] dst_codec_format codec (AVC vs HEVC)
859  *
860  * \return nothing program exit on error
861  ******************************************************************************/
862 void parse_arguments(int argc, char *argv[], char *input_filename,
863  char *output_filename, int *iXcoderGUID, int *arg_width,
864  int *arg_height, int *dst_codec_format)
865 {
866  char xcoderGUID[32];
867  char mode_description[128];
868  char *n; // used for parsing width and height from --size
869  size_t i;
870  int opt;
871  int opt_index;
872  ni_log_level_t log_level;
873 
874  static const char *opt_string = "hvl:c:i:s:m:o:r:";
875  static const struct option long_options[] = {
876  {"help", no_argument, NULL, 'h'},
877  {"version", no_argument, NULL, 'v'},
878  {"loglevel", no_argument, NULL, 'l'},
879  {"card", required_argument, NULL, 'c'},
880  {"input", required_argument, NULL, 'i'},
881  {"size", required_argument, NULL, 's'},
882  {"mode", required_argument, NULL, 'm'},
883  {"output", required_argument, NULL, 'o'},
884  {"repeat", required_argument, NULL, 'r'},
885  {NULL, 0, NULL, 0},
886  };
887 
888  while ((opt = getopt_long(argc, argv, opt_string, long_options,
889  &opt_index)) != -1)
890  {
891  switch (opt)
892  {
893  case 'h':
894  print_usage();
895  exit(0);
896  case 'v':
897  printf("Release ver: %s\n", NI_LOGAN_XCODER_REVISION);
898  exit(0);
899  case 'l':
900  log_level = log_str_to_level(optarg);
901  if (log_level < NI_LOG_NONE || log_level > NI_LOG_TRACE)
902  arg_error_exit("-l | --loglevel", optarg);
903  ni_log_set_level(log_level);
904  break;
905  case 'c':
906  strcpy(xcoderGUID, optarg);
907  *iXcoderGUID = (int)strtol(optarg, &n, 10);
908  // No numeric characters found in left side of optarg
909  if (n == xcoderGUID)
910  arg_error_exit("-c | --card", optarg);
911  break;
912  case 'i':
913  strcpy(input_filename, optarg);
914  break;
915  case 's':
916  *arg_width = (int)strtol(optarg, &n, 10);
917  *arg_height = atoi(n + 1);
918  if ((*n != 'x') || (!*arg_width || !*arg_height))
919  arg_error_exit("-s | --size", optarg);
920  break;
921  case 'm':
922  if (!(strlen(optarg) == 3))
923  arg_error_exit("-m | --mode", optarg);
924 
925  // convert to lower case for processing
926  for (i = 0; i < strlen(optarg); i++)
927  optarg[i] = (char)tolower((unsigned char)optarg[i]);
928 
929  if (strcmp(optarg, "p2a") != 0 && strcmp(optarg, "p2h") != 0)
930  arg_error_exit("-, | --mode", optarg);
931 
932  // determine codec
933  sprintf(mode_description, "P2P + Encoding");
934 
935  if (optarg[2] == 'a')
936  {
937  *dst_codec_format = NI_LOGAN_CODEC_FORMAT_H264;
938  strcat(mode_description, " to AVC");
939  }
940 
941  if (optarg[2] == 'h')
942  {
943  *dst_codec_format = NI_LOGAN_CODEC_FORMAT_H265;
944  strcat(mode_description, " to HEVC");
945  }
946  printf("%s...\n", mode_description);
947 
948  break;
949  case 'o':
950  strcpy(output_filename, optarg);
951  break;
952  case 'r':
953  if (!(atoi(optarg) >= 1))
954  arg_error_exit("-r | --repeat", optarg);
955  g_repeat = atoi(optarg);
956  break;
957  default:
958  print_usage();
959  exit(1);
960  }
961  }
962 
963  // Check required args are present
964  if (!input_filename[0])
965  {
966  printf("Error: missing argument for -i | --input\n");
967  exit(-1);
968  }
969 
970  if (!output_filename[0])
971  {
972  printf("Error: missing argument for -o | --output\n");
973  exit(-1);
974  }
975 }
976 
977 int main(int argc, char *argv[])
978 {
979  static char input_filename[FILE_NAME_LEN];
980  static char output_filename[FILE_NAME_LEN];
981  unsigned long total_bytes_sent;
982  unsigned long long total_bytes_received;
983  int input_video_width;
984  int input_video_height;
985  int iXcoderGUID = 0;
986  int arg_width = 0;
987  int arg_height = 0;
988  int input_exhausted = 0;
989  int num_post_recycled = 0;
990  int dst_codec_format = 0;
991  int ret;
992  int timeDiff;
993  int print_time;
994  int need_to_resend = 0;
995  int render_index = 0;
996  int encode_index = -1;
997  FILE *p_file = NULL;
998  ni_logan_encoder_params_t api_param;
999  ni_logan_session_context_t enc_ctx = {0};
1000  ni_logan_session_context_t upl_ctx = {0};
1001  ni_logan_frame_t p2p_frame[POOL_SIZE];
1002  ni_logan_session_data_io_t out_packet = {0};
1003  int input_file_fd = -1;
1004  char encConfXcoderParams[2048] = { 0 };
1005 
1006  parse_arguments(argc, argv, input_filename, output_filename, &iXcoderGUID,
1007  &arg_width, &arg_height, &dst_codec_format);
1008 
1009  // Load input file into memory
1010  if (load_input_file(input_filename, &total_file_size) < 0)
1011  {
1012  exit(-1);
1013  }
1014 
1016 
1017  // Create output file
1018  if (strcmp(output_filename, "null") != 0)
1019  {
1020  p_file = fopen(output_filename, "wb");
1021  if (p_file == NULL)
1022  {
1023  fprintf(stderr, "Error: cannot open %s\n", output_filename);
1024  goto end;
1025  }
1026  }
1027 
1028  printf("SUCCESS: Opened output file: %s\n", output_filename);
1029 
1032 
1033  enc_ctx.nb_rois = 0;
1034  enc_ctx.roi_side_data_size = 0;
1035  enc_ctx.nb_rois = 0;
1036  enc_ctx.roi_side_data_size = 0;
1037  enc_ctx.av_rois = NULL;
1038  enc_ctx.codec_format = dst_codec_format;
1039 
1040  total_bytes_received = 0;
1041  total_bytes_sent = 0;
1042 
1043  send_fin_flag = 0;
1044  receive_fin_flag = 0;
1045 
1046  printf("User video resolution: %dx%d\n", arg_width, arg_height);
1047 
1048  if (arg_width == 0 || arg_height == 0)
1049  {
1050  input_video_width = 1280;
1051  input_video_height = 720;
1052  } else
1053  {
1054  input_video_width = arg_width;
1055  input_video_height = arg_height;
1056  }
1057 
1062 
1063  printf("P2P Encoding resolution: %dx%d\n", input_video_width,
1064  input_video_height);
1065 
1066  // Open an uploader session to Logan
1067  if (uploader_open_session(&upl_ctx, &iXcoderGUID, arg_width, arg_height))
1068  {
1069  goto end;
1070  }
1071 
1072  // Configure the encoder parameter structure. We'll use some basic
1073  // defaults: 30 fps, 200000 bps CBR encoding, AVC or HEVC encoding
1074  if (ni_logan_encoder_init_default_params(&api_param, 30, 1, 200000, arg_width,
1075  arg_height) < 0)
1076  {
1077  fprintf(stderr, "Error: encoder init default set up error\n");
1079  return -1;
1080  }
1081 
1082  // For P2P demo, change some of the encoding parameters from
1083  // the default. Enable low delay encoding.
1084  if ((ret = ni_logan_encoder_params_set_value(&api_param, "lowDelay", "1", &enc_ctx)) !=
1086  {
1087  fprintf(stderr, "Error: can't set low delay mode %d\n", ret);
1089  return -1;
1090  }
1091 
1092  // Use a GOP preset of 9 which represents a GOP pattern of
1093  // IPPPPPPP....This will be low latency.
1094  if ((ret = ni_logan_encoder_params_set_value(&api_param, "gopPresetIdx", "9", &enc_ctx)) !=
1096  {
1097  fprintf(stderr, "Error: can't set gop preset %d\n", ret);
1099  return -1;
1100  }
1101 
1102  // Prepare two frames for double buffering
1103  ret = p2p_prepare_frames(&upl_ctx, input_video_width, input_video_height,
1104  p2p_frame);
1105 
1106  if (ret < 0)
1107  {
1109  goto end;
1110  }
1111 
1112  int video_full_range_flag = 0;
1113  if (api_param.video_full_range_flag >= 0)
1114  {
1115  ni_log(NI_LOG_TRACE, "Using user-configured video_full_range_flag "
1116  "%d\n", api_param.video_full_range_flag);
1117  video_full_range_flag = api_param.video_full_range_flag;
1118  }
1119 
1120  // Open the encoder session with given parameters
1121  ret = encoder_open_session(&enc_ctx, dst_codec_format, iXcoderGUID, "",
1122  &api_param, 8, arg_width, arg_height,
1123  api_param.color_primaries,
1125  api_param.color_space,
1126  video_full_range_flag,
1127  api_param.sar_num, api_param.sar_denom, &p2p_frame[render_index]);
1128  if (ret < 0)
1129  {
1131  goto end;
1132  }
1133 
1134 #ifdef _WIN32
1135  input_file_fd = open(input_filename, O_RDONLY | O_BINARY);
1136 #else
1137  input_file_fd = open(input_filename, O_RDONLY);
1138 #endif
1139 
1140  if (input_file_fd < 0)
1141  {
1142  fprintf(stderr, "Error: can not open input file %s\n", input_filename);
1143  goto end;
1144  }
1145 
1146  /* send out a frame to do rendering */
1148  &upl_ctx, input_file_fd, &g_yuv_frame[render_index],
1149  &p2p_frame[render_index], input_video_width, input_video_height,
1150  &total_bytes_sent, &input_exhausted))
1151  {
1152  fprintf(stderr, "Error: upload frame error\n");
1153  close(input_file_fd);
1154  return -1;
1155  }
1156 
1157  while (send_fin_flag == 0 || receive_fin_flag == 0)
1158  {
1160 
1161  // Print the time if >= 1 second has passed
1162  print_time = ((current_time.tv_sec - previous_time.tv_sec) > 1);
1163  encode_index = render_index;
1164 
1165 #ifndef _WIN32
1166  // Lock the hardware frame prior to encoding. This call will
1167  // block until the frame is ready then lock the frame for use.
1168  ni_logan_uploader_frame_buffer_lock(&upl_ctx, &p2p_frame[encode_index]);
1169 #endif
1170 
1171  // Encode the frame
1172  send_fin_flag = encoder_encode_frame(&enc_ctx, &p2p_frame[encode_index],
1173  input_exhausted, &need_to_resend);
1174 
1175  // Error, exit
1176  if (send_fin_flag == 2)
1177  {
1178  break;
1179  }
1180 
1181  // Switch to the other hw frame buffer
1182  render_index = !render_index;
1183 
1184  // Fill the frame buffer with YUV data while the previous frame is being encoded
1185  if (!input_exhausted && need_to_resend == 0)
1186  {
1188  &upl_ctx, input_file_fd, &g_yuv_frame[render_index],
1189  &p2p_frame[render_index], input_video_width,
1190  input_video_height, &total_bytes_sent, &input_exhausted))
1191  {
1192  fprintf(stderr, "Error: upload frame error\n");
1193  close(input_file_fd);
1194  return -1;
1195  }
1196  }
1197 
1198  // Receive encoded packet data from the encoder
1200  &enc_ctx, &out_packet, p_file, &total_bytes_received, print_time);
1201 
1202 #ifndef _WIN32
1203  // Unlock the encoded frame now that the compressed packet data has
1204  // been received. This frame can be re-used.
1205  ret =
1206  ni_logan_uploader_frame_buffer_unlock(&upl_ctx, &p2p_frame[encode_index]);
1207  if (ret < 0)
1208  {
1209  fprintf(stderr, "Failed to unlock frame\n");
1210  goto end;
1211  }
1212 #endif
1213 
1214  if (print_time)
1215  {
1217  }
1218 
1219  // Error or eos
1220  if (receive_fin_flag < 0 || out_packet.data.packet.end_of_stream)
1221  {
1222  break;
1223  }
1224  }
1225 
1226  timeDiff = (int)(current_time.tv_sec - start_time.tv_sec);
1227  timeDiff = (timeDiff > 0) ? timeDiff : 1; // avoid division by zero
1228 
1229  printf("[R] Got: Packets= %u fps=%u Total bytes %llu\n",
1231  total_bytes_received);
1232 
1233  // Recycle the hardware frames back to the pool prior
1234  // to closing the uploader session.
1235  //num_post_recycled = recycle_frames(p2p_frame);
1236 
1237  ni_log(NI_LOG_DEBUG, "Cleanup recycled %d internal buffers\n", num_post_recycled);
1238 
1241 
1244 
1245  int i;
1246  for (i = 0; i < POOL_SIZE; i++)
1247  {
1248  ni_logan_frame_buffer_free(&(p2p_frame[i]));
1249  }
1250 
1251  ni_logan_packet_buffer_free(&(out_packet.data.packet));
1252 
1253 end:
1254  close(input_file_fd);
1255 
1256  if (p_file)
1257  {
1258  fclose(p_file);
1259  }
1260 
1261  printf("All done\n");
1262 
1263  return 0;
1264 }
void ni_logan_set_vui(ni_logan_encoder_params_t *p_param, ni_logan_session_context_t *p_ctx, ni_color_primaries_t color_primaries, ni_color_transfer_characteristic_t color_trc, ni_color_space_t color_space, int video_full_range_flag, int sar_num, int sar_den, ni_logan_codec_format_t codec_format)
Set SPS VUI part of encoded stream header.
NETINT audio/video related utility functions.
enum _ni_color_primaries ni_color_primaries_t
enum _ni_color_transfer_characteristic ni_color_transfer_characteristic_t
enum _ni_color_space ni_color_space_t
ni_logan_retcode_t
@ NI_LOGAN_RETCODE_SUCCESS
#define NI_LOGAN_FW_ENC_BITSTREAM_META_DATA_SIZE
#define NI_LOGAN_MAX_NUM_DATA_POINTERS
#define NI_LOGAN_XCODER_REVISION
Definition: ni_defs_logan.h:62
@ NI_LOGAN_DEVICE_TYPE_UPLOAD
@ NI_LOGAN_DEVICE_TYPE_ENCODER
#define NI_LOGAN_MAX_TX_SZ
ni_logan_retcode_t ni_logan_uploader_frame_buffer_unlock(ni_logan_session_context_t *p_upl_ctx, ni_logan_frame_t *p_frame)
Unlock a hardware P2P frame after encoding.
ni_logan_retcode_t ni_logan_packet_buffer_alloc(ni_logan_packet_t *p_packet, int packet_size)
Allocate memory for the packet buffer based on provided packet size.
ni_logan_retcode_t ni_logan_device_session_close(ni_logan_session_context_t *p_ctx, int eos_recieved, ni_logan_device_type_t device_type)
Closes device session that was previously opened by calling ni_logan_device_session_open() If device_...
ni_logan_retcode_t ni_logan_frame_buffer_alloc_hwenc(ni_logan_frame_t *p_frame, int video_width, int video_height, int extra_len)
Allocate memory for the frame buffer based on provided parameters taking into account pic line size a...
ni_logan_retcode_t ni_logan_uploader_frame_buffer_lock(ni_logan_session_context_t *p_upl_ctx, ni_logan_frame_t *p_frame)
Lock a hardware P2P frame prior to encoding.
int ni_logan_device_session_acquire(ni_logan_session_context_t *p_ctx, ni_logan_frame_t *p_frame)
Acquire a P2P frame buffer from the hwupload session.
ni_logan_retcode_t ni_logan_packet_buffer_free(ni_logan_packet_t *p_packet)
Free packet buffer that was previously allocated with either ni_logan_packet_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.
ni_logan_retcode_t ni_logan_frame_buffer_free(ni_logan_frame_t *p_frame)
Free frame buffer that was previously allocated with either ni_logan_frame_buffer_alloc or ni_logan_e...
int ni_logan_device_session_init_framepool(ni_logan_session_context_t *p_ctx, uint32_t pool_size, uint32_t p2p_pool)
Sends frame pool setup info to device.
ni_logan_retcode_t ni_logan_uploader_p2p_test_send(ni_logan_session_context_t *p_upl_ctx, uint8_t *p_data, uint32_t len, ni_logan_frame_t *p_hwframe)
Special P2P test API function. Copies YUV data from the software frame to the hardware P2P frame on t...
int ni_logan_device_session_read(ni_logan_session_context_t *p_ctx, ni_logan_session_data_io_t *p_data, ni_logan_device_type_t device_type)
Reads data the device If device_type is NI_LOGAN_DEVICE_TYPE_DECODER reads data packet from decoder I...
ni_logan_retcode_t ni_logan_encoder_params_set_value(ni_logan_encoder_params_t *p_params, const char *name, const char *value, ni_logan_session_context_t *ctx)
Set value referenced by name in encoder parameters structure.
#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_encoder_init_default_params(ni_logan_encoder_params_t *p_param, int fps_num, int fps_denom, long bit_rate, int width, int height)
Initialize default encoder parameters.
ni_logan_retcode_t ni_logan_device_session_open(ni_logan_session_context_t *p_ctx, ni_logan_device_type_t device_type)
Opens a new device session depending on the device_type parameter If device_type is NI_LOGAN_DEVICE_T...
int ni_logan_device_session_write(ni_logan_session_context_t *p_ctx, ni_logan_session_data_io_t *p_data, ni_logan_device_type_t device_type)
Sends data the device If device_type is NI_LOGAN_DEVICE_TYPE_DECODER sends data packet to decoder If ...
Main NETINT device API header file provides the ability to communicate with NI T-408 type hardware tr...
@ NI_LOGAN_CODEC_HW_ENABLE
#define NI_LOGAN_MIN_WIDTH
#define NI_LOGAN_MIN_HEIGHT
#define NI_LOGAN_FRAME_LITTLE_ENDIAN
@ NI_LOGAN_CODEC_FORMAT_H265
@ NI_LOGAN_CODEC_FORMAT_H264
@ NI_LOGAN_PIX_FMT_YUV420P
#define NI_LOGAN_INVALID_SESSION_ID
char * optarg
int getopt_long(int argc, char *argv[], const char *optstring, const struct option *longopts, int *longindex)
#define no_argument
#define required_argument
void ni_log_set_level(ni_log_level_t level)
Set ni_log_level.
Definition: ni_log_logan.c:138
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_level_t
Definition: ni_log_logan.h:60
@ NI_LOG_NONE
Definition: ni_log_logan.h:62
@ NI_LOG_DEBUG
Definition: ni_log_logan.h:66
@ NI_LOG_TRACE
Definition: ni_log_logan.h:67
@ NI_LOG_FATAL
Definition: ni_log_logan.h:63
@ NI_LOG_ERROR
Definition: ni_log_logan.h:64
@ NI_LOG_INFO
Definition: ni_log_logan.h:65
int load_input_file(const char *filename, unsigned long *bytes_read)
Load the input file into memory.
#define MAX_YUV_FRAME_SIZE
time_t start_timestamp
int main(int argc, char *argv[])
uint8_t * g_curr_cache_pos
time_t previous_timestamp
struct timeval current_time
void parse_arguments(int argc, char *argv[], char *input_filename, char *output_filename, int *iXcoderGUID, int *arg_width, int *arg_height, int *dst_codec_format)
Parse user command line arguments.
time_t current_timestamp
int enc_eos_sent
int uploader_open_session(ni_logan_session_context_t *p_upl_ctx, int *iXcoderGUID, int width, int height)
Open an upload session to T408.
int encoder_receive_data(ni_logan_session_context_t *p_enc_ctx, ni_logan_session_data_io_t *p_out_data, FILE *p_file, unsigned long long *total_bytes_received, int print_time)
Receive output packet data from the Quadra encoder.
int read_next_chunk_from_file(int fd, uint8_t *p_dst, uint32_t to_read)
Read the next frame.
void print_usage(void)
Print usage information.
#define POOL_SIZE
int p2p_prepare_frames(ni_logan_session_context_t *p_upl_ctx, int input_video_width, int input_video_height, ni_logan_frame_t p2p_frame[])
Prepare frames to simulate P2P transfers.
uint8_t * g_yuv_frame[POOL_SIZE]
uint32_t number_of_packets
unsigned long total_file_size
struct timeval start_time
int encoder_encode_frame(ni_logan_session_context_t *p_enc_ctx, ni_logan_frame_t *p_in_frame, int input_exhausted, int *need_to_resend)
Send the Quadra encoder a hardware frame which triggers Quadra to encode the frame.
uint64_t data_left_size
int p2p_upload_send_data(ni_logan_session_context_t *p_upl_ctx, int fd, uint8_t **p_yuv420p_frame, ni_logan_frame_t *p_in_frame, int input_video_width, int input_video_height, unsigned long *bytes_sent, int *input_exhausted)
Recycle hw frames back to T408.
void arg_error_exit(char *arg_name, char *param)
Exit on argument error.
int receive_fin_flag
int g_repeat
struct timeval previous_time
uint32_t number_of_frames
int send_fin_flag
int encoder_open_session(ni_logan_session_context_t *p_enc_ctx, int dst_codec_format, int xcoder_id, const char *xcoder_name, ni_logan_encoder_params_t *p_enc_params, int src_bit_depth, int width, int height, ni_color_primaries_t color_primaries, ni_color_transfer_characteristic_t color_trc, ni_color_space_t color_space, int video_full_range_flag, int sar_num, int sar_den, ni_logan_frame_t *p_frame)
Encoder session open.
#define FILE_NAME_LEN
int32_t ni_logan_posix_memalign(void **pp_memptr, size_t alignment, size_t size)
void ni_logan_copy_hw_yuv420p(uint8_t *p_dst[NI_LOGAN_MAX_NUM_DATA_POINTERS], uint8_t *p_src[NI_LOGAN_MAX_NUM_DATA_POINTERS], int frame_width, int frame_height, int bit_depth_factor, int dst_stride[NI_LOGAN_MAX_NUM_DATA_POINTERS], int dst_height[NI_LOGAN_MAX_NUM_DATA_POINTERS], int src_stride[NI_LOGAN_MAX_NUM_DATA_POINTERS], int src_height[NI_LOGAN_MAX_NUM_DATA_POINTERS])
Copy YUV data to Netint HW YUV420p frame layout to be sent to encoder for encoding....
void ni_logan_get_hw_yuv420p_dim(int width, int height, int bit_depth_factor, int is_h264, int plane_stride[NI_LOGAN_MAX_NUM_DATA_POINTERS], int plane_height[NI_LOGAN_MAX_NUM_DATA_POINTERS])
Get dimension information of Netint HW YUV420p frame to be sent to encoder for encoding....
int32_t ni_logan_gettimeofday(struct timeval *p_tp, void *p_tzp)
Definition: ni_util_logan.c:56
Exported utility routines definition.
ni_logan_encoder_input_params_t enc_input_params
ni_logan_frame_t * p_first_frame
uint32_t data_len[NI_LOGAN_MAX_NUM_DATA_POINTERS]
unsigned int extra_data_len
ni_device_handle_t device_handle
ni_device_handle_t blk_io_handle
ni_region_of_interest_t * av_rois
union _ni_logan_session_data_io::@4 data