mirror of
https://repo.dec05eba.com/gpu-screen-recorder
synced 2026-03-31 09:07:13 +09:00
X11 nvidia monitor capture: fix capture broken after sleep/suspend or monitor reconfiguration
This commit is contained in:
4
TODO
4
TODO
@@ -34,8 +34,6 @@ NVreg_RegistryDwords.
|
||||
Restore nvfbc screen recording on monitor reconfiguration.
|
||||
Window capture doesn't work properly in _control_ game after going from pause menu to in-game (and back to pause menu). There might be some x11 event we need to catch. Same for vr-video-player.
|
||||
|
||||
Properly handle monitor reconfiguration (kms vaapi, nvfbc).
|
||||
|
||||
Monitor capture on steam deck is slightly below the game fps, but only when capturing on the steam deck screen. If capturing on another monitor, there is no issue.
|
||||
Is this related to the dma buf rotation issue? different modifier being slow? does this always happen?
|
||||
|
||||
@@ -80,8 +78,6 @@ Preset is set to p5 for now but it should ideally be p6 or p7.
|
||||
For low latency, see https://developer.download.nvidia.com/compute/nvenc/v4.0/NVENC_VideoEncoder_API_ProgGuide.pdf (section 7.1).
|
||||
Remove follow focused option.
|
||||
|
||||
Overclocking (-oc) can overclock too much on some systems. Maybe remove the option?
|
||||
|
||||
Exit if X11/Wayland killed (if drm plane dead or something?)
|
||||
|
||||
Use SRC_W and SRC_H for screen plane instead of crtc_w and crtc_h.
|
||||
|
||||
@@ -14,7 +14,7 @@ if [ -d "/usr/lib/systemd/user" ]; then
|
||||
fi
|
||||
# Not necessary, but removes the password prompt when trying to record a monitor on amd/intel or nvidia wayland
|
||||
setcap cap_sys_admin+ep /usr/bin/gsr-kms-server
|
||||
# Not necessary, but allows use of EGL_CONTEXT_PRIORITY_LEVEL_IMG which allows gpu screen recorder to run without being limited to game fps under heavy load
|
||||
# Not necessary, but allows use of EGL_CONTEXT_PRIORITY_LEVEL_IMG which allows gpu screen recorder to run without being limited to game fps under heavy load on AMD/Intel
|
||||
setcap cap_sys_nice+ep /usr/bin/gpu-screen-recorder
|
||||
|
||||
echo "Successfully installed gpu-screen-recorder (debug)"
|
||||
|
||||
@@ -16,7 +16,7 @@ if [ -d "/usr/lib/systemd/user" ]; then
|
||||
fi
|
||||
# Not necessary, but removes the password prompt when trying to record a monitor on amd/intel or nvidia wayland
|
||||
setcap cap_sys_admin+ep /usr/bin/gsr-kms-server
|
||||
# Not necessary, but allows use of EGL_CONTEXT_PRIORITY_LEVEL_IMG which allows gpu screen recorder to run without being limited to game fps under heavy load
|
||||
# Not necessary, but allows use of EGL_CONTEXT_PRIORITY_LEVEL_IMG which allows gpu screen recorder to run without being limited to game fps under heavy load on AMD/Intel
|
||||
setcap cap_sys_nice+ep /usr/bin/gpu-screen-recorder
|
||||
|
||||
echo "Successfully installed gpu-screen-recorder"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "../../external/NvFBC.h"
|
||||
#include "../../include/cuda.h"
|
||||
#include "../../include/egl.h"
|
||||
#include "../../include/utils.h"
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -30,6 +31,16 @@ typedef struct {
|
||||
CUarray mapped_arrays[2];
|
||||
CUstream cuda_stream; // TODO: asdasdsa
|
||||
NVFBC_TOGL_SETUP_PARAMS setup_params;
|
||||
|
||||
bool direct_capture;
|
||||
bool supports_direct_cursor;
|
||||
bool capture_region;
|
||||
uint32_t x, y, width, height;
|
||||
NVFBC_TRACKING_TYPE tracking_type;
|
||||
uint32_t output_id;
|
||||
uint32_t tracking_width, tracking_height;
|
||||
bool nvfbc_needs_recreate;
|
||||
double nvfbc_dead_start;
|
||||
} gsr_capture_nvfbc;
|
||||
|
||||
#if defined(_WIN64) || defined(__LP64__)
|
||||
@@ -157,57 +168,34 @@ static void set_vertical_sync_enabled(gsr_egl *egl, int enabled) {
|
||||
fprintf(stderr, "gsr warning: setting vertical sync failed\n");
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if(!gsr_capture_nvfbc_load_library(cap)) {
|
||||
gsr_cuda_unload(&cap_nvfbc->cuda);
|
||||
return -1;
|
||||
static void gsr_capture_nvfbc_destroy_session(gsr_capture_nvfbc *cap_nvfbc) {
|
||||
if(cap_nvfbc->fbc_handle_created && cap_nvfbc->capture_session_created) {
|
||||
NVFBC_DESTROY_CAPTURE_SESSION_PARAMS destroy_capture_params;
|
||||
memset(&destroy_capture_params, 0, sizeof(destroy_capture_params));
|
||||
destroy_capture_params.dwVersion = NVFBC_DESTROY_CAPTURE_SESSION_PARAMS_VER;
|
||||
cap_nvfbc->nv_fbc_function_list.nvFBCDestroyCaptureSession(cap_nvfbc->nv_fbc_handle, &destroy_capture_params);
|
||||
cap_nvfbc->capture_session_created = false;
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t x = max_int(cap_nvfbc->params.pos.x, 0);
|
||||
const uint32_t y = max_int(cap_nvfbc->params.pos.y, 0);
|
||||
const uint32_t width = max_int(cap_nvfbc->params.size.x, 0);
|
||||
const uint32_t height = max_int(cap_nvfbc->params.size.y, 0);
|
||||
|
||||
const bool capture_region = (x > 0 || y > 0 || width > 0 || height > 0);
|
||||
|
||||
bool supports_direct_cursor = false;
|
||||
bool direct_capture = cap_nvfbc->params.direct_capture;
|
||||
int driver_major_version = 0;
|
||||
int driver_minor_version = 0;
|
||||
if(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);
|
||||
|
||||
// TODO:
|
||||
if(version_at_least(driver_major_version, driver_minor_version, 515, 57) && version_less_than(driver_major_version, driver_minor_version, 520, 56)) {
|
||||
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");
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// Cursor capture disabled because moving the cursor doesn't update capture rate to monitor hz and instead captures at 10-30 hz
|
||||
/*
|
||||
if(direct_capture) {
|
||||
if(version_at_least(driver_major_version, driver_minor_version, 515, 57))
|
||||
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");
|
||||
}
|
||||
*/
|
||||
static void gsr_capture_nvfbc_destroy_handle(gsr_capture_nvfbc *cap_nvfbc) {
|
||||
if(cap_nvfbc->fbc_handle_created) {
|
||||
NVFBC_DESTROY_HANDLE_PARAMS destroy_params;
|
||||
memset(&destroy_params, 0, sizeof(destroy_params));
|
||||
destroy_params.dwVersion = NVFBC_DESTROY_HANDLE_PARAMS_VER;
|
||||
cap_nvfbc->nv_fbc_function_list.nvFBCDestroyHandle(cap_nvfbc->nv_fbc_handle, &destroy_params);
|
||||
cap_nvfbc->fbc_handle_created = false;
|
||||
cap_nvfbc->nv_fbc_handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void gsr_capture_nvfbc_destroy_session_and_handle(gsr_capture_nvfbc *cap_nvfbc) {
|
||||
gsr_capture_nvfbc_destroy_session(cap_nvfbc);
|
||||
gsr_capture_nvfbc_destroy_handle(cap_nvfbc);
|
||||
}
|
||||
|
||||
static int gsr_capture_nvfbc_setup_handle(gsr_capture_nvfbc *cap_nvfbc) {
|
||||
NVFBCSTATUS status;
|
||||
NVFBC_TRACKING_TYPE tracking_type;
|
||||
uint32_t output_id = 0;
|
||||
cap_nvfbc->fbc_handle_created = false;
|
||||
cap_nvfbc->capture_session_created = false;
|
||||
|
||||
NVFBC_CREATE_HANDLE_PARAMS create_params;
|
||||
memset(&create_params, 0, sizeof(create_params));
|
||||
@@ -246,10 +234,10 @@ static int gsr_capture_nvfbc_start(gsr_capture *cap, AVCodecContext *video_codec
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
uint32_t tracking_width = XWidthOfScreen(DefaultScreenOfDisplay(cap_nvfbc->params.egl->x11.dpy));
|
||||
uint32_t tracking_height = XHeightOfScreen(DefaultScreenOfDisplay(cap_nvfbc->params.egl->x11.dpy));
|
||||
tracking_type = strcmp(cap_nvfbc->params.display_to_capture, "screen") == 0 ? NVFBC_TRACKING_SCREEN : NVFBC_TRACKING_OUTPUT;
|
||||
if(tracking_type == NVFBC_TRACKING_OUTPUT) {
|
||||
cap_nvfbc->tracking_width = XWidthOfScreen(DefaultScreenOfDisplay(cap_nvfbc->params.egl->x11.dpy));
|
||||
cap_nvfbc->tracking_height = XHeightOfScreen(DefaultScreenOfDisplay(cap_nvfbc->params.egl->x11.dpy));
|
||||
cap_nvfbc->tracking_type = strcmp(cap_nvfbc->params.display_to_capture, "screen") == 0 ? NVFBC_TRACKING_SCREEN : NVFBC_TRACKING_OUTPUT;
|
||||
if(cap_nvfbc->tracking_type == NVFBC_TRACKING_OUTPUT) {
|
||||
if(!status_params.bXRandRAvailable) {
|
||||
fprintf(stderr, "gsr error: gsr_capture_nvfbc_start failed: the xrandr extension is not available\n");
|
||||
goto error_cleanup;
|
||||
@@ -260,34 +248,42 @@ static int gsr_capture_nvfbc_start(gsr_capture *cap, AVCodecContext *video_codec
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
output_id = get_output_id_from_display_name(status_params.outputs, status_params.dwOutputNum, cap_nvfbc->params.display_to_capture, &tracking_width, &tracking_height);
|
||||
if(output_id == 0) {
|
||||
cap_nvfbc->output_id = get_output_id_from_display_name(status_params.outputs, status_params.dwOutputNum, cap_nvfbc->params.display_to_capture, &cap_nvfbc->tracking_width, &cap_nvfbc->tracking_height);
|
||||
if(cap_nvfbc->output_id == 0) {
|
||||
fprintf(stderr, "gsr error: gsr_capture_nvfbc_start failed: display '%s' not found\n", cap_nvfbc->params.display_to_capture);
|
||||
goto error_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_cleanup:
|
||||
gsr_capture_nvfbc_destroy_session_and_handle(cap_nvfbc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int gsr_capture_nvfbc_setup_session(gsr_capture_nvfbc *cap_nvfbc) {
|
||||
NVFBC_CREATE_CAPTURE_SESSION_PARAMS create_capture_params;
|
||||
memset(&create_capture_params, 0, sizeof(create_capture_params));
|
||||
create_capture_params.dwVersion = NVFBC_CREATE_CAPTURE_SESSION_PARAMS_VER;
|
||||
create_capture_params.eCaptureType = NVFBC_CAPTURE_TO_GL;
|
||||
create_capture_params.bWithCursor = (!direct_capture || supports_direct_cursor) ? NVFBC_TRUE : NVFBC_FALSE;
|
||||
create_capture_params.bWithCursor = (!cap_nvfbc->direct_capture || cap_nvfbc->supports_direct_cursor) ? NVFBC_TRUE : NVFBC_FALSE;
|
||||
if(!cap_nvfbc->params.record_cursor)
|
||||
create_capture_params.bWithCursor = false;
|
||||
if(capture_region)
|
||||
create_capture_params.captureBox = (NVFBC_BOX){ x, y, width, height };
|
||||
create_capture_params.eTrackingType = tracking_type;
|
||||
if(cap_nvfbc->capture_region)
|
||||
create_capture_params.captureBox = (NVFBC_BOX){ cap_nvfbc->x, cap_nvfbc->y, cap_nvfbc->width, cap_nvfbc->height };
|
||||
create_capture_params.eTrackingType = cap_nvfbc->tracking_type;
|
||||
create_capture_params.dwSamplingRateMs = (uint32_t)ceilf(1000.0f / (float)cap_nvfbc->params.fps);
|
||||
create_capture_params.bAllowDirectCapture = direct_capture ? NVFBC_TRUE : NVFBC_FALSE;
|
||||
create_capture_params.bPushModel = direct_capture ? NVFBC_TRUE : NVFBC_FALSE;
|
||||
//create_capture_params.bDisableAutoModesetRecovery = true; // TODO:
|
||||
if(tracking_type == NVFBC_TRACKING_OUTPUT)
|
||||
create_capture_params.dwOutputId = output_id;
|
||||
create_capture_params.bAllowDirectCapture = cap_nvfbc->direct_capture ? NVFBC_TRUE : NVFBC_FALSE;
|
||||
create_capture_params.bPushModel = cap_nvfbc->direct_capture ? NVFBC_TRUE : NVFBC_FALSE;
|
||||
create_capture_params.bDisableAutoModesetRecovery = true;
|
||||
if(cap_nvfbc->tracking_type == NVFBC_TRACKING_OUTPUT)
|
||||
create_capture_params.dwOutputId = cap_nvfbc->output_id;
|
||||
|
||||
status = cap_nvfbc->nv_fbc_function_list.nvFBCCreateCaptureSession(cap_nvfbc->nv_fbc_handle, &create_capture_params);
|
||||
NVFBCSTATUS status = cap_nvfbc->nv_fbc_function_list.nvFBCCreateCaptureSession(cap_nvfbc->nv_fbc_handle, &create_capture_params);
|
||||
if(status != NVFBC_SUCCESS) {
|
||||
fprintf(stderr, "gsr error: gsr_capture_nvfbc_start failed: %s\n", cap_nvfbc->nv_fbc_function_list.nvFBCGetLastErrorStr(cap_nvfbc->nv_fbc_handle));
|
||||
goto error_cleanup;
|
||||
return -1;
|
||||
}
|
||||
cap_nvfbc->capture_session_created = true;
|
||||
|
||||
@@ -298,15 +294,73 @@ static int gsr_capture_nvfbc_start(gsr_capture *cap, AVCodecContext *video_codec
|
||||
status = cap_nvfbc->nv_fbc_function_list.nvFBCToGLSetUp(cap_nvfbc->nv_fbc_handle, &cap_nvfbc->setup_params);
|
||||
if(status != NVFBC_SUCCESS) {
|
||||
fprintf(stderr, "gsr error: gsr_capture_nvfbc_start failed: %s\n", cap_nvfbc->nv_fbc_function_list.nvFBCGetLastErrorStr(cap_nvfbc->nv_fbc_handle));
|
||||
gsr_capture_nvfbc_destroy_session(cap_nvfbc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if(!gsr_capture_nvfbc_load_library(cap)) {
|
||||
gsr_cuda_unload(&cap_nvfbc->cuda);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cap_nvfbc->x = max_int(cap_nvfbc->params.pos.x, 0);
|
||||
cap_nvfbc->y = max_int(cap_nvfbc->params.pos.y, 0);
|
||||
cap_nvfbc->width = max_int(cap_nvfbc->params.size.x, 0);
|
||||
cap_nvfbc->height = max_int(cap_nvfbc->params.size.y, 0);
|
||||
|
||||
cap_nvfbc->capture_region = (cap_nvfbc->x > 0 || cap_nvfbc->y > 0 || cap_nvfbc->width > 0 || cap_nvfbc->height > 0);
|
||||
|
||||
cap_nvfbc->supports_direct_cursor = false;
|
||||
bool direct_capture = cap_nvfbc->params.direct_capture;
|
||||
int driver_major_version = 0;
|
||||
int driver_minor_version = 0;
|
||||
if(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);
|
||||
|
||||
// TODO:
|
||||
if(version_at_least(driver_major_version, driver_minor_version, 515, 57) && version_less_than(driver_major_version, driver_minor_version, 520, 56)) {
|
||||
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");
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// Cursor capture disabled because moving the cursor doesn't update capture rate to monitor hz and instead captures at 10-30 hz
|
||||
/*
|
||||
if(direct_capture) {
|
||||
if(version_at_least(driver_major_version, driver_minor_version, 515, 57))
|
||||
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");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if(gsr_capture_nvfbc_setup_handle(cap_nvfbc) != 0) {
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
if(capture_region) {
|
||||
video_codec_context->width = width & ~1;
|
||||
video_codec_context->height = height & ~1;
|
||||
if(gsr_capture_nvfbc_setup_session(cap_nvfbc) != 0) {
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
if(cap_nvfbc->capture_region) {
|
||||
video_codec_context->width = cap_nvfbc->width & ~1;
|
||||
video_codec_context->height = cap_nvfbc->height & ~1;
|
||||
} else {
|
||||
video_codec_context->width = tracking_width & ~1;
|
||||
video_codec_context->height = tracking_height & ~1;
|
||||
video_codec_context->width = cap_nvfbc->tracking_width & ~1;
|
||||
video_codec_context->height = cap_nvfbc->tracking_height & ~1;
|
||||
}
|
||||
|
||||
frame->width = video_codec_context->width;
|
||||
@@ -331,52 +385,38 @@ static int gsr_capture_nvfbc_start(gsr_capture *cap, AVCodecContext *video_codec
|
||||
return 0;
|
||||
|
||||
error_cleanup:
|
||||
if(cap_nvfbc->fbc_handle_created) {
|
||||
if(cap_nvfbc->capture_session_created) {
|
||||
NVFBC_DESTROY_CAPTURE_SESSION_PARAMS destroy_capture_params;
|
||||
memset(&destroy_capture_params, 0, sizeof(destroy_capture_params));
|
||||
destroy_capture_params.dwVersion = NVFBC_DESTROY_CAPTURE_SESSION_PARAMS_VER;
|
||||
cap_nvfbc->nv_fbc_function_list.nvFBCDestroyCaptureSession(cap_nvfbc->nv_fbc_handle, &destroy_capture_params);
|
||||
cap_nvfbc->capture_session_created = false;
|
||||
}
|
||||
|
||||
NVFBC_DESTROY_HANDLE_PARAMS destroy_params;
|
||||
memset(&destroy_params, 0, sizeof(destroy_params));
|
||||
destroy_params.dwVersion = NVFBC_DESTROY_HANDLE_PARAMS_VER;
|
||||
cap_nvfbc->nv_fbc_function_list.nvFBCDestroyHandle(cap_nvfbc->nv_fbc_handle, &destroy_params);
|
||||
cap_nvfbc->fbc_handle_created = false;
|
||||
}
|
||||
|
||||
gsr_capture_nvfbc_destroy_session_and_handle(cap_nvfbc);
|
||||
gsr_capture_base_stop(&cap_nvfbc->base);
|
||||
gsr_cuda_unload(&cap_nvfbc->cuda);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void gsr_capture_nvfbc_destroy_session(gsr_capture *cap) {
|
||||
gsr_capture_nvfbc *cap_nvfbc = cap->priv;
|
||||
|
||||
if(cap_nvfbc->fbc_handle_created) {
|
||||
if(cap_nvfbc->capture_session_created) {
|
||||
NVFBC_DESTROY_CAPTURE_SESSION_PARAMS destroy_capture_params;
|
||||
memset(&destroy_capture_params, 0, sizeof(destroy_capture_params));
|
||||
destroy_capture_params.dwVersion = NVFBC_DESTROY_CAPTURE_SESSION_PARAMS_VER;
|
||||
cap_nvfbc->nv_fbc_function_list.nvFBCDestroyCaptureSession(cap_nvfbc->nv_fbc_handle, &destroy_capture_params);
|
||||
cap_nvfbc->capture_session_created = false;
|
||||
}
|
||||
|
||||
NVFBC_DESTROY_HANDLE_PARAMS destroy_params;
|
||||
memset(&destroy_params, 0, sizeof(destroy_params));
|
||||
destroy_params.dwVersion = NVFBC_DESTROY_HANDLE_PARAMS_VER;
|
||||
cap_nvfbc->nv_fbc_function_list.nvFBCDestroyHandle(cap_nvfbc->nv_fbc_handle, &destroy_params);
|
||||
cap_nvfbc->fbc_handle_created = false;
|
||||
}
|
||||
|
||||
cap_nvfbc->nv_fbc_handle = 0;
|
||||
}
|
||||
|
||||
static int gsr_capture_nvfbc_capture(gsr_capture *cap, AVFrame *frame) {
|
||||
gsr_capture_nvfbc *cap_nvfbc = cap->priv;
|
||||
|
||||
const double nvfbc_recreate_retry_time_seconds = 1.0;
|
||||
if(cap_nvfbc->nvfbc_needs_recreate) {
|
||||
const double now = clock_get_monotonic_seconds();
|
||||
if(now - cap_nvfbc->nvfbc_dead_start >= nvfbc_recreate_retry_time_seconds) {
|
||||
cap_nvfbc->nvfbc_dead_start = now;
|
||||
gsr_capture_nvfbc_destroy_session_and_handle(cap_nvfbc);
|
||||
|
||||
if(gsr_capture_nvfbc_setup_handle(cap_nvfbc) != 0) {
|
||||
fprintf(stderr, "gsr error: gsr_capture_nvfbc_capture failed to recreate nvfbc handle, trying again in %f second(s)\n", nvfbc_recreate_retry_time_seconds);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(gsr_capture_nvfbc_setup_session(cap_nvfbc) != 0) {
|
||||
fprintf(stderr, "gsr error: gsr_capture_nvfbc_capture failed to recreate nvfbc session, trying again in %f second(s)\n", nvfbc_recreate_retry_time_seconds);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cap_nvfbc->nvfbc_needs_recreate = false;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
NVFBC_FRAME_GRAB_INFO frame_info;
|
||||
memset(&frame_info, 0, sizeof(frame_info));
|
||||
|
||||
@@ -389,8 +429,10 @@ static int gsr_capture_nvfbc_capture(gsr_capture *cap, AVFrame *frame) {
|
||||
|
||||
NVFBCSTATUS status = cap_nvfbc->nv_fbc_function_list.nvFBCToGLGrabFrame(cap_nvfbc->nv_fbc_handle, &grab_params);
|
||||
if(status != NVFBC_SUCCESS) {
|
||||
fprintf(stderr, "gsr error: gsr_capture_nvfbc_capture failed: %s\n", cap_nvfbc->nv_fbc_function_list.nvFBCGetLastErrorStr(cap_nvfbc->nv_fbc_handle));
|
||||
return -1;
|
||||
fprintf(stderr, "gsr error: gsr_capture_nvfbc_capture failed: %s (%d), recreating session after %f second(s)\n", cap_nvfbc->nv_fbc_function_list.nvFBCGetLastErrorStr(cap_nvfbc->nv_fbc_handle), status, nvfbc_recreate_retry_time_seconds);
|
||||
cap_nvfbc->nvfbc_needs_recreate = true;
|
||||
cap_nvfbc->nvfbc_dead_start = clock_get_monotonic_seconds();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//cap_nvfbc->params.egl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
@@ -434,7 +476,7 @@ 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);
|
||||
gsr_capture_nvfbc_destroy_session_and_handle(cap_nvfbc);
|
||||
if(cap_nvfbc) {
|
||||
gsr_capture_base_stop(&cap_nvfbc->base);
|
||||
gsr_cuda_unload(&cap_nvfbc->cuda);
|
||||
|
||||
@@ -2424,7 +2424,7 @@ int main(int argc, char **argv) {
|
||||
if(got_audio_data)
|
||||
received_audio_time = this_audio_frame_time;
|
||||
|
||||
// Jesus is there a better way to do this? I JUST WANT TO KEEP VIDEO AND AUDIO SYNCED HOLY FUCK I WANT TO KILL MYSELF NOW.
|
||||
// Fucking hell is there a better way to do this? I JUST WANT TO KEEP VIDEO AND AUDIO SYNCED HOLY FUCK I WANT TO KILL MYSELF NOW.
|
||||
// THIS PIECE OF SHIT WANTS EMPTY FRAMES OTHERWISE VIDEO PLAYS TOO FAST TO KEEP UP WITH AUDIO OR THE AUDIO PLAYS TOO EARLY.
|
||||
// BUT WE CANT USE DELAYS TO GIVE DUMMY DATA BECAUSE PULSEAUDIO MIGHT GIVE AUDIO A BIG DELAYED!!!
|
||||
// This garbage is needed because we want to produce constant frame rate videos instead of variable frame rate
|
||||
|
||||
Reference in New Issue
Block a user