FFmpeg 4 with NVIDIA Encoding and Decoding support

12/03/2019 - 14:45
No votes yet

FFmpeg is an extremely versatile video manipulation utility and used by many related software packages. It support many video and audio formats and can use hardware acceleration, with for example NVIDIA GPUs. Unfortunately, due to legal & license reasons and also version dependencies, the binary distributed versions of FFmpeg don't usually have NVIDIA hardware acceleration enabled. This tutorial will help you build proper FFmpeg packages that includes NVIDIA hardware acceleration for encoding and decoding of various video formats. The formats supported varies with the GPU used, consult this video encode & decode support matrix for details.

We will need to add a couple of PPAs and install quite a lot of dependencies, so make sure you have enough disk space available. FFmpeg sources and build result will take about 3GB.

Why use hardware acceleration ?

Using the GPU for encoding or decoding is much faster the CPU-only based codecs and you can free up CPU resources for the uses. For example if you are streaming and your CPU is not fast enough you will get frame drops.

Lets get started !

Add required repositories

Add FFMPEG PPA

Fortunately there exists a PPA with everything we need for FFmpeg 4.

sudo add-apt-repository ppa:jonathonf/ffmpeg-4
sudo apt-get update

Note: If all you need is updated FFmpeg, without the NVIDIA hardware acceleration extras, then you can just install the ffmpeg package and you are done.

sudo apt-get install ffmpeg

Otherwise continue with the tutorial!

Add NVIDIA Driver PPA

You need to be running updated NVIDIA GPU driver, so first upgrade your NVIDIA drivers. Luckily there is a PPA for that too.

Add the Proprietary GPU Drivers PPA and upgrade your driver:

sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt-get update
sudo apt-get install nvidia-418

Note: If nvidia-418 is not available for your distribution, for example if you are on Ubuntu Xenical / Linux Mint 18.3, then install nvidia-415.

Install various dependencies

Install build dependencies

sudo apt-get build-dep ffmpeg
sudo apt install nvidia-cuda-toolkit

Install external dependencies

FFmpeg NVIDIA headers ("ffnvcodec")

FFmpeg sources used to come with the required headers, but they where recently split out into their own repository. You need to install them.

mkdir -p ffmpeg-deb/src
cd ffmpeg-deb
git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
cd nv-codec-headers
make
sudo make install

Note: If you are running NVIDIA Drivers 415 or older, you need to go back a bit in the API used. Checkout the 8.x API headers with:

git checkout 106d84a2c1960d1ccac7fa2646f0adc52d2d4ff2

Get the FFmpeg sources

Create a build location for FFmpeg and download the Debianized sources.

mkdir -p ffmpeg-deb/src
cd -p ffmpeg-deb
sudo apt-get source ffmpeg

This will fetch the FFmpeg sources from the ffmpeg ppa repository. At the time of writing, the version used was 4.1.1, but check first if the version has been bumped. In the following examples, substitue [version] with the version of the sources used.

Adjust the FFmpeg build rules

Edit ffmpeg-[version]/debian/rules

Add the line:

CONFIG+= --enable-nvenc --enable-cuda

somewhere after the big list of --enable-* lines. It should be quite obvious.

Optional: Add changelog entry

Edit ffmpeg-[version]/debian/changelog

and add an entry for your build version and changes.

Build the FFmpeg binary package

cd ffmpeg-[version]
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -r -b -j4

If all goes well, you should now have a bunch of packages, install the with:

dpkg -i *.deb

Check that FFmpeg has NVIDIA hardware acceleration enabled

ffmpeg -codecs|grep nvenc

DEV.LS h264    H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (decoders: h264 h264_crystalhd h264_v4l2m2m h264_cuvid ) (encoders: libx264 libx264rgb h264_nvenc h264_omx h264_v4l2m2m h264_vaapi nvenc nvenc_h264 )
DEV.L. hevc    H.265 / HEVC (High Efficiency Video Coding) (decoders: hevc hevc_cuvid ) (encoders: libx265 nvenc_hevc hevc_nvenc hevc_vaapi )

How to use NVIDIA hardware acceleration with FFmpeg ?

FFmpeg won't use hardware acceleration automatically. You need to specify it as the encoder when encoding video material.

Example conversion FFmpeg command lines
Example FFmpeg command line
Accelerated encoding of random video file to h264, using codec default settings.
ffmpeg -i input-file.mov \
-c:v h264_nvenc output-file.mp4
Accelerated decoding of h264 encoded video file to DNxHD (50 Fps, 75Mbit, FullHD), raw PCM audio
ffmpeg -c:v h264_cuvid -i GOPR0926.MP4 \
-c:v dnxhd -vf "fps=50/1,format=yuv422p" -b:v 75M -c:a pcm_s16le output.mov
High Quality h264 encoding, 4500K bitrate, High Quality encoding preset, Hiqh Quality VBR, 32 frame lookahead.
ffmpeg -i input-file.mov \
-c:v h264_nvenc -profile:v high -pixel_format nv12 \
-b:v 4500k -preset slow -rc vbr_hq -rc-lookahead 32 output-file.mp4
Encode with yuv444p color format (Note: Not all GPUs support this)
ffmpeg -i input-file.mov \
-c:v h264_nvenc -profile high444p \
-pixel_format yuv444p -preset default output-file.mp4
YouTube recommended 1080p 8000k video bitrate, fast start

AAC384k audio bitrate
ffmpeg -i input-file.mov \
-c:v h264_nvenc -profile:v high -pixel_format nv12 \
-b:v 8000k -preset slow -bf:v 2 -rc vbr_hq -rc-lookahead 32 \
-c:a aac -b:a 384k \
-movflags +faststart \
output-file.mp4

Encoding options for NVIDIA NVENC H.264 encoder

  -preset            <int>        E..V..... Set the encoding preset (from 0 to 11) (default medium)
     default                      E..V.....
     slow                         E..V..... hq 2 passes
     medium                       E..V..... hq 1 pass
     fast                         E..V..... hp 1 pass
     hp                           E..V.....
     hq                           E..V.....
     bd                           E..V.....
     ll                           E..V..... low latency
     llhq                         E..V..... low latency hq
     llhp                         E..V..... low latency hp
     lossless                     E..V.....
     losslesshp                   E..V.....
  -profile           <int>        E..V..... Set the encoding profile (from 0 to 3) (default main)
     baseline                     E..V.....
     main                         E..V.....
     high                         E..V.....
     high444p                     E..V.....
  -level             <int>        E..V..... Set the encoding level restriction (from 0 to 51) (default auto)
     auto                         E..V.....
     1                            E..V.....
     1.0                          E..V.....
     1b                           E..V.....
     1.0b                         E..V.....
     1.1                          E..V.....
     1.2                          E..V.....
     1.3                          E..V.....
     2                            E..V.....
     2.0                          E..V.....
     2.1                          E..V.....
     2.2                          E..V.....
     3                            E..V.....
     3.0                          E..V.....
     3.1                          E..V.....
     3.2                          E..V.....
     4                            E..V.....
     4.0                          E..V.....
     4.1                          E..V.....
     4.2                          E..V.....
     5                            E..V.....
     5.0                          E..V.....
     5.1                          E..V.....
  -rc                <int>        E..V..... Override the preset rate-control (from -1 to INT_MAX) (default -1)
     constqp                      E..V..... Constant QP mode
     vbr                          E..V..... Variable bitrate mode
     cbr                          E..V..... Constant bitrate mode
     vbr_minqp                    E..V..... Variable bitrate mode with MinQP (deprecated)
     ll_2pass_quality              E..V..... Multi-pass optimized for image quality (deprecated)
     ll_2pass_size                E..V..... Multi-pass optimized for constant frame size (deprecated)
     vbr_2pass                    E..V..... Multi-pass variable bitrate mode (deprecated)
     cbr_ld_hq                    E..V..... Constant bitrate low delay high quality mode
     cbr_hq                       E..V..... Constant bitrate high quality mode
     vbr_hq                       E..V..... Variable bitrate high quality mode
  -rc-lookahead      <int>        E..V..... Number of frames to look ahead for rate-control (from 0 to INT_MAX) (default 0)
  -surfaces          <int>        E..V..... Number of concurrent surfaces (from 0 to 64) (default 0)
  -cbr               <boolean>    E..V..... Use cbr encoding mode (default false)
  -2pass             <boolean>    E..V..... Use 2pass encoding mode (default auto)
  -gpu               <int>        E..V..... Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on. (from -2 to INT_MAX) (default any)
     any                          E..V..... Pick the first device available
     list                         E..V..... List the available devices
  -delay             <int>        E..V..... Delay frame output by the given amount of frames (from 0 to INT_MAX) (default INT_MAX)
  -no-scenecut       <boolean>    E..V..... When lookahead is enabled, set this to 1 to disable adaptive I-frame insertion at scene cuts (default false)
  -forced-idr        <boolean>    E..V..... If forcing keyframes, force them as IDR frames. (default false)
  -b_adapt           <boolean>    E..V..... When lookahead is enabled, set this to 0 to disable adaptive B-frame decision (default true)
  -spatial-aq        <boolean>    E..V..... set to 1 to enable Spatial AQ (default false)
  -temporal-aq       <boolean>    E..V..... set to 1 to enable Temporal AQ (default false)
  -zerolatency       <boolean>    E..V..... Set 1 to indicate zero latency operation (no reordering delay) (default false)
  -nonref_p          <boolean>    E..V..... Set this to 1 to enable automatic insertion of non-reference P-frames (default false)
  -strict_gop        <boolean>    E..V..... Set 1 to minimize GOP-to-GOP rate fluctuations (default false)
  -aq-strength       <int>        E..V..... When Spatial AQ is enabled, this field is used to specify AQ strength. AQ strength scale is from 1 (low) - 15 (aggressive) (from 1 to 15) (default 8)
  -cq                <float>      E..V..... Set target quality level (0 to 51, 0 means automatic) for constant quality mode in VBR rate control (from 0 to 51) (default 0)
  -aud               <boolean>    E..V..... Use access unit delimiters (default false)
  -bluray-compat     <boolean>    E..V..... Bluray compatibility workarounds (default false)
  -init_qpP          <int>        E..V..... Initial QP value for P frame (from -1 to 51) (default -1)
  -init_qpB          <int>        E..V..... Initial QP value for B frame (from -1 to 51) (default -1)
  -init_qpI          <int>        E..V..... Initial QP value for I frame (from -1 to 51) (default -1)
  -qp                <int>        E..V..... Constant quantization parameter rate control method (from -1 to 51) (default -1)
  -weighted_pred     <int>        E..V..... Set 1 to enable weighted prediction (from 0 to 1) (default 0)
  -coder             <int>        E..V..... Coder type (from -1 to 2) (default default)
     default                      E..V.....
     auto                         E..V.....
     cabac                        E..V.....
     cavlc                        E..V.....
     ac                           E..V.....
     vlc                          E..V.....
  -b_ref_mode        <int>        E..V..... Use B frames as references (from 0 to 2) (default disabled)
     disabled                     E..V..... B frames will not be used for reference
     each                         E..V..... Each B frame will be used for reference
     middle                       E..V..... Only (number of B frames)/2 will be used for reference
  -a53cc             <boolean>    E..V..... Use A53 Closed Captions (if available) (default true)

 

Possible problems with FFmpeg

Issue Possible Solution(s)

Trying to use hardware accelerated codec when running ffmpeg results in the following output:

[h264_nvenc @ 0x561547b86280] Driver does not support the required nvenc API version. Required: 9.0 Found: 8.1

[h264_nvenc @ 0x561547b86280] The minimum required Nvidia driver for nvenc is 390.25 or newer

GPU Driver version problem:

  1. Your NVIDIA Driver is too old. Upgrade to 418 or later.
  2. If you can't upgrade to 418, use 8.1 API. See FFmpeg NVIDIA headers section.
[h264_nvenc @ 0x55aea2012280] EncodePicture failed!: unsupported param (12) You are trying to encode with options that your GPU does not support.
   

Enjoy NVIDIA acceleration with FFmpeg!

Changelog: 
08/03/2019 - 11:10
Keywords: 
NVIDIA, FFmpeg, OBS, nvenc