Building ffmpeg 6 on Windows 10

Introduction

ffmpeg is a cross-platform solution to record, convert, and stream audio and video. It can be used from Unreal Engine to change image formats, to record gameplay, and to convert content to and from various video formats. Here I am using it just to show how an Unreal Engine plugin can be developed.

ffmpeg can be downloaded from the https://ffmpeg.org/ or from https://git.ffmpeg.org/ffmpeg.git.

We download the source as a step in the build process. This is important because we use a Unix-like environment to configure and build the software, and dowloading using git from Windows can result in line-endings which are incompatible with Unix line-endings.

ffmpeg is cross-platform meaning it can be compiled for Windows, Linux, Macs and other operating systems and architectures. It has a Unix-based build system which uses Unix tools for configuring the build and finding and building dependent libraries. ffmpeg supports many different video encoders and decoders, some of which are downloaded separately from different websites if they are needed for the version you are building.

Approaches to building ffmpeg

We will be using a Unix-like terminal emulation approach to build ffmpeg. There are many alternative approaches to building ffmpeg from different sites including:

None of the above tools worked for me, whether because they were out of date or my development system was not compatible I don't know. I didn't have time to dig into them in any depth.

Using MSYS2

MSYS2 is a command line terminal which looks and behaves like a Unix terminal and supports a collection of development tools. It is not a virtual machine (VM) like VMWare, in that VMWare typically has its own disk space, whereas MSYS2 shares its file system with Windows, so you can compile using the MSYS2 terminal and create executables and libraries are visible in the Windows file system.

Another difference from a VM is that while you are inside the MSYS2 terminal you can use both Unix-style commands and Windows commands. We will be using:

  • a Unix-style "configure" command to create a makefile
  • followed by a Unix-style "make" command which
  • executes the Visual Studio C++ compiler

All this makes package management and diagnosing problems much more confusing then just using one operating system.

Using the right compiler

MSYS2 uses the Microsoft C/C++ compiler which is configured in the current environment. To create a 64 bit version of ffmpeg we need to open the 64 bit command line; specifically the "x86_x64 Cross Tools Command Prompt"
which is an option under Visual Studio 2022 on the start menu:

If you open the 32 bit "x64_x86 Cross Tools Command Prompt" everything below will work but you will end up with a 32 bit version of ffmpeg which will not work with Unreal.

Preparation

Download and install MSYS2 from https://www.msys2.org/. I installed it to the d:\tools\msys64 directory so that is the path used in the examples below.

Install nasm from https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/ to d:\tools\nasm.

Edit the msys2_shell.cmd command where MSYS2 is installed and uncomment one line, changing this line:

rem set MSYS2_PATH_TYPE=inherit

to:

set MSYS2_PATH_TYPE=inherit

Run MSYS2 with this command

d:\tools\msys64\msys2_shell.cmd -msys -use-full-path

Change the d:\tools\msys64 part to wherever you installed MSYS2

MSYS2 Prerequisites

Running msys2_shell.cmd will open a command shell. Run these commands one at a time to download and install development tools (you can't run them all at once, some of them may want you to restart the MSYS2 terminal):

pacman -Syu
pacman -S make
pacman -S diffutils
pacman -S yasm
pacman -S nasm
pacman -S mingw64/mingw-w64-x86_64-aom
pacman -S git 
pacman -S pkg-config
mv /usr/bin/link.exe /usr/bin/link.exe.bak

Setup directories

Execute these commands:

cd /d/tools
mkdir ffmpeg6
cd ffmpeg6
mkdir build sources

Building x264

Many encoders or decoders which can be included in an ffmpeg build come from different projects and vendors. If you want them to be part of your ffmpeg they might need to be downloaded and built separately.

The x264 encoder is an example of one such module. To build it execute the commands below. The "CC=cl" part of the configure command on line 9 sets the CC environment variable to tell the build process to use the Microsoft "cl" compiler command

cd /d/tools/ffmpeg6/sources
git clone --depth 1 https://code.videolan.org/videolan/x264.git
cd x264
curl "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD" > config.guess
sed -i 's/host_os = mingw/host_os = msys/' configure
cd ../../build
mkdir x264
cd x264
CC=cl ../../sources/x264/configure --prefix=./../../installed --enable-shared
make -j 16
make install
mv ../../installed/lib/libx264.dll.lib ../../installed/lib/libx264.lib

Checking the build is 64 bits

Execute this command:

 file ../../installed/bin/libx264-164.dll

you should see something like:

../../installed/bin/libx264-164.dll: PE32+ executable (DLL) (GUI) x86-64, for MS Windows,

which indicates it is a 64 bit build.

If you see this:

../../installed/bin/libx264-164.dll: PE32 executable (DLL) (GUI) Intel 80386, for MS Windows

You have accidently build a 32 bit version, probably because you have the wrong command prompt open.

Building ffmpeg

While still in the MSYS2 terminal do these steps to build ffpmeg command tools (ffmpeg, ffplay, ffprobe) and shared libraries which can be loaded into Unreal Engine.

Get the source:

cd /d/tools/ffmpeg6/sources
git clone --depth 1 git://source.ffmpeg.org/ffmpeg.git

Make a build directory:

cd ../build
mkdir ffmpeg
cd ffmpeg

Configure the build

Running a separate configuration pre-pass is a common approach in cross-platform software. This step uses all the MSYS2 packages we installed using the pacman command earlier.

The command line below also:

  • sets the CC environment variable to tell the build process to use the Microsoft cl compiler command
  • adds a directory (../../installed/lib/pkgconfig) to the PKG_CONFIG_PATH environment variable so that the configure command can find the x264.pc package configuration file which was created when we built the x264 project.
CC=cl PKG_CONFIG_PATH=$PKG_CONFIG_PATH:../../installed/lib/pkgconfig \
    ../../sources/ffmpeg/configure --prefix=../../installed \
    --toolchain=msvc --target-os=win64 --arch=x86_64 \
    --enable-x86asm --enable-asm --enable-shared  \
    --enable-gpl --enable-libx264 --enable-nonfree --enable-debug --disable-optimizations \
    --extra-ldflags="-LIBPATH:../../installed/lib" \
    --extra-cxxflags="-I../../installed/include/ -MTd -Od -Zi" \
    --extra-cflags="-I../../installed/include/ -MTd -Od -Zi" 

This configure command can take quite a while to run, sometime longer than the build itself.

Build

Execute these make commands to do the build and install the libraries and commands.

make -j 14
make install

The libraries which we built will be in /d/tools/ffmpeg6/installed/bin directory.

References