From 8d30d40b7958fdfad68e7a628f4e62b31451fa5e Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Wed, 7 Feb 2018 12:25:52 +0100 Subject: [PATCH] Make SKIP_FRAMES a compilation flag The skip_frames flag was a non-configurable runtime flag. Since it is not exposed to the user, there is no need for a (possible) runtime cost. For testing purpose, we still want it to be configurable, so make it a compilation flag. --- app/meson.build | 5 +++++ app/src/decoder.c | 15 ++++++++++----- app/src/decoder.h | 1 - app/src/frames.c | 9 ++++++--- app/src/frames.h | 4 ++++ app/src/scrcpy.c | 9 +++++---- 6 files changed, 30 insertions(+), 13 deletions(-) diff --git a/app/meson.build b/app/meson.build index 4536aab4..e3ee90b9 100644 --- a/app/meson.build +++ b/app/meson.build @@ -44,6 +44,11 @@ conf.set('DEFAULT_MAX_SIZE', '0') # 0: unlimited # overridden by option --bit-rate conf.set('DEFAULT_BIT_RATE', '4000000') # 4Mbps +# whether the app should always display the most recent available frame, even +# if the previous one has not been displayed +# SKIP_FRAMES improves latency at the cost of framerate +conf.set('SKIP_FRAMES', true) + configure_file(configuration: conf, output: 'config.h') executable('scrcpy', src, dependencies: dependencies) diff --git a/app/src/decoder.c b/app/src/decoder.c index e9f50645..33a3b097 100644 --- a/app/src/decoder.c +++ b/app/src/decoder.c @@ -6,6 +6,7 @@ #include #include +#include "config.h" #include "events.h" #include "frames.h" #include "lockutil.h" @@ -22,13 +23,17 @@ static int read_packet(void *opaque, uint8_t *buf, int buf_size) { static void push_frame(struct decoder *decoder) { struct frames *frames = decoder->frames; mutex_lock(frames->mutex); - if (!decoder->skip_frames) { - while (!frames->rendering_frame_consumed) { - cond_wait(frames->rendering_frame_consumed_cond, frames->mutex); - } - } else if (!frames->rendering_frame_consumed) { +#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) { + cond_wait(frames->rendering_frame_consumed_cond, frames->mutex); + } +#else + if (!frames->rendering_frame_consumed) { SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "Skip frame"); } +#endif frames_swap(frames); frames->rendering_frame_consumed = SDL_FALSE; diff --git a/app/src/decoder.h b/app/src/decoder.h index a76dd1c7..9c07ab22 100644 --- a/app/src/decoder.h +++ b/app/src/decoder.h @@ -11,7 +11,6 @@ struct decoder { TCPsocket video_socket; SDL_Thread *thread; SDL_mutex *mutex; - SDL_bool skip_frames; }; SDL_bool decoder_start(struct decoder *decoder); diff --git a/app/src/frames.c b/app/src/frames.c index f9a01777..cb8d7e79 100644 --- a/app/src/frames.c +++ b/app/src/frames.c @@ -17,16 +17,17 @@ SDL_bool frames_init(struct frames *frames) { goto error_2; } +#ifndef SKIP_FRAMES if (!(frames->rendering_frame_consumed_cond = SDL_CreateCond())) { - goto error_3; + SDL_DestroyMutex(frames->mutex); + goto error_2; } +#endif frames->rendering_frame_consumed = SDL_TRUE; return SDL_TRUE; -error_3: - SDL_DestroyMutex(frames->mutex); error_2: av_frame_free(&frames->rendering_frame); error_1: @@ -36,7 +37,9 @@ error_0: } 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); diff --git a/app/src/frames.h b/app/src/frames.h index 66ee2a58..ba4d5fe7 100644 --- a/app/src/frames.h +++ b/app/src/frames.h @@ -4,6 +4,8 @@ #include #include +#include "config.h" + // forward declarations typedef struct AVFrame AVFrame; @@ -11,7 +13,9 @@ struct frames { AVFrame *decoding_frame; AVFrame *rendering_frame; SDL_mutex *mutex; +#ifndef SKIP_FRAMES SDL_cond *rendering_frame_consumed_cond; +#endif SDL_bool rendering_frame_consumed; }; diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index be9c17d9..19daa67d 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -336,9 +336,11 @@ static SDL_bool handle_new_frame(void) { mutex_lock(frames.mutex); AVFrame *frame = frames.rendering_frame; frames.rendering_frame_consumed = SDL_TRUE; - if (!decoder.skip_frames) { - cond_signal(frames.rendering_frame_consumed_cond); - } +#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 struct size current_frame_size = {frame->width, frame->height}; if (!prepare_for_frame(window, renderer, &texture, frame_size, current_frame_size)) { @@ -583,7 +585,6 @@ SDL_bool scrcpy(const char *serial, Uint16 local_port, Uint16 max_size, Uint32 b decoder.frames = &frames; decoder.video_socket = device_socket; - decoder.skip_frames = SDL_TRUE; // now we consumed the header values, the socket receives the video stream // start the decoder