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.
pull/3757/head
Romain Vimont 1 year ago
parent efc15744da
commit f25a67f342

@ -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);

@ -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;

Loading…
Cancel
Save