Skip to content

Repository files navigation

libavif-ffm

Panama FFM bindings for libavif with bundled, from-source native libraries. One Maven coordinate gives Java 22+ direct access to the complete public libavif 1.4.2 C API, without JNI or a system libavif installation.

Artifact Contents License
io.github.ghosthack:libavif-ffm jextract-generated Java stubs and runtime loader MIT
io.github.ghosthack:libavif-ffm-natives platform shared library with statically linked codecs BSD licenses; see THIRD-PARTY.md

Supported classifiers are macos-arm64, windows-x64, and linux-x64. The native build uses dav1d 1.5.3 for decoding, libaom 3.14.1 for encoding, and libyuv for accelerated RGB/YUV conversion. libavif's automatic decoder selection prefers dav1d.

Use

<dependency>
  <groupId>io.github.ghosthack</groupId>
  <artifactId>libavif-ffm</artifactId>
  <version>1.4.2-0.1.0</version>
</dependency>
<dependency>
  <groupId>io.github.ghosthack</groupId>
  <artifactId>libavif-ffm-natives</artifactId>
  <version>1.4.2-0.1.0</version>
  <classifier>macos-arm64</classifier> <!-- windows-x64 or linux-x64 -->
  <scope>runtime</scope>
</dependency>

On the module path, declare requires libavif.ffm; and run with --enable-native-access=libavif.ffm. On the class path, use --enable-native-access=ALL-UNNAMED.

import io.github.ghosthack.libavifffm.libavif.LibAvif;

String version = LibAvif.avifVersion().getString(0);
String decoder = LibAvif.avifCodecName(
        LibAvif.AVIF_CODEC_CHOICE_AUTO(),
        LibAvif.AVIF_CODEC_FLAG_CAN_DECODE()).getString(0); // dav1d

The API intentionally mirrors C: pointers are MemorySegment, structs have generated layout/accessor classes such as avifImage, avifDecoder, and avifRGBImage, and callers own native lifetimes. See core/src/test/java/io/github/ghosthack/libavifffm/LibAvifSmokeTest.java for a complete RGBA → AVIF → RGBA encode/decode round trip with correct cleanup.

Native resolution

The generated stubs resolve symbols lazily in this order:

  1. -Dlibavifffm.libdir=<dir> or LIBAVIF_FFM_LIBDIR;
  2. the matching natives classifier jar, extracted once under ~/.cache/libavif-ffm/<version>-<platform>/;
  3. libraries already loaded by the host process and the platform's default symbol lookup.

The override is useful for testing a compatible system build or substituting custom codec options.

Build

Each native classifier must be built on its target OS. Start from the tagged libavif source:

mkdir -p build
curl -sfL https://github.com/AOMediaCodec/libavif/archive/refs/tags/v1.4.2.tar.gz | tar xz -C build
build-natives/macos-arm64.sh
jextract/gen-bindings.sh
mvn install

gen-bindings.sh uses jextract 22 from ../ffmpeg-ffm by default; set JEXTRACT=/path/to/jextract to override it. Stub generation is performed once on macOS because libavif's public C layouts are portable across the supported 64-bit targets.

The Linux script needs CMake, GCC/G++, Git, Meson, Ninja, NASM, Perl, and patchelf. The Windows script documents its MSYS2 MINGW64 prerequisites in its header. Every script rejects unexpected dynamic dependencies and stages licenses plus reproducible build metadata beside the library.

Generated array accessors

jextract 22's indexed accessor for an array field can address relative to the start of a struct rather than the array field. Prefer a field slice, for example:

MemorySegment planes = avifImage.yuvPlanes(image);
MemorySegment yPlane = planes.getAtIndex(ValueLayout.ADDRESS, 0);

instead of the generated indexed convenience overload.

About

Panama FFM bindings for libavif with bundled dav1d/libaom natives

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages