From 6885d1a30e41cbb86355820ecc4005706937cb23 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 2 Oct 2022 22:19:54 +0200 Subject: [PATCH] Sacrifice seek speed for reduced file size --- README.md | 4 +++- src/main.cpp | 33 ++++++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 878b193..0d2c49c 100644 --- a/README.md +++ b/README.md @@ -7,17 +7,19 @@ where only the last few seconds are saved. ## Note For NvFBC to work with PRIME, you must set the primary GPU to your dedicated Nvidia graphics card. On Pop OS, you can select the 'NVIDIA Graphics' option in the power menu, or on Arch Linux you can use Optimus Manager.\ -If you are using a variable refresh rate monitor, then choose to record "screen-direct". This will allow variable refresh rate to work when recording fullscreen applications. Note that some applications such as mpv will not work in fullscreen mode. A fix is being developed for this.\ +If you are using a variable refresh rate monitor, then choose to record "screen-direct". This will allow variable refresh rate to work when recording fullscreen applications. Note that some applications such as mpv will not work in fullscreen mode. A fix is being developed for this. # Performance When recording Legend of Zelda Breath of the Wild at 4k, fps drops from 30 to 7 when using OBS Studio + nvenc, however when using this screen recorder the fps remains at 30.\ When recording GTA V at 4k on highest settings, fps drops from 60 to 23 when using obs-nvfbc + nvenc, however when using this screen recorder the fps only drops to 55. The quality is also much better when using gpu-screen-recorder.\ It is recommended to save the video to a SSD because of the large file size, which a slow HDD might not be fast enough to handle.\ Using NvFBC (recording the monitor/screen) is not faster than not using NvFBC (recording a single window) with gpu screen recorder, in fact it might be a tiny bit slower. + # Installation If you are running an Arch Linux based distro, then you can find gpu screen recorder on aur under the name gpu-screen-recorder-git (`yay -S gpu-screen-recorder-git`).\ If you are running an Ubuntu based distro then run `install_ubuntu.sh` as root: `sudo ./install_ubuntu.sh`.\ If you are running another distro then you can run `install.sh` as root: `sudo ./install.sh`, but you need to manually install the dependencies, as described below. + # Dependencies `libgl (libglvnd), ffmpeg, libx11, libxcomposite, libpulse`. You need to additionally have `cuda` installed when you run `gpu-screen-recorder`.\ Recording monitors requires a gpu with NvFBC support (note: this is not required when recording a single window!). Normally only tesla and quadro gpus support this, but by using [nvidia-patch](https://github.com/keylase/nvidia-patch) or [nvlax](https://github.com/illnyang/nvlax) you can do this on all gpus that support nvenc as well (gpus as old as the nvidia 600 series), provided you are not using outdated gpu drivers. diff --git a/src/main.cpp b/src/main.cpp index 45a53d1..61cd07c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -623,15 +623,18 @@ static AVCodecContext *create_video_codec_context(AVFormatContext *av_format_con codec_context->framerate.den = 1; codec_context->sample_aspect_ratio.num = 0; codec_context->sample_aspect_ratio.den = 0; - codec_context->gop_size = fps * 2; + // High values reeduce file size but increases time it takes to seek + codec_context->gop_size = fps * 10; + codec_context->keyint_min = fps * 10; codec_context->max_b_frames = 0; codec_context->pix_fmt = AV_PIX_FMT_CUDA; codec_context->color_range = AVCOL_RANGE_JPEG; - //if(use_hevc) - // codec_context->codec_tag = MKTAG('h', 'v', 'c', '1'); + if(use_hevc) + codec_context->codec_tag = MKTAG('h', 'v', 'c', '1'); switch(video_quality) { case VideoQuality::VERY_HIGH: - codec_context->bit_rate = 10000000 + (codec_context->width * codec_context->height) / 2; + codec_context->bit_rate = 10000000 + (codec_context->width * codec_context->height) / 2; + /* if(use_hevc) { codec_context->qmin = 20; codec_context->qmax = 35; @@ -639,12 +642,14 @@ static AVCodecContext *create_video_codec_context(AVFormatContext *av_format_con codec_context->qmin = 5; codec_context->qmax = 20; } + */ //av_opt_set(codec_context->priv_data, "preset", "slow", 0); //av_opt_set(codec_context->priv_data, "profile", "high", 0); //codec_context->profile = FF_PROFILE_H264_HIGH; //av_opt_set(codec_context->priv_data, "preset", "p4", 0); break; case VideoQuality::ULTRA: + /* if(use_hevc) { codec_context->qmin = 17; codec_context->qmax = 30; @@ -652,12 +657,14 @@ static AVCodecContext *create_video_codec_context(AVFormatContext *av_format_con codec_context->qmin = 5; codec_context->qmax = 15; } + */ //av_opt_set(codec_context->priv_data, "preset", "slow", 0); //av_opt_set(codec_context->priv_data, "profile", "high", 0); //codec_context->profile = FF_PROFILE_H264_HIGH; //av_opt_set(codec_context->priv_data, "preset", "p5", 0); break; } + //codec_context->profile = FF_PROFILE_H264_MAIN; if (codec_context->codec_id == AV_CODEC_ID_MPEG1VIDEO) codec_context->mb_decision = 2; @@ -731,7 +738,7 @@ static AVBufferRef* dummy_hw_frame_init(size_t size) { static void open_video(AVCodecContext *codec_context, WindowPixmap &window_pixmap, AVBufferRef **device_ctx, - CUgraphicsResource *cuda_graphics_resource, CUcontext cuda_context, bool use_nvfbc) { + CUgraphicsResource *cuda_graphics_resource, CUcontext cuda_context, bool use_nvfbc, VideoQuality video_quality) { int ret; *device_ctx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA); @@ -777,7 +784,19 @@ static void open_video(AVCodecContext *codec_context, codec_context->hw_device_ctx = *device_ctx; codec_context->hw_frames_ctx = frame_context; - ret = avcodec_open2(codec_context, codec_context->codec, nullptr); + AVDictionary *options = nullptr; + switch(video_quality) { + case VideoQuality::VERY_HIGH: + av_dict_set_int(&options, "qp", 28, 0); + //av_dict_set(&options, "preset", "hq", 0); + break; + case VideoQuality::ULTRA: + av_dict_set_int(&options, "qp", 18, 0); + //av_dict_set(&options, "preset", "slow", 0); + break; + } + + ret = avcodec_open2(codec_context, codec_context->codec, &options); if (ret < 0) { fprintf(stderr, "Error: Could not open video codec: %s\n", "blabla"); // av_err2str(ret)); @@ -1361,7 +1380,7 @@ int main(int argc, char **argv) { AVBufferRef *device_ctx; CUgraphicsResource cuda_graphics_resource; - open_video(video_codec_context, window_pixmap, &device_ctx, &cuda_graphics_resource, cu_ctx, !src_window_id); + open_video(video_codec_context, window_pixmap, &device_ctx, &cuda_graphics_resource, cu_ctx, !src_window_id, quality); if(video_stream) avcodec_parameters_from_context(video_stream->codecpar, video_codec_context);