google/ExoPlayer · critical · Gav1DecoderException
Failed to load decoder native library.
Error message
Failed to load decoder native library.
What it means
Gav1DecoderException thrown by the Gav1Decoder constructor when Gav1Library.isAvailable() is false, meaning the libgav1 JNI native library (.so) could not be loaded. The extension decodes AV1 in software via libgav1, so the native library is mandatory; without it the renderer cannot be constructed at all.
Source
Thrown at extensions/av1/src/main/java/com/google/android/exoplayer2/ext/av1/Gav1Decoder.java:68
private volatile @C.VideoOutputMode int outputMode;
/**
* Creates a Gav1Decoder.
*
* @param numInputBuffers Number of input buffers.
* @param numOutputBuffers Number of output buffers.
* @param initialInputBufferSize The initial size of each input buffer, in bytes.
* @param threads Number of threads libgav1 will use to decode. If {@link
* Libgav1VideoRenderer#THREAD_COUNT_AUTODETECT} is passed, then this class will auto detect
* the number of threads to be used.
* @throws Gav1DecoderException Thrown if an exception occurs when initializing the decoder.
*/
public Gav1Decoder(
int numInputBuffers, int numOutputBuffers, int initialInputBufferSize, int threads)
throws Gav1DecoderException {
super(new DecoderInputBuffer[numInputBuffers], new VideoDecoderOutputBuffer[numOutputBuffers]);
if (!Gav1Library.isAvailable()) {
throw new Gav1DecoderException("Failed to load decoder native library.");
}
if (threads == Libgav1VideoRenderer.THREAD_COUNT_AUTODETECT) {
// Try to get the optimal number of threads from the AV1 heuristic.
threads = gav1GetThreads();
if (threads <= 0) {
// If that is not available, default to the number of available processors.
threads = getRuntime().availableProcessors();
}
}
gav1DecoderContext = gav1Init(threads);
if (gav1DecoderContext == GAV1_ERROR || gav1CheckError(gav1DecoderContext) == GAV1_ERROR) {
throw new Gav1DecoderException(
"Failed to initialize decoder. Error: " + gav1GetErrorMessage(gav1DecoderContext));
}
setInitialInputBufferSize(initialInputBufferSize);
}View on GitHub (pinned to dd430f7053)
Solutions
- Package the libgav1 native library for every ABI you support (check the APK's lib/<abi>/libgav1.so via Analyze APK)
- Add or fix abiFilters / splits so each delivered APK contains a matching .so
- Check Gav1Library.isAvailable() before enabling Libgav1VideoRenderer and fall back to platform AV1 decoding or a different renderer
- If bundling manually, ensure jniLibs.useLegacyPackaging and the extension AAR with native artifacts are both on the classpath
Example fix
// before
Gav1Decoder decoder = new Gav1Decoder(numInputBuffers, numOutputBuffers, initialInputBufferSize, threads);
// after: gate renderer registration on native availability
RenderersFactory factory = new DefaultRenderersFactory(context) {
@Override
protected void buildVideoRenderers(Context ctx, ExtensionRendererMode mode,
ArrayList<Renderer> out) {
if (Gav1Library.isAvailable()) {
out.add(new Libgav1VideoRenderer(...));
}
super.buildVideoRenderers(ctx, mode, out);
}
}; Defensive patterns
Strategy: validation
Validate before calling
if (!Gav1Library.isAvailable()) {
// do not construct Gav1Decoder / Libgav1VideoRenderer;
// rely on platform AV1 decode (MediaCodec) instead
} Try / catch
try {
decoder = new Gav1Decoder(numIn, numOut, initialInputBufferSize, threads);
} catch (Gav1DecoderException e) {
if (e.getMessage() != null && e.getMessage().contains("native library")) {
// packaging problem: check APK lib/<abi>/libgav1.so, then fall back
Log.e(TAG, "libgav1 missing", e);
}
throw e;
} Prevention
- After every release build, verify libgav1.so appears under every ABI you ship (Analyze APK)
- Gate extension renderer registration on XxxLibrary.isAvailable() so absence degrades instead of crashing
- Keep abiFilters and split APK configuration in sync with the packaged native ABIs
When it happens
Trigger: Constructing Gav1Decoder (via Libgav1VideoRenderer on an AV1 stream) in an app that ships the extension Java code but not the native libgav1 .so; missing ABIs (e.g. only arm64-v8a packaged while the device is armeabi-v7a); proguard or packaging options excluding jniLibs.
Common situations: Depending on extension-av1 without building/packaging the native artifacts; using abiFilters that exclude the shipped ABI; running on an emulator image whose ABI is not packaged; split APKs stripping the native lib.
Related errors
- Failed to load decoder native libraries.
- Failed to initialize decoder. Error: ${gav1GetErrorMessage(g
- Buffer render error: ${gav1GetErrorMessage(gav1DecoderContex
- Invalid output mode.
- Failed to render output buffer to surface: decoder is not in
AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14).
Data as JSON: /api/errors/5e1f753e813bf01a.
Report an issue: GitHub.