使用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

已有 18 条评论

  1. paul paul

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

  2. yy yy

    nv编码不支持交叉场吗

  3. hooli hooli

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

  4. hooli hooli

    大神

  5. end end

    同求Ubuntu的libnvcuvid.so

  6. 三十多 三十多

    谢谢分享!!!!

  7. 谢晟 谢晟

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

  8. 谢晟 谢晟

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

  9. Songjinxue Songjinxue

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

    1. K K

      有没有linux下的补丁?跪求

      1. 谢晟 谢晟

        请问您现在搞定了吗

  10. 同求patch 同求patch

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

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

      1. parhcl parhcl

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

      2. sanwz sanwz

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

  11. chenjinyun chenjinyun

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

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

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

      1. 阿牛 阿牛

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

添加新评论