{"record":{"id":"7d5c20e0ddf5af63","repo":"google/ExoPlayer","slug":"no-suitable-decoder-error","errorCode":"NO_SUITABLE_DECODER_ERROR","errorMessage":"Decoder init failed: [{errorCode}], {format}","messagePattern":"Decoder init failed: \\[(.+?)\\], (.+?)","errorType":"exception","errorClass":"MediaCodecRenderer.DecoderInitializationException","httpStatus":null,"severity":"error","filePath":"library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java","lineNumber":1027,"sourceCode":"            getAvailableCodecInfos(mediaCryptoRequiresSecureDecoder);\n        availableCodecInfos = new ArrayDeque<>();\n        if (enableDecoderFallback) {\n          availableCodecInfos.addAll(allAvailableCodecInfos);\n        } else if (!allAvailableCodecInfos.isEmpty()) {\n          availableCodecInfos.add(allAvailableCodecInfos.get(0));\n        }\n        preferredDecoderInitializationException = null;\n      } catch (DecoderQueryException e) {\n        throw new DecoderInitializationException(\n            inputFormat,\n            e,\n            mediaCryptoRequiresSecureDecoder,\n            DecoderInitializationException.DECODER_QUERY_ERROR);\n      }\n    }\n\n    if (availableCodecInfos.isEmpty()) {\n      throw new DecoderInitializationException(\n          inputFormat,\n          /* cause= */ null,\n          mediaCryptoRequiresSecureDecoder,\n          DecoderInitializationException.NO_SUITABLE_DECODER_ERROR);\n    }\n\n    MediaCodecInfo preferredCodecInfo = availableCodecInfos.peekFirst();\n    while (codec == null) {\n      MediaCodecInfo codecInfo = availableCodecInfos.peekFirst();\n      if (!shouldInitCodec(codecInfo)) {\n        return;\n      }\n      try {\n        try {\n          initCodec(codecInfo, crypto);\n        } catch (Exception e) {\n          if (codecInfo == preferredCodecInfo) {\n            // If creating the preferred decoder failed then sleep briefly before retrying.","sourceCodeStart":1009,"sourceCodeEnd":1045,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java#L1009-L1045","documentation":"After the codec query succeeds, MediaCodecRenderer checks the deque of candidate MediaCodecInfos; if it is empty, no installed decoder matches the input format (considering the secure-decoder requirement when DRM needs secure decoding), and it throws DecoderInitializationException with NO_SUITABLE_DECODER_ERROR. Unlike DECODER_QUERY_ERROR, the codec database was queried fine — the device simply has no decoder for the format/profile.","triggerScenarios":"Stream codec/profile not supported by the hardware: HEVC on devices without an HEVC decoder, AV1 on pre-Android-10/pre-AV1 devices, H.264 High-10 profile, Dolby Vision, DTS:X etc.; or mediaCryptoRequiresSecureDecoder=true (DRM L1 HD content) and the only matching decoder is insecure, filtering the deque to empty.","commonSituations":"Single-rendition streams assuming universal codec support; HLS/DASH packaging without per-device variant selection; secure-path DRM content on devices that only offer insecure decoders for that codec; emulators lacking hardware codecs; 10-bit HDR profiles on older chipsets.","solutions":["Offer multiple renditions/variants (H.264 baseline/main fallback alongside HEVC/AV1) and let ABR + track selection pick a supported codec per device.","Before playback, query support with MediaCodecUtil.getCodecInfos / MediaCapability and skip or replace unsupported tracks (e.g. prefer an audio-only or lower-profile variant).","For niche codecs, ship the FFmpeg extension (software video/audio renderers) so decoding is not dependent on OEM hardware.","For DRM secure-decoder failures, check MediaCodecInfo.hardwareAccelerated/secure playback support per codec and consider L3 streams for devices lacking a secure decoder for that MIME type."],"exampleFix":"// before\nTrackSelectionParameters params = player.getTrackSelectionParameters(); // defaults: unsupported video may still be selected first try\n\n// after\nTrackSelectionParameters params = player.getTrackSelectionParameters()\n    .buildUpon()\n    .setVideoResolutionCeilingForSizeConstrained(1920)\n    // prefer codecs known broadly supported when packaging offers them\n    .setOverrideForType(new TrackSelectionOverride(\n        new TrackGroupInfo..., /* H.264 track index */ 0))\n    .build();\nplayer.setTrackSelectionParameters(params);","handlingStrategy":"validation","validationCode":"// Before playback, check the device can decode the primary codec:\nMimeTypes primary = MimeTypes.VIDEO_H265;\nboolean hevcSupported = false;\ntry {\n  for (MediaCodecInfo info : MediaCodecUtil.getCodecInfos()) {\n    if (info.isDecoder() && info.supportedMimeTypes.contains(primary)\n        && info.getCapabilitiesForType(primary).isFormatSupported(format)) {\n      hevcSupported = true;\n      break;\n    }\n  }\n} catch (DecoderQueryException e) {\n  hevcSupported = false;\n}\nif (!hevcSupported) {\n  // select H.264 variant / lower profile instead of failing with NO_SUITABLE_DECODER\n}","typeGuard":null,"tryCatchPattern":"@Override\npublic void onPlayerError(PlaybackException error) {\n  if (error.getCause() instanceof DecoderInitializationException\n      && ((DecoderInitializationException) error.getCause()).getDecoderName() == null) {\n    DecoderInitializationException die = (DecoderInitializationException) error.getCause();\n    if (die.getCause() == null /* no cause -> no suitable decoder */) {\n      // codec unsupported: switch to fallback rendition (H.264) or audio-only\n    }\n  }\n}","preventionTips":["Package at least one universally decodable variant (H.264 main profile, AAC-LC) per stream.","Use TrackSelectionParameters and track-selection overrides informed by device codec checks, so unsupported tracks are never selected.","Ship the FFmpeg extension when supporting niche codecs (10-bit HEVC, AV1, DTS) on heterogeneous devices.","For DRM content, verify a secure decoder exists for the codec+level (MediaDrm security level + codec secure support) before offering L1-only streams."],"tags":["exoplayer","android","media-codec","decoder","codec-support","playback"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}