{"record":{"id":"aab18a83929c6d83","repo":"google/ExoPlayer","slug":"unsupported-color-transfer-colortransfer","errorCode":null,"errorMessage":"Unsupported color transfer: {colorTransfer}","messagePattern":"Unsupported color transfer: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"library/common/src/main/java/com/google/android/exoplayer2/util/GlUtil.java","lineNumber":328,"sourceCode":"      windowAttributes = EGL_WINDOW_SURFACE_ATTRIBUTES_NONE;\n    } else if (colorTransfer == C.COLOR_TRANSFER_ST2084) {\n      configAttributes = EGL_CONFIG_ATTRIBUTES_RGBA_1010102;\n      if (isEncoderInputSurface) {\n        // Outputting BT2020 PQ with EGL_WINDOW_SURFACE_ATTRIBUTES_BT2020_PQ to an encoder causes\n        // the encoder to incorrectly switch to full range color, even if the encoder is configured\n        // with limited range color, because EGL_WINDOW_SURFACE_ATTRIBUTES_BT2020_PQ sets full range\n        // color output, and GL windowAttributes overrides encoder settings.\n        windowAttributes = EGL_WINDOW_SURFACE_ATTRIBUTES_NONE;\n      } else {\n        // TODO(b/262259999) HDR10 PQ content looks dark on the screen.\n        windowAttributes = EGL_WINDOW_SURFACE_ATTRIBUTES_BT2020_PQ;\n      }\n    } else if (colorTransfer == C.COLOR_TRANSFER_HLG) {\n      checkArgument(isEncoderInputSurface, \"Outputting HLG to the screen is not supported.\");\n      configAttributes = EGL_CONFIG_ATTRIBUTES_RGBA_1010102;\n      windowAttributes = EGL_WINDOW_SURFACE_ATTRIBUTES_NONE;\n    } else {\n      throw new IllegalArgumentException(\"Unsupported color transfer: \" + colorTransfer);\n    }\n    return Api17.createEglSurface(eglDisplay, surface, configAttributes, windowAttributes);\n  }\n\n  /**\n   * Creates a new {@link EGLSurface} wrapping a pixel buffer.\n   *\n   * @param eglDisplay The {@link EGLDisplay} to attach the surface to.\n   * @param width The width of the pixel buffer.\n   * @param height The height of the pixel buffer.\n   * @param configAttributes EGL configuration attributes. Valid arguments include {@link\n   *     #EGL_CONFIG_ATTRIBUTES_RGBA_8888} and {@link #EGL_CONFIG_ATTRIBUTES_RGBA_1010102}.\n   */\n  @RequiresApi(17)\n  private static EGLSurface createPbufferSurface(\n      EGLDisplay eglDisplay, int width, int height, int[] configAttributes) throws GlException {\n    int[] pbufferAttributes =\n        new int[] {","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/library/common/src/main/java/com/google/android/exoplayer2/util/GlUtil.java#L310-L346","documentation":"Thrown by GlUtil.createEglSurface(...) when the requested C.COLOR_TRANSFER value is neither SDR (gamma) nor one of the two supported HDR transfers (SMPTE 2084 PQ handled above, or HLG handled just before). This argument must be one of the C.COLOR_TRANSFER_* constants; arbitrary integers or ColorInfo values with an unknown transfer function are rejected before EGL surface creation.","triggerScenarios":"Passing colorTransfer from ColorInfo.colorTransfer when it is COLOR_TRANSFER_SDR_VIDEO/HLG is fine, but a value like C.COLOR_TRANSFER_LINEAR, C.COLOR_TRANSFER_GAMMA_2_2, an unrecognized vendor transfer, or COLOR_TRANSFER_UNKNOWN (-1) reaches the final else and throws IllegalArgumentException. Also, HLG on a non-encoder (display) surface throws earlier via checkArgument, not here.","commonSituations":"Building a transformer/effects pipeline that copies ColorInfo from arbitrary source media (some cameras tag LINEAR or GAMMA_2_2), forwarding ToneMapping-heavy or AV1-HDR metadata into GlUtil.createEglSurface, or passing 0/-1 defaults from an uninitialized ColorInfo instead of a concrete transfer constant.","solutions":["Map or clamp the transfer before calling: treat COLOR_TRANSFER_UNKNOWN/LINEAR/GAMMA_2_2 as C.COLOR_TRANSFER_SDR_VIDEO (or skip EGL HDR path)","Apply tone mapping (or force SDR) when the source transfer is unsupported: set the experimental tone-mapping setting in DefaultRenderersFactory, or transcode to SDR first","Validate ColorInfo.colorTransfer against the supported set {COLOR_TRANSFER_SDR_VIDEO, COLOR_TRANSFER_SDR_GAMMA_2_2 (SDR path), COLOR_TRANSFER_HLG, COLOR_TRANSFER_SMPTE_170M/2084 as handled} and fail with a clear upstream message before touching EGL","Upgrade media3 — HDR/EGL transfer support expands across versions (b/262259999 and friends track added transfers)"],"exampleFix":"// before\nEGLSurface surface = GlUtil.createEglSurface(eglDisplay, outputSurface, colorInfo.colorTransfer);\n// after\nint transfer = colorInfo.colorTransfer;\nboolean hdrOk = transfer == C.COLOR_TRANSFER_SDR_VIDEO\n    || transfer == C.COLOR_TRANSFER_HLG\n    || transfer == C.COLOR_TRANSFER_SMPTE_2084;\nint safeTransfer = hdrOk ? transfer : C.COLOR_TRANSFER_SDR_VIDEO;\nEGLSurface surface = GlUtil.createEglSurface(eglDisplay, outputSurface, safeTransfer);","handlingStrategy":"type-guard","validationCode":"private static final Set<Integer> SUPPORTED = Set.of(\n    C.COLOR_TRANSFER_SDR_VIDEO, C.COLOR_TRANSFER_SDR_GAMMA_2_2,\n    C.COLOR_TRANSFER_HLG, C.COLOR_TRANSFER_SMPTE_2084);\nint transfer = SUPPORTED.contains(colorInfo.colorTransfer)\n    ? colorInfo.colorTransfer : C.COLOR_TRANSFER_SDR_VIDEO;","typeGuard":"static boolean isSupportedColorTransfer(@Nullable ColorInfo info) {\n  return info != null && (info.colorTransfer == C.COLOR_TRANSFER_SDR_VIDEO\n      || info.colorTransfer == C.COLOR_TRANSFER_SDR_GAMMA_2_2\n      || info.colorTransfer == C.COLOR_TRANSFER_HLG\n      || info.colorTransfer == C.COLOR_TRANSFER_SMPTE_2084);\n}","tryCatchPattern":"catch (IllegalArgumentException e) { /* downgrade transfer to SDR and retry createEglSurface */ }","preventionTips":["Normalize ColorInfo from arbitrary media at ingest: unknown transfer -> SDR","Enable tone mapping when shipping HDR through effects on mixed device fleets","Remember HLG requires an encoder-input surface (isEncoderInputSurface=true)"],"tags":["opengl","egl","hdr","color","video"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}