使用NVIDIA显卡GPU进行视频编码时,如果同时进行多路转码,在某些显卡上会报错: Out of Memory,一般就是调用nvEncOpenEncodeSessionEx函数出错,返回的错误码是10(NV_ENC_ERR_OUT_OF_MEMORY),NVENC并发的Session数目超过了限制,具体信息可以去官网查一下。
Video Encode and Decode GPU Support Matrix
2020-10-28更新到版本456.71

2020-01-03_15-21-19.png
2020-01-03_15-21-35.png

很奇怪NVIDIA会做如此的限制,因为并不是GPU能力不够。就我的电脑来说,NVIDIA显卡型号是GeForce GTX 1650,NVENC的并发最大数目是2,为了查找在哪里进行了限制,我写了如下代码:

cuInit(0);
CUdevice cuDevice = 0;
cuDeviceGet(&cuDevice, 0);
CUcontext cuContext = NULL;
cuCtxCreate(&cuContext, CU_CTX_SCHED_BLOCKING_SYNC, cuDevice);

NV_ENCODE_API_FUNCTION_LIST nvenc = { NV_ENCODE_API_FUNCTION_LIST_VER };
NVENCSTATUS nvStatus = NvEncodeAPICreateInstance(&nvenc);

NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS encodeSessionExParams = {         
NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER };
encodeSessionExParams.device     = cuContext;
encodeSessionExParams.deviceType = NV_ENC_DEVICE_TYPE_CUDA;
encodeSessionExParams.apiVersion = NVENCAPI_VERSION;

printf("OpenEncodeSesionEx #1\n");
void *hEncoder1 = NULL;
nvStatus = nvenc.nvEncOpenEncodeSessionEx(&encodeSessionExParams, &hEncoder1);

printf("OpenEncodeSesionEx #2\n");
void *hEncoder2 = NULL;
nvStatus = nvenc.nvEncOpenEncodeSessionEx(&encodeSessionExParams, &hEncoder2);

printf("OpenEncodeSesionEx #3\n");
void *hEncoder3 = NULL;
nvStatus = nvenc.nvEncOpenEncodeSessionEx(&encodeSessionExParams, &hEncoder3);

最后在Open第3个Session时返回了NV_ENC_ERR_OUT_OF_MEMORY,之后我使用x64dbg对代码进行了跟踪调试,原来限制的模块并不是在驱动层,而是在应用层,动态库文件是nvcuvid.dll,汇编代码大概如下:

.text:00000001800E7FAF FF 90+                call    qword ptr [rax+90h] ; 调用这个函数检查数目是否超过限制
.text:00000001800E7FB5 84 C0                 test    al, al
.text:00000001800E7FB7 74 08                 jz      short loc_1800E7FC1
.text:00000001800E7FB9 C6 43+                mov     byte ptr [rbx+38h], 1
.text:00000001800E7FBD 33 C0                 xor     eax, eax
.text:00000001800E7FBF EB 05                 jmp     short loc_1800E7FC6
.text:00000001800E7FC1       loc_1800E7FC1:
.text:00000001800E7FC1 B8 0A+                mov     eax, 0Ah            ; 超过限制就设置返回值为10

找到了位置,然后就简单了,只需要把jz short loc_1800E7FC1 这个判断跳转nop掉即可

.text:00000001800E7FAF FF 90+                call    qword ptr [rax+90h]
.text:00000001800E7FB5 84 C0                 test    al, al
.text:00000001800E7FB7 90                    nop    ;这里nop掉之后,就不会跳转到loc_1800E7FC1
.text:00000001800E7FB8 90                    nop
.text:00000001800E7FB9 C6 43+                mov     byte ptr [rbx+38h], 1
.text:00000001800E7FBD 33 C0                 xor     eax, eax
.text:00000001800E7FBF EB 05                 jmp     short loc_1800E7FC6
.text:00000001800E7FC1       loc_1800E7FC1:
.text:00000001800E7FC1 B8 0A+                mov     eax, 0Ah

汇编修改之后对nvcuvid.dll打patch,替换掉系统目录下的文件,然后再运行测试程序,开十几路同时编码也没问题了,没限制的感觉太香了!哈哈...

通过一些版本的测试,发现完全是可以使用特征码来制作补丁,而且目前特征码是唯一的,因此就不需要反编译分析代码位置。

特征码:84 C0 74 08 C6 43 38 01 33 C0 
修改为:84 C0 90 90 C6 43 38 01 33 C0

第二组特征码,只需要改动1个字节(Studio)

特征码:01 FF 90 B0 00 00 00 84 C0 74 08 C6 43 38 01 33
修改为:00 FF 90 B0 00 00 00 84 C0 74 08 C6 43 38 01 33

版本496.13之后(Game Ready)

特征码:B2 01 FF 90 C0 00 00 00 84 C0
修改为:B2 00 FF 90 C0 00 00 00 84 C0

使用二进制工具可以非常简单的快速破解不同的版本,Enjoy!

2020-01-02更新版本441.66的补丁: 下载
2020-04-07更新版本442.19的补丁: 下载
2020-07-28更新版本451.77的补丁: 下载
2020-09-23更新版本451.82的补丁: 下载
2020-10-28更新版本456.71的补丁: 下载

标签: cuda, nvenc, nvidia

已有 21 条评论

  1. 1 1

    555

  2. tyxxy tyxxy

    这里有个开源项目干了一样的事。
    https://github.com/keylase/nvidia-patch

    btw,楼主是否注意到,nvenc一开,显存就会至少增加120MB?就是调用nvEncOpenEncodeSessionEx这个api时候。而且每路视频都会至少120M左右的显存消耗,因此开多路的话,显存消耗很大(我的场景需要开二十多路,而且每路后面还有200M左右的图形渲染显存开销)。有什么解决方法没?有知道的欢迎联系:tyxxyhm@hotmail.com,感谢。

  3. 南风 南风

    20220905最新版本驱动修改好的,和修改软件打包下载(自解压文件)此补丁对应的驱动版本是516.94
    STUDIO
    「NVDIA-ENCODE线程破解.exe」https://www.aliyundrive.com/s/uzfzvgZet4X 提取码: fi65
    点击链接保存,或者复制本段内容,打开「阿里云盘」APP

  4. paul paul

    请问新版本驱动可以更新一下破解补丁吗?2022年3月了

  5. yy yy

    nv编码不支持交叉场吗

  6. hooli hooli

    请问这个nvcuid.dll能下载吗,谢谢?

  7. hooli hooli

    大神

  8. end end

    同求Ubuntu的libnvcuvid.so

  9. 三十多 三十多

    谢谢分享!!!!

  10. 谢晟 谢晟

    我在ubuntu上尝试了好几次还是不行,求ubuntu上修改方法或者帮我改个so的版本可以吗,能邮件发我联系方式吗

  11. 谢晟 谢晟

    同问,有ubuntu修改教程吗,或者ubuntu能用的包

  12. Songjinxue Songjinxue

    我也遇到这个问题了,可以发给我一个打上patch后的nvcuvid.dll吗?十分感谢

    1. K K

      有没有linux下的补丁?跪求

      1. 谢晟 谢晟

        请问您现在搞定了吗

  13. 同求patch 同求patch

    我在做视频硬编码时候也遇到这个问题了,跪求

    1. 我可以帮你弄。我的弄好了。

      1. parhcl parhcl

        大佬能帮忙弄一个496.76的吗……

      2. sanwz sanwz

        请问怎么弄的,我的显卡驱动版本是471.68.

  14. chenjinyun chenjinyun

    能否发一个打上patch后的nvcuvid.dll给我,非常感谢。

    1. 求打上path后的nvcuvid.dl 求打上path后的nvcuvid.dl

      大神求发一个打上patch后的nvcuvid.dll,万分感谢。

      1. 阿牛 阿牛

        我需要支持2080ti的最新显卡驱动的 nvcuvid.dll

添加新评论