do not crash when resizing window

This commit is contained in:
dec05eba 2020-03-31 20:02:18 +02:00
parent 07a8635c55
commit 19dfa524d4
2 changed files with 51 additions and 10 deletions

View File

@ -12,7 +12,7 @@ the fps remains at 30.
X11, Nvidia (cuda) X11, Nvidia (cuda)
# TODO # TODO
* Support resizing the target window! right now that crashes the recorder. * Scale video when the window is rescaled.
* Use the sound source in src/sound.cpp to record audio and mux it with ffmpeg to the final video. * Use the sound source in src/sound.cpp to record audio and mux it with ffmpeg to the final video.
* Support AMD and Intel, using VAAPI. cuda and vaapi should be loaded at runtime using dlopen instead of linking to those * Support AMD and Intel, using VAAPI. cuda and vaapi should be loaded at runtime using dlopen instead of linking to those
libraries at compile-time. libraries at compile-time.

View File

@ -102,8 +102,8 @@ static void cleanup_window_pixmap(Display *dpy, WindowPixmap &pixmap) {
} }
if (pixmap.glx_pixmap) { if (pixmap.glx_pixmap) {
glXReleaseTexImageEXT(dpy, pixmap.glx_pixmap, GLX_FRONT_EXT);
glXDestroyPixmap(dpy, pixmap.glx_pixmap); glXDestroyPixmap(dpy, pixmap.glx_pixmap);
glXReleaseTexImageEXT(dpy, pixmap.glx_pixmap, GLX_FRONT_EXT);
pixmap.glx_pixmap = None; pixmap.glx_pixmap = None;
} }
@ -415,10 +415,12 @@ static void open_video(AVCodec *codec, AVStream *stream,
CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY); CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY);
// cuGraphicsUnregisterResource(*cuda_graphics_resource); // cuGraphicsUnregisterResource(*cuda_graphics_resource);
if (res != CUDA_SUCCESS) { if (res != CUDA_SUCCESS) {
const char *err_str;
cuGetErrorString(res, &err_str);
fprintf(stderr, fprintf(stderr,
"Error: cuGraphicsGLRegisterImage failed, error %d, texture " "Error: cuGraphicsGLRegisterImage failed, error %s, texture "
"id: %u\n", "id: %u\n",
res, window_pixmap.target_texture_id); err_str, window_pixmap.target_texture_id);
exit(1); exit(1);
} }
res = cuCtxPopCurrent(&old_ctx); res = cuCtxPopCurrent(&old_ctx);
@ -445,7 +447,7 @@ int main(int argc, char **argv) {
const char *filename = "/dev/stdout"; const char *filename = "/dev/stdout";
const float target_fps = 1.0f / (float)fps; const double target_fps = 1.0f / (double)fps;
Display *dpy = XOpenDisplay(nullptr); Display *dpy = XOpenDisplay(nullptr);
if (!dpy) { if (!dpy) {
@ -480,6 +482,10 @@ int main(int argc, char **argv) {
return 1; return 1;
} }
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow *window = GLFWwindow *window =
@ -493,7 +499,6 @@ int main(int argc, char **argv) {
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
glfwSwapInterval(0); glfwSwapInterval(0);
#define DEBUG
#if defined(DEBUG) #if defined(DEBUG)
XSetErrorHandler(x11_error_handler); XSetErrorHandler(x11_error_handler);
XSetIOErrorHandler(x11_io_error_handler); XSetIOErrorHandler(x11_io_error_handler);
@ -611,6 +616,8 @@ int main(int argc, char **argv) {
double start_time = glfwGetTime(); double start_time = glfwGetTime();
double frame_timer_start = start_time; double frame_timer_start = start_time;
double window_resize_timer = start_time;
bool window_resized = true;
int fps_counter = 0; int fps_counter = 0;
int current_fps = 30; int current_fps = 30;
@ -623,8 +630,7 @@ int main(int argc, char **argv) {
frame->width = video_stream->codec->width; frame->width = video_stream->codec->width;
frame->height = video_stream->codec->height; frame->height = video_stream->codec->height;
if (av_hwframe_get_buffer(video_stream->codec->hw_frames_ctx, frame, 0) < if (av_hwframe_get_buffer(video_stream->codec->hw_frames_ctx, frame, 0) < 0) {
0) {
fprintf(stderr, "Error: av_hwframe_get_buffer failed\n"); fprintf(stderr, "Error: av_hwframe_get_buffer failed\n");
exit(1); exit(1);
} }
@ -645,8 +651,8 @@ int main(int argc, char **argv) {
if(e.xconfigure.width != window_width || e.xconfigure.height != window_height) { if(e.xconfigure.width != window_width || e.xconfigure.height != window_height) {
window_width = e.xconfigure.width; window_width = e.xconfigure.width;
window_height = e.xconfigure.height; window_height = e.xconfigure.height;
fprintf(stderr, "Resize window!\n"); window_resize_timer = glfwGetTime();
recreate_window_pixmap(dpy, src_window_id, window_pixmap); window_resized = false;
} }
} }
@ -698,6 +704,41 @@ int main(int argc, char **argv) {
fps_counter = 0; fps_counter = 0;
} }
const double window_resize_timeout = 1.0; // 1 second
if(!window_resized && time_now - window_resize_timer >= window_resize_timeout) {
window_resized = true;
fprintf(stderr, "Resize window!\n");
recreate_window_pixmap(dpy, src_window_id, window_pixmap);
// Resolution must be a multiple of two
video_stream->codec->width = window_pixmap.texture_width & ~1;
video_stream->codec->height = window_pixmap.texture_height & ~1;
cuGraphicsUnregisterResource(cuda_graphics_resource);
res = cuGraphicsGLRegisterImage(
&cuda_graphics_resource, window_pixmap.target_texture_id, GL_TEXTURE_2D,
CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY);
if (res != CUDA_SUCCESS) {
const char *err_str;
cuGetErrorString(res, &err_str);
fprintf(stderr,
"Error: cuGraphicsGLRegisterImage failed, error %s, texture "
"id: %u\n",
err_str, window_pixmap.target_texture_id);
exit(1);
}
res = cuGraphicsResourceSetMapFlags(
cuda_graphics_resource, CU_GRAPHICS_MAP_RESOURCE_FLAGS_READ_ONLY);
res = cuGraphicsMapResources(1, &cuda_graphics_resource, 0);
res = cuGraphicsSubResourceGetMappedArray(&mapped_array, cuda_graphics_resource, 0, 0);
av_frame_unref(frame);
if (av_hwframe_get_buffer(video_stream->codec->hw_frames_ctx, frame, 0) < 0) {
fprintf(stderr, "Error: av_hwframe_get_buffer failed\n");
exit(1);
}
}
double frame_time_overflow = frame_timer_elapsed - target_fps; double frame_time_overflow = frame_timer_elapsed - target_fps;
if (frame_time_overflow >= 0.0) { if (frame_time_overflow >= 0.0) {
frame_timer_start = time_now - frame_time_overflow; frame_timer_start = time_now - frame_time_overflow;