summaryrefslogtreecommitdiff
path: root/src/buffer
diff options
context:
space:
mode:
Diffstat (limited to 'src/buffer')
-rw-r--r--src/buffer/audio.c8
-rw-r--r--src/buffer/clock.c18
-rw-r--r--src/buffer/clock.h2
-rw-r--r--src/buffer/video.c39
-rw-r--r--src/buffer/video.h6
5 files changed, 52 insertions, 21 deletions
diff --git a/src/buffer/audio.c b/src/buffer/audio.c
index 7bb2c4c..d438d25 100644
--- a/src/buffer/audio.c
+++ b/src/buffer/audio.c
@@ -9,9 +9,9 @@
#include "common_internal.h"
#include "volume.h"
-#define BUFFER_SIZE 9.0
-#define BUFFER_MARK_MIN 4.3 // Must be a most half of the buffer size.
-#define BUFFER_MARK_BUFFERED 2.0
+#define BUFFER_SIZE 4.0
+#define BUFFER_MARK_MIN 1.75 // Must be a most half of the buffer size.
+#define BUFFER_MARK_BUFFERED 1.0
#ifdef CAMU_AUDIO_BUFFER_FADE
#define FADE_STEP(fmt) (1.75f / (fmt)->sample_rate)
@@ -291,7 +291,7 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re
}
f64 base = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
- f64 pts = camu_clock_get_pts(buf->clock, buf->latency);
+ f64 pts = camu_clock_get_pts(buf->clock, buf->latency, false);
size_t ret, signal = req;
size_t have = al_ring_buffer_occupied(&buf->rb);
#ifdef CAMU_AUDIO_BUFFER_FADE
diff --git a/src/buffer/clock.c b/src/buffer/clock.c
index 33118aa..b711a27 100644
--- a/src/buffer/clock.c
+++ b/src/buffer/clock.c
@@ -57,6 +57,7 @@ void camu_clock_offset(struct camu_clock *clock, f64 amount)
void camu_clock_pause(struct camu_clock *clock, u64 target)
{
al_assert(clock->paused_at == -1.0);
+
f64 tick = nn_get_tick();
if (target > 0) {
tick = calc_tick_offset(tick, nn_get_timestamp(), target);
@@ -64,19 +65,19 @@ void camu_clock_pause(struct camu_clock *clock, u64 target)
} else {
al_atomic_store(f64)(&clock->pause, PAUSED, AL_ATOMIC_RELAXED);
}
+
clock->paused_at = tick;
}
void camu_clock_resume(struct camu_clock *clock, u64 target)
{
al_assert(clock->paused_at != -1.0);
+
f64 tick = nn_get_tick();
- //if (pause != PAUSED && tick < pause) {
- // tick = pause;
- //} else if (target > 0) {
if (target > 0) {
tick = calc_tick_offset(tick, nn_get_timestamp(), target);
}
+
if (clock->paused_at == 0.0) {
if (target == 0) {
// target = 0 can never be synced.
@@ -87,6 +88,7 @@ void camu_clock_resume(struct camu_clock *clock, u64 target)
} else {
clock->offset += tick - clock->paused_at;
}
+
al_atomic_store(f64)(&clock->pause, RUNNING, AL_ATOMIC_RELAXED);
clock->paused_at = -1.0;
}
@@ -106,7 +108,7 @@ f64 camu_clock_get_base_pts(struct camu_clock *clock)
return clock->base;
}
-f64 camu_clock_get_pts(struct camu_clock *clock, f64 offset)
+f64 camu_clock_get_pts(struct camu_clock *clock, f64 offset, bool skip_set)
{
f64 pause = al_atomic_load(f64)(&clock->pause, AL_ATOMIC_ACQUIRE);
if (pause == PAUSED) return -1.0;
@@ -115,8 +117,12 @@ f64 camu_clock_get_pts(struct camu_clock *clock, f64 offset)
f64 tick = al_atomic_load(f64)(&clock->tick, AL_ATOMIC_RELAXED);
if (tick == -1.0) {
- tick = al_atomic_compare_and_swap(f64)(&clock->tick, -1.0, current);
- if (tick == -1.0) tick = current;
+ if (skip_set) {
+ return -1.0;
+ } else {
+ tick = al_atomic_compare_and_swap(f64)(&clock->tick, -1.0, current);
+ if (tick == -1.0) tick = current;
+ }
}
// pause > 0.0 means running or pause armed.
diff --git a/src/buffer/clock.h b/src/buffer/clock.h
index 86eba5e..edad287 100644
--- a/src/buffer/clock.h
+++ b/src/buffer/clock.h
@@ -48,4 +48,4 @@ bool camu_clock_is_armed(struct camu_clock *clock);
bool camu_clock_is_paused(struct camu_clock *clock);
f64 camu_clock_get_base_pts(struct camu_clock *clock);
-f64 camu_clock_get_pts(struct camu_clock *clock, f64 offset);
+f64 camu_clock_get_pts(struct camu_clock *clock, f64 offset, bool skip_set);
diff --git a/src/buffer/video.c b/src/buffer/video.c
index fefb307..e2b6f8e 100644
--- a/src/buffer/video.c
+++ b/src/buffer/video.c
@@ -10,22 +10,25 @@
#endif
#endif
-#define BUFFER_MARK_LOW ((1.0 / 30.0) * 6)
-#define BUFFER_MARK_BUFFERED ((1.0 / 30.0) * 8)
-#define BUFFER_MARK_HIGH ((1.0 / 30.0) * 12)
+#define BUFFER_MARK_LOW ((1.0 / 30.0) * 4)
+#define BUFFER_MARK_BUFFERED ((1.0 / 30.0) * 5)
+#define BUFFER_MARK_HIGH ((1.0 / 30.0) * 10)
#define BUFFER_MARK_RESET (BUFFER_MARK_HIGH * 2.0)
bool camu_video_buffer_init(struct camu_video_buffer *buf, struct camu_clock *clock)
{
+
buf->clock = clock;
buf->latency = 0.0;
al_atomic_store(f64)(&buf->pts, -1.0, AL_ATOMIC_RELAXED);
+ buf->last_pts = -1.0;
// The least confusing behavior for single_frame is that it can't be
// set unless the buffer is not empty.
buf->single_frame = false;
buf->avg_frame_duration = 0.0;
buf->queue = NULL;
buf->buffered = false;
+ buf->weighted_read = false;
al_atomic_store(u8)(&buf->flow, FLOWING, AL_ATOMIC_RELAXED);
#ifdef CAMU_SCREEN_THREADED
al_atomic_store(u8)(&buf->ref, 0, AL_ATOMIC_RELAXED);
@@ -43,6 +46,7 @@ bool camu_video_buffer_configure(struct camu_video_buffer *buf, struct camu_code
struct camu_video_format *fmt = &buf->stream->video.fmt;
switch (stream->mode) {
case CAMU_NORMAL: {
+ buf->single_frame = true;
camu_video_format_copy(&buf->fmt.in, fmt);
const char *format_name = camu_pixel_format_name(fmt->format);
if (!format_name) format_name = "unknown";
@@ -122,16 +126,24 @@ bool camu_video_buffer_is_single_frame(struct camu_video_buffer *buf)
static void after_push_internal(struct camu_video_buffer *buf)
{
f64 have = buf->queue->count(buf->queue) * buf->avg_frame_duration;
+
if (!buf->buffered && (buf->single_frame || have >= BUFFER_MARK_BUFFERED)) {
- al_log_debug("video_buffer", "Buffered (mark: %.2fs).", have);
// Preserve order of: flush -> callback -> set flow, for single frames.
if (buf->single_frame) buf->queue->flush(buf->queue);
+
+ al_log_debug("video_buffer", "Buffered (mark: %.2fs).", have);
buf->callback(buf->userdata, CAMU_BUFFER_BUFFERED);
buf->buffered = true;
+
if (buf->single_frame) al_atomic_store(u8)(&buf->flow, FLUSHED, AL_ATOMIC_RELAXED);
}
- if (have >= BUFFER_MARK_RESET) buf->queue->reset(buf->queue);
- else if (have >= BUFFER_MARK_HIGH) buf->callback(buf->userdata, CAMU_BUFFER_CORK);
+
+ if (have >= BUFFER_MARK_RESET) {
+ al_log_warn("video_buffer", "Buffer overflow, resetting.");
+ buf->queue->reset(buf->queue);
+ } else if (have >= BUFFER_MARK_HIGH) {
+ buf->callback(buf->userdata, CAMU_BUFFER_CORK);
+ }
}
static inline bool frame_is_late(struct camu_clock *clock, f64 base, f64 pts, f64 duration)
@@ -218,17 +230,19 @@ void camu_video_buffer_flush(struct camu_video_buffer *buf)
// Not thread-safe, must be called while the buffer is not being read from or written to.
void camu_video_buffer_reset(struct camu_video_buffer *buf)
{
- al_atomic_store(f64)(&buf->pts, -1.0, AL_ATOMIC_RELAXED);
+ buf->last_pts = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
+ al_atomic_store(f64)(&buf->pts, -1.0, AL_ATOMIC_RELEASE);
+ // pl_queue_pts_offset for looping?
if (buf->queue) buf->queue->reset(buf->queue);
buf->buffered = false;
al_atomic_store(u8)(&buf->flow, FLOWING, AL_ATOMIC_RELAXED);
}
-bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out)
+bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weighted)
{
f64 base = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
if (!buf->single_frame) {
- f64 pts = camu_clock_get_pts(buf->clock, buf->latency);
+ f64 pts = camu_clock_get_pts(buf->clock, buf->latency, buf->weighted_read);
if (pts > base) {
base = pts;
al_atomic_store(f64)(&buf->pts, base, AL_ATOMIC_RELEASE);
@@ -241,6 +255,7 @@ bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out)
al_atomic_store(u8)(&buf->flow, ERRORED, AL_ATOMIC_RELEASE);
return false;
}
+
if (flow == FLUSHED && (ret == CAMU_QUEUE_EOF || (buf->single_frame && ret == CAMU_QUEUE_OK))) {
al_log_debug("video_buffer", "Flushed.");
buf->callback(buf->userdata, CAMU_BUFFER_EOF);
@@ -251,6 +266,12 @@ bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out)
buf->callback(buf->userdata, CAMU_BUFFER_UNCORK);
}
}
+
+ if (ret == CAMU_QUEUE_OK) {
+ *weighted = buf->weighted_read;
+ buf->weighted_read = false;
+ }
+
return ret == CAMU_QUEUE_OK || ret == CAMU_QUEUE_MORE;
}
diff --git a/src/buffer/video.h b/src/buffer/video.h
index f6f4e28..5313f75 100644
--- a/src/buffer/video.h
+++ b/src/buffer/video.h
@@ -17,6 +17,7 @@ struct camu_video_buffer {
struct camu_clock *clock;
f64 latency;
atomic(f64) pts;
+ f64 last_pts;
bool single_frame;
f64 avg_frame_duration;
@@ -28,6 +29,9 @@ struct camu_video_buffer {
struct camu_frame_queue *queue;
bool buffered;
+ // Flush the render pipeline on this read and don't allow
+ // it to set the clock.
+ bool weighted_read;
atomic(u8) flow;
@@ -55,5 +59,5 @@ void camu_video_buffer_push_subtitle(struct camu_video_buffer *buf, AVPacket *pk
#endif
void camu_video_buffer_flush(struct camu_video_buffer *buf);
void camu_video_buffer_reset(struct camu_video_buffer *buf);
-bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out);
+bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weighted);
void camu_video_buffer_free(struct camu_video_buffer *buf);