stride3d/stride · error · InvalidOperationException

unexpected result from audio decoder.DequeueOutputBuffer

Error message

unexpected result from audio decoder.DequeueOutputBuffer: {0}

What it means

ExtractSomeAudioData throws this when MediaCodec.DequeueOutputBuffer returns an unexpected negative status (not INFO_TRY_AGAIN_LATER, INFO_OUTPUT_FORMAT_CHANGED, or INFO_OUTPUT_BUFFERS_CHANGED). It signals the Android audio decoder entered an unrecognized/failed state, so extraction cannot continue reliably.

Solutions

  1. Verify the media file decodes correctly in another player and is not truncated/corrupt
  2. On this exception, dispose and re-create the MediaCodec and MediaExtractor (full re-initialization) rather than continuing to dequeue
  3. Check the Configure call uses the exact MediaFormat from GetTrackFormat(trackIndexAudio)
  4. Log the raw decoderStatus value; negative codes other than -1/-2/-3 indicate a codec error needing reconfigure
  5. Handle seek carefully: after SeekInternalImpl, flush the codec (Flush()) before resuming dequeue loops

Example fix

// before
default:
    if (decoderStatus < 0)
        throw new InvalidOperationException(string.Format("unexpected result from audio decoder.DequeueOutputBuffer: {0}", decoderStatus));
// after
default:
    if (decoderStatus < 0)
    {
        Logger.Error($"audio decoder error {decoderStatus}; reinitializing extractor");
        ReleaseMediaInternal();
        InitializeMediaExtractor(InputFile.AbsolutePath, 0, 0);
        return;
    }
Defensive patterns

Strategy: retry

Validate before calling

// before streaming, verify the track selects a supported codec
var format = extractor.GetTrackFormat(trackIndexAudio);
var mime = format.GetString(MediaFormat.KeyMime);
if (!MediaCodecList.GetCodecInfos().Any(c => c.GetCodecCapabilities()?.GetSupportedTypes()?.Contains(mime) == true))
    throw new InvalidOperationException($"No decoder available for {mime}");

Try / catch

try
{
    ExtractSomeAudioData();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("DequeueOutputBuffer"))
{
    Logger.Warn($"Decoder error, resetting stream: {ex.Message}");
    ResetDecoder(); // ReleaseMediaInternal + re-init
}

Prevention

When it happens

Trigger: DequeueOutputBuffer returns a negative code such as MediaCodec.InfoReturned(-101) or a codec-specific error while feeding compressed input and draining output during streaming playback of the audio file.

Common situations: Corrupt or truncated media files; unsupported codec profile passed to MediaExtractor (e.g. unusual AAC profiles); decoder released/reconfigured mid-stream (seek racing extraction); device-specific codec bugs on old Android versions.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/4e703c260c6a4931. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Audio/StreamedBufferSoundSource.MediaCodec.cs:162

                case (int)MediaCodecInfoState.OutputFormatChanged:
                    {
                        MediaFormat newFormat = audioMediaDecoder.OutputFormat;
                        string newFormatStr = newFormat.ToString();
                        Logger.Verbose("audio decoder output format changed: " + newFormatStr);
                        break;
                    }

                case (int)MediaCodecInfoState.OutputBuffersChanged:
                    {
                        //deprecated: we just ignore it
                        break;
                    }

                default:
                    {
                        if (decoderStatus < 0)
                            throw new InvalidOperationException(string.Format("unexpected result from audio decoder.DequeueOutputBuffer: {0}", decoderStatus));

                        if ((info.Flags & MediaCodecBufferFlags.EndOfStream) != 0)
                        {
                            Logger.Verbose("audio: output EOS");
                            extractionOutputDone = true;
                        }

                        if (info.Size > 0)
                        {
                            hasExtractedData = true;
                            var buffer = audioMediaDecoder.GetOutputBuffer(decoderStatus);
                            var presentationTime = TimeSpanExtensions.FromMicroSeconds(info.PresentationTimeUs);

                            if (storageBuffer.CountDataBytes + info.Size <= storageBuffer.Data.Length)
                            {
                                buffer.Get(storageBuffer.Data, storageBuffer.CountDataBytes, info.Size); // Read the buffer all at once
                                buffer.Clear(); // MUST DO!!! OTHERWISE THE NEXT TIME YOU GET THIS SAME BUFFER BAD THINGS WILL HAPPEN
                                buffer.Position(0);

View on GitHub (pinned to 96fad776d2)