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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user