From fff87095d95c257f9d6cab34f605da65d0bf478d Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sat, 2 Mar 2019 15:16:55 +0100 Subject: [PATCH] Rename "frames" to "video_buffer" It better describes the purpose of the structure. --- app/meson.build | 2 +- app/src/decoder.c | 14 ++-- app/src/decoder.h | 6 +- app/src/frames.c | 110 --------------------------- app/src/input_manager.c | 14 ++-- app/src/input_manager.h | 4 +- app/src/scrcpy.c | 18 ++--- app/src/screen.c | 11 +-- app/src/screen.h | 5 +- app/src/video_buffer.c | 110 +++++++++++++++++++++++++++ app/src/{frames.h => video_buffer.h} | 18 ++--- 11 files changed, 157 insertions(+), 155 deletions(-) delete mode 100644 app/src/frames.c create mode 100644 app/src/video_buffer.c rename app/src/{frames.h => video_buffer.h} (65%) diff --git a/app/meson.build b/app/meson.build index 3286fde1..4c4c807b 100644 --- a/app/meson.build +++ b/app/meson.build @@ -8,7 +8,6 @@ src = [ 'src/device.c', 'src/file_handler.c', 'src/fps_counter.c', - 'src/frames.c', 'src/input_manager.c', 'src/lock_util.c', 'src/net.c', @@ -18,6 +17,7 @@ src = [ 'src/server.c', 'src/str_util.c', 'src/tiny_xpm.c', + 'src/video_buffer.c', ] if not get_option('crossbuild_windows') diff --git a/app/src/decoder.c b/app/src/decoder.c index 9b3ca2f1..adc59a30 100644 --- a/app/src/decoder.c +++ b/app/src/decoder.c @@ -12,10 +12,10 @@ #include "config.h" #include "buffer_util.h" #include "events.h" -#include "frames.h" #include "lock_util.h" #include "log.h" #include "recorder.h" +#include "video_buffer.h" #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 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) { // the previous EVENT_NEW_FRAME will consume this frame return; @@ -227,7 +227,7 @@ static int run_decoder(void *data) { LOGE("Could not send video packet: %d", ret); 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) { // a frame was received push_frame(decoder); @@ -239,7 +239,7 @@ static int run_decoder(void *data) { #else while (packet.size > 0) { 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) { LOGE("Could not decode video packet: %d", len); av_packet_unref(&packet); @@ -298,9 +298,9 @@ run_end: 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) { - decoder->frames = frames; + decoder->video_buffer = vb; decoder->video_socket = video_socket; decoder->recorder = recorder; } @@ -317,7 +317,7 @@ SDL_bool decoder_start(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) { diff --git a/app/src/decoder.h b/app/src/decoder.h index f266d9ba..240dab00 100644 --- a/app/src/decoder.h +++ b/app/src/decoder.h @@ -7,7 +7,7 @@ #include "common.h" #include "net.h" -struct frames; +struct video_buffer; struct frame_meta { uint64_t pts; @@ -15,7 +15,7 @@ struct frame_meta { }; struct decoder { - struct frames *frames; + struct video_buffer *video_buffer; socket_t video_socket; SDL_Thread *thread; struct recorder *recorder; @@ -26,7 +26,7 @@ struct decoder { } 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); SDL_bool decoder_start(struct decoder *decoder); void decoder_stop(struct decoder *decoder); diff --git a/app/src/frames.c b/app/src/frames.c deleted file mode 100644 index 514d4788..00000000 --- a/app/src/frames.c +++ /dev/null @@ -1,110 +0,0 @@ -#include "frames.h" - -#include -#include -#include -#include - -#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 -} diff --git a/app/src/input_manager.c b/app/src/input_manager.c index ef3d372c..35e029f0 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -114,16 +114,16 @@ static void collapse_notification_panel(struct controller *controller) { } } -static void switch_fps_counter_state(struct frames *frames) { - mutex_lock(frames->mutex); - if (frames->fps_counter.started) { +static void switch_fps_counter_state(struct video_buffer *vb) { + mutex_lock(vb->mutex); + if (vb->fps_counter.started) { LOGI("FPS counter stopped"); - fps_counter_stop(&frames->fps_counter); + fps_counter_stop(&vb->fps_counter); } else { 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) { @@ -260,7 +260,7 @@ void input_manager_process_key(struct input_manager *input_manager, case SDLK_i: if (ctrl && !meta && !shift && !repeat && event->type == SDL_KEYDOWN) { - switch_fps_counter_state(input_manager->frames); + switch_fps_counter_state(input_manager->video_buffer); } return; case SDLK_n: diff --git a/app/src/input_manager.h b/app/src/input_manager.h index b9037aa1..7aed1793 100644 --- a/app/src/input_manager.h +++ b/app/src/input_manager.h @@ -4,12 +4,12 @@ #include "common.h" #include "controller.h" #include "fps_counter.h" -#include "frames.h" +#include "video_buffer.h" #include "screen.h" struct input_manager { struct controller *controller; - struct frames *frames; + struct video_buffer *video_buffer; struct screen *screen; }; diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 9a1c29d5..fa347bf5 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -14,7 +14,6 @@ #include "device.h" #include "events.h" #include "file_handler.h" -#include "frames.h" #include "fps_counter.h" #include "input_manager.h" #include "log.h" @@ -24,10 +23,11 @@ #include "screen.h" #include "server.h" #include "tiny_xpm.h" +#include "video_buffer.h" static struct server server = SERVER_INITIALIZER; static struct screen screen = SCREEN_INITIALIZER; -static struct frames frames; +static struct video_buffer video_buffer; static struct decoder decoder; static struct controller controller; static struct file_handler file_handler; @@ -35,7 +35,7 @@ static struct recorder recorder; static struct input_manager input_manager = { .controller = &controller, - .frames = &frames, + .video_buffer = &video_buffer, .screen = &screen, }; @@ -82,7 +82,7 @@ static SDL_bool event_loop(void) { // this is the very first frame, show the window screen_show_window(&screen); } - if (!screen_update_frame(&screen, &frames)) { + if (!screen_update_frame(&screen, &video_buffer)) { return SDL_FALSE; } break; @@ -215,7 +215,7 @@ SDL_bool scrcpy(const struct scrcpy_options *options) { goto finally_destroy_server; } - if (!frames_init(&frames)) { + if (!video_buffer_init(&video_buffer)) { server_stop(&server); ret = SDL_FALSE; goto finally_destroy_server; @@ -224,7 +224,7 @@ SDL_bool scrcpy(const struct scrcpy_options *options) { if (!file_handler_init(&file_handler, server.serial)) { ret = SDL_FALSE; server_stop(&server); - goto finally_destroy_frames; + goto finally_destroy_video_buffer; } struct recorder *rec = NULL; @@ -242,7 +242,7 @@ SDL_bool scrcpy(const struct scrcpy_options *options) { 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 // start the decoder @@ -299,8 +299,8 @@ finally_destroy_recorder: if (options->record_filename) { recorder_destroy(&recorder); } -finally_destroy_frames: - frames_destroy(&frames); +finally_destroy_video_buffer: + video_buffer_destroy(&video_buffer); finally_destroy_server: if (options->show_touches) { if (!show_touches_waited) { diff --git a/app/src/screen.c b/app/src/screen.c index 1632e27f..54920c94 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -8,6 +8,7 @@ #include "lock_util.h" #include "log.h" #include "tiny_xpm.h" +#include "video_buffer.h" #define DISPLAY_MARGINS 96 @@ -262,16 +263,16 @@ static void update_texture(struct screen *screen, const AVFrame *frame) { frame->data[2], frame->linesize[2]); } -SDL_bool screen_update_frame(struct screen *screen, struct frames *frames) { - mutex_lock(frames->mutex); - const AVFrame *frame = frames_consume_rendered_frame(frames); +SDL_bool screen_update_frame(struct screen *screen, struct video_buffer *vb) { + mutex_lock(vb->mutex); + const AVFrame *frame = video_buffer_consume_rendered_frame(vb); struct size new_frame_size = {frame->width, frame->height}; if (!prepare_for_frame(screen, new_frame_size)) { - mutex_unlock(frames->mutex); + mutex_unlock(vb->mutex); return SDL_FALSE; } update_texture(screen, frame); - mutex_unlock(frames->mutex); + mutex_unlock(vb->mutex); screen_render(screen); return SDL_TRUE; diff --git a/app/src/screen.h b/app/src/screen.h index 05729a12..4a13bfca 100644 --- a/app/src/screen.h +++ b/app/src/screen.h @@ -5,7 +5,8 @@ #include #include "common.h" -#include "frames.h" + +struct video_buffer; struct screen { SDL_Window *window; @@ -53,7 +54,7 @@ void screen_show_window(struct screen *screen); void screen_destroy(struct screen *screen); // 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 void screen_render(struct screen *screen); diff --git a/app/src/video_buffer.c b/app/src/video_buffer.c new file mode 100644 index 00000000..f2a288d4 --- /dev/null +++ b/app/src/video_buffer.c @@ -0,0 +1,110 @@ +#include "video_buffer.h" + +#include +#include +#include +#include + +#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 +} diff --git a/app/src/frames.h b/app/src/video_buffer.h similarity index 65% rename from app/src/frames.h rename to app/src/video_buffer.h index 437838fc..5c19557d 100644 --- a/app/src/frames.h +++ b/app/src/video_buffer.h @@ -1,5 +1,5 @@ -#ifndef FRAMES_H -#define FRAMES_H +#ifndef VIDEO_BUFFER_H +#define VIDEO_BUFFER_H #include #include @@ -10,7 +10,7 @@ // forward declarations typedef struct AVFrame AVFrame; -struct frames { +struct video_buffer { AVFrame *decoding_frame; AVFrame *rendering_frame; SDL_mutex *mutex; @@ -22,21 +22,21 @@ struct frames { struct fps_counter fps_counter; }; -SDL_bool frames_init(struct frames *frames); -void frames_destroy(struct frames *frames); +SDL_bool video_buffer_init(struct video_buffer *vb); +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 // 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 // MUST be called with frames->mutex locked!!! // the caller is expected to render the returned frame to some texture before // 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 -void frames_stop(struct frames *frames); +void video_buffer_stop(struct video_buffer *vb); #endif