diff options
Diffstat (limited to 'src/capture/nvfbc.c')
-rw-r--r-- | src/capture/nvfbc.c | 112 |
1 files changed, 44 insertions, 68 deletions
diff --git a/src/capture/nvfbc.c b/src/capture/nvfbc.c index ee77a20..13b46c3 100644 --- a/src/capture/nvfbc.c +++ b/src/capture/nvfbc.c @@ -3,15 +3,16 @@ #include "../../include/egl.h" #include "../../include/utils.h" #include "../../include/color_conversion.h" +#include "../../include/window/window.h" #include <dlfcn.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <math.h> +#include <assert.h> #include <X11/Xlib.h> -#include <libavcodec/avcodec.h> typedef struct { gsr_capture_nvfbc_params params; @@ -26,8 +27,7 @@ typedef struct { NVFBC_TOGL_SETUP_PARAMS setup_params; bool supports_direct_cursor; - bool capture_region; - uint32_t x, y, width, height; + uint32_t width, height; NVFBC_TRACKING_TYPE tracking_type; uint32_t output_id; uint32_t tracking_width, tracking_height; @@ -131,28 +131,6 @@ static bool gsr_capture_nvfbc_load_library(gsr_capture *cap) { return true; } -/* TODO: check for glx swap control extension string (GLX_EXT_swap_control, etc) */ -static void set_vertical_sync_enabled(gsr_egl *egl, int enabled) { - int result = 0; - - if(egl->glXSwapIntervalEXT) { - egl->glXSwapIntervalEXT(egl->x11.dpy, egl->x11.window, enabled ? 1 : 0); - } else if(egl->glXSwapIntervalMESA) { - result = egl->glXSwapIntervalMESA(enabled ? 1 : 0); - } else if(egl->glXSwapIntervalSGI) { - result = egl->glXSwapIntervalSGI(enabled ? 1 : 0); - } else { - static int warned = 0; - if (!warned) { - warned = 1; - fprintf(stderr, "gsr warning: setting vertical sync not supported\n"); - } - } - - if(result != 0) - fprintf(stderr, "gsr warning: setting vertical sync failed\n"); -} - static void gsr_capture_nvfbc_destroy_session(gsr_capture_nvfbc *self) { if(self->fbc_handle_created && self->capture_session_created) { NVFBC_DESTROY_CAPTURE_SESSION_PARAMS destroy_capture_params; @@ -219,8 +197,11 @@ static int gsr_capture_nvfbc_setup_handle(gsr_capture_nvfbc *self) { goto error_cleanup; } - self->tracking_width = XWidthOfScreen(DefaultScreenOfDisplay(self->params.egl->x11.dpy)); - self->tracking_height = XHeightOfScreen(DefaultScreenOfDisplay(self->params.egl->x11.dpy)); + assert(gsr_window_get_display_server(self->params.egl->window) == GSR_DISPLAY_SERVER_X11); + Display *display = gsr_window_get_display(self->params.egl->window); + + self->tracking_width = XWidthOfScreen(DefaultScreenOfDisplay(display)); + self->tracking_height = XHeightOfScreen(DefaultScreenOfDisplay(display)); self->tracking_type = strcmp(self->params.display_to_capture, "screen") == 0 ? NVFBC_TRACKING_SCREEN : NVFBC_TRACKING_OUTPUT; if(self->tracking_type == NVFBC_TRACKING_OUTPUT) { if(!status_params.bXRandRAvailable) { @@ -240,6 +221,8 @@ static int gsr_capture_nvfbc_setup_handle(gsr_capture_nvfbc *self) { } } + self->width = self->tracking_width; + self->height = self->tracking_height; return 0; error_cleanup: @@ -255,8 +238,6 @@ static int gsr_capture_nvfbc_setup_session(gsr_capture_nvfbc *self) { create_capture_params.bWithCursor = (!self->params.direct_capture || self->supports_direct_cursor) ? NVFBC_TRUE : NVFBC_FALSE; if(!self->params.record_cursor) create_capture_params.bWithCursor = false; - if(self->capture_region) - create_capture_params.captureBox = (NVFBC_BOX){ self->x, self->y, self->width, self->height }; create_capture_params.eTrackingType = self->tracking_type; create_capture_params.dwSamplingRateMs = (uint32_t)ceilf(1000.0f / (float)self->params.fps); create_capture_params.bAllowDirectCapture = self->params.direct_capture ? NVFBC_TRUE : NVFBC_FALSE; @@ -298,29 +279,22 @@ static void gsr_capture_nvfbc_stop(gsr_capture_nvfbc *self) { } } -static int gsr_capture_nvfbc_start(gsr_capture *cap, AVCodecContext *video_codec_context, AVFrame *frame) { +static int gsr_capture_nvfbc_start(gsr_capture *cap, gsr_capture_metadata *capture_metadata) { gsr_capture_nvfbc *self = cap->priv; if(!gsr_capture_nvfbc_load_library(cap)) return -1; - self->x = max_int(self->params.pos.x, 0); - self->y = max_int(self->params.pos.y, 0); - self->width = max_int(self->params.size.x, 0); - self->height = max_int(self->params.size.y, 0); - - self->capture_region = (self->x > 0 || self->y > 0 || self->width > 0 || self->height > 0); - self->supports_direct_cursor = false; int driver_major_version = 0; int driver_minor_version = 0; if(self->params.direct_capture && get_driver_version(&driver_major_version, &driver_minor_version)) { - fprintf(stderr, "Info: detected nvidia version: %d.%d\n", driver_major_version, driver_minor_version); + fprintf(stderr, "gsr info: detected nvidia version: %d.%d\n", driver_major_version, driver_minor_version); // TODO: if(version_at_least(driver_major_version, driver_minor_version, 515, 57) && version_less_than(driver_major_version, driver_minor_version, 520, 56)) { self->params.direct_capture = false; - fprintf(stderr, "Warning: \"screen-direct\" has temporary been disabled as it causes stuttering with driver versions >= 515.57 and < 520.56. Please update your driver if possible. Capturing \"screen\" instead.\n"); + fprintf(stderr, "gsr warning: \"screen-direct\" has temporary been disabled as it causes stuttering with driver versions >= 515.57 and < 520.56. Please update your driver if possible. Capturing \"screen\" instead.\n"); } // TODO: @@ -330,7 +304,7 @@ static int gsr_capture_nvfbc_start(gsr_capture *cap, AVCodecContext *video_codec if(version_at_least(driver_major_version, driver_minor_version, 515, 57)) self->supports_direct_cursor = true; else - fprintf(stderr, "Info: capturing \"screen-direct\" but driver version appears to be less than 515.57. Disabling capture of cursor. Please update your driver if you want to capture your cursor or record \"screen\" instead.\n"); + fprintf(stderr, "gsr info: capturing \"screen-direct\" but driver version appears to be less than 515.57. Disabling capture of cursor. Please update your driver if you want to capture your cursor or record \"screen\" instead.\n"); } */ } @@ -343,19 +317,17 @@ static int gsr_capture_nvfbc_start(gsr_capture *cap, AVCodecContext *video_codec goto error_cleanup; } - if(self->capture_region) { - video_codec_context->width = FFALIGN(self->width, 2); - video_codec_context->height = FFALIGN(self->height, 2); - } else { - video_codec_context->width = FFALIGN(self->tracking_width, 2); - video_codec_context->height = FFALIGN(self->tracking_height, 2); - } - - frame->width = video_codec_context->width; - frame->height = video_codec_context->height; + capture_metadata->width = self->tracking_width; + capture_metadata->height = self->tracking_height; - /* Disable vsync */ - set_vertical_sync_enabled(self->params.egl, 0); + if(self->params.output_resolution.x > 0 && self->params.output_resolution.y > 0) { + self->params.output_resolution = scale_keep_aspect_ratio((vec2i){capture_metadata->width, capture_metadata->height}, self->params.output_resolution); + capture_metadata->width = self->params.output_resolution.x; + capture_metadata->height = self->params.output_resolution.y; + } else if(self->params.region_size.x > 0 && self->params.region_size.y > 0) { + capture_metadata->width = self->params.region_size.x; + capture_metadata->height = self->params.region_size.y; + } return 0; @@ -364,7 +336,7 @@ static int gsr_capture_nvfbc_start(gsr_capture *cap, AVCodecContext *video_codec return -1; } -static int gsr_capture_nvfbc_capture(gsr_capture *cap, AVFrame *frame, gsr_color_conversion *color_conversion) { +static int gsr_capture_nvfbc_capture(gsr_capture *cap, gsr_capture_metadata *capture_metadata, gsr_color_conversion *color_conversion) { gsr_capture_nvfbc *self = cap->priv; const double nvfbc_recreate_retry_time_seconds = 1.0; @@ -390,6 +362,17 @@ static int gsr_capture_nvfbc_capture(gsr_capture *cap, AVFrame *frame, gsr_color } } + vec2i frame_size = (vec2i){self->width, self->height}; + const vec2i original_frame_size = frame_size; + if(self->params.region_size.x > 0 && self->params.region_size.y > 0) + frame_size = self->params.region_size; + + const bool is_scaled = self->params.output_resolution.x > 0 && self->params.output_resolution.y > 0; + vec2i output_size = is_scaled ? self->params.output_resolution : frame_size; + output_size = scale_keep_aspect_ratio(frame_size, output_size); + + 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) }; + NVFBC_FRAME_GRAB_INFO frame_info; memset(&frame_info, 0, sizeof(frame_info)); @@ -408,27 +391,21 @@ static int gsr_capture_nvfbc_capture(gsr_capture *cap, AVFrame *frame, gsr_color return 0; } - self->params.egl->glFlush(); - self->params.egl->glFinish(); + //self->params.egl->glFlush(); + //self->params.egl->glFinish(); gsr_color_conversion_draw(color_conversion, self->setup_params.dwTextures[grab_params.dwTextureIndex], - (vec2i){0, 0}, (vec2i){frame->width, frame->height}, - (vec2i){0, 0}, (vec2i){frame->width, frame->height}, - 0.0f, false); + target_pos, (vec2i){output_size.x, output_size.y}, + self->params.region_position, frame_size, original_frame_size, + GSR_ROT_0, GSR_SOURCE_COLOR_BGR, false, false); - self->params.egl->glFlush(); - self->params.egl->glFinish(); + //self->params.egl->glFlush(); + //self->params.egl->glFinish(); return 0; } -static gsr_source_color gsr_capture_nvfbc_get_source_color(gsr_capture *cap) { - (void)cap; - return GSR_SOURCE_COLOR_BGR; -} - -static void gsr_capture_nvfbc_destroy(gsr_capture *cap, AVCodecContext *video_codec_context) { - (void)video_codec_context; +static void gsr_capture_nvfbc_destroy(gsr_capture *cap) { gsr_capture_nvfbc *self = cap->priv; gsr_capture_nvfbc_stop(self); free(cap->priv); @@ -472,7 +449,6 @@ gsr_capture* gsr_capture_nvfbc_create(const gsr_capture_nvfbc_params *params) { .tick = NULL, .should_stop = NULL, .capture = gsr_capture_nvfbc_capture, - .get_source_color = gsr_capture_nvfbc_get_source_color, .uses_external_image = NULL, .destroy = gsr_capture_nvfbc_destroy, .priv = cap_nvfbc |