From 7b699f3344615849cd0affef82d9ff2e2b8aa845 Mon Sep 17 00:00:00 2001 From: Dan Shick Date: Wed, 19 Feb 2020 11:48:36 -0500 Subject: [PATCH] Use variable framerate, add CLI option to override pixelformat metadata --- include/screencast_common.h | 7 ++-- include/xdpw.h | 2 +- src/core/main.c | 44 +++++++++++++++++++++++- src/screencast/pipewire_screencast.c | 4 +++ src/screencast/screencast.c | 3 +- src/screencast/screencast_common.c | 50 +++++++++++++++++----------- src/screencast/wlr_screencast.c | 2 +- 7 files changed, 84 insertions(+), 28 deletions(-) diff --git a/include/screencast_common.h b/include/screencast_common.h index a1613a4..cbcf7e8 100644 --- a/include/screencast_common.h +++ b/include/screencast_common.h @@ -45,7 +45,6 @@ struct screencast_context { // pipewire struct pwr_type type; - struct pw_main_loop *loop; struct spa_source *event; struct pw_core *core; @@ -57,13 +56,10 @@ struct screencast_context { struct spa_video_info_raw pwr_format; uint32_t seq; uint32_t node_id; - bool stream_state; - pthread_t pwr_thread; // wlroots - struct wl_display *display; struct wl_list output_list; struct wl_registry *registry; @@ -85,6 +81,9 @@ struct screencast_context { // frame mutex pthread_mutex_t lock; + // cli options + const char *forced_pixelformat; + // if something happens during capture int err; bool quit; diff --git a/include/xdpw.h b/include/xdpw.h index 267c2c1..625e2a8 100644 --- a/include/xdpw.h +++ b/include/xdpw.h @@ -19,7 +19,7 @@ enum { }; int init_screenshot(sd_bus *bus); -int init_screencast(sd_bus *bus); +int init_screencast(sd_bus *bus, const char *forced_pixelformat); struct xdpw_request *request_create(sd_bus *bus, const char *object_path); void request_destroy(struct xdpw_request *req); diff --git a/src/core/main.c b/src/core/main.c index 178d2b2..cdfbf5d 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1,10 +1,52 @@ #include #include +#include #include "xdpw.h" static const char service_name[] = "org.freedesktop.impl.portal.desktop.wlr"; +int xdpw_usage(FILE* stream, int rc) +{ + static const char* usage = +"Usage: xdg-desktop-portal-wlr [options]\n" +"\n" +" -p,--pixelformat=BGRx|RGBx Force a pixelformat in pipewire\n" +" metadata (performs no conversion).\n" +" -h,--help Get help (this text).\n" +"\n"; + + fprintf(stream, "%s", usage); + + return rc; +} + int main(int argc, char *argv[]) { + + const char* forced_pixelformat = NULL; + + static const char* shortopts = "p:h"; + static const struct option longopts[] = { + { "pixelformat", required_argument, NULL, 'p' }, + { "help", no_argument, NULL, 'h' }, + { NULL, 0, NULL, 0 } + }; + + while (1) { + int c = getopt_long(argc, argv, shortopts, longopts, NULL); + if (c < 0) + break; + + switch (c) { + case 'p': + forced_pixelformat = optarg; + break; + case 'h': + return xdpw_usage(stdout, 0); + default: + return xdpw_usage(stderr, 1); + } + } + int ret = 0; sd_bus *bus = NULL; @@ -15,7 +57,7 @@ int main(int argc, char *argv[]) { } init_screenshot(bus); - init_screencast(bus); + init_screencast(bus, forced_pixelformat); ret = sd_bus_request_name(bus, service_name, 0); if (ret < 0) { diff --git a/src/screencast/pipewire_screencast.c b/src/screencast/pipewire_screencast.c index 1c99de7..3d29280 100644 --- a/src/screencast/pipewire_screencast.c +++ b/src/screencast/pipewire_screencast.c @@ -174,6 +174,10 @@ static void pwr_handle_state_changed(void *data, enum pw_remote_state old, &SPA_RECTANGLE(ctx->simple_frame.width, ctx->simple_frame.height), SPA_POD_PROP_MIN_MAX(&SPA_RECTANGLE(1, 1), &SPA_RECTANGLE(4096, 4096)), ":", ctx->type.format_video.framerate, "F", + // specify variable framerate + &SPA_FRACTION(0, 1), + ":", ctx->type.format_video.max_framerate, "F", + // with a maximum at the wlroots specified hardware framerate &SPA_FRACTION(ctx->framerate, 1)); pw_stream_add_listener(ctx->stream, &ctx->stream_listener, diff --git a/src/screencast/screencast.c b/src/screencast/screencast.c index 1712a16..f384eb8 100644 --- a/src/screencast/screencast.c +++ b/src/screencast/screencast.c @@ -300,11 +300,12 @@ static const sd_bus_vtable screencast_vtable[] = { SD_BUS_VTABLE_END }; -int init_screencast(sd_bus *bus) { +int init_screencast(sd_bus *bus, const char *forced_pixelformat) { // TODO: cleanup sd_bus_slot *slot = NULL; //struct screencast_context ctx = (struct screencast_context){0}; + ctx.forced_pixelformat = forced_pixelformat; ctx.simple_frame = (struct simple_frame){0}; ctx.simple_frame.damage = &(struct damage){0}; diff --git a/src/screencast/screencast_common.c b/src/screencast/screencast_common.c index 969c459..03089a8 100644 --- a/src/screencast/screencast_common.c +++ b/src/screencast/screencast_common.c @@ -10,26 +10,36 @@ char *strdup(const char *src) { uint32_t pipewire_from_wl_shm(void *data) { struct screencast_context *ctx = data; + + if(ctx->forced_pixelformat){ + if(strcmp(ctx->forced_pixelformat, "BGRx") == 0) { + return ctx->type.video_format.BGRx; + } + if(strcmp(ctx->forced_pixelformat, "RGBx") == 0){ + return ctx->type.video_format.RGBx; + } + } + switch (ctx->simple_frame.format) { - case WL_SHM_FORMAT_ARGB8888: - return ctx->type.video_format.BGRA; - case WL_SHM_FORMAT_XRGB8888: - return ctx->type.video_format.BGRx; - case WL_SHM_FORMAT_RGBA8888: - return ctx->type.video_format.ABGR; - case WL_SHM_FORMAT_RGBX8888: - return ctx->type.video_format.xBGR; - case WL_SHM_FORMAT_ABGR8888: - return ctx->type.video_format.RGBA; - case WL_SHM_FORMAT_XBGR8888: - return ctx->type.video_format.RGBx; - case WL_SHM_FORMAT_BGRA8888: - return ctx->type.video_format.ARGB; - case WL_SHM_FORMAT_BGRX8888: - return ctx->type.video_format.xRGB; - case WL_SHM_FORMAT_NV12: - return ctx->type.video_format.NV12; - default: - exit(EXIT_FAILURE); + case WL_SHM_FORMAT_ARGB8888: + return ctx->type.video_format.BGRA; + case WL_SHM_FORMAT_XRGB8888: + return ctx->type.video_format.BGRx; + case WL_SHM_FORMAT_RGBA8888: + return ctx->type.video_format.ABGR; + case WL_SHM_FORMAT_RGBX8888: + return ctx->type.video_format.xBGR; + case WL_SHM_FORMAT_ABGR8888: + return ctx->type.video_format.RGBA; + case WL_SHM_FORMAT_XBGR8888: + return ctx->type.video_format.RGBx; + case WL_SHM_FORMAT_BGRA8888: + return ctx->type.video_format.ARGB; + case WL_SHM_FORMAT_BGRX8888: + return ctx->type.video_format.xRGB; + case WL_SHM_FORMAT_NV12: + return ctx->type.video_format.NV12; + default: + exit(EXIT_FAILURE); } } diff --git a/src/screencast/wlr_screencast.c b/src/screencast/wlr_screencast.c index 41479a6..f13acb5 100644 --- a/src/screencast/wlr_screencast.c +++ b/src/screencast/wlr_screencast.c @@ -161,7 +161,7 @@ static void wlr_output_handle_mode(void *data, struct wl_output *wl_output, int32_t height, int32_t refresh) { if (flags & WL_OUTPUT_MODE_CURRENT) { struct wayland_output *output = data; - output->framerate = (float)refresh * 1000; + output->framerate = (float)refresh/1000; } }