From ce433d9b1e08ffd33b8eaff9fcecbfc41a5faf51 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 18 Oct 2022 09:02:24 +0200 Subject: Attempt to reduce stuttering of video --- src/main.cpp | 180 +++++++++++++++++++++++++++-------------------------------- 1 file changed, 83 insertions(+), 97 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 021d6e3..05f062d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -882,10 +882,13 @@ static void open_video(AVCodecContext *codec_context, // with pretty good performance but you now have to choose p1-p7, which are gpu agnostic and on // older gpus p5-p7 slow the gpu down to a crawl... // "hq" is now just an alias for p7 in ffmpeg :( + // TODO: Temporary disable because of stuttering? + /* if(very_old_gpu) av_dict_set(&options, "preset", supports_p4 ? "p4" : "medium", 0); else av_dict_set(&options, "preset", supports_p7 ? "p7" : "slow", 0); + */ av_dict_set(&options, "tune", "hq", 0); av_dict_set(&options, "rc", "constqp", 0); @@ -948,16 +951,8 @@ static void usage() { exit(1); } -static sig_atomic_t started = 0; static sig_atomic_t running = 1; static sig_atomic_t save_replay = 0; -static const char *pid_file = "/tmp/gpu-screen-recorder"; - -static void term_handler(int) { - if(started) - unlink(pid_file); - exit(0); -} static void int_handler(int) { running = 0; @@ -1172,7 +1167,6 @@ static bool is_livestream_path(const char *str) { } int main(int argc, char **argv) { - signal(SIGTERM, term_handler); signal(SIGINT, int_handler); signal(SIGUSR1, save_replay_handler); @@ -1213,6 +1207,8 @@ int main(int argc, char **argv) { VideoCodec video_codec; const char *codec_to_use = args["-k"].value(); + fprintf(stderr, "Info: forcing codec to h264 to investigate stuttering with some configs\n"); + codec_to_use = "h264"; if(!codec_to_use) codec_to_use = "auto"; @@ -1681,6 +1677,8 @@ int main(int argc, char **argv) { frame->extended_data = frame->data; } + frame->color_range = AVCOL_RANGE_JPEG; + if(window_pixmap.texture_width < record_width) frame->width = window_pixmap.texture_width & ~1; else @@ -1818,21 +1816,16 @@ int main(int argc, char **argv) { }, av_format_context, &write_output_mutex); } - started = 1; - // Set update_fps to 24 to test if duplicate/delayed frames cause video/audio desync or too fast/slow video. const double update_fps = fps + 190; int64_t video_pts_counter = 0; - bool redraw = true; XEvent e; while (running) { double frame_start = clock_get_monotonic_seconds(); if(window) gl.glClear(GL_COLOR_BUFFER_BIT); - redraw = true; - if(src_window_id) { if (XCheckTypedWindowEvent(dpy, src_window_id, DestroyNotify, &e)) { running = 0; @@ -1936,108 +1929,102 @@ int main(int argc, char **argv) { if (frame_time_overflow >= 0.0) { frame_timer_start = time_now - frame_time_overflow; - bool frame_captured = true; - if(redraw) { - redraw = false; - if(src_window_id) { - // TODO: Use a framebuffer instead. glCopyImageSubData requires - // opengl 4.2 - int source_x = 0; - int source_y = 0; + if(src_window_id) { + // TODO: Use a framebuffer instead. glCopyImageSubData requires + // opengl 4.2 + int source_x = 0; + int source_y = 0; - int source_width = window_pixmap.texture_width; - int source_height = window_pixmap.texture_height; + int source_width = window_pixmap.texture_width; + int source_height = window_pixmap.texture_height; - bool clamped = false; + bool clamped = false; - if(window_pixmap.composite_window) { - source_x = window_x; - source_y = window_y; + if(window_pixmap.composite_window) { + source_x = window_x; + source_y = window_y; - int underflow_x = 0; - int underflow_y = 0; + int underflow_x = 0; + int underflow_y = 0; - if(source_x < 0) { - underflow_x = -source_x; - source_x = 0; - source_width += source_x; - } + if(source_x < 0) { + underflow_x = -source_x; + source_x = 0; + source_width += source_x; + } - if(source_y < 0) { - underflow_y = -source_y; - source_y = 0; - source_height += source_y; - } + if(source_y < 0) { + underflow_y = -source_y; + source_y = 0; + source_height += source_y; + } - const int clamped_source_width = std::max(0, window_pixmap.texture_real_width - source_x - underflow_x); - const int clamped_source_height = std::max(0, window_pixmap.texture_real_height - source_y - underflow_y); + const int clamped_source_width = std::max(0, window_pixmap.texture_real_width - source_x - underflow_x); + const int clamped_source_height = std::max(0, window_pixmap.texture_real_height - source_y - underflow_y); - if(clamped_source_width < source_width) { - source_width = clamped_source_width; - clamped = true; - } - - if(clamped_source_height < source_height) { - source_height = clamped_source_height; - clamped = true; - } + if(clamped_source_width < source_width) { + source_width = clamped_source_width; + clamped = true; } - if(clamped) { - // Requires opengl 4.4... TODO: Replace with earlier opengl if opengl < 4.2 - if(gl.glClearTexImage) - gl.glClearTexImage(window_pixmap.target_texture_id, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + if(clamped_source_height < source_height) { + source_height = clamped_source_height; + clamped = true; } + } - // Requires opengl 4.2... TODO: Replace with earlier opengl if opengl < 4.2 - gl.glCopyImageSubData( - window_pixmap.texture_id, GL_TEXTURE_2D, 0, source_x, source_y, 0, - window_pixmap.target_texture_id, GL_TEXTURE_2D, 0, 0, 0, 0, - source_width, source_height, 1); - unsigned int err = gl.glGetError(); - if(err != 0) { - static bool error_shown = false; - if(!error_shown) { - error_shown = true; - fprintf(stderr, "Error: glCopyImageSubData failed, gl error: %d\n", err); - } - } - gl.glXSwapBuffers(dpy, window); - // int err = gl.glGetError(); - // fprintf(stderr, "error: %d\n", err); + if(clamped) { + // Requires opengl 4.4... TODO: Replace with earlier opengl if opengl < 4.2 + if(gl.glClearTexImage) + gl.glClearTexImage(window_pixmap.target_texture_id, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + } - // TODO: Remove this copy, which is only possible by using nvenc directly and encoding window_pixmap.target_texture_id + // Requires opengl 4.2... TODO: Replace with earlier opengl if opengl < 4.2 + gl.glCopyImageSubData( + window_pixmap.texture_id, GL_TEXTURE_2D, 0, source_x, source_y, 0, + window_pixmap.target_texture_id, GL_TEXTURE_2D, 0, 0, 0, 0, + source_width, source_height, 1); + unsigned int err = gl.glGetError(); + if(err != 0) { + static bool error_shown = false; + if(!error_shown) { + error_shown = true; + fprintf(stderr, "Error: glCopyImageSubData failed, gl error: %d\n", err); + } + } + gl.glXSwapBuffers(dpy, window); + // int err = gl.glGetError(); + // fprintf(stderr, "error: %d\n", err); - frame->linesize[0] = frame->width * 4; + // TODO: Remove this copy, which is only possible by using nvenc directly and encoding window_pixmap.target_texture_id - CUDA_MEMCPY2D memcpy_struct; - memcpy_struct.srcXInBytes = 0; - memcpy_struct.srcY = 0; - memcpy_struct.srcMemoryType = CUmemorytype::CU_MEMORYTYPE_ARRAY; + frame->linesize[0] = frame->width * 4; - memcpy_struct.dstXInBytes = 0; - memcpy_struct.dstY = 0; - memcpy_struct.dstMemoryType = CUmemorytype::CU_MEMORYTYPE_DEVICE; + CUDA_MEMCPY2D memcpy_struct; + memcpy_struct.srcXInBytes = 0; + memcpy_struct.srcY = 0; + memcpy_struct.srcMemoryType = CUmemorytype::CU_MEMORYTYPE_ARRAY; - memcpy_struct.srcArray = mapped_array; - memcpy_struct.dstDevice = (CUdeviceptr)frame->data[0]; - memcpy_struct.dstPitch = frame->linesize[0]; - memcpy_struct.WidthInBytes = frame->width * 4; - memcpy_struct.Height = frame->height; - cuda.cuMemcpy2D_v2(&memcpy_struct); + memcpy_struct.dstXInBytes = 0; + memcpy_struct.dstY = 0; + memcpy_struct.dstMemoryType = CUmemorytype::CU_MEMORYTYPE_DEVICE; - frame_captured = true; - } else { - // TODO: Check when src_cu_device_ptr changes and re-register resource - frame->linesize[0] = frame->width * 4; + memcpy_struct.srcArray = mapped_array; + memcpy_struct.dstDevice = (CUdeviceptr)frame->data[0]; + memcpy_struct.dstPitch = frame->linesize[0]; + memcpy_struct.WidthInBytes = frame->width * 4; + memcpy_struct.Height = frame->height; + cuda.cuMemcpy2D_v2(&memcpy_struct); + } else { + // TODO: Check when src_cu_device_ptr changes and re-register resource + frame->linesize[0] = frame->width * 4; - uint32_t byte_size = 0; - CUdeviceptr src_cu_device_ptr = 0; - frame_captured = nv_fbc_library.capture(&src_cu_device_ptr, &byte_size); - frame->data[0] = (uint8_t*)src_cu_device_ptr; - } - // res = cuda.cuCtxPopCurrent_v2(&old_ctx); + uint32_t byte_size = 0; + CUdeviceptr src_cu_device_ptr = 0; + nv_fbc_library.capture(&src_cu_device_ptr, &byte_size); + frame->data[0] = (uint8_t*)src_cu_device_ptr; } + // res = cuda.cuCtxPopCurrent_v2(&old_ctx); const double this_video_frame_time = clock_get_monotonic_seconds(); const int64_t expected_frames = std::round((this_video_frame_time - start_time_pts) / target_fps); @@ -2097,6 +2084,5 @@ int main(int argc, char **argv) { if(dpy) XCloseDisplay(dpy); - unlink(pid_file); free(empty_audio); } -- cgit v1.2.3