blueyi's notes

Follow Excellence,Success will chase you!

0%

Ubuntu 16.04下编译ffmpeg支持CUDA下的cuvid vnenc和NPP

FFmpeg可以用来处理音视频的编解码,通过对GPU硬解码的支持,可以加速编解码,但需要手动编译FFmpeg时加入对GPU的支持。这里参考Nvidia官网和FFmpeg官网文档进行编译FFmpeg的编译。 编译ffmpeg时启用CUVID,其中包括NVENCODE API和NVDECODE API,ffmpeg中通过nvenc来来提供对Nvidia显卡的支持,同时添加NPP支持来增强编解码性能。

环境准备

我的硬件环境为ubuntu 16.04.1 x64 服务器版的最小化系统,具体参数如下:

1
2
3
4
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"

首先确定已经安装好了CUDA 8,如果还没有安装CUDA 8环境可以参考这里安装http://notes.maxwi.com/2017/02/26/ubuntu-cuda8-env-set/
我的显卡信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Device 0: "GeForce GTX 1080"
CUDA Driver Version / Runtime Version 8.0 / 8.0
CUDA Capability Major/Minor version number: 6.1
Total amount of global memory: 8112 MBytes (8506179584 bytes)
(20) Multiprocessors, (128) CUDA Cores/MP: 2560 CUDA Cores
GPU Max Clock rate: 1734 MHz (1.73 GHz)
Memory Clock rate: 5005 Mhz
Memory Bus Width: 256-bit
L2 Cache Size: 2097152 bytes
Maximum Texture Dimension Size (x,y,z) 1D=(131072), 2D=(131072, 65536), 3D=(16384, 16384, 16384)
Maximum Layered 1D Texture Size, (num) layers 1D=(32768), 2048 layers
Maximum Layered 2D Texture Size, (num) layers 2D=(32768, 32768), 2048 layers
Total amount of constant memory: 65536 bytes
Total amount of shared memory per block: 49152 bytes
Total number of registers available per block: 65536
Warp size: 32
Maximum number of threads per multiprocessor: 2048
Maximum number of threads per block: 1024
Max dimension size of a thread block (x,y,z): (1024, 1024, 64)
Max dimension size of a grid size (x,y,z): (2147483647, 65535, 65535)
Maximum memory pitch: 2147483647 bytes
Texture alignment: 512 bytes
Concurrent copy and kernel execution: Yes with 2 copy engine(s)
Run time limit on kernels: Yes
Integrated GPU sharing Host Memory: No
Support host page-locked memory mapping: Yes
Alignment requirement for Surfaces: Yes
Device has ECC support: Disabled
Device supports Unified Addressing (UVA): Yes
Device PCI Domain ID / Bus ID / location ID: 0 / 3 / 0
Compute Mode:
< Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) >

deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 8.0, CUDA Runtime Version = 8.0, NumDevs = 1, Device0 = GeForce GTX 1080

安装编译FFmpeg所需要的依赖:

基本依赖

1
2
3
4
sudo apt-get update
sudo apt-get -y install autoconf automake build-essential libass-dev libfreetype6-dev \
libsdl2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev \
libxcb-xfixes0-dev pkg-config texinfo zlib1g-dev

如果是服务器系统,即没有桌面环境的话可以不安装ffplay和x11grab的依赖: libsdl2-dev libva-dev libvdpau-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev
在用户根目录下创建文件夹ffmpeg_sourcesffmpeg_buildbin以备用,其中约定:

  • ffmpeg_sources里面放所有编译所需要的源码文件,该文件夹在编译之后可以被删除
  • ffmpeg_build里面存放编译文件,包括头文件、库文件和文档,该文件夹在编译之后可以被删除,但建议保留
  • bin存放编译后的二进制程序文件,不能被删除
    当然这些文件夹都可以自定义存放位置

    安装yasm

    如果系统中的yasm版本号大于1.2.0,可以直接通过系统源来安装
    查看yasm版本等信息:
    1
    apt-cache show yasm
    我这里显示版本为1.3,可以直接通过系统源安装:
    1
    sudo apt-get install yasm
    或者手动编译安装:
    1
    2
    3
    4
    5
    6
    7
    cd ~/ffmpeg_sources
    wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
    tar xzvf yasm-1.3.0.tar.gz
    cd yasm-1.3.0
    ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin"
    make
    make install
  • 以下安装的所有依赖包都是可选的,需要在FFmpeg编译是添加相应的启用选项,所以可以根据自己需要来安装*

    安装libx264

    类似上面查看yasm版本号一样,需要libx264-dev的版本号大于118
    我这里显示是148,所以可以直接安装:
    1
    sudo apt-get install libx264-dev
    或者编译安装:
    1
    2
    3
    4
    5
    6
    7
    cd ~/ffmpeg_sources
    wget http://download.videolan.org/pub/x264/snapshots/last_x264.tar.bz2
    tar xjvf last_x264.tar.bz2
    cd x264-snapshot*
    PATH="$HOME/bin:$PATH" ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" --enable-static --disable-opencl
    PATH="$HOME/bin:$PATH" make
    make install

    安装libx265

    与上面安装方法一样,需要其版本号大于68,我这里源里面版本号是79,直接安装
    1
    sudo apt-get install libx265-dev
    或者编译安装:
    1
    2
    3
    4
    5
    6
    7
    sudo apt-get install cmake mercurial
    cd ~/ffmpeg_sources
    hg clone https://bitbucket.org/multicoreware/x265
    cd ~/ffmpeg_sources/x265/build/linux
    PATH="$HOME/bin:$PATH" cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="$HOME/ffmpeg_build" -DENABLE_SHARED:bool=off ../../source
    make
    make install

安装libvpx

要求libvpx-dev版本号大于0.9.7,我这里显示的版本号提1.5.0,直接安装:

1
sudo apt-get install libvpx-dev

或者编译安装:

1
2
3
4
5
6
7
cd ~/ffmpeg_sources
wget http://storage.googleapis.com/downloads.webmproject.org/releases/webm/libvpx-1.6.1.tar.bz2
tar xjvf libvpx-1.6.1.tar.bz2
cd libvpx-1.6.1
PATH="$HOME/bin:$PATH" ./configure --prefix="$HOME/ffmpeg_build" --disable-examples --disable-unit-tests
PATH="$HOME/bin:$PATH" make
make install

下面是一些音频相关的包,如果只是做视频图像相关,可以不安装

安装libfdk-aac

这个没有要求版本号,只要系统有libfdk-aac-dev就可以直接安装:

1
sudo apt-get install libfdk-aac-dev

或者编译安装:

1
2
3
4
5
6
7
8
cd ~/ffmpeg_sources
wget -O fdk-aac.tar.gz https://github.com/mstorsjo/fdk-aac/tarball/master
tar xzvf fdk-aac.tar.gz
cd mstorsjo-fdk-aac*
autoreconf -fiv
./configure --prefix="$HOME/ffmpeg_build" --disable-shared
make
make install

安装libmp3lam

要求版本号大于3.98.3,直接安装:

1
sudo apt-get install libmp3lame-dev

或者编译安装:

1
2
3
4
5
6
7
8
sudo apt-get install nasm
cd ~/ffmpeg_sources
wget http://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz
tar xzvf lame-3.99.5.tar.gz
cd lame-3.99.5
./configure --prefix="$HOME/ffmpeg_build" --enable-nasm --disable-shared
make
make install

安装libopus

要求libopus-dev版本号大于1.1,我这里版本号是1.1.2,直接安装:

1
sudo apt-get install libopus-dev

或者编译安装:

1
2
3
4
5
6
7
cd ~/ffmpeg_sources
wget http://downloads.xiph.org/releases/opus/opus-1.1.4.tar.gz
tar xzvf opus-1.1.4.tar.gz
cd opus-1.1.4
./configure --prefix="$HOME/ffmpeg_build" --disable-shared
make
make install

至此ffmpeg所需要的依赖已经安装完成,下面配置nvcuvid

配置NVENC并下载ffmpeg

安装NVENC的依赖:

1
2
3
4
sudo apt-get -y install glew-utils libglew-dbg libglew-dev libglew1.13 \
libglewmx-dev libglewmx-dbg freeglut3 freeglut3-dev freeglut3-dbg libghc-glut-dev \
libghc-glut-doc libghc-glut-prof libalut-dev libxmu-dev libxmu-headers libxmu6 \
libxmu6-dbg libxmuu-dev libxmuu1 libxmuu1-dbg

下载ffmpeg

1
2
3
cd ~/ffmpeg_sources
wget http://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2
tar xjvf ffmpeg-snapshot.tar.bz2

或者通过git下载最新的版本:

1
2
cd ~/ffmpeg_sources
git clone https://github.com/FFmpeg/FFmpeg ffmpeg -b master

这个时候目录结构应该是这样的(如果上面的其他依赖包都没有通过编译安装的话):

1
2
3
ffmpeg_sources/
├── ffmpeg
└── ffmpeg-snapshot.tar.bz2

下载Nvidia Video Codec SDK
由于Nvidia的下载需要较验用户,所以可能还需要先注册账号才能下载,下载后重命名为nv_sdk.zip并上传到~/ffmpeg_sources目录即可
下载地址是:https://developer.nvidia.com/nvidia-video-codec-sdk#Download

1
2
cd ~/ffmpeg_sources
wget -O nv_sdk.zip http://developer.download.nvidia.com/designworks/video-codec-sdk/secure/7.1/01/Video_Codec_SDK_7.1.9.zip?autho=1488251582_076cae8f68a8a091cd5a6f9405967dab&file=Video_Codec_SDK_7.1.9.zip

解压nv_sdk.zip并将其中的头文件拷贝到系统头文件夹/usr/include/,然后修改sdk文件夹为nv_sdk,后面编译要用:

1
2
3
unzip nv_sdk.zip
sudo cp -r Video_Codec_SDK_7.1.9/Samples/common/inc/* /usr/include/
mv Video_Codec_SDK_7.1.9 nv_sdk

编译ffmpeg与cuvid, cuda, npp以及nvenc

现在的目录结构如下(可以忽略根目录下的2个压缩包):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
ffmpeg_sources
├── ffmpeg
│ ├── arch.mak
│ ├── Changelog
│ ├── cmdutils.c
│ ├── cmdutils_common_opts.h
│ ├── cmdutils.h
│ ├── cmdutils_opencl.c
│ ├── common.mak
│ ├── compat
│ ├── configure
│ ├── CONTRIBUTING.md
│ ├── COPYING.GPLv2
│ ├── COPYING.GPLv3
│ ├── COPYING.LGPLv2.1
│ ├── COPYING.LGPLv3
│ ├── CREDITS
│ ├── doc
│ ├── ffmpeg.c
│ ├── ffmpeg_cuvid.c
│ ├── ffmpeg_dxva2.c
│ ├── ffmpeg_filter.c
│ ├── ffmpeg.h
│ ├── ffmpeg_opt.c
│ ├── ffmpeg_qsv.c
│ ├── ffmpeg_vaapi.c
│ ├── ffmpeg_vdpau.c
│ ├── ffmpeg_videotoolbox.c
│ ├── ffplay.c
│ ├── ffprobe.c
│ ├── ffserver.c
│ ├── ffserver_config.c
│ ├── ffserver_config.h
│ ├── INSTALL.md
│ ├── libavcodec
│ ├── libavdevice
│ ├── libavfilter
│ ├── libavformat
│ ├── libavresample
│ ├── libavutil
│ ├── libpostproc
│ ├── library.mak
│ ├── libswresample
│ ├── libswscale
│ ├── LICENSE.md
│ ├── MAINTAINERS
│ ├── Makefile
│ ├── presets
│ ├── README.md
│ ├── RELEASE
│ ├── tests
│ ├── tools
│ ├── VERSION
│ └── version.sh
├── ffmpeg-snapshot.tar.bz2
├── nv_sdk
│ ├── doc
│ ├── LicenseAgreement.pdf
│ ├── ReadMe.txt
│ ├── Release_notes.txt
│ └── Samples
└── nv_sdk.zip

编译命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
cd ~/ffmpeg_sources/ffmpeg
PATH="$HOME/bin:$PATH" PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure \
--prefix="$HOME/ffmpeg_build" \
--pkg-config-flags="--static" \
--extra-cflags="-I$HOME/ffmpeg_build/include" \
--extra-ldflags="-L$HOME/ffmpeg_build/lib" \
--bindir="$HOME/bin" \
--enable-gpl \
--enable-libass \
--enable-libfdk-aac \
--enable-libfreetype \
--enable-libmp3lame \
--enable-libopus \
--enable-libtheora \
--enable-libvorbis \
--enable-libvpx \
--enable-libx264 \
--enable-libx265 \
--enable-nonfree \
--extra-cflags=-I../nv_sdk \
--extra-ldflags=-L../nv_sdk \
--extra-cflags="-I/usr/local/cuda/include/" \
--extra-ldflags=-L/usr/local/cuda/lib64 \
--disable-shared \
--enable-nvenc \
--enable-cuda \
--enable-cuvid \
--enable-libnpp
PATH="$HOME/bin:$PATH" make -j$(nproc)
make -j$(nproc) install
make -j$(nproc) distclean
hash -r

编译完成之后的文件在目录~/bin下面,将其添加到path路径之后即可直接调用:

1
2
echo 'export PATH=~/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

将编译好的ffmpeg库加入到系统动态库搜索路径中:

1
2
echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/ffmpeg_build/lib' >> ~/.bashrc
sudo ldconfig

不过好像make安装之后会自动添加库路径,可以通过以下命令查看所有库:

1
sudo ldconfig -v

bin目录下的文件结构:

1
2
3
4
5
bin/
├── ffmpeg
├── ffplay
├── ffprobe
└── ffserver

ffmpeg_build目录下的文件结构:

1
2
3
4
5
ffmpeg_build/
├── bin
├── include
├── lib
└── share

为了能够使用man ffmpeg等ffmpeg相关的man手册,可以执行以下语句:

1
echo "MANPATH_MAP $HOME/bin $HOME/ffmpeg_build/share/man" >> ~/.manpath

测试FFmpeg与GPU的硬解码

测试ffplay播放视频(假定输入文件都已经存在):

1
ffplay input.avi

测试ffmpeg转码:

1
ffmpeg -i input.avi output.mp4

测试采用GPU进行解码加速转码:

1
ffmpeg -i input.avi -c:v h264_nvenc -preset default output_2.mp4

同时使用CUVID,NVENC和NPP进行加速转码:

1
ffmpeg -hwaccel_device 0 -hwaccel cuvid -c:v h264_cuvid -i input.mp4 -vf scale_npp=-1:720 -c:v h264_nvenc -preset slow output.mkv

转码过程中可以看到后面有个倍速,使用GPU明显比不使用速度要快

查看ffmpeg支持的cuvid的解码格式:

1
ffmpeg -decoders | grep cuvid

我这里的输出为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ffmpeg version N-83691-g7f62368 Copyright (c) 2000-2017 the FFmpeg developers
built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.4) 20160609
configuration: --prefix=/home/dutoeserver/ffmpeg_build --pkg-config-flags=--static --extra-cflags=-I/home/dutoeserver/ffmpeg_build/include --extra-ldflags=-L/home/dutoeserver/ffmpeg_build/lib --bindir=/home/dutoeserver/bin --enable-gpl --enable-libass --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-nonfree --extra-cflags=-I../nv_sdk --extra-ldflags=-L../nv_sdk --extra-cflags=-I/usr/local/cuda/include/ --extra-ldflags=-L/usr/local/cuda/lib64 --disable-shared --enable-nvenc --enable-cuda --enable-cuvid --enable-libnpp
libavutil 55. 47.100 / 55. 47.100
libavcodec 57. 81.100 / 57. 81.100
libavformat 57. 66.102 / 57. 66.102
libavdevice 57. 3.100 / 57. 3.100
libavfilter 6. 74.100 / 6. 74.100
libswscale 4. 3.101 / 4. 3.101
libswresample 2. 4.100 / 2. 4.100
libpostproc 54. 2.100 / 54. 2.100
V..... h264_cuvid Nvidia CUVID H264 decoder (codec h264)
V..... hevc_cuvid Nvidia CUVID HEVC decoder (codec hevc)
V..... mjpeg_cuvid Nvidia CUVID MJPEG decoder (codec mjpeg)
V..... mpeg1_cuvid Nvidia CUVID MPEG1VIDEO decoder (codec mpeg1video)
V..... mpeg2_cuvid Nvidia CUVID MPEG2VIDEO decoder (codec mpeg2video)
V..... mpeg4_cuvid Nvidia CUVID MPEG4 decoder (codec mpeg4)
V..... vc1_cuvid Nvidia CUVID VC1 decoder (codec vc1)
V..... vp8_cuvid Nvidia CUVID VP8 decoder (codec vp8)
V..... vp9_cuvid Nvidia CUVID VP9 decoder (codec vp9)

不使用grep过滤的话会显示所有支持的解码格式

通过以下选项查看ffmpeg支持硬件加速方式:

1
ffmpeg -hwaccels

我这里的输出为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ffmpeg version N-83691-g7f62368 Copyright (c) 2000-2017 the FFmpeg developers
built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.4) 20160609
configuration: --prefix=/home/dutoeserver/ffmpeg_build --pkg-config-flags=--static --extra-cflags=-I/home/dutoeserver/ffmpeg_build/include --extra-ldflags=-L/home/dutoeserver/ffmpeg_build/lib --bindir=/home/dutoeserver/bin --enable-gpl --enable-libass --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-nonfree --extra-cflags=-I../nv_sdk --extra-ldflags=-L../nv_sdk --extra-cflags=-I/usr/local/cuda/include/ --extra-ldflags=-L/usr/local/cuda/lib64 --disable-shared --enable-nvenc --enable-cuda --enable-cuvid --enable-libnpp
libavutil 55. 47.100 / 55. 47.100
libavcodec 57. 81.100 / 57. 81.100
libavformat 57. 66.102 / 57. 66.102
libavdevice 57. 3.100 / 57. 3.100
libavfilter 6. 74.100 / 6. 74.100
libswscale 4. 3.101 / 4. 3.101
libswresample 2. 4.100 / 2. 4.100
libpostproc 54. 2.100 / 54. 2.100
Hardware acceleration methods:
vdpau
vaapi
cuvid

卸载ffmpeg

卸载刚刚编译安装的ffmpeg命令如下:

1
2
3
4
5
6
rm -rf ~/ffmpeg_build ~/ffmpeg_sources ~/bin/{ffmpeg,ffprobe,ffplay,ffserver,vsyasm,x264,x265,yasm,ytasm}
sudo apt-get autoremove autoconf automake build-essential cmake libass-dev libfreetype6-dev \
libmp3lame-dev libopus-dev libsdl2-dev libtheora-dev libtool libva-dev libvdpau-dev \
libvorbis-dev libvpx-dev libx264-dev libxcb1-dev libxcb-shm0-dev ibxcb-xfixes0-dev mercurial texinfo zlib1g-dev
sed -i '/ffmpeg_build/c\' ~/.manpath
hash -r

可能遇到的错误:
ERROR: x265 not found using pkg-config
按照上面的x265编译安装方法重新编译,而不是直接使用系统源中自带的包安装
ERROR: libnpp not found
添加编译参数--extra-cflags="-I/usr/local/cuda/include/" --extra-ldflags=-L/usr/local/cuda/lib64 \,并且要在--enable-libnpp之前的位置

参考:
1.https://trac.ffmpeg.org/wiki/CompilationGuide/Generic
2.https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu
3.https://developer.nvidia.com/nvidia-video-codec-sdk
4.https://developer.nvidia.com/ffmpeg
5.https://gist.github.com/Brainiarc7/988473b79fd5c8f0db54b92ebb47387a

Welcome to my other publishing channels