How libavif Manages Multiple Encoder and Decoder Backends

The open-source libavif library serves as a portable middleware layer that allows applications to encode and decode AVIF images using various underlying AV1 codecs. This article explains how libavif abstracts different encoder and decoder backends—such as aom, dav1d, rav1e, and SVT-AV1—managing them simultaneously through compile-time configuration, a unified internal API, and dynamic runtime selection.

The Unified Codec Abstraction Layer

At the core of libavif’s multi-backend capability is its abstraction layer, defined in its internal source code (specifically within the codec interface headers). Rather than forcing application developers to write custom code for each AV1 library, libavif defines a generic interface structure (often referred to as avifCodec).

Every supported backend has a corresponding wrapper file (e.g., codec_aom.c, codec_dav1d.c, codec_svt.c) that implements this generic interface. These wrappers translate libavif’s standardized commands for configuration, image feeding, and compressed payload extraction into the specific API calls required by the underlying third-party library.

Compile-Time Selection and Configuration

libavif determines which backends are available at compile time using CMake build flags. Developers can enable or disable specific encoders and decoders depending on their platform requirements, licensing constraints, or performance needs.

Common build flags include: * AVIF_CODEC_AOM: Enables the Alliance for Open Media Reference Encoder/Decoder (supports both encoding and decoding). * AVIF_CODEC_DAV1D: Enables the highly optimized dav1d decoder (decoding only). * AVIF_CODEC_SVT: Enables the SVT-AV1 encoder (encoding only). * AVIF_CODEC_RAV1E: Enables the Rust-based rav1e encoder (encoding only).

When these flags are toggled, the CMake build system compiles only the enabled wrappers and links the corresponding external libraries into the final libavif binary.

Runtime Selection and Priority Queue

If a binary is compiled with multiple backends enabled simultaneously (for example, having both aom and dav1d available for decoding), libavif manages them using an internal priority list and developer-controlled settings.

Automatic Choice (Default)

By default, libavif uses an internal preference order optimized for performance. For decoding, it will prioritize dav1d over aom because dav1d is generally faster and more resource-efficient. For encoding, it will choose the first available encoder in its default list (usually preferring aom or SVT-AV1).

Explicit API Selection

Developers can override the automatic selection at runtime. The avifEncoder and avifDecoder structures feature a codecChoice member variable. By setting this variable, developers can explicitly force the library to use a specific backend:

If the requested codec is not compiled into the binary, libavif will return an initialization error, allowing the application to gracefully fall back to another choice.