diff options
Diffstat (limited to 'src/capture/portal.c')
-rw-r--r-- | src/capture/portal.c | 97 |
1 files changed, 31 insertions, 66 deletions
diff --git a/src/capture/portal.c b/src/capture/portal.c index a441299..ec87ab6 100644 --- a/src/capture/portal.c +++ b/src/capture/portal.c @@ -8,10 +8,9 @@ #include <stdlib.h> #include <stdio.h> #include <unistd.h> +#include <limits.h> #include <assert.h> -#include <libavcodec/avcodec.h> - typedef struct { gsr_capture_portal_params params; @@ -24,9 +23,6 @@ typedef struct { vec2i capture_size; gsr_pipewire_video_dmabuf_data dmabuf_data[GSR_PIPEWIRE_VIDEO_DMABUF_MAX_PLANES]; int num_dmabuf_data; - - AVCodecContext *video_codec_context; - bool fast_path_failed; } gsr_capture_portal; static void gsr_capture_portal_cleanup_plane_fds(gsr_capture_portal *self) { @@ -68,26 +64,31 @@ static void gsr_capture_portal_stop(gsr_capture_portal *self) { } static void gsr_capture_portal_create_input_textures(gsr_capture_portal *self) { + const float border_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + self->params.egl->glGenTextures(1, &self->texture_map.texture_id); self->params.egl->glBindTexture(GL_TEXTURE_2D, self->texture_map.texture_id); - self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + self->params.egl->glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); self->params.egl->glBindTexture(GL_TEXTURE_2D, 0); self->params.egl->glGenTextures(1, &self->texture_map.external_texture_id); self->params.egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, self->texture_map.external_texture_id); - self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + self->params.egl->glTexParameterfv(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BORDER_COLOR, border_color); self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); self->params.egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); self->params.egl->glGenTextures(1, &self->texture_map.cursor_texture_id); self->params.egl->glBindTexture(GL_TEXTURE_2D, self->texture_map.cursor_texture_id); - self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + self->params.egl->glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); self->params.egl->glBindTexture(GL_TEXTURE_2D, 0); @@ -256,7 +257,7 @@ static bool gsr_capture_portal_get_frame_dimensions(gsr_capture_portal *self) { return false; } -static int gsr_capture_portal_start(gsr_capture *cap, AVCodecContext *video_codec_context, AVFrame *frame) { +static int gsr_capture_portal_start(gsr_capture *cap, gsr_capture_metadata *capture_metadata) { gsr_capture_portal *self = cap->priv; gsr_capture_portal_create_input_textures(self); @@ -285,7 +286,7 @@ static int gsr_capture_portal_start(gsr_capture *cap, AVCodecContext *video_code fprintf(stderr, "gsr info: gsr_capture_portal_start: setting up pipewire\n"); /* TODO: support hdr when pipewire supports it */ /* gsr_pipewire closes the pipewire fd, even on failure */ - if(!gsr_pipewire_video_init(&self->pipewire, pipewire_fd, pipewire_node, video_codec_context->framerate.num, self->params.record_cursor, self->params.egl)) { + if(!gsr_pipewire_video_init(&self->pipewire, pipewire_fd, pipewire_node, capture_metadata->fps, self->params.record_cursor, self->params.egl)) { fprintf(stderr, "gsr error: gsr_capture_portal_start: failed to setup pipewire with fd: %d, node: %" PRIu32 "\n", pipewire_fd, pipewire_node); gsr_capture_portal_stop(self); return -1; @@ -297,27 +298,15 @@ static int gsr_capture_portal_start(gsr_capture *cap, AVCodecContext *video_code return -1; } - /* Disable vsync */ - self->params.egl->eglSwapInterval(self->params.egl->egl_display, 0); - if(self->params.output_resolution.x == 0 && self->params.output_resolution.y == 0) { - self->params.output_resolution = self->capture_size; - video_codec_context->width = FFALIGN(self->capture_size.x, 2); - video_codec_context->height = FFALIGN(self->capture_size.y, 2); + capture_metadata->width = self->capture_size.x; + capture_metadata->height = self->capture_size.y; } else { self->params.output_resolution = scale_keep_aspect_ratio(self->capture_size, self->params.output_resolution); - video_codec_context->width = FFALIGN(self->params.output_resolution.x, 2); - video_codec_context->height = FFALIGN(self->params.output_resolution.y, 2); + capture_metadata->width = self->params.output_resolution.x; + capture_metadata->height = self->params.output_resolution.y; } - self->fast_path_failed = self->params.egl->gpu_info.vendor == GSR_GPU_VENDOR_AMD && !gl_driver_version_greater_than(self->params.egl, 24, 0, 9); - if(self->fast_path_failed) - fprintf(stderr, "gsr warning: gsr_capture_kms_start: your amd driver (mesa) version is known to be buggy (<= version 24.0.9), falling back to opengl copy\n"); - - frame->width = video_codec_context->width; - frame->height = video_codec_context->height; - - self->video_codec_context = video_codec_context; return 0; } @@ -325,8 +314,7 @@ static int max_int(int a, int b) { return a > b ? a : b; } -static int gsr_capture_portal_capture(gsr_capture *cap, AVFrame *frame, gsr_color_conversion *color_conversion) { - (void)frame; +static int gsr_capture_portal_capture(gsr_capture *cap, gsr_capture_metadata *capture_metadata, gsr_color_conversion *color_conversion) { (void)color_conversion; gsr_capture_portal *self = cap->priv; @@ -350,39 +338,17 @@ static int gsr_capture_portal_capture(gsr_capture *cap, AVFrame *frame, gsr_colo vec2i output_size = is_scaled ? self->params.output_resolution : self->capture_size; output_size = scale_keep_aspect_ratio(self->capture_size, output_size); - const vec2i target_pos = { max_int(0, frame->width / 2 - output_size.x / 2), max_int(0, frame->height / 2 - output_size.y / 2) }; + const vec2i target_pos = { max_int(0, capture_metadata->width / 2 - output_size.x / 2), max_int(0, capture_metadata->height / 2 - output_size.y / 2) }; - self->params.egl->glFlush(); - self->params.egl->glFinish(); + //self->params.egl->glFlush(); + //self->params.egl->glFinish(); // TODO: Handle region crop - /* Fast opengl free path */ - if(!self->fast_path_failed && video_codec_context_is_vaapi(self->video_codec_context) && self->params.egl->gpu_info.vendor == GSR_GPU_VENDOR_AMD) { - int fds[4]; - uint32_t offsets[4]; - uint32_t pitches[4]; - uint64_t modifiers[4]; - for(int i = 0; i < self->num_dmabuf_data; ++i) { - fds[i] = self->dmabuf_data[i].fd; - offsets[i] = self->dmabuf_data[i].offset; - pitches[i] = self->dmabuf_data[i].stride; - modifiers[i] = pipewire_modifiers; - } - if(!vaapi_copy_drm_planes_to_video_surface(self->video_codec_context, frame, (vec2i){region.x, region.y}, self->capture_size, target_pos, output_size, pipewire_fourcc, self->capture_size, fds, offsets, pitches, modifiers, self->num_dmabuf_data)) { - fprintf(stderr, "gsr error: gsr_capture_portal_capture: vaapi_copy_drm_planes_to_video_surface failed, falling back to opengl copy. Please report this as an issue at https://github.com/dec05eba/gpu-screen-recorder-issues\n"); - self->fast_path_failed = true; - } - } else { - self->fast_path_failed = true; - } - - if(self->fast_path_failed) { - gsr_color_conversion_draw(color_conversion, using_external_image ? self->texture_map.external_texture_id : self->texture_map.texture_id, - target_pos, output_size, - (vec2i){region.x, region.y}, self->capture_size, - 0.0f, using_external_image, GSR_SOURCE_COLOR_RGB); - } + gsr_color_conversion_draw(color_conversion, using_external_image ? self->texture_map.external_texture_id : self->texture_map.texture_id, + target_pos, output_size, + (vec2i){region.x, region.y}, self->capture_size, self->capture_size, + GSR_ROT_0, using_external_image, GSR_SOURCE_COLOR_RGB); if(self->params.record_cursor && self->texture_map.cursor_texture_id > 0 && cursor_region.width > 0) { const vec2d scale = { @@ -399,13 +365,13 @@ static int gsr_capture_portal_capture(gsr_capture *cap, AVFrame *frame, gsr_colo self->params.egl->glScissor(target_pos.x, target_pos.y, output_size.x, output_size.y); gsr_color_conversion_draw(color_conversion, self->texture_map.cursor_texture_id, (vec2i){cursor_pos.x, cursor_pos.y}, (vec2i){cursor_region.width * scale.x, cursor_region.height * scale.y}, - (vec2i){0, 0}, (vec2i){cursor_region.width, cursor_region.height}, - 0.0f, false, GSR_SOURCE_COLOR_RGB); + (vec2i){0, 0}, (vec2i){cursor_region.width, cursor_region.height}, (vec2i){cursor_region.width, cursor_region.height}, + GSR_ROT_0, false, GSR_SOURCE_COLOR_RGB); self->params.egl->glDisable(GL_SCISSOR_TEST); } - self->params.egl->glFlush(); - self->params.egl->glFinish(); + //self->params.egl->glFlush(); + //self->params.egl->glFinish(); gsr_capture_portal_cleanup_plane_fds(self); @@ -427,8 +393,7 @@ static void gsr_capture_portal_clear_damage(gsr_capture *cap) { gsr_pipewire_video_clear_damage(&self->pipewire); } -static void gsr_capture_portal_destroy(gsr_capture *cap, AVCodecContext *video_codec_context) { - (void)video_codec_context; +static void gsr_capture_portal_destroy(gsr_capture *cap) { gsr_capture_portal *self = cap->priv; if(cap->priv) { gsr_capture_portal_stop(self); |