google/ExoPlayer · error · VpxDecoderException
Failed to render output buffer to surface: decoder is not in
Error message
Failed to render output buffer to surface: decoder is not initialized.
What it means
LibvpxVideoRenderer.renderOutputBufferToSurface was called while its cached decoder field is null, i.e. before a decoder was created by initDecoder (or after it was released). This path only runs in OUTPUT_MODE_SURFACE_YUV, where the renderer must push the decoded buffer into the VpxDecoder itself.
Source
Thrown at extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java:165
@Override
protected VpxDecoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig)
throws VpxDecoderException {
TraceUtil.beginSection("createVpxDecoder");
int initialInputBufferSize =
format.maxInputSize != Format.NO_VALUE ? format.maxInputSize : DEFAULT_INPUT_BUFFER_SIZE;
VpxDecoder decoder =
new VpxDecoder(
numInputBuffers, numOutputBuffers, initialInputBufferSize, cryptoConfig, threads);
this.decoder = decoder;
TraceUtil.endSection();
return decoder;
}
@Override
protected void renderOutputBufferToSurface(VideoDecoderOutputBuffer outputBuffer, Surface surface)
throws VpxDecoderException {
if (decoder == null) {
throw new VpxDecoderException(
"Failed to render output buffer to surface: decoder is not initialized.");
}
decoder.renderToSurface(outputBuffer, surface);
outputBuffer.release();
}
@Override
protected void setDecoderOutputMode(@C.VideoOutputMode int outputMode) {
if (decoder != null) {
decoder.setOutputMode(outputMode);
}
}
@Override
protected DecoderReuseEvaluation canReuseDecoder(
String decoderName, Format oldFormat, Format newFormat) {
return new DecoderReuseEvaluation(
decoderName,View on GitHub (pinned to dd430f7053)
Solutions
- Do not set OUTPUT_MODE_SURFACE_YUV before the renderer reports the decoder as initialized; use the default OUTPUT_MODE_YUV (decoder outputs buffers rendered by the renderer).
- If subclassing, guard calls with a null check on the decoder / ensure initDecoder completed before any render call.
- Upgrade the extension — modern versions prefer VideoDecoderOutputBufferRenderer and surface-YUV is rarely needed.
Example fix
// before
player.setVideoOutputMode(C.OUTPUT_MODE_SURFACE_YUV); // before decoder init completes
// after
// keep default OUTPUT_MODE_YUV, or guard:
if (decoder != null) {
decoder.renderToSurface(outputBuffer, surface);
} Defensive patterns
Strategy: validation
Validate before calling
// Inside a subclass, before rendering to surface:
if (decoder == null) { throw new IllegalStateException("render before initDecoder"); /* or drop the buffer */ } Try / catch
catch (VpxDecoderException e) { log and re-prepare; surface mode cannot render without an initialized decoder } Prevention
- Avoid OUTPUT_MODE_SURFACE_YUV unless required; default YUV mode does not hit this path.
- Ensure initDecoder has completed before any output buffer is rendered.
- Null out the video surface before releasing it.
When it happens
Trigger: Player switches to OUTPUT_MODE_SURFACE_YUV and renders an output buffer before initDecoder(...) has run, or setDecoderOutputMode is invoked in a window where decoder is null but a buffer is still rendered to surface. Almost always an ordering bug inside a custom renderer pipeline or an unsupported mode being forced.
Common situations: Apps forcing videoSurfaceViewYuv output mode with the VP9 extension; races between renderer initialization and the first frame; subclassing LibvpxVideoRenderer and calling renderOutputBufferToSurface directly.
Related errors
- Buffer render failed.
- Failed to load decoder native libraries.
- Vpx decoder does not support secure decode.
- Failed to initialize decoder
- Error instantiating VP9 extension
AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14).
Data as JSON: /api/errors/d9c596b1999ad4a2.
Report an issue: GitHub.