Add runtime option to render expired frames

Replace the compilation flag SKIP_FRAMES by a runtime flag to force
rendering of expired frames. By default, the expired frames are skipped.
This commit is contained in:
Romain Vimont
2019-06-05 19:02:50 +02:00
parent a143b8b07a
commit ebccb9f6cc
9 changed files with 67 additions and 61 deletions

View File

@@ -10,7 +10,7 @@
#include "log.h"
bool
video_buffer_init(struct video_buffer *vb) {
video_buffer_init(struct video_buffer *vb, bool render_expired_frames) {
if (!(vb->decoding_frame = av_frame_alloc())) {
goto error_0;
}
@@ -23,13 +23,16 @@ video_buffer_init(struct video_buffer *vb) {
goto error_2;
}
#ifndef SKIP_FRAMES
if (!(vb->rendering_frame_consumed_cond = SDL_CreateCond())) {
SDL_DestroyMutex(vb->mutex);
goto error_2;
vb->render_expired_frames = render_expired_frames;
if (render_expired_frames) {
if (!(vb->rendering_frame_consumed_cond = SDL_CreateCond())) {
SDL_DestroyMutex(vb->mutex);
goto error_2;
}
// interrupted is not used if expired frames are not rendered
// since offering a frame will never block
vb->interrupted = false;
}
vb->interrupted = false;
#endif
// there is initially no rendering frame, so consider it has already been
// consumed
@@ -48,9 +51,9 @@ error_0:
void
video_buffer_destroy(struct video_buffer *vb) {
#ifndef SKIP_FRAMES
SDL_DestroyCond(vb->rendering_frame_consumed_cond);
#endif
if (vb->render_expired_frames) {
SDL_DestroyCond(vb->rendering_frame_consumed_cond);
}
SDL_DestroyMutex(vb->mutex);
av_frame_free(&vb->rendering_frame);
av_frame_free(&vb->decoding_frame);
@@ -67,17 +70,16 @@ void
video_buffer_offer_decoded_frame(struct video_buffer *vb,
bool *previous_frame_skipped) {
mutex_lock(vb->mutex);
#ifndef SKIP_FRAMES
// if SKIP_FRAMES is disabled, then the decoder must wait for the current
// frame to be consumed
while (!vb->rendering_frame_consumed && !vb->interrupted) {
cond_wait(vb->rendering_frame_consumed_cond, vb->mutex);
if (vb->render_expired_frames) {
// wait for the current (expired) frame to be consumed
while (!vb->rendering_frame_consumed && !vb->interrupted) {
cond_wait(vb->rendering_frame_consumed_cond, vb->mutex);
}
} else {
if (vb->fps_counter.started && !vb->rendering_frame_consumed) {
fps_counter_add_skipped_frame(&vb->fps_counter);
}
}
#else
if (vb->fps_counter.started && !vb->rendering_frame_consumed) {
fps_counter_add_skipped_frame(&vb->fps_counter);
}
#endif
video_buffer_swap_frames(vb);
@@ -94,23 +96,20 @@ video_buffer_consume_rendered_frame(struct video_buffer *vb) {
if (vb->fps_counter.started) {
fps_counter_add_rendered_frame(&vb->fps_counter);
}
#ifndef SKIP_FRAMES
// if SKIP_FRAMES is disabled, then notify the decoder the current frame is
// consumed, so that it may push a new one
cond_signal(vb->rendering_frame_consumed_cond);
#endif
if (vb->render_expired_frames) {
// unblock video_buffer_offer_decoded_frame()
cond_signal(vb->rendering_frame_consumed_cond);
}
return vb->rendering_frame;
}
void
video_buffer_interrupt(struct video_buffer *vb) {
#ifdef SKIP_FRAMES
(void) vb; // unused
#else
mutex_lock(vb->mutex);
vb->interrupted = true;
mutex_unlock(vb->mutex);
// wake up blocking wait
cond_signal(vb->rendering_frame_consumed_cond);
#endif
if (vb->render_expired_frames) {
mutex_lock(vb->mutex);
vb->interrupted = true;
mutex_unlock(vb->mutex);
// wake up blocking wait
cond_signal(vb->rendering_frame_consumed_cond);
}
}