FMA has two parts and they must run on opposite sides of the PRoot boundary:
flowchart LR
A["Termux host<br/>Android fake-media-acceld"] -->|"Unix socket + file descriptors"| B["PRoot distro<br/>FMA VA-API driver"]
B --> C["FFmpeg, VLC or another VA-API client"]
The Android daemon must run in Termux, where it can use MediaCodec. The VA-API driver and Linux media application run inside the distro. Do not start the daemon from the PRoot shell.
This is currently a development install. There is no FMA Termux package or prebuilt release yet.
On a computer with the Android SDK, NDK, CMake and ADB installed:
git clone https://github.com/RandomCoderOrg/fake-media-accel.git
cd fake-media-accel
cmake -S . -B build-android \
-DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-26 \
-DCMAKE_BUILD_TYPE=Release
cmake --build build-android --parallel --target fake-media-acceld
adb push build-android/fake-media-acceld \
/sdcard/Download/fake-media-acceldUse the ABI reported by getprop ro.product.cpu.abi if the device is not
ARM64. The repository CI also builds armeabi-v7a and x86_64.
In Termux, grant storage access once and install the daemon:
pkg install coreutils
termux-setup-storage
install -m 755 "$HOME/storage/downloads/fake-media-acceld" \
"$PREFIX/bin/fake-media-acceld"Use a pathname socket in Termux's temporary directory. Both setup routes below
map that directory to /tmp inside the distro.
mkdir -p "$PREFIX/var/log" "$PREFIX/var/run"
rm -f "$TMPDIR/fake-media-accel.sock"
nohup fake-media-acceld "$TMPDIR/fake-media-accel.sock" \
>"$PREFIX/var/log/fake-media-acceld.log" 2>&1 &
echo $! >"$PREFIX/var/run/fake-media-acceld.pid"Confirm that it started:
cat "$PREFIX/var/log/fake-media-acceld.log"The expected line is:
fake-media-acceld listening on /data/data/com.termux/files/usr/tmp/fake-media-accel.sock
FMA itself does not require a display. The vainfo and graphical application
checks later in this guide use an X11 VA display, so start Termux:X11 when those
checks are needed:
termux-x11 :0 >"$PREFIX/var/log/termux-x11.log" 2>&1 &To stop it later:
kill "$(cat "$PREFIX/var/run/fake-media-acceld.pid")"
rm -f "$TMPDIR/fake-media-accel.sock"Install a distro if needed:
pkg install proot-distro
proot-distro install ubuntuThe shared temporary directory is required for the FMA socket and a graphical
session. If /dev/dma_heap/system is readable in Termux, bind the DMA heaps as
well:
proot-distro login ubuntu --shared-tmp --bind /dev/dma_heap:/dev/dma_heapIf the DMA heap does not exist or Termux cannot read it, omit the bind:
proot-distro login ubuntu --shared-tmpThe driver will then use its CPU-mappable fallback. Decode still works, but VA surface export to EGL or another DRM PRIME consumer will not.
Use the installed suite name shown by udroid --list, for example:
udroid login jammy:rawThe uDroid Bash CLI shares Termux's temporary directory and binds /dev by
default. Do not use --no-shared-tmp or --isolated for an FMA session. Check
the two resources after login:
test -S /tmp/fake-media-accel.sock && echo "FMA socket is visible"
test -r /dev/dma_heap/system && echo "DMA heap is usable"If the second check fails, the driver automatically falls back to ordinary CPU-mappable surfaces.
These commands are for Ubuntu or Debian:
apt update
apt install -y build-essential cmake pkg-config git \
libva-dev libva-x11-2 libdrm-dev vainfo ffmpeg
mkdir -p "$HOME/src"
git clone https://github.com/RandomCoderOrg/fake-media-accel.git \
"$HOME/src/fake-media-accel"
cd "$HOME/src/fake-media-accel"
cmake -S . -B build-proot \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="$HOME/.local" \
-DCMAKE_INSTALL_LIBDIR=lib
cmake --build build-proot --parallel --target fma-va-driver fma-info
cmake --install build-prootPackage equivalents for other common guests:
# Arch Linux
pacman -S --needed base-devel cmake pkgconf git libva libdrm libva-utils ffmpeg
# Alpine Linux
apk add build-base cmake pkgconf git libva-dev libdrm-dev libva-utils ffmpegThen build with the same CMake commands.
Set the X display used by Termux:X11. Change :0 if the server uses another
display number.
export DISPLAY=:0
export FMA_SOCKET=/tmp/fake-media-accel.sock
export LIBVA_DRIVER_NAME=fma
export LIBVA_DRIVERS_PATH="$HOME/.local/lib/dri"First test the cross-PRoot connection without libva:
"$HOME/src/fake-media-accel/build-proot/fma-info" "$FMA_SOCKET"It should print the protocol version and the codecs reported by Android. Then check that libva loads the FMA driver:
vainfo --display x11The current VA-API adapter intentionally exposes only H.264 VLD. The Android
daemon may report additional MediaCodec decoders through fma-info, but that
does not mean the VA-API frontend implements them yet.
For a correctness check against FFmpeg's software decoder, use a local H.264 video:
cd "$HOME/src/fake-media-accel"
tools/fma-va-verify.sh /path/to/h264-video.mp4Success ends with decoded output matches. A normal application can then be
launched with the same environment. For example, after installing VLC:
apt install -y vlc
vlc --avcodec-hw=vaapi /path/to/h264-video.mp4After verification, put the four environment exports in the desktop session's startup file so applications inherit them.
connect: No such file or directory: the daemon is not running or the distro was entered without a shared Termux/tmp.vainfocannot open the display: start Termux:X11 and use its actualDISPLAYnumber.vaInitialize failed: checkLIBVA_DRIVER_NAME,LIBVA_DRIVERS_PATHand confirm that the directory containsfma_drv_video.so.- No
/dev/dma_heap/system: decoding can use the fallback. SetFMA_VA_DMA_HEAP=noneexplicitly when testing that route. - The daemon disappears after Termux is backgrounded: exempt Termux from Android battery optimization or keep the Termux session in the foreground.
- For short protocol traces, set
FMA_VA_DEBUG=1. Do not leave it enabled for normal playback.
Related projects: proot-distro, Termux:X11 and the uDroid Bash CLI.