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

  1. Package the libgav1 native library for every ABI you support (check the APK's lib/<abi>/libgav1.so via Analyze APK)
  2. Add or fix abiFilters / splits so each delivered APK contains a matching .so
  3. Check Gav1Library.isAvailable() before enabling Libgav1VideoRenderer and fall back to platform AV1 decoding or a different renderer
  4. 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

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


AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14). Data as JSON: /api/errors/5e1f753e813bf01a. Report an issue: GitHub.