Compiling FFmpeg for TDM
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.
In my case its root directory is C:\msys64.
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.
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:
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:
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:
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.
Go to FFmpeg root directory within the MSYS console (note forward slashes):
Run the configuration script tdm_configure.sh you created at the very beginning:
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 providing hardware acceleration:
Libraries: avcodec avformat avutil swresample swscale
Enabled decoders: aac h263 h264 mp3 mpeg4 roq
Enabled parsers: aac h263 h264 mpeg4video mpegaudio
Enabled demuxers: avi m4v mov roq
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.
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:
- Delete directory C:\TheDarkMod\darkmod_src\include\ffmpeg with old include files.
- Copy C:\msys64\usr\local\include directory to C:\TheDarkMod\darkmod_src\include\ffmpeg.
- Delete all the libraries which look like parts of FFmpeg from C:\TheDarkMod\darkmod_src\win64\lib.
- 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:
Then rebuild TDM 64-bit in Visual Studio and proceed to the Testing section to make sure everything is built properly.
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:
- In tdm_configure.sh, change --arch=x86_64 to --arch=x86_32.
- When opening MSVC command prompt, open the 32-bit version.
- 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.
sudo apt-get install yasm
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:
- Remove --toolchain=msvc option from it.
- Set --arch=x86_64 for initial 64-bit build.
Now run the script:
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.
Run the make command:
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.
To build 32-bit Linux version, you have to follow the same general instructions (starting from section Build on Linux), with the following differences:
- Set --arch=x86_32 instead of --arch=x86_64 in configure script.
- 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:
- Use 32-bit Linux OS --- yeah, the second one. It is rather easy to do if you use VM.
- Add an additional option --cc="gcc -m32" into the configure script. Then you can hopefully build 32-bit FFmpeg on 64-bit Linux.
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.