Refactor capture base

This commit is contained in:
dec05eba
2024-03-09 18:54:53 +01:00
parent a3fedae329
commit 45ad3695b6
12 changed files with 145 additions and 160 deletions

2
TODO
View File

@@ -121,3 +121,5 @@ Show error when using compressed kms plane which isn't supported. Also do that i
Modify ffmpeg to accept opengl texture for nvenc encoding. Removes extra buffers and copies.
When vulkan encode is added, mention minimum nvidia driver required. (550.54.14?).
Dont display cursor in window capture mode if another window than the capture window selected.

View File

@@ -33,6 +33,8 @@ struct gsr_capture {
typedef struct gsr_capture_base gsr_capture_base;
struct gsr_capture_base {
gsr_egl *egl;
unsigned int input_texture;
unsigned int target_textures[2];
unsigned int cursor_texture;
@@ -56,11 +58,11 @@ void gsr_capture_end(gsr_capture *cap, AVFrame *frame);
/* Calls |gsr_capture_stop| as well */
void gsr_capture_destroy(gsr_capture *cap, AVCodecContext *video_codec_context);
bool gsr_capture_base_setup_vaapi_textures(gsr_capture_base *self, AVFrame *frame, gsr_egl *egl, VADisplay va_dpy, VADRMPRIMESurfaceDescriptor *prime, gsr_color_range color_range);
bool gsr_capture_base_setup_cuda_textures(gsr_capture_base *base, AVFrame *frame, gsr_cuda_context *cuda_context, gsr_egl *egl, gsr_color_range color_range, gsr_source_color source_color, bool hdr);
void gsr_capture_base_stop(gsr_capture_base *self, gsr_egl *egl);
bool gsr_capture_base_setup_vaapi_textures(gsr_capture_base *self, AVFrame *frame, VADisplay va_dpy, VADRMPRIMESurfaceDescriptor *prime, gsr_color_range color_range);
bool gsr_capture_base_setup_cuda_textures(gsr_capture_base *self, AVFrame *frame, gsr_cuda_context *cuda_context, gsr_color_range color_range, gsr_source_color source_color, bool hdr);
void gsr_capture_base_stop(gsr_capture_base *self);
bool drm_create_codec_context(const char *card_path, AVCodecContext *video_codec_context, bool hdr, VADisplay *va_dpy);
bool cuda_create_codec_context(CUcontext cu_ctx, AVCodecContext *video_codec_context, CUstream *cuda_stream);
bool drm_create_codec_context(const char *card_path, AVCodecContext *video_codec_context, int width, int height, bool hdr, VADisplay *va_dpy);
bool cuda_create_codec_context(CUcontext cu_ctx, AVCodecContext *video_codec_context, int width, int height, CUstream *cuda_stream);
#endif /* GSR_CAPTURE_CAPTURE_H */

View File

@@ -1,13 +1,13 @@
#ifndef GSR_CAPTURE_KMS_H
#define GSR_CAPTURE_KMS_H
#include "capture.h"
#include "../../kms/client/kms_client.h"
#include "../color_conversion.h"
#include "../vec2.h"
#include "../defs.h"
#include <stdbool.h>
typedef struct gsr_capture_base gsr_capture_base;
typedef struct AVCodecContext AVCodecContext;
typedef struct AVMasteringDisplayMetadata AVMasteringDisplayMetadata;
typedef struct AVContentLightMetadata AVContentLightMetadata;
@@ -23,6 +23,8 @@ typedef struct {
} MonitorId;
struct gsr_capture_kms {
gsr_capture_base base;
bool should_stop;
bool stop_is_error;
@@ -40,9 +42,9 @@ struct gsr_capture_kms {
};
/* Returns 0 on success */
int gsr_capture_kms_start(gsr_capture_kms *self, gsr_capture_base *base, const char *display_to_capture, gsr_egl *egl, AVCodecContext *video_codec_context, AVFrame *frame);
int gsr_capture_kms_start(gsr_capture_kms *self, const char *display_to_capture, gsr_egl *egl, AVCodecContext *video_codec_context, AVFrame *frame);
void gsr_capture_kms_stop(gsr_capture_kms *self);
bool gsr_capture_kms_capture(gsr_capture_kms *self, gsr_capture_base *base, AVFrame *frame, gsr_egl *egl, bool hdr, bool screen_plane_use_modifiers, bool cursor_texture_is_external);
bool gsr_capture_kms_capture(gsr_capture_kms *self, AVFrame *frame, bool hdr, bool screen_plane_use_modifiers, bool cursor_texture_is_external);
void gsr_capture_kms_cleanup_kms_fds(gsr_capture_kms *self);
#endif /* GSR_CAPTURE_KMS_H */

View File

@@ -42,7 +42,7 @@ typedef struct {
void gsr_capture_xcomposite_init(gsr_capture_xcomposite *self, const gsr_capture_xcomposite_params *params);
int gsr_capture_xcomposite_start(gsr_capture_xcomposite *self, AVCodecContext *video_codec_context, AVFrame *frame);
void gsr_capture_xcomposite_stop(gsr_capture_xcomposite *self, AVCodecContext *video_codec_context);
void gsr_capture_xcomposite_stop(gsr_capture_xcomposite *self);
void gsr_capture_xcomposite_tick(gsr_capture_xcomposite *self, AVCodecContext *video_codec_context);
bool gsr_capture_xcomposite_should_stop(gsr_capture_xcomposite *self, bool *err);
int gsr_capture_xcomposite_capture(gsr_capture_xcomposite *self, AVFrame *frame);

View File

@@ -75,7 +75,7 @@ static uint32_t fourcc(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
return (d << 24) | (c << 16) | (b << 8) | a;
}
bool gsr_capture_base_setup_vaapi_textures(gsr_capture_base *self, AVFrame *frame, gsr_egl *egl, VADisplay va_dpy, VADRMPRIMESurfaceDescriptor *prime, gsr_color_range color_range) {
bool gsr_capture_base_setup_vaapi_textures(gsr_capture_base *self, AVFrame *frame, VADisplay va_dpy, VADRMPRIMESurfaceDescriptor *prime, gsr_color_range color_range) {
const int res = av_hwframe_get_buffer(self->video_codec_context->hw_frames_ctx, frame, 0);
if(res < 0) {
fprintf(stderr, "gsr error: gsr_capture_kms_setup_vaapi_textures: av_hwframe_get_buffer failed: %d\n", res);
@@ -91,21 +91,21 @@ bool gsr_capture_base_setup_vaapi_textures(gsr_capture_base *self, AVFrame *fram
}
vaSyncSurface(va_dpy, target_surface_id);
egl->glGenTextures(1, &self->input_texture);
egl->glBindTexture(GL_TEXTURE_2D, self->input_texture);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
egl->glBindTexture(GL_TEXTURE_2D, 0);
self->egl->glGenTextures(1, &self->input_texture);
self->egl->glBindTexture(GL_TEXTURE_2D, self->input_texture);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
self->egl->glBindTexture(GL_TEXTURE_2D, 0);
egl->glGenTextures(1, &self->cursor_texture);
egl->glBindTexture(GL_TEXTURE_2D, self->cursor_texture);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
egl->glBindTexture(GL_TEXTURE_2D, 0);
self->egl->glGenTextures(1, &self->cursor_texture);
self->egl->glBindTexture(GL_TEXTURE_2D, self->cursor_texture);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
self->egl->glBindTexture(GL_TEXTURE_2D, 0);
const uint32_t formats_nv12[2] = { fourcc('R', '8', ' ', ' '), fourcc('G', 'R', '8', '8') };
const uint32_t formats_p010[2] = { fourcc('R', '1', '6', ' '), fourcc('G', 'R', '3', '2') };
@@ -114,7 +114,7 @@ bool gsr_capture_base_setup_vaapi_textures(gsr_capture_base *self, AVFrame *fram
const uint32_t *formats = prime->fourcc == FOURCC_NV12 ? formats_nv12 : formats_p010;
const int div[2] = {1, 2}; // divide UV texture size by 2 because chroma is half size
egl->glGenTextures(2, self->target_textures);
self->egl->glGenTextures(2, self->target_textures);
for(int i = 0; i < 2; ++i) {
const int layer = i;
const int plane = 0;
@@ -134,37 +134,37 @@ bool gsr_capture_base_setup_vaapi_textures(gsr_capture_base *self, AVFrame *fram
EGL_NONE
};
while(egl->eglGetError() != EGL_SUCCESS){}
EGLImage image = egl->eglCreateImage(egl->egl_display, 0, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr);
while(self->egl->eglGetError() != EGL_SUCCESS){}
EGLImage image = self->egl->eglCreateImage(self->egl->egl_display, 0, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr);
if(!image) {
fprintf(stderr, "gsr error: gsr_capture_kms_setup_vaapi_textures: failed to create egl image from drm fd for output drm fd, error: %d\n", egl->eglGetError());
fprintf(stderr, "gsr error: gsr_capture_kms_setup_vaapi_textures: failed to create egl image from drm fd for output drm fd, error: %d\n", self->egl->eglGetError());
return false;
}
egl->glBindTexture(GL_TEXTURE_2D, self->target_textures[i]);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
self->egl->glBindTexture(GL_TEXTURE_2D, self->target_textures[i]);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
while(egl->glGetError()) {}
while(egl->eglGetError() != EGL_SUCCESS){}
egl->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
if(egl->glGetError() != 0 || egl->eglGetError() != EGL_SUCCESS) {
while(self->egl->glGetError()) {}
while(self->egl->eglGetError() != EGL_SUCCESS){}
self->egl->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
if(self->egl->glGetError() != 0 || self->egl->eglGetError() != EGL_SUCCESS) {
// TODO: Get the error properly
fprintf(stderr, "gsr error: gsr_capture_kms_setup_vaapi_textures: failed to bind egl image to gl texture, error: %d\n", egl->eglGetError());
egl->eglDestroyImage(egl->egl_display, image);
egl->glBindTexture(GL_TEXTURE_2D, 0);
fprintf(stderr, "gsr error: gsr_capture_kms_setup_vaapi_textures: failed to bind egl image to gl texture, error: %d\n", self->egl->eglGetError());
self->egl->eglDestroyImage(self->egl->egl_display, image);
self->egl->glBindTexture(GL_TEXTURE_2D, 0);
return false;
}
egl->eglDestroyImage(egl->egl_display, image);
egl->glBindTexture(GL_TEXTURE_2D, 0);
self->egl->eglDestroyImage(self->egl->egl_display, image);
self->egl->glBindTexture(GL_TEXTURE_2D, 0);
}
gsr_color_conversion_params color_conversion_params = {0};
color_conversion_params.color_range = color_range;
color_conversion_params.egl = egl;
color_conversion_params.egl = self->egl;
color_conversion_params.source_color = GSR_SOURCE_COLOR_RGB;
if(prime->fourcc == FOURCC_NV12)
color_conversion_params.destination_color = GSR_DESTINATION_COLOR_NV12;
@@ -223,29 +223,29 @@ static bool cuda_register_opengl_texture(gsr_cuda *cuda, CUgraphicsResource *cud
return true;
}
bool gsr_capture_base_setup_cuda_textures(gsr_capture_base *base, AVFrame *frame, gsr_cuda_context *cuda_context, gsr_egl *egl, gsr_color_range color_range, gsr_source_color source_color, bool hdr) {
bool gsr_capture_base_setup_cuda_textures(gsr_capture_base *self, AVFrame *frame, gsr_cuda_context *cuda_context, gsr_color_range color_range, gsr_source_color source_color, bool hdr) {
// TODO:
const int res = av_hwframe_get_buffer(base->video_codec_context->hw_frames_ctx, frame, 0);
const int res = av_hwframe_get_buffer(self->video_codec_context->hw_frames_ctx, frame, 0);
if(res < 0) {
fprintf(stderr, "gsr error: gsr_capture_kms_setup_cuda_textures: av_hwframe_get_buffer failed: %d\n", res);
return false;
}
egl->glGenTextures(1, &base->input_texture);
egl->glBindTexture(GL_TEXTURE_2D, base->input_texture);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
egl->glBindTexture(GL_TEXTURE_2D, 0);
self->egl->glGenTextures(1, &self->input_texture);
self->egl->glBindTexture(GL_TEXTURE_2D, self->input_texture);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
self->egl->glBindTexture(GL_TEXTURE_2D, 0);
egl->glGenTextures(1, &base->cursor_texture);
egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, base->cursor_texture);
egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
self->egl->glGenTextures(1, &self->cursor_texture);
self->egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, self->cursor_texture);
self->egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
self->egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
self->egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
self->egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
self->egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
const unsigned int internal_formats_nv12[2] = { GL_R8, GL_RG8 };
const unsigned int internal_formats_p010[2] = { GL_R16, GL_RG16 };
@@ -253,31 +253,31 @@ bool gsr_capture_base_setup_cuda_textures(gsr_capture_base *base, AVFrame *frame
const int div[2] = {1, 2}; // divide UV texture size by 2 because chroma is half size
for(int i = 0; i < 2; ++i) {
base->target_textures[i] = gl_create_texture(egl, base->video_codec_context->width / div[i], base->video_codec_context->height / div[i], !hdr ? internal_formats_nv12[i] : internal_formats_p010[i], formats[i]);
if(base->target_textures[i] == 0) {
self->target_textures[i] = gl_create_texture(self->egl, self->video_codec_context->width / div[i], self->video_codec_context->height / div[i], !hdr ? internal_formats_nv12[i] : internal_formats_p010[i], formats[i]);
if(self->target_textures[i] == 0) {
fprintf(stderr, "gsr error: gsr_capture_kms_setup_cuda_textures: failed to create opengl texture\n");
return false;
}
if(!cuda_register_opengl_texture(cuda_context->cuda, &cuda_context->cuda_graphics_resources[i], &cuda_context->mapped_arrays[i], base->target_textures[i])) {
if(!cuda_register_opengl_texture(cuda_context->cuda, &cuda_context->cuda_graphics_resources[i], &cuda_context->mapped_arrays[i], self->target_textures[i])) {
return false;
}
}
gsr_color_conversion_params color_conversion_params = {0};
color_conversion_params.color_range = color_range;
color_conversion_params.egl = egl;
color_conversion_params.egl = self->egl;
color_conversion_params.source_color = source_color;
if(!hdr)
color_conversion_params.destination_color = GSR_DESTINATION_COLOR_NV12;
else
color_conversion_params.destination_color = GSR_DESTINATION_COLOR_P010;
color_conversion_params.destination_textures[0] = base->target_textures[0];
color_conversion_params.destination_textures[1] = base->target_textures[1];
color_conversion_params.destination_textures[0] = self->target_textures[0];
color_conversion_params.destination_textures[1] = self->target_textures[1];
color_conversion_params.num_destination_textures = 2;
if(gsr_color_conversion_init(&base->color_conversion, &color_conversion_params) != 0) {
if(gsr_color_conversion_init(&self->color_conversion, &color_conversion_params) != 0) {
fprintf(stderr, "gsr error: gsr_capture_kms_setup_cuda_textures: failed to create color conversion\n");
return false;
}
@@ -285,27 +285,32 @@ bool gsr_capture_base_setup_cuda_textures(gsr_capture_base *base, AVFrame *frame
return true;
}
void gsr_capture_base_stop(gsr_capture_base *self, gsr_egl *egl) {
void gsr_capture_base_stop(gsr_capture_base *self) {
gsr_color_conversion_deinit(&self->color_conversion);
if(egl->egl_context) {
if(self->egl->egl_context) {
if(self->input_texture) {
egl->glDeleteTextures(1, &self->input_texture);
self->egl->glDeleteTextures(1, &self->input_texture);
self->input_texture = 0;
}
if(self->cursor_texture) {
egl->glDeleteTextures(1, &self->cursor_texture);
self->egl->glDeleteTextures(1, &self->cursor_texture);
self->cursor_texture = 0;
}
egl->glDeleteTextures(2, self->target_textures);
self->egl->glDeleteTextures(2, self->target_textures);
self->target_textures[0] = 0;
self->target_textures[1] = 0;
}
if(self->video_codec_context->hw_device_ctx)
av_buffer_unref(&self->video_codec_context->hw_device_ctx);
if(self->video_codec_context->hw_frames_ctx)
av_buffer_unref(&self->video_codec_context->hw_frames_ctx);
}
bool drm_create_codec_context(const char *card_path, AVCodecContext *video_codec_context, bool hdr, VADisplay *va_dpy) {
bool drm_create_codec_context(const char *card_path, AVCodecContext *video_codec_context, int width, int height, bool hdr, VADisplay *va_dpy) {
char render_path[128];
if(!gsr_card_path_get_render_path(card_path, render_path)) {
fprintf(stderr, "gsr error: failed to get /dev/dri/renderDXXX file from %s\n", card_path);
@@ -327,8 +332,8 @@ bool drm_create_codec_context(const char *card_path, AVCodecContext *video_codec
AVHWFramesContext *hw_frame_context =
(AVHWFramesContext *)frame_context->data;
hw_frame_context->width = video_codec_context->width;
hw_frame_context->height = video_codec_context->height;
hw_frame_context->width = width;
hw_frame_context->height = height;
hw_frame_context->sw_format = hdr ? AV_PIX_FMT_P010LE : AV_PIX_FMT_NV12;
hw_frame_context->format = video_codec_context->pix_fmt;
hw_frame_context->device_ref = device_ctx;
@@ -352,7 +357,7 @@ bool drm_create_codec_context(const char *card_path, AVCodecContext *video_codec
return true;
}
bool cuda_create_codec_context(CUcontext cu_ctx, AVCodecContext *video_codec_context, CUstream *cuda_stream) {
bool cuda_create_codec_context(CUcontext cu_ctx, AVCodecContext *video_codec_context, int width, int height, CUstream *cuda_stream) {
AVBufferRef *device_ctx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA);
if(!device_ctx) {
fprintf(stderr, "gsr error: cuda_create_codec_context failed: failed to create hardware device context\n");
@@ -376,8 +381,8 @@ bool cuda_create_codec_context(CUcontext cu_ctx, AVCodecContext *video_codec_con
}
AVHWFramesContext *hw_frame_context = (AVHWFramesContext*)frame_context->data;
hw_frame_context->width = video_codec_context->width;
hw_frame_context->height = video_codec_context->height;
hw_frame_context->width = width;
hw_frame_context->height = height;
hw_frame_context->sw_format = AV_PIX_FMT_NV12;
hw_frame_context->format = video_codec_context->pix_fmt;
hw_frame_context->device_ref = device_ctx;

View File

@@ -39,8 +39,10 @@ static int max_int(int a, int b) {
return a > b ? a : b;
}
int gsr_capture_kms_start(gsr_capture_kms *self, gsr_capture_base *base, const char *display_to_capture, gsr_egl *egl, AVCodecContext *video_codec_context, AVFrame *frame) {
base->video_codec_context = video_codec_context;
int gsr_capture_kms_start(gsr_capture_kms *self, const char *display_to_capture, gsr_egl *egl, AVCodecContext *video_codec_context, AVFrame *frame) {
memset(self, 0, sizeof(*self));
self->base.video_codec_context = video_codec_context;
self->base.egl = egl;
gsr_monitor monitor;
self->monitor_id.num_connector_ids = 0;
@@ -75,17 +77,18 @@ int gsr_capture_kms_start(gsr_capture_kms *self, gsr_capture_base *base, const c
/* Disable vsync */
egl->eglSwapInterval(egl->egl_display, 0);
base->video_codec_context->width = max_int(2, even_number_ceil(self->capture_size.x));
base->video_codec_context->height = max_int(2, even_number_ceil(self->capture_size.y));
self->base.video_codec_context->width = max_int(2, even_number_ceil(self->capture_size.x));
self->base.video_codec_context->height = max_int(2, even_number_ceil(self->capture_size.y));
frame->width = base->video_codec_context->width;
frame->height = base->video_codec_context->height;
frame->width = self->base.video_codec_context->width;
frame->height = self->base.video_codec_context->height;
return 0;
}
void gsr_capture_kms_stop(gsr_capture_kms *self) {
gsr_capture_kms_cleanup_kms_fds(self);
gsr_kms_client_deinit(&self->kms_client);
gsr_capture_base_stop(&self->base);
}
static float monitor_rotation_to_radians(gsr_monitor_rotation rot) {
@@ -190,9 +193,9 @@ static vec2i swap_vec2i(vec2i value) {
return value;
}
bool gsr_capture_kms_capture(gsr_capture_kms *self, gsr_capture_base *base, AVFrame *frame, gsr_egl *egl, bool hdr, bool screen_plane_use_modifiers, bool cursor_texture_is_external) {
bool gsr_capture_kms_capture(gsr_capture_kms *self, AVFrame *frame, bool hdr, bool screen_plane_use_modifiers, bool cursor_texture_is_external) {
//egl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
egl->glClear(0);
self->base.egl->glClear(0);
gsr_capture_kms_cleanup_kms_fds(self);
@@ -280,11 +283,11 @@ bool gsr_capture_kms_capture(gsr_capture_kms *self, gsr_capture_base *base, AVFr
img_attr[13] = EGL_NONE;
}
EGLImage image = egl->eglCreateImage(egl->egl_display, 0, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr);
egl->glBindTexture(GL_TEXTURE_2D, base->input_texture);
egl->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
egl->eglDestroyImage(egl->egl_display, image);
egl->glBindTexture(GL_TEXTURE_2D, 0);
EGLImage image = self->base.egl->eglCreateImage(self->base.egl->egl_display, 0, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr);
self->base.egl->glBindTexture(GL_TEXTURE_2D, self->base.input_texture);
self->base.egl->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
self->base.egl->eglDestroyImage(self->base.egl->egl_display, image);
self->base.egl->glBindTexture(GL_TEXTURE_2D, 0);
vec2i capture_pos = self->capture_pos;
if(!capture_is_combined_plane)
@@ -292,7 +295,7 @@ bool gsr_capture_kms_capture(gsr_capture_kms *self, gsr_capture_base *base, AVFr
const float texture_rotation = monitor_rotation_to_radians(self->monitor_rotation);
gsr_color_conversion_draw(&base->color_conversion, base->input_texture,
gsr_color_conversion_draw(&self->base.color_conversion, self->base.input_texture,
(vec2i){0, 0}, self->capture_size,
capture_pos, self->capture_size,
texture_rotation, false);
@@ -336,22 +339,22 @@ bool gsr_capture_kms_capture(gsr_capture_kms *self, gsr_capture_base *base, AVFr
EGL_NONE
};
EGLImage cursor_image = egl->eglCreateImage(egl->egl_display, 0, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr_cursor);
EGLImage cursor_image = self->base.egl->eglCreateImage(self->base.egl->egl_display, 0, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr_cursor);
const int target = cursor_texture_is_external ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
egl->glBindTexture(target, base->cursor_texture);
egl->glEGLImageTargetTexture2DOES(target, cursor_image);
egl->eglDestroyImage(egl->egl_display, cursor_image);
egl->glBindTexture(target, 0);
self->base.egl->glBindTexture(target, self->base.cursor_texture);
self->base.egl->glEGLImageTargetTexture2DOES(target, cursor_image);
self->base.egl->eglDestroyImage(self->base.egl->egl_display, cursor_image);
self->base.egl->glBindTexture(target, 0);
gsr_color_conversion_draw(&base->color_conversion, base->cursor_texture,
gsr_color_conversion_draw(&self->base.color_conversion, self->base.cursor_texture,
cursor_pos, cursor_size,
(vec2i){0, 0}, cursor_size,
texture_rotation, false);
}
egl->eglSwapBuffers(egl->egl_display, egl->egl_surface);
//egl->glFlush();
//egl->glFinish();
self->base.egl->eglSwapBuffers(self->base.egl->egl_display, self->base.egl->egl_surface);
//self->base.egl->glFlush();
//self->base.egl->glFinish();
return true;
}

View File

@@ -10,7 +10,6 @@
#include <libavcodec/avcodec.h>
typedef struct {
gsr_capture_base base;
gsr_capture_kms kms;
gsr_capture_kms_cuda_params params;
@@ -26,7 +25,7 @@ static void gsr_capture_kms_cuda_stop(gsr_capture *cap, AVCodecContext *video_co
static int gsr_capture_kms_cuda_start(gsr_capture *cap, AVCodecContext *video_codec_context, AVFrame *frame) {
gsr_capture_kms_cuda *cap_kms = cap->priv;
const int res = gsr_capture_kms_start(&cap_kms->kms, &cap_kms->base, cap_kms->params.display_to_capture, cap_kms->params.egl, video_codec_context, frame);
const int res = gsr_capture_kms_start(&cap_kms->kms, cap_kms->params.display_to_capture, cap_kms->params.egl, video_codec_context, frame);
if(res != 0) {
gsr_capture_kms_cuda_stop(cap, video_codec_context);
return res;
@@ -39,7 +38,7 @@ static int gsr_capture_kms_cuda_start(gsr_capture *cap, AVCodecContext *video_co
return -1;
}
if(!cuda_create_codec_context(cap_kms->cuda.cu_ctx, video_codec_context, &cap_kms->cuda_stream)) {
if(!cuda_create_codec_context(cap_kms->cuda.cu_ctx, video_codec_context, video_codec_context->width, video_codec_context->height, &cap_kms->cuda_stream)) {
gsr_capture_kms_cuda_stop(cap, video_codec_context);
return -1;
}
@@ -50,7 +49,7 @@ static int gsr_capture_kms_cuda_start(gsr_capture *cap, AVCodecContext *video_co
.mapped_arrays = cap_kms->mapped_arrays
};
if(!gsr_capture_base_setup_cuda_textures(&cap_kms->base, frame, &cuda_context, cap_kms->params.egl, cap_kms->params.color_range, GSR_SOURCE_COLOR_RGB, cap_kms->params.hdr)) {
if(!gsr_capture_base_setup_cuda_textures(&cap_kms->kms.base, frame, &cuda_context, cap_kms->params.color_range, GSR_SOURCE_COLOR_RGB, cap_kms->params.hdr)) {
gsr_capture_kms_cuda_stop(cap, video_codec_context);
return -1;
}
@@ -91,7 +90,7 @@ static void gsr_capture_kms_unload_cuda_graphics(gsr_capture_kms_cuda *cap_kms)
static int gsr_capture_kms_cuda_capture(gsr_capture *cap, AVFrame *frame) {
gsr_capture_kms_cuda *cap_kms = cap->priv;
gsr_capture_kms_capture(&cap_kms->kms, &cap_kms->base, frame, cap_kms->params.egl, cap_kms->params.hdr, true, true);
gsr_capture_kms_capture(&cap_kms->kms, frame, cap_kms->params.hdr, true, true);
const int div[2] = {1, 2}; // divide UV texture size by 2 because chroma is half size
for(int i = 0; i < 2; ++i) {
@@ -127,18 +126,11 @@ static void gsr_capture_kms_cuda_capture_end(gsr_capture *cap, AVFrame *frame) {
}
static void gsr_capture_kms_cuda_stop(gsr_capture *cap, AVCodecContext *video_codec_context) {
(void)video_codec_context;
gsr_capture_kms_cuda *cap_kms = cap->priv;
gsr_capture_kms_unload_cuda_graphics(cap_kms);
if(video_codec_context->hw_device_ctx)
av_buffer_unref(&video_codec_context->hw_device_ctx);
if(video_codec_context->hw_frames_ctx)
av_buffer_unref(&video_codec_context->hw_frames_ctx);
gsr_cuda_unload(&cap_kms->cuda);
gsr_capture_kms_stop(&cap_kms->kms);
gsr_capture_base_stop(&cap_kms->base, cap_kms->params.egl);
}
static void gsr_capture_kms_cuda_destroy(gsr_capture *cap, AVCodecContext *video_codec_context) {

View File

@@ -10,7 +10,6 @@
#include <va/va_drmcommon.h>
typedef struct {
gsr_capture_base base;
gsr_capture_kms kms;
gsr_capture_kms_vaapi_params params;
@@ -24,18 +23,18 @@ static void gsr_capture_kms_vaapi_stop(gsr_capture *cap, AVCodecContext *video_c
static int gsr_capture_kms_vaapi_start(gsr_capture *cap, AVCodecContext *video_codec_context, AVFrame *frame) {
gsr_capture_kms_vaapi *cap_kms = cap->priv;
int res = gsr_capture_kms_start(&cap_kms->kms, &cap_kms->base, cap_kms->params.display_to_capture, cap_kms->params.egl, video_codec_context, frame);
int res = gsr_capture_kms_start(&cap_kms->kms, cap_kms->params.display_to_capture, cap_kms->params.egl, video_codec_context, frame);
if(res != 0) {
gsr_capture_kms_vaapi_stop(cap, video_codec_context);
return res;
}
if(!drm_create_codec_context(cap_kms->params.egl->card_path, video_codec_context, cap_kms->params.hdr, &cap_kms->va_dpy)) {
if(!drm_create_codec_context(cap_kms->params.egl->card_path, video_codec_context, video_codec_context->width, video_codec_context->height, cap_kms->params.hdr, &cap_kms->va_dpy)) {
gsr_capture_kms_vaapi_stop(cap, video_codec_context);
return -1;
}
if(!gsr_capture_base_setup_vaapi_textures(&cap_kms->base, frame, cap_kms->params.egl, cap_kms->va_dpy, &cap_kms->prime, cap_kms->params.color_range)) {
if(!gsr_capture_base_setup_vaapi_textures(&cap_kms->kms.base, frame, cap_kms->va_dpy, &cap_kms->prime, cap_kms->params.color_range)) {
gsr_capture_kms_vaapi_stop(cap, video_codec_context);
return -1;
}
@@ -58,7 +57,7 @@ static bool gsr_capture_kms_vaapi_should_stop(gsr_capture *cap, bool *err) {
static int gsr_capture_kms_vaapi_capture(gsr_capture *cap, AVFrame *frame) {
gsr_capture_kms_vaapi *cap_kms = cap->priv;
gsr_capture_kms_capture(&cap_kms->kms, &cap_kms->base, frame, cap_kms->params.egl, cap_kms->params.hdr, false, false);
gsr_capture_kms_capture(&cap_kms->kms, frame, cap_kms->params.hdr, false, false);
return 0;
}
@@ -69,6 +68,7 @@ static void gsr_capture_kms_vaapi_capture_end(gsr_capture *cap, AVFrame *frame)
}
static void gsr_capture_kms_vaapi_stop(gsr_capture *cap, AVCodecContext *video_codec_context) {
(void)video_codec_context;
gsr_capture_kms_vaapi *cap_kms = cap->priv;
for(uint32_t i = 0; i < cap_kms->prime.num_objects; ++i) {
@@ -78,13 +78,7 @@ static void gsr_capture_kms_vaapi_stop(gsr_capture *cap, AVCodecContext *video_c
}
}
if(video_codec_context->hw_device_ctx)
av_buffer_unref(&video_codec_context->hw_device_ctx);
if(video_codec_context->hw_frames_ctx)
av_buffer_unref(&video_codec_context->hw_frames_ctx);
gsr_capture_kms_stop(&cap_kms->kms);
gsr_capture_base_stop(&cap_kms->base, cap_kms->params.egl);
}
static void gsr_capture_kms_vaapi_destroy(gsr_capture *cap, AVCodecContext *video_codec_context) {

View File

@@ -159,6 +159,10 @@ static void set_vertical_sync_enabled(gsr_egl *egl, int enabled) {
static int gsr_capture_nvfbc_start(gsr_capture *cap, AVCodecContext *video_codec_context, AVFrame *frame) {
gsr_capture_nvfbc *cap_nvfbc = cap->priv;
cap_nvfbc->base.video_codec_context = video_codec_context;
cap_nvfbc->base.egl = cap_nvfbc->params.egl;
if(!gsr_cuda_load(&cap_nvfbc->cuda, cap_nvfbc->params.egl->x11.dpy, cap_nvfbc->params.overclock))
return -1;
@@ -295,7 +299,6 @@ static int gsr_capture_nvfbc_start(gsr_capture *cap, AVCodecContext *video_codec
goto error_cleanup;
}
cap_nvfbc->base.video_codec_context = video_codec_context;
if(capture_region) {
video_codec_context->width = width & ~1;
video_codec_context->height = height & ~1;
@@ -307,7 +310,7 @@ static int gsr_capture_nvfbc_start(gsr_capture *cap, AVCodecContext *video_codec
frame->width = video_codec_context->width;
frame->height = video_codec_context->height;
if(!cuda_create_codec_context(cap_nvfbc->cuda.cu_ctx, video_codec_context, &cap_nvfbc->cuda_stream))
if(!cuda_create_codec_context(cap_nvfbc->cuda.cu_ctx, video_codec_context, video_codec_context->width, video_codec_context->height, &cap_nvfbc->cuda_stream))
goto error_cleanup;
gsr_cuda_context cuda_context = {
@@ -317,7 +320,7 @@ static int gsr_capture_nvfbc_start(gsr_capture *cap, AVCodecContext *video_codec
};
// TODO: Remove this, it creates shit we dont need
if(!gsr_capture_base_setup_cuda_textures(&cap_nvfbc->base, frame, &cuda_context, cap_nvfbc->params.egl, cap_nvfbc->params.color_range, GSR_SOURCE_COLOR_BGR, cap_nvfbc->params.hdr)) {
if(!gsr_capture_base_setup_cuda_textures(&cap_nvfbc->base, frame, &cuda_context, cap_nvfbc->params.color_range, GSR_SOURCE_COLOR_BGR, cap_nvfbc->params.hdr)) {
goto error_cleanup;
}
/* Disable vsync */
@@ -342,12 +345,7 @@ static int gsr_capture_nvfbc_start(gsr_capture *cap, AVCodecContext *video_codec
cap_nvfbc->fbc_handle_created = false;
}
if(video_codec_context->hw_device_ctx)
av_buffer_unref(&video_codec_context->hw_device_ctx);
if(video_codec_context->hw_frames_ctx)
av_buffer_unref(&video_codec_context->hw_frames_ctx);
gsr_capture_base_stop(&cap_nvfbc->base, cap_nvfbc->params.egl);
gsr_capture_base_stop(&cap_nvfbc->base);
gsr_cuda_unload(&cap_nvfbc->cuda);
return -1;
}
@@ -432,14 +430,11 @@ static int gsr_capture_nvfbc_capture(gsr_capture *cap, AVFrame *frame) {
}
static void gsr_capture_nvfbc_destroy(gsr_capture *cap, AVCodecContext *video_codec_context) {
(void)video_codec_context;
gsr_capture_nvfbc *cap_nvfbc = cap->priv;
gsr_capture_nvfbc_destroy_session(cap);
if(video_codec_context->hw_device_ctx)
av_buffer_unref(&video_codec_context->hw_device_ctx);
if(video_codec_context->hw_frames_ctx)
av_buffer_unref(&video_codec_context->hw_frames_ctx);
if(cap_nvfbc) {
gsr_capture_base_stop(&cap_nvfbc->base, cap_nvfbc->params.egl);
gsr_capture_base_stop(&cap_nvfbc->base);
gsr_cuda_unload(&cap_nvfbc->cuda);
dlclose(cap_nvfbc->library);
free((void*)cap_nvfbc->params.display_to_capture);

View File

@@ -42,6 +42,7 @@ static Window get_focused_window(Display *display, Atom net_active_window_atom)
int gsr_capture_xcomposite_start(gsr_capture_xcomposite *self, AVCodecContext *video_codec_context, AVFrame *frame) {
self->base.video_codec_context = video_codec_context;
self->base.egl = self->params.egl;
if(self->params.follow_focused) {
self->net_active_window_atom = XInternAtom(self->params.egl->x11.dpy, "_NET_ACTIVE_WINDOW", False);
@@ -89,7 +90,7 @@ int gsr_capture_xcomposite_start(gsr_capture_xcomposite *self, AVCodecContext *v
}
if(gsr_cursor_init(&self->cursor, self->params.egl, self->params.egl->x11.dpy) != 0) {
gsr_capture_xcomposite_stop(self, video_codec_context);
gsr_capture_xcomposite_stop(self);
return -1;
}
@@ -119,10 +120,10 @@ int gsr_capture_xcomposite_start(gsr_capture_xcomposite *self, AVCodecContext *v
return 0;
}
void gsr_capture_xcomposite_stop(gsr_capture_xcomposite *self, AVCodecContext *video_codec_context) {
(void)video_codec_context;
void gsr_capture_xcomposite_stop(gsr_capture_xcomposite *self) {
window_texture_deinit(&self->window_texture);
gsr_cursor_deinit(&self->cursor);
gsr_capture_base_stop(&self->base);
}
void gsr_capture_xcomposite_tick(gsr_capture_xcomposite *self, AVCodecContext *video_codec_context) {

View File

@@ -33,7 +33,7 @@ static int gsr_capture_xcomposite_cuda_start(gsr_capture *cap, AVCodecContext *v
return -1;
}
if(!cuda_create_codec_context(cap_xcomp->cuda.cu_ctx, video_codec_context, &cap_xcomp->cuda_stream)) {
if(!cuda_create_codec_context(cap_xcomp->cuda.cu_ctx, video_codec_context, video_codec_context->width, video_codec_context->height, &cap_xcomp->cuda_stream)) {
gsr_capture_xcomposite_cuda_stop(cap, video_codec_context);
return -1;
}
@@ -44,7 +44,7 @@ static int gsr_capture_xcomposite_cuda_start(gsr_capture *cap, AVCodecContext *v
.mapped_arrays = cap_xcomp->mapped_arrays
};
if(!gsr_capture_base_setup_cuda_textures(&cap_xcomp->xcomposite.base, frame, &cuda_context, cap_xcomp->xcomposite.params.egl, cap_xcomp->xcomposite.params.color_range, GSR_SOURCE_COLOR_RGB, false)) {
if(!gsr_capture_base_setup_cuda_textures(&cap_xcomp->xcomposite.base, frame, &cuda_context, cap_xcomp->xcomposite.params.color_range, GSR_SOURCE_COLOR_RGB, false)) {
gsr_capture_xcomposite_cuda_stop(cap, video_codec_context);
return -1;
}
@@ -70,15 +70,9 @@ static void gsr_capture_xcomposite_unload_cuda_graphics(gsr_capture_xcomposite_c
}
static void gsr_capture_xcomposite_cuda_stop(gsr_capture *cap, AVCodecContext *video_codec_context) {
(void)video_codec_context;
gsr_capture_xcomposite_cuda *cap_xcomp = cap->priv;
if(video_codec_context->hw_device_ctx)
av_buffer_unref(&video_codec_context->hw_device_ctx);
if(video_codec_context->hw_frames_ctx)
av_buffer_unref(&video_codec_context->hw_frames_ctx);
gsr_capture_base_stop(&cap_xcomp->xcomposite.base, cap_xcomp->xcomposite.params.egl);
gsr_capture_xcomposite_stop(&cap_xcomp->xcomposite, video_codec_context);
gsr_capture_xcomposite_stop(&cap_xcomp->xcomposite);
gsr_capture_xcomposite_unload_cuda_graphics(cap_xcomp);
gsr_cuda_unload(&cap_xcomp->cuda);
}

View File

@@ -25,12 +25,12 @@ static int gsr_capture_xcomposite_vaapi_start(gsr_capture *cap, AVCodecContext *
return res;
}
if(!drm_create_codec_context(cap_xcomp->xcomposite.params.egl->card_path, video_codec_context, false, &cap_xcomp->va_dpy)) {
if(!drm_create_codec_context(cap_xcomp->xcomposite.params.egl->card_path, video_codec_context, video_codec_context->width, video_codec_context->height, false, &cap_xcomp->va_dpy)) {
gsr_capture_xcomposite_vaapi_stop(cap, video_codec_context);
return -1;
}
if(!gsr_capture_base_setup_vaapi_textures(&cap_xcomp->xcomposite.base, frame, cap_xcomp->xcomposite.params.egl, cap_xcomp->va_dpy, &cap_xcomp->prime, cap_xcomp->xcomposite.params.color_range)) {
if(!gsr_capture_base_setup_vaapi_textures(&cap_xcomp->xcomposite.base, frame, cap_xcomp->va_dpy, &cap_xcomp->prime, cap_xcomp->xcomposite.params.color_range)) {
gsr_capture_xcomposite_vaapi_stop(cap, video_codec_context);
return -1;
}
@@ -54,6 +54,7 @@ static int gsr_capture_xcomposite_vaapi_capture(gsr_capture *cap, AVFrame *frame
}
static void gsr_capture_xcomposite_vaapi_stop(gsr_capture *cap, AVCodecContext *video_codec_context) {
(void)video_codec_context;
gsr_capture_xcomposite_vaapi *cap_xcomp = cap->priv;
for(uint32_t i = 0; i < cap_xcomp->prime.num_objects; ++i) {
@@ -63,13 +64,7 @@ static void gsr_capture_xcomposite_vaapi_stop(gsr_capture *cap, AVCodecContext *
}
}
if(video_codec_context->hw_device_ctx)
av_buffer_unref(&video_codec_context->hw_device_ctx);
if(video_codec_context->hw_frames_ctx)
av_buffer_unref(&video_codec_context->hw_frames_ctx);
gsr_capture_base_stop(&cap_xcomp->xcomposite.base, cap_xcomp->xcomposite.params.egl);
gsr_capture_xcomposite_stop(&cap_xcomp->xcomposite, video_codec_context);
gsr_capture_xcomposite_stop(&cap_xcomp->xcomposite);
}
static void gsr_capture_xcomposite_vaapi_destroy(gsr_capture *cap, AVCodecContext *video_codec_context) {