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

  1. Prefer the default OUTPUT_MODE_YUV with a VideoDecoderOutputBufferRenderer instead of OUTPUT_MODE_SURFACE_YUV.
  2. Ensure the Surface stays valid while rendering: only call setVideoSurface with a live surface, and clear it (null) before releasing it.
  3. If the surface is replaced, re-initialize the decoder/surface pairing before further render calls.
  4. 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

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


AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14). Data as JSON: /api/errors/26dcfec4dee9535c. Report an issue: GitHub.