diff options
Diffstat (limited to 'src/buffer')
| -rw-r--r-- | src/buffer/common_internal.h | 3 | ||||
| -rw-r--r-- | src/buffer/video.c | 36 |
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."); } |