How does mpv convert BT.2020 to BT.709?

When playing Ultra High Definition (UHD) video on a standard dynamic range (SDR) display, the media player mpv must convert the video’s wide BT.2020 color gamut and high dynamic range (HDR) metadata to fit the narrow BT.709 color space and standard gamma curve. To achieve this without losing detail or introducing major color distortion, mpv utilizes hardware-accelerated video outputs (vo=gpu or vo=gpu-next) powered by libplacebo. The player processes the transformation by decoding the YCbCr video stream into a linear, non-clipped RGB color space, performing necessary dynamic range adjustments via tone mapping, and then compressing the wider gamut down to the BT.709 primaries.

1. Decoding YCbCr to Linear Light

The conversion process begins at the pixel level. HDR video is typically encoded using the BT.2020 Non-Constant Luminance (NCL) color matrix and the Perceptual Quantizer (PQ) transfer function. mpv reads this metadata and executes the following steps:

2. Tone Mapping and Dynamic Range Reduction

Before shifting the colors into the target space, mpv must address the massive difference in luminance between HDR and SDR. HDR content is frequently mastered for peaks up to 1,000 or 4,000 nits, whereas standard BT.709 displays target roughly 100 nits.

Using algorithms such as spline, bt.2390, or mobius, mpv calculates how to compress the highlights while preserving midtone contrast. This tone mapping step adjusts the brightness of the linear RGB values so they do not clip aggressively when squeezed into standard dynamic range boundaries.

3. Gamut Mapping to BT.709 Primaries

Once the luminance is scaled appropriately, mpv targets the color gamut itself. Because BT.2020 can represent highly saturated colors that physically do not exist within the BT.709 spectrum, the player must map the coordinates.

By default, mpv calculates a 3x3 color transformation matrix derived from the difference between the BT.2020 and BT.709 primary coordinates and white points. To prevent out-of-gamut colors from clipping harshly—which causes a loss of detail in highly saturated areas, like bright neon lights—mpv’s rendering engine utilizes advanced gamut mapping modes. Under modern configurations using vo=gpu-next, it handles colors outside the target boundary smoothly, balancing desaturation with hue preservation to ensure the resulting output looks rich and natural on a standard monitor.