NVIDIA VIDEO CODEC SDK介绍
作者:罗上文,微信:Loken1,公众号:FFmpeg弦外之音
本文主要介绍 NVIDIA 显卡的硬件编解码功能,我们可以通过 Video Encode and Decode GPU Support Matrix 查看自己显卡对硬件编解码的支持情况。如下:

NVDEC 是硬件解码单元,NVENC 是硬件编码单元。我们可以在上图中看到,一个 Chip 里有多少个 NVDEC 或者是 NVENC。
但是需要注意,NVDEC、NVENC 这两个单元是独立于 CUDA core 跟 graphics engine(图像渲染引擎)的,如下图:

也就是说,你在使用显卡的硬件编解码功能的时候,是不会影响到 图像渲染跟 CUDA 通用计算的那些功能的。
NVENC和NVDEC这两个硬件的编解码芯片只占用了GPU核心很小的部分,如果只需要转码功能,就买一块很贵的卡不太划算。
如果读者学过 CUDA C/C++,会知道我们可以通过写 CUDA C/C++ 代码来调用 CUDA core 的计算能力。但是 NVDEC/NVENC 硬件编解码不是通过 一行一行的 CUDA C/C++ 代码写出来的。NVDEC/NVENC 是封装好的动态库,我们是完全看不到他编解码算法的源代码的。
在 Windows 环境,NVDEC 的动态库是 nvcuvid.dll,NVENC 的动态库是 nvEncodeAPI.dll,如下:

这些动态库都是在安装显卡驱动的时候一起装上去的。
要调用 dll 里面的函数,肯定需要一些头文件跟导入库(import library),所以 NVIDIA 提供了 VIDEO CODEC SDK 给我们用。
VIDEO CODEC SDK 的下载比较麻烦,如果你想下载历史版本,需要注册 NVIDIA 开发者账号,然后绑定 GitLab ID,最后点击下面的 Source Code 申请权限才能访问到 历史版本的源代码。


本文下载的是 10.0.26 的版本,打开之后内容如下:

Interface 里面就是头文件,Lib 里面就是导入库。Doc 里面有非常重要的文档,NVDEC/NVENC 的 API 函数用法都在文档里面。
Samples 里面是各种示例,他不仅仅演示了 NVDEC/NVENC 的 API 函数用法,还演示 NVDEC/NVENC 怎么跟其他框架交互,例如:
- NVDEC 解码之后,怎么把显存的数据直接给 OpenGL 渲染。
- NVDEC 解码之后,如何用 CUDA C++ 进行后续的处理。
- 等等
如果想把 Samples 的示例跑起来,需要安装 CUDA Toolkit,DirectX,Vulkan 等众多工具。
但是这里提醒一下,如果我们仅仅只是想使用显卡的 NVDEC/NVENC 功能,只需要 Interface 文件夹里的头文件跟 Lib 文件夹的导入库就行了,是不需要完全安装 CUDA Toolkit 的。
Samples 要安装 CUDA Toolkit ,是因为他要用 CUDA Toolkit 来对数据进行前处理、后处理。
由于 Samples 项目的构建比较复杂,依赖众多。所以这里我自己写一个小例子来演示一下如何引入 nvcuvid.dll 动态库。
首先创建一个 test.c 文件,放在跟 Samples 同级的目录,代码如下:
#include <stdio.h>
#include "Interface/nvcuvid.h"
int main()
{
cuvidCreateVideoParser(NULL,NULL);
return 0;
}
由于 nvcuvid.h 里面引入了 cuda.h 头文件,cuda.h 在 VIDEO CODEC SDK 里面是没有的,它是在 CUDA Toolkit 安装包里面的,所以我们需要把 cuda.h 拷贝过来。
这里读者可能会有疑惑,不是说使用 NVDEC/NVENC 硬件编解码不需要安装 CUDA Toolkit 吗?
是不需要安装 CUDA Toolkit,因为 硬件编解码只会用到 3 个库,就是 nvcuvid.dll,nvEncodeAPI.dll,nvcuda.dll。这 3 个库都是安装显卡驱动的时候一起装的。
但重点是 nvcuda.dll 这个动态库,他对应的头文件 cuda.h 跟 导入库 cuda.lib 不在 VIDEO CODEC SDK 里面,而是在 CUDA Toolkit 里面。
nvcuda.dll 是 CUDA Driver API,负责做一些通用任务的,例如获取GPU设备信息,创建 cuContext 上下文。
简单来说,NVDEC/NVENC 硬件编解码 只用到了 CUDA Toolkit 里面的 cuda.h 跟 cuda.lib (导入库),这两个文件我们是完全可以拷贝出来的,不需要安装CUDA Toolkit。
如果你是 dl_open() 显式调用 nvcuda.dll,就会连 cuda.lib 都不需要,只需要 cuda.h 头文件就可以了。
显式调用就是 ffmpeg 项目里的用法,他是直接用 dl_open() 显式调用 nvcuda.dll、nvcuvid.dll,nvEncodeAPI.dll,所以他只需要几个头文件就行了。
让 ffmpeg 支持 NVDEC/NVENC 硬件编解码 就不需要安装 CUDA Toolkit,这个下篇文章会介绍。
回到正题,我们可以执行下面的命令来编译一下 test.c。
cl.exe /c /Fotest.obj test.c
link.exe /DEBUG /OUT:test.exe test.obj
我们再用 dumpbin 查看一下 test.exe 的依赖,如下:

可以看到 test.exe 已经链接上 nvcuvid.dll 了。