{"record":{"id":"9f7a682e978361cd","repo":"google/ExoPlayer","slug":"failed-to-load-decoder-native-libraries","errorCode":null,"errorMessage":"Failed to load decoder native libraries.","messagePattern":"Failed to load decoder native libraries\\.","errorType":"exception","errorClass":"FfmpegDecoderException","httpStatus":null,"severity":"critical","filePath":"extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioDecoder.java","lineNumber":69,"sourceCode":"  @Nullable private final byte[] extraData;\n  private final @C.PcmEncoding int encoding;\n  private final int outputBufferSize;\n\n  private long nativeContext; // May be reassigned on resetting the codec.\n  private boolean hasOutputFormat;\n  private volatile int channelCount;\n  private volatile int sampleRate;\n\n  public FfmpegAudioDecoder(\n      Format format,\n      int numInputBuffers,\n      int numOutputBuffers,\n      int initialInputBufferSize,\n      boolean outputFloat)\n      throws FfmpegDecoderException {\n    super(new DecoderInputBuffer[numInputBuffers], new SimpleDecoderOutputBuffer[numOutputBuffers]);\n    if (!FfmpegLibrary.isAvailable()) {\n      throw new FfmpegDecoderException(\"Failed to load decoder native libraries.\");\n    }\n    Assertions.checkNotNull(format.sampleMimeType);\n    codecName = Assertions.checkNotNull(FfmpegLibrary.getCodecName(format.sampleMimeType));\n    extraData = getExtraData(format.sampleMimeType, format.initializationData);\n    encoding = outputFloat ? C.ENCODING_PCM_FLOAT : C.ENCODING_PCM_16BIT;\n    outputBufferSize = outputFloat ? OUTPUT_BUFFER_SIZE_32BIT : OUTPUT_BUFFER_SIZE_16BIT;\n    nativeContext =\n        ffmpegInitialize(codecName, extraData, outputFloat, format.sampleRate, format.channelCount);\n    if (nativeContext == 0) {\n      throw new FfmpegDecoderException(\"Initialization failed.\");\n    }\n    setInitialInputBufferSize(initialInputBufferSize);\n  }\n\n  @Override\n  public String getName() {\n    return \"ffmpeg\" + FfmpegLibrary.getVersion() + \"-\" + codecName;\n  }","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioDecoder.java#L51-L87","documentation":"FfmpegDecoderException thrown by the FfmpegAudioDecoder constructor when FfmpegLibrary.isAvailable() is false — the FFmpeg JNI native libraries were not loaded. Unlike the AAR-published extensions, the FFmpeg extension requires you to build and package libffmpeg JNI .so files yourself, so this error means the native side is missing at runtime.","triggerScenarios":"Enabling FfmpegAudioRenderer in an app whose APK contains no lib/<abi>/libffmpegJNI.so; shipping the Java dependency only (compileOnly-style usage); building FFmpeg for a subset of ABIs and running on an excluded device; proguard/packaging stripping the .so.","commonSituations":"Adding the ffmpeg extension source without running its native build; abiFilters mismatch; using a third-party maven artifact of the extension that ships no natives; 16KB-page devices rejecting an old-style .so alignment.","solutions":["Build the FFmpeg extension natives (scripts in extensions/ffmpeg) and package libffmpegJNI.so for every target ABI; verify with Analyze APK","Check FfmpegLibrary.isAvailable() before registering FfmpegAudioRenderer and fall back to platform MediaCodec decoding","Fix abiFilters/splits so the delivered APK matches device ABIs; rebuild .so with 16KB alignment for Android 15+ targets","Verify FfmpegLibrary.supportsFormat(sampleMimeType) too, since the codec list depends on how FFmpeg was configured at build time"],"exampleFix":"// before\nout.add(new FfmpegAudioRenderer(...)); // crashes when natives are absent\n\n// after\nif (FfmpegLibrary.isAvailable()) {\n  out.add(new FfmpegAudioRenderer(...));\n} else {\n  Log.w(TAG, \"FFmpeg natives missing; using platform decoders\");\n}\nsuper.buildAudioRenderers(context, extensionRendererMode, ...); // platform fallback","handlingStrategy":"validation","validationCode":"if (FfmpegLibrary.isAvailable()) {\n  // safe to construct FfmpegAudioDecoder / register FfmpegAudioRenderer\n} else {\n  // libffmpegJNI.so not packaged: use platform MediaCodec rendering only\n}","typeGuard":null,"tryCatchPattern":"try {\n  decoder = new FfmpegAudioDecoder(format, numIn, numOut, initialSize, outputFloat);\n} catch (FfmpegDecoderException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"native libraries\")) {\n    // packaging problem: verify lib/<abi>/libffmpegJNI.so, then fall back\n    Log.e(TAG, \"FFmpeg natives missing\", e);\n  }\n  throw e;\n}","preventionTips":["Build and package the FFmpeg extension natives for every shipped ABI; verify in the APK artifact","Gate FFmpeg renderer registration on FfmpegLibrary.isAvailable() and keep MediaCodec as fallback","Rebuild natives when targeting Android 15+ (16KB page alignment) or new ABIs"],"tags":["android","ffmpeg","native-library","decoder","extension"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}