Skip to content

Fix HD and full range videos showing wrong colors - #31408

Open
meh7an wants to merge 3 commits into
telegramdesktop:devfrom
meh7an:fix/hd-video-colors
Open

meh7an wants to merge 3 commits into
telegramdesktop:devfrom
meh7an:fix/hd-video-colors

Conversation

@meh7an

@meh7an meh7an commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Based on #31407 and needs desktop-app/lib_ui#381; only the last commit is new here.

Every YUV to RGB conversion assumes BT.601 limited range, whatever the video says. HD videos use the BT.709 matrix, so their colors shift (red turns orange, green turns yellow). Full range videos, common from phone cameras and screen recordings, come out with crushed blacks and clipped whites. Re-encoded videos also keep tags that no longer match their samples.

The matrix and range now follow the video's tags. Untagged videos use BT.709 when they are at least 1280 wide or taller than 576 and BT.601 otherwise, which is what other players do:

  • The GL renderers take the same matrix uniform as the RHI ones, through the new option of the lib_ui YUV texture shaders.
  • Every swscale conversion gets the coefficients and range through sws_setColorspaceDetails(), with the same table on both sides so a YUV to YUV scale keeps its matrix instead of being converted to BT.601 through RGB.
  • The re-encode keeps the source range and tags the output with the matrix playback used for the source, so untagged videos and tags that aren't recognized, like SMPTE 240M, get the guessed matrix instead of a tag that decodes differently after the resize. Frames that go through RGB (edited videos, RGB sources, and still images with animated stickers) are tagged with the SMPTE 170M matrix swscale uses for them.

Testing

Tested on macOS 27.0, in a Debug build:

  • HD and SD videos play with correct colors in the media viewer, in Pip and inline.
  • Temporary code decoded SMPTE HD color bars encoded as tagged BT.709, untagged and full range: a same size YUV to YUV conversion now copies the planes exactly, where the old swscale setup changed them by up to 22 levels, and converting after a YUV to YUV resize gives the same colors as converting directly.
  • Temporary code re-encoded those bars and SMPTE 240M, HDR10 and P3 HDR10 clips with reduced quality: the tags match the samples, the output decodes with the same matrix as the source, and the colors stay 2 to 3 levels apart in the median.
  • A still image with animated stickers sent as a video keeps its colors within 1 level, tagged with the SMPTE 170M matrix.
@meh7an
meh7an force-pushed the fix/hd-video-colors branch from 95bfc9a to 7e79521 Compare October 22, 2026 21:05

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant