{"record":{"id":"ab21b0cc472db4db","repo":"google/ExoPlayer","slug":"failed-to-initialize-decoder-ab21b0","errorCode":null,"errorMessage":"Failed to initialize decoder","messagePattern":"Failed to initialize decoder","errorType":"exception","errorClass":"OpusDecoderException","httpStatus":null,"severity":"error","filePath":"extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoder.java","lineNumber":145,"sourceCode":"        throw new OpusDecoderException(\"Invalid header, missing stream map\");\n      }\n      numStreams = 1;\n      numCoupled = (channelCount == 2) ? 1 : 0;\n      streamMap[0] = 0;\n      streamMap[1] = 1;\n    } else {\n      if (headerBytes.length < 21 + channelCount) {\n        throw new OpusDecoderException(\"Invalid header length\");\n      }\n      // Read the channel mapping.\n      numStreams = headerBytes[19] & 0xFF;\n      numCoupled = headerBytes[20] & 0xFF;\n      System.arraycopy(headerBytes, 21, streamMap, 0, channelCount);\n    }\n    nativeDecoderContext =\n        opusInit(SAMPLE_RATE, channelCount, numStreams, numCoupled, gain, streamMap);\n    if (nativeDecoderContext == 0) {\n      throw new OpusDecoderException(\"Failed to initialize decoder\");\n    }\n    setInitialInputBufferSize(initialInputBufferSize);\n\n    this.outputFloat = outputFloat;\n    if (outputFloat) {\n      opusSetFloatOutput();\n    }\n  }\n\n  /**\n   * Sets whether discard padding is enabled. When enabled, discard padding samples (provided as\n   * supplemental data on the input buffer) will be removed from the end of the decoder output.\n   *\n   * <p>This method is experimental, and will be renamed or removed in a future release.\n   */\n  public void experimentalSetDiscardPaddingEnabled(boolean enabled) {\n    this.experimentalDiscardPaddingEnabled = enabled;\n  }","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoder.java#L127-L163","documentation":"The native opusInit(...) call returned 0 (a null context), so the JNI multistream decoder could not be created from the supplied channel count, stream count, coupled count, gain and stream map. It means the header passed structural validation but libopus rejected the configuration (e.g. numStreams/numCoupled inconsistent with channelCount, or the native library failed internally).","triggerScenarios":"opusInit(SAMPLE_RATE, channelCount, numStreams, numCoupled, gain, streamMap) == 0. Typical when the header's numStreams (byte 19) and numCoupled (byte 20) do not satisfy channelCount <= numStreams + numCoupled*2, or when the bundled libopus JNI wrapper is built without multistream support.","commonSituations":"Malformed family-1 headers where the stream counts contradict the channel count; device-specific native library issues in custom builds of the Opus extension; headers where gain is corrupt is tolerated, so almost always the stream-count mismatch.","solutions":["Validate header consistency before playback: channelCount <= numStreams + 2*numCoupled and numStreams >= 1.","Re-encode the audio with a known-good encoder (ffmpeg opus / libopus) so mapping metadata is coherent.","If building the extension from source, confirm the JNI opusInit wrapper and linked libopus support multistream (OPUS_MULTISTREAM).","Fall back to MediaCodec ('audio/opus' hardware/passthrough) by excluding the extension renderer."],"exampleFix":"// before\n// multichannel family-1 header with channels=6, numStreams=1, numCoupled=0 -> opusInit fails\n\n// after\nint channels = h[9] & 0xFF, ns = h[19] & 0xFF, nc = h[20] & 0xFF;\nif (channels > ns + 2 * nc) {\n  // header is inconsistent; deselect the track or fail with a clear message\n  throw new IOException(\"Opus stream counts do not cover channel count\");\n}","handlingStrategy":"fallback","validationCode":"int channels = h[9] & 0xFF, ns = h[19] & 0xFF, nc = h[20] & 0xFF;\nboolean consistent = ns >= 1 && channels <= ns + 2 * nc;\nif (!consistent) { /* deselect opus extension track */ }","typeGuard":null,"tryCatchPattern":"try { renderer.init(...); } catch (OpusDecoderException e) { /* fall back to MediaCodec audio/opus decoder or skip track */ }","preventionTips":["Check numStreams/numCoupled cover the channel count before playback.","Keep a MediaCodec fallback renderer for audio/opus.","Build the extension's native code with multistream support if you need >2 channels."],"tags":["opus","native","decoder-init","multistream","exoplayer-extension"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}