1

I need to capture bit-perfect lossless videos of the whole screen at a certain framerate (at least 30 fps). I am currently using Windows 10 and an up-to-date version of FFmpeg. Given that the resolution in which the video has to be recorded is considerable (4K or higher), software encoders such as libx264rgb, which allow a genuinely lossless encoding, cannot do the job, as the frame rate drops to 15 fps or lower, even with the ultrafast preset. Additionally, the transference of information from the GPU to the CPU for that purpose is a bottleneck in this regard, so I would like to avoid it if this is possible.

For this reason, I have been investigating about hardware encoders to check whether all the job could be delegated to my GPU (RTX 4070 Ti). After some research, I realized that the screen can be recorded efficiently using the Windows 8+ desktop duplication API plus HEVC NVENC encoder through the following FFmpeg command:

ffmpeg -filter_complex ddagrab=0:framerate=30:draw_mouse=0 -c:v hevc_nvenc -tune lossless output.mkv

Despite this approach is very performant (it can even go beyond 60 fps), the color space is set by default to yuv420p, which is lossy, as can be seen after checking the metadata of the video through ffmpeg -i output.mkv:

Input #0, matroska,webm, from 'output.mkv': Metadata: ENCODER : Lavf60.10.100 Duration: 00:00:04.63, start: 0.000000, bitrate: 2537 kb/s Stream #0:0: Video: hevc (Main), yuv420p(tv, bt470bg/bt709/iec61966-2-1, progressive), 3840x2160 [SAR 1:1 DAR 16:9], 30 fps, 30 tbr, 1k tbn Metadata: ENCODER : Lavc60.22.100 hevc_nvenc DURATION : 00:00:04.633000000

Therefore, this approach had to be improved, so I had checked which pixel formats can be used in this encoder through the command ffmpeg -h encoder=hevc_nvenc and got the following information in this regard:

Supported pixel formats: yuv420p nv12 p010le yuv444p p016le yuv444p16le bgr0 bgra rgb0 rgba x2rgb10le x2bgr10le gbrp gbrp16le cuda d3d11

However, not matter which option I choose for the pixel format, for instance, doing

ffmpeg -filter_complex ddagrab=0:framerate=30:draw_mouse=0 -c:v hevc_nvenc -tune lossless -pix_fmt bgr0 output.mkv

I always get the following error:

Impossible to convert between the formats supported by the filter 'Parsed_ddagrab_0' and the filter 'auto_scale_0' [fc#0 @ 0000018a81585c80] Error configuring filter graph: Function not implemented Error opening output file output.mkv. Error opening output files: Function not implemented

Even if I try to force compatible pixel formats between the captures to be encoded and the output video, I get exactly the same error, for instance with this command:

ffmpeg -filter_complex ddagrab=0:framerate=30:draw_mouse=0,format=bgra -c:v hevc_nvenc -tune lossless -pix_fmt bgra output.mkv

Interestingly, the command also fails and throws the same error even if yuv420p is chosen as the output pixel format, which is actually the one in which the video is ultimately encoded by default. Hence, this suggests that something is preventing from setting or changing the pixel format.

It is also worth noting that after many unsuccessful combinations, I realized that if the hardware frames are downloaded to memory with hwdownload, then I am allowed to set the pixel format. Nevertheless, the only combination in which genuinely lossless videos are obtained is by using the pixel format gbrp, namely, through the command:

ffmpeg -filter_complex ddagrab=0:framerate=30:draw_mouse=0,hwdownload,format=bgra -c:v hevc_nvenc -tune lossless -pix_fmt gbrp output.mkv

If I try any other pixel format from the RGB colorspace with which allegedly a lossless encoding can be obtained (such as bgr0, bgra, rgb0 or rgba), the option will be ignored and the pixel format of the output video will be stubbornly set to yuv420p. This is no longer relevant because at least one of the options works, but this adds up to the above suspicions related to something being possibly done wrong when setting the pixel format, while also proves that the hevc_nvenc encoder, at least in this context, is able to encode frames bit-perfectly in a full RGB colorspace.

However, and despite this solution or patch is more performant than the usage of software encoders such as libx264rgb, having to resort to hwdownload (with the bottleneck it implies) just to be able to use the appropriate pixel format, is still not an option. Besides, the desired 30 fps cannot be reached with this alternative approach, and hence the question summarized in the title:

Is there a way to force hevc_nvenc to use a pixel format allowing bit-perfect lossless outputs (e.g., gbrp), without having to download the hardware frames to memory (with the loss of performance it implies)?

Many thanks in advance for all your efforts and my apologies beforehand if the question was not as concise as it should. I just tried to be as explicit as possible with my attempts and discoveries in order to save possible job to all those willing to investigate the issue, so that solutions or suggestions can be investigated or proposed in the right direction.

ksb496
  • 111

0 Answers0