diff options
Diffstat (limited to 'src/utils.c')
-rw-r--r-- | src/utils.c | 79 |
1 files changed, 64 insertions, 15 deletions
diff --git a/src/utils.c b/src/utils.c index 42f4c40..e871126 100644 --- a/src/utils.c +++ b/src/utils.c @@ -7,6 +7,7 @@ #include <fcntl.h> #include <stdlib.h> #include <sys/stat.h> +#include <sys/random.h> #include <errno.h> #include <assert.h> @@ -27,6 +28,25 @@ double clock_get_monotonic_seconds(void) { return (double)ts.tv_sec + (double)ts.tv_nsec * 0.000000001; } +bool generate_random_characters(char *buffer, int buffer_size, const char *alphabet, size_t alphabet_size) { + /* TODO: Use other functions on other platforms than linux */ + if(getrandom(buffer, buffer_size, 0) < buffer_size) { + fprintf(stderr, "Failed to get random bytes, error: %s\n", strerror(errno)); + return false; + } + + for(int i = 0; i < buffer_size; ++i) { + unsigned char c = *(unsigned char*)&buffer[i]; + buffer[i] = alphabet[c % alphabet_size]; + } + + return true; +} + +bool generate_random_characters_standard_alphabet(char *buffer, int buffer_size) { + return generate_random_characters(buffer, buffer_size, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62); +} + static gsr_monitor_rotation wayland_transform_to_gsr_rotation(int32_t rot) { switch(rot) { case 0: return GSR_MONITOR_ROT_0; @@ -71,6 +91,16 @@ static uint32_t x11_output_get_connector_id(Display *dpy, RROutput output, Atom return result; } +static vec2i get_monitor_size_rotated(int width, int height, gsr_monitor_rotation rotation) { + vec2i size = { .x = width, .y = height }; + if(rotation == GSR_MONITOR_ROT_90 || rotation == GSR_MONITOR_ROT_270) { + int tmp_x = size.x; + size.x = size.y; + size.y = tmp_x; + } + return size; +} + void for_each_active_monitor_output_x11_not_cached(Display *display, active_monitor_callback callback, void *userdata) { XRRScreenResources *screen_res = XRRGetScreenResources(display, DefaultRootWindow(display)); if(!screen_res) @@ -84,16 +114,23 @@ void for_each_active_monitor_output_x11_not_cached(Display *display, active_moni if(out_info && out_info->crtc && out_info->connection == RR_Connected) { XRRCrtcInfo *crt_info = XRRGetCrtcInfo(display, screen_res, out_info->crtc); if(crt_info && crt_info->mode) { + // We want to use the current mode info width/height (mode_info->width/height) instead of crtc info width/height (crt_info->width/height) because crtc info + // is scaled if the monitor is scaled (xrandr --output DP-1 --scale 1.5). Normally this is not an issue for x11 applications, + // but gpu screen recorder captures the drm framebuffer instead of x11 api. This drm framebuffer which doesn't increase in size when using xrandr scaling. + // Maybe a better option would be to get the drm crtc size instead. const XRRModeInfo *mode_info = get_mode_info(screen_res, crt_info->mode); if(mode_info && out_info->nameLen < (int)sizeof(display_name)) { snprintf(display_name, sizeof(display_name), "%.*s", (int)out_info->nameLen, out_info->name); + const gsr_monitor_rotation rotation = x11_rotation_to_gsr_rotation(crt_info->rotation); + const vec2i monitor_size = get_monitor_size_rotated(mode_info->width, mode_info->height, rotation); + const gsr_monitor monitor = { .name = display_name, .name_len = out_info->nameLen, .pos = { .x = crt_info->x, .y = crt_info->y }, - .size = { .x = (int)crt_info->width, .y = (int)crt_info->height }, + .size = monitor_size, .connector_id = x11_output_get_connector_id(display, screen_res->outputs[i], randr_connector_id_atom), - .rotation = x11_rotation_to_gsr_rotation(crt_info->rotation), + .rotation = rotation, .monitor_identifier = out_info->crtc }; callback(&monitor, userdata); @@ -400,6 +437,8 @@ bool gl_get_gpu_info(gsr_egl *egl, gsr_gpu_info *info) { if(strstr((const char*)gl_vendor, "AMD")) info->vendor = GSR_GPU_VENDOR_AMD; + else if(strstr((const char*)gl_vendor, "Mesa") && gl_renderer && strstr((const char*)gl_renderer, "AMD")) + info->vendor = GSR_GPU_VENDOR_AMD; else if(strstr((const char*)gl_vendor, "Intel")) info->vendor = GSR_GPU_VENDOR_INTEL; else if(strstr((const char*)gl_vendor, "NVIDIA")) @@ -464,23 +503,14 @@ static bool try_card_has_valid_plane(const char *card_path) { return false; } -static void string_copy(char *dst, const char *src, int len) { - int src_len = strlen(src); - int min_len = src_len; - if(len - 1 < min_len) - min_len = len - 1; - memcpy(dst, src, min_len); - dst[min_len] = '\0'; -} - bool gsr_get_valid_card_path(gsr_egl *egl, char *output, bool is_monitor_capture) { if(egl->dri_card_path) { - string_copy(output, egl->dri_card_path, 127); + snprintf(output, 128, "%s", egl->dri_card_path); return is_monitor_capture ? try_card_has_valid_plane(output) : true; } for(int i = 0; i < 10; ++i) { - snprintf(output, 127, DRM_DEV_NAME, DRM_DIR_NAME, i); + snprintf(output, 128, DRM_DEV_NAME, DRM_DIR_NAME, i); if(try_card_has_valid_plane(output)) return true; } @@ -494,7 +524,7 @@ bool gsr_card_path_get_render_path(const char *card_path, char *render_path) { char *render_path_tmp = drmGetRenderDeviceNameFromFd(fd); if(render_path_tmp) { - string_copy(render_path, render_path_tmp, 127); + snprintf(render_path, 128, "%s", render_path_tmp); free(render_path_tmp); close(fd); return true; @@ -745,6 +775,8 @@ bool vaapi_copy_drm_planes_to_video_surface(AVCodecContext *video_codec_context, .height = dest_size.y }; + const bool scaled = dest_size.x != source_size.x || dest_size.y != source_size.y; + // Copying a surface to another surface will automatically perform the color conversion. Thanks vaapi! VAProcPipelineParameterBuffer params = {0}; params.surface = input_surface_id; @@ -752,7 +784,7 @@ bool vaapi_copy_drm_planes_to_video_surface(AVCodecContext *video_codec_context, params.surface_region = &source_region; params.output_region = &output_region; params.output_background_color = 0; - params.filter_flags = VA_FRAME_PICTURE; + params.filter_flags = scaled ? (VA_FILTER_SCALING_HQ | VA_FILTER_INTERPOLATION_BILINEAR) : 0; params.pipeline_flags = VA_PROC_PIPELINE_FAST; params.input_color_properties.colour_primaries = 1; @@ -884,3 +916,20 @@ bool vaapi_copy_egl_image_to_video_surface(gsr_egl *egl, EGLImage image, vec2i s return success; } + +vec2i scale_keep_aspect_ratio(vec2i from, vec2i to) { + if(from.x == 0 || from.y == 0) + return (vec2i){0, 0}; + + const double height_to_width_ratio = (double)from.y / (double)from.x; + from.x = to.x; + from.y = from.x * height_to_width_ratio; + + if(from.y > to.y) { + const double width_height_ratio = (double)from.x / (double)from.y; + from.y = to.y; + from.x = from.y * width_height_ratio; + } + + return from; +} |