From 26249566f2c6ac8a1df7eccf0bb981af6617bb17 Mon Sep 17 00:00:00 2001 From: Zsolt Donca Date: Fri, 25 Dec 2020 18:20:07 +0200 Subject: [PATCH] Introduce an optional CLI argument for the max FPS The default value is 0, meaning unlimited FPS; this also disables the measuring and logging of the average FPS. --- include/fps_limit.h | 2 +- include/screencast_common.h | 2 ++ include/xdpw.h | 2 +- src/core/main.c | 10 ++++++++-- src/screencast/fps_limit.c | 5 ++--- src/screencast/screencast.c | 4 +++- src/screencast/wlr_screencast.c | 2 +- 7 files changed, 18 insertions(+), 9 deletions(-) diff --git a/include/fps_limit.h b/include/fps_limit.h index edf877ed..509d28d4 100644 --- a/include/fps_limit.h +++ b/include/fps_limit.h @@ -10,6 +10,6 @@ struct fps_limit_state { uint32_t fps_measurement_frame_count; }; -void fps_limit_apply(struct fps_limit_state* state); +void fps_limit_apply(struct fps_limit_state* state, double max_fps); #endif diff --git a/include/screencast_common.h b/include/screencast_common.h index e6fd164d..38db03db 100644 --- a/include/screencast_common.h +++ b/include/screencast_common.h @@ -61,6 +61,7 @@ struct xdpw_screencast_context { // cli options const char *output_name; + double max_fps; // sessions struct wl_list screencast_instances; @@ -95,6 +96,7 @@ struct xdpw_screencast_instance { bool quit; // fps limit + double max_fps; // 0 means no limit struct fps_limit_state fps_limit; }; diff --git a/include/xdpw.h b/include/xdpw.h index 2d556d77..053b5506 100644 --- a/include/xdpw.h +++ b/include/xdpw.h @@ -41,7 +41,7 @@ enum { }; int xdpw_screenshot_init(struct xdpw_state *state); -int xdpw_screencast_init(struct xdpw_state *state, const char *output_name); +int xdpw_screencast_init(struct xdpw_state *state, const char *output_name, double max_fps); struct xdpw_request *xdpw_request_create(sd_bus *bus, const char *object_path); void xdpw_request_destroy(struct xdpw_request *req); diff --git a/src/core/main.c b/src/core/main.c index 5d164496..d4d797ac 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -25,6 +25,7 @@ static int xdpw_usage(FILE* stream, int rc) { " -o, --output= Select output to capture.\n" " metadata (performs no conversion).\n" " -r, --replace Replace a running instance.\n" + " -f, --max-fps= Set the FPS limit (default 0, no limit).\n" " -h, --help Get help (this text).\n" "\n"; @@ -42,12 +43,14 @@ int main(int argc, char *argv[]) { const char* output_name = NULL; enum LOGLEVEL loglevel = ERROR; bool replace = false; + double max_fps = 0; - static const char* shortopts = "l:o:rh"; + static const char* shortopts = "l:o:f:rh"; static const struct option longopts[] = { { "loglevel", required_argument, NULL, 'l' }, { "output", required_argument, NULL, 'o' }, { "replace", no_argument, NULL, 'r' }, + { "max-fps", required_argument, NULL, 'f' }, { "help", no_argument, NULL, 'h' }, { NULL, 0, NULL, 0 } }; @@ -67,6 +70,9 @@ int main(int argc, char *argv[]) { case 'r': replace = true; break; + case 'f': + max_fps = atof(optarg); + break; case 'h': return xdpw_usage(stdout, EXIT_SUCCESS); default: @@ -116,7 +122,7 @@ int main(int argc, char *argv[]) { wl_list_init(&state.xdpw_sessions); xdpw_screenshot_init(&state); - ret = xdpw_screencast_init(&state, output_name); + ret = xdpw_screencast_init(&state, output_name, max_fps); if (ret < 0) { logprint(ERROR, "xdpw: failed to initialize screencast"); goto error; diff --git a/src/screencast/fps_limit.c b/src/screencast/fps_limit.c index 364835e9..92feb53c 100644 --- a/src/screencast/fps_limit.c +++ b/src/screencast/fps_limit.c @@ -5,14 +5,13 @@ #include #define FPS_MEASURE_PERIOD_SEC 5.0 -#define TARGET_FPS 10.0 void measure_fps(struct fps_limit_state* state, uint64_t now_us); void fps_limit_apply(struct fps_limit_state* state, double max_fps) { if (max_fps <= 0.0) return; - + uint64_t now_us = gettime_us(); if (state->last_time_us == 0) { @@ -23,7 +22,7 @@ void fps_limit_apply(struct fps_limit_state* state, double max_fps) { measure_fps(state, now_us); - uint64_t target_us = (1.0 / TARGET_FPS) * 1e6; + uint64_t target_us = (1.0 / max_fps) * 1e6; int64_t delay_us = target_us - elapsed_us; if (delay_us > 0) { logprint(TRACE, "fps_limit: elapsed time since the end of last sleep: %u, sleeping for %u (microseconds)", elapsed_us, delay_us); diff --git a/src/screencast/screencast.c b/src/screencast/screencast.c index 05ffd3f5..7fa9d7e5 100644 --- a/src/screencast/screencast.c +++ b/src/screencast/screencast.c @@ -22,6 +22,7 @@ void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx, struct xdpw_screencast_instance *cast, struct xdpw_wlr_output *out, bool with_cursor) { cast->ctx = ctx; cast->target_output = out; + cast->max_fps = ctx->max_fps; cast->framerate = out->framerate; cast->with_cursor = with_cursor; cast->refcount = 1; @@ -434,12 +435,13 @@ static const sd_bus_vtable screencast_vtable[] = { SD_BUS_VTABLE_END }; -int xdpw_screencast_init(struct xdpw_state *state, const char *output_name) { +int xdpw_screencast_init(struct xdpw_state *state, const char *output_name, double max_fps) { sd_bus_slot *slot = NULL; state->screencast = (struct xdpw_screencast_context) { 0 }; state->screencast.state = state; state->screencast.output_name = output_name; + state->screencast.max_fps = max_fps; int err; err = xdpw_pwr_core_connect(state); diff --git a/src/screencast/wlr_screencast.c b/src/screencast/wlr_screencast.c index 43527d59..1d4b9a2c 100644 --- a/src/screencast/wlr_screencast.c +++ b/src/screencast/wlr_screencast.c @@ -135,7 +135,7 @@ static void wlr_frame_buffer_done(void *data, logprint(TRACE, "wlroots: buffer_done event handler"); - fps_limit_apply(&cast->fps_limit); + fps_limit_apply(&cast->fps_limit, cast->max_fps); zwlr_screencopy_frame_v1_copy_with_damage(frame, cast->simple_frame.buffer); logprint(TRACE, "wlroots: frame copied");