How libavif Uses avifResult for Error Handling
This article explains how the libavif library manages
runtime errors and operational statuses using the
avifResult enumeration. You will learn about the role of
this enum in the library’s architecture, discover the most common error
codes returned during AVIF image processing, and see practical examples
of how to translate these codes into human-readable error messages for
robust application development.
The Role of avifResult in libavif
In the libavif library—the standard open-source library
for encoding and decoding AVIF (AV1 Image File Format) files—error
handling is structured around a central enumeration called
avifResult.
Instead of throwing exceptions or relying solely on null pointers,
almost every function in libavif that performs an operation
capable of failing returns an avifResult value. This design
provides a predictable, thread-safe, and low-overhead mechanism for
C-based APIs to communicate success or failure back to the calling
application.
Understanding the Enum Values
The avifResult enum, defined in the core header file
avif/avif.h, contains a variety of status codes. The most
fundamental value is:
AVIF_RESULT_OK(Value: 0): This indicates that the operation completed successfully without any issues.
Any value other than AVIF_RESULT_OK represents a failure
or an unexpected state. These error codes are categorized based on where
the failure occurred in the pipeline:
Container and Parsing Errors
These errors occur when libavif attempts to read the ISO
Base Media File Format (ISOBMFF) container wrapper of an AVIF file: *
AVIF_RESULT_INVALID_FTYP: The file’s brand
or file type box (ftyp) does not match the expected AVIF
requirements. *
AVIF_RESULT_BMFF_PARSE_FAILED: The
internal structure of the BMFF container is malformed or corrupt. *
AVIF_RESULT_TRUNCATED_DATA: The input
buffer contains incomplete data, preventing the parser from reading the
necessary headers.
Codec and Decoding Errors
These codes are returned when the container parses correctly, but the
underlying AV1 video decoder (such as aom, dav1d, or rav1e) fails to
decode the compressed payload: *
AVIF_RESULT_DECODE_COLOR_FAILED: The
decoder was unable to process the primary color payload of the image. *
AVIF_RESULT_DECODE_ALPHA_FAILED: The
decoder failed to process the auxiliary alpha (transparency) channel. *
AVIF_RESULT_NO_CONTENT: The file parsed
correctly, but it contains no decodable image tracks or items.
System and Resource Errors
These represent environmental failures during execution: *
AVIF_RESULT_OUT_OF_MEMORY: The system
could not allocate enough RAM to complete the encoding, decoding, or
parsing process. *
AVIF_RESULT_NOT_IMPLEMENTED: The requested
feature, codec, or bit-depth is not supported by the current build of
libavif.
Implementing Error Handling in C
To handle errors effectively, developers must capture the
avifResult return value and check it against
AVIF_RESULT_OK.
libavif provides a helper function,
avifResultToString(), which converts any
avifResult enum value into a constant, human-readable
string. This is highly useful for logging and debugging.
Here is a standard pattern for error handling when decoding an AVIF image:
#include <stdio.h>
#include "avif/avif.h"
void decode_image(const uint8_t* raw_data, size_t data_size) {
avifDecoder* decoder = avifDecoderCreate();
if (!decoder) {
printf("Failed to allocate decoder.\n");
return;
}
// Attempt to parse the AVIF container
avifResult result = avifDecoderSetIOMemory(decoder, raw_data, data_size);
if (result != AVIF_RESULT_OK) {
printf("IO Memory setup failed: %s\n", avifResultToString(result));
avifDecoderDestroy(decoder);
return;
}
result = avifDecoderParse(decoder);
if (result != AVIF_RESULT_OK) {
// Handle parsing errors (e.g., AVIF_RESULT_BMFF_PARSE_FAILED)
printf("Failed to parse AVIF: %s\n", avifResultToString(result));
avifDecoderDestroy(decoder);
return;
}
// Attempt to decode the image frames
result = avifDecoderNextImage(decoder);
if (result != AVIF_RESULT_OK) {
// Handle decoding errors (e.g., AVIF_RESULT_DECODE_COLOR_FAILED)
printf("Failed to decode AVIF: %s\n", avifResultToString(result));
avifDecoderDestroy(decoder);
return;
}
// Success
printf("Successfully decoded image: %dx%d\n", decoder->image->width, decoder->image->height);
avifDecoderDestroy(decoder);
}By consistently checking the returned avifResult at each
step of the pipeline, developers can isolate whether an image loading
failure was caused by a memory allocation issue, a corrupted file
structure, or an incompatible codec.