libxcoder 5.8.0
Loading...
Searching...
No Matches
ni_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 <stddef.h>
34#include <stdint.h>
35
36#define _POSIX_C_SOURCE 200809L // NOLINT(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
37#include <getopt.h>
38#include <unistd.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <fcntl.h>
42#include <sys/time.h>
43#include <time.h>
44
45#include "ni_device_api.h"
46#include "ni_util.h"
47
48// max YUV frame size
49#define MAX_YUV_FRAME_SIZE (7680 * 4320 * 3 / 2)
50#define MAX_ABGR_FRAME_SIZE (7680 * 4320 * 4)
51#define POOL_SIZE 2
52#define FILE_NAME_LEN 256
53
57
58uint32_t number_of_frames = 0;
59uint32_t number_of_packets = 0;
60uint64_t data_left_size = 0;
61int g_repeat = 1;
62
63struct timeval start_time;
64struct timeval previous_time;
65struct timeval current_time;
66
67time_t start_timestamp = 0;
70
71unsigned long total_file_size = 0;
72
73uint8_t *g_curr_cache_pos = NULL;
74uint8_t *g_yuv_frame[POOL_SIZE] = {NULL, NULL};
75uint8_t *g_rgba_frame[POOL_SIZE] = {NULL, NULL};
76
77uint8_t g_rgb2yuv_csc = 0;
78
79/*!****************************************************************************
80 * \brief Exit on argument error
81 *
82 * \param[in] arg_name pointer to argument name
83 * [in] param pointer to provided parameter
84 *
85 * \return None program exit
86 ******************************************************************************/
87void arg_error_exit(char *arg_name, char *param)
88{
89 (void)fprintf(stderr, "Error: unrecognized argument for %s, \"%s\"\n", arg_name,
90 param);
91 exit(-1); // NOLINT(concurrency-mt-unsafe) - single-threaded CLI tool
92}
93
94/*!****************************************************************************
95 * \brief Read the next frame
96 *
97 * \param[in] fd file descriptor of input file
98 * \param[out] p_dst pointer to place the frame
99 * \param[in] to_read number of bytes to copy to the pointer
100 *
101 * \return bytes copied
102 ******************************************************************************/
103int read_next_chunk_from_file(int fd, uint8_t *p_dst, uint32_t to_read)
104{
105 uint8_t *tmp_dst = p_dst;
107 "read_next_chunk_from_file:p_dst %p len %u totalSize %llu left %llu\n",
108 tmp_dst, to_read, (unsigned long long)total_file_size, (unsigned long long)data_left_size);
109 int to_copy = (int)to_read;
110 unsigned long tmpFileSize = to_read;
111 if (data_left_size == 0)
112 {
113 if (g_repeat > 1)
114 {
116 g_repeat--;
117 ni_log(NI_LOG_DEBUG, "input processed %d left\n", g_repeat);
118 lseek(fd, 0, SEEK_SET); //back to beginning
119 } else
120 {
121 return 0;
122 }
123 } else if (data_left_size < to_read)
124 {
125 tmpFileSize = data_left_size;
126 to_copy = (int)data_left_size;
127 }
128
129 int one_read_size = (int)read(fd, tmp_dst, to_copy);
130 if (one_read_size == -1)
131 {
132 (void)fprintf(stderr, "Error: reading file, quit! left-to-read %lu\n",
133 tmpFileSize);
134 (void)fprintf(stderr, "Error: input file read error\n");
135 return -1;
136 }
137 data_left_size -= one_read_size;
138
139 return to_copy;
140}
141
142/*!****************************************************************************
143 * \brief Load the input file into memory
144 *
145 * \param [in] filename name of input file
146 * [out] bytes_read number of bytes read from file
147 *
148 * \return 0 on success
149 * < 0 on error
150 ******************************************************************************/
151int load_input_file(const char *filename, unsigned long *bytes_read)
152{
153 struct stat info;
154
155 /* Get information on the file */
156 if (stat(filename, &info) < 0)
157 {
158 (void)fprintf(stderr, "Can't stat %s\n", filename);
159 return -1;
160 }
161
162 /* Check the file size */
163 if (info.st_size <= 0)
164 {
165 (void)fprintf(stderr, "File %s is empty\n", filename);
166 return -1;
167 }
168
169 *bytes_read = info.st_size;
170
171 return 0;
172}
173
174/*!****************************************************************************
175* \brief Recycle hw frames back to Quadra
176*
177* \param [in] p2p_frame - array of hw frames to recycle
178*
179* \return Returns the number of hw frames that have been recycled
180*******************************************************************************/
182{
183 int i;
184 int cnt = 0;
185 ni_retcode_t rc;
186
187 for (i = 0; i < POOL_SIZE; i++)
188 {
189 rc = ni_hwframe_p2p_buffer_recycle(&p2p_frame[i]);
190
191 if (rc != NI_RETCODE_SUCCESS)
192 {
193 (void)fprintf(stderr, "Recycle failed\n");
194 }
195
196 cnt += (rc == NI_RETCODE_SUCCESS) ? 1 : 0;
197 }
198
199 return cnt;
200}
201
202/*!****************************************************************************
203 * \brief Reads YUV data from input file then calls a special libxcoder API
204 * function to transfer the YUV data into the hardware frame on
205 * the Quadra device.
206 *
207 * \param [in] p_upl_ctx pointer to upload session context
208 * [in] fd file descriptor of input file
209 * [in] p_yuv420p_frame address of pointer to YUV data
210 * [in] p_in_frame pointer to hardware frame
211 * [in] input_video_width video width
212 * [in] input_video_height video height
213 * [out] bytes_sent updated byte count of total data read
214 * [out] input_exhausted set to 1 when we reach end-of-file
215 *
216 * \return 0 on success
217 * -1 on error
218 ******************************************************************************/
220 uint8_t **p_yuv420p_frame, ni_frame_t *p_in_frame,
221 int input_video_width, int input_video_height,
222 unsigned long *bytes_sent, int *input_exhausted)
223{
224 static uint8_t tmp_buf[MAX_YUV_FRAME_SIZE];
225 void *p_buffer;
226 uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS];
227 uint8_t *p_dst[NI_MAX_NUM_DATA_POINTERS];
228 int src_stride[NI_MAX_NUM_DATA_POINTERS];
229 int src_height[NI_MAX_NUM_DATA_POINTERS];
230 int dst_stride[NI_MAX_NUM_DATA_POINTERS] = {0, 0, 0, 0};
231 int dst_height[NI_MAX_NUM_DATA_POINTERS] = {0, 0, 0, 0};
232 int frame_size;
233 int chunk_size;
234 int alignedh;
235 int Ysize;
236 int Usize;
237 int Vsize;
238 int total_size;
239
240 ni_log2(p_upl_ctx, NI_LOG_DEBUG, "===> p2p upload_send_data <===\n");
241
242 /* An 8-bit YUV420 planar frame occupies [(width x height x 3)/2] bytes */
243 frame_size = input_video_height * input_video_width * 3 / 2;
244
245 chunk_size = read_next_chunk_from_file(fd, tmp_buf, frame_size);
246
247 if (chunk_size == 0)
248 {
249 ni_log2(p_upl_ctx, NI_LOG_DEBUG, "p2p_upload_send_data: read chunk size 0, eos!\n");
250 *input_exhausted = 1;
251 }
252
253 p_in_frame->video_width = input_video_width;
254 p_in_frame->video_height = input_video_height;
255 p_in_frame->extra_data_len = 0;
256
257 ni_get_hw_yuv420p_dim(input_video_width, input_video_height,
258 p_upl_ctx->bit_depth_factor, 0, dst_stride,
259 dst_height);
260
261 ni_log2(p_upl_ctx, NI_LOG_DEBUG, "p_dst alloc linesize = %d/%d/%d src height=%d "
262 "dst height aligned = %d/%d/%d \n",
263 dst_stride[0], dst_stride[1], dst_stride[2],
264 input_video_height, dst_height[0], dst_height[1],
265 dst_height[2]);
266
267 src_stride[0] = input_video_width * p_upl_ctx->bit_depth_factor;
268 src_stride[1] = src_stride[2] = src_stride[0] / 2;
269
270 src_height[0] = input_video_height;
271 src_height[1] = src_height[0] / 2;
272 src_height[2] = src_height[1];
273
274 p_src[0] = tmp_buf;
275 p_src[1] = tmp_buf + (ptrdiff_t)src_stride[0] * src_height[0];
276 p_src[2] = p_src[1] + (ptrdiff_t)src_stride[1] * src_height[1];
277
278 alignedh = (input_video_height + 1) & ~1;
279
280 Ysize = dst_stride[0] * alignedh;
281 Usize = dst_stride[1] * alignedh / 2;
282 Vsize = dst_stride[2] * alignedh / 2;
283
284 total_size = Ysize + Usize + Vsize;
285 total_size = ((total_size + 4095) & ~4095) + 4096;
286
287 if (*p_yuv420p_frame == NULL)
288 {
289 if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), total_size))
290 {
291 (void)fprintf(stderr, "Can't alloc memory\n");
292 return -1;
293 }
294
295 *p_yuv420p_frame = p_buffer;
296 }
297
298 p_dst[0] = *p_yuv420p_frame;
299 p_dst[1] = *p_yuv420p_frame + Ysize;
300 p_dst[2] = *p_yuv420p_frame + Ysize + Usize;
301 p_dst[3] = NULL;
302
303 ni_copy_hw_yuv420p(p_dst, p_src, input_video_width, input_video_height, 1,
304 0, 0, dst_stride, dst_height, src_stride, src_height);
305#ifndef _WIN32
306 if (ni_uploader_p2p_test_send(p_upl_ctx, *p_yuv420p_frame, total_size,
307 p_in_frame))
308 {
309 (void)fprintf(stderr, "Error: failed ni_uploader_p2p_test_send()\n");
310 return -1;
311 } else
312#endif
313 {
314 *bytes_sent = total_size;
315 }
316
317 return 0;
318}
319
320/*!****************************************************************************
321 * \brief Reads RGBA data from input file then calls a special libxcoder API
322 * function to transfer the RGBA data into the hardware frame on
323 * the Quadra device.
324 *
325 * \param [in] p_upl_ctx pointer to upload session context
326 * [in] fd file descriptor of input file
327 * [in] p_rgba_frame address of pointer to RGBA data
328 * [in] p_in_frame pointer to hardware frame
329 * [in] input_video_width video width
330 * [in] input_video_height video height
331 * [out] bytes_sent updated byte count of total data read
332 * [out] input_exhausted set to 1 when we reach end-of-file
333 *
334 * \return 0 on success
335 * -1 on error
336 ******************************************************************************/
338 uint8_t **p_rgba_frame, ni_frame_t *p_in_frame,
339 int input_video_width, int input_video_height,
340 unsigned long *bytes_sent, int *input_exhausted)
341{
342 static uint8_t tmp_buf[MAX_ABGR_FRAME_SIZE];
343 void *p_buffer;
344 uint8_t *p_src,*p_dst;
345 int linewidth;
346 int frame_size;
347 int chunk_size;
348 int total_size;
349 int row;
350
351 ni_log2(p_upl_ctx, NI_LOG_DEBUG, "===> p2p upload_rgba_send_data <===\n");
352
353 /* An 8-bit RGBA frame is in a packed raster (or linear) format */
354 /* and occupies width * height * 4 bytes. */
355 frame_size = input_video_width * input_video_height * 4;
356
357 chunk_size = read_next_chunk_from_file(fd, tmp_buf, frame_size);
358
359 if (chunk_size == 0)
360 {
361 ni_log2(p_upl_ctx, NI_LOG_DEBUG, "p2p_upload_rgba_send_data: eos!\n");
362 *input_exhausted = 1;
363 }
364
365 p_in_frame->video_width = input_video_width;
366 p_in_frame->video_height = input_video_height;
367 p_in_frame->extra_data_len = 0;
368
369 linewidth = input_video_width * 4;
370
371 // Round up to 4K
372 total_size = NI_VPU_ALIGN4096(frame_size);
373
374 if (*p_rgba_frame == NULL)
375 {
376 if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), total_size))
377 {
378 (void)fprintf(stderr, "Can't alloc memory\n");
379 return -1;
380 }
381
382 *p_rgba_frame = p_buffer;
383 }
384
385 p_src = tmp_buf;
386 p_dst = *p_rgba_frame;
387
388 for (row = 0; row < input_video_height; row++)
389 {
390 memcpy(p_dst, p_src, linewidth);
391 p_src += linewidth;
392 p_dst += linewidth;
393 }
394
395 if (ni_uploader_p2p_test_send(p_upl_ctx, *p_rgba_frame, total_size,
396 p_in_frame))
397 {
398 (void)fprintf(stderr, "Error: failed ni_uploader_p2p_test_send()\n");
399 return -1;
400 } else
401 {
402 *bytes_sent = total_size;
403 }
404
405 return 0;
406}
407
408/*!****************************************************************************
409 * \brief Prepare frames to simulate P2P transfers
410 *
411 * \param [in] p_upl_ctx pointer to caller allocated uploader
412 * session context
413 * [in] input_video_width video width
414 * [in] input_video_height video height
415 * [out] p2p_frame array of hw frames
416 *
417 * \return 0 on success
418 * -1 on error
419 ******************************************************************************/
420int p2p_prepare_frames(ni_session_context_t *p_upl_ctx, int input_video_width,
421 int input_video_height, ni_frame_t p2p_frame[])
422{
423 int i;
424 int ret = 0;
425 ni_frame_t *p_in_frame;
426
427 // Allocate memory for two hardware frames
428 for (i = 0; i < POOL_SIZE; i++)
429 {
430 p_in_frame = &p2p_frame[i];
431
432 p_in_frame->start_of_stream = 0;
433 p_in_frame->end_of_stream = 0;
434 p_in_frame->force_key_frame = 0;
435 p_in_frame->extra_data_len = 0;
436
437 // Allocate a hardware ni_frame structure for the encoder
439 p_in_frame, input_video_width, input_video_height,
440 (int)p_in_frame->extra_data_len) != NI_RETCODE_SUCCESS)
441 {
442 (void)fprintf(stderr, "Error: could not allocate hw frame buffer!");
443 ret = -1;
444 goto fail_out;
445 }
446
447#ifndef _WIN32
448 // Acquire a hw frame from the upload session. This obtains a handle
449 // to Quadra memory from the previously created frame pool.
450 if (ni_device_session_acquire(p_upl_ctx, p_in_frame))
451 {
452 (void)fprintf(stderr, "Error: failed ni_device_session_acquire()\n");
453 ret = -1;
454 goto fail_out;
455 }
456#endif
457 }
458
459 return ret;
460
461fail_out:
462 for (i = 0; i < POOL_SIZE; i++)
463 {
464 ni_frame_buffer_free(&(p2p_frame[i]));
465 }
466
467 return ret;
468}
469
470/*!****************************************************************************
471 * \brief Send the Quadra encoder a hardware frame which triggers
472 * Quadra to encode the frame
473 *
474 * \param [in] p_enc_ctx pointer to encoder context
475 * [in] p_in_frame pointer to hw frame
476 * [in] input_exhausted flag indicating this is the last frame
477 * [in/out] need_to_resend flag indicating need to re-send
478 *
479 * \return 0 on success
480 * -1 on failure
481 ******************************************************************************/
483 ni_frame_t *p_in_frame, int input_exhausted,
484 int *need_to_resend)
485{
486 static int started = 0;
487 int oneSent;
488 ni_session_data_io_t in_data;
489
490 ni_log2(p_enc_ctx, NI_LOG_DEBUG, "===> encoder_encode_frame <===\n");
491
492 if (enc_eos_sent == 1)
493 {
494 ni_log2(p_enc_ctx, NI_LOG_DEBUG, "encoder_encode_frame: ALL data (incl. eos) sent "
495 "already!\n");
496 return 0;
497 }
498
499 if (*need_to_resend)
500 {
501 goto send_frame;
502 }
503
504 p_in_frame->start_of_stream = 0;
505
506 // If this is the first frame, mark the frame as start-of-stream
507 if (!started)
508 {
509 started = 1;
510 p_in_frame->start_of_stream = 1;
511 }
512
513 // If this is the last frame, mark the frame as end-of-stream
514 p_in_frame->end_of_stream = input_exhausted ? 1 : 0;
515 p_in_frame->force_key_frame = 0;
516
517send_frame:
518
519 in_data.data.frame = *p_in_frame;
520 oneSent =
522
523 if (oneSent < 0)
524 {
525 (void)fprintf(stderr,
526 "Error: failed ni_device_session_write() for encoder\n");
527 *need_to_resend = 1;
528 return -1;
529 } else if (oneSent == 0 && !p_enc_ctx->ready_to_close)
530 {
531 *need_to_resend = 1;
532 ni_log2(p_enc_ctx, NI_LOG_DEBUG, "NEEDED TO RESEND");
533 } else
534 {
535 *need_to_resend = 0;
536
537 ni_log2(p_enc_ctx, NI_LOG_DEBUG, "encoder_encode_frame: total sent data size=%u\n",
538 p_in_frame->data_len[3]);
539
540 ni_log2(p_enc_ctx, NI_LOG_DEBUG, "encoder_encode_frame: success\n");
541
542 if (p_enc_ctx->ready_to_close)
543 {
544 enc_eos_sent = 1;
545 }
546 }
547
548 return 0;
549}
550
551/*!****************************************************************************
552 * \brief Receive output packet data from the Quadra encoder
553 *
554 * \param [in] p_enc_ctx pointer to encoder session context
555 * [in] p_out_data pointer to output data session
556 * [in] p_file pointer to file to write the packet
557 * [out] total_bytes_received running counter of bytes read
558 * [in] print_time 1 = print the time
559 *
560 * \return 0 - success got packet
561 * 1 - received eos
562 * 2 - got nothing, need retry
563 * -1 - failure
564 ******************************************************************************/
566 ni_session_data_io_t *p_out_data, FILE *p_file,
567 unsigned long long *total_bytes_received,
568 int print_time)
569{
570 int packet_size = NI_MAX_TX_SZ;
571 int rc = 0;
572 int end_flag = 0;
573 int rx_size = 0;
574 int meta_size = (int)p_enc_ctx->meta_size;
575 ni_packet_t *p_out_pkt = &(p_out_data->data.packet);
576 static int received_stream_header = 0;
577
578 ni_log2(p_enc_ctx, NI_LOG_DEBUG, "===> encoder_receive_data <===\n");
579
580 if (NI_INVALID_SESSION_ID == p_enc_ctx->session_id ||
581 NI_INVALID_DEVICE_HANDLE == p_enc_ctx->blk_io_handle)
582 {
583 ni_log2(p_enc_ctx, NI_LOG_DEBUG, "encode session not opened yet, return\n");
584 return 0;
585 }
586
587 if (p_file == NULL)
588 {
589 ni_log2(p_enc_ctx, NI_LOG_ERROR, "Bad file pointer, return\n");
590 return -1;
591 }
592
593 rc = ni_packet_buffer_alloc(p_out_pkt, packet_size);
594 if (rc != NI_RETCODE_SUCCESS)
595 {
596 (void)fprintf(stderr, "Error: malloc packet failed, ret = %d!\n", rc);
597 return -1;
598 }
599
600 /*
601 * The first data read from the encoder session context
602 * is a stream header read.
603 */
604 if (!received_stream_header)
605 {
606 /* Read the encoded stream header */
607 rc = ni_encoder_session_read_stream_header(p_enc_ctx, p_out_data);
608
609 if (rc > 0)
610 {
611 /* Write out the stream header */
612 if (fwrite((uint8_t *)p_out_pkt->p_data + meta_size,
613 p_out_pkt->data_len - meta_size, 1, p_file) != 1)
614 {
615 (void)fprintf(stderr, "Error: writing data %u bytes error!\n",
616 p_out_pkt->data_len - meta_size);
617 (void)fprintf(stderr, "Error: ferror rc = %d\n", ferror(p_file));
618 }
619
620 rx_size = rc;
621 *total_bytes_received += rx_size;
623 received_stream_header = 1;
624 } else if (rc != 0)
625 {
626 (void)fprintf(stderr, "Error: reading header %d\n", rc);
627 return -1;
628 }
629
630 if (print_time)
631 {
632 int timeDiff = (int)(current_time.tv_sec - start_time.tv_sec);
633 if (timeDiff == 0)
634 {
635 timeDiff = 1;
636 }
637 printf("[R] Got:%d Packets= %u fps=%u Total bytes %llu\n",
638 rx_size, number_of_packets, number_of_packets / timeDiff,
639 *total_bytes_received);
640 }
641
642 /* This shouldn't happen */
643 if (p_out_pkt->end_of_stream)
644 {
645 return 1;
646 } else if (rc == 0)
647 {
648 return 2;
649 }
650 }
651
652receive_data:
653 rc = ni_device_session_read(p_enc_ctx, p_out_data, NI_DEVICE_TYPE_ENCODER);
654
655 end_flag = (int)p_out_pkt->end_of_stream;
656 rx_size = rc;
657
658 ni_log2(p_enc_ctx, NI_LOG_DEBUG, "encoder_receive_data: received data size=%d\n", rx_size);
659
660 if (rx_size > meta_size)
661 {
662 if (fwrite((uint8_t *)p_out_pkt->p_data + meta_size,
663 p_out_pkt->data_len - meta_size, 1, p_file) != 1)
664 {
665 (void)fprintf(stderr, "Error: writing data %u bytes error!\n",
666 p_out_pkt->data_len - meta_size);
667 (void)fprintf(stderr, "Error: ferror rc = %d\n", ferror(p_file));
668 }
669
670 *total_bytes_received += rx_size - meta_size;
672
673 ni_log2(p_enc_ctx, NI_LOG_DEBUG, "Got: Packets= %u\n", number_of_packets);
674 } else if (rx_size != 0)
675 {
676 (void)fprintf(stderr, "Error: received %d bytes, <= metadata size %d!\n",
677 rx_size, meta_size);
678 return -1;
679 } else if (!end_flag &&
680 (((ni_xcoder_params_t *)(p_enc_ctx->p_session_config))
681 ->low_delay_mode))
682 {
683 ni_log2(p_enc_ctx, NI_LOG_DEBUG, "low delay mode and NO pkt, keep reading...\n");
684 goto receive_data;
685 }
686
687 if (print_time)
688 {
689 int timeDiff = (int)(current_time.tv_sec - start_time.tv_sec);
690 if (timeDiff == 0)
691 {
692 timeDiff = 1;
693 }
694 printf("[R] Got:%d Packets= %u fps=%u Total bytes %llu\n", rx_size,
696 *total_bytes_received);
697 }
698
699 if (end_flag)
700 {
701 printf("Encoder Receiving done\n");
702 return 1;
703 } else if (0 == rx_size)
704 {
705 return 2;
706 }
707
708 ni_log2(p_enc_ctx, NI_LOG_DEBUG, "encoder_receive_data: success\n");
709
710 return 0;
711}
712
713/*!****************************************************************************
714 * \brief Open an encoder session to Quadra
715 *
716 * \param [out] p_enc_ctx pointer to an encoder session context
717 * [in] dst_codec_format AVC or HEVC
718 * [in] iXcoderGUID id to identify the Quadra device
719 * [in] p_enc_params sets the encoder parameters
720 * [in] width width of frames to encode
721 * [in] height height of frames to encode
722 *
723 * \return 0 if successful, < 0 otherwise
724 ******************************************************************************/
725int encoder_open_session(ni_session_context_t *p_enc_ctx, int dst_codec_format,
726 int iXcoderGUID, ni_xcoder_params_t *p_enc_params,
727 int width, int height, ni_frame_t *p_frame)
728{
729 int ret = 0;
730
731 // Enable hardware frame encoding
732 p_enc_ctx->hw_action = NI_CODEC_HW_ENABLE;
733 p_enc_params->hwframes = 1;
734
735 // Provide the first frame to the Quadra encoder
736 p_enc_params->p_first_frame = p_frame;
737
738 // Specify codec, AVC vs HEVC
739 p_enc_ctx->codec_format = dst_codec_format;
740
741 p_enc_ctx->p_session_config = p_enc_params;
743
744 // Assign the card GUID in the encoder context to open a session
745 // to that specific Quadra device
746 p_enc_ctx->device_handle = NI_INVALID_DEVICE_HANDLE;
747 p_enc_ctx->blk_io_handle = NI_INVALID_DEVICE_HANDLE;
748 p_enc_ctx->hw_id = iXcoderGUID;
749
750 if (g_rgb2yuv_csc)
751 p_enc_ctx->pixel_format = NI_PIX_FMT_ABGR;
752
753 ni_encoder_set_input_frame_format(p_enc_ctx, p_enc_params, width, height, 8,
755
756 // Encoder will operate in P2P mode
758 if (ret != NI_RETCODE_SUCCESS)
759 {
760 (void)fprintf(stderr, "Error: encoder open session failure\n");
761 } else
762 {
763 printf("Encoder device %d session open successful\n", iXcoderGUID);
764 }
765
766 return ret;
767}
768
769/*!****************************************************************************
770 * \brief Open an upload session to Quadra
771 *
772 * \param [out] p_upl_ctx pointer to an upload context of the open session
773 * [in] iXcoderGUID pointer to Quadra card hw id
774 * [in] width width of the frames
775 * [in] height height of the frames
776 *
777 * \return 0 if successful, < 0 otherwise
778 ******************************************************************************/
779int uploader_open_session(ni_session_context_t *p_upl_ctx, int *iXcoderGUID,
780 int width, int height)
781{
782 int ret = 0;
783 ni_pix_fmt_t frame_format;
784
786
787 // Assign the card GUID in the encoder context
788 p_upl_ctx->device_handle = NI_INVALID_DEVICE_HANDLE;
789 p_upl_ctx->blk_io_handle = NI_INVALID_DEVICE_HANDLE;
790
791 // Assign the card id to specify the specific Quadra device
792 p_upl_ctx->hw_id = *iXcoderGUID;
793
794 // Assign the pixel format we want to use
796
797 // Set the input frame format of the upload session
798 ni_uploader_set_frame_format(p_upl_ctx, width, height, frame_format,
799 1);
800
802 if (ret != NI_RETCODE_SUCCESS)
803 {
804 (void)fprintf(stderr, "Error: uploader_open_session failure!\n");
805 return ret;
806 } else
807 {
808 printf("Uploader device %d session opened successfully\n",
809 *iXcoderGUID);
810 *iXcoderGUID = p_upl_ctx->hw_id;
811 }
812
813 // Create a P2P frame pool for the uploader sesson of pool size 2
814 ret = ni_device_session_init_framepool(p_upl_ctx, POOL_SIZE, 1);
815 if (ret < 0)
816 {
817 (void)fprintf(stderr, "Error: Can't create frame pool\n");
819 } else
820 {
821 printf("Uploader device %d configured successfully\n", *iXcoderGUID);
822 }
823
824 return ret;
825}
826
827/*!****************************************************************************
828 * \brief Print usage information
829 *
830 * \param none
831 *
832 * \return none
833 ******************************************************************************/
834void print_usage(void)
835{
836 printf("Video encoder/P2P application directly using Netint "
837 "Libxcoder release v%s\n"
838 "Usage: xcoderp2p [options]\n"
839 "\n"
840 "options:\n"
841 "--------------------------------------------------------------------------------\n"
842 " -h | --help Show help.\n"
843 " -v | --version Print version info.\n"
844 " -l | --loglevel Set loglevel of libxcoder API.\n"
845 " [none, fatal, error, info, debug, trace]\n"
846 " Default: info\n"
847 " -c | --card Set card index to use.\n"
848 " See `ni_rsrc_mon` for cards on system.\n"
849 " (Default: 0)\n"
850 " -i | --input Input file path.\n"
851 " -r | --repeat (Positive integer) to Repeat input X times "
852 "for performance \n"
853 " test. (Default: 1)\n"
854 " -s | --size Resolution of input file in format "
855 "WIDTHxHEIGHT.\n"
856 " (eg. '1920x1080')\n"
857 " -m | --mode Input to output codec processing mode in "
858 "format:\n"
859 " INTYPE2OUTTYPE. [p2a, p2h, r2a, r2h]\n"
860 " Type notation: p=P2P, a=AVC, h=HEVC, r=ABGR\n"
861 " -o | --output Output file path.\n",
863}
864
865/*!****************************************************************************
866 * \brief Parse user command line arguments
867 *
868 * \param [in] argc argument count
869 * [in] argv argument vector
870 * [out] input_filename input filename
871 * [out] output_filename output filename
872 * [out] iXcoderGUID Quadra device
873 * [out] arg_width resolution width
874 * [out] arg_height resolution height
875 * [out] dst_codec_format codec (AVC vs HEVC)
876 *
877 * \return nothing program exit on error
878 ******************************************************************************/
879void parse_arguments(int argc, char *argv[], char *input_filename,
880 char *output_filename, int *iXcoderGUID, int *arg_width,
881 int *arg_height, int *dst_codec_format)
882{
883 char xcoderGUID[32];
884 char mode_description[128];
885 char *n; // used for parsing width and height from --size
886 size_t i;
887 int opt;
888 int opt_index;
889 ni_log_level_t log_level;
890
891 static const char *opt_string = "hvl:c:i:s:m:o:r:";
892 static const struct option long_options[] = {
893 {"help", no_argument, NULL, 'h'},
894 {"version", no_argument, NULL, 'v'},
895 {"loglevel", no_argument, NULL, 'l'},
896 {"card", required_argument, NULL, 'c'},
897 {"input", required_argument, NULL, 'i'},
898 {"size", required_argument, NULL, 's'},
899 {"mode", required_argument, NULL, 'm'},
900 {"output", required_argument, NULL, 'o'},
901 {"repeat", required_argument, NULL, 'r'},
902 {NULL, 0, NULL, 0},
903 };
904
905 while ((opt = getopt_long(argc, argv, opt_string, long_options, // NOLINT(concurrency-mt-unsafe) - single-threaded CLI tool
906 &opt_index)) != -1)
907 {
908 switch (opt)
909 {
910 case 'h':
911 print_usage();
912 exit(0); // NOLINT(concurrency-mt-unsafe) - single-threaded CLI tool
913 case 'v':
914 printf("Release ver: %s\n"
915 "API ver: %s\n"
916 "Date: %s\n"
917 "ID: %s\n",
920 exit(0); // NOLINT(concurrency-mt-unsafe) - single-threaded CLI tool
921 case 'l':
922 log_level = arg_to_ni_log_level(optarg);
923 if (log_level != NI_LOG_INVALID)
924 {
925 ni_log_set_level(log_level);
926 } else {
927 arg_error_exit("-l | --loglevel", optarg);
928 }
929 break;
930 case 'c':
931 ni_strcpy(xcoderGUID, sizeof(xcoderGUID), optarg);
932 *iXcoderGUID = (int)strtol(optarg, &n, 10);
933 // No numeric characters found in left side of optarg
934 if (n == xcoderGUID)
935 arg_error_exit("-c | --card", optarg);
936 break;
937 case 'i':
938 ni_strcpy(input_filename, FILE_NAME_LEN, optarg);
939 break;
940 case 's':
941 *arg_width = (int)strtol(optarg, &n, 10);
942 {
943 int32_t tmp_height;
944 if (ni_strtoi(n + 1, &tmp_height) != NI_RETCODE_SUCCESS)
945 arg_error_exit("-s | --size", optarg);
946 *arg_height = (int)tmp_height;
947 }
948 if ((*n != 'x') || (!*arg_width || !*arg_height))
949 arg_error_exit("-s | --size", optarg);
950 break;
951 case 'm':
952 if (!(strlen(optarg) == 3))
953 arg_error_exit("-m | --mode", optarg);
954
955 // convert to lower case for processing
956 for (i = 0; i < strlen(optarg); i++)
957 optarg[i] = (char)tolower((unsigned char)optarg[i]);
958
959 if (strcmp(optarg, "p2a") != 0 && strcmp(optarg, "p2h") != 0 &&
960 strcmp(optarg, "r2a") != 0 && strcmp(optarg, "r2h") != 0)
961 arg_error_exit("-, | --mode", optarg);
962
963 // determine codec
964 ni_sprintf(mode_description, 128, "P2P + Encoding");
965
966 g_rgb2yuv_csc = (optarg[0] == 'r') ? 1 : 0;
967
968 if (optarg[2] == 'a')
969 {
970 *dst_codec_format = NI_CODEC_FORMAT_H264;
971 ni_strcat(mode_description, 128, " to AVC");
972 }
973
974 if (optarg[2] == 'h')
975 {
976 *dst_codec_format = NI_CODEC_FORMAT_H265;
977 ni_strcat(mode_description, 128, " to HEVC");
978 }
979 printf("%s...\n", mode_description);
980
981 break;
982 case 'o':
983 ni_strcpy(output_filename, FILE_NAME_LEN, optarg);
984 break;
985 case 'r':
986 {
987 int32_t tmp_repeat;
988 if (ni_strtoi(optarg, &tmp_repeat) != NI_RETCODE_SUCCESS)
989 arg_error_exit("-r | --repeat", optarg);
990 if (!(tmp_repeat >= 1))
991 arg_error_exit("-r | --repeat", optarg);
992 g_repeat = (int)tmp_repeat;
993 break;
994 }
995 default:
996 print_usage();
997 exit(1); // NOLINT(concurrency-mt-unsafe) - single-threaded CLI tool
998 }
999 }
1000
1001 // Check required args are present
1002 if (!input_filename[0])
1003 {
1004 printf("Error: missing argument for -i | --input\n");
1005 exit(-1); // NOLINT(concurrency-mt-unsafe) - single-threaded CLI tool
1006 }
1007
1008 if (!output_filename[0])
1009 {
1010 printf("Error: missing argument for -o | --output\n");
1011 exit(-1); // NOLINT(concurrency-mt-unsafe) - single-threaded CLI tool
1012 }
1013}
1014
1015int main(int argc, char *argv[])
1016{
1017 static char input_filename[FILE_NAME_LEN];
1018 static char output_filename[FILE_NAME_LEN];
1019 unsigned long total_bytes_sent;
1020 unsigned long long total_bytes_received;
1021 int input_video_width;
1022 int input_video_height;
1023 int iXcoderGUID = 0;
1024 int arg_width = 0;
1025 int arg_height = 0;
1026 int input_exhausted = 0;
1027 int num_post_recycled = 0;
1028 int dst_codec_format = 0;
1029 int ret;
1030 int timeDiff;
1031 int print_time;
1032 int need_to_resend = 0;
1033 int render_index = 0;
1034 int encode_index = -1;
1035 FILE *p_file = NULL;
1036 ni_xcoder_params_t api_param;
1037 ni_session_context_t enc_ctx = {0};
1038 ni_session_context_t upl_ctx = {0};
1039 ni_frame_t p2p_frame[POOL_SIZE];
1040 ni_session_data_io_t out_packet = {0};
1041 int input_file_fd = -1;
1042
1043 parse_arguments(argc, argv, input_filename, output_filename, &iXcoderGUID,
1044 &arg_width, &arg_height, &dst_codec_format);
1045
1046 // Load input file into memory
1047 if (load_input_file(input_filename, &total_file_size) < 0)
1048 {
1049 exit(-1); // NOLINT(concurrency-mt-unsafe) - single-threaded CLI tool
1050 }
1051
1053
1054 // Create output file
1055 if (strcmp(output_filename, "null") != 0)
1056 {
1057 ni_fopen(&p_file, output_filename, "wb");
1058 if (p_file == NULL)
1059 {
1060 (void)fprintf(stderr, "Error: cannot open %s\n", output_filename);
1061 goto end;
1062 }
1063 }
1064
1065 printf("SUCCESS: Opened output file: %s\n", output_filename);
1066
1067 if (ni_device_session_context_init(&enc_ctx) < 0)
1068 {
1069 (void)fprintf(stderr, "Error: init encoder context error\n");
1070 return -1;
1071 }
1072
1073 if (ni_device_session_context_init(&upl_ctx) < 0)
1074 {
1075 (void)fprintf(stderr, "Error: init uploader context error\n");
1076 return -1;
1077 }
1078
1079 total_bytes_received = 0;
1080 total_bytes_sent = 0;
1081
1082 send_fin_flag = 0;
1083 receive_fin_flag = 0;
1084
1085 printf("User video resolution: %dx%d\n", arg_width, arg_height);
1086
1087 if (arg_width == 0 || arg_height == 0)
1088 {
1089 input_video_width = 1280;
1090 input_video_height = 720;
1091 } else
1092 {
1093 input_video_width = arg_width;
1094 input_video_height = arg_height;
1095 }
1096
1101
1102 printf("P2P Encoding resolution: %dx%d\n", input_video_width,
1103 input_video_height);
1104
1105 // Open an uploader session to Quadra
1106 if (uploader_open_session(&upl_ctx, &iXcoderGUID, arg_width, arg_height))
1107 {
1108 goto end;
1109 }
1110
1111 // Configure the encoder parameter structure. We'll use some basic
1112 // defaults: 30 fps, 200000 bps CBR encoding, AVC or HEVC encoding
1113 if (ni_encoder_init_default_params(&api_param, 30, 1, 200000, arg_width,
1114 arg_height, enc_ctx.codec_format) < 0)
1115 {
1116 (void)fprintf(stderr, "Error: encoder init default set up error\n");
1118 return -1;
1119 }
1120
1121 // For P2P demo, change some of the encoding parameters from
1122 // the default. Enable low delay encoding.
1123 ret = ni_encoder_params_set_value(&api_param, "lowDelay", "1");
1124 if (ret != NI_RETCODE_SUCCESS)
1125 {
1126 (void)fprintf(stderr, "Error: can't set low delay mode %d\n", ret);
1128 return -1;
1129 }
1130
1131 // Use a GOP preset of 9 which represents a GOP pattern of
1132 // IPPPPPPP....This will be low latency.
1133 ret = ni_encoder_params_set_value(&api_param, "gopPresetIdx", "9");
1134 if (ret != NI_RETCODE_SUCCESS)
1135 {
1136 (void)fprintf(stderr, "Error: can't set gop preset %d\n", ret);
1138 return -1;
1139 }
1140
1141 // Prepare two frames for double buffering
1142 ret = p2p_prepare_frames(&upl_ctx, input_video_width, input_video_height,
1143 p2p_frame);
1144
1145 if (ret < 0)
1146 {
1148 goto end;
1149 }
1150
1151 // Open the encoder session with given parameters
1152 ret = encoder_open_session(&enc_ctx, dst_codec_format, iXcoderGUID,
1153 &api_param, arg_width, arg_height,
1154 &p2p_frame[render_index]);
1155 if (ret < 0)
1156 {
1158 goto end;
1159 }
1160
1161#ifdef _WIN32
1162 input_file_fd = open(input_filename, O_RDONLY | O_BINARY);
1163#else
1164 input_file_fd = open(input_filename, O_RDONLY);
1165#endif
1166
1167 if (input_file_fd < 0)
1168 {
1169 (void)fprintf(stderr, "Error: can not open input file %s\n", input_filename);
1170 goto end;
1171 }
1172
1173 if (g_rgb2yuv_csc)
1174 {
1175 // upload an rgba frame to quadra
1177 &upl_ctx, input_file_fd, &g_rgba_frame[render_index],
1178 &p2p_frame[render_index], input_video_width, input_video_height,
1179 &total_bytes_sent, &input_exhausted))
1180 {
1181 (void)fprintf(stderr, "Error: upload frame error\n");
1183 goto end;
1184 }
1185 } else
1186 {
1187 /* send out a frame to do rendering */
1189 &upl_ctx, input_file_fd, &g_yuv_frame[render_index],
1190 &p2p_frame[render_index], input_video_width, input_video_height,
1191 &total_bytes_sent, &input_exhausted))
1192 {
1193 (void)fprintf(stderr, "Error: upload frame error\n");
1194 close(input_file_fd);
1195 return -1;
1196 }
1197 }
1198
1199 while (send_fin_flag == 0 || receive_fin_flag == 0)
1200 {
1202
1203 // Print the time if >= 1 second has passed
1204 print_time = ((current_time.tv_sec - previous_time.tv_sec) > 1);
1205 encode_index = render_index;
1206
1207 // Encode the frame
1208 send_fin_flag = encoder_encode_frame(&enc_ctx, &p2p_frame[encode_index],
1209 input_exhausted, &need_to_resend);
1210
1211 // Error, exit
1212 if (send_fin_flag == 2)
1213 {
1214 break;
1215 }
1216
1217 // Switch to the other hw frame buffer
1218 render_index = !render_index;
1219
1220 // Fill the frame buffer with YUV data while the previous frame is being encoded
1221 if (!input_exhausted && need_to_resend == 0)
1222 {
1223 if (g_rgb2yuv_csc)
1224 {
1226 &upl_ctx, input_file_fd, &g_rgba_frame[render_index],
1227 &p2p_frame[render_index], input_video_width,
1228 input_video_height, &total_bytes_sent, &input_exhausted))
1229 {
1230 (void)fprintf(stderr, "Error: upload frame error\n");
1231 close(input_file_fd);
1232 return -1;
1233 }
1234 }
1235 else
1236 {
1238 &upl_ctx, input_file_fd, &g_yuv_frame[render_index],
1239 &p2p_frame[render_index], input_video_width,
1240 input_video_height, &total_bytes_sent, &input_exhausted))
1241 {
1242 (void)fprintf(stderr, "Error: upload frame error\n");
1243 close(input_file_fd);
1244 return -1;
1245 }
1246 }
1247 }
1248
1249 // Receive encoded packet data from the encoder
1251 &enc_ctx, &out_packet, p_file, &total_bytes_received, print_time);
1252
1253 if (print_time)
1254 {
1256 }
1257
1258 // Error or eos
1259 if (receive_fin_flag < 0 || out_packet.data.packet.end_of_stream)
1260 {
1261 break;
1262 }
1263 }
1264
1265 timeDiff = (int)(current_time.tv_sec - start_time.tv_sec);
1266 timeDiff = (timeDiff > 0) ? timeDiff : 1; // avoid division by zero
1267
1268 printf("[R] Got: Packets= %u fps=%u Total bytes %llu\n",
1270 total_bytes_received);
1271
1272 // Recycle the hardware frames back to the pool prior
1273 // to closing the uploader session.
1274 num_post_recycled = recycle_frames(p2p_frame);
1275
1276 ni_log(NI_LOG_DEBUG, "Cleanup recycled %d internal buffers\n", num_post_recycled);
1277
1280
1283
1284 for (int i = 0; i < POOL_SIZE; i++)
1285 {
1286 ni_frame_buffer_free(&(p2p_frame[i]));
1287 }
1288
1289 ni_packet_buffer_free(&(out_packet.data.packet));
1290
1291end:
1292 close(input_file_fd);
1293
1294 if (p_file)
1295 {
1296 (void)fclose(p_file);
1297 }
1298
1299 printf("All done\n");
1300
1301 return 0;
1302}
int main()
Definition client.cpp:51
#define NI_XCODER_REVISION
Definition ni_defs.h:98
#define LIBXCODER_API_VERSION
Definition ni_defs.h:115
#define NI_MAX_NUM_DATA_POINTERS
Definition ni_defs.h:244
@ NI_DEVICE_TYPE_UPLOAD
Definition ni_defs.h:367
@ NI_DEVICE_TYPE_ENCODER
Definition ni_defs.h:361
#define NI_MAX_TX_SZ
Definition ni_defs.h:261
ni_retcode_t
Definition ni_defs.h:447
@ NI_RETCODE_SUCCESS
Definition ni_defs.h:448
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...
ni_retcode_t ni_device_session_close(ni_session_context_t *p_ctx, int eos_recieved, ni_device_type_t device_type)
Close device session that was previously opened by calling ni_device_session_open() If device_type is...
ni_retcode_t ni_device_session_open(ni_session_context_t *p_ctx, ni_device_type_t device_type)
Open a new device session depending on the device_type parameter If device_type is NI_DEVICE_TYPE_DEC...
ni_retcode_t ni_encoder_set_input_frame_format(ni_session_context_t *p_enc_ctx, ni_xcoder_params_t *p_enc_params, int width, int height, int bit_depth, int src_endian, int planar)
Set the incoming frame format for the encoder.
ni_retcode_t ni_packet_buffer_free(ni_packet_t *p_packet)
Free packet buffer that was previously allocated with ni_packet_buffer_alloc.
ni_retcode_t ni_hwframe_p2p_buffer_recycle(ni_frame_t *p_frame)
Recycle hw P2P frames.
ni_retcode_t ni_encoder_init_default_params(ni_xcoder_params_t *p_param, int fps_num, int fps_denom, long bit_rate, int width, int height, ni_codec_format_t codec_format)
Initialize default encoder parameters.
ni_retcode_t ni_uploader_p2p_test_send(ni_session_context_t *p_upl_ctx, uint8_t *p_data, uint32_t len, ni_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_device_session_read(ni_session_context_t *p_ctx, ni_session_data_io_t *p_data, ni_device_type_t device_type)
Read data from the device If device_type is NI_DEVICE_TYPE_DECODER reads data packet from decoder If ...
int ni_device_session_acquire(ni_session_context_t *p_ctx, ni_frame_t *p_frame)
Acquire a P2P frame buffer from the hwupload session.
int ni_encoder_session_read_stream_header(ni_session_context_t *p_ctx, ni_session_data_io_t *p_data)
Read encoder stream header from the device.
ni_retcode_t ni_uploader_set_frame_format(ni_session_context_t *p_upl_ctx, int width, int height, ni_pix_fmt_t pixel_format, int isP2P)
Set the outgoing frame format for the uploader.
ni_retcode_t ni_device_session_context_init(ni_session_context_t *p_ctx)
Initialize already allocated session context to a known state.
ni_retcode_t ni_encoder_params_set_value(ni_xcoder_params_t *p_params, const char *name, const char *value)
Set value referenced by name in encoder parameters structure.
int ni_device_session_init_framepool(ni_session_context_t *p_ctx, uint32_t pool_size, uint32_t pool)
Sends frame pool setup info to device.
ni_retcode_t ni_frame_buffer_alloc_hwenc(ni_frame_t *p_frame, int video_width, int video_height, int extra_len)
Allocate memory for the hwDescriptor buffer based on provided parameters taking into account pic size...
ni_retcode_t ni_packet_buffer_alloc(ni_packet_t *p_packet, int packet_size)
Allocate memory for the packet buffer based on provided packet size.
void ni_device_session_context_clear(ni_session_context_t *p_ctx)
Clear already allocated session context.
int ni_device_session_write(ni_session_context_t *p_ctx, ni_session_data_io_t *p_data, ni_device_type_t device_type)
Sends data to the device If device_type is NI_DEVICE_TYPE_DECODER sends data packet to decoder If dev...
Public definitions for operating NETINT video processing devices for video processing.
#define NI_FRAME_LITTLE_ENDIAN
#define NI_INVALID_SESSION_ID
#define NI_VPU_ALIGN4096(_x)
@ NI_CODEC_HW_ENABLE
@ NI_CODEC_FORMAT_H265
@ NI_CODEC_FORMAT_H264
ni_pix_fmt_t
@ NI_PIX_FMT_YUV420P
@ NI_PIX_FMT_ABGR
char * optarg
Definition ni_getopt.c:33
int getopt_long(int argc, char *argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition ni_getopt.c:99
#define no_argument
Definition ni_getopt.h:85
#define required_argument
Definition ni_getopt.h:86
void ni_log2(const void *p_context, ni_log_level_t level, const char *fmt,...)
print log message and additional information using ni_log_callback,
Definition ni_log.c:337
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
void ni_log_set_level(ni_log_level_t level)
Set ni_log_level.
Definition ni_log.c:202
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_level_t
Definition ni_log.h:58
@ NI_LOG_DEBUG
Definition ni_log.h:64
@ NI_LOG_ERROR
Definition ni_log.h:62
@ NI_LOG_INVALID
Definition ni_log.h:59
int load_input_file(const char *filename, unsigned long *bytes_read)
Load the input file into memory.
#define MAX_YUV_FRAME_SIZE
Definition ni_p2p_test.c:49
int p2p_upload_rgba_send_data(ni_session_context_t *p_upl_ctx, int fd, uint8_t **p_rgba_frame, ni_frame_t *p_in_frame, int input_video_width, int input_video_height, unsigned long *bytes_sent, int *input_exhausted)
Reads RGBA data from input file then calls a special libxcoder API function to transfer the RGBA data...
int encoder_receive_data(ni_session_context_t *p_enc_ctx, ni_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.
#define MAX_ABGR_FRAME_SIZE
Definition ni_p2p_test.c:50
time_t start_timestamp
Definition ni_p2p_test.c:67
uint8_t * g_curr_cache_pos
Definition ni_p2p_test.c:73
int encoder_encode_frame(ni_session_context_t *p_enc_ctx, ni_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.
uint8_t g_rgb2yuv_csc
Definition ni_p2p_test.c:77
int p2p_prepare_frames(ni_session_context_t *p_upl_ctx, int input_video_width, int input_video_height, ni_frame_t p2p_frame[])
Prepare frames to simulate P2P transfers.
time_t previous_timestamp
Definition ni_p2p_test.c:68
struct timeval current_time
Definition ni_p2p_test.c:65
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
Definition ni_p2p_test.c:69
int enc_eos_sent
Definition ni_p2p_test.c:56
uint8_t * g_rgba_frame[POOL_SIZE]
Definition ni_p2p_test.c:75
int recycle_frames(ni_frame_t p2p_frame[])
Recycle hw frames back to Quadra.
int encoder_open_session(ni_session_context_t *p_enc_ctx, int dst_codec_format, int iXcoderGUID, ni_xcoder_params_t *p_enc_params, int width, int height, ni_frame_t *p_frame)
Open an encoder session to Quadra.
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
Definition ni_p2p_test.c:51
uint8_t * g_yuv_frame[POOL_SIZE]
Definition ni_p2p_test.c:74
uint32_t number_of_packets
Definition ni_p2p_test.c:59
unsigned long total_file_size
Definition ni_p2p_test.c:71
struct timeval start_time
Definition ni_p2p_test.c:63
uint64_t data_left_size
Definition ni_p2p_test.c:60
void arg_error_exit(char *arg_name, char *param)
Exit on argument error.
Definition ni_p2p_test.c:87
int receive_fin_flag
Definition ni_p2p_test.c:55
int g_repeat
Definition ni_p2p_test.c:61
struct timeval previous_time
Definition ni_p2p_test.c:64
uint32_t number_of_frames
Definition ni_p2p_test.c:58
int uploader_open_session(ni_session_context_t *p_upl_ctx, int *iXcoderGUID, int width, int height)
Open an upload session to Quadra.
int p2p_upload_send_data(ni_session_context_t *p_upl_ctx, int fd, uint8_t **p_yuv420p_frame, ni_frame_t *p_in_frame, int input_video_width, int input_video_height, unsigned long *bytes_sent, int *input_exhausted)
Reads YUV data from input file then calls a special libxcoder API function to transfer the YUV data i...
int send_fin_flag
Definition ni_p2p_test.c:54
#define FILE_NAME_LEN
Definition ni_p2p_test.c:52
#define NI_SW_RELEASE_ID
#define NI_SW_RELEASE_TIME
int ni_posix_memalign(void **memptr, size_t alignment, size_t size)
Allocate aligned memory.
Definition ni_util.c:206
int32_t ni_gettimeofday(struct timeval *p_tp, void *p_tzp)
Get time for logs with microsecond timestamps.
Definition ni_util.c:147
ni_retcode_t ni_strcat(char *dest, size_t dmax, const char *src)
Definition ni_util.c:704
void ni_get_hw_yuv420p_dim(int width, int height, int factor, int is_semiplanar, int plane_stride[NI_MAX_NUM_DATA_POINTERS], int plane_height[NI_MAX_NUM_DATA_POINTERS])
Get dimension information of Netint HW YUV420p frame to be sent to encoder for encoding....
Definition ni_util.c:2743
ni_retcode_t ni_fopen(FILE **fp, const char *filename, const char *mode)
Definition ni_util.c:998
ni_retcode_t ni_strcpy(char *dest, size_t dmax, const char *src)
Definition ni_util.c:460
int ni_sprintf(char *dest, size_t dmax, const char *fmt,...)
Definition ni_util.c:1077
ni_retcode_t ni_strtoi(const char *str, int32_t *out_val)
Safely convert a decimal string to a 32-bit integer with full validation. Trailing whitespace is tole...
Definition ni_util.c:2577
void ni_copy_hw_yuv420p(uint8_t *p_dst[NI_MAX_NUM_DATA_POINTERS], uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS], int frame_width, int frame_height, int factor, int is_semiplanar, int conf_win_right, int dst_stride[NI_MAX_NUM_DATA_POINTERS], int dst_height[NI_MAX_NUM_DATA_POINTERS], int src_stride[NI_MAX_NUM_DATA_POINTERS], int src_height[NI_MAX_NUM_DATA_POINTERS])
Copy YUV data to Netint HW YUV420p frame layout to be sent to encoder for encoding....
Definition ni_util.c:3056
Utility definitions.
uint32_t data_len[NI_MAX_NUM_DATA_POINTERS]
uint32_t start_of_stream
uint32_t end_of_stream
uint32_t video_width
unsigned int extra_data_len
uint32_t video_height
uint32_t data_len
uint32_t end_of_stream
ni_device_handle_t device_handle
uint32_t meta_size
Params used in VFR mode Done///.
ni_device_handle_t blk_io_handle
union _ni_session_data_io::@19 data
ni_frame_t * p_first_frame