Compiling FFmpeg for TDM

From The DarkMod Wiki
Jump to navigationJump to search

This is a guide for building FFmpeg library manually. It describes exactly how FFmpeg was built for TDM 2.07.

Starting from TDM 2.08, conan package manager is used to build all dependencies, including FFmpeg. Thus, this article should no longer be used as a guide to action. It is still valuable for in-depth explanation of how and why is FFmpeg configured. See more info in Libraries and Dependencies.

Note: If you decide to change FFmpeg version, then you have to rebuild it for all the four official platforms: Windows/Linux 32/64-bit. This is because all platforms use same headers, so if you rebuild it only on some platforms, then the other platforms will have headers/libs conflict.


Build: common steps

As a first step on any platform, you have to download FFmpeg source code. It is recommended to choose the major/minor version which was cut from master at least a year ago, and take the latest build of it.

Unpack the source code into some directory. In my case it is at C:\TheDarkMod\ffmpeg-3.3.7\.

In the FFmpeg root directory, create a text file named tdm_configure.sh with the following contents:

   ./configure \
       --toolchain=msvc \
       --disable-debug \
       --arch=x86_64 \
       --enable-static --disable-shared \
       --enable-gpl \
       --disable-all \
       --disable-autodetect \
       --enable-avformat --enable-avcodec --enable-swresample --enable-swscale \
       --enable-demuxer=roq,mov,m4v,avi \
       --enable-parser=h264,mpeg4video,aac,mpegaudio \
       --enable-decoder=roq,h264,mpeg4,aac,mp3 \

This is the command for configuring FFmpeg. The parameters are most important here.

The basic parameters include:

  • --toolchain=msvc: Use Visual C++ compiler in build.
  • --disable-debug: Strip debug information, otherwise the resulting libs will be huge.
  • --arch=x86_64: Build 64-bit version.
  • --enable-static --disable-shared: Make sure to get static libraries.
  • --enable-gpl: Make sure resulting binaries are GPL-licensed (just as TDM is).

The next set of parameters is necessary for disabling feature which we don't explicitly allow:

  • --disable-all: Disable all the features of FFmpeg.
  • --disable-autodetect: Disable all the external libraries.

Note: If your FFmpeg package does not support --disable-autodetect yet, then you have to manually disable every external library which FFmpeg tries to use in your case.

The remaining parameters enable back precisely the features which are necessary for TDM:

  • --enable-avformat --enable-avcodec --enable-swresample --enable-swscale: Build these four libraries.
  • --enable-demuxer=roq,mov,m4v,avi: Support this set of containers.
  • --enable-decoder=roq,h264,mpeg4,aac,mp3: Include this set of codecs (for decoding only).
  • --enable-parser=h264,mpeg4video,aac,mpegaudio: Include this set of parsers. Note that they cover all the decoders included.


Build on Windows

This guide mostly follows the official compilation guide on FFmpeg wiki.

Install MSYS

Download and install MSYS2 for windows. Better choose 64-bit version, e.g. msys2-x86_64-20180531.exe.

In my case its root directory is C:\msys64.

Install yasm

Download yasm as a single exe file. Better choose 64-bit version, e.g. yasm-1.3.0-win64.exe.

No installation is required. I put the executable into C:\yasm\.

Rename/copy the downloaded executable as yasm.exe. For instance, I have it as C:\yasm\yasm.exe.

Prepare MSYS

Run MSYS console with msys2_shell.cmd located at MSYS root directory. The steps described here must be done in this console.

Sync package database and update all packages with command:

   pacman -Syu

Agree to whatever it wants from you.

When it stops installing, close the console. Then start the fresh console and run "pacman -Syu" command once again.

Now you need to install packages for make and cmp commands. So run the following:

   pacman -S make
   pacman -S diffutils

After that, close the MSYS console.

Note: It seems that MSYS uses pacman manager for packages, which is also used on ArchLinux.

Open MSYS console properly

Open Visual C++ command prompt with environment set for 64-bit MSVC compilation. In my case it is called "x64 Native Tools Command Prompt for VS 2017", located in C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat. To check that you started proper console, run cl in it: it will print compiler version and bitness.

Add the directory with yasm.exe to PATH:

   set PATH=%PATH%;C:\yasm

Check that it works by running yasm command: it must print something like "yasm: No input files specified".

Now open MSYS console from within the MSVC command prompt:

   C:\msys64\msys2_shell.cmd -use-full-path

The parameter -use-full-path is important here: without it environment variables will be dropped. You can check that everything is still OK by running cl and yasm commands in the MSYS console.

Configure FFmpeg

Go to FFmpeg root directory within the MSYS console (note forward slashes):

   cd C:/TheDarkMod/ffmpeg-3.3.7

Run the configuration script tdm_configure.sh you created at the very beginning:

   ./tdm_configure.sh

Review the output with full attention. In my case I get the following output (expand the collapsed section):

   $ ./tdm_configure.sh
   install prefix            /usr/local
   source path               .
   C compiler                cl
   C library                 msvcrt
   ARCH                      x86 (generic)
   big-endian                no
   runtime cpu detection     yes
   yasm                      yes
   MMX enabled               yes
   MMXEXT enabled            yes
   3DNow! enabled            yes
   3DNow! extended enabled   yes
   SSE enabled               yes
   SSSE3 enabled             yes
   AESNI enabled             yes
   AVX enabled               yes
   XOP enabled               yes
   FMA3 enabled              yes
   FMA4 enabled              yes
   i686 features enabled     yes
   CMOV is fast              yes
   EBX available             no
   EBP available             no
   debug symbols             no
   strip symbols             no
   optimize for size         no
   optimizations             yes
   static                    yes
   shared                    no
   postprocessing support    no
   network support           no
   threading support         w32threads
   safe bitstream reader     yes
   texi2html enabled         no
   perl enabled              no
   pod2man enabled           no
   makeinfo enabled          no
   makeinfo supports HTML    no
   External libraries:
   External libraries providing hardware acceleration:
   Libraries:
   avcodec                 avformat                avutil                  swresample              swscale
   Programs:
   Enabled decoders:
   aac                     h263                    h264                    mp3                     mpeg4                   roq
   Enabled encoders:
   Enabled hwaccels:
   Enabled parsers:
   aac                     h263                    h264                    mpeg4video              mpegaudio
   Enabled demuxers:
   avi                     m4v                     mov                     roq
   Enabled muxers:
   Enabled protocols:
   Enabled filters:
   Enabled bsfs:
   Enabled indevs:
   Enabled outdevs:
   License: GPL version 2 or later
   Creating configuration files ...
   libavutil/avconfig.h is unchanged
   libavcodec/bsf_list.c is unchanged
   libavformat/protocol_list.c is unchanged
   WARNING: pkg-config not found, library detection may fail.

You should have the same features listed in your output. If some excessive options are present, disable them directly by adding appropriate flag in tdm_configure.sh. Then rerun this script in MSYS console until you get desired result.

Make sure that multithreading is enabled: w32threads on Windows and pthreads on Linux.


Build FFmpeg

After FFmpeg has been configured properly, run build in the MSYS console:

   make install -j6

The parameter -j6 sets the number of build threads, set it to the number of CPU cores you have. When build finishes successfully, close the MSYS console.

Now it remains only to copy all the files to proper place for TDM. In my case, build results are located in C:\msys64\usr\local directory. Suppose that svn root of TDM source code is located at C:\TheDarkMod\darkmod_src. Do the following:

  1. Delete directory C:\TheDarkMod\darkmod_src\include\ffmpeg with old include files.
  2. Copy C:\msys64\usr\local\include directory to C:\TheDarkMod\darkmod_src\include\ffmpeg.
  3. Delete all the libraries which look like parts of FFmpeg from C:\TheDarkMod\darkmod_src\win64\lib.
  4. Copy all the five produced .a files from C:\msys64\usr\local\lib to C:\TheDarkMod\darkmod_src\win64\lib.

After you have copied everything, clean all the trash produced by FFmpeg build:

   make distclean

Then rebuild TDM 64-bit in Visual Studio and proceed to the Testing section to make sure everything is built properly.


32-bit version

It is also necessary to build 32-bit version. To achieve it, do all the same steps starting from Open MSYS console properly section, with the following changes:

  1. In tdm_configure.sh, change --arch=x86_64 to --arch=x86_32.
  2. When opening MSVC command prompt, open the 32-bit version.
  3. When copying build results, not that 32-bit libraries are located in C:\TheDarkMod\darkmod_src\win32\lib instead of C:\TheDarkMod\darkmod_src\win64\lib.


Build on Linux

The steps on Linux are generally similar to the ones on Windows, but greatly simplified.

You need a 64-bit Linux (preferably Ubuntu) with GCC already installed. A virtual machine is perfectly OK, just share FFmpeg source code directory with it. All the steps are completed in the Linux terminal.

Install yasm
   sudo apt-get install yasm
Configure FFmpeg

Go to source code root directory, which in my case is /media/sf_TheDarkMod/ffmpeg-3.3.7.

Edit tdm_configure.sh script you have from Windows build:

  1. Remove --toolchain=msvc option from it.
  2. Set --arch=x86_64 for initial 64-bit build.

Now run the script:

   ./tdm_configure.sh

If it complains with something like "--disable-debug: command not found", then you need to convert EOLs:

   sudo apt-get install dos2unix
   dos2unix tdm_configure.sh

After that run ./tdm_configure.sh again.

Check the output of configure script, make sure it is the same as on Windows. If you see something excessive, add a flag to disable it in tdm_configure.sh and rerun the script.

Build FFmpeg

Run the make command:

   make -j6

Now search for all the .a files in the source code directory --- these are the built libs. Copy them to C:\TheDarkMod\darkmod_src\linux\ffmpeg\lib64\.

Finally, rebuild x64 version of TDM as usual and proceed to Testing section.


32-bit version

To build 32-bit Linux version, you have to follow the same general instructions (starting from section Build on Linux), with the following differences:

  1. Set --arch=x86_32 instead of --arch=x86_64 in configure script.
  2. Copy resulting binaries to C:\TheDarkMod\darkmod_src\linux\ffmpeg\.

However, the is one important caveat: the --arch options is not enough to change bitness of your build !

You have two options to workaround the problem:

  1. Use 32-bit Linux OS --- yeah, the second one. It is rather easy to do if you use VM.
  2. Add an additional option --cc="gcc -m32" into the configure script. Then you can hopefully build 32-bit FFmpeg on 64-bit Linux.


Testing

This testing routine covers all the enabled features. It should be performed for each supported platform.

Run TheDarkMod game and start any mission. "Closemouthed Shadows" FM suits well because it is fast to load.

When in game, open game console and execute the following commands one by one:

   testVideo video/ffmpeg_test/sykes_roq_roq.roq
   testVideo video/ffmpeg_test/looped_m4v_h264.m4v
   testVideo video/ffmpeg_test/tennis_mp4_h264_aac.mp4 withAudio
   testVideo video/ffmpeg_test/tearsofsteel_avi_mpeg4_mp3.avi withAudio

After each command, a video must be shown on the screen. View it up to the end.

Ensure that video plays properly, that sound is played when withAudio is specified, that no serious warnings appear in console.