Rename "frames" to "video_buffer"
It better describes the purpose of the structure.
This commit is contained in:
parent
aacb09a3d6
commit
fff87095d9
11 changed files with 157 additions and 155 deletions
|
@ -8,7 +8,6 @@ src = [
|
||||||
'src/device.c',
|
'src/device.c',
|
||||||
'src/file_handler.c',
|
'src/file_handler.c',
|
||||||
'src/fps_counter.c',
|
'src/fps_counter.c',
|
||||||
'src/frames.c',
|
|
||||||
'src/input_manager.c',
|
'src/input_manager.c',
|
||||||
'src/lock_util.c',
|
'src/lock_util.c',
|
||||||
'src/net.c',
|
'src/net.c',
|
||||||
|
@ -18,6 +17,7 @@ src = [
|
||||||
'src/server.c',
|
'src/server.c',
|
||||||
'src/str_util.c',
|
'src/str_util.c',
|
||||||
'src/tiny_xpm.c',
|
'src/tiny_xpm.c',
|
||||||
|
'src/video_buffer.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
if not get_option('crossbuild_windows')
|
if not get_option('crossbuild_windows')
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "buffer_util.h"
|
#include "buffer_util.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "frames.h"
|
|
||||||
#include "lock_util.h"
|
#include "lock_util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "recorder.h"
|
#include "recorder.h"
|
||||||
|
#include "video_buffer.h"
|
||||||
|
|
||||||
#define BUFSIZE 0x10000
|
#define BUFSIZE 0x10000
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ static int read_raw_packet(void *opaque, uint8_t *buf, int buf_size) {
|
||||||
|
|
||||||
// set the decoded frame as ready for rendering, and notify
|
// set the decoded frame as ready for rendering, and notify
|
||||||
static void push_frame(struct decoder *decoder) {
|
static void push_frame(struct decoder *decoder) {
|
||||||
SDL_bool previous_frame_consumed = frames_offer_decoded_frame(decoder->frames);
|
SDL_bool previous_frame_consumed = video_buffer_offer_decoded_frame(decoder->video_buffer);
|
||||||
if (!previous_frame_consumed) {
|
if (!previous_frame_consumed) {
|
||||||
// the previous EVENT_NEW_FRAME will consume this frame
|
// the previous EVENT_NEW_FRAME will consume this frame
|
||||||
return;
|
return;
|
||||||
|
@ -227,7 +227,7 @@ static int run_decoder(void *data) {
|
||||||
LOGE("Could not send video packet: %d", ret);
|
LOGE("Could not send video packet: %d", ret);
|
||||||
goto run_quit;
|
goto run_quit;
|
||||||
}
|
}
|
||||||
ret = avcodec_receive_frame(codec_ctx, decoder->frames->decoding_frame);
|
ret = avcodec_receive_frame(codec_ctx, decoder->video_buffer->decoding_frame);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
// a frame was received
|
// a frame was received
|
||||||
push_frame(decoder);
|
push_frame(decoder);
|
||||||
|
@ -239,7 +239,7 @@ static int run_decoder(void *data) {
|
||||||
#else
|
#else
|
||||||
while (packet.size > 0) {
|
while (packet.size > 0) {
|
||||||
int got_picture;
|
int got_picture;
|
||||||
int len = avcodec_decode_video2(codec_ctx, decoder->frames->decoding_frame, &got_picture, &packet);
|
int len = avcodec_decode_video2(codec_ctx, decoder->video_buffer->decoding_frame, &got_picture, &packet);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
LOGE("Could not decode video packet: %d", len);
|
LOGE("Could not decode video packet: %d", len);
|
||||||
av_packet_unref(&packet);
|
av_packet_unref(&packet);
|
||||||
|
@ -298,9 +298,9 @@ run_end:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decoder_init(struct decoder *decoder, struct frames *frames,
|
void decoder_init(struct decoder *decoder, struct video_buffer *vb,
|
||||||
socket_t video_socket, struct recorder *recorder) {
|
socket_t video_socket, struct recorder *recorder) {
|
||||||
decoder->frames = frames;
|
decoder->video_buffer = vb;
|
||||||
decoder->video_socket = video_socket;
|
decoder->video_socket = video_socket;
|
||||||
decoder->recorder = recorder;
|
decoder->recorder = recorder;
|
||||||
}
|
}
|
||||||
|
@ -317,7 +317,7 @@ SDL_bool decoder_start(struct decoder *decoder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void decoder_stop(struct decoder *decoder) {
|
void decoder_stop(struct decoder *decoder) {
|
||||||
frames_stop(decoder->frames);
|
video_buffer_stop(decoder->video_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void decoder_join(struct decoder *decoder) {
|
void decoder_join(struct decoder *decoder) {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
struct frames;
|
struct video_buffer;
|
||||||
|
|
||||||
struct frame_meta {
|
struct frame_meta {
|
||||||
uint64_t pts;
|
uint64_t pts;
|
||||||
|
@ -15,7 +15,7 @@ struct frame_meta {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct decoder {
|
struct decoder {
|
||||||
struct frames *frames;
|
struct video_buffer *video_buffer;
|
||||||
socket_t video_socket;
|
socket_t video_socket;
|
||||||
SDL_Thread *thread;
|
SDL_Thread *thread;
|
||||||
struct recorder *recorder;
|
struct recorder *recorder;
|
||||||
|
@ -26,7 +26,7 @@ struct decoder {
|
||||||
} receiver_state;
|
} receiver_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
void decoder_init(struct decoder *decoder, struct frames *frames,
|
void decoder_init(struct decoder *decoder, struct video_buffer *vb,
|
||||||
socket_t video_socket, struct recorder *recoder);
|
socket_t video_socket, struct recorder *recoder);
|
||||||
SDL_bool decoder_start(struct decoder *decoder);
|
SDL_bool decoder_start(struct decoder *decoder);
|
||||||
void decoder_stop(struct decoder *decoder);
|
void decoder_stop(struct decoder *decoder);
|
||||||
|
|
110
app/src/frames.c
110
app/src/frames.c
|
@ -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
|
|
||||||
}
|
|
|
@ -114,16 +114,16 @@ static void collapse_notification_panel(struct controller *controller) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void switch_fps_counter_state(struct frames *frames) {
|
static void switch_fps_counter_state(struct video_buffer *vb) {
|
||||||
mutex_lock(frames->mutex);
|
mutex_lock(vb->mutex);
|
||||||
if (frames->fps_counter.started) {
|
if (vb->fps_counter.started) {
|
||||||
LOGI("FPS counter stopped");
|
LOGI("FPS counter stopped");
|
||||||
fps_counter_stop(&frames->fps_counter);
|
fps_counter_stop(&vb->fps_counter);
|
||||||
} else {
|
} else {
|
||||||
LOGI("FPS counter started");
|
LOGI("FPS counter started");
|
||||||
fps_counter_start(&frames->fps_counter);
|
fps_counter_start(&vb->fps_counter);
|
||||||
}
|
}
|
||||||
mutex_unlock(frames->mutex);
|
mutex_unlock(vb->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clipboard_paste(struct controller *controller) {
|
static void clipboard_paste(struct controller *controller) {
|
||||||
|
@ -260,7 +260,7 @@ void input_manager_process_key(struct input_manager *input_manager,
|
||||||
case SDLK_i:
|
case SDLK_i:
|
||||||
if (ctrl && !meta && !shift && !repeat
|
if (ctrl && !meta && !shift && !repeat
|
||||||
&& event->type == SDL_KEYDOWN) {
|
&& event->type == SDL_KEYDOWN) {
|
||||||
switch_fps_counter_state(input_manager->frames);
|
switch_fps_counter_state(input_manager->video_buffer);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDLK_n:
|
case SDLK_n:
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "fps_counter.h"
|
#include "fps_counter.h"
|
||||||
#include "frames.h"
|
#include "video_buffer.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
|
||||||
struct input_manager {
|
struct input_manager {
|
||||||
struct controller *controller;
|
struct controller *controller;
|
||||||
struct frames *frames;
|
struct video_buffer *video_buffer;
|
||||||
struct screen *screen;
|
struct screen *screen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "file_handler.h"
|
#include "file_handler.h"
|
||||||
#include "frames.h"
|
|
||||||
#include "fps_counter.h"
|
#include "fps_counter.h"
|
||||||
#include "input_manager.h"
|
#include "input_manager.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
@ -24,10 +23,11 @@
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "tiny_xpm.h"
|
#include "tiny_xpm.h"
|
||||||
|
#include "video_buffer.h"
|
||||||
|
|
||||||
static struct server server = SERVER_INITIALIZER;
|
static struct server server = SERVER_INITIALIZER;
|
||||||
static struct screen screen = SCREEN_INITIALIZER;
|
static struct screen screen = SCREEN_INITIALIZER;
|
||||||
static struct frames frames;
|
static struct video_buffer video_buffer;
|
||||||
static struct decoder decoder;
|
static struct decoder decoder;
|
||||||
static struct controller controller;
|
static struct controller controller;
|
||||||
static struct file_handler file_handler;
|
static struct file_handler file_handler;
|
||||||
|
@ -35,7 +35,7 @@ static struct recorder recorder;
|
||||||
|
|
||||||
static struct input_manager input_manager = {
|
static struct input_manager input_manager = {
|
||||||
.controller = &controller,
|
.controller = &controller,
|
||||||
.frames = &frames,
|
.video_buffer = &video_buffer,
|
||||||
.screen = &screen,
|
.screen = &screen,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ static SDL_bool event_loop(void) {
|
||||||
// this is the very first frame, show the window
|
// this is the very first frame, show the window
|
||||||
screen_show_window(&screen);
|
screen_show_window(&screen);
|
||||||
}
|
}
|
||||||
if (!screen_update_frame(&screen, &frames)) {
|
if (!screen_update_frame(&screen, &video_buffer)) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -215,7 +215,7 @@ SDL_bool scrcpy(const struct scrcpy_options *options) {
|
||||||
goto finally_destroy_server;
|
goto finally_destroy_server;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!frames_init(&frames)) {
|
if (!video_buffer_init(&video_buffer)) {
|
||||||
server_stop(&server);
|
server_stop(&server);
|
||||||
ret = SDL_FALSE;
|
ret = SDL_FALSE;
|
||||||
goto finally_destroy_server;
|
goto finally_destroy_server;
|
||||||
|
@ -224,7 +224,7 @@ SDL_bool scrcpy(const struct scrcpy_options *options) {
|
||||||
if (!file_handler_init(&file_handler, server.serial)) {
|
if (!file_handler_init(&file_handler, server.serial)) {
|
||||||
ret = SDL_FALSE;
|
ret = SDL_FALSE;
|
||||||
server_stop(&server);
|
server_stop(&server);
|
||||||
goto finally_destroy_frames;
|
goto finally_destroy_video_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct recorder *rec = NULL;
|
struct recorder *rec = NULL;
|
||||||
|
@ -242,7 +242,7 @@ SDL_bool scrcpy(const struct scrcpy_options *options) {
|
||||||
|
|
||||||
av_log_set_callback(av_log_callback);
|
av_log_set_callback(av_log_callback);
|
||||||
|
|
||||||
decoder_init(&decoder, &frames, device_socket, rec);
|
decoder_init(&decoder, &video_buffer, device_socket, rec);
|
||||||
|
|
||||||
// now we consumed the header values, the socket receives the video stream
|
// now we consumed the header values, the socket receives the video stream
|
||||||
// start the decoder
|
// start the decoder
|
||||||
|
@ -299,8 +299,8 @@ finally_destroy_recorder:
|
||||||
if (options->record_filename) {
|
if (options->record_filename) {
|
||||||
recorder_destroy(&recorder);
|
recorder_destroy(&recorder);
|
||||||
}
|
}
|
||||||
finally_destroy_frames:
|
finally_destroy_video_buffer:
|
||||||
frames_destroy(&frames);
|
video_buffer_destroy(&video_buffer);
|
||||||
finally_destroy_server:
|
finally_destroy_server:
|
||||||
if (options->show_touches) {
|
if (options->show_touches) {
|
||||||
if (!show_touches_waited) {
|
if (!show_touches_waited) {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "lock_util.h"
|
#include "lock_util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "tiny_xpm.h"
|
#include "tiny_xpm.h"
|
||||||
|
#include "video_buffer.h"
|
||||||
|
|
||||||
#define DISPLAY_MARGINS 96
|
#define DISPLAY_MARGINS 96
|
||||||
|
|
||||||
|
@ -262,16 +263,16 @@ static void update_texture(struct screen *screen, const AVFrame *frame) {
|
||||||
frame->data[2], frame->linesize[2]);
|
frame->data[2], frame->linesize[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_bool screen_update_frame(struct screen *screen, struct frames *frames) {
|
SDL_bool screen_update_frame(struct screen *screen, struct video_buffer *vb) {
|
||||||
mutex_lock(frames->mutex);
|
mutex_lock(vb->mutex);
|
||||||
const AVFrame *frame = frames_consume_rendered_frame(frames);
|
const AVFrame *frame = video_buffer_consume_rendered_frame(vb);
|
||||||
struct size new_frame_size = {frame->width, frame->height};
|
struct size new_frame_size = {frame->width, frame->height};
|
||||||
if (!prepare_for_frame(screen, new_frame_size)) {
|
if (!prepare_for_frame(screen, new_frame_size)) {
|
||||||
mutex_unlock(frames->mutex);
|
mutex_unlock(vb->mutex);
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
update_texture(screen, frame);
|
update_texture(screen, frame);
|
||||||
mutex_unlock(frames->mutex);
|
mutex_unlock(vb->mutex);
|
||||||
|
|
||||||
screen_render(screen);
|
screen_render(screen);
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
#include <libavformat/avformat.h>
|
#include <libavformat/avformat.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "frames.h"
|
|
||||||
|
struct video_buffer;
|
||||||
|
|
||||||
struct screen {
|
struct screen {
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
|
@ -53,7 +54,7 @@ void screen_show_window(struct screen *screen);
|
||||||
void screen_destroy(struct screen *screen);
|
void screen_destroy(struct screen *screen);
|
||||||
|
|
||||||
// resize if necessary and write the rendered frame into the texture
|
// resize if necessary and write the rendered frame into the texture
|
||||||
SDL_bool screen_update_frame(struct screen *screen, struct frames *frames);
|
SDL_bool screen_update_frame(struct screen *screen, struct video_buffer *vb);
|
||||||
|
|
||||||
// render the texture to the renderer
|
// render the texture to the renderer
|
||||||
void screen_render(struct screen *screen);
|
void screen_render(struct screen *screen);
|
||||||
|
|
110
app/src/video_buffer.c
Normal file
110
app/src/video_buffer.c
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef FRAMES_H
|
#ifndef VIDEO_BUFFER_H
|
||||||
#define FRAMES_H
|
#define VIDEO_BUFFER_H
|
||||||
|
|
||||||
#include <SDL2/SDL_mutex.h>
|
#include <SDL2/SDL_mutex.h>
|
||||||
#include <SDL2/SDL_stdinc.h>
|
#include <SDL2/SDL_stdinc.h>
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
// forward declarations
|
// forward declarations
|
||||||
typedef struct AVFrame AVFrame;
|
typedef struct AVFrame AVFrame;
|
||||||
|
|
||||||
struct frames {
|
struct video_buffer {
|
||||||
AVFrame *decoding_frame;
|
AVFrame *decoding_frame;
|
||||||
AVFrame *rendering_frame;
|
AVFrame *rendering_frame;
|
||||||
SDL_mutex *mutex;
|
SDL_mutex *mutex;
|
||||||
|
@ -22,21 +22,21 @@ struct frames {
|
||||||
struct fps_counter fps_counter;
|
struct fps_counter fps_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
SDL_bool frames_init(struct frames *frames);
|
SDL_bool video_buffer_init(struct video_buffer *vb);
|
||||||
void frames_destroy(struct frames *frames);
|
void video_buffer_destroy(struct video_buffer *vb);
|
||||||
|
|
||||||
// set the decoder frame as ready for rendering
|
// set the decoded frame as ready for rendering
|
||||||
// this function locks frames->mutex during its execution
|
// this function locks frames->mutex during its execution
|
||||||
// returns true if the previous frame had been consumed
|
// returns true if the previous frame had been consumed
|
||||||
SDL_bool frames_offer_decoded_frame(struct frames *frames);
|
SDL_bool video_buffer_offer_decoded_frame(struct video_buffer *vb);
|
||||||
|
|
||||||
// mark the rendering frame as consumed and return it
|
// mark the rendering frame as consumed and return it
|
||||||
// MUST be called with frames->mutex locked!!!
|
// MUST be called with frames->mutex locked!!!
|
||||||
// the caller is expected to render the returned frame to some texture before
|
// the caller is expected to render the returned frame to some texture before
|
||||||
// unlocking frames->mutex
|
// unlocking frames->mutex
|
||||||
const AVFrame *frames_consume_rendered_frame(struct frames *frames);
|
const AVFrame *video_buffer_consume_rendered_frame(struct video_buffer *vb);
|
||||||
|
|
||||||
// wake up and avoid any blocking call
|
// wake up and avoid any blocking call
|
||||||
void frames_stop(struct frames *frames);
|
void video_buffer_stop(struct video_buffer *vb);
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in a new issue