Cross compiling ffmpeg


As you can see from attachment putty.txt, I have successfully built a static version of ffmpeg 4.4 as I need the libraries for Migrate Vn 0.9 (all about adding transcoding subtitles : including non-graphical forms). Slightly off topic : I offered my DVD language metadata enhancements to ffmpeg on ticket #9158 and it went down like the proverbial lead balloon.

I wondered if it was possible to build the shared libraries from the static objects I had i.e. no other dependencies e.g. libx264, libx265, … Or to put it another way no dependencies outside ffmpeg’s DSOs (Dynamic Shared Object also known as shared library). Building a DSO from purely static parts is a generic linux “black art”.

As you can see from attachment Errors.txt, I have made DSOs that the “on box” GCC is happy to link against. The .7z of the .tar used is 11.7 MB (12,316,672 bytes) so is probably bigger than I can attach. My “silly question” is am I missing a package for the llrint(f) errors? I know these functions are not part of ulibc, but I have only installed the basic gcc bundle.

As you can see from attachment SimulatorError.txt, my next problem is dynamic link loading TLS (Thread-Local Storage) data. As the native hardware and the simulator have almost identical linux kernels, the native is likely to have the same reaction to the DSOs. This is a very similar problem to the one that resulted in for early x86 pc’s, so I am going to try that approach for my own intellectual curiosity.


  • Errors.txt
    26.5 KB · Views: 5
  • putty.txt
    8.8 KB · Views: 6
  • SimulatorError.txt
    7.7 KB · Views: 4


Well-Known Member
You need compiler options -lm for /lib/, and -D_XOPEN_SOURCE=500 (or greater), and -std=c99, and #include <math.h> in the source. The -D/#define is not required according to the specification, but this is an old implementation.

Anything involving shared objects is going to need libtool, or at least I've had next to no success without it. It's a sooper-dooper shell script that calls the necessary tools depending on what is installed. There's a write-up here.

The on-box POSIX Threads library was a branch retrofitted to the version of uClibc used, as it had not yet been integrated into the main release at 0.9.29. Weird behaviour, spec violations, etc, might be expected.

The header package may not properly reflect the configuration of the on-box libraries, as evidenced by this bug. IIRC not all the functional Pthreads APIs in the .so are declared.

I recently tried to install ffmpeg on a Core i5 MacBook using Homebrew. On this old but quite beefy machine the build failed after several hours of downloading, make-ing and make check-ing hundreds of dependencies without ever getting near ffmpeg when it decided to include some new codec that is written in Rust and failed to build the Rust compiler. Nightmare.

I don't think the FFMPEG devs response to your code offer was particularly leaden. They have a page with clear guidance on submission of patches.
Last edited:


Thanks for the information, but I am now more confused.

I started with a “clean box” (purchased as “spares or repair”, previously unused 2T pipeline drive fitted, custom firmware from memory stick, not yet loaded with family video archive). I put in the gcc bundle (see attachment opkg_install.log). I examined the log and it looks to me as though it installed correctly. I read the reply from /df. I then checked stuff on the box (see attachment confused.txt). The libmath seems to be present, my shell script contains -lm, the llrint(f) problems are unresolved references, so I appear to be back to my original question.

I know that llrint(f) are not part of the standard libmath for ulibc. ffmpeg.c compiles so that indicates they are in the include files (i.e. not implicitly declared) and I have checked the source for the include. So are they in ? If so which package has the updated libmath ? If not do I have to write my own, is there an existing library with them in ?


  • confused.txt
    7.2 KB · Views: 2
  • opkg_install.log
    1.3 KB · Views: 3
Last edited:


Well-Known Member
The unresolved references will occur if the relevant declarations in math.h (actually in bits/mathcalls.h) haven't been processed: hence the need for appropriate compiler options and/or #defines, but you seem to have those.

The apparently different library versions in /lib are just links: the actual library, its unversioned alias, and its major version alias:
# ls -l /lib/libm*
-rw------- 1 root root 84568 May  8  2009 /lib/
lrwxrwxrwx 1 root root     9 Apr 26  2017 /lib/ ->
lrwxrwxrwx 1 root root    14 Apr 26  2017 /lib/ ->
In fact, like the way you set up the ffmpeg libs.

My reading of man gcc implies that -pthread is not a valid option for MIPS and you only need -lpthread.
I know that llrint(f) are not part of the standard libmath for ulibc. ...
There's the problem. The headers are correct but the ll* functions aren't in the math library itself, and I now recall coming up against that.
# nm -DC /lib/ | grep -E '[^p]rint'
00009a90 T lrint
0000be40 T lrintf
0000a7e0 T rint
0000bf90 T rintf
You may need -mhard-float (see here: the on-box build run-time object has the wrong floating-point, ie soft-float), and/or to supply an additional object file with the necessary routines. If you do need the missing ll* routines, look here.


Thank you for the information I needed. My understanding is that several libraries are non-standard on the box. So I needed to confirm that the bundle had the most up to date package … I did not want to do something about llrint(f) if there was already an on-box solution.

I believe -march=mips32 gives hard float etc on all versions of gcc.

Thanks for the pthread catch. I have done so much work cross compiling with gcc 10.2.* that I forgot to look for early gcc processor differences.


Well-Known Member
Thank you for the information I needed. My understanding is that several libraries are non-standard on the box. So I needed to confirm that the bundle had the most up to date package … I did not want to do something about llrint(f) if there was already an on-box solution.
A library that was never released as version 1 is a good candidate for non-standard-ness. And the Humax devs intercepted the pthreads implementation which hadn't been merged into the release branch at the time. And then the header package and the compiler package don't quite match the Humax build.
I believe -march=mips32 gives hard float etc on all versions of gcc.
That seems to match the manual:
    Use floating-point coprocessor instructions.
    Do not use floating-point coprocessor instructions. Implement floating-point calculations using library calls instead.
    Assume that the floating-point coprocessor only supports single-precision operations.
    Assume that the floating-point coprocessor supports double-precision operations. This is the default.
This is what the advance product information promised for the MIPS4380 core in the BCM7405 SoC:
HardWareModule_7405.pdf said:
• Full MIPS32 architecture compliant
- MIPS32 instruction set architecture (ISA)
- MISP32 privileged resource architecture
- MIPS32 MMU with 32-entry TLB
- Odd/even page translation, variable page sizes from 4 KB to 256 MB
- Fully programmable with a set of CP0 registers and instructions
- Byte ordering of operands in either big or little endian configuration
• MIPS32 extended and optional instructions
- IEEE 754 standard floating-point unit supporting single-precision and double-precision
- MIPS16e application-specific extension
- Multiply-accumulate instructions (MADD, MADDU, MSUB, MSUBU)
- Targeted multiply instruction (MUL)
- Count leading zero and one bit-manipulation instructions (CLZ, CLO)
- Conditional move instructions (MOVZ, MOVN)
- Atomic instructions of load-linked (LL) and store-conditional (SC) enhanced for cache sharing by concurrent threads
- PREF instructions with all the hint options
- Cache instructions and line-based locking
- eDSP instructions in SPECIAL2 for 16-bit DSP computation, dual MAC, two pairs of HI/LO special registers, direct store from Hi/Lo to the memory
• Concurrent multi-threading (CMT)
- Two thread processors (TPs) can simultaneously execute two applications
- Each of the TPs has its own instruction unit, execution unit, register file, MMU, and exception state, but they share the data cache, level-2 cache, and the rest of system resources.
Based on this and the MIPS specification it looks like a plain -march=mips32, possibly with -mllsc if that's not the configured default.


As the documentation is provisional, I took the hacking approach to the processor capabilities (see attachment : attachment is too big if I include the executable and/or object files) and got :-
humax# ./ProcessorInfo
PRid = 0x0002a044
Configuration register = 0x80000083
Configuration register 1 = 0x3ea95587
Warning: Reading optional registers can crash the program !
FIR = 0x00130001
Illegal instruction

I believe we are violently agreeing about the processor capabilities. “And hence the efficacy of -march=mips32 to sort out any compiler configuration settings”, maybe not so much.


    5.8 KB · Views: 3


I have moved on since my last post. The ld-linux approach seems to have legs, i.e. just a loader : does not also work as a standard linked library like does. For a loader based on glibc’s to work it has to contain 2 hard coded paths. I looked for standard linux locations (see attachment QuickLook.txt) from which I believe does not exist anywhere (makes sense as it is only used by glibc’s rtld) and the 2 standard library paths exist. For a loader based on glibc’s rtld to work, it needs 2 hard coded paths in the executable. The first is it’s own installed location. The second in the cache location. For debugging on the QEMU simulator I chose the standard locations i.e. /bin for the loader and /etc for the cache.

I got to the point where it can cope with multiple versions/types of libc on the simulator so decided to have an initial attempt on the box. Attachment putty.txt is “warts and all” in case there is something I did that caused knock on problems. WIMP (Windows, Icons, Mouse and Pointer) interfaces have converged over time so you generally do not have to remember which type of os you are using, however CLIs are still divergent so I apologise for occasionally using commands for the wring type of os. I stopped because I know what happens if you put a space in LD_LIBRARY_PATH.

I encountered read only problems with standard locations and protection problems with execution from /mod/lib. I wish to “play nicely” with the existing stuff so is /mod/usr/bin or /mod/bin a location I can execute a loader from anywhere (i.e. not just when “cd”ed to the folder)? For the future (i.e. if my mixed ulibc/glibc loader works as I expect) where should I hard code the location e.g. /etc or /mod/etc … ?

The segment trap was because I invoked the default loader. I believe this was because my loader was not in an executable location. However this leads to another question. Are my efforts to set a non-default “interpreter” in vain because the default loader is forced by something else in the chain on the box ?


  • putty.txt
    42.6 KB · Views: 3
  • QuickLook.txt
    4 KB · Views: 2

Black Hole

May contain traces of nut
For the future (i.e. if my mixed ulibc/glibc loader works as I expect) where should I hard code the location e.g. /etc or /mod/etc … ?
You should regard anything other than /mod... as inaccessible for write. It will either be read only, or only a temporary file system. On a HDR-FOX the HDD is only used for data and the box "works" without a HDD connected; a HD-FOX has no (internal) HDD at all. The file system (as standard) is (effectively) entirely ROM or RAM.

CF creates /mod on HDD and mounts it into the file system, and can insert stuff into ROM (flash), but free space is severely limited.


Thanks for the information. /mod/usr only contains include on my box, so I am using that, so I know what I have updated. Attachment “Part 1.txt” shows I am back into generic linux debugging again. There is actually a circular logic problem (A depends on B … depends on A) which I enjoy, but requires inspiration, so is not a “quick fix”.

As the quote says “Sometimes when you are up to your arse in alligators, you forget the original intention was to drain the swamp”. I started wanting to create stuff that would “just run” on the Humax. I looked at the standard cross compile stuff and realised that uClibc limits the capabilities to the stuff supported by the kernel. I then read the history of the relationship between glibc and the kernel, and was particularly interested that there was (insecure) user space implementations of functions that were not yet in kernels, or, as support for older kernels back to the minimum version. The glibc documentation gives a reasoned argument for the minimum supported kernel version. It definitely holds true for 64 bit kernels but seemed weak for 32 bit kernels so I produced a static modern (vn 2.32) glibc for the Humax’s kernel version. The shared version has the spectacular random crashes predicted in the glibc documentation because critical user space facilities can be unloaded rather than just swapped out. Time passes and I generate the first version of Migrate. This has a spectacular crash due to running out of swap. People were correctly sceptical because the Humax has the standard linux mechanism for automatically growing swap to meet the current needs. This failed for me because it only gets a “look in” when shared objects are loaded and unloaded and my executable just swaps in and out. My solution for Migrate was to produce a custom 9G swap file that happens when the program first starts. This is only necessary if FFmpeg’s libraries are used to transcode. Re-multiplexing is fine. Every time I update Migrate, I rebuild FFmpeg. It seams churlish not to make it available but, being totally static, has the latent crash. This lead me to explore a dynamic “Frankenstein’s monster” where the main program was native and FFmeg’s libraries were dynamic but built from the stuff I has already compiled for Migrate.

Looking at the bigger picture, Vn4.1 is available natively. This will successfully allow SD recordings (including subtitles) to be re-multiplexed to DVD compliant mpegs as the subtitle problems are only in the to DVB ts direction. Similarly for blu-ray. I therefore believe that me not having a quick solution to building with a uClibc compiler is not a problem.

There are 2 things I can do now.

Firstly I can modify FFmpeg’s main program to look for anything other than the copy codec being requested (i.e. transcoding) and conditionally invoke the 9G swap file.

Secondly I can ‘zip’ the relevant parts of the QEMU debian etch glibc library and put them in /mod/usr/lib and change the rpath etc of the main program I already have working on the QEMU simulator.

Would either of these be of interest to the community ?


  • Part 1.txt
    106.1 KB · Views: 1