google/ExoPlayer · error · VpxDecoderException
Buffer render failed.
Error message
Buffer render failed.
What it means
VpxDecoder.renderToSurface calls the native vpxRenderFrame to push a decoded YUV buffer to a Surface (OUTPUT_MODE_SURFACE_YUV only) and throws when the native call returns -1. The render failed inside libvpx/JNI — typically because the Surface is invalid (released consumer), dimensions changed, or the context/Surface pairing broke.
Source
Thrown at extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java:208
lastSupplementalData = null;
vpxClose(vpxDecContext);
}
/**
* Sets the output mode for frames rendered by the decoder.
*
* @param outputMode The output mode.
*/
public void setOutputMode(@C.VideoOutputMode int outputMode) {
this.outputMode = outputMode;
}
/** Renders the outputBuffer to the surface. Used with OUTPUT_MODE_SURFACE_YUV only. */
public void renderToSurface(VideoDecoderOutputBuffer outputBuffer, Surface surface)
throws VpxDecoderException {
int getFrameResult = vpxRenderFrame(vpxDecContext, surface, outputBuffer);
if (getFrameResult == -1) {
throw new VpxDecoderException("Buffer render failed.");
}
}
private native long vpxInit(
boolean disableLoopFilter, boolean enableRowMultiThreadMode, int threads);
private native long vpxClose(long context);
private native long vpxDecode(long context, ByteBuffer encoded, int length);
private native long vpxSecureDecode(
long context,
ByteBuffer encoded,
int length,
@Nullable CryptoConfig mediaCrypto,
int inputMode,
byte[] key,
byte[] iv,View on GitHub (pinned to dd430f7053)
Solutions
- Prefer the default OUTPUT_MODE_YUV with a VideoDecoderOutputBufferRenderer instead of OUTPUT_MODE_SURFACE_YUV.
- Ensure the Surface stays valid while rendering: only call setVideoSurface with a live surface, and clear it (null) before releasing it.
- If the surface is replaced, re-initialize the decoder/surface pairing before further render calls.
- Catch VpxDecoderException at the player level and re-prepare playback to recover.
Example fix
// before player.setVideoSurface(surface); surface.release(); // then a frame arrives -> vpxRenderFrame fails // after player.setVideoSurface(null); surface.release(); // later, attach a new valid surface before playback resumes player.setVideoSurface(newSurface);
Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure surface is valid before attaching:
if (!surface.isValid()) { player.setVideoSurface(null); } Try / catch
catch (VpxDecoderException e) { player.setVideoSurface(null); player.prepare(); } // recover by re-preparing on a fresh surface Prevention
- Prefer OUTPUT_MODE_YUV with a VideoDecoderOutputBufferRenderer.
- Detach the surface (setVideoSurface(null)) before releasing it.
- Re-attach a new surface after SurfaceTexture/Surface replacement instead of rendering to the dead one.
When it happens
Trigger: vpxRenderFrame(vpxDecContext, surface, outputBuffer) == -1 while using OUTPUT_MODE_SURFACE_YUV. Happens when the Surface was destroyed/replaced, when rendering after decoder release, or when the buffer format does not match the surface buffers.
Common situations: SurfaceView surface detached during playback; switching surfaces without resetting output mode; backgrounding the app mid-frame; using surface-YUV mode with a Surface from an ImageReader of mismatched size.
Related errors
- Failed to render output buffer to surface: decoder is not in
- Failed to load decoder native libraries.
- Vpx decoder does not support secure decode.
- Failed to initialize decoder
- Invalid output mode.
AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14).
Data as JSON: /api/errors/26dcfec4dee9535c.
Report an issue: GitHub.