From f25a67f3424406c9cbf33b7b11956ad7dcf2ddb3 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Wed, 1 Mar 2023 22:21:43 +0100 Subject: [PATCH] Use VecDeque in video_buffer The packets queued for buffering were wrapped in a dynamically allocated structure with a "next" field. To avoid this additional layer of allocation and indirection, use a VecDeque. --- app/src/video_buffer.c | 63 ++++++++++++++++++++---------------------- app/src/video_buffer.h | 5 ++-- 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/app/src/video_buffer.c b/app/src/video_buffer.c index 11f76479..b3b29098 100644 --- a/app/src/video_buffer.c +++ b/app/src/video_buffer.c @@ -10,35 +10,26 @@ #define SC_BUFFERING_NDEBUG // comment to debug -static struct sc_video_buffer_frame * -sc_video_buffer_frame_new(const AVFrame *frame) { - struct sc_video_buffer_frame *vb_frame = malloc(sizeof(*vb_frame)); - if (!vb_frame) { - LOG_OOM(); - return NULL; - } - +static bool +sc_video_buffer_frame_init(struct sc_video_buffer_frame *vb_frame, + const AVFrame *frame) { vb_frame->frame = av_frame_alloc(); if (!vb_frame->frame) { - LOG_OOM(); - free(vb_frame); - return NULL; + return false; } if (av_frame_ref(vb_frame->frame, frame)) { av_frame_free(&vb_frame->frame); - free(vb_frame); - return NULL; + return false; } - return vb_frame; + return true; } static void -sc_video_buffer_frame_delete(struct sc_video_buffer_frame *vb_frame) { +sc_video_buffer_frame_destroy(struct sc_video_buffer_frame *vb_frame) { av_frame_unref(vb_frame->frame); av_frame_free(&vb_frame->frame); - free(vb_frame); } static bool @@ -62,7 +53,7 @@ run_buffering(void *data) { for (;;) { sc_mutex_lock(&vb->b.mutex); - while (!vb->b.stopped && sc_queue_is_empty(&vb->b.queue)) { + while (!vb->b.stopped && sc_vecdeque_is_empty(&vb->b.queue)) { sc_cond_wait(&vb->b.queue_cond, &vb->b.mutex); } @@ -71,12 +62,11 @@ run_buffering(void *data) { goto stopped; } - struct sc_video_buffer_frame *vb_frame; - sc_queue_take(&vb->b.queue, next, &vb_frame); + struct sc_video_buffer_frame vb_frame = sc_vecdeque_pop(&vb->b.queue); sc_tick max_deadline = sc_tick_now() + vb->buffering_time; // PTS (written by the server) are expressed in microseconds - sc_tick pts = SC_TICK_TO_US(vb_frame->frame->pts); + sc_tick pts = SC_TICK_TO_US(vb_frame.frame->pts); bool timed_out = false; while (!vb->b.stopped && !timed_out) { @@ -91,7 +81,7 @@ run_buffering(void *data) { } if (vb->b.stopped) { - sc_video_buffer_frame_delete(vb_frame); + sc_video_buffer_frame_destroy(&vb_frame); sc_mutex_unlock(&vb->b.mutex); goto stopped; } @@ -100,20 +90,19 @@ run_buffering(void *data) { #ifndef SC_BUFFERING_NDEBUG LOGD("Buffering: %" PRItick ";%" PRItick ";%" PRItick, - pts, vb_frame->push_date, sc_tick_now()); + pts, vb_frame.push_date, sc_tick_now()); #endif - sc_video_buffer_offer(vb, vb_frame->frame); + sc_video_buffer_offer(vb, vb_frame.frame); - sc_video_buffer_frame_delete(vb_frame); + sc_video_buffer_frame_destroy(&vb_frame); } stopped: // Flush queue - while (!sc_queue_is_empty(&vb->b.queue)) { - struct sc_video_buffer_frame *vb_frame; - sc_queue_take(&vb->b.queue, next, &vb_frame); - sc_video_buffer_frame_delete(vb_frame); + while (!sc_vecdeque_is_empty(&vb->b.queue)) { + struct sc_video_buffer_frame *p = sc_vecdeque_popref(&vb->b.queue); + sc_video_buffer_frame_destroy(p); } LOGD("Buffering thread ended"); @@ -154,7 +143,7 @@ sc_video_buffer_init(struct sc_video_buffer *vb, sc_tick buffering_time, } sc_clock_init(&vb->b.clock); - sc_queue_init(&vb->b.queue); + sc_vecdeque_init(&vb->b.queue); } assert(cbs); @@ -230,17 +219,25 @@ sc_video_buffer_push(struct sc_video_buffer *vb, const AVFrame *frame) { return sc_video_buffer_offer(vb, frame); } - struct sc_video_buffer_frame *vb_frame = sc_video_buffer_frame_new(frame); - if (!vb_frame) { + struct sc_video_buffer_frame vb_frame; + bool ok = sc_video_buffer_frame_init(&vb_frame, frame); + if (!ok) { sc_mutex_unlock(&vb->b.mutex); LOG_OOM(); return false; } #ifndef SC_BUFFERING_NDEBUG - vb_frame->push_date = sc_tick_now(); + vb_frame.push_date = sc_tick_now(); #endif - sc_queue_push(&vb->b.queue, next, vb_frame); + + ok = sc_vecdeque_push(&vb->b.queue, vb_frame); + if (!ok) { + sc_mutex_unlock(&vb->b.mutex); + LOG_OOM(); + return false; + } + sc_cond_signal(&vb->b.queue_cond); sc_mutex_unlock(&vb->b.mutex); diff --git a/app/src/video_buffer.h b/app/src/video_buffer.h index 48777703..41b09434 100644 --- a/app/src/video_buffer.h +++ b/app/src/video_buffer.h @@ -7,22 +7,21 @@ #include "clock.h" #include "frame_buffer.h" -#include "util/queue.h" #include "util/thread.h" #include "util/tick.h" +#include "util/vecdeque.h" // forward declarations typedef struct AVFrame AVFrame; struct sc_video_buffer_frame { AVFrame *frame; - struct sc_video_buffer_frame *next; #ifndef NDEBUG sc_tick push_date; #endif }; -struct sc_video_buffer_frame_queue SC_QUEUE(struct sc_video_buffer_frame); +struct sc_video_buffer_frame_queue SC_VECDEQUE(struct sc_video_buffer_frame); struct sc_video_buffer { struct sc_frame_buffer fb;