06 June 2014

Building FFmpeg for H.264 and AAC

I'm planning to encode a bunch of family videos into MPEG-4 with H.264 and AAC. In my next post I'll get into the details of the command-line settings.

Due to licensing issues, the pre-built versions of FFmpeg for Windows that you can download do not include AAC audio encoding. For maximum compatibility across Windows, MacOS, iOS and others I need to use AAC. So, it becomes necessary to download and build FFmpeg from the source code.

The following are instructions for building FFmpeg in 64-bit with H.264 and AAC support. It's pretty straightforward for anyone who's used command-line software. But, if these instructions look too intimidating you might pay a college student $15 to do this and send you the result.

The build is on Windows and is targeted at 64-bit Windows. If you run into problems, first check the comments to see if someone else has addressed the issue, then check the original sources in the list below. Finally, if you have hints or solutions to emerging issues please comment for the sake of others. Here are the sources from which I assembled all of this (along with some trial and error):
Everything will be done in a new "ffb" folder (for "FFmpeg build"). There are no changes to the registry, no software installation programs to run. When you're finished just delete the "ffb" folder and your system will be as pristine as when you started. (But don't forget to copy the FFmpeg.exe file out of there before deleting the folder!)

1. Download and install MinGW-64 with MSYS

MinGW is a minimalist GNU Compliler collection for windows. MSYS is a set of Unix-like build utilities. There are a number of versions of these tools out there. In addition to the basic MinGW and MSYS you need a bunch of libraries and header files. Nyakov pointed to a package on xhmikosr.1f0.de that has all of the needed packages. For convenience, I've repackaged it as a .zip file from the original 7-Zip.

1.a. Create a folder called "ffb" in the root of your "C" drive (C:\ffb). You can put this elsewhere but the instructions below will be easier if it's in the root of "C". 
1.b. Download MSYS_MinGW-w64_GCC_483_x86-x64_Full.zip. It's a big file, approximately 170MB. If you've got 7-Zip handy you can download this smaller version from xhmikosr.1f0.de. You can also use a download manager.
1.c. Open the MSYS_MinGW-w64_GCC_483_x86-x64_Full.7z package using 7-Zip. Copy the MSYS folder and all of its contents into C:\ffb. So, now you have folder called C:\ffb\MSYS.
1.d. In the Windows File Explorer browse to C:\ffb\msys\postinstall and launch "pi.bat". The batch file will ask "Do you wish to continue..." You answer:  y (enter). It will ask "Do you have "MinGW" installed?" You answer: y (enter). It will ask "Where is your MinGW installation?" You answer: C:/ffb/MSYS/mingw (enter).
This is a post install process that will try to normalize between
your MinGW install if any as well as your previous MSYS installs
if any.  I don't have any traps as aborts will not hurt anything.
Do you wish to continue with the post install? [yn ] y

Do you have MinGW installed? [yn ] y

Please answer the following in the form of c:/foo/bar.
Where is your MinGW installation? C:/ffb/MSYS/mingw

        Normalizing your MSYS environment.

You have script /bin/cmd

Oh joy, you do not have C:/ffb/MSYS/mingw/bin/make.exe. Keep it that way.

When you configured MSYS, it created a "home" folder with your username. For these instructions we'll pretend that your username is "Fred". In the tasks that follow, substitute your username wherever "Fred" appears.

2. Download the source code packages

You'll need source code to the following packages. Download each from the specified URL

LAME MP3 audio encoder
Browse here and download lame-3.99.5.tar.gz
If the version you get is not 3.99.5 then either search the code repository for the earlier version or use the new version name in the commands that follow.

FDK AAC audio encoder
Browse here and download fdk-aac-0.1.3.tar.gz
As with the MP3 encoder. if the version is different from 0.1.3 you'll either need to search for the earlier version or use the new version name in the commands that follow.

VideoLAN x264 video encoder for H.264
Browse here and download last_x264.tar.bz2

FFmpeg video conversion utility
Browse here and scroll down to the "FFmpeg releases" section. Click on the "Download bzip2 tarball" link.
In my case, I chose the "FFmpeg 2.2.3 Muybridge" version which was released on 2014-06-03.

Move the four downloaded packages to your MSYS home folder, "C:\ffb\msys\home\Fred". (Remember, substitute your username for "Fred".)

3. Launch the MSYS command-line shell

MSYS has it's own command-line shell. Launch "C:\ffb\msys\msys.bat" to get it running. Then type the following command to make sure all the files are in the right place:

ls
Fred@System ~
$ ls
fdk-aac-0.1.3.tar.gz  lame-3.99.5.tar.gz
ffmpeg-2.2.3.tar.bz2  last_x264.tar.bz2

4. Build the LAME MP3 audio Encoder

In the MSYS command-line shell type the following commands:
tar xvfz lame-3.99.5.tar.gz
cd ~/lame-3.99.5
./configure --prefix=/usr/local/x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --enable-static --disable-shared --disable-decoder --enable-nasm
make clean && make
make install
cd ~
Fred@System ~
$ tar xvfz lame-3.99.5.tar.gz
lame-3.99.5/
lame-3.99.5/frontend/
lame-3.99.5/frontend/amiga_mpega.c
    ... a bunch of stuff ...
lame-3.99.5/include/lame.h
lame-3.99.5/include/lame.def
lame-3.99.5/HACKING

Fred@System ~
$ cd ~/lame-3.99.5

Fred@System ~/lame-3.99.5
$ ./configure --prefix=/usr/local/x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --enable-static --disable-shared --disable-decoder --enable-nasm
configure: WARNING: if you wanted to set the --build type, don't use --host.
    If a cross compiler is detected then cross compile mode will be used
checking build system type... i686-pc-mingw32
checking host system type... x86_64-w64-mingw32
checking for a BSD-compatible install... /bin/install -c
    ... a bunch of stuff ...
config.status: creating config.h
config.status: executing depfiles commands
config.status: executing libtool commands

Fred@System ~/lame-3.99.5
$ make clean && make
Making clean in vc_solution
make[1]: Entering directory `/home/Fred/lame-3.99.5/vc_solution'
rm -rf .libs _libs
    ... a whole bunch of stuff ...
make[2]: Nothing to be done for `all-am'.
make[2]: Leaving directory `/home/Fred/lame-3.99.5'
make[1]: Leaving directory `/home/Fred/lame-3.99.5'

Fred@System ~/lame-3.99.5
$ make install
Making install in mpglib
make[1]: Entering directory `/home/Fred/lame-3.99.5/mpglib'
make[2]: Entering directory `/home/Fred/lame-3.99.5/mpglib'
    ... a bunch of stuff ...
----------------------------------------
Libraries have been installed in:
   /usr/local/x86_64-w64-mingw32/lib
    ... more stuff ...
make[2]: Nothing to be done for `install-data-am'.
make[2]: Leaving directory `/home/Fred/lame-3.99.5'
make[1]: Leaving directory `/home/Fred/lame-3.99.5'

Fred@System ~/lame-3.99.5
$ cd ~

Fred@System ~
$

5. Build the FDK AAC audio encoder

In the MSYS command-line shell type the following commands:
tar xvfz fdk-aac-0.1.3.tar.gz
cd ~/fdk-aac-0.1.3
./configure --prefix=/usr/local/x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --enable-shared=no
make clean && make
make install
cd ~
Fred@System ~
$ tar xvfz fdk-aac-0.1.3.tar.gz
fdk-aac-0.1.3/
fdk-aac-0.1.3/configure.ac
fdk-aac-0.1.3/aac-enc.c
    ... a bunch of stuff ...
fdk-aac-0.1.3/config.sub
fdk-aac-0.1.3/ltmain.sh
fdk-aac-0.1.3/wavreader.c

Fred@System ~
$ cd ~/fdk-aac-0.1.3

Fred@System ~/fdk-aac-0.1.3
$ ./configure --prefix=/usr/local/x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --enable-shared=no
checking for a BSD-compatible install... /bin/install -c
checking whether build environment is sane... yes
checking for x86_64-w64-mingw32-strip... x86_64-w64-mingw32-strip
    ... a bunch of stuff ...
config.status: creating fdk-aac.pc
config.status: executing depfiles commands
config.status: executing libtool commands

Fred@System ~/fdk-aac-0.1.3
$ make clean && make
test -z "libfdk-aac.la" || rm -f libfdk-aac.la
rm -f "./so_locations"
rm -rf .libs _libs
    ... a bunch of stuff ...
  CXX    libSYS/src/wav_file.lo
  GEN    libfdk-aac.la
copying selected object files to avoid basename conflicts...

Fred@System ~/fdk-aac-0.1.3
$ make install
make[1]: Entering directory `/home/Fred/fdk-aac-0.1.3'
 /bin/mkdir -p '/usr/local/x86_64-w64-mingw32/lib'
    ... some stuff ...
 /bin/mkdir -p '/usr/local/x86_64-w64-mingw32/lib/pkgconfig'
 /bin/install -c -m 644 fdk-aac.pc '/usr/local/x86_64-w64-mingw32/lib/pkgconfig'

make[1]: Leaving directory `/home/Fred/fdk-aac-0.1.3'

Fred@System ~/fdk-aac-0.1.3
$ cd ~

Fred@System ~
$

6. Build the x264 video encoder

In the MSYS command-line shell type the following commands. Since VideoLan posts daily snapshots, the name of the folder to which the tarball unpacks will probably be different from the one shown in the "cd" command. Look at the output from the "tar" command and use the corresponding folder name on the "cd" command:
tar xvjf last_x264.tar.bz2
cd ~/x264-snapshot-20140605-2245
./configure --prefix=/usr/local/x86_64-w64-mingw32 --cross-prefix=x86_64-w64-mingw32- --host=x86_64-w64-mingw32 --enable-static --bit-depth=8 --enable-win32thread
make clean && make
make install
cd ~
Fred@System ~
$     ... a bunch of stuff ...
x264-snapshot-20140605-2245/COPYING
x264-snapshot-20140605-2245/AUTHORS
x264-snapshot-20140605-2245/.gitignore

Fred@System ~/x264-snapshot-20140605-2245
$ ./configure --prefix=/usr/local/x86_64-w64-mingw32 --cross-prefix=x86_64-w64-mingw32- --host=x86_64-w64-mingw32 --enable-static --bit-depth=8 --enable-win32thread
platform:      X86_64
system:        WINDOWS
cli:           yes
    ... some stuff ...
bit depth:     8
chroma format: all

You can run 'make' or 'make fprofiled' now.

Fred@System ~/x264-snapshot-20140605-2245
$     ... a bunch of stuff ...
deo/crop.o filters/video/depth.o input/avs.o input/threa
.a -lgpac_static -lz -lws2_32 -lwinmm  -lshell32 -m64
dynamicbase

Fred@System ~/x264-snapshot-20140605-2245
$ make install
install -d /usr/local/x86_64-w64-mingw32/bin
install x264.exe /usr/local/x86_64-w64-mingw32/bin
    ... some stuff ...
install -m 644 libx264.a /usr/local/x86_64-w64-mingw32/lib
x86_64-w64-mingw32-ranlib /usr/local/x86_64-w64-mingw32/lib/libx264.a

Fred@System ~/x264-snapshot-20140605-2245
$ cd ~

Fred@System ~
$

7. Build FFmpeg

In the MSYS command-line shell type the following commands:
tar xvjf ffmpeg-2.2.3.tar.bz2
cd ~/ffmpeg-2.2.3
CPPFLAGS="$CPPFLAGS -I/usr/local/x86_64-w64-mingw32/include" ./configure --extra-ldflags='-L/usr/local/x86_64-w64-mingw32/lib' --prefix=/usr/local/x86_64-w64-mingw32 --cross-prefix=x86_64-w64-mingw32- --target-os=mingw32 --enable-w32threads --enable-memalign-hack --arch=x86_64 --enable-runtime-cpudetect --disable-debug --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-gpl --enable-version3 --enable-nonfree --enable-libmp3lame --enable-libfdk-aac --enable-libx264
make clean && make
make install
cd ~
Fred@System ~
$ tar xvjf ffmpeg-2.2.3.tar.bz2
ffmpeg-2.2.3/
ffmpeg-2.2.3/INSTALL
ffmpeg-2.2.3/libavresample/
    ... a bunch of stuff ...
ffmpeg-2.2.3/ffplay.c
ffmpeg-2.2.3/README
ffmpeg-2.2.3/ffmpeg.h

Fred@System ~
$ cd ~/ffmpeg-2.2.3

Fred@System ~/ffmpeg-2.2.3
$ CPPFLAGS="$CPPFLAGS -I/usr/local/x86_64-w64-mingw32/include" ./configure --extra-ldflags='-L/usr/local/x86_64-w64-mingw32/lib' --prefix=/usr/local/x86_64-w64-mingw32 --cross-prefix=x86_64-w64-mingw32- --target-os=mingw32 --enable-w32threads --enable-memalign-hack --arch=x86_64 --enable-runtime-cpudetect --disable-debug --enable-static --disable-shared --disable-ffplay --disable-ffserver --enable-gpl --enable-version3 --enable-nonfree --enable-libmp3lame --enable-libfdk-aac --enable-libx264
install prefix            /usr/local/x86_64-w64-mingw32
source path               .
C compiler                x86_64-w64-mingw32-gcc
    ... a bunch of stuff ...
License: nonfree and unredistributable
Creating config.mak, config.h, and doc/config.texi...
config.h is unchanged
config.asm is unchanged
libavutil/avconfig.h is unchanged

WARNING: x86_64-w64-mingw32-pkg-config not found, library detection may fail.

Fred@System ~/ffmpeg-2.2.3
$ make clean && make
CC      libavdevice/alldevices.o
CC      libavdevice/avdevice.o
CC      libavdevice/dshow.o
    ... a whole bunch of stuff ...
CP      ffmpeg.exe
STRIP   ffprobe.exe
STRIP   ffmpeg.exe

Fred@System ~/ffmpeg-2.2.3
$ make install
INSTALL doc/ffmpeg.1
INSTALL doc/ffprobe.1
INSTALL doc/ffmpeg-all.1
    ... a bunch of stuff ...
INSTALL libavutil/avconfig.h
INSTALL libavutil/ffversion.h
INSTALL libavutil/libavutil.pc

Fred@System ~/ffmpeg-2.2.3
$ cd ~

Fred@System ~
$

FFMpeg is ready

If all of the above has proceeded without significant errors, the result will be four applications all located in C:\ffb\MSYS\local\x86_64-w64-mingw32. They are:

  • ffmpeg.exe: The video converter application we were seeking through this exercise.
  • ffprobe.exe: An application for reporting information about a multimedia file or stream including the container type, codecs used, resolution, metadata and so forth.
  • lame.exe: A command-line encoder for MP3 audio files.
  • x264.exe: A command-line version of the x264 video encoder.
So, how do you put FFmpeg to work converting your video files? That will be the subject of my next blog post.