google/ExoPlayer · error · Gav1DecoderException
Buffer render error: ${gav1GetErrorMessage(gav1DecoderContex
Error message
Buffer render error: ${gav1GetErrorMessage(gav1DecoderContext)} What it means
Gav1DecoderException thrown when the native gav1RenderFrame call returns GAV1_ERROR while pushing a decoded frame to the output surface. The appended gav1GetErrorMessage() text carries the native reason, typically an unusable surface, a bad frame, or an errored decoder context.
Source
Thrown at extensions/av1/src/main/java/com/google/android/exoplayer2/ext/av1/Gav1Decoder.java:180
this.outputMode = outputMode;
}
/**
* Renders output buffer to the given surface. Must only be called when in {@link
* C#VIDEO_OUTPUT_MODE_SURFACE_YUV} mode.
*
* @param outputBuffer Output buffer.
* @param surface Output surface.
* @throws Gav1DecoderException Thrown if called with invalid output mode or frame rendering
* fails.
*/
public void renderToSurface(VideoDecoderOutputBuffer outputBuffer, Surface surface)
throws Gav1DecoderException {
if (outputBuffer.mode != C.VIDEO_OUTPUT_MODE_SURFACE_YUV) {
throw new Gav1DecoderException("Invalid output mode.");
}
if (gav1RenderFrame(gav1DecoderContext, surface, outputBuffer) == GAV1_ERROR) {
throw new Gav1DecoderException(
"Buffer render error: " + gav1GetErrorMessage(gav1DecoderContext));
}
}
/**
* Initializes a libgav1 decoder.
*
* @param threads Number of threads to be used by a libgav1 decoder.
* @return The address of the decoder context or {@link #GAV1_ERROR} if there was an error.
*/
private native long gav1Init(int threads);
/**
* Deallocates the decoder context.
*
* @param context Decoder context.
*/
private native void gav1Close(long context);View on GitHub (pinned to dd430f7053)
Solutions
- Read the native message text to distinguish 'surface invalid' from 'decoder errored'
- Guarantee the surface stays valid while rendering: only release it after the renderer has been stopped/flushed
- Recreate/flush the renderer (and re-init the decoder) when the surface changes instead of reusing the old context
- Catch Gav1DecoderException in the render path and trigger renderer recovery rather than crashing the playback thread
Example fix
// before
decoder.renderToSurface(outputBuffer, surface);
outputBuffer.release();
// after: detect dead surfaces and recover
try {
decoder.renderToSurface(outputBuffer, surface);
} catch (Gav1DecoderException e) {
Log.e(TAG, "render failed: " + e.getMessage(), e);
// signal the player to disable/re-enable the renderer with a fresh surface
} finally {
outputBuffer.release();
} Defensive patterns
Strategy: try-catch
Validate before calling
if (surface == null || !surface.isValid()) {
// do not render into a released/invalid surface
outputBuffer.release();
return;
} Try / catch
try {
decoder.renderToSurface(outputBuffer, surface);
} catch (Gav1DecoderException e) {
// native message via gav1GetErrorMessage() identifies surface vs decoder failure;
// signal renderer disable/re-enable to rebuild the decoder+surface pair
onRendererRecoveryNeeded(e);
} finally {
outputBuffer.release();
} Prevention
- Keep the surface alive until after the renderer is stopped or flushed
- Recreate the decoder context when the output surface changes; do not reuse the old one
- Check surface.isValid() before render attempts during teardown windows
When it happens
Trigger: The Surface passed to renderToSurface was released or its producer disconnected between renderer setup and frame render; the decoder context is in an error state from an earlier failed decode; EGL/SurfaceTexture backing the surface destroyed on a different thread.
Common situations: Activity teardown or surface destroyed mid-playback; switching surfaces while frames are in flight; codec surface detached by the UI layer concurrently with rendering.
Related errors
- Failed to load decoder native library.
- Failed to initialize decoder. Error: ${gav1GetErrorMessage(g
- Invalid output mode.
- Failed to render output buffer to surface: decoder is not in
- Failed to load decoder native libraries.
AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14).
Data as JSON: /api/errors/7645304dd19c75a4.
Report an issue: GitHub.