aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-03-31 20:02:18 +0200
committerdec05eba <dec05eba@protonmail.com>2020-03-31 20:02:18 +0200
commit19dfa524d4bd2963531868c141af635fe31c3efd (patch)
tree97bc9136e33b3e10e33ecb242cfdcb1612016bc0
parent07a8635c550303b44c0a751ef24ad1b1768df7f8 (diff)
do not crash when resizing window
-rw-r--r--README.md2
-rw-r--r--src/main.cpp59
2 files changed, 51 insertions, 10 deletions
diff --git a/README.md b/README.md
index 673fbf5..6bf921b 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ the fps remains at 30.
X11, Nvidia (cuda)
# 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.
* 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.
diff --git a/src/main.cpp b/src/main.cpp
index 4836189..49e651c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -102,8 +102,8 @@ static void cleanup_window_pixmap(Display *dpy, WindowPixmap &pixmap) {
}
if (pixmap.glx_pixmap) {
- glXReleaseTexImageEXT(dpy, pixmap.glx_pixmap, GLX_FRONT_EXT);
glXDestroyPixmap(dpy, pixmap.glx_pixmap);
+ glXReleaseTexImageEXT(dpy, pixmap.glx_pixmap, GLX_FRONT_EXT);
pixmap.glx_pixmap = None;
}
@@ -415,10 +415,12 @@ static void open_video(AVCodec *codec, AVStream *stream,
CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY);
// cuGraphicsUnregisterResource(*cuda_graphics_resource);
if (res != CUDA_SUCCESS) {
+ const char *err_str;
+ cuGetErrorString(res, &err_str);
fprintf(stderr,
- "Error: cuGraphicsGLRegisterImage failed, error %d, texture "
+ "Error: cuGraphicsGLRegisterImage failed, error %s, texture "
"id: %u\n",
- res, window_pixmap.target_texture_id);
+ err_str, window_pixmap.target_texture_id);
exit(1);
}
res = cuCtxPopCurrent(&old_ctx);
@@ -445,7 +447,7 @@ int main(int argc, char **argv) {
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);
if (!dpy) {
@@ -480,6 +482,10 @@ int main(int argc, char **argv) {
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);
GLFWwindow *window =
@@ -493,7 +499,6 @@ int main(int argc, char **argv) {
glfwMakeContextCurrent(window);
glfwSwapInterval(0);
-#define DEBUG
#if defined(DEBUG)
XSetErrorHandler(x11_error_handler);
XSetIOErrorHandler(x11_io_error_handler);
@@ -611,6 +616,8 @@ int main(int argc, char **argv) {
double start_time = glfwGetTime();
double frame_timer_start = start_time;
+ double window_resize_timer = start_time;
+ bool window_resized = true;
int fps_counter = 0;
int current_fps = 30;
@@ -623,8 +630,7 @@ int main(int argc, char **argv) {
frame->width = video_stream->codec->width;
frame->height = video_stream->codec->height;
- if (av_hwframe_get_buffer(video_stream->codec->hw_frames_ctx, frame, 0) <
- 0) {
+ 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);
}
@@ -645,8 +651,8 @@ int main(int argc, char **argv) {
if(e.xconfigure.width != window_width || e.xconfigure.height != window_height) {
window_width = e.xconfigure.width;
window_height = e.xconfigure.height;
- fprintf(stderr, "Resize window!\n");
- recreate_window_pixmap(dpy, src_window_id, window_pixmap);
+ window_resize_timer = glfwGetTime();
+ window_resized = false;
}
}
@@ -698,6 +704,41 @@ int main(int argc, char **argv) {
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;
if (frame_time_overflow >= 0.0) {
frame_timer_start = time_now - frame_time_overflow;