libxcoder 5.6.0
Loading...
Searching...
No Matches
ni_generic_utils.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 generic_utils.c
24 *
25 * \brief Miscellaneous utility functions shared by Libxcoder API examples
26 ******************************************************************************/
27
28#if __linux__ || __APPLE__
29#include <sys/types.h>
30#endif
31
32#include "ni_generic_utils.h"
33#include "ni_filter_utils.h"
34#include "ni_log.h"
35#include "ni_util.h"
36
37static const ni_pix_fmt_name_t g_ni_pix_fmt_name_list[] = {
38 {"yuv420p", NI_PIX_FMT_YUV420P}, /* 8-bit YUV420 planar */
39 {"yuv420p10le", NI_PIX_FMT_YUV420P10LE}, /* 10-bit YUV420 planar */
40 {"nv12", NI_PIX_FMT_NV12}, /* 8-bit YUV420 semi-planar */
41 {"p010le", NI_PIX_FMT_P010LE}, /* 10-bit YUV420 semi-planar */
42 {"rgba", NI_PIX_FMT_RGBA}, /* 32-bit RGBA packed */
43 {"bgra", NI_PIX_FMT_BGRA}, /* 32-bit BGRA packed */
44 {"argb", NI_PIX_FMT_ARGB}, /* 32-bit ARGB packed */
45 {"abgr", NI_PIX_FMT_ABGR}, /* 32-bit ABGR packed */
46 {"bgr0", NI_PIX_FMT_BGR0}, /* 32-bit RGB packed */
47 {"null", NI_PIX_FMT_NONE}, /* invalid format */
48};
49
50static const ni_gc620_pix_fmt_t g_ni_gc620_pix_fmt_list[] = {
64};
65
66void print_version(void)
67{
69 "Release ver: %s\n"
70 "API ver: %s\n"
71 "Date: %s\n"
72 "ID: %s\n",
75}
76
78{
79 return pix_fmt == NI_PIX_FMT_YUV420P || pix_fmt == NI_PIX_FMT_NV12 ||
80 pix_fmt == NI_PIX_FMT_YUV420P10LE || pix_fmt == NI_PIX_FMT_P010LE ||
81 pix_fmt == NI_PIX_FMT_RGBA || pix_fmt == NI_PIX_FMT_BGRA ||
82 pix_fmt == NI_PIX_FMT_ARGB || pix_fmt == NI_PIX_FMT_ABGR;
83}
84
86{
87 int i;
88
89 for (i = 0; i < sizeof(g_ni_pix_fmt_name_list)/sizeof(ni_pix_fmt_name_t); i++)
90 {
91 if (!strcmp(name, g_ni_pix_fmt_name_list[i].name))
92 {
93 return g_ni_pix_fmt_name_list[i].pix_fmt;
94 }
95 }
96
97 return NI_PIX_FMT_NONE;
98}
99
101{
102 int i;
103
104 for (i = 0; i < sizeof(g_ni_pix_fmt_name_list)/sizeof(ni_pix_fmt_name_t); i++)
105 {
106 if (pix_fmt == g_ni_pix_fmt_name_list[i].pix_fmt)
107 {
108 return g_ni_pix_fmt_name_list[i].name;
109 }
110 }
111
112 return NULL;
113}
114
116{
117 int i;
118
119 for (i = 0; i < sizeof(g_ni_gc620_pix_fmt_list)/sizeof(ni_gc620_pix_fmt_t); i++)
120 {
121 if (g_ni_gc620_pix_fmt_list[i].pix_fmt_ni == pix_fmt)
122 {
123 return g_ni_gc620_pix_fmt_list[i].pix_fmt_gc620;
124 }
125 }
126
127 return -1;
128}
129
131{
132 int i;
133
134 for (i = 0; i < sizeof(g_ni_gc620_pix_fmt_list)/sizeof(ni_gc620_pix_fmt_t); i++)
135 {
136 if (g_ni_gc620_pix_fmt_list[i].pix_fmt_gc620 == pix_fmt)
137 {
138 return g_ni_gc620_pix_fmt_list[i].pix_fmt_ni;
139 }
140 }
141
142 return -1;
143}
144
146{
147 ni_pixel_planar_format ret = -1;
148 switch (pix_fmt)
149 {
150 case NI_PIX_FMT_NV12:
153 break;
157 break;
160 case NI_PIX_FMT_ABGR: /* 32-bit ABGR packed */
161 case NI_PIX_FMT_ARGB:
162 case NI_PIX_FMT_RGBA:
163 case NI_PIX_FMT_BGRA:
164 case NI_PIX_FMT_BGR0:
166 break;
167 default:
168 break;
169 }
170
171 return ret;
172}
173
175{
176 return (list->head == list->tail);
177}
178
180{
181 return (list->head == ((list->tail + 1) % NI_MAX_BUFFERED_FRAME));
182}
183
185{
186 // There are two types of pixel formats for hw uploading. One is those
187 // supported by the NI encoder such as yuv420p nv12 etc. The other is those
188 // unsupported by the NI encoder such as rgba bgr0 etc. Such formats should
189 // be restricted by the hw scaler pool size in number because they have to
190 // be converted into the formats as former.
191 if (is_ni_enc_pix_fmt(pix_fmt))
192 {
193 return frame_list_is_full(list);
194 } else
195 {
196 return frame_list_length(list) >=
199 }
200}
201
203{
204 return ((list->tail - list->head + NI_MAX_BUFFERED_FRAME) %
206}
207
209{
210 if (frame_list_is_full(list))
211 {
212 return -1;
213 }
214 list->tail = (list->tail + 1) % NI_MAX_BUFFERED_FRAME;
215 return 0;
216}
217
219{
220 if (frame_list_is_empty(list))
221 {
222 return -1;
223 }
224 list->head = (list->head + 1) % NI_MAX_BUFFERED_FRAME;
225 return 0;
226}
227
228//Applies only to hwframe where recycling HW frame to FW is needed
229//Loop through unsent frames to set in tracking list for cleanup
231{
232 int i;
233
234 // store the unsent frames in the tracker to be cleared out by scan at end
235 while (!frame_list_is_empty(list))
236 {
237 ni_frame_t *p_frame = &list->frames[list->head].data.frame;
238 niFrameSurface1_t *p_surface = (niFrameSurface1_t *)p_frame->p_data[3];
239 ni_hw_frame_ref(p_surface);
240 frame_list_drain(list);
241 }
242
243 for (i = 0; i < NI_MAX_BUFFERED_FRAME; i++)
244 {
246 }
247}
248
249uint64_t get_total_file_size(FILE *fp)
250{
251 uint64_t total_file_size;
252 fseek(fp, 0, SEEK_END);
253 total_file_size = ftell(fp);
254 fseek(fp, 0, SEEK_SET);
255 return total_file_size;
256}
257
258int read_and_cache_file(ni_demo_context_t *ctx, char *filename)
259{
260 FILE *fp = NULL;
261 uint64_t total_file_size;
262 size_t read_chunk = 4096;
263 size_t read_rc;
264 uint64_t file_size_left;
265
266 ni_fopen(&fp, filename, "rb");
267 if (!fp)
268 {
269 ni_log(NI_LOG_ERROR, "Error: Failed to open file %s\n", filename);
270 return -1;
271 }
274 file_size_left = total_file_size;
275
276 //try to allocate memory for input file buffer, quit if failure
277 if (total_file_size > 0 && !(ctx->file_cache = malloc(total_file_size)))
278 {
280 "Error: Failed to allocate memory of size %llu for file cache\n",
281 (unsigned long long)total_file_size);
282 fclose(fp);
283 return -1;
284 }
285
286 ctx->curr_file_offset = 0;
287 ni_log(NI_LOG_INFO, "Reading %llu bytes into memory\n", (unsigned long long)total_file_size);
288
289 while (file_size_left)
290 {
291 if (read_chunk > file_size_left)
292 {
293 read_chunk = file_size_left;
294 }
295 read_rc = fread(ctx->file_cache + ctx->curr_file_offset, read_chunk, 1, fp);
296 if (read_rc != 1)
297 {
298 ni_log(NI_LOG_ERROR, "Error: Failure when reading file, bytes left to read %llu\n",
299 file_size_left);
300 fclose(fp);
301 return -1;
302 } else
303 {
304 file_size_left -= read_chunk;
305 ctx->curr_file_offset += read_chunk;
306 }
307 }
308
309 ctx->curr_file_offset = 0;
310 fclose(fp);
311 return 0;
312}
313
314// reset input data buffer position to the start
316{
317 p_ctx->curr_file_offset = 0;
318}
319
320// rewind input data buffer position by a number of bytes, if possible
321void rewind_data_buf_pos_by(ni_demo_context_t *p_ctx, uint64_t nb_bytes)
322{
323 // curr_found_pos (current input parser offset) could be equal to nb_bytes (NAL size) when offset jumps back to 0 due to repeat option
324 if (p_ctx->curr_file_offset >= nb_bytes)
325 {
326 p_ctx->curr_file_offset -= nb_bytes;
327 } else
328 {
329 ni_log(NI_LOG_ERROR, "Error %s %d bytes!\n", __func__, nb_bytes);
330 }
331}
332
333// Note we do not need to consider padding bytes from yuv/rgba file reading
334int frame_read_buffer_size(int w, int h, ni_pix_fmt_t pix_fmt,
335 ni_sw_pix_fmt_t sw_pix_fmt)
336{
337 int data_len = 0;
338
339 if (sw_pix_fmt == NI_SW_PIX_FMT_YUV444P)
340 {
341 data_len = w * h * 3;
342 } else if (sw_pix_fmt == NI_SW_PIX_FMT_YUV444P10LE)
343 {
344 data_len = w * h * 6;
345 } else
346 {
347 switch (pix_fmt)
348 {
349 case NI_PIX_FMT_NV12:
351 data_len = w * h * 3 / 2;
352 break;
355 data_len = w * h * 3;
356 break;
357 case NI_PIX_FMT_RGBA:
358 case NI_PIX_FMT_BGRA:
359 case NI_PIX_FMT_ARGB:
360 case NI_PIX_FMT_ABGR:
361 case NI_PIX_FMT_BGR0:
362 case NI_PIX_FMT_BGRP:
363 data_len = w * 4 * h;
364 break;
365 default:
366 break;
367 }
368 }
369
370 return data_len;
371}
372
373// return actual bytes read from file, in requested size
375 uint8_t *p_dst, uint32_t to_read)
376{
377 uint64_t data_left_size = p_ctx->total_file_size - p_ctx->curr_file_offset;
378
379 ni_log(NI_LOG_DEBUG, "%s: p_dst %p len %u total size %llu current offset %llu\n",
380 __func__, p_dst, to_read, p_ctx->total_file_size, p_ctx->curr_file_offset);
381
382 if (data_left_size == 0)
383 {
384 if (p_ctx->loops_left > 1)
385 {
386 p_ctx->loops_left--;
387 ni_log(NI_LOG_DEBUG, "input processed %d left\n", p_ctx->loops_left);
388 fseek(fp, 0, SEEK_SET); //back to beginning
390 p_ctx->curr_file_offset = 0;
391 } else
392 {
393 return 0;
394 }
395 } else if (data_left_size < to_read)
396 {
397 to_read = (uint32_t)data_left_size;
398 }
399
400 size_t read_rc = fread(p_dst, to_read, 1, fp);
401 if (read_rc != 1)
402 {
403 ni_log(NI_LOG_ERROR, "Error: Failed to read input file, %lu bytes left to read\n",
405 return -1;
406 }
407 p_ctx->curr_file_offset += to_read;
408
409 return to_read;
410}
411
412int read_yuv_from_file(ni_demo_context_t *p_ctx, FILE *pfs, void *yuv_buf, int width, int height,
413 ni_pix_fmt_t pix_fmt, ni_sw_pix_fmt_t sw_pix_fmt,
414 int *eos, ni_session_run_state_t run_state)
415{
416 int chunk_size, frame_size;
417
419 {
420 // The first YUV frame was consumed on sequence change. Reset the file
421 // pointer until the end of encoded packet is read.
422 ni_log(NI_LOG_DEBUG, "read_yuv_from_file wait sequence change finish\n");
424 p_ctx->curr_file_offset = 0;
425 return 0;
426 }
427
428 frame_size = frame_read_buffer_size(width, height, pix_fmt, sw_pix_fmt);
429
430 chunk_size = read_next_chunk_from_file(p_ctx, pfs, yuv_buf, frame_size);
431 if (chunk_size < 0)
432 {
433 ni_log(NI_LOG_ERROR, "Error: could not read file!");
434 return -1;
435 } else if (chunk_size == 0)
436 {
437 *eos = 1;
438 ni_log(NI_LOG_DEBUG, "%s: read chunk size 0, eos!\n", __func__);
439 return 0;
440 } else
441 {
442 *eos = 0;
443 return chunk_size;
444 }
445}
446
448 void *yuv_buf, int width, int height,
449 ni_sw_pix_fmt_t sw_pix_fmt, int mode,
450 ni_codec_format_t codec_format)
451{
452 int i, factor;
453 uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS] = { NULL };
454 int dst_stride[NI_MAX_NUM_DATA_POINTERS] = { 0 };
455 int height_aligned[NI_MAX_NUM_DATA_POINTERS] = { 0 };
456
457 if (yuv_buf == NULL)
458 {
459 // EOS
460 return 0;
461 }
462
463 switch (sw_pix_fmt)
464 {
466 factor = 1;
467 break;
469 factor = 2;
470 break;
471 default:
472 ni_log(NI_LOG_ERROR, "Error: invalid sw pix fmt %d\n", sw_pix_fmt);
473 return -1;
474 }
475
476 ni_get_hw_yuv420p_dim(width, height, factor, 0, dst_stride, height_aligned);
477
478 for (i = 0; i < 2; i++)
479 {
480 ni_frame_t *frame = &p_frame[i].data.frame;
481 ni_encoder_frame_buffer_alloc(frame, width, height, dst_stride,
482 codec_format == NI_CODEC_FORMAT_H264,
484 if (frame->p_data[0] == NULL)
485 {
486 ni_log(NI_LOG_ERROR, "Error: could not allocate YUV frame buffer!\n");
487 return -1;
488 }
489 }
490
491 p_src[0] = yuv_buf;
492 p_src[1] = p_src[0] + width * factor * height;
493 p_src[2] = p_src[1] + width * factor * height;
494
495 ni_copy_yuv_444p_to_420p(p_frame[0].data.frame.p_data,
496 p_frame[1].data.frame.p_data,
497 p_src, width, height, factor, mode);
498
499 return 0;
500}
501
502/*!*****************************************************************************
503 * \brief Write hwdl data to files.
504 *
505 * \param
506 *
507 * \return 0 if successful, < 0 otherwise
508 ******************************************************************************/
509int write_rawvideo_data(FILE *p_file, int input_aligned_width, int input_aligned_height,
510 int output_width, int output_height, int format, ni_frame_t *p_out_frame)
511{
512 int i, j;
513 uint8_t *src;
514 int plane_width, plane_height, write_width, write_height, bit_depth_factor;
515
516 if (p_file && p_out_frame)
517 {
518 switch (format)
519 {
522 case NI_PIX_FMT_NV12:
524 {
525 for (i = 0; i < 3; i++)
526 {
527 src = p_out_frame->p_data[i];
528
529 plane_width = input_aligned_width;
530 plane_height = input_aligned_height;
531 write_width = output_width;
532 write_height = output_height;
533
534 // support for 8/10 bit depth
535 bit_depth_factor = 1;
536 if (format == NI_PIX_FMT_YUV420P10LE || format == NI_PIX_FMT_P010LE) {
537 bit_depth_factor = 2;
538 }
539 write_width *= bit_depth_factor;
540
541 if (i == 1 || i == 2)
542 {
543 plane_height /= 2;
544 // U/V stride size is multiple of 128, following the calculation
545 // in ni_decoder_frame_buffer_alloc
546 plane_width = ((output_width / 2 * bit_depth_factor + 127) / 128) * 128;
547
548 if (format == NI_PIX_FMT_NV12 || format == NI_PIX_FMT_P010LE)
549 {
550 plane_width = (((output_width * bit_depth_factor + 127) / 128) * 128);
551 // for semi-planar format, output UV at same time (data[1]) and skip data[2]
552 if (i == 1)
553 {
554 write_width *= 2;
555 }
556 if (i == 2)
557 {
558 plane_height = 0;
559 }
560 }
561
562 write_height /= 2;
563 write_width /= 2;
564 }
565
566 // apply the cropping window in writing out the YUV frame
567 // for now the window is usually crop-left = crop-top = 0, and we
568 // use this to simplify the cropping logic
569 for (j = 0; j < plane_height; j++)
570 {
571 if (j < write_height &&
572 fwrite(src, write_width, 1, p_file) != 1)
573 {
575 "Error: writing data plane %d: height %d error!\n",
576 i, plane_height);
577 ni_log(NI_LOG_ERROR, "Error: ferror rc = %d\n", ferror(p_file));
578 return NI_RETCODE_FAILURE;
579 }
580 src += plane_width;
581 }
582 }
583 break;
584 }
585 case NI_PIX_FMT_RGBA:
586 case NI_PIX_FMT_BGRA:
587 case NI_PIX_FMT_ARGB:
588 case NI_PIX_FMT_ABGR:
589 case NI_PIX_FMT_BGR0:
590 {
591 src = p_out_frame->p_data[0];
592 if (fwrite(src, output_width * output_height * 4, 1, p_file) != 1)
593 {
594 ni_log(NI_LOG_ERROR, "Error: ferror rc = %d\n", ferror(p_file));
595 return NI_RETCODE_FAILURE;
596 }
597 break;
598 }
599 case NI_PIX_FMT_BGRP:
600 {
601 for (i = 0; i < 3; i++)
602 {
603 src = p_out_frame->p_data[i];
604 if (fwrite(src, output_width * output_height, 1, p_file) != 1)
605 {
606 ni_log(NI_LOG_ERROR, "Error: ferror rc = %d\n", ferror(p_file));
607 return NI_RETCODE_FAILURE;
608 }
609 }
610 break;
611 }
612 default:
613 {
614 ni_log(NI_LOG_ERROR, "Unsupported format %d\n", format);
615 return NI_RETCODE_FAILURE;
616 }
617 }
618
619 if (fflush(p_file))
620 {
622 "Error: writing data frame flush failed! errno %d\n",
623 errno);
624 return NI_RETCODE_FAILURE;
625 }
626 }
627 return NI_RETCODE_SUCCESS;
628}
629
631
632// final scan clean up of ref counted HW frame pool, return number of recycled
633// HW frames.
635{
636 int i;
637 int recycled = 0;
638
639 for (i = 0; i < NI_MAX_DR_HWDESC_FRAME_INDEX; i++)
640 {
641 if (g_hwframe_pool[i].ref_cnt &&
642 g_hwframe_pool[i].surface.ui16FrameIdx)
643 {
644 ni_log(NI_LOG_DEBUG, "clean/recycle frame idx %u ref_cnt %d\n,",
645 g_hwframe_pool[i].surface.ui16FrameIdx,
646 g_hwframe_pool[i].ref_cnt);
647 ni_hwframe_buffer_recycle2(&g_hwframe_pool[i].surface);
648 g_hwframe_pool[i].ref_cnt = 0;
649 recycled++;
650 }
651 }
652
653 return recycled;
654}
655
656// reference HW frame
657void ni_hw_frame_ref(const niFrameSurface1_t *p_surface)
658{
659 uint16_t hwframe_index;
660
661 if (!p_surface)
662 {
663 return;
664 }
665
666 hwframe_index = p_surface->ui16FrameIdx;
667 g_hwframe_pool[hwframe_index].ref_cnt++;
668 if (1 == g_hwframe_pool[hwframe_index].ref_cnt)
669 {
670 memcpy(&g_hwframe_pool[hwframe_index].surface, p_surface,
671 sizeof(niFrameSurface1_t));
672 }
673 ni_log(NI_LOG_TRACE, "%s frame idx %u ref_cnt %d ..\n", __func__,
674 hwframe_index, g_hwframe_pool[hwframe_index].ref_cnt);
675}
676
677// unref HW frame
678void ni_hw_frame_unref(uint16_t hwframe_index)
679{
680 if (g_hwframe_pool[hwframe_index].ref_cnt > 0)
681 {
682 g_hwframe_pool[hwframe_index].ref_cnt--;
683 if (0 == g_hwframe_pool[hwframe_index].ref_cnt &&
684 g_hwframe_pool[hwframe_index].surface.ui16FrameIdx)
685 {
686 ni_log(NI_LOG_TRACE, "%s frame idx recycing frame idx %u\n", __func__,
687 g_hwframe_pool[hwframe_index].surface.ui16FrameIdx);
688
689 ni_hwframe_buffer_recycle2(&g_hwframe_pool[hwframe_index].surface);
690 }
691 ni_log(NI_LOG_TRACE, "%s frame idx %u ref_cnt now: %d\n", __func__,
692 hwframe_index, g_hwframe_pool[hwframe_index].ref_cnt);
693 } else
694 {
695 ni_log(NI_LOG_ERROR, "%s error frame idx %u ref_cnt %d <= 0\n",
696 __func__, hwframe_index,
697 g_hwframe_pool[hwframe_index].ref_cnt);
698 }
699}
700
701/*!*****************************************************************************
702 * \brief Download hw frames by HwDesc.
703 *
704 * \param
705 *
706 * \return number of bytes downloaded if successful, <= 0 if failed
707 ******************************************************************************/
709 ni_session_data_io_t *p_session_data, ni_frame_t *p_src_frame,
710 int output_format)
711{
712 niFrameSurface1_t *src_surf = (niFrameSurface1_t *)(p_src_frame->p_data[3]);
713 int ret = 0;
714
715 ret = ni_frame_buffer_alloc_dl(&(p_session_data->data.frame),
716 src_surf->ui16width, src_surf->ui16height,
717 output_format);
718
719 if (ret != NI_RETCODE_SUCCESS)
720 {
722 }
723
724 p_ctx->is_auto_dl = false;
725 ret = ni_device_session_hwdl(p_ctx, p_session_data, src_surf);
726 if (ret <= 0)
727 {
728 ni_frame_buffer_free(&p_session_data->data.frame);
729 return ret;
730 }
731 return ret;
732}
733
734/*!*****************************************************************************
735 * \brief Read from input file, upload to encoder, retrieve HW descriptor
736 *
737 * \param
738 *
739 * \return
740 ******************************************************************************/
742 ni_session_data_io_t *p_swin_data, //intermediate for swf
743 ni_session_data_io_t *p_in_data,
744 int input_video_width, int input_video_height,
745 void *yuv_buf)
746{
747 int retval, is_semiplanar;
748 ni_frame_t *p_in_frame = &p_in_data->data.frame; //hwframe
749 ni_frame_t *p_swin_frame = &p_swin_data->data.frame; //swframe
750 niFrameSurface1_t *dst_surf = NULL;
751
752 ni_log(NI_LOG_DEBUG, "===> upload_send_data <===\n");
753
754 p_in_frame->start_of_stream = 0;
755 p_in_frame->end_of_stream = yuv_buf == NULL;
756 p_in_frame->force_key_frame = 0;
757 p_in_frame->video_width = p_swin_frame->video_width = input_video_width;
758 p_in_frame->video_height = p_swin_frame->video_height = input_video_height;
759 // only metadata header for now
762
763 int dst_stride[NI_MAX_NUM_DATA_POINTERS] = {0};
764 int dst_height_aligned[NI_MAX_NUM_DATA_POINTERS] = {0};
766 input_video_width, input_video_height,
767 p_upl_ctx->pixel_format, dst_stride,
768 dst_height_aligned);
769 is_semiplanar = (
772 !is_semiplanar, p_swin_frame, input_video_width,
773 dst_height_aligned[0], dst_stride, 0,
774 (int)p_swin_frame->extra_data_len, false);
775 if (!p_swin_frame->p_data[0])
776 {
777 ni_log(NI_LOG_ERROR, "Error: could not allocate YUV frame buffer!");
778 return -1;
779 }
780
781 //can also be ni_frame_buffer_alloc()
782 ni_frame_buffer_alloc_hwenc(p_in_frame, input_video_width,
783 input_video_height,
784 (int)p_in_frame->extra_data_len);
785 if (!p_in_frame->p_data[3])
786 {
787 ni_log(NI_LOG_ERROR, "Error: could not allocate hw frame buffer!");
788 return -1;
789 }
790
791 dst_surf = (niFrameSurface1_t *)p_in_frame->p_data[3];
792
793 ni_log(NI_LOG_DEBUG, "p_dst alloc linesize = %d/%d/%d src height=%d "
794 "dst height aligned = %d/%d/%d\n",
795 dst_stride[0], dst_stride[1], dst_stride[2],
796 input_video_height, dst_height_aligned[0],
797 dst_height_aligned[1], dst_height_aligned[2]);
798
799 if (p_in_frame->end_of_stream)
800 {
801 goto hwupload;
802 }
803
804 uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS] = {NULL};
805 int src_stride[NI_MAX_NUM_DATA_POINTERS] = {0};
806 int src_height[NI_MAX_NUM_DATA_POINTERS] = {0};
807 src_height[0] = input_video_height;
808 src_height[1] = input_video_height / 2;
809 src_height[2] = (is_semiplanar) ? 0 : (input_video_height / 2);
810 uint32_t conf_win_right = 0;
811
812 switch (p_upl_ctx->pixel_format)
813 {
814 case NI_PIX_FMT_RGBA:
815 case NI_PIX_FMT_BGRA:
816 case NI_PIX_FMT_ABGR:
817 case NI_PIX_FMT_ARGB:
818 case NI_PIX_FMT_BGR0:
819 src_stride[0] = input_video_width * p_upl_ctx->bit_depth_factor;
820 src_height[0] = input_video_height;
821 src_height[1] = 0;
822 src_height[2] = 0;
823 p_src[0] = yuv_buf;
824 break;
825 case NI_PIX_FMT_NV12:
829 src_stride[0] = input_video_width * p_upl_ctx->bit_depth_factor;
830 src_stride[1] = is_semiplanar ? src_stride[0] : src_stride[0] / 2;
831 src_stride[2] = is_semiplanar ? 0 : src_stride[0] / 2;
832
833 p_src[0] = yuv_buf;
834 p_src[1] = p_src[0] + src_stride[0] * src_height[0];
835 p_src[2] = p_src[1] + src_stride[1] * src_height[1];
836 if (input_video_width < NI_MIN_WIDTH)
837 {
838 conf_win_right += (NI_MIN_WIDTH - input_video_width) / 2 * 2;
839 } else
840 {
841 conf_win_right += (NI_VPU_CEIL(input_video_width, 2) - input_video_width) / 2 * 2;
842 }
843 break;
844 default:
845 ni_log(NI_LOG_ERROR, "%s: Error Invalid pixel format %s\n", __func__,
847 return -1;
848 }
849
851 (uint8_t **)(p_swin_frame->p_data),
852 p_src, input_video_width,
853 input_video_height, p_upl_ctx->bit_depth_factor,
854 p_upl_ctx->pixel_format, conf_win_right, dst_stride,
855 dst_height_aligned, src_stride, src_height);
856
857hwupload:
858 retval = ni_device_session_hwup(p_upl_ctx, p_swin_data, dst_surf);
859 if (retval < 0)
860 {
861 ni_log(NI_LOG_ERROR, "Error: ni_device_session_hwup():%d, frameNum %u\n",
862 retval, p_ctx->num_frames_received);
863 return -1;
864 } else
865 {
866 p_ctx->dec_total_bytes_sent += p_swin_frame->data_len[0] + p_swin_frame->data_len[1] +
867 p_swin_frame->data_len[2] + p_swin_frame->data_len[3];
868 ni_log(NI_LOG_DEBUG, "upload_send_data: total sent data size=%lu\n",
869 p_ctx->dec_total_bytes_sent);
870
871 dst_surf->ui16width = input_video_width;
872 dst_surf->ui16height = input_video_height;
873 dst_surf->encoding_type = is_semiplanar ?
876
877 p_ctx->num_frames_received++;
878
879 ni_log(NI_LOG_DEBUG, "upload_send_data: FID = %d success, number:%u\n",
880 dst_surf->ui16FrameIdx, p_ctx->num_frames_received);
881 }
882
883 return 0;
884}
885
886/*!*****************************************************************************
887 * \brief Uploader session open
888 *
889 * \param
890 *
891 * \return 0 if successful, < 0 otherwise
892 ******************************************************************************/
893int uploader_open_session(ni_session_context_t *p_upl_ctx, int iXcoderGUID,
894 int width, int height, ni_pix_fmt_t pix_fmt,
895 int is_p2p, int pool_size)
896{
897 int ret = 0;
899
900 // assign the card GUID in the encoder context and let session open
901 // take care of the rest
902 p_upl_ctx->device_handle = NI_INVALID_DEVICE_HANDLE;
903 p_upl_ctx->blk_io_handle = NI_INVALID_DEVICE_HANDLE;
904 p_upl_ctx->hw_id = iXcoderGUID;
905
906 // Set the input frame format of the upload session
907 ret = ni_uploader_set_frame_format(p_upl_ctx, width, height, pix_fmt, is_p2p);
908 if(ret != NI_RETCODE_SUCCESS)
909 {
910 ni_log(NI_LOG_ERROR, "Error: %s failure. Failed to set uploader format!\n", __func__);
911 return ret;
912 }
913
915 if (ret != NI_RETCODE_SUCCESS)
916 {
917 ni_log(NI_LOG_ERROR, "Error: %s failure!\n", __func__);
918 return ret;
919 } else
920 {
921 ni_log(NI_LOG_INFO, "Uploader device %d session open successful.\n", iXcoderGUID);
922 }
923
924 ret = ni_device_session_init_framepool(p_upl_ctx, pool_size, 0);
925 if (ret < 0)
926 {
927 ni_log(NI_LOG_ERROR, "Error: %s failure!\n", __func__);
928 } else
929 {
930 ni_log(NI_LOG_INFO, "Uploader device %d configured successful.\n", iXcoderGUID);
931 }
932
933 return ret;
934}
935
937 ni_session_context_t *p_upl_ctx,
938 ni_session_context_t *p_sca_ctx,
939 ni_session_data_io_t *p_sw_data,
940 ni_session_data_io_t *p_hw_data,
941 ni_session_data_io_t *p_scale_data,
942 ni_pix_fmt_t pix_fmt, int width,
943 int height, FILE *pfs, void *yuv_buf, int *eos)
944{
945 int ret, chunk_size;
946 niFrameSurface1_t *p_hwframe = NULL;
947
948 chunk_size = read_yuv_from_file(p_ctx, pfs, yuv_buf, width, height, pix_fmt,
950 p_upl_ctx->session_run_state);
951 if (chunk_size < 0)
952 {
953 ni_log(NI_LOG_ERROR, "Error: read yuv file error\n");
954 return NULL;
955 }
956
957 // need to have the hwframe before open encoder
958 ret = upload_send_data_get_desc(p_ctx, p_upl_ctx, p_sw_data, p_hw_data, width,
959 height, *eos ? NULL : yuv_buf);
961 {
962 ni_log(NI_LOG_DEBUG, "No space to write to, try to read a packet\n");
963 //file was read so reset read pointer and try again
964 rewind_data_buf_pos_by(p_ctx, chunk_size);
965 fseek(pfs, (long)p_ctx->curr_file_offset, SEEK_SET);
966 return NULL;
967 } else if (ret)
968 {
969 ni_log(NI_LOG_ERROR, "Error: upload frame error\n");
970 return NULL;
971 }
972
973 p_hwframe = (niFrameSurface1_t *)p_hw_data->data.frame.p_data[3];
974 if (p_hw_data->data.frame.end_of_stream)
975 {
976 // reach eos
977 return p_hwframe;
978 }
979
980 // need to convert into pixel format for NI encoding
981 if (!is_ni_enc_pix_fmt(pix_fmt))
982 {
983 ni_hw_frame_ref(p_hwframe);
984 ret = scale_filter(p_sca_ctx, &p_hw_data->data.frame, p_scale_data,
985 p_upl_ctx->hw_id, width, height,
988 if (ret)
989 {
990 ni_log(NI_LOG_ERROR, "Error: upload frame error\n");
991 return NULL;
992 }
993 p_hwframe = (niFrameSurface1_t *)p_scale_data->data.frame.p_data[3];
994 }
995
996 return p_hwframe;
997}
#define NI_MAX_DR_HWDESC_FRAME_INDEX
Definition ni_defs.h:265
#define NI_MAX_FILTER_POOL_SIZE
Definition ni_defs.h:329
#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
#define NI_APP_ENC_FRAME_META_DATA_SIZE
Definition ni_defs.h:322
@ NI_DEVICE_TYPE_UPLOAD
Definition ni_defs.h:367
@ NI_RETCODE_FAILURE
Definition ni_defs.h:444
@ NI_RETCODE_NVME_SC_WRITE_BUFFER_FULL
Definition ni_defs.h:550
@ NI_RETCODE_SUCCESS
Definition ni_defs.h:443
@ NI_RETCODE_ERROR_MEM_ALOC
Definition ni_defs.h:447
ni_retcode_t ni_frame_buffer_alloc_dl(ni_frame_t *p_frame, int video_width, int video_height, int pixel_format)
Allocate preliminary memory for the frame buffer based on provided parameters.
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...
int ni_device_session_hwdl(ni_session_context_t *p_ctx, ni_session_data_io_t *p_data, niFrameSurface1_t *hwdesc)
Reads YUV data from hw descriptor stored location on device.
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...
int ni_device_session_hwup(ni_session_context_t *p_ctx, ni_session_data_io_t *p_src_data, niFrameSurface1_t *hwdesc)
Sends raw YUV input to uploader instance and retrieves a HW descriptor to represent it.
ni_retcode_t ni_hwframe_buffer_recycle2(niFrameSurface1_t *surface)
Recycle a frame buffer on card, only hwframe descriptor is needed.
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.
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_encoder_sw_frame_buffer_alloc(bool planar, ni_frame_t *p_frame, int video_width, int video_height, int linesize[], int alignment, int extra_len, bool alignment_2pass_wa)
This API is a wrapper for ni_encoder_frame_buffer_alloc(), used for planar pixel formats,...
ni_retcode_t ni_encoder_frame_buffer_alloc(ni_frame_t *p_frame, int video_width, int video_height, int linesize[], int alignment, int extra_len, bool alignment_2pass_wa)
Allocate memory for the frame buffer for encoding based on given parameters, taking into account pic ...
@ SESSION_RUN_STATE_SEQ_CHANGE_DRAINING
#define GC620_I420
#define GC620_NV16
#define NI_MIN_WIDTH
enum _ni_session_run_state ni_session_run_state_t
Session running state type.
@ NI_PIXEL_PLANAR_FORMAT_SEMIPLANAR
@ NI_PIXEL_PLANAR_FORMAT_TILED4X4
@ NI_PIXEL_PLANAR_FORMAT_PLANAR
#define GC620_UYVY
#define GC620_NV12
#define GC620_RGBA8888
#define GC620_YUYV
#define GC620_P010_MSB
#define NI_INVALID_SESSION_ID
enum _ni_codec_format ni_codec_format_t
This is an enumeration for supported codec formats.
@ NI_CODEC_FORMAT_H264
ni_pix_fmt_t
@ NI_PIX_FMT_ARGB
@ NI_PIX_FMT_P010LE
@ NI_PIX_FMT_YUV420P
@ NI_PIX_FMT_ABGR
@ NI_PIX_FMT_NONE
@ NI_PIX_FMT_10_TILED4X4
@ NI_PIX_FMT_BGRP
@ NI_PIX_FMT_BGR0
@ NI_PIX_FMT_YUYV422
@ NI_PIX_FMT_RGBA
@ NI_PIX_FMT_NV12
@ NI_PIX_FMT_8_TILED4X4
@ NI_PIX_FMT_BGRA
@ NI_PIX_FMT_NV16
@ NI_PIX_FMT_UYVY422
@ NI_PIX_FMT_YUV420P10LE
#define GC620_ABGR8888
#define GC620_ARGB8888
#define GC620_BGRX8888
#define GC620_RGB888_PLANAR
enum _ni_pixel_planar_format ni_pixel_planar_format
#define GC620_I010
#define GC620_BGRA8888
#define NI_VPU_CEIL(_data, _align)
int scale_filter(ni_session_context_t *p_ctx, ni_frame_t *p_frame_in, ni_session_data_io_t *p_data_out, int iXcoderGUID, int scale_width, int scale_height, int in_format, int out_format)
Do a scale and/or format-change operation.
ni_pix_fmt_t gc620_to_ni_pix_fmt(int pix_fmt)
bool uploader_frame_list_full(ni_test_frame_list_t *list, ni_pix_fmt_t pix_fmt)
const char * ni_pixel_format_name(ni_pix_fmt_t pix_fmt)
ni_pix_fmt_t ni_pixel_format_search(const char *name)
uint32_t read_next_chunk_from_file(ni_demo_context_t *p_ctx, FILE *fp, uint8_t *p_dst, uint32_t to_read)
int read_yuv_from_file(ni_demo_context_t *p_ctx, FILE *pfs, void *yuv_buf, int width, int height, ni_pix_fmt_t pix_fmt, ni_sw_pix_fmt_t sw_pix_fmt, int *eos, ni_session_run_state_t run_state)
int frame_list_length(ni_test_frame_list_t *list)
void ni_hw_frame_unref(uint16_t hwframe_index)
int is_ni_enc_pix_fmt(ni_pix_fmt_t pix_fmt)
niFrameSurface1_t * hwupload_frame(ni_demo_context_t *p_ctx, ni_session_context_t *p_upl_ctx, ni_session_context_t *p_sca_ctx, ni_session_data_io_t *p_sw_data, ni_session_data_io_t *p_hw_data, ni_session_data_io_t *p_scale_data, ni_pix_fmt_t pix_fmt, int width, int height, FILE *pfs, void *yuv_buf, int *eos)
int ni_to_gc620_pix_fmt(ni_pix_fmt_t pix_fmt)
uint64_t get_total_file_size(FILE *fp)
int upload_send_data_get_desc(ni_demo_context_t *p_ctx, ni_session_context_t *p_upl_ctx, ni_session_data_io_t *p_swin_data, ni_session_data_io_t *p_in_data, int input_video_width, int input_video_height, void *yuv_buf)
Read from input file, upload to encoder, retrieve HW descriptor.
ni_pixel_planar_format get_pixel_planar(ni_pix_fmt_t pix_fmt)
bool frame_list_is_empty(ni_test_frame_list_t *list)
bool frame_list_is_full(ni_test_frame_list_t *list)
void rewind_data_buf_pos_by(ni_demo_context_t *p_ctx, uint64_t nb_bytes)
int read_and_cache_file(ni_demo_context_t *ctx, char *filename)
int hwdl_frame(ni_session_context_t *p_ctx, ni_session_data_io_t *p_session_data, ni_frame_t *p_src_frame, int output_format)
Download hw frames by HwDesc.
int frame_list_drain(ni_test_frame_list_t *list)
void hwframe_list_release(ni_test_frame_list_t *list)
void print_version(void)
int scan_and_clean_hwdescriptors(void)
int frame_read_buffer_size(int w, int h, ni_pix_fmt_t pix_fmt, ni_sw_pix_fmt_t sw_pix_fmt)
int write_rawvideo_data(FILE *p_file, int input_aligned_width, int input_aligned_height, int output_width, int output_height, int format, ni_frame_t *p_out_frame)
Write hwdl data to files.
void reset_data_buf_pos(ni_demo_context_t *p_ctx)
int uploader_open_session(ni_session_context_t *p_upl_ctx, int iXcoderGUID, int width, int height, ni_pix_fmt_t pix_fmt, int is_p2p, int pool_size)
Uploader session open.
int frame_list_enqueue(ni_test_frame_list_t *list)
void ni_hw_frame_ref(const niFrameSurface1_t *p_surface)
int convert_yuv_444p_to_420p(ni_session_data_io_t *p_frame, void *yuv_buf, int width, int height, ni_sw_pix_fmt_t sw_pix_fmt, int mode, ni_codec_format_t codec_format)
#define NI_MAX_BUFFERED_FRAME
ni_sw_pix_fmt_t
@ NI_SW_PIX_FMT_NONE
@ NI_SW_PIX_FMT_YUV444P10LE
@ NI_SW_PIX_FMT_YUV444P
void ni_log(ni_log_level_t level, const char *fmt,...)
print log message using ni_log_callback
Definition ni_log.c:183
Logging definitions.
@ NI_LOG_DEBUG
Definition ni_log.h:64
@ NI_LOG_TRACE
Definition ni_log.h:65
@ NI_LOG_ERROR
Definition ni_log.h:62
@ NI_LOG_INFO
Definition ni_log.h:63
unsigned long total_file_size
uint64_t data_left_size
#define NI_SW_RELEASE_ID
#define NI_SW_RELEASE_TIME
void ni_copy_frame_data(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, ni_pix_fmt_t pix_fmt, 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 RGBA or YUV data to Netint HW frame layout to be sent to encoder for encoding....
Definition ni_util.c:3022
void ni_copy_yuv_444p_to_420p(uint8_t *p_dst0[NI_MAX_NUM_DATA_POINTERS], uint8_t *p_dst1[NI_MAX_NUM_DATA_POINTERS], uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS], int frame_width, int frame_height, int factor, int mode)
Copy yuv444p data to yuv420p frame layout to be sent to encoder for encoding. Data buffer (dst) is us...
Definition ni_util.c:3102
void ni_get_min_frame_dim(int width, int height, ni_pix_fmt_t pix_fmt, int plane_stride[NI_MAX_NUM_DATA_POINTERS], int plane_height[NI_MAX_NUM_DATA_POINTERS])
Get dimension information of frame to be sent to encoder for encoding. Caller usually retrieves this ...
Definition ni_util.c:2805
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:2664
ni_retcode_t ni_fopen(FILE **fp, const char *filename, const char *mode)
Definition ni_util.c:983
Utility definitions.
uint64_t dec_total_bytes_sent
uint32_t data_len[NI_MAX_NUM_DATA_POINTERS]
uint32_t start_of_stream
uint32_t end_of_stream
uint32_t video_width
uint8_t * p_data[NI_MAX_NUM_DATA_POINTERS]
unsigned int extra_data_len
uint32_t video_height
ni_pix_fmt_t pix_fmt_ni
ni_pix_fmt_t pix_fmt
ni_device_handle_t device_handle
ni_device_handle_t blk_io_handle
ni_session_run_state_t session_run_state
union _ni_session_data_io::@19 data
ni_session_data_io_t frames[NI_MAX_BUFFERED_FRAME]