{"record":{"id":"d9c596b1999ad4a2","repo":"google/ExoPlayer","slug":"failed-to-render-output-buffer-to-surface-decoder-d9c596","errorCode":null,"errorMessage":"Failed to render output buffer to surface: decoder is not initialized.","messagePattern":"Failed to render output buffer to surface: decoder is not initialized\\.","errorType":"exception","errorClass":"VpxDecoderException","httpStatus":null,"severity":"error","filePath":"extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java","lineNumber":165,"sourceCode":"  @Override\n  protected VpxDecoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig)\n      throws VpxDecoderException {\n    TraceUtil.beginSection(\"createVpxDecoder\");\n    int initialInputBufferSize =\n        format.maxInputSize != Format.NO_VALUE ? format.maxInputSize : DEFAULT_INPUT_BUFFER_SIZE;\n    VpxDecoder decoder =\n        new VpxDecoder(\n            numInputBuffers, numOutputBuffers, initialInputBufferSize, cryptoConfig, threads);\n    this.decoder = decoder;\n    TraceUtil.endSection();\n    return decoder;\n  }\n\n  @Override\n  protected void renderOutputBufferToSurface(VideoDecoderOutputBuffer outputBuffer, Surface surface)\n      throws VpxDecoderException {\n    if (decoder == null) {\n      throw new VpxDecoderException(\n          \"Failed to render output buffer to surface: decoder is not initialized.\");\n    }\n    decoder.renderToSurface(outputBuffer, surface);\n    outputBuffer.release();\n  }\n\n  @Override\n  protected void setDecoderOutputMode(@C.VideoOutputMode int outputMode) {\n    if (decoder != null) {\n      decoder.setOutputMode(outputMode);\n    }\n  }\n\n  @Override\n  protected DecoderReuseEvaluation canReuseDecoder(\n      String decoderName, Format oldFormat, Format newFormat) {\n    return new DecoderReuseEvaluation(\n        decoderName,","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java#L147-L183","documentation":"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.","triggerScenarios":"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.","commonSituations":"Apps forcing videoSurfaceViewYuv output mode with the VP9 extension; races between renderer initialization and the first frame; subclassing LibvpxVideoRenderer and calling renderOutputBufferToSurface directly.","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."],"exampleFix":"// before\nplayer.setVideoOutputMode(C.OUTPUT_MODE_SURFACE_YUV); // before decoder init completes\n\n// after\n// keep default OUTPUT_MODE_YUV, or guard:\nif (decoder != null) {\n  decoder.renderToSurface(outputBuffer, surface);\n}","handlingStrategy":"validation","validationCode":"// Inside a subclass, before rendering to surface:\nif (decoder == null) { throw new IllegalStateException(\"render before initDecoder\"); /* or drop the buffer */ }","typeGuard":null,"tryCatchPattern":"catch (VpxDecoderException e) { log and re-prepare; surface mode cannot render without an initialized decoder }","preventionTips":["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."],"tags":["vp9","libvpx","video","renderer","surface-yuv","exoplayer-extension"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}