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.
This commit is contained in:
parent
efc15744da
commit
f25a67f342
2 changed files with 32 additions and 36 deletions
|
@ -10,35 +10,26 @@
|
||||||
|
|
||||||
#define SC_BUFFERING_NDEBUG // comment to debug
|
#define SC_BUFFERING_NDEBUG // comment to debug
|
||||||
|
|
||||||
static struct sc_video_buffer_frame *
|
static bool
|
||||||
sc_video_buffer_frame_new(const AVFrame *frame) {
|
sc_video_buffer_frame_init(struct sc_video_buffer_frame *vb_frame,
|
||||||
struct sc_video_buffer_frame *vb_frame = malloc(sizeof(*vb_frame));
|
const AVFrame *frame) {
|
||||||
if (!vb_frame) {
|
|
||||||
LOG_OOM();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
vb_frame->frame = av_frame_alloc();
|
vb_frame->frame = av_frame_alloc();
|
||||||
if (!vb_frame->frame) {
|
if (!vb_frame->frame) {
|
||||||
LOG_OOM();
|
return false;
|
||||||
free(vb_frame);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (av_frame_ref(vb_frame->frame, frame)) {
|
if (av_frame_ref(vb_frame->frame, frame)) {
|
||||||
av_frame_free(&vb_frame->frame);
|
av_frame_free(&vb_frame->frame);
|
||||||
free(vb_frame);
|
return false;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return vb_frame;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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_unref(vb_frame->frame);
|
||||||
av_frame_free(&vb_frame->frame);
|
av_frame_free(&vb_frame->frame);
|
||||||
free(vb_frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -62,7 +53,7 @@ run_buffering(void *data) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
sc_mutex_lock(&vb->b.mutex);
|
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);
|
sc_cond_wait(&vb->b.queue_cond, &vb->b.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,12 +62,11 @@ run_buffering(void *data) {
|
||||||
goto stopped;
|
goto stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sc_video_buffer_frame *vb_frame;
|
struct sc_video_buffer_frame vb_frame = sc_vecdeque_pop(&vb->b.queue);
|
||||||
sc_queue_take(&vb->b.queue, next, &vb_frame);
|
|
||||||
|
|
||||||
sc_tick max_deadline = sc_tick_now() + vb->buffering_time;
|
sc_tick max_deadline = sc_tick_now() + vb->buffering_time;
|
||||||
// PTS (written by the server) are expressed in microseconds
|
// 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;
|
bool timed_out = false;
|
||||||
while (!vb->b.stopped && !timed_out) {
|
while (!vb->b.stopped && !timed_out) {
|
||||||
|
@ -91,7 +81,7 @@ run_buffering(void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vb->b.stopped) {
|
if (vb->b.stopped) {
|
||||||
sc_video_buffer_frame_delete(vb_frame);
|
sc_video_buffer_frame_destroy(&vb_frame);
|
||||||
sc_mutex_unlock(&vb->b.mutex);
|
sc_mutex_unlock(&vb->b.mutex);
|
||||||
goto stopped;
|
goto stopped;
|
||||||
}
|
}
|
||||||
|
@ -100,20 +90,19 @@ run_buffering(void *data) {
|
||||||
|
|
||||||
#ifndef SC_BUFFERING_NDEBUG
|
#ifndef SC_BUFFERING_NDEBUG
|
||||||
LOGD("Buffering: %" PRItick ";%" PRItick ";%" PRItick,
|
LOGD("Buffering: %" PRItick ";%" PRItick ";%" PRItick,
|
||||||
pts, vb_frame->push_date, sc_tick_now());
|
pts, vb_frame.push_date, sc_tick_now());
|
||||||
#endif
|
#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:
|
stopped:
|
||||||
// Flush queue
|
// Flush queue
|
||||||
while (!sc_queue_is_empty(&vb->b.queue)) {
|
while (!sc_vecdeque_is_empty(&vb->b.queue)) {
|
||||||
struct sc_video_buffer_frame *vb_frame;
|
struct sc_video_buffer_frame *p = sc_vecdeque_popref(&vb->b.queue);
|
||||||
sc_queue_take(&vb->b.queue, next, &vb_frame);
|
sc_video_buffer_frame_destroy(p);
|
||||||
sc_video_buffer_frame_delete(vb_frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGD("Buffering thread ended");
|
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_clock_init(&vb->b.clock);
|
||||||
sc_queue_init(&vb->b.queue);
|
sc_vecdeque_init(&vb->b.queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(cbs);
|
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);
|
return sc_video_buffer_offer(vb, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sc_video_buffer_frame *vb_frame = sc_video_buffer_frame_new(frame);
|
struct sc_video_buffer_frame vb_frame;
|
||||||
if (!vb_frame) {
|
bool ok = sc_video_buffer_frame_init(&vb_frame, frame);
|
||||||
|
if (!ok) {
|
||||||
sc_mutex_unlock(&vb->b.mutex);
|
sc_mutex_unlock(&vb->b.mutex);
|
||||||
LOG_OOM();
|
LOG_OOM();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SC_BUFFERING_NDEBUG
|
#ifndef SC_BUFFERING_NDEBUG
|
||||||
vb_frame->push_date = sc_tick_now();
|
vb_frame.push_date = sc_tick_now();
|
||||||
#endif
|
#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_cond_signal(&vb->b.queue_cond);
|
||||||
|
|
||||||
sc_mutex_unlock(&vb->b.mutex);
|
sc_mutex_unlock(&vb->b.mutex);
|
||||||
|
|
|
@ -7,22 +7,21 @@
|
||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "frame_buffer.h"
|
#include "frame_buffer.h"
|
||||||
#include "util/queue.h"
|
|
||||||
#include "util/thread.h"
|
#include "util/thread.h"
|
||||||
#include "util/tick.h"
|
#include "util/tick.h"
|
||||||
|
#include "util/vecdeque.h"
|
||||||
|
|
||||||
// forward declarations
|
// forward declarations
|
||||||
typedef struct AVFrame AVFrame;
|
typedef struct AVFrame AVFrame;
|
||||||
|
|
||||||
struct sc_video_buffer_frame {
|
struct sc_video_buffer_frame {
|
||||||
AVFrame *frame;
|
AVFrame *frame;
|
||||||
struct sc_video_buffer_frame *next;
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
sc_tick push_date;
|
sc_tick push_date;
|
||||||
#endif
|
#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_video_buffer {
|
||||||
struct sc_frame_buffer fb;
|
struct sc_frame_buffer fb;
|
||||||
|
|
Loading…
Reference in a new issue