FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

@datetime: 2021/06/14

@author: shenhao

文章目录


须知:一个章节如果标注了可跳过,那么它的子章节都需要跳过

FFmpeg硬件加速并且在代码中使用NVIDIA的编解码器

本文中所有步骤来自NVIDIA官方文档,以及参考了各大网友的做法总结和实践而成。另外本文只介绍一般的平台下的安装,不涉及特定的平台,如有需要,请参照NVIDIA官方文档

转载请标明出处。

前言

Windows上的FFmpeg的一般都已经集成了NVDIA的编解码器,但是为了在代码中使用,需要重新对FFmpeg进行重新编译。不建议在windows上编译,因为非常麻烦。而且不适合新手编译。本文介绍了三个不同平台下的**ffmpeg硬件加速方案**,还有如何在代码中如何使用GPU加速。刚开始本来是想先用windows的,因为便于测试,但是后来发现在windows平台下自己的内存不够,完不成编译(自己的内存是16G,最少的要求内存暂时还不知道),另外,在使用预先编译好的ffmpeg测试的时候,发现显卡又不支持h265的编解码,所以一直报no devices found或者codec not support。后来又使用虚拟机,但是又发现英伟达的显卡驱动不支持虚拟机递送(目前)。所以windows的用户确保自己的内存够用。另外,重要的是。不管是linuxwindows的用户,都要确保CUDA是否支持,对应的编解码是否支持。所以总结起来,先确保以下几点

  • 如果环境在虚拟机中,并想参考此文档进行。那么可以不用继续了。

  • 如果环境在windows下,内存要大于16G<= 16G的谨慎继续。

  • 确定自己的显卡是否支持CUDA

    支持CUDA的显卡型号列表

  • 确定显卡是否支持h264,265的编解码器或者其他编解码的格式,以免在编译完成后,如果发现测试有误,首先先排除掉设备的问题

    显卡编解码支持列表

    FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

    FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

    ​ 例如,我笔记本的显卡为860m,则不支持h265编码

另外:

  • 本文中的Windows编译用到了Visual Studio 2019,但不介绍Visual Studio 2019安装。

  • makecmake等编译工具链也不介绍。

  • 文中所用到的pexports工具和pkg-config自行百度。

CUDA简单介绍

CUDA® 是由 NVIDIA® 发明的并行计算平台和编程模型。 通过利用图形处理单元 (GPU) 的强大功能,它可以显着提高计算性能。注意,它只是一种架构。

1.Windows

1.1 准备工作

1.1.1 安装Msys2

​ 在Windows中编译FFmpeg需要Msys2(Msys2简单来说是在windows下可以兼容posix,说白了就是可以使用make && make install等)

Msys2下载地址

FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

  • 按照官方提示安装Msys2

  • 进入Msys2目录,并打开msys2_shell.cmd

  • 输入以下命令

#更新
pacman -Syu
#安装相关工具
pacman -S make pkg-config diffutils yasm
#安装mingw64 mingw32的gcc
pacman -S mingw-w64-i686-nasm mingw-w64-i686-gcc mingw-w64-i686-SDL2 	mingw-w64_x86_64-gcc
#安装nasm汇编器
pacman -S nasm

1.1.2 编译libx264(可跳过)

​ 这一步的目的是避免有些机器没有NVDIA显卡,不能使用CUDA,所以作为候选,可以使用CPU编码.

  • 下载x264源代码
git clone https://code.videolan.org/videolan/x264.git
  • 打开Msys2目录中的mingw64.exe
FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器
  • cdlibx264源代码目录中(注意:当前目录下必须要有configure 和 makefile)

    #注意,以下为64位的编译
    #prefix可以切换成别的路径
    
    ./configure --host=x86_64-w64-mingw32 --enable-shared --prefix="C:\\"
    make && make install
    

成功安装所示

FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

1.1.2.1 使用pexports

pexports可以在windows下把dll生成lib映射文件

下载地址

下载完成后,打开cmd,进入到pexport.exe所在的目录.

#注意:libx264后面的数字根据具体情况修改。
pexport.exe "x264源代码路径"/libx264-163.dll > libx264.def

这时候会在pexport目录中会有libx264.def生成

1.1.2.2 使用Visual Studio的Developer Cmd Prompt

FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

打开后并cdpexport目录(也就是libx264.def所在的目录)

LIB /machine:x64 /DEF:libx264.def

此时会生成lib文件。注意这是动态库的lib文件,需要一起拷贝libx264-163.dll到文件夹中。

FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

1.1.3 编译libx265(可跳过)

编译libx265需要cmake。自行下载。

cmake的编译比较简单。

  • 克隆代码

    https://github.com/videolan/x265/releases
    
  • 进入源代码目录的source子目录下

#指定x64
cmake -Bbuild -A=x64
#Release
cmake --build build --config Release
cd build
cmake --install . --prefix="前缀路径"

注意:也可以不指定–prefix,但cmd要管理员权限运行,因为默认安装路径在Programs Files下

如图,分别生成了静态库和动态库

FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

1.1.4 安装CUDA Toolkit

CUDA Toolkit下载。选择windows平台。

下载完成后,会在此目录下。此目录中有includelib

FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

1.2 正式开始编译

  • 拉取ffnvcodec源代码
git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
  • 拉取FFmpeg源代码
git clone https://git.ffmpeg.org/ffmpeg.git
  • FFmpeg源代码的目录下创建一个名为nv_sdk的文件夹,复制C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\include中的所有头文件和C:\Program Files\NVIDIA GPU Computing Toolkit中的库文件 \CUDA\v11.0\lib\x64nv_sdk文件夹。
  • 启动Visual Studio x64 Native Tools Command Prompt。 从 Visual Studio x64 Native Tools Command Prompt运行 msys2安装文件夹中的 mingw64.exe启动 MinGW64 环境。 在MinGW64环境下,安装必要的包。
FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器
#以下操作在mingw64命令行中(由vs native tools 打开)
pacman -S diffutils make pkg-config yasm
#添加vc的cl.exe和link.exe所在的路径
export PATH="/c/Users/oaho/development/visual studio/2019/Community/VC/Tools/MSVC/14.29.30037/bin/Hostx64/x64":$PATH
#添加cuda sdk目录
export PATH="/c/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.0/bin/":$PATH
  • 进入ffnvcodec(之前克隆的)的源代码目录
make install PREFIX=/usr
  • 进入FFmpeg源代码目录
./configure --enable-nonfree --enable-shared --enable-cuda-sdk --enable-libnpp --toolchain=msvc --extra-cflags="-I../nv_sdk" --extra-ldflags="-libpath:../nv_sdk"
--prefix="安装路径"

注意:如果想加入x264x265编解码器。可以在--extra-cflags中添加x264x265的头文件路径(空格隔开), 当然也在--extra-ldflags中添加库路径

  • make && make install

编译非常耗内存

到此处完成编译。

2.Linux(centos7.9)和Unbuntu20.04安装

2.1 Linux

​ Linux中有两种安装方式。第一种为普通安装(centos7.9演示的则是普通安装),第二种是runfile安装.。Ubuntu20.04下,使用runfile的方式安装。简单说一下runfile安装和普通安装。runfile安装更简单,通用性高。但是如果在特定的平台,需要使用普通平台安装。

**注意:以下安装前的内核要求,必须按照以下表内给出的限制。**具体细节说明,请参照系统内核要求说明。另外请参照NVIDIA官方文档

内核支持的版本

FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

2.1.1 安装前准备

  • 确定你当前系统的版本
uname -m && cat /etc/*release

FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

  • 确认是否安装gcc,如果没有,则安装gcc
#gcc的版本一定要6以上。对照上表进行。
yum install gcc
  • 查看内核版本
#对于cuda11.3来说,centos 7.9 Release的内核必须要为3.10.0-1136
uname -r
  • 安装内核头文件和开发工具包
yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r)

2.1.2 安装CUDA

#(1)安装之前,先删除旧的,防止冲突
sudo /usr/local/cuda-X.Y/bin/cuda-uninstaller
sudo /usr/bin/nvidia-uninstall

wget https://developer.download.nvidia.com/compute/cuda/11.3.1/local_installers/cuda-repo-rhel7-11-3-local-11.3.1_465.19.01-1.x86_64.rpm

#看看输出是否为 028fd3c6c0c3e6c392f053afa52ce2f1
#如果不一致,则说明下载不完整,需要重新下载
md5sum cuda-repo-rhel7-11-3-local-11.3.1_465.19.01-1.x86_64.rpm
#(2) 下载驱动程序和库
yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install subscription-manager
#这一步是为了之后的SDL2的依赖
yum install libX*
yum -y install yum-utils
#该驱动程序依赖于 /etc/X11/xorg.conf 中自动生成的 xorg.conf 文件。 如果存在自定义构建的 #xorg.conf 文件,则此功能将被禁用并且驱动程序可能无法运行。 删除现有的 xorg.conf 文件,或将 #/etc/X11/xorg.conf.d/00-nvidia.conf 的内容添加到 xorg.conf 文件中。 

#安装先前安装的rpm
rpm --install cuda-repo-rhel7-11-3-local-11.3.1_465.19.01-1.x86_64.rpm

#(3) 加入额外的依赖 
#此处可能需要加入yum代理,不然下载很慢
sudo yum-config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/cuda-rhel7.repo
#(4) 清除yum缓存
sudo yum clean expire-cache
#(5) 安装CUDA
sudo yum install nvidia-driver-latest-dkms
sudo yum install cuda
sudo yum install cuda-drivers

进行到这一步,CentOS7的用户请跳转到 [2.3 验证是否安装成功](#2.3 验证是否安装成功).

2.2 Ubuntu20.04

2.2.1 安装前准备

  • 安装依赖库
sudo apt-get install gcc
sudo apt-get install linux-headers-$(uname -r)
  • 禁用Nouveau驱动

    1. 创建/etc/modprobe.d/blacklist-nouveau.conf,在文件中加入以下内容
    blacklist nouveau
    options nouveau modset=0
    
    1. 重新生成内核文件
    sudo update-initramfs -u
    
  • runlevel 3的方式重启

    下面来介绍以下,runlevel 3如何启动。重启电脑,在Ubuntu选择界面中按E。找到splash单词,后面加上nomodeset.最后在这一行的末尾加上3。然后按F10.重进系统后

    runlevel
    #如果显示的是N 3,则成功
    

    注意: 重启后如果进入不了图形界面,则说明成功,如果进入了图形界面,则说明失败,重新尝试。

    如果进入不了命令行进行,则按Ctrl + Alt + F1

    #验证一下,输入此行命令,如果没有输出,则说明禁用成功
    lsmod | grep nouveau
    

2.2.2 安装CUDA

wget https://developer.download.nvidia.com/compute/cuda/11.3.1/local_installers/cuda_11.3.1_465.19.01_linux.run
sudo sh cuda_11.3.1_465.19.01_linux.run  --no-opengl-libs --run-nvidia-xconfig

安装成功后,路径在/usr/local/cuda-11.3

2.3 验证是否安装成功

  • 查看驱动版本

    cat /proc/driver/nvidia/version
    
  • 挂载NVIDIA设备

    modprobe nvidia
    
  • 进入/dev目录,保证nvdia*设备的执行权限

    chmod 666 nvidia*
    
  • 执行命令检测

    nvidia-smi
    

    如果有以下显示,则说明驱动安装成功

    FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

    如果出现了类似于以下的提示。则说明驱动安装失败

    NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.
    
  • 运行测试

    在安装成功后的用户主目录,会有NVIDIA_CUDA-11.3_Samples/文件夹,cd后make(编译时间很长),进入到同目录的bin文件夹中,运行./deviceQuery和BandwidthTest。如果成功的话,会有类似的显示。

FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

2.4 开始编译

  • 拉取ffnvcodec,并安装
git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
cd nv-codec-headers && sudo make install
  • 拉取ffmpeg
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg/
  • 安装所需库
sudo apt-get install build-essential yasm cmake libtool libc6 libc6-dev unzip wget libnuma1 libnuma-dev
  • 配置
./configure --enable-nonfree -–enable-cuda-sdk –enable-libnpp --extra-cflags=-I/usr/local/cuda/include --extra-ldflags=-L/usr/local/cuda/lib64

这里可以加入之前编译的x264库,根据自己选择

  • 编译和安装
make && make install 

2.1.1 编译SDL2(可跳过)

  • 下载源代码

  • 进入源代码目录

./configure && make && make install

2.1.2 编译x264(可跳过)

git clone https://code.videolan.org/videolan/x264.git
cd x264 && ./configure --disable-asm --prefix=/usr/local/x264 --enable-shared && make && make install && sudo ldconfig
#加入pkg-config
export PKG_CONFIG_PATH=/usr/local/x264/lib/pkgconfig:${PKG_CONFIG_PATH}

2.1.3 编译FFmpeg

  • 安装ffnvcodec
git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
  • 拉取FFmpeg源代码
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg/
  • 安装依赖库和工具
yum install -y build-essential yasm cmake libtool libc6 libc6-dev unzip wget libnuma1 libnuma-dev
  • 加入cuda的二进制目录到环境变量和pkg-config
export PATH=/usr/local/cuda-11.3/bin${PATH:+:${PATH}}
#注意,如果PKG_CONFIG_PATH是空的,不用加入":${PKG_CONFIG_PATH}"
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:${PKG_CONFIG_PATH}
#检验ffnvcodec版本
pkg-config --modversion ffnvcodec
  • 进入ffmpeg源代码目录并配置
./configure --enable-nonfree -–enable-cuda-sdk –enable-libnpp --extra-cflags=-I/usr/local/cuda/include --extra-ldflags=-L/usr/local/cuda/lib64 --prefix=/root/ffmpeg-lib-cuda

注意:这里需要更改lib和include的路径

  • 安装
make && make install

注意: 可以使用make -j8增加编译速度

  • 安装后的配置(可选)

注意:如果配置了安装前缀,则需要建立软链接

注意:如果动态链接了x264,需要加入动态库路径

FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

2.5 完成编译

输入以下命令查看H264或者H265的编解码器

ffmpeg -codecs | grep nvenc

成功后如下图所示

FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

  • nvenc_***: nvdia的编码器
  • *_cuvid: nvdia的解码器

3. NVIDIA编解码器的测试

3.1 FFmpeg使用NVIDIA编解码器

这里注意一下,要确定自己的显卡是否支持这些编码。

  • h265编码测试
ffmpeg -s 1920x1080 -pix_fmt yuv420p -i BQTerrace_1920x1080_60.yuv -vcodec hevc_nvenc -r 60 -y 2_60.265 
ffmpeg -s 1920x1080 -pix_fmt yuv420p -i BQTerrace_1920x1080_60.yuv -vcodec hevc_nvenc -r 30 -y 2_30.265
  • h264编码测试
ffmpeg -s 1920x1080 -pix_fmt yuv420p -i BQTerrace_1920x1080_60.yuv -vcodec h264_nvenc -r 60 -y 2_60.264 
ffmpeg -s 1920x1080 -pix_fmt yuv420p -i BQTerrace_1920x1080_60.yuv -vcodec h264_nvenc -r 30 -y 2_30.264
  • h264h265
ffmpeg -i 1_60.264 -vcodec hevc_nvenc -r 60 -y 2_60_264to265.265 
ffmpeg -i 1_30.264 -vcodec hevc_nvenc -r 30 -y 2_30_264to265.265
  • h265h264
ffmpeg -i 1_60.265 -vcodec h264_nvenc -r 60 -y 2_60_265to264.264 
ffmpeg -i 1_30.265 -vcodec h264_nvenc -r 30 -y 2_30_265to264.264

3.2 GPU使用情况查看

watch -n 1 nvidia-smi 

FFmpeg`硬件加速并且在代码中使用`NVIDIA`的编解码器

4. 代码中使用NVIDIA编解码器

在使用FFmpeg API的时候, AVCodec编解码器可以改成:

#使用nvidia的264的编码器
av_find_encoder_by_name(“h264_nvenc”); 
#使用nvidia的265的编码器
av_find_encoder_by_name(“hevc_nvenc”);

FAQ

  • 在windows平台下编译时,ffmpeg的编译日志:无效的选项,–extra-ldflags将忽略

    -L选项在windows下的适配性不太友好,使用-libpath::“路径”

  • [h264_nvenc @ 0x5649bab0c500] 10 bit encode not supported

    此种编码,显卡不支持。参照显卡编解码支持列表

  • [h264_nvenc @ 0x5649bab0c500] No capable devices found

    这种有多种情况

    • 驱动没有安装好
    • 显卡不支持此种编码
  • Ubuntu在禁用nouveau后,重启会黑屏。并之后都会黑屏

    恢复nouveau驱动

API的时候,AVCodec`编解码器可以改成:

#使用nvidia的264的编码器
av_find_encoder_by_name(“h264_nvenc”); 
#使用nvidia的265的编码器
av_find_encoder_by_name(“hevc_nvenc”);

FAQ

  • 在windows平台下编译时,ffmpeg的编译日志:无效的选项,–extra-ldflags将忽略

    -L选项在windows下的适配性不太友好,使用-libpath::“路径”

  • [h264_nvenc @ 0x5649bab0c500] 10 bit encode not supported

    此种编码,显卡不支持。参照显卡编解码支持列表

  • [h264_nvenc @ 0x5649bab0c500] No capable devices found

    这种有多种情况

    • 驱动没有安装好
    • 显卡不支持此种编码
  • Ubuntu在禁用nouveau后,重启会黑屏。并之后都会黑屏

    恢复nouveau驱动

上一篇:吴恩达深度学习课程脉络(五)序列建模(更新ing)


下一篇:成功解决Windows无法启动服务NVIDIA Dispaly Container LS服务(位于本地计算机上),错误2:系统找不到指定的文件