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
- Verify the media file decodes correctly in another player and is not truncated/corrupt
- On this exception, dispose and re-create the MediaCodec and MediaExtractor (full re-initialization) rather than continuing to dequeue
- Check the Configure call uses the exact MediaFormat from GetTrackFormat(trackIndexAudio)
- Log the raw decoderStatus value; negative codes other than -1/-2/-3 indicate a codec error needing reconfigure
- 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
- Flush/re-create the MediaCodec after every seek
- Validate media files with ffprobe/another player before shipping
- Configure the codec with the exact MediaFormat from MediaExtractor.GetTrackFormat
- Test on low-end Android devices with hardware codec quirks
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
- Unable to read
- Failed to create Celt decoder.
- Unable to read
- The Media Codec has not been initialized for a media
- mediaCodec has already been initialized
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)