DrKLO/Telegram · critical · FfmpegDecoderException

Failed to load decoder native libraries.

Error message

Failed to load decoder native libraries.

What it means

FfmpegAudioDecoder's constructor throws FfmpegDecoderException('Failed to load decoder native libraries.') when FfmpegLibrary.isAvailable() is false — meaning the FFmpeg native (.so) libraries were not packaged or could not be loaded by the app. This is a hard precondition: without the native libs the decoder cannot run, so it fails before any codec initialization.

Source

Thrown at TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioDecoder.java:61

  @Nullable private final byte[] extraData;
  private final @C.PcmEncoding int encoding;
  private final int outputBufferSize;

  private long nativeContext; // May be reassigned on resetting the codec.
  private boolean hasOutputFormat;
  private volatile int channelCount;
  private volatile int sampleRate;

  public FfmpegAudioDecoder(
      Format format,
      int numInputBuffers,
      int numOutputBuffers,
      int initialInputBufferSize,
      boolean outputFloat)
      throws FfmpegDecoderException {
    super(new DecoderInputBuffer[numInputBuffers], new SimpleDecoderOutputBuffer[numOutputBuffers]);
    if (!FfmpegLibrary.isAvailable()) {
      throw new FfmpegDecoderException("Failed to load decoder native libraries.");
    }
    Assertions.checkNotNull(format.sampleMimeType);
    codecName = Assertions.checkNotNull(FfmpegLibrary.getCodecName(format.sampleMimeType));
    extraData = getExtraData(format.sampleMimeType, format.initializationData);
    encoding = outputFloat ? C.ENCODING_PCM_FLOAT : C.ENCODING_PCM_16BIT;
    outputBufferSize = outputFloat ? OUTPUT_BUFFER_SIZE_32BIT : OUTPUT_BUFFER_SIZE_16BIT;
    nativeContext =
        ffmpegInitialize(codecName, extraData, outputFloat, format.sampleRate, format.channelCount);
    if (nativeContext == 0) {
      throw new FfmpegDecoderException("Initialization failed.");
    }
    setInitialInputBufferSize(initialInputBufferSize);
  }

  @Override
  public String getName() {
    return "ffmpeg" + FfmpegLibrary.getVersion() + "-" + codecName;
  }

View on GitHub (pinned to 45ab8f4308)

Solutions

  1. Package the FFmpeg native libraries for all target ABIs (build the FFmpeg extension and include its .so outputs in jniLibs).
  2. Verify FfmpegLibrary.isAvailable() before enabling FFmpeg-backed playback; fall back to a platform decoder otherwise.
  3. Check abiFilters includes the device's ABI and that packaging did not exclude the libs.

Example fix

// before
if (FfmpegLibrary.isAvailable()) { /* never reached */ }

// after
android {
  defaultConfig { ndk { abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64' } }
}
Defensive patterns

Strategy: validation

Validate before calling

// guard on library availability before enabling FFmpeg renderer
if (FfmpegLibrary.isAvailable()) {
  renderers.add(new FfmpegAudioRenderer(...));
} else { /* rely on platform decoders */ }

Try / catch

try { new FfmpegAudioDecoder(format, nIn, nOut, bufSize, outputFloat); }
catch (FfmpegDecoderException e) { /* fall back to MediaCodec */ }

Prevention

When it happens

Trigger: Constructing FfmpegAudioDecoder (typically via DefaultRenderersFactory with extension extension enabled) on an APK that does not include the FFmpeg native libraries for the current ABI.

Common situations: The FFmpeg extension AAR/.so files are absent from the build; the device's ABI is not among the packaged ABIs (abiFilters); ProGuard/R8 stripping JNI symbols; shipping a release APK without the FFmpeg JNI native libs.

Related errors


AI-assisted analysis of DrKLO/Telegram@45ab8f4308 (2026-08-14). Data as JSON: /api/errors/4c4125a56355acfb. Report an issue: GitHub.