{"record":{"id":"70041db2f47f959d","repo":"google/ExoPlayer","slug":"failed-to-initialize-decoder-error-gav1geterro","errorCode":null,"errorMessage":"Failed to initialize decoder. Error: ${gav1GetErrorMessage(gav1DecoderContext)}","messagePattern":"Failed to initialize decoder\\. Error: (.+?)","errorType":"exception","errorClass":"Gav1DecoderException","httpStatus":null,"severity":"critical","filePath":"extensions/av1/src/main/java/com/google/android/exoplayer2/ext/av1/Gav1Decoder.java","lineNumber":82,"sourceCode":"      int numInputBuffers, int numOutputBuffers, int initialInputBufferSize, int threads)\n      throws Gav1DecoderException {\n    super(new DecoderInputBuffer[numInputBuffers], new VideoDecoderOutputBuffer[numOutputBuffers]);\n    if (!Gav1Library.isAvailable()) {\n      throw new Gav1DecoderException(\"Failed to load decoder native library.\");\n    }\n\n    if (threads == Libgav1VideoRenderer.THREAD_COUNT_AUTODETECT) {\n      // Try to get the optimal number of threads from the AV1 heuristic.\n      threads = gav1GetThreads();\n      if (threads <= 0) {\n        // If that is not available, default to the number of available processors.\n        threads = getRuntime().availableProcessors();\n      }\n    }\n\n    gav1DecoderContext = gav1Init(threads);\n    if (gav1DecoderContext == GAV1_ERROR || gav1CheckError(gav1DecoderContext) == GAV1_ERROR) {\n      throw new Gav1DecoderException(\n          \"Failed to initialize decoder. Error: \" + gav1GetErrorMessage(gav1DecoderContext));\n    }\n    setInitialInputBufferSize(initialInputBufferSize);\n  }\n\n  @Override\n  public String getName() {\n    return \"libgav1\";\n  }\n\n  @Override\n  protected DecoderInputBuffer createInputBuffer() {\n    return new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT);\n  }\n\n  @Override\n  protected VideoDecoderOutputBuffer createOutputBuffer() {\n    return new VideoDecoderOutputBuffer(this::releaseOutputBuffer);","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/extensions/av1/src/main/java/com/google/android/exoplayer2/ext/av1/Gav1Decoder.java#L64-L100","documentation":"Gav1DecoderException thrown when gav1Init(threads) returns GAV1_ERROR (or the context is flagged as errored immediately after init), meaning native libgav1 failed to create a decoder context. The message includes gav1GetErrorMessage() output from native code describing the concrete failure.","triggerScenarios":"Constructing Gav1Decoder with a resolved thread count <= 0 or absurdly large when THREAD_COUNT_AUTODETECT path produced a bad value; native memory exhaustion when allocating the decoder context; corrupted or mismatched libgav1 build versus the Java bindings.","commonSituations":"Low-memory devices where the native allocation fails; custom libgav1 builds with an incompatible JNI surface; passing an explicit negative thread count.","solutions":["Read the appended gav1GetErrorMessage text — it names the native failure (allocation vs invalid argument)","Pass a sane positive thread count (or THREAD_COUNT_AUTODETECT) instead of a computed value that could be <= 0","Catch Gav1DecoderException around renderer construction and fall back to platform AV1 decoding (MediaCodec) when available","Free memory / reduce concurrent decoders if the native allocation fails under pressure"],"exampleFix":"// before\nint threads = Libgav1VideoRenderer.THREAD_COUNT_AUTODETECT;\nGav1Decoder decoder = new Gav1Decoder(numIn, numOut, initialInputBufferSize, threads);\n\n// after: clamp explicit thread counts and fall back on failure\nint threads = Math.max(1, requestedThreads);\ntry {\n  decoder = new Gav1Decoder(numIn, numOut, initialInputBufferSize, threads);\n} catch (Gav1DecoderException e) {\n  Log.e(TAG, \"libgav1 init failed: \" + e.getMessage(), e);\n  decoder = null; // let the pipeline pick the platform AV1 decoder\n}","handlingStrategy":"try-catch","validationCode":"int threads = requestedThreads;\nif (threads == Libgav1VideoRenderer.THREAD_COUNT_AUTODETECT) {\n  threads = Math.max(1, Runtime.getRuntime().availableProcessors());\n}\n// gav1Init cannot fail on an invalid thread count if threads >= 1 is guaranteed","typeGuard":null,"tryCatchPattern":"try {\n  Gav1Decoder decoder = new Gav1Decoder(numIn, numOut, initialInputBufferSize, threads);\n} catch (Gav1DecoderException e) {\n  String msg = e.getMessage(); // contains gav1GetErrorMessage() detail\n  Log.e(TAG, \"libgav1 init failed: \" + msg, e);\n  // fall back to platform AV1 renderer by not adding Libgav1VideoRenderer\n}","preventionTips":["Always clamp thread counts to >= 1 before constructing the decoder","Log the appended native message — it distinguishes allocation failure from bad arguments","Keep a platform-decoder fallback path when software AV1 init fails"],"tags":["android","av1","native-library","decoder-initialization"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}