parent
aacb09a3d6
commit
fff87095d9
@ -1,110 +0,0 @@
|
|||||||
#include "frames.h"
|
|
||||||
|
|
||||||
#include <SDL2/SDL_assert.h>
|
|
||||||
#include <SDL2/SDL_mutex.h>
|
|
||||||
#include <libavutil/avutil.h>
|
|
||||||
#include <libavformat/avformat.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "lock_util.h"
|
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
SDL_bool frames_init(struct frames *frames) {
|
|
||||||
if (!(frames->decoding_frame = av_frame_alloc())) {
|
|
||||||
goto error_0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(frames->rendering_frame = av_frame_alloc())) {
|
|
||||||
goto error_1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(frames->mutex = SDL_CreateMutex())) {
|
|
||||||
goto error_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef SKIP_FRAMES
|
|
||||||
if (!(frames->rendering_frame_consumed_cond = SDL_CreateCond())) {
|
|
||||||
SDL_DestroyMutex(frames->mutex);
|
|
||||||
goto error_2;
|
|
||||||
}
|
|
||||||
frames->stopped = SDL_FALSE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// there is initially no rendering frame, so consider it has already been
|
|
||||||
// consumed
|
|
||||||
frames->rendering_frame_consumed = SDL_TRUE;
|
|
||||||
fps_counter_init(&frames->fps_counter);
|
|
||||||
|
|
||||||
return SDL_TRUE;
|
|
||||||
|
|
||||||
error_2:
|
|
||||||
av_frame_free(&frames->rendering_frame);
|
|
||||||
error_1:
|
|
||||||
av_frame_free(&frames->decoding_frame);
|
|
||||||
error_0:
|
|
||||||
return SDL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void frames_destroy(struct frames *frames) {
|
|
||||||
#ifndef SKIP_FRAMES
|
|
||||||
SDL_DestroyCond(frames->rendering_frame_consumed_cond);
|
|
||||||
#endif
|
|
||||||
SDL_DestroyMutex(frames->mutex);
|
|
||||||
av_frame_free(&frames->rendering_frame);
|
|
||||||
av_frame_free(&frames->decoding_frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void frames_swap(struct frames *frames) {
|
|
||||||
AVFrame *tmp = frames->decoding_frame;
|
|
||||||
frames->decoding_frame = frames->rendering_frame;
|
|
||||||
frames->rendering_frame = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_bool frames_offer_decoded_frame(struct frames *frames) {
|
|
||||||
mutex_lock(frames->mutex);
|
|
||||||
#ifndef SKIP_FRAMES
|
|
||||||
// if SKIP_FRAMES is disabled, then the decoder must wait for the current
|
|
||||||
// frame to be consumed
|
|
||||||
while (!frames->rendering_frame_consumed && !frames->stopped) {
|
|
||||||
cond_wait(frames->rendering_frame_consumed_cond, frames->mutex);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (frames->fps_counter.started && !frames->rendering_frame_consumed) {
|
|
||||||
fps_counter_add_skipped_frame(&frames->fps_counter);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
frames_swap(frames);
|
|
||||||
|
|
||||||
SDL_bool previous_frame_consumed = frames->rendering_frame_consumed;
|
|
||||||
frames->rendering_frame_consumed = SDL_FALSE;
|
|
||||||
|
|
||||||
mutex_unlock(frames->mutex);
|
|
||||||
return previous_frame_consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AVFrame *frames_consume_rendered_frame(struct frames *frames) {
|
|
||||||
SDL_assert(!frames->rendering_frame_consumed);
|
|
||||||
frames->rendering_frame_consumed = SDL_TRUE;
|
|
||||||
if (frames->fps_counter.started) {
|
|
||||||
fps_counter_add_rendered_frame(&frames->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(frames->rendering_frame_consumed_cond);
|
|
||||||
#endif
|
|
||||||
return frames->rendering_frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
void frames_stop(struct frames *frames) {
|
|
||||||
#ifdef SKIP_FRAMES
|
|
||||||
(void) frames; // unused
|
|
||||||
#else
|
|
||||||
mutex_lock(frames->mutex);
|
|
||||||
frames->stopped = SDL_TRUE;
|
|
||||||
mutex_unlock(frames->mutex);
|
|
||||||
// wake up blocking wait
|
|
||||||
cond_signal(frames->rendering_frame_consumed_cond);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@ -0,0 +1,110 @@
|
|||||||
|
#include "video_buffer.h"
|
||||||
|
|
||||||
|
#include <SDL2/SDL_assert.h>
|
||||||
|
#include <SDL2/SDL_mutex.h>
|
||||||
|
#include <libavutil/avutil.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "lock_util.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
SDL_bool video_buffer_init(struct video_buffer *vb) {
|
||||||
|
if (!(vb->decoding_frame = av_frame_alloc())) {
|
||||||
|
goto error_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(vb->rendering_frame = av_frame_alloc())) {
|
||||||
|
goto error_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(vb->mutex = SDL_CreateMutex())) {
|
||||||
|
goto error_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef SKIP_FRAMES
|
||||||
|
if (!(vb->rendering_frame_consumed_cond = SDL_CreateCond())) {
|
||||||
|
SDL_DestroyMutex(vb->mutex);
|
||||||
|
goto error_2;
|
||||||
|
}
|
||||||
|
vb->stopped = SDL_FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// there is initially no rendering frame, so consider it has already been
|
||||||
|
// consumed
|
||||||
|
vb->rendering_frame_consumed = SDL_TRUE;
|
||||||
|
fps_counter_init(&vb->fps_counter);
|
||||||
|
|
||||||
|
return SDL_TRUE;
|
||||||
|
|
||||||
|
error_2:
|
||||||
|
av_frame_free(&vb->rendering_frame);
|
||||||
|
error_1:
|
||||||
|
av_frame_free(&vb->decoding_frame);
|
||||||
|
error_0:
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void video_buffer_destroy(struct video_buffer *vb) {
|
||||||
|
#ifndef SKIP_FRAMES
|
||||||
|
SDL_DestroyCond(vb->rendering_frame_consumed_cond);
|
||||||
|
#endif
|
||||||
|
SDL_DestroyMutex(vb->mutex);
|
||||||
|
av_frame_free(&vb->rendering_frame);
|
||||||
|
av_frame_free(&vb->decoding_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void video_buffer_swap_frames(struct video_buffer *vb) {
|
||||||
|
AVFrame *tmp = vb->decoding_frame;
|
||||||
|
vb->decoding_frame = vb->rendering_frame;
|
||||||
|
vb->rendering_frame = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_bool video_buffer_offer_decoded_frame(struct video_buffer *vb) {
|
||||||
|
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->stopped) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
video_buffer_swap_frames(vb);
|
||||||
|
|
||||||
|
SDL_bool previous_frame_consumed = vb->rendering_frame_consumed;
|
||||||
|
vb->rendering_frame_consumed = SDL_FALSE;
|
||||||
|
|
||||||
|
mutex_unlock(vb->mutex);
|
||||||
|
return previous_frame_consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AVFrame *video_buffer_consume_rendered_frame(struct video_buffer *vb) {
|
||||||
|
SDL_assert(!vb->rendering_frame_consumed);
|
||||||
|
vb->rendering_frame_consumed = SDL_TRUE;
|
||||||
|
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
|
||||||
|
return vb->rendering_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void video_buffer_stop(struct video_buffer *vb) {
|
||||||
|
#ifdef SKIP_FRAMES
|
||||||
|
(void) vb; // unused
|
||||||
|
#else
|
||||||
|
mutex_lock(vb->mutex);
|
||||||
|
vb->stopped = SDL_TRUE;
|
||||||
|
mutex_unlock(vb->mutex);
|
||||||
|
// wake up blocking wait
|
||||||
|
cond_signal(vb->rendering_frame_consumed_cond);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
Loading…
Reference in new issue