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.
This commit is contained in:
Romain Vimont 2018-02-07 12:25:52 +01:00
parent 53ff1aa410
commit 8d30d40b79
6 changed files with 30 additions and 13 deletions

View file

@ -44,6 +44,11 @@ conf.set('DEFAULT_MAX_SIZE', '0') # 0: unlimited
# overridden by option --bit-rate # overridden by option --bit-rate
conf.set('DEFAULT_BIT_RATE', '4000000') # 4Mbps 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') configure_file(configuration: conf, output: 'config.h')
executable('scrcpy', src, dependencies: dependencies) executable('scrcpy', src, dependencies: dependencies)

View file

@ -6,6 +6,7 @@
#include <SDL2/SDL_thread.h> #include <SDL2/SDL_thread.h>
#include <unistd.h> #include <unistd.h>
#include "config.h"
#include "events.h" #include "events.h"
#include "frames.h" #include "frames.h"
#include "lockutil.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) { static void push_frame(struct decoder *decoder) {
struct frames *frames = decoder->frames; struct frames *frames = decoder->frames;
mutex_lock(frames->mutex); mutex_lock(frames->mutex);
if (!decoder->skip_frames) { #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) { while (!frames->rendering_frame_consumed) {
cond_wait(frames->rendering_frame_consumed_cond, frames->mutex); cond_wait(frames->rendering_frame_consumed_cond, frames->mutex);
} }
} else if (!frames->rendering_frame_consumed) { #else
if (!frames->rendering_frame_consumed) {
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "Skip frame"); SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "Skip frame");
} }
#endif
frames_swap(frames); frames_swap(frames);
frames->rendering_frame_consumed = SDL_FALSE; frames->rendering_frame_consumed = SDL_FALSE;

View file

@ -11,7 +11,6 @@ struct decoder {
TCPsocket video_socket; TCPsocket video_socket;
SDL_Thread *thread; SDL_Thread *thread;
SDL_mutex *mutex; SDL_mutex *mutex;
SDL_bool skip_frames;
}; };
SDL_bool decoder_start(struct decoder *decoder); SDL_bool decoder_start(struct decoder *decoder);

View file

@ -17,16 +17,17 @@ SDL_bool frames_init(struct frames *frames) {
goto error_2; goto error_2;
} }
#ifndef SKIP_FRAMES
if (!(frames->rendering_frame_consumed_cond = SDL_CreateCond())) { 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; frames->rendering_frame_consumed = SDL_TRUE;
return SDL_TRUE; return SDL_TRUE;
error_3:
SDL_DestroyMutex(frames->mutex);
error_2: error_2:
av_frame_free(&frames->rendering_frame); av_frame_free(&frames->rendering_frame);
error_1: error_1:
@ -36,7 +37,9 @@ error_0:
} }
void frames_destroy(struct frames *frames) { void frames_destroy(struct frames *frames) {
#ifndef SKIP_FRAMES
SDL_DestroyCond(frames->rendering_frame_consumed_cond); SDL_DestroyCond(frames->rendering_frame_consumed_cond);
#endif
SDL_DestroyMutex(frames->mutex); SDL_DestroyMutex(frames->mutex);
av_frame_free(&frames->rendering_frame); av_frame_free(&frames->rendering_frame);
av_frame_free(&frames->decoding_frame); av_frame_free(&frames->decoding_frame);

View file

@ -4,6 +4,8 @@
#include <SDL2/SDL_mutex.h> #include <SDL2/SDL_mutex.h>
#include <SDL2/SDL_stdinc.h> #include <SDL2/SDL_stdinc.h>
#include "config.h"
// forward declarations // forward declarations
typedef struct AVFrame AVFrame; typedef struct AVFrame AVFrame;
@ -11,7 +13,9 @@ struct frames {
AVFrame *decoding_frame; AVFrame *decoding_frame;
AVFrame *rendering_frame; AVFrame *rendering_frame;
SDL_mutex *mutex; SDL_mutex *mutex;
#ifndef SKIP_FRAMES
SDL_cond *rendering_frame_consumed_cond; SDL_cond *rendering_frame_consumed_cond;
#endif
SDL_bool rendering_frame_consumed; SDL_bool rendering_frame_consumed;
}; };

View file

@ -336,9 +336,11 @@ static SDL_bool handle_new_frame(void) {
mutex_lock(frames.mutex); mutex_lock(frames.mutex);
AVFrame *frame = frames.rendering_frame; AVFrame *frame = frames.rendering_frame;
frames.rendering_frame_consumed = SDL_TRUE; frames.rendering_frame_consumed = SDL_TRUE;
if (!decoder.skip_frames) { #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); cond_signal(frames.rendering_frame_consumed_cond);
} #endif
struct size current_frame_size = {frame->width, frame->height}; struct size current_frame_size = {frame->width, frame->height};
if (!prepare_for_frame(window, renderer, &texture, frame_size, current_frame_size)) { 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.frames = &frames;
decoder.video_socket = device_socket; decoder.video_socket = device_socket;
decoder.skip_frames = SDL_TRUE;
// 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