The open source OpenXR runtime
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

u/sink: Allow u_sink_queue to queue more than one frame

Passing max_size=1 gives a similar behaviour as before, although instead
of discarding the last enqueued frame, it just ignores the new frame.

authored by

Mateo de Mayo and committed by
Jakob Bornecrantz
e245f4e5 ba7f9d95

+105 -28
+1
src/xrt/auxiliary/util/u_sink.h
··· 96 96 */ 97 97 bool 98 98 u_sink_queue_create(struct xrt_frame_context *xfctx, 99 + uint64_t max_size, 99 100 struct xrt_frame_sink *downstream, 100 101 struct xrt_frame_sink **out_xfs); 101 102
+96 -20
src/xrt/auxiliary/util/u_sink_queue.c
··· 14 14 #include <stdio.h> 15 15 #include <pthread.h> 16 16 17 + struct u_sink_queue_elem 18 + { 19 + struct xrt_frame *frame; 20 + struct u_sink_queue_elem *next; 21 + }; 17 22 18 23 /*! 19 24 * An @ref xrt_frame_sink queue, any frames received will be pushed to the ··· 33 38 //! The consumer of the frames that are queued. 34 39 struct xrt_frame_sink *consumer; 35 40 36 - //! The current queued frame. 37 - struct xrt_frame *frame; 41 + //! Front of the queue (oldest frame, first to be consumed) 42 + struct u_sink_queue_elem *front; 43 + 44 + //! Back of the queue (newest frame, back->next is always null) 45 + struct u_sink_queue_elem *back; 46 + 47 + //! Number of currently enqueued frames 48 + uint64_t size; 49 + 50 + //! Max amount of frames before dropping new ones. 0 means unbounded. 51 + uint64_t max_size; 38 52 39 53 pthread_t thread; 40 54 pthread_mutex_t mutex; 41 55 pthread_cond_t cond; 42 56 43 - struct 44 - { 45 - uint64_t current; 46 - uint64_t last; 47 - } seq; 48 - 49 57 //! Should we keep running. 50 58 bool running; 51 59 }; 52 60 61 + //! Call with q->mutex locked. 62 + static bool 63 + queue_is_empty(struct u_sink_queue *q) 64 + { 65 + return q->size == 0; 66 + } 67 + 68 + //! Call with q->mutex locked. 69 + static bool 70 + queue_is_full(struct u_sink_queue *q) 71 + { 72 + bool is_unbounded = q->max_size == 0; 73 + return q->size >= q->max_size && !is_unbounded; 74 + } 75 + 76 + //! Pops the oldest frame, reference counting unchanged. 77 + //! Call with q->mutex locked. 78 + static struct xrt_frame * 79 + queue_pop(struct u_sink_queue *q) 80 + { 81 + assert(!queue_is_empty(q)); 82 + struct xrt_frame *frame = q->front->frame; 83 + struct u_sink_queue_elem *old_front = q->front; 84 + q->front = q->front->next; 85 + free(old_front); 86 + q->size--; 87 + if (q->front == NULL) { 88 + assert(queue_is_empty(q)); 89 + q->back = NULL; 90 + } 91 + return frame; 92 + } 93 + 94 + //! Tries to push a frame and increases its reference count. 95 + //! Call with q->mutex locked. 96 + static bool 97 + queue_try_refpush(struct u_sink_queue *q, struct xrt_frame *xf) 98 + { 99 + if (!queue_is_full(q)) { 100 + struct u_sink_queue_elem *elem = U_TYPED_CALLOC(struct u_sink_queue_elem); 101 + xrt_frame_reference(&elem->frame, xf); 102 + elem->next = NULL; 103 + if (q->back == NULL) { // First frame 104 + q->front = elem; 105 + } else { // Next frame 106 + q->back->next = elem; 107 + } 108 + q->back = elem; 109 + q->size++; 110 + return true; 111 + } 112 + return false; 113 + } 114 + 115 + //! Clears the queue and unreferences all of its frames. 116 + //! Call with q->mutex locked. 117 + static void 118 + queue_refclear(struct u_sink_queue *q) 119 + { 120 + while (!queue_is_empty(q)) { 121 + assert((q->size > 1) ^ (q->front == q->back)); 122 + struct xrt_frame *xf = queue_pop(q); 123 + xrt_frame_reference(&xf, NULL); 124 + } 125 + } 126 + 53 127 static void * 54 128 queue_mainloop(void *ptr) 55 129 { ··· 63 137 while (q->running) { 64 138 65 139 // No new frame, wait. 66 - if (q->seq.last >= q->seq.current) { 140 + if (queue_is_empty(q)) { 67 141 pthread_cond_wait(&q->cond, &q->mutex); 68 142 } 69 143 ··· 73 147 } 74 148 75 149 // Just in case. 76 - if (q->seq.last >= q->seq.current || q->frame == NULL) { 150 + if (queue_is_empty(q)) { 77 151 continue; 78 152 } 79 153 80 154 SINK_TRACE_IDENT(queue_frame); 81 155 82 - // We have a new frame, send it out. 83 - q->seq.last = q->seq.current; 84 - 85 156 /* 157 + * Dequeue frame. 86 158 * We need to take a reference on the current frame, this is to 87 159 * keep it alive during the call to the consumer should it be 88 160 * replaced. But we no longer need to hold onto the frame on the 89 - * queue so we just move the pointer. 161 + * queue so we just dequeue it. 90 162 */ 91 - frame = q->frame; 92 - q->frame = NULL; 163 + frame = queue_pop(q); 93 164 94 165 /* 95 166 * Unlock the mutex when we do the work, so a new frame can be ··· 126 197 127 198 // Only schedule new frames if we are running. 128 199 if (q->running) { 129 - q->seq.current++; 130 - xrt_frame_reference(&q->frame, xf); 200 + queue_try_refpush(q, xf); 131 201 } 132 202 133 203 // Wake up the thread. ··· 149 219 q->running = false; 150 220 151 221 // Release any frame waiting for submission. 152 - xrt_frame_reference(&q->frame, NULL); 222 + queue_refclear(q); 153 223 154 224 // Wake up the thread. 155 225 pthread_cond_signal(&q->cond); ··· 180 250 */ 181 251 182 252 bool 183 - u_sink_queue_create(struct xrt_frame_context *xfctx, struct xrt_frame_sink *downstream, struct xrt_frame_sink **out_xfs) 253 + u_sink_queue_create(struct xrt_frame_context *xfctx, 254 + uint64_t max_size, 255 + struct xrt_frame_sink *downstream, 256 + struct xrt_frame_sink **out_xfs) 184 257 { 185 258 struct u_sink_queue *q = U_TYPED_CALLOC(struct u_sink_queue); 186 259 int ret = 0; ··· 190 263 q->node.destroy = queue_destroy; 191 264 q->consumer = downstream; 192 265 q->running = true; 266 + 267 + q->size = 0; 268 + q->max_size = max_size; 193 269 194 270 ret = pthread_mutex_init(&q->mutex, NULL); 195 271 if (ret != 0) {
+2 -2
src/xrt/drivers/ht/ht_driver.cpp
··· 714 714 715 715 // This puts u_sink_create_to_r8g8b8_or_l8 on its own thread, so that nothing gets backed up if it runs slower 716 716 // than the native camera framerate. 717 - u_sink_queue_create(&htd->camera.xfctx, tmp, &tmp); 717 + u_sink_queue_create(&htd->camera.xfctx, 1, tmp, &tmp); 718 718 719 719 // Converts images (we'd expect YUV422 or MJPEG) to R8G8B8. Can take a long time, especially on unoptimized 720 720 // builds. If it's really slow, triple-check that you built Monado with optimizations! ··· 722 722 723 723 // Puts the hand tracking code on its own thread, so that nothing upstream of it gets backed up if the hand 724 724 // tracking code runs slower than the upstream framerate. 725 - u_sink_queue_create(&htd->camera.xfctx, tmp, &tmp); 725 + u_sink_queue_create(&htd->camera.xfctx, 1, tmp, &tmp); 726 726 727 727 xrt_fs_mode *modes; 728 728 uint32_t count;
+3 -3
src/xrt/state_trackers/gui/gui_scene_calibrate.c
··· 320 320 321 321 p->texs[p->num_texs++] = gui_ogl_sink_create("Calibration", cs->xfctx, &rgb); 322 322 u_sink_create_to_r8g8b8_or_l8(cs->xfctx, rgb, &rgb); 323 - u_sink_queue_create(cs->xfctx, rgb, &rgb); 323 + u_sink_queue_create(cs->xfctx, 1, rgb, &rgb); 324 324 325 325 p->texs[p->num_texs++] = gui_ogl_sink_create("Raw", cs->xfctx, &raw); 326 326 u_sink_create_to_r8g8b8_or_l8(cs->xfctx, raw, &raw); 327 - u_sink_queue_create(cs->xfctx, raw, &raw); 327 + u_sink_queue_create(cs->xfctx, 1, raw, &raw); 328 328 329 329 t_calibration_stereo_create(cs->xfctx, &cs->params, &cs->status, rgb, &cali); 330 330 u_sink_split_create(cs->xfctx, raw, cali, &cali); 331 331 u_sink_deinterleaver_create(cs->xfctx, cali, &cali); 332 - u_sink_queue_create(cs->xfctx, cali, &cali); 332 + u_sink_queue_create(cs->xfctx, 1, cali, &cali); 333 333 334 334 // Just after the camera create a quirk stream. 335 335 struct u_sink_quirk_params qp;
+2 -2
src/xrt/state_trackers/gui/gui_window_record.c
··· 123 123 if (do_convert) { 124 124 u_sink_create_to_r8g8b8_or_l8(&rw->gst.xfctx, tmp, &tmp); 125 125 } 126 - u_sink_queue_create(&rw->gst.xfctx, tmp, &tmp); 126 + u_sink_queue_create(&rw->gst.xfctx, 1, tmp, &tmp); 127 127 128 128 os_mutex_lock(&rw->gst.mutex); 129 129 rw->gst.gs = gs; ··· 273 273 struct xrt_frame_sink *tmp = NULL; 274 274 rw->texture.ogl = gui_ogl_sink_create("View", &rw->texture.xfctx, &tmp); 275 275 u_sink_create_to_r8g8b8_or_l8(&rw->texture.xfctx, tmp, &tmp); 276 - u_sink_queue_create(&rw->texture.xfctx, tmp, &rw->texture.sink); 276 + u_sink_queue_create(&rw->texture.xfctx, 1, tmp, &rw->texture.sink); 277 277 278 278 return true; 279 279 }
+1 -1
src/xrt/state_trackers/prober/p_tracking.c
··· 200 200 u_sink_create_to_yuv_or_yuyv(&fact->xfctx, xsink, &xsink); 201 201 202 202 // Put a queue before it to multi-thread the filter. 203 - u_sink_queue_create(&fact->xfctx, xsink, &xsink); 203 + u_sink_queue_create(&fact->xfctx, 1, xsink, &xsink); 204 204 205 205 struct xrt_frame_sink *ht_sink = NULL; 206 206 t_hand_create(&fact->xfctx, fact->data, &fact->xth, &ht_sink);