libxcoder  3.5.1
ni_util_logan.h
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_util_logan.h
24 *
25 * \brief Exported utility routines definition
26 *
27 *******************************************************************************/
28 
29 #pragma once
30 
31 #ifdef _WIN32
32 #define _SC_PAGESIZE 8
33 #define sysconf(x) 4096
34 #endif
35 
36 #include "ni_device_api_logan.h"
37 #include "ni_log_logan.h"
38 
39 #ifdef __cplusplus
40 extern "C"
41 {
42 #endif
43 
44 #ifdef XCODER_LINUX_CUSTOM_DRIVER
45 #define NI_LOGAN_NVME_PREFIX "ninvme"
46 #define NI_LOGAN_NVME_PREFIX_SZ 6
47 #elif defined(XCODER_LINUX_VIRTIO_DRIVER_ENABLED)
48 #define NI_LOGAN_NVME_PREFIX "vd"
49 #define NI_LOGAN_NVME_PREFIX_SZ 2
50 #elif defined(__APPLE__)
51 #define NI_LOGAN_NVME_PREFIX "rdisk"
52 #define NI_LOGAN_NVME_PREFIX_SZ 4
53 #else
54 #define NI_LOGAN_NVME_PREFIX "nvme"
55 #define NI_LOGAN_NVME_PREFIX_SZ 4
56 #endif
57 
58 //#define XCODER_MAX_NUM_TS_TABLE 32
59 #define LOGAN_XCODER_FRAME_OFFSET_DIFF_THRES 100
60 //#define XCODER_MAX_ENC_PACKETS_PER_READ 16
61 #define LOGAN_XCODER_MAX_NUM_QUEUE_ENTRIES 6000
62 #define LOGAN_XCODER_MAX_NUM_TEMPORAL_LAYER 7
63 #define LOGAN_BUFFER_POOL_SZ_PER_CONTEXT 300
64 
65 // for _T400_ENC
66 #define LOGAN_XCODER_MIN_ENC_PIC_WIDTH 256
67 #define LOGAN_XCODER_MIN_ENC_PIC_HEIGHT 128
68 #define LOGAN_XCODER_MAX_ENC_PIC_WIDTH 8192
69 #define LOGAN_XCODER_MAX_ENC_PIC_HEIGHT 8192
70 
71 #define NI_LOGAN_DEC_FRAME_BUF_POOL_SIZE_INIT 20
72 #define NI_LOGAN_DEC_FRAME_BUF_POOL_SIZE_EXPAND 20
73 
74 #define NI_LOGAN_INPUT_DATA_BUF_CNT_INIT 30
75 
76 #define NI_LOGAN_VPU_FREQ 450 //450Mhz
77 
78 #define MAX_THREADS 1000
79 
80 #define NI_LOGAN_ODD2EVEN(X) ((X&1)&&(X>31))?(X+1):(X)
81 
82 #ifdef XCODER_SIM_ENABLED
83 extern int32_t sim_eos_flag;
84 #endif
85 
86 typedef struct _ni_logan_queue_t
87 {
88  char name[32];
89  uint32_t count;
92 
94 
96 {
98 
100 
101 typedef struct ni_task
102 {
103  void *(*run)(void *args); //process function
104  void *arg; //param
105  struct ni_task *next; //the next task of the queue
107 
108 typedef struct threadpool
109 {
110  ni_pthread_mutex_t pmutex; //mutex
111  ni_pthread_cond_t pcond; //cond
112  ni_task_t *first; //the first task of the queue
113  ni_task_t *last; //the last task of the queue
114  int counter; //current thread number of the pool
115  int idle; //current idle thread number of the pool
116  int max_threads; //The max thread number of the pool
117  int quit; //exit sign
119 
120 // memory buffer pool operations (one use is for decoder frame buffer pool)
121 
122 /*!******************************************************************************
123  * \brief get a free memory buffer from the pool
124  *
125  * \param
126  *
127  * \return
128  *******************************************************************************/
130 
131 /*!******************************************************************************
132  * \brief return a used memory buffer to the pool
133  *
134  * \param
135  *
136  * \return
137  *******************************************************************************/
139 
140 /*!******************************************************************************
141  * \brief allocate a memory buffer and place it in the pool
142  *
143  * \param
144  *
145  * \return
146  *******************************************************************************/
148 
149 // decoder frame buffer pool init & free
150 
151 /*!******************************************************************************
152  * \brief decoder frame buffer pool init & free
153  *
154  * \param
155  *
156  * \return
157  *******************************************************************************/
159  int32_t number_of_buffers,
160  int width,
161  int height,
162  int height_align,
163  int factor);
164 
165 /*!******************************************************************************
166  * \brief free decoder frame buffer pool
167  *
168  * \param
169  *
170  * \return
171  *******************************************************************************/
173 
174 // timestamp buffer pool operations
175 
176 /*!******************************************************************************
177  * \brief free buffer memory pool
178  *
179  * \param
180  *
181  * \return
182  *******************************************************************************/
184 
185 /*!******************************************************************************
186  * \brief Find NVMe name space block from device name
187  * If none is found, assume nvme multi-pathing is disabled and return /dev/nvmeXn1
188  *
189  * \param[in] p_dev Device name represented as c string. ex: "/dev/nvme0"
190  * \param[in] out_buf Output buffer to put NVMe name space block. Must be at least length 21
191  *
192  * \return On success returns NI_LOGAN_RETCODE_SUCCESS
193  * On failure returns NI_LOGAN_RETCODE_FAILURE
194  *******************************************************************************/
195 ni_logan_retcode_t ni_logan_find_blk_name(const char *p_dev, char *p_out_buf, int out_buf_len);
196 
197 /*!******************************************************************************
198  * \brief Initialize timestamp handling
199  *
200  * \param
201  *
202  * \return
203  *******************************************************************************/
205  ni_logan_timestamp_table_t **pp_table,
206  const char *name);
207 
208 /*!******************************************************************************
209  * \brief Clean up timestamp handling
210  *
211  * \param
212  *
213  * \return
214  *******************************************************************************/
216  ni_logan_queue_buffer_pool_t *p_buffer_pool);
217 
218 /*!******************************************************************************
219  * \brief Register timestamp in timestamp/frame offset table
220  *
221  * \param
222  *
223  * \return
224  *******************************************************************************/
227  int64_t timestamp,
228  uint64_t data_info);
229 
230 /*!******************************************************************************
231  * \brief Retrieve timestamp from table based on frame offset info
232  *
233  * \param
234  *
235  * \return
236  *******************************************************************************/
238  uint64_t frame_info,
239  int64_t *p_timestamp,
240  int32_t threshold,
241  int32_t print,
242  ni_logan_queue_buffer_pool_t *p_buffer_pool);
243 
244 /*!******************************************************************************
245  * \brief Retrieve timestamp from table based on frame offset info
246  *
247  * \param
248  *
249  * \return
250  *******************************************************************************/
252  uint64_t frame_offset,
253  int64_t *p_timestamp,
254  int32_t threshold,
255  ni_logan_queue_buffer_pool_t *p_buffer_pool);
256 
257 /*!******************************************************************************
258  * \brief Retrieve timestamp from table based on frame offset info with respect
259  * to threshold
260  *
261  * \param
262  *
263  * \return
264  *******************************************************************************/
266  uint64_t frame_info,
267  int64_t *p_timestamp,
268  int32_t threshold,
269  int32_t print,
270  ni_logan_queue_buffer_pool_t *p_buffer_pool);
271 
272 /*!******************************************************************************
273  * \brief Timestamp queue clean up
274  *
275  * \param
276  *
277  * \return
278  *******************************************************************************/
280  ni_logan_timestamp_table_t *dts_list,
281  ni_logan_queue_buffer_pool_t *p_buffer_pool);
282 
283 /*!******************************************************************************
284  * \brief Initialize xcoder queue
285  *
286  * \param
287  *
288  * \return
289  *******************************************************************************/
291  ni_logan_queue_t *p_queue,
292  const char *name);
293 
294 /*!******************************************************************************
295  * \brief Push into xcoder queue
296  *
297  * \param
298  *
299  * \return
300  *******************************************************************************/
302  ni_logan_queue_t *p_queue,
303  uint64_t frame_offset,
304  int64_t timestamp);
305 
306 /*!******************************************************************************
307  * \brief Pop from the xcoder queue
308  *
309  * \param
310  *
311  * \return
312  *******************************************************************************/
314  uint64_t frame_offset,
315  int64_t *p_timestamp,
316  int32_t threshold,
317  int32_t print,
318  ni_logan_queue_buffer_pool_t *p_buffer_pool);
319 
320 /*!******************************************************************************
321  * \brief Pop from the xcoder queue with respect to threshold
322  *
323  * \param
324  *
325  * \return
326  *******************************************************************************/
328  uint64_t frame_offset,
329  int64_t *p_timestamp,
330  int32_t threshold,
331  int32_t print,
332  ni_logan_queue_buffer_pool_t *p_buffer_pool);
333 
334 /*!******************************************************************************
335  * \brief Free xcoder queue
336  *
337  * \param
338  *
339  * \return
340  *******************************************************************************/
342 
343 /*!******************************************************************************
344  * \brief Print xcoder queue
345  *
346  * \param
347  *
348  * \return
349  *******************************************************************************/
351 
352 /*!******************************************************************************
353  * \brief Initialize a fifo buffer
354  *
355  * \param[in] number_of_buffers Total number of buffers in this fifo
356  * \param[in] size The size of every buffer
357  *
358  * \return On success return fifo pointer, On failure return NULL
359  *******************************************************************************/
360 ni_logan_fifo_buffer_t * ni_logan_fifo_initialize(uint32_t number_of_buffers,
361  uint32_t size);
362 
363 /*!******************************************************************************
364  * \brief Free a fifo
365  *
366  * \param[in] p_fifo The pointer of ni_logan_fifo_buffer_t
367  *
368  * \return
369  *******************************************************************************/
371 
372 /*!******************************************************************************
373  * \brief Check if a fifo is full
374  *
375  * \param[in] p_fifo The pointer of ni_logan_fifo_buffer_t
376  *
377  * \return 1 is full; 0 is not full
378  *******************************************************************************/
380 
381 /*!******************************************************************************
382  * \brief Check if a fifo is empty
383  *
384  * \param[in] p_fifo The pointer of ni_logan_fifo_buffer_t
385  *
386  * \return 1 is empty; 0 is not empty
387  *******************************************************************************/
389 
390 /*!******************************************************************************
391  * \brief Get free buffer to write in the fifo
392  *
393  * \param[in] p_fifo The pointer of ni_logan_fifo_buffer_t
394  *
395  * \return On success return the pointer of free buffer,
396  * On failure return NULL
397  *******************************************************************************/
399 
400 /*!******************************************************************************
401  * \brief Get first filled buffer to read in the fifo
402  *
403  * \param[in] p_fifo The pointer of ni_logan_fifo_buffer_t
404  *
405  * \return On success return the pointer of filled buffer in fifo,
406  * On failure return NULL
407  *******************************************************************************/
409 
410 /*!******************************************************************************
411  * \brief Push back the last read buffer to the fifo
412  *
413  * \param[in] p_fifo The pointer of ni_logan_fifo_buffer_t
414  *
415  * \return On success return 0,
416  * On failure return -1
417  *******************************************************************************/
419 
420 // Type conversion functions
421 /*!******************************************************************************
422  * \brief convert string to boolean
423  *
424  * \param
425  *
426  * \return
427  *******************************************************************************/
428 int32_t ni_logan_atobool(const char *p_str, bool *b_error);
429 
430 /*!******************************************************************************
431  * \brief convert string to integer
432  *
433  * \param
434  *
435  * \return
436  *******************************************************************************/
437 int32_t ni_logan_atoi(const char *p_str, bool *b_error);
438 
439 /*!******************************************************************************
440  * \brief convert string to float
441  *
442  * \param
443  *
444  * \return
445  *******************************************************************************/
446 double ni_logan_atof(const char *p_str, bool *b_error);
447 
448 /*!******************************************************************************
449  * \brief string parser
450  *
451  * \param
452  *
453  * \return
454  *******************************************************************************/
455 int32_t ni_logan_parse_name(const char *arg, const char *const *names, bool *b_error);
456 
457 /*!*****************************************************************************
458  * \brief Init the threadpool
459  *
460  * \param[in] pool threadpool address
461  *
462  * \return NULL
463  *
464  *
465  ******************************************************************************/
466 void threadpool_init(threadpool_t *pool);
467 
468 
469 /*!*****************************************************************************
470  * \brief add task to threadpool
471  *
472  * \param[in] pool threadpool address
473  * \param[in] run run function
474  * \param[in] arg run function params
475  *
476  * \return 0 success
477  * <0 failed
478  *
479  ******************************************************************************/
480 int threadpool_add_task(threadpool_t *pool, void *(*run)(void *arg), void *arg);
481 
482 
483 /*!*****************************************************************************
484  * \brief add task to threadpool using newThread control it
485  *
486  * \param[in] pool threadpool address
487  * \param[in] run run function
488  * \param[in] arg run function params
489  * \param[in] newThread 1: create a new thread.
490  * 0: do not create a new thread.
491  *
492  * \return 0 success
493  * <0 failed
494  *
495  *
496  ******************************************************************************/
498  void *(*run)(void *arg),
499  void *arg,
500  int newThread);
501 
502 
503 /*!*****************************************************************************
504  * \brief destroy threadpool
505  *
506  * \param[in] pool threadpool address
507  *
508  * \return NULL
509  *
510  *
511  ******************************************************************************/
512 void threadpool_destroy(threadpool_t *pool);
513 
514 
515 /*!*****************************************************************************
516  * \brief threadpool control
517  *
518  * \param[in] params
519  *
520  * \return NULL
521  *
522  *
523  ******************************************************************************/
524 void *thread_routine(void *arg);
525 
526 // Netint HW YUV420p data layout related utility functions
527 
528 /*!*****************************************************************************
529  * \brief Get dimension information of Netint HW YUV420p frame to be sent
530  * to encoder for encoding. Caller usually retrieves this info and
531  * uses it in the call to ni_logan_encoder_frame_buffer_alloc for buffer
532  * allocation.
533  *
534  * \param[in] width source YUV frame width
535  * \param[in] height source YUV frame height
536  * \param[in] bit_depth_factor 1 for 8 bit, 2 for 10 bit
537  * \param[in] is_h264 non-0 for H.264 codec, 0 otherwise (H.265)
538  * \param[out] plane_stride size (in bytes) of each plane width
539  * \param[out] plane_height size of each plane height
540  *
541  * \return Y/Cb/Cr stride and height info
542  *
543  ******************************************************************************/
544 LIB_API void ni_logan_get_hw_yuv420p_dim(int width, int height, int bit_depth_factor,
545  int is_h264,
546  int plane_stride[NI_LOGAN_MAX_NUM_DATA_POINTERS],
547  int plane_height[NI_LOGAN_MAX_NUM_DATA_POINTERS]);
548 
549 
550 /*!*****************************************************************************
551  * \brief Copy YUV data to Netint HW YUV420p frame layout to be sent
552  * to encoder for encoding. Data buffer (dst) is usually allocated by
553  * ni_logan_encoder_frame_buffer_alloc.
554  *
555  * \param[out] p_dst pointers of Y/Cb/Cr to which data is copied
556  * \param[in] p_src pointers of Y/Cb/Cr from which data is copied
557  * \param[in] width source YUV frame width
558  * \param[in] height source YUV frame height
559  * \param[in] bit_depth_factor 1 for 8 bit, 2 for 10 bit
560  * \param[in] dst_stride size (in bytes) of each plane width in destination
561  * \param[in] dst_height size of each plane height in destination
562  * \param[in] src_stride size (in bytes) of each plane width in source
563  * \param[in] src_height size of each plane height in source
564  *
565  * \return Y/Cb/Cr data
566  *
567  ******************************************************************************/
568 LIB_API void ni_logan_copy_hw_yuv420p(uint8_t *p_dst[NI_LOGAN_MAX_NUM_DATA_POINTERS],
569  uint8_t *p_src[NI_LOGAN_MAX_NUM_DATA_POINTERS],
570  int width, int height, int bit_depth_factor,
571  int dst_stride[NI_LOGAN_MAX_NUM_DATA_POINTERS],
572  int dst_height[NI_LOGAN_MAX_NUM_DATA_POINTERS],
573  int src_stride[NI_LOGAN_MAX_NUM_DATA_POINTERS],
574  int src_height[NI_LOGAN_MAX_NUM_DATA_POINTERS]);
575 
576 
577 // NAL operations
578 
579 /*!*****************************************************************************
580  * \brief Insert emulation prevention byte(s) as needed into the data buffer
581  *
582  * \param buf data buffer to be worked on - new byte(s) will be inserted
583  * size number of bytes starting from buf to check
584  *
585  * \return the number of emulation prevention bytes inserted into buf, 0 if
586  * none.
587  *
588  * Note: caller *MUST* ensure for newly inserted bytes, buf has enough free
589  * space starting from buf + size
590  ******************************************************************************/
591 LIB_API int ni_logan_insert_emulation_prevent_bytes(uint8_t *buf, int size);
592 
593 /*!*****************************************************************************
594  * \brief Remove emulation prevention byte(s) as needed from the data buffer
595  *
596  * \param buf data buffer to be worked on - emu prevent byte(s) will be
597  * removed from.
598  * size number of bytes starting from buf to check
599  *
600  * \return the number of emulation prevention bytes removed from buf, 0 if
601  * none.
602  *
603  * Note: buf will be modified if emu prevent byte(s) found and removed.
604  ******************************************************************************/
605 LIB_API int ni_logan_remove_emulation_prevent_bytes(uint8_t *buf, int size);
606 
607 /*!******************************************************************************
608  * \brief overwrite the 32 bits of integer value at bit position pos
609  *
610  * \param buf data buffer to be worked on
611  * pos the position to be modified
612  * value The value that needs to be modified to
613  *
614  * \return void
615  *
616  * Note: caller *MUST* ensure that the pos and value won't go beyond the memory
617  * boundary of data. otherwise memory corruption would occur.
618  ******************************************************************************/
619 LIB_API void ni_logan_overwrite_specified_pos(uint8_t *buf, int pos, int value);
620 
621 #ifdef MEASURE_LATENCY
622 // NI latency measurement queue operations
623 ni_logan_lat_meas_q_t * ni_logan_lat_meas_q_create(unsigned capacity);
624 
625 void * ni_logan_lat_meas_q_add_entry(ni_logan_lat_meas_q_t *dec_frame_time_q,
626  uint64_t abs_time,
627  int64_t ts_time);
628 
629 uint64_t ni_logan_lat_meas_q_check_latency(ni_logan_lat_meas_q_t *dec_frame_time_q,
630  uint64_t abs_time,
631  int64_t ts_time);
632 
633 #endif
634 
635 LIB_API uint64_t ni_logan_gettime_ns(void);
636 LIB_API void ni_logan_usleep(int64_t usec);
637 LIB_API int32_t ni_logan_gettimeofday(struct timeval* p_tp, void *p_tzp);
638 int32_t ni_logan_posix_memalign(void **pp_memptr, size_t alignment, size_t size);
639 uint32_t ni_logan_round_up(uint32_t number_to_round, uint32_t multiple);
640 
641 #define ni_logan_aligned_free(p_memptr) \
642 { \
643  free(p_memptr); \
644  p_memptr = NULL; \
645 }
646 
647 #if defined(__linux__) || defined(__APPLE__)
648 uint32_t ni_logan_get_kernel_max_io_size(const char * p_dev);
649 #endif
650 
651 /*!******************************************************************************
652  * \brief initialize a mutex
653  *
654  * \param
655  *
656  * \return On success returns 0
657  * On failure returns <0
658  *******************************************************************************/
659 static inline int ni_logan_pthread_mutex_init(ni_pthread_mutex_t *mutex)
660 {
661 #ifdef _WIN32
662  InitializeCriticalSection(mutex);
663  return 0;
664 #else
665  int rc;
666  ni_pthread_mutexattr_t attr;
667 
668  rc = pthread_mutexattr_init(&attr);
669  if (rc != 0)
670  {
671  return -1;
672  }
673 
674  /* For some cases to prevent the lock owner locking twice (i.e. internal
675  * API calls or if user application decides to lock the xcoder_mutex outside
676  * of API), The recursive mutex is a nice thing to solve the problem.
677  */
678  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
679 
680  return pthread_mutex_init(mutex, &attr);
681 #endif
682 }
683 
684 /*!******************************************************************************
685  * \brief destory a mutex
686  *
687  * \param
688  *
689  * \return On success returns 0
690  * On failure returns <0
691  *******************************************************************************/
692 static inline int ni_logan_pthread_mutex_destroy(ni_pthread_mutex_t *mutex)
693 {
694 #ifdef _WIN32
695  DeleteCriticalSection(mutex);
696  return 0;
697 #else
698  return pthread_mutex_destroy(mutex);
699 #endif
700 }
701 
702 /*!******************************************************************************
703  * \brief thread mutex alloc&init
704  *
705  * \param
706  *
707  * \return On success returns true
708  * On failure returns false
709  *******************************************************************************/
710 static bool ni_logan_pthread_mutex_alloc_and_init(ni_pthread_mutex_t **mutex)
711 {
712  int rc = 0;
713  *mutex = (ni_pthread_mutex_t *)calloc(1, sizeof(ni_pthread_mutex_t));
714  if (!(*mutex))
715  {
716  return false;
717  }
718 
719  rc = ni_logan_pthread_mutex_init(*mutex);
720  if (rc != 0)
721  {
722  free(*mutex);
723  return false;
724  }
725 
726  return true;
727 }
728 
729 /*!******************************************************************************
730  * \brief thread mutex free&destroy
731  *
732  * \param
733  *
734  * \return On success returns true
735  * On failure returns false
736  *******************************************************************************/
737 static bool ni_logan_pthread_mutex_free_and_destroy(ni_pthread_mutex_t **mutex)
738 {
739  int rc = 0;
740  void *p;
741  static void *const tmp = NULL;
742 
743  // Avoid static analyzer inspection
744  memcpy(&p, mutex, sizeof(p));
745  if (p != NULL)
746  {
747  rc = ni_logan_pthread_mutex_destroy((ni_pthread_mutex_t *)p);
748  memcpy(mutex, &tmp, sizeof(p));
749  free(p);
750  } else
751  {
752  rc = -1;
753  }
754 
755  return rc == 0;
756 }
757 
758 /*!******************************************************************************
759  * \brief thread mutex lock
760  *
761  * \param
762  *
763  * \return On success returns 0
764  * On failure returns <0
765  *******************************************************************************/
766 static inline int ni_logan_pthread_mutex_lock(ni_pthread_mutex_t *mutex)
767 {
768  int rc = 0;
769  if (mutex != NULL)
770  {
771 #ifdef _WIN32
772  EnterCriticalSection(mutex);
773 #else
774  rc = pthread_mutex_lock(mutex);
775 #endif
776  } else
777  {
778  rc = -1;
779  }
780 
781  return rc;
782 }
783 
784 /*!******************************************************************************
785  * \brief thread mutex unlock
786  *
787  * \param
788  *
789  * \return On success returns 0
790  * On failure returns <0
791  *******************************************************************************/
792 static inline int ni_logan_pthread_mutex_unlock(ni_pthread_mutex_t *mutex)
793 {
794  int rc = 0;
795  if (mutex != NULL)
796  {
797 #ifdef _WIN32
798  LeaveCriticalSection(mutex);
799 #else
800  rc = pthread_mutex_unlock(mutex);
801 #endif
802  } else
803  {
804  rc = -1;
805  }
806 
807  return rc;
808 }
809 
810 #ifdef _WIN32
811 static unsigned __stdcall __thread_worker(void *arg)
812 {
813  ni_pthread_t *t = (ni_pthread_t *)arg;
814  t->rc = t->start_routine(t->arg);
815  return 0;
816 }
817 #endif
818 
819 /*!******************************************************************************
820  * \brief create a new thread
821  *
822  * \param
823  *
824  * \return On success returns 0
825  * On failure returns <0
826  *******************************************************************************/
827 static int ni_logan_pthread_create(ni_pthread_t *thread,
828  const ni_pthread_attr_t *attr,
829  void *(*start_routine)(void *), void *arg)
830 {
831 #ifdef _WIN32
832  thread->start_routine = start_routine;
833  thread->arg = arg;
834  thread->handle =
835 #if HAVE_WINRT
836  (void *)CreateThread(NULL, 0, __thread_worker, thread, 0, NULL);
837 #else
838  (void *)_beginthreadex(NULL, 0, __thread_worker, thread, 0, NULL);
839 #endif
840  return !thread->handle;
841 #else
842  return pthread_create(thread, attr, start_routine, arg);
843 #endif
844 }
845 
846 /*!******************************************************************************
847  * \brief join with a terminated thread
848  *
849  * \param
850  *
851  * \return On success returns 0
852  * On failure returns <0
853  *******************************************************************************/
854 static int ni_logan_pthread_join(ni_pthread_t thread, void **value_ptr)
855 {
856 #ifdef _WIN32
857  DWORD rc = WaitForSingleObject(thread.handle, INFINITE);
858  if (rc != WAIT_OBJECT_0)
859  {
860  if (rc == WAIT_ABANDONED)
861  return EINVAL;
862  else
863  return EDEADLK;
864  }
865  if (value_ptr)
866  *value_ptr = thread.rc;
867  CloseHandle(thread.handle);
868  return 0;
869 #else
870  return pthread_join(thread, value_ptr);
871 #endif
872 }
873 
874 /*!******************************************************************************
875  * \brief initialize condition variables
876  *
877  * \param
878  *
879  * \return On success returns 0
880  * On failure returns <0
881  *******************************************************************************/
882 static inline int ni_logan_pthread_cond_init(ni_pthread_cond_t *cond,
883  const ni_pthread_condattr_t *attr)
884 {
885 #ifdef _WIN32
886  InitializeConditionVariable(cond);
887  return 0;
888 #else
889  return pthread_cond_init(cond, attr);
890 #endif
891 }
892 
893 /*!******************************************************************************
894  * \brief destroy condition variables
895  *
896  * \param
897  *
898  * \return On success returns 0
899  * On failure returns <0
900  *******************************************************************************/
901 static inline int ni_logan_pthread_cond_destroy(ni_pthread_cond_t *cond)
902 {
903 #ifdef _WIN32
904  /* native condition variables do not destroy */
905  return 0;
906 #else
907  return pthread_cond_destroy(cond);
908 #endif
909 }
910 
911 /*!******************************************************************************
912  * \brief broadcast a condition
913  *
914  * \param
915  *
916  * \return On success returns 0
917  * On failure returns <0
918  *******************************************************************************/
919 static inline int ni_logan_pthread_cond_broadcast(ni_pthread_cond_t *cond)
920 {
921 #ifdef _WIN32
922  WakeAllConditionVariable(cond);
923  return 0;
924 #else
925  return pthread_cond_broadcast(cond);
926 #endif
927 }
928 
929 /*!******************************************************************************
930  * \brief wait on a condition
931  *
932  * \param
933  *
934  * \return On success returns 0
935  * On failure returns <0
936  *******************************************************************************/
937 static inline int ni_logan_pthread_cond_wait(ni_pthread_cond_t *cond,
938  ni_pthread_mutex_t *mutex)
939 {
940 #ifdef _WIN32
941  SleepConditionVariableCS(cond, mutex, INFINITE);
942  return 0;
943 #else
944  return pthread_cond_wait(cond, mutex);
945 #endif
946 }
947 
948 /*!******************************************************************************
949  * \brief signal a condition
950  *
951  * \param
952  *
953  * \return On success returns 0
954  * On failure returns <0
955  *******************************************************************************/
956 static inline int ni_logan_pthread_cond_signal(ni_pthread_cond_t *cond)
957 {
958 #ifdef _WIN32
959  WakeConditionVariable(cond);
960  return 0;
961 #else
962  return pthread_cond_signal(cond);
963 #endif
964 }
965 
966 /*!******************************************************************************
967  * \brief wait on a condition
968  *
969  * \param
970  *
971  * \return On success returns 0
972  * On failure returns <0
973  *******************************************************************************/
974 static int ni_logan_pthread_cond_timedwait(ni_pthread_cond_t *cond,
975  ni_pthread_mutex_t *mutex,
976  const struct timespec *abstime)
977 {
978 #ifdef _WIN32
979  int64_t abs_ns = abstime->tv_sec * 1000000000LL + abstime->tv_nsec;
980  DWORD t = (uint32_t)((abs_ns - ni_logan_gettime_ns()) / 1000000);
981 
982  if (!SleepConditionVariableCS(cond, mutex, t))
983  {
984  DWORD err = GetLastError();
985  if (err == ERROR_TIMEOUT)
986  return ETIMEDOUT;
987  else
988  return EINVAL;
989  }
990  return 0;
991 #else
992  return pthread_cond_timedwait(cond, mutex, abstime);
993 #endif
994 }
995 
996 /*!******************************************************************************
997  * \brief examine and change mask of blocked signals
998  *
999  * \param
1000  *
1001  * \return On success returns 0
1002  * On failure returns <0
1003  *******************************************************************************/
1004 static inline int ni_logan_pthread_sigmask(int how, const ni_sigset_t *set,
1005  ni_sigset_t *oldset)
1006 {
1007 #ifdef _WIN32
1008  return 0;
1009 #else
1010  return pthread_sigmask(how, set, oldset);
1011 #endif
1012 }
1013 
1014 #ifdef __cplusplus
1015 }
1016 #endif
ni_logan_retcode_t
#define NI_LOGAN_MAX_NUM_DATA_POINTERS
Main NETINT device API header file provides the ability to communicate with NI T-408 type hardware tr...
Exported logging routines definition.
ni_logan_retcode_t ni_logan_queue_push(ni_logan_queue_buffer_pool_t *p_buffer_pool, ni_logan_queue_t *p_queue, uint64_t frame_offset, int64_t timestamp)
Push into xcoder queue.
LIB_API int32_t ni_logan_gettimeofday(struct timeval *p_tp, void *p_tzp)
Definition: ni_util_logan.c:56
ni_logan_buf_t * ni_logan_buf_pool_allocate_buffer(ni_logan_buf_pool_t *p_buffer_pool, int buffer_size)
allocate a memory buffer and place it in the pool
uint8_t * ni_logan_fifo_generic_read(ni_logan_fifo_buffer_t *p_fifo)
Get first filled buffer to read in the fifo.
uint32_t ni_logan_round_up(uint32_t number_to_round, uint32_t multiple)
ni_logan_retcode_t ni_logan_timestamp_get(ni_logan_timestamp_table_t *p_table, uint64_t frame_info, int64_t *p_timestamp, int32_t threshold, int32_t print, ni_logan_queue_buffer_pool_t *p_buffer_pool)
Retrieve timestamp from table based on frame offset info.
uint8_t * ni_logan_fifo_generic_write(ni_logan_fifo_buffer_t *p_fifo)
Get free buffer to write in the fifo.
int threadpool_auto_add_task_thread(threadpool_t *pool, void *(*run)(void *arg), void *arg, int newThread)
add task to threadpool using newThread control it
LIB_API void ni_logan_overwrite_specified_pos(uint8_t *buf, int pos, int value)
overwrite the 32 bits of integer value at bit position pos
void ni_logan_timestamp_scan_cleanup(ni_logan_timestamp_table_t *pts_list, ni_logan_timestamp_table_t *dts_list, ni_logan_queue_buffer_pool_t *p_buffer_pool)
Timestamp queue clean up.
int32_t ni_logan_dec_fme_buffer_pool_initialize(ni_logan_session_context_t *p_ctx, int32_t number_of_buffers, int width, int height, int height_align, int factor)
decoder frame buffer pool init & free
int32_t ni_logan_posix_memalign(void **pp_memptr, size_t alignment, size_t size)
ni_logan_retcode_t ni_logan_queue_free(ni_logan_queue_t *p_queue, ni_logan_queue_buffer_pool_t *p_buffer_pool)
Free xcoder queue.
int32_t ni_logan_atobool(const char *p_str, bool *b_error)
convert string to boolean
ni_logan_retcode_t ni_logan_queue_pop(ni_logan_queue_t *p_queue, uint64_t frame_offset, int64_t *p_timestamp, int32_t threshold, int32_t print, ni_logan_queue_buffer_pool_t *p_buffer_pool)
Pop from the xcoder queue.
ni_logan_retcode_t ni_logan_find_blk_name(const char *p_dev, char *p_out_buf, int out_buf_len)
Find NVMe name space block from device name If none is found, assume nvme multi-pathing is disabled a...
LIB_API void ni_logan_usleep(int64_t usec)
LIB_API uint64_t ni_logan_gettime_ns(void)
Definition: ni_util_logan.c:81
int ni_logan_fifo_return_read(ni_logan_fifo_buffer_t *p_fifo)
Push back the last read buffer to the fifo.
void ni_logan_buffer_pool_free(ni_logan_queue_buffer_pool_t *p_buffer_pool)
free buffer memory pool
int32_t ni_logan_parse_name(const char *arg, const char *const *names, bool *b_error)
string parser
ni_logan_retcode_t ni_logan_timestamp_done(ni_logan_timestamp_table_t *p_table, ni_logan_queue_buffer_pool_t *p_buffer_pool)
Clean up timestamp handling.
int ni_logan_fifo_is_empty(ni_logan_fifo_buffer_t *p_fifo)
Check if a fifo is empty.
ni_logan_retcode_t ni_logan_timestamp_register(ni_logan_queue_buffer_pool_t *p_buffer_pool, ni_logan_timestamp_table_t *p_table, int64_t timestamp, uint64_t data_info)
Register timestamp in timestamp/frame offset table.
ni_logan_retcode_t ni_logan_timestamp_init(ni_logan_session_context_t *p_ctx, ni_logan_timestamp_table_t **pp_table, const char *name)
Initialize timestamp handling.
LIB_API 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 width, int 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....
int ni_logan_fifo_is_full(ni_logan_fifo_buffer_t *p_fifo)
Check if a fifo is full.
struct _ni_logan_queue_t ni_logan_queue_t
void ni_logan_buf_pool_return_buffer(ni_logan_buf_t *buf, ni_logan_buf_pool_t *p_buffer_pool)
return a used memory buffer to the pool
ni_logan_retcode_t ni_logan_queue_print(ni_logan_queue_t *p_queue)
Print xcoder queue.
void ni_logan_dec_fme_buffer_pool_free(ni_logan_buf_pool_t *p_buffer_pool)
free decoder frame buffer pool
ni_logan_retcode_t ni_logan_queue_pop_threshold(ni_logan_queue_t *p_queue, uint64_t frame_offset, int64_t *p_timestamp, int32_t threshold, int32_t print, ni_logan_queue_buffer_pool_t *p_buffer_pool)
Pop from the xcoder queue with respect to threshold.
int32_t ni_logan_atoi(const char *p_str, bool *b_error)
convert string to integer
LIB_API int ni_logan_insert_emulation_prevent_bytes(uint8_t *buf, int size)
Insert emulation prevention byte(s) as needed into the data buffer.
LIB_API int ni_logan_remove_emulation_prevent_bytes(uint8_t *buf, int size)
Remove emulation prevention byte(s) as needed from the data buffer.
ni_logan_fifo_buffer_t * ni_logan_fifo_initialize(uint32_t number_of_buffers, uint32_t size)
Initialize a fifo buffer.
struct threadpool threadpool_t
struct ni_task ni_task_t
ni_logan_retcode_t ni_logan_queue_init(ni_logan_session_context_t *p_ctx, ni_logan_queue_t *p_queue, const char *name)
Initialize xcoder queue.
void ni_logan_fifo_free(ni_logan_fifo_buffer_t *p_fifo)
Free a fifo.
void threadpool_destroy(threadpool_t *pool)
destroy threadpool
void * thread_routine(void *arg)
threadpool control
ni_logan_buf_t * ni_logan_buf_pool_get_buffer(ni_logan_buf_pool_t *p_buffer_pool)
get a free memory buffer from the pool
ni_logan_retcode_t ni_logan_timestamp_get_v2(ni_logan_timestamp_table_t *p_table, uint64_t frame_offset, int64_t *p_timestamp, int32_t threshold, ni_logan_queue_buffer_pool_t *p_buffer_pool)
Retrieve timestamp from table based on frame offset info.
LIB_API 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....
void threadpool_init(threadpool_t *pool)
Init the threadpool.
struct _ni_logan_timestamp_table_t ni_logan_timestamp_table_t
double ni_logan_atof(const char *p_str, bool *b_error)
convert string to float
int threadpool_add_task(threadpool_t *pool, void *(*run)(void *arg), void *arg)
add task to threadpool
ni_logan_retcode_t ni_logan_timestamp_get_with_threshold(ni_logan_timestamp_table_t *p_table, uint64_t frame_info, int64_t *p_timestamp, int32_t threshold, int32_t print, ni_logan_queue_buffer_pool_t *p_buffer_pool)
Retrieve timestamp from table based on frame offset info with respect to threshold.
ni_logan_queue_node_t * p_last
Definition: ni_util_logan.h:91
ni_logan_queue_node_t * p_first
Definition: ni_util_logan.h:90
void * arg
struct ni_task * next
ni_pthread_cond_t pcond
ni_pthread_mutex_t pmutex
ni_task_t * last
ni_task_t * first