summaryrefslogtreecommitdiff
path: root/src/buffer
diff options
context:
space:
mode:
Diffstat (limited to 'src/buffer')
-rw-r--r--src/buffer/common_internal.h3
-rw-r--r--src/buffer/video.c36
2 files changed, 21 insertions, 18 deletions
diff --git a/src/buffer/common_internal.h b/src/buffer/common_internal.h
index 11caddc..700e278 100644
--- a/src/buffer/common_internal.h
+++ b/src/buffer/common_internal.h
@@ -17,6 +17,5 @@ enum {
static inline bool frame_is_late(struct camu_clock *clock, f64 base, f64 pts, f64 duration)
{
- if (base == -1.0) base = camu_clock_get_base_pts(clock);
- return pts + duration < base;
+ return pts + duration < ((base == -1.0) ? camu_clock_get_base_pts(clock) : base);
}
diff --git a/src/buffer/video.c b/src/buffer/video.c
index 8bedbf6..ab61c2a 100644
--- a/src/buffer/video.c
+++ b/src/buffer/video.c
@@ -1,4 +1,5 @@
#define AL_LOG_SECTION "video_buffer"
+//#define AL_LOG_ENABLE_TRACE
#include <al/log.h>
#ifdef CAMU_HAVE_FFMPEG
@@ -14,10 +15,10 @@
// quite incompatible with very low frame rates.
// MARK_LOW is considered directly after reading a frame, so in other words,
// it will trigger at the point where there is about (LOW+1) frames left. Even at
-// something like 240fps that's still ~12 whole ms to uncork and produce a new frame.
-#define BUFFER_MARK_LOW 2
-#define BUFFER_MARK_BUFFERED 5 // Must be >1.
-#define BUFFER_MARK_HIGH 7
+// something like 240fps that's still ~(4*(LOW+1))ms to uncork and produce a new frame.
+#define BUFFER_MARK_LOW 3
+#define BUFFER_MARK_BUFFERED 6 // Must be >1.
+#define BUFFER_MARK_HIGH 8
#define BUFFER_MARK_RESET (BUFFER_MARK_HIGH * 2)
bool camu_video_buffer_init(struct camu_video_buffer *buf, struct camu_clock *clock)
@@ -75,7 +76,7 @@ bool camu_video_buffer_configure(struct camu_video_buffer *buf, struct camu_code
camu_video_format_copy(req, in);
if (fmt->width > 0 && fmt->height > 0 &&
#ifdef CAMU_VIDEO_BUFFER_REQUIRE_RGB
- (fmt->format != CAMU_PIXEL_FORMAT_RGBA && fmt->format != CAMU_PIXEL_FORMAT_RGB32)
+ (fmt->format != CAMU_PIXEL_FORMAT_RGBA && fmt->format != CAMU_PIXEL_FORMAT_RGB24 && fmt->format != CAMU_PIXEL_FORMAT_RGB32)
#else
(fmt->format == CAMU_PIXEL_FORMAT_PAL8)
#endif
@@ -84,10 +85,9 @@ bool camu_video_buffer_configure(struct camu_video_buffer *buf, struct camu_code
req->width = fmt->width;
req->height = fmt->height;
#ifdef CAMU_HAVE_FFMPEG
- //const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get((enum AVPixelFormat)fmt->format);
- //bool has_alpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) != 0;
- //req->format = CAMU_PIXEL_FORMAT_RGB32;
- req->format = CAMU_PIXEL_FORMAT_RGBA;
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get((enum AVPixelFormat)fmt->format);
+ bool has_alpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) != 0;
+ req->format = has_alpha ? CAMU_PIXEL_FORMAT_RGB32 : CAMU_PIXEL_FORMAT_RGB24;
buf->scaler = camu_ff_scaler_create();
if (!buf->scaler->init(buf->scaler, &buf->fmt)) {
// Scaler will be freed in video_buffer_free().
@@ -143,8 +143,8 @@ static bool push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame
{
AVStream *stream = buf->stream->av.stream;
f64 pts = frame->best_effort_timestamp * av_q2d(stream->time_base);
- f64 duration = camu_ff_frame_duration(frame) * av_q2d(stream->time_base);
f64 base_pts = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
+ f64 duration = camu_ff_frame_duration(frame) * av_q2d(stream->time_base);
if (!buf->single_frame && frame_is_late(buf->clock, base_pts, pts, duration)) {
return false;
}
@@ -228,10 +228,7 @@ bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weig
f64 base_pts = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
if (!buf->single_frame) {
f64 pts = camu_clock_get_pts(buf->clock, buf->latency, !buf->weighted_read);
- if (pts > base_pts) {
- base_pts = pts;
- al_atomic_store(f64)(&buf->pts, base_pts, AL_ATOMIC_RELEASE);
- }
+ if (pts > base_pts) base_pts = pts;
}
u8 flow = al_atomic_load(u8)(&buf->flow, AL_ATOMIC_ACQUIRE);
@@ -263,8 +260,15 @@ bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weig
}
if (ret == CAMU_QUEUE_OK) {
- *weighted = buf->weighted_read;
- buf->weighted_read = false;
+ if (UNLIKELY(buf->weighted_read)) {
+ *weighted = buf->weighted_read;
+ buf->weighted_read = false;
+ }
+ // Only updating buf->pts on QUEUE_OK affects the behavior when we fall completely behind.
+ // Setting it here will result in laggily displaying out of date frames as they come in.
+ // Setting it on every read() will cause the video to freeze.
+ // This option ignores sync but is easier for the user to understand what's happening.
+ al_atomic_store(f64)(&buf->pts, base_pts, AL_ATOMIC_RELEASE);
} else if (ret == CAMU_QUEUE_MORE) {
log_trace("Underrun.");
}