Skip to content

Instantly share code, notes, and snippets.

@pikassogod
Created October 25, 2019 21:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pikassogod/08f0d5a55bb751ff6671c16223510b3e to your computer and use it in GitHub Desktop.
Save pikassogod/08f0d5a55bb751ff6671c16223510b3e to your computer and use it in GitHub Desktop.
This gist will show you how to build a minimalist, statically-linked ffmpeg binary under the ~/bin subdirectory on your home on Ubuntu 16.04LTS. Comes with (optiona) NPP, CUDA and NVENC capabilities. See notes in the warning section.

Minimalist static FFmpeg build on Ubuntu 18.04 with Nvidia NVENC enabled.

Original guide with a standard build is here.

With this guide, I'm adding more instructions to enable support for NVIDIA CUVID and NVIDIA NPP for enhanced encode and decode performance.

Warning:

If all you require is NVENC's enablement, you do NOT need the CUDA SDK. The nv-codec-headers (below) is ALL you require. However, the SDK is needed IF, and only IF, the usage of the scale_npp and any other CUDA-based filters is required.

With that in mind, do note that the NVIDIA proprietary driver is mandatory. See the driver setup instructions below, and the warning notes for Ubuntu 18.04LTS.

Steps:

First, prepare for the build and create the work space directory:

cd ~/
mkdir ~/ffmpeg_sources
sudo apt-get -y update && apt-get dist-upgrade -y
sudo apt-get -y install autoconf automake build-essential libass-dev \
  libtool \
  pkg-config texinfo zlib1g-dev cmake mercurial libbz2-dev

Install CUDA 10.x SDK from Nvidia's repository:

Ensure that you have the latest driver:

sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt-get update && sudo apt-get -y upgrade

On Ubuntu 18.04LTS desktop, this should be enough for the device driver:

sudo apt-get install nvidia-kernel-source-430 nvidia-driver-430

On Ubuntu 18.04LTS server systems, this will do:

sudo apt install nvidia-headless-430 nvidia-utils-430 libnvidia-common-430 libnvidia-encode-430 libnvidia-decode-430 libnvidia-fbc1-430

We keep the device driver up to the latest version so as to pass ffnvcodec driver version check.

Fetch the repository installers first:

cd ~/ffmpeg_sources
wget -c -v -nc https://developer.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda_10.1.105_418.39_linux.run
chmod +x ./cuda_10.1.105_418.39_linux.run
./cuda_10.1.105_418.39_linux.run

Confirm that the library configuration file for CUDA libraries also exists with the correct settings:

/etc/ld.so.conf.d/cuda.conf

The content should be:

/usr/local/cuda/lib64

When done, load the new configuration:

sudo ldconfig -vvvv

Now, set up the environment variables for CUDA:

Edit the /etc/environment file and append the following:

CUDA_HOME=/usr/local/cuda

Now, append the PATH variable with the following:

/usr/local/cuda/bin:$HOME/bin

When done, remember to source the file:

source /etc/environment

Build FFmpeg's dependency chain:

Build and deploy nasm: Nasm is an assembler for x86 optimizations used by x264 and FFmpeg. Highly recommended or your resulting build may be very slow. Note that we're using the latest release candidate, and not the stable version as of the time of writing.

cd ~/ffmpeg_sources
wget wget http://www.nasm.us/pub/nasm/releasebuilds/2.14.02/nasm-2.14.02.tar.gz
tar xzvf nasm-2.14.02.tar.gz
cd nasm-2.14.02
./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" 
make -j$(nproc) VERBOSE=1
make -j$(nproc) install
make -j$(nproc) distclean

Build and deploy libx264 statically: This library provides a H.264 video encoder. See the H.264 Encoding Guide for more information and usage examples. This requires ffmpeg to be configured with --enable-gpl --enable-libx264.

cd ~/ffmpeg_sources
git clone http://git.videolan.org/git/x264.git -b stable
cd x264/
PATH="$HOME/bin:$PATH" ./configure --prefix="$HOME/ffmpeg_build" --enable-static --enable-pic --bit-depth=all
PATH="$HOME/bin:$PATH" make -j$(nproc) VERBOSE=1
make -j$(nproc) install VERBOSE=1
make -j$(nproc) distclean

Note: If you need to enable OpenCL support for either libx264 or FFmpeg, ensure that:

(a). The flag --disable-opencl is removed from libx264's configuration.

(b). The flag enable-opencl is present in FFmpeg's configure options.

(c ). The prerequisite packages for OpenCL development are present:

With OpenCL, the installable client drivers (ICDs) are normally issued with the accelerator's device drivers, namely:

  1. The NVIDIA CUDA toolkit (and the device driver) for NVIDIA GPUs.
  2. AMD's RoCM for GCN-class AMD hardware.
  3. Intel's beignet and the newer Neo compute runtime.

The purpose of the installable client driver model is to allow multiple OpenCL platforms to coexist on the same platform. That way, multiple OpenCL accelerators, be they discrete GPUs paired with a combination of FPGAs and integrated GPUs can all coexist.

However, for linkage purposes, you'll require the ocl-icd package, which can be installed by:

sudo apt install ocl-icd-* 

Why ocl-icd? Simple: Whereas other ICDs may permit you to link against them directly, it is discouraged so as to limit the risk of unexpected runtime behavior. Assume ocl-icd to be the gold link target if your goal is to be platform-neutral as possible.

OpenCL in FFmpeg:

OpenCL's enablement in FFmpeg comes in two ways:

(a):. Some encoders, such as libx264, if built with OpenCL enablement, can utilize these capabilities for accelerated lookahead functions. The performance impact for this enablement will vary with the GPU on the platform, and with older GPUs, may slow down the encoder. Lower power platforms such as specific AMD APUs and their SoCs may see modest performance improvements at best, but on modern, high performance GPUs, your mileage may vary. Expect no miracles. The reason OpenCL lookahead is available for this library in particular is that the lookahead algorithms for OpenCL are easily parallelized.

For instance, you can combine the -hwaccel auto option which allows you to select the hardware-based accelerated decoding to use for the encode session with libx264. You can add this parameter with "auto" before input (if your x264 is compiled with OpenCL support you can try to add -x264opts param), for example:

ffmpeg -hwaccel auto -i input -vcodec libx264 -x264opts opencl output

(b):. FFmpeg, in particular, can utilize OpenCL with some filters, namely program_opencl and opencl_src as documented in the filters documentation, among others.

See the sample command below:

ffmpeg -hide_banner -v verbose -init_hw_device 
opencl=ocl:1.0 -filter_hw_device ocl -i 
"cheeks.mkv" -an -map_metadata -1 -sws_flags 
lanczos+accurate_rnd+full_chroma_int+full_chroma_inp -filter_complex 
"[0:v]yadif=0:0:0,hwupload,unsharp_opencl=lx=3:ly=3:la=0.5:cx=3:cy=3:ca=0.5,hwdownload,setdar=dar=16/9" 
 -r 25 -c:v h264_nvenc -preset:v llhq -bf 2 -g 50 -refs 3 -rc:v 
vbr_hq -rc-lookahead:v 32 -coder:v cabac -movflags 
+faststart -profile:v high -level 4.1 -pixel_format yuv420p -y 
".crunchy_cheeks.mp4"

List OpenCL platform devices:

ffmpeg -hide_banner -v verbose -init_hw_device list
ffmpeg -hide_banner -v verbose -init_hw_device opencl
ffmpeg -hide_banner -v verbose -init_hw_device opencl:1.0 

For the filter, see:

ffmpeg -hide_banner -v verbose -h filter=unsharp_opencl 

Bonus score: If you're adventurous, you could also try out this OpenCL build of libvpx from Ittiam systems, especially if you're using Integrated graphics.

Carrying on:

Build and configure libx265: This library provides a H.265/HEVC video encoder. See the H.265 Encoding Guide for more information and usage examples.

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 -j$(nproc) VERBOSE=1
make -j$(nproc) install
make -j$(nproc) clean

Build and deploy the libfdk-aac library: This provides an AAC audio encoder. See the AAC Audio Encoding Guide for more information and usage examples. This requires ffmpeg to be configured with --enable-libfdk-aac (and --enable-nonfree if you also included --enable-gpl).

cd ~/ffmpeg_sources
git clone https://github.com/mstorsjo/fdk-aac
cd fdk-aac
autoreconf -fiv
./configure --prefix="$HOME/ffmpeg_build" --disable-shared
make -j$(nproc)
make -j$(nproc) install
make -j$(nproc) distclean

Take note that changes to the inclusion of third party headers affects new builds, and this is fixed by:

cd ~/ffmpeg_sources
git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
cd nv-codec-headers
make
make install PREFIX="$HOME/ffmpeg_build"

Proceed as usual:

Building a static ffmpeg binary with the required options:

cd ~/ffmpeg_sources
git clone https://github.com/FFmpeg/FFmpeg -b master
cd 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-cuda-nvcc \
  --enable-cuvid \
  --enable-libnpp \
  --extra-cflags="-I/usr/local/cuda/include/" \
  --extra-ldflags=-L/usr/local/cuda/lib64/ \
  --enable-gpl \
  --enable-libass \
  --enable-libfdk-aac \
  --enable-libx264 \
  --enable-libx265 \
  --enable-pic \
  --extra-libs="-lpthread -lm -lz -ldl" \
  --enable-nvenc \
  --enable-nonfree
PATH="$HOME/bin:$PATH" make -j$(nproc) VERBOSE=1
make -j$(nproc) install
make -j$(nproc) distclean
hash -r

Remember the notes above on builds that do not require any CUDA-based filters? This build below will give you exactly that:

cd ~/ffmpeg_sources
git clone https://github.com/FFmpeg/FFmpeg -b master
cd 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-libx264 \
  --enable-libx265 \
  --enable-pic \
  --extra-libs="-lpthread -lm -lz -ldl" \
  --enable-nvenc \
  --enable-nonfree
PATH="$HOME/bin:$PATH" make -j$(nproc) VERBOSE=1
make -j$(nproc) install
make -j$(nproc) distclean
hash -r

Handling package upgrades:

For individual packages availed via git, simply navigate to their source directory and run git pull followed by re-building them:

(a). For nasm:

cd ~/ffmpeg_sources
git clone git://repo.or.cz/nasm.git
cd nasm
./autogen.sh
./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin"
make -j$(nproc) VERBOSE=1
make -j$(nproc) install
make -j$(nproc) distclean

(b). For x264:

cd ~/ffmpeg_sources/x264
git pull
PATH="$HOME/bin:$PATH" ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" --enable-static --enable-pic --disable-opencl
PATH="$HOME/bin:$PATH" make -j$(nproc) VERBOSE=1
make -j$(nproc) install
make -j$(nproc) distclean

(c). For x265:

cd ~/ffmpeg_sources/x265
hg pull
hg update
cd ~/ffmpeg_sources/x265/build/linux
PATH="$HOME/bin:$PATH" cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="$HOME/ffmpeg_build" -DENABLE_SHARED:bool=on ../../source
make -j$(nproc) VERBOSE=1
make -j$(nproc) install
make -j$(nproc) clean

(d). For the FFmpeg NVENC headers:

cd nv-codec-headers
git pull
make
sudo make install

(e). For FFmpeg:

cd ~/ffmpeg_sources/FFmpeg
git pull
PATH="$HOME/bin:$PATH" PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig:/usr/lib/x86_64-linux-gnu/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-cuda-nvcc \
  --enable-cuvid \
  --enable-libnpp \
  --extra-cflags="-I/usr/local/cuda/include/" \
  --extra-ldflags=-L/usr/local/cuda/lib64/ \
  --enable-gpl \
  --enable-libass \
  --enable-libfdk-aac \
  --enable-libx264 \
  --enable-libx265 \
  --enable-pic \
  --extra-libs="-lpthread -lm -lz -ldl" \
  --enable-nvenc \
  --enable-nonfree
PATH="$HOME/bin:$PATH" make -j$(nproc) VERBOSE=1
make -j$(nproc) install
make -j$(nproc) distclean
hash -r
  1. An FFmpeg build with NVENC only (without CUDA dependencies):
cd ~/ffmpeg_sources/FFmpeg
git pull
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-libx264 \
  --enable-libx265 \
  --enable-nvenc \
  --enable-pic \
  --extra-libs="-lpthread -lm -lz -ldl" \
  --enable-nonfree
PATH="$HOME/bin:$PATH" make -j$(nproc) VERBOSE=1
make -j$(nproc) install
make -j$(nproc) distclean
hash -r

On nasm:

We build nasm from source, using the git master tip as it contains the latest assembler optimizations for modern processor architectures. When considering subsequent updates to FFmpeg, consider switching to the git clone rather than the tarball fetched from nasm.us. However, we retain both versions for assembler testing and compatibility, should the master tip version fail to build due to compiler errors and warnings.

Confirm that all GPUs are working:

nvidia-smi -q | grep Encoder | wc -l

This should return the number of GPUs present , and in the case of the dual Tesla M60s, based on the GM204GL SKUs, expect the number to be 4 on a dual-GPU system as each card has a single NVENC chip per graphics processor.

Note that on newer platforms (such as the Nvidia Pascal P1000), the number of NVENC chips per GPU may vary, and may be up to 3 per GPU, totalling to six per Tesla board. See the GPU support matrix for more information.

If ~/bin is already in your path, you can call up ffmpeg directly. Note that the build instructions assume that the NVIDIA CUDA toolkit is on the system path, as is recommended during setup.

Hint: Use this guide to learn how to launch ffmpeg in multiple instances for faster NVENC based encoding on capable hardware.

@Brainiarc7
Copy link

Hello @pikassogod , kindly contact me as soon as possible. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment