aboutsummaryrefslogtreecommitdiff
path: root/src/capture/portal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/capture/portal.c')
-rw-r--r--src/capture/portal.c97
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);