{"record":{"id":"6eff3541e083c18c","repo":"google/ExoPlayer","slug":"vpx-decoder-does-not-support-secure-decode","errorCode":null,"errorMessage":"Vpx decoder does not support secure decode.","messagePattern":"Vpx decoder does not support secure decode\\.","errorType":"exception","errorClass":"VpxDecoderException","httpStatus":null,"severity":"error","filePath":"extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java","lineNumber":84,"sourceCode":"   * @param cryptoConfig The {@link CryptoConfig} object required for decoding encrypted content.\n   *     May be null and can be ignored if decoder does not handle encrypted content.\n   * @param threads Number of threads libvpx will use to decode.\n   * @throws VpxDecoderException Thrown if an exception occurs when initializing the decoder.\n   */\n  public VpxDecoder(\n      int numInputBuffers,\n      int numOutputBuffers,\n      int initialInputBufferSize,\n      @Nullable CryptoConfig cryptoConfig,\n      int threads)\n      throws VpxDecoderException {\n    super(new DecoderInputBuffer[numInputBuffers], new VideoDecoderOutputBuffer[numOutputBuffers]);\n    if (!VpxLibrary.isAvailable()) {\n      throw new VpxDecoderException(\"Failed to load decoder native libraries.\");\n    }\n    this.cryptoConfig = cryptoConfig;\n    if (cryptoConfig != null && !VpxLibrary.vpxIsSecureDecodeSupported()) {\n      throw new VpxDecoderException(\"Vpx decoder does not support secure decode.\");\n    }\n    vpxDecContext =\n        vpxInit(/* disableLoopFilter= */ false, /* enableRowMultiThreadMode= */ false, threads);\n    if (vpxDecContext == 0) {\n      throw new VpxDecoderException(\"Failed to initialize decoder\");\n    }\n    setInitialInputBufferSize(initialInputBufferSize);\n  }\n\n  @Override\n  public String getName() {\n    return \"libvpx\" + VpxLibrary.getVersion();\n  }\n\n  @Override\n  protected DecoderInputBuffer createInputBuffer() {\n    return new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT);\n  }","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java#L66-L102","documentation":"The VpxDecoder constructor rejects playback when a non-null CryptoConfig is supplied (the stream is DRM-protected) but the loaded libvpx build does not advertise secure decode support (VpxLibrary.vpxIsSecureDecodeSupported() == false). Secure decode requires a specially built libvpx with protected-path support.","triggerScenarios":"DrmSessionManager provides a CryptoConfig for the VP9 track (e.g. Widevine L1 secure decoder required) while the extension's libvpx was built without secure decode. Combination of DRM content plus the software VP9 extension.","commonSituations":"Playing Widevine-protected VP9 through the libvpx extension on a stock extension build; devices where the hardware secure path is unavailable so ExoPlayer falls back to the extension renderer with a CryptoConfig.","solutions":["For DRM VP9 content, prefer the platform/MediaCodec secure decoder (setSecureDecoder(true) path) instead of the libvpx extension.","If you truly need libvpx secure decode, rebuild the extension's native code with secure-decode support so vpxIsSecureDecodeSupported() returns true.","At track selection, exclude the libvpx renderer for DRM-protected content by inspecting whether the format requires crypto.","As a last resort allow non-secure playback only if the license permits it (clear-content fallback)."],"exampleFix":"// before\n// DRM VP9 session routed to LibvpxVideoRenderer -> throws in VpxDecoder ctor\n\n// after\nRenderersFactory factory = new DefaultRenderersFactory(context) {\n  @Override protected void buildVideoRenderers(...) {\n    // skip LibvpxVideoRenderer when the content uses DRM\n    if (drmScheme == null) super.buildVideoRenderers(...);\n  }\n};","handlingStrategy":"validation","validationCode":"boolean secureVpx = VpxLibrary.isAvailable() && VpxLibrary.vpxIsSecureDecodeSupported();\nif (drmContent && !secureVpx) { /* exclude libvpx renderer for this track */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Route DRM-protected VP9 to MediaCodec secure decoders, not the extension.","If secure libvpx is required, build the extension with secure-decode support and assert vpxIsSecureDecodeSupported() in tests.","Mark DRM tracks during track selection and filter renderers by format.cryptoType."],"tags":["vp9","drm","secure-decode","widevine","exoplayer-extension"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}