libxcoder 5.6.0
Loading...
Searching...
No Matches
ni_lat_meas.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_lat_meas.c
24 *
25 * \brief Utility definitions for measuring frame/packet processing time in
26 * NETINT video processing devices
27 ******************************************************************************/
28
29#ifdef __linux__
30#include <sys/ioctl.h>
31#include <sys/stat.h>
32#include <sys/ioctl.h>
33#include <sys/mman.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <fcntl.h>
37#include <unistd.h>
38#endif
39
40#include "ni_lat_meas.h"
41#include "ni_log.h"
42#include "ni_util.h"
43
44/*!*****************************************************************************
45 * \brief Create a latency measurement queue object of a given capacity
46 *
47 * \param capacity maximum size of queue
48 *
49 * \return ni_lat_meas_q_t latency measurement queue structure
50 *
51 ******************************************************************************/
53{
54 if (1 > capacity)
55 {
57 "ERROR: ni_lat_meas_q_create() called with capacity less than 1"
58 "\n");
59 return NULL;
60 }
61
62 ni_lat_meas_q_t *queue = (ni_lat_meas_q_t *)malloc(sizeof(ni_lat_meas_q_t));
63 if (!queue)
64 {
66 "ERROR %d: Failed to allocate memory for "
67 "lat_meas-queue queue\n",
68 NI_ERRNO);
69 return NULL;
70 }
71 queue->capacity = capacity;
72 queue->front = queue->size = 0;
73 queue->rear = capacity - 1;
75 queue->array = (ni_lat_meas_q_entry_t *)malloc(
76 queue->capacity * sizeof(ni_lat_meas_q_entry_t));
77 if (!queue->array)
78 {
80 "ERROR %d: Failed to allocate memory for "
81 "lat_meas_queue queue->array\n",
82 NI_ERRNO);
83 free(queue);
84 return NULL;
85 }
86 return queue;
87}
88
89/*!*****************************************************************************
90 * \brief Destroy a latency measurement queue object
91 *
92 * \param frame_time_q pointer to ni_lat_meas_q_t object
93 *
94 * \return
95 *
96 ******************************************************************************/
98{
99 free(frame_time_q->array);
100 free(frame_time_q);
101}
102
103/*!*****************************************************************************
104 * \brief Push an item onto the queue
105 *
106 * \param queue pointer to latency queue
107 * \param item ni_lat_meas_q_entry_t item to push onto the queue
108 *
109 * \return void 1 if success, NULL if failed
110 *
111 ******************************************************************************/
113{
114 if (queue->size == queue->capacity)
115 {
116 return NULL;
117 }
118 queue->rear = (queue->rear + 1) % queue->capacity;
119 queue->array[queue->rear] = item;
120 queue->size = queue->size + 1;
121 return (void *)1;
122}
123
124/*!*****************************************************************************
125 * \brief Pop an item from the queue
126 *
127 * \param queue pointer to latency queue
128 *
129 * \return void pointer to popped item
130 *
131 ******************************************************************************/
133{
134 ni_lat_meas_q_entry_t *dequeue_item;
135 if (queue->size == 0)
136 {
137 return NULL;
138 }
139 dequeue_item = &queue->array[queue->front];
140 queue->front = (queue->front + 1) % queue->capacity;
141 queue->size = queue->size - 1;
142 return dequeue_item;
143}
144
145/*!*****************************************************************************
146 * \brief Get a pointer to rear of queue
147 *
148 * \param queue pointer to latency queue
149 *
150 * \return void pointer to rear of queue
151 *
152 ******************************************************************************/
154{
155 return queue->size == 0 ? NULL : &queue->array[queue->rear];
156}
157
158/*!*****************************************************************************
159 * \brief Get a pointer to front of queue
160 *
161 * \param queue pointer to latency queue
162 *
163 * \return void pointer to front of queue
164 *
165 ******************************************************************************/
167{
168 return queue->size == 0 ? NULL : &queue->array[queue->front];
169}
170
171/*!*****************************************************************************
172 * \brief Add a new entry to latency queue
173 *
174 * \param frame_time_q pointer to latency queue
175 * \param abs_time frame start time for latency comparison
176 * \param ts_time reference frame timestamp time
177 *
178 * \return void 1 if success, NULL if failed
179 *
180 ******************************************************************************/
181void *ni_lat_meas_q_add_entry(ni_lat_meas_q_t *frame_time_q, uint64_t abs_time,
182 int64_t ts_time)
183{
184 // ni_log(NI_LOG_DEBUG, "ni_lat_meas_q_add_entry abs_time=%" PRIu64 " "
185 // "ts_time=%" PRId64 "\n", abs_time, ts_time);
186 ni_lat_meas_q_entry_t entry = {.abs_timenano = abs_time,
187 .ts_time = ts_time};
188 return ni_lat_meas_q_enqueue(frame_time_q, entry);
189}
190
191/*!*****************************************************************************
192 * \brief Check latency of a frame referenced by its timestamp
193 *
194 * \param frame_time_q pointer to latency queue
195 * \param abs_time frame end time for latency comparison
196 * \param ts_time reference frame timestamp time
197 *
198 * \return uint64_t value of latency if suceeded, -1 if failed
199 *
200 ******************************************************************************/
202 uint64_t abs_time, int64_t ts_time)
203{
204 // ni_log(NI_LOG_DEBUG, "ni_lat_meas_q_check_latency abs_time=%" PRIu64 " "
205 // "ts_time="%" PRId64 "\n", abs_time, ts_time);
206 uint64_t ret = -1;
207 uint32_t dequeue_count = 0;
208 ni_lat_meas_q_entry_t *entry = ni_lat_meas_q_front(frame_time_q);
209
210 if (entry == NULL)
211 {
212 return -1;
213 }
214
215 if (entry->ts_time == ts_time)
216 {
217 ni_lat_meas_q_dequeue(frame_time_q);
218 dequeue_count++;
219 } else
220 { // queue miss, perhaps frame was not decoded properly or TS was offset
221 while (entry->ts_time < ts_time)
222 {
223 entry = ni_lat_meas_q_dequeue(frame_time_q);
224 dequeue_count++;
225 if (entry == NULL)
226 {
227 return -1;
228 }
229 }
230 }
231 ni_log(NI_LOG_DEBUG, "DQ_CNT:%u,QD:%d", dequeue_count, frame_time_q->size);
232
233 if ((entry == NULL) || (entry->ts_time > ts_time))
234 { // queue overrun OR
235 // queue miss, perhaps frame was not enqueued properly or TS was offset
236 ret = -1;
237 } else if (entry->ts_time == ts_time)
238 {
239 ret = abs_time - entry->abs_timenano;
240 }
241
242 return ret;
243}
#define NI_ERRNO
Definition ni_defs.h:229
void * ni_lat_meas_q_front(ni_lat_meas_q_t *queue)
Get a pointer to front of queue.
ni_lat_meas_q_t * ni_lat_meas_q_create(int capacity)
Create a latency measurement queue object of a given capacity.
Definition ni_lat_meas.c:52
void ni_lat_meas_q_destroy(ni_lat_meas_q_t *frame_time_q)
Destroy a latency measurement queue object.
Definition ni_lat_meas.c:97
void * ni_lat_meas_q_rear(ni_lat_meas_q_t *queue)
Get a pointer to rear of queue.
void * ni_lat_meas_q_add_entry(ni_lat_meas_q_t *frame_time_q, uint64_t abs_time, int64_t ts_time)
Add a new entry to latency queue.
void * ni_lat_meas_q_dequeue(ni_lat_meas_q_t *queue)
Pop an item from the queue.
uint64_t ni_lat_meas_q_check_latency(ni_lat_meas_q_t *frame_time_q, uint64_t abs_time, int64_t ts_time)
Check latency of a frame referenced by its timestamp.
void * ni_lat_meas_q_enqueue(ni_lat_meas_q_t *queue, ni_lat_meas_q_entry_t item)
Push an item onto the queue.
Utility definitions for measuring frame/packet processing time in NETINT video processing devices.
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_ERROR
Definition ni_log.h:62
uint64_t ni_gettime_ns(void)
Definition ni_util.c:2622
Utility definitions.
Definition ni_lat_meas.h:34
int64_t ts_time
Definition ni_lat_meas.h:36
uint64_t abs_timenano
Definition ni_lat_meas.h:35
uint64_t last_benchmark_time
Definition ni_lat_meas.h:42
ni_lat_meas_q_entry_t * array
Definition ni_lat_meas.h:43