Skip to content

vo_gpu_next: set min_luma to HDR black if edid value is below 0.2 - #17009

Closed
llyyr wants to merge 1 commit into
mpv-player:masterfrom
llyyr:edid-minluma-2
Closed

vo_gpu_next: set min_luma to HDR black if edid value is below 0.2#17009
llyyr wants to merge 1 commit into
mpv-player:masterfrom
llyyr:edid-minluma-2

Conversation

@llyyr

@llyyr llyyr commented Nov 4, 2025

Copy link
Copy Markdown
Contributor

And set it to 0.2 if it's higher than 0.2.

This hopefully results in better defaults than current status quo and avoids issues like #16933

In #16933, the reporter's display has a min_luma of 0.01 and setting target-contrast=inf gets the desired output from mpv.

@llyyr

llyyr commented Nov 4, 2025

Copy link
Copy Markdown
Contributor Author

@kasper93 do you have thoughts on this? I think this would be better out of box default than master for most displays. IMO it's still an improvement even if we drop the part where values above 0.2 get clamped to 0.2, if you don't like that.

Comment thread video/out/vo_gpu_next.c Outdated
// sRGB reference display minimum luminance, assume it's an OLED display
// and set min_luma to 0. Otherwise, leave it to the reference display
// value which shouldn't be too different from the reported value.
target_csp.hdr.min_luma = (target_csp.hdr.min_luma < 0.2f) ? 0 : 0.2f;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 is undefined, you want to use PL_COLOR_HDR_BLACK.

Also for cutoff point you can use (PL_COLOR_SDR_WHITE / PL_COLOR_SDR_CONTRAST)

I don't know what are the good values here though. I don't see how changing this to binary selection helps. It's quite opinionated decision to categorize all displays into two groups, ignoring the reported luminance.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the cutoff being 0.1 being makes more sense? The point is to have better out of box default for OLED screens, where min_luma=0.01 raises blacks and users report target-contrast=inf is the correct output.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point is to have better out of box default for OLED screens, where min_luma=0.01 raises blacks

OLEDs should really not report such high black level, unless they have good reason too. But if that's the case, it's indeed an issue.

Comment thread video/out/vo_gpu_next.c Outdated
@ghost

ghost commented Nov 4, 2025

Copy link
Copy Markdown

+1 for >0.2 clamp being re-added to this commit, unless we're going to claim that #16928 (comment) is using a 400:1 contrast display in 2025.

@kasper93

kasper93 commented Nov 4, 2025

Copy link
Copy Markdown
Member

+1 for >0.2 clamp being re-added to this commit, unless we're going to claim that #16928 (comment) is using a 400:1 contrast display in 2025.

@atrxia1: you would be surprised what people use to watch movies.

@verygoodlee what display was that?

@llyyr
llyyr force-pushed the edid-minluma-2 branch 2 times, most recently from a9bce14 to 33a71b0 Compare November 4, 2025 20:42
@llyyr llyyr changed the title vo_gpu_next: set min_luma to 0 if edid value is below 0.2 vo_gpu_next: set min_luma to HDR black if edid value is below 0.2 Nov 4, 2025
Comment thread video/out/vo_gpu_next.c Outdated
And set it to 0.203 if it's higher than 0.203.

This hopefully results in better defaults than current status quo and
avoids issues like mpv-player#16933

In mpv-player#16933, the reporter's display has a min_luma of 0.01 and setting
target-contrast=inf gets the desired output from mpv.
@ghost

ghost commented Nov 4, 2025

Copy link
Copy Markdown

@atrxia1: you would be surprised what people use to watch movies.

Just fyi, I can recreate the same 0.5 min_luma on two separate 1700:1 and 1000:1 IPS screens. This is more than likely an issue with auto-detection on Windows.

@llyyr

llyyr commented Nov 4, 2025

Copy link
Copy Markdown
Contributor Author

Do we have good reason to believe that the information provided by Windows isn't accurate here? Can you check the display EDID with a 3rd party tool and see what it says?

@ghost

ghost commented Nov 4, 2025

Copy link
Copy Markdown

Do we have good reason to believe that the information provided by Windows isn't accurate here?

I'm confused by this question. Isn't the basis for this PR that the auto-detected black level in #16933 is inaccurate? We're already doubting the accuracy of parsed EDID information in the first place, otherwise it wouldn't have necessitated this workaround. I will check EDID whenever I have time, but I think I misunderstood the scope of this change.

@llyyr

llyyr commented Nov 4, 2025

Copy link
Copy Markdown
Contributor Author

Isn't the basis for this PR that the auto-detected black level in #16933 is inaccurate?

No, OLED reporting 0.01 in EDID is honestly believable. Anything reporting 0.5 is not, because this field only exists for displays that have HDR modes and anything that has a HDR mode should be able to do better than 0.5 minimum luminance no matter what. For displays without a HDR mode, this should be undefined or whatever the default value is. 0.5 makes no sense whatsoever.

@kasper93

kasper93 commented Nov 4, 2025

Copy link
Copy Markdown
Member

Anything reporting 0.5 is not

Citation needed. VESA HDR400 certification defines 0.4 nits as black level.

, because this field only exists for displays that have HDR modes

I already explained to you why to is not true. I think your believe comes from the fact you mistaken ST2086 for ST2084. There is nothing about HDR in ST2086 and it explicitly states that it's format agnostic.

and anything that has a HDR mode should be able to do better than 0.5 minimum luminance no matter what.

False. Many IPS screens has glow that is way beyond that level.

For displays without a HDR mode, this should be undefined or whatever the default value is. 0.5 makes no sense whatsoever.

The difference between 0.2 and 0.5 is not that big to make the difference you think it would.

@llyyr

llyyr commented Nov 4, 2025

Copy link
Copy Markdown
Contributor Author

I already explained to you why to is not true. I think your believe comes from the fact you mistaken ST2086 for ST2084. There is nothing about HDR in ST2086 and it explicitly states that it's format agnostic.

It comes from having displays that have HDR mode and ones that don't.

Here's one example display I own which doesn't have HDR mode and its EDID:

Block 0, Base EDID:
  EDID Structure Version & Revision: 1.4
  Vendor & Product Identification:
    Manufacturer: MSI
    Model: 19380
    Made in: week 51 of 2023
  Basic Display Parameters & Features:
    Digital display
    Bits per primary color channel: 8
    DisplayPort interface
    Maximum image size: 53 cm x 29 cm
    Gamma: 2.20
    DPMS levels: Off
    Supported color formats: RGB 4:4:4, YCrCb 4:4:4, YCrCb 4:2:2
    First detailed timing includes the native pixel format and preferred refresh rate
    Display supports continuous frequencies
  Color Characteristics:
    Red  : 0.6826, 0.3056
    Green: 0.2441, 0.6748
    Blue : 0.1552, 0.0849
    White: 0.3125, 0.3281
  Established Timings I & II:
    IBM     :   720x400    70.081663 Hz   9:5     31.467 kHz     28.320000 MHz
    DMT 0x04:   640x480    59.940476 Hz   4:3     31.469 kHz     25.175000 MHz
    Apple   :   640x480    66.666667 Hz   4:3     35.000 kHz     30.240000 MHz
    DMT 0x05:   640x480    72.808802 Hz   4:3     37.861 kHz     31.500000 MHz
    DMT 0x06:   640x480    75.000000 Hz   4:3     37.500 kHz     31.500000 MHz
    DMT 0x08:   800x600    56.250000 Hz   4:3     35.156 kHz     36.000000 MHz
    DMT 0x09:   800x600    60.316541 Hz   4:3     37.879 kHz     40.000000 MHz
    DMT 0x0a:   800x600    72.187572 Hz   4:3     48.077 kHz     50.000000 MHz
    DMT 0x0b:   800x600    75.000000 Hz   4:3     46.875 kHz     49.500000 MHz
    Apple   :   832x624    74.551266 Hz   4:3     49.726 kHz     57.284000 MHz
    DMT 0x10:  1024x768    60.003840 Hz   4:3     48.363 kHz     65.000000 MHz
    DMT 0x11:  1024x768    70.069359 Hz   4:3     56.476 kHz     75.000000 MHz
    DMT 0x12:  1024x768    75.028582 Hz   4:3     60.023 kHz     78.750000 MHz
    DMT 0x24:  1280x1024   75.024675 Hz   5:4     79.976 kHz    135.000000 MHz
  Standard Timings:
    DMT 0x23:  1280x1024   60.019740 Hz   5:4     63.981 kHz    108.000000 MHz
    GTF     :  1280x1024  120.000185 Hz   5:4    131.640 kHz    233.793000 MHz
    GTF     :  1920x1080   84.999879 Hz  16:9     96.390 kHz    252.927000 MHz
    GTF     :  1440x900   119.999896 Hz  16:10   115.800 kHz    229.747000 MHz
    DMT 0x3a:  1680x1050   59.954250 Hz  16:10    65.290 kHz    146.250000 MHz
    GTF     :  1680x1050  120.000000 Hz  16:10   135.000 kHz    313.200000 MHz
    DMT 0x52:  1920x1080   60.000000 Hz  16:9     67.500 kHz    148.500000 MHz
    GTF     :  1920x1080  119.999987 Hz  16:9    138.840 kHz    368.759000 MHz
  Detailed Timing Descriptors:
    DTD 1:  1920x1080   60.000000 Hz  16:9     67.500 kHz    148.500000 MHz (527 mm x 296 mm)
                 Hfront   88 Hsync  44 Hback  148 Hpol P
                 Vfront    4 Vsync   5 Vback   36 Vpol P
    Display Range Limits:
      Monitor ranges (Range Limits Only): 48-180 Hz V, 160-160 kHz H, max dotclock 600 MHz
    Display Product Serial Number: 'BB4H213C01015'
    Display Product Name: 'MSI G244F E2'
  Extension blocks: 1
Checksum: 0x7f

----------------

Block 1, CTA-861 Extension Block:
  Revision: 3
  Underscans IT Video Formats by default
  Basic audio support
  Supports YCbCr 4:4:4
  Supports YCbCr 4:2:2
  Native detailed modes: 1
  Video Data Block:
    VIC   1:   640x480    59.940476 Hz   4:3     31.469 kHz     25.175000 MHz
    VIC   3:   720x480    59.940060 Hz  16:9     31.469 kHz     27.000000 MHz
    VIC   5:  1920x1080i  60.000000 Hz  16:9     33.750 kHz     74.250000 MHz
    VIC  20:  1920x1080i  50.000000 Hz  16:9     28.125 kHz     74.250000 MHz
    VIC   4:  1280x720    60.000000 Hz  16:9     45.000 kHz     74.250000 MHz
    VIC  19:  1280x720    50.000000 Hz  16:9     37.500 kHz     74.250000 MHz
    VIC  31:  1920x1080   50.000000 Hz  16:9     56.250 kHz    148.500000 MHz
    VIC  18:   720x576    50.000000 Hz  16:9     31.250 kHz     27.000000 MHz
    VIC   2:   720x480    59.940060 Hz   4:3     31.469 kHz     27.000000 MHz
    VIC  17:   720x576    50.000000 Hz   4:3     31.250 kHz     27.000000 MHz
    VIC  16:  1920x1080   60.000000 Hz  16:9     67.500 kHz    148.500000 MHz (native)
    VIC   4:  1280x720    60.000000 Hz  16:9     45.000 kHz     74.250000 MHz
    VIC  63:  1920x1080  120.000000 Hz  16:9    135.000 kHz    297.000000 MHz
  Audio Data Block:
    Linear PCM:
      Max channels: 2
      Supported sample rates (kHz): 48 44.1 32
      Supported sample sizes (bits): 24 20 16
  Speaker Allocation Data Block:
    FL/FR - Front Left/Right
  Detailed Timing Descriptors:
    DTD 2:  1920x1080  119.982181 Hz  16:9    137.260 kHz    285.500000 MHz (527 mm x 296 mm)
                 Hfront   48 Hsync  32 Hback   80 Hpol P
                 Vfront    3 Vsync   5 Vback   56 Vpol P
    DTD 3:  1920x1080  143.975834 Hz  16:9    159.813 kHz    325.060000 MHz (527 mm x 296 mm)
                 Hfront   24 Hsync  32 Hback   58 Hpol P
                 Vfront    3 Vsync   5 Vback   22 Vpol P
    DTD 4:  1920x1080  165.001284 Hz  16:9    183.151 kHz    372.530000 MHz (527 mm x 296 mm)
                 Hfront   24 Hsync  32 Hback   58 Hpol P
                 Vfront    3 Vsync   5 Vback   22 Vpol P
    DTD 5:  1920x1080  179.999117 Hz  16:9    199.799 kHz    407.590000 MHz (527 mm x 296 mm)
                 Hfront   48 Hsync  44 Hback   28 Hpol P
                 Vfront    3 Vsync   5 Vback   22 Vpol P
Checksum: 0xc7

----------------

EDID conformity: PASS

This does not report the luminance anywhere. The ones that do have it under the HDR Static Metadata Data Block but this block doesn't exist for displays that don't have HDR mode.

@llyyr

llyyr commented Nov 4, 2025

Copy link
Copy Markdown
Contributor Author

@kasper93 This repository has EDID for thousands of monitors, we can see clearly that any display that doesn't support HDR transfer, also doesn't advertise any information about the panel luminance.

https://github.com/linuxhw/EDID?tab=readme-ov-file#digital-display

I didn't check every single, but I clicked about 20-30 models from 2018 onwards to see if they followed this pattern or not.

Citation needed. VESA HDR400 certification defines 0.4 nits as black level.

You are right about this claim however.

@nissel

nissel commented Nov 4, 2025

Copy link
Copy Markdown

Citation needed. VESA HDR400 certification defines 0.4 nits as black level.

I'm no expert but don't standards like VESA HDR400 mean the display device should be capable of displaying a black level of <=0.4 nits when given a black 0 nit signal.

Doesn't sending a raised black level just make the problem worse for low contrast displays?

@kasper93

kasper93 commented Nov 5, 2025

Copy link
Copy Markdown
Member

Citation needed. VESA HDR400 certification defines 0.4 nits as black level.

I'm no expert but don't standards like VESA HDR400 mean the display device should be capable of displaying a black level of <=0.4 nits when given a black 0 nit signal.

Doesn't sending a raised black level just make the problem worse for low contrast displays?

If you have black level at 0.4 nits and send signal between 0 and 0.4 nits this all should be black, because it's below black level that display can reproduce. So shadow detail is raised above black level to avoid clipping.

Note that this is only don't for HDR output, because in SDR output 0 means always display 0, not absolute 0.

There was a lot of noise in previous thread, could you remind me with stats screen what is the current issue?

@nissel

nissel commented Nov 5, 2025

Copy link
Copy Markdown

There was a lot of noise in previous thread, could you remind me with stats screen what is the current issue?

If this question is addressed to me, I have two slightly different issues related to the raised minimum brightness.

  1. The 0.01 nits defaulted to in SDR raises contents black levels slightly for me, I've been setting contrast to inf (or something large ~30000) to solve this.
Screenshot SDR
  1. The 0.01 nits defaulted to in HDR, doesn't seem to effect the content much but any black bars displayed on cropped content are grey / slightly raised black. Setting contrast to inf to solves this too. It seems the minimum brightness is effecting black bars more than the actual content which seems like a bug.
Screenshot HDR

This is on an Samsung S90C qd-oled TV. It does not present any HDR luminance metadata

HDR static metadata
  SDR luminance............ Yes
  HDR luminance............ No
  SMPTE ST2084............. Yes
  Hybrid log............... Yes
  Data payload............. 060D01

@kasper93

kasper93 commented Nov 5, 2025

Copy link
Copy Markdown
Member

The 0.01 nits defaulted to in HDR

Could you go to your Windows settings and run HDR calibration and adjust those values for your screen and your liking? (it's settings -> system -> display -> hdr -> hdr display calibration) We cannot possibly support all cases of "not lifted blacks" and "not clipped shadows" when this value is wrong. And this is why the HDR calibration exists in Windows settings and in any game really.

Note that this is not related to any recent changes, HDR would work the same way for a long time and for SDR we would default to 1000:1 contrast which would lift shadows even more, than your current 0.01 value.

The 0.01 nits defaulted to in SDR raises contents black levels slightly for me

Again similar situation, it's still better than it was before where it would use 0.2 nits. Generally when tone mapping HDR to SDR how black level is handles depends on tone-mapping setting.

do you have thoughts on this?

@llyyr: See, there is really no difference between HDR and SDR as reported by the user. While I agree we could sanitize the reported luminance value. It's not that easy to just use inf. Even if we assume that reported values are always false, the HDR calibration exist which essentially adjust those value for user liking, and mpv should follow those user setting. Similar in Wayland we should respect compositor luminances, they are not at all direct from EDID and depend on screen brightness and other settings.

I'm trying to say that, but no one listens. We have to stop focusing on single case and adding band-aids to it.

It's exactly the same way with target-peak value, if you have it set wrong, our tonemapping will not work or do bad thing. I think users understand that mpv is not always able the predict exact display values.


Since we are using 203 for sdr tonammaping, we could infer the contrast from max reported luminance and use this value. Instead absolute min_luminace. But frankly this is not that correct and would just scale down black point arbitrary.

Realistically we could min(lum, 203 / 800) to limit this value to 800:1 displays, which arguably on screens with lower contrast we wouldn't do anything useful anyway.

EDIT:

I've been setting contrast to inf (or something large ~30000) to solve this.
Samsung S90C qd-oled TV

Depending on your ambient lights the black level of qd-oled will vary, but setting 30000 is resonable value. Also inf works, because at this point we can just ignore black lift.

@nissel

nissel commented Nov 5, 2025

Copy link
Copy Markdown

Thanks for your detailed reply.

Could you go to your Windows settings and run HDR calibration and adjust those values for your screen and your liking?

Yes that solves it.

The only thing I want to mention again are the in-full black bars in HDR being very raised, above the contents black level. To make the issue very obvious I've set target-peak=1000 and target-contrast=1000 giving a min brightness of 1 nit. This is a 2.39:1 file on a 16:9 display.

Screenshot 2025-11-05 105817

This does not happen in SDR even if you set target-peak=203 and target-contrast=203 for a similar 1 nit minimum.

@kasper93

kasper93 commented Nov 5, 2025

Copy link
Copy Markdown
Member

The only thing I want to mention again are the in-full black bars in HDR being very raised, above the contents black level.

Does this also happen when you don't try to break it with target-contrast? I know why this happens, but it's not like you should be seeing it in normal use.

I will think about adjusting this to not be annoying.

This does not happen in SDR even if you set target-peak=203 and target-contrast=203 for a similar 1 nit minimum.

Yes, SDR modes by design doesn't lift blacks.

@nissel

nissel commented Nov 5, 2025

Copy link
Copy Markdown

Yes to a slighter degree it's just visible at a 0.01 minimum. But that's not really my point, shouldn't the black level of the content be lifted to the same degree as the black bars? Or if that's not the case maybe the black bars shouldn't be raised either.

@kasper93

kasper93 commented Nov 5, 2025

Copy link
Copy Markdown
Member

Yes to a slighter degree it's just visible at a 0.01 minimum.

After calibration, you probably no longer use 0.01 min.

But that's not really my point, shouldn't the black level of the content be lifted to the same degree as the black bars? Or if that's not the case maybe the black bars shouldn't be raised either.

Background color is interpreted as srgb, which does this lift, it's processed differently than PQ (HDR) movie. But I agree, it's probably more pragmatic to avoid this. But the point is, when you dial the target-constrast or the hdr calibration correctly, you shouldn't be seeing this lifted black.

And this is also good way to adjust target-contrast manually, until it no longer get's blacker.

@llyyr

llyyr commented Nov 5, 2025

Copy link
Copy Markdown
Contributor Author

Yes that solves it.

what is the new reported min luminance after doing this calibration?

@nissel

nissel commented Nov 5, 2025

Copy link
Copy Markdown

Yes that solves it.

what is the new reported min luminance after doing this calibration?

Setting it to 0 via the windows calibration, correctly applies to mpv as 0. And the max carries over too.

After calibration, you probably no longer use 0.01 min.

Yeah I'm fine with using the windows calibration, or target-contrast inf. Every looks great now to me.

Not sure if other users were getting a much higher inappropriate min using other displays, but I'll leave that to them to chime in.

@kasper93

kasper93 commented Nov 5, 2025

Copy link
Copy Markdown
Member

Setting it to 0 via the windows calibration, correctly applies to mpv as 0. And the max carries over too.

Good to hear.

Not sure if other users were getting a much higher inappropriate min using other displays, but I'll leave that to them to chime in.

Up until some time ago, there was no automatic detection of peak/min display values. And you had to manually specify them. Else we would use something like 0/10000 which is never correct.

I think current status is an improvement, I agree that reported luminance values may not be correct especially when no factory ICC profile is installed or user calibration has not been done. But we cannot imagine those values in any other way.

@llyyr

llyyr commented Nov 5, 2025

Copy link
Copy Markdown
Contributor Author

I opened this PR (and my previous thoughts on the matter were) under the assumption that the platform reported values were direct readings from the EDID. But as it turns out, Windows has a calibration tool and it's not a direct reporting from EDID so I don't think this PR is necessary anymore.

If users still have problems with raised or crushed blacks, the current defaults and properly calibrating should resolve all issues.

@kasper93

kasper93 commented Nov 5, 2025

Copy link
Copy Markdown
Member

I opened this PR (and my previous thoughts on the matter were) under the assumption that the platform reported values were direct readings from the EDID. But as it turns out, Windows has a calibration tool and it's not a direct reporting from EDID so I don't think this PR is necessary anymore.

The EDID is one source of this metadata. The other is ICC profile that is applied system wide (monitors generally come with ICC profiles these days). And calibration tool, which basically creates small ICC profile embedded with those values. Last is fallback to some "SDR" default values, if none of the above is available.

I'm not opposed to sanitizing those values, but I would wait for more users to report issues, so we can get more familiarity when the problem is caused.

@Jules-A

Jules-A commented Nov 5, 2025

Copy link
Copy Markdown

If users still have problems with raised or crushed blacks, the current defaults and properly calibrating should resolve all issues.

Defaults are so bad for me, super raised that I actually see colour bleeding now (that's when watching a HDR video, SDR videos are just raised)...
I could try re-calibrating but I spent like 12hrs when I first got this monitor deciding/blind testing on calibration settings and the issue hasn't occurred in any other app, well besides CoD:MW3 (remake) that enabled HDR by default (but that's different since MPV doesn't unless I increase to >203).

Anyway, "sdr-adjust-gamma=yes
treat-srgb-as-power22=no" fixes it for me so it's not really a big deal for me but saying the issue is now that the monitor isn't calibrated just isn't true.

@kasper93

kasper93 commented Nov 5, 2025

Copy link
Copy Markdown
Member

@Jules-A: Please show stats page 1. We don't know what issue you are taking about.

@Jules-A

Jules-A commented Nov 5, 2025

Copy link
Copy Markdown

@Jules-A: Please show stats page 1. We don't know what issue you are taking about.
Non-HDR

HDR
HDR

NOTE: The default for watching HDR videos in SDR mode is actually unwatchable, it's worse than it looks in the screenshot with tonnes of blocky/banding artifacts on blacks/greys. It seems gamma 2.2 is broken.

EDIT: Zzz... Looks like posting links/inlining images in spoilers is broken.

@kasper93

kasper93 commented Nov 5, 2025

Copy link
Copy Markdown
Member

Ok, so your screen expects sRGB piecewise transfer. In which case you should use treat-srgb-as-power22=no.

I honestly don't know how to fix that. We have no preexisting knowladge what the user display is and sRGB is what it is.

Is your first testcase affected or only HDR? There is no conversion at all in first screen it's bt.1886 on both ends.

@Jules-A

Jules-A commented Nov 5, 2025

Copy link
Copy Markdown

Ok, so your screen expects sRGB piecewise transfer. In which case you should use treat-srgb-as-power22=no.

I mean, I already am as part of the workaround and that just fixes HDR content on it's own.

I honestly don't know how to fix that. We have no preexisting knowladge what the user display is and sRGB is what it is.

Understandable but shouldn't defaults aim for compatibility? I don't know how common it is for monitors to expect sRGB piecewise though. It's not something that's an issue with any other apps I've used.

Is your first testcase affected or only HDR? There is no conversion at all in first screen it's bt.1886 on both ends.

It was an image to just show the stats so doesn't really show the raised blacks but yeah, that's still an issue, it's far from unwatchable like HDR content was but it's pretty distracting. Raising tc to inf helps a little but I have to use sdr-adjust-gamma=yes (along with treat-srgb-as-power22=no) to fix it.

Comment thread video/out/vo_gpu_next.c
Comment on lines +1111 to +1112
target_csp.hdr.min_luma = target_csp.hdr.min_luma < ref_min_luma ?
PL_COLOR_HDR_BLACK : ref_min_luma;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition is always true on wayland. On KDE the LHS is 0.01 and on other compositors it is 0.2.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I don't believe this patch is needed anymore, I was under the impression this value reflected the display EDID.

@kasper93

kasper93 commented Nov 5, 2025

Copy link
Copy Markdown
Member

It was an image to just show the stats so doesn't really show the raised blacks but yeah, that's still an issue, it's far from unwatchable like HDR content was but it's pretty distracting. Raising tc to inf helps a little but I have to use sdr-adjust-gamma=yes (along with treat-srgb-as-power22=no) to fix it.

Ok, I'm confused. Because what you show on the screenshot is how mpv 0.40 for example would work. Do you have an issue there? In fact there is no adjustment what so ever, so why it doesn't look good for you?

The other case is different and will look different, but not this case.

@Jules-A

Jules-A commented Nov 5, 2025

Copy link
Copy Markdown

Ok, I'm confused. Because what you show on the screenshot is how mpv 0.40 for example would work. Do you have an issue there? In fact there is no adjustment what so ever, so why it doesn't look good for you?

Ah, yeah, it's not exactly the same but it's basically the same by default on sdr content, I was using another param to adjust it then I believe and dropped it when the switch to srgb occurred.

@dyphire

dyphire commented Nov 6, 2025

Copy link
Copy Markdown
Contributor

This is incorrect behavior, the minimum luma of MiniLED displays is likewise below 0.2 but does not reach the infinite contrast ratio of OLED at all, and applying HDR black to them will only cause the blacks to shatter. Please respect the value of the edid below 0.2, and the user can override it with target-contrast option if it is inaccurate instead of forcing an immutable value.

Edit: Handling of values greater than 0.2 is necessary, which is obviously an incorrect report.

@mahkoh

mahkoh commented Nov 6, 2025

Copy link
Copy Markdown
Contributor

This code is in any case only reached if the output is operating with an SDR transfer function and AIUI in that case the reported luminance values should not come from the EDID.

@na-na-hi

na-na-hi commented Nov 6, 2025

Copy link
Copy Markdown
Contributor

Ok, so your screen expects sRGB piecewise transfer. In which case you should use treat-srgb-as-power22=no.

All SDR displays are assumed standard sRGB displays by default, and sRGB displays accept sRGB encoded values, not gamma2.2 values, no matter if the display has gamma2.2 EOTF.

The current behavior is broken. Only when sRGB content -> HDR display should mpv emulate a gamma2.2 display, not when HDR content -> sRGB displays.

@llyyr
llyyr marked this pull request as draft November 6, 2025 02:48
@llyyr

llyyr commented Nov 6, 2025

Copy link
Copy Markdown
Contributor Author

All SDR displays are assumed standard sRGB displays by default

Correct, and sRGB specification says the reference display has input/output characteristics of G22.

sRGB displays accept sRGB encoded values, not gamma2.2 values, no matter if the display has gamma2.2 EOTF.

This doesn't track, we need to apply the EOTF^-1 of the display EOTF to roundtrip.

The current behavior is broken.

If you believe this open an issue after reading the sources in the PR that added the option.

I'm closing this PR but feel free to continue discussion

@llyyr llyyr closed this Nov 6, 2025
@ghost

ghost commented Nov 6, 2025

Copy link
Copy Markdown

I think most users just want mpv to have sensible enough defaults, and right now it's hard to say that mpv works out-of-the-box. --sdr-adjust-gamma=auto is a step in the right direction, but there should probably be a similar option for target-contrast that ignores hinting and falls back to assuming inf for HDR TRC and 1000 for SDR TRC.

--treat-srgb-as-power22=auto should also respect --sdr-adjust-gamma=auto, as it currently doesn't. Outside of the obvious issue of adjusting gamma for images, if you use a custom background-color for transparent image viewing, it ends up messing up the intended r/g/b color values.

@kasper93

kasper93 commented Nov 6, 2025

Copy link
Copy Markdown
Member

Ok, so your screen expects sRGB piecewise transfer. In which case you should use treat-srgb-as-power22=no.

All SDR displays are assumed standard sRGB displays by default, and sRGB displays accept sRGB encoded values, not gamma2.2 values, no matter if the display has gamma2.2 EOTF.

The current behavior is broken. Only when sRGB content -> HDR display should mpv emulate a gamma2.2 display, not when HDR content -> sRGB displays.

@na-na-hi: This discussion again, aren't you getting tired? sRGB display EOTF is G2.2. Also please go to relevant thread, where you can discuss this topic with more knowledge people, see #16915 and possibly https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/442 . I could explain it yet again here, but I don't think there is much more to say in this topic.

I think most users just want mpv to have sensible enough defaults, and right now it's hard to say that mpv works out-of-the-box.

@atrxia1: Which cases doesn't work currently?

there should probably be a similar option for target-contrast that ignores hinting and falls back to assuming inf for HDR TRC and 1000 for SDR TRC.

Is this what people want? 0/10000 for HDR won't produce nice looking image, with both clipped blacks and clipped highlights.

and 1000 for SDR TRC.

So far all reports were that the contrast was too low in SDR mode on displays that report it. 1000:1 would be even lower than what is generally reported. I'm not sure what it fixes? Please provide examples. Also note that contrast is mostly irrelevant in SDR->SDR mode, because the black level is normalized to zero on output anyway. Only bt.1886 have special term to not only lift black, but also adjust curve. But without 'sdr-adjust-gamma` it wouldn't happen.

If you mean HDR->SDR tonemapping, please provide examples when 1000:1 would work better than reported contrast.

--treat-srgb-as-power22=auto should also respect --sdr-adjust-gamma=auto, as it currently doesn't. Outside of the obvious issue of adjusting gamma for images,

Please show example. treat-srgb-as-power22 by design take precedence over sdr-adjust-gamma, as it's not related to input/output, but to the sRGB transfer itself. However it's not relevant to what you say, in default config there is no conversion of sRGB input, as you seem to imply.

if you use a custom background-color for transparent image viewing, it ends up messing up the intended r/g/b color values.

That's completely separate issue, background-color is not subject to the same color correction, nor does it follow any of the options, except doing srgb->target color conversion. Whatever your target is, this is separate and I belive there is room for improvement, up until recently background-color rgb triplet was drawn completely untouched, even to incompatible target, so not like this is regression.

@na-na-hi

na-na-hi commented Nov 6, 2025

Copy link
Copy Markdown
Contributor

This doesn't track, we need to apply the EOTF^-1 of the display EOTF to roundtrip.

sRGB displays always accept sRGB signals no matter if the display have gamma2.2 or piecewise EOTF. There is also no "roundtrip" for HDR->sRGB conversion when absolute light intensity is already destroyed by tonemapping.

sRGB display EOTF is G2.2.

Have I ever said otherwise? Still it does not matter. Do you convert SDR gamma when displaying sRGB content on sRGB display just because the display EOTF is G2.2? Same for anything else targeting sRGB display output.

and possibly https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/442 . I could explain it yet again here, but I don't think there is much more to say in this topic.

If Wayland advertises sRGB display as G2.2 and as a result displaying sRGB content performs sRGB->G2.2 conversion, then it is Wayland/compositor's fault.

@ghost

ghost commented Nov 6, 2025

Copy link
Copy Markdown

Is this what people want? 0/10000 for HDR won't produce nice looking image, with both clipped blacks and clipped highlights.

mpv has defaulted to this behavior for a while now, and I don't see a flood of bug reports about how the default target-contrast behavior was "incorrect" and necessitated fixes. Yes, we can ad-hoc imply that mpv has always been broken and that it only now has started functioning correctly. But from the end-user perspective, mpv simply made sensible assumptions about the user's target, providing a consistent and hardware-agnostic output.

So far all reports were that the contrast was too low in SDR mode on displays that report it. 1000:1 would be even lower than what is generally reported. I'm not sure what it fixes? Please provide examples. Also note that contrast is mostly irrelevant in SDR->SDR mode, because the black level is normalized to zero on output anyway. Only bt.1886 have special term to not only lift black, but also adjust curve. But without 'sdr-adjust-gamma` it wouldn't happen.

Again, I already acknowledged that --sdr-adjust-gamma=auto/no is an improvement for SDR->SDR in my previous post, as this gets mpv closer to its old default behavior. There is simply a discrepancy with target-contrast where the user cannot opt out of contrast hinting for HDR->SDR, or even SDR->SDR if they decide to adjust --target-colorspace-hint-strict=no --target-trc=.

However it's not relevant to what you say, in default config there is no conversion of sRGB input, as you seem to imply.

You are correct. I think the background getting washed out made it seem like the image gamma was being adjusted on my end.

At the the end of the day, mpv is a developer-driven project and it's under no obligation to be user friendly. But over the past few weeks of development, I feel like too much onus has been put on the user to manually adjust everything.

@kasper93

kasper93 commented Nov 6, 2025

Copy link
Copy Markdown
Member

sRGB displays always accept sRGB signals no matter if the display have gamma2.2 or piecewise EOTF.

Could you elaborate what do you mean by this sentence? sRGB encoding (OETF) is meant to be displayed on gamma2.2 (EOTF) display. This is what spec says, including the paragraph about the mismatch that this encoding brings, but spec assumes that difference wouldn't be significant enough.

Have I ever said otherwise? Still it does not matter. Do you convert SDR gamma when displaying sRGB content on sRGB display just because the display EOTF is G2.2? Same for anything else targeting sRGB display output.

Do you convert G2.2 to sRGB just because the display is "sRGB compliant"? Let's not discuss technical topics with rhetorical questions.

We are targeting display with EOTF of gamma2.2. We are not bound with aRGB piecewise OETF encoding, this is not relevant in our usecase. We don't have to convert PQ to sRGB, which would include the mismatch that specification warns about, we can and should directly convert to display response (EOTF).

Similarly, we don't use bt.709 OETF. I know this can be confusing, I hope this makes it clearer. Let me know if you have further questions.

@kasper93

kasper93 commented Nov 6, 2025

Copy link
Copy Markdown
Member

Is this what people want? 0/10000 for HDR won't produce nice looking image, with both clipped blacks and clipped highlights.

mpv has defaulted to this behavior for a while now, and I don't see a flood of bug reports about how the default target-contrast behavior was "incorrect" and necessitated fixes.

Survivorship bias. The automatic HDR output was one of the most requested features in recent time.

Yes, we can ad-hoc imply that mpv has always been broken and that it only now has started functioning correctly. But from the end-user perspective, mpv simply made sensible assumptions about the user's target, providing a consistent and hardware-agnostic output.

It made hardcoded assumptions about transfer functions. They were not sensible for any display. And users were manually adjusting the knobs.

Also there seem to be confusion. Because display metadata is used since 04.11.2024, which is included in v0.40.0. And reception of this was positive. So, I'm not sure what exactly do you mean.

So far all reports were that the contrast was too low in SDR mode on displays that report it. 1000:1 would be even lower than what is generally reported. I'm not sure what it fixes? Please provide examples. Also note that contrast is mostly irrelevant in SDR->SDR mode, because the black level is normalized to zero on output anyway. Only bt.1886 have special term to not only lift black, but also adjust curve. But without 'sdr-adjust-gamma` it wouldn't happen.

Again, I already acknowledged that --sdr-adjust-gamma=auto/no is an improvement for SDR->SDR in my previous post, as this gets mpv closer to its old default behavior. There is simply a discrepancy with target-contrast where the user cannot opt out of contrast hinting for HDR->SDR, or even SDR->SDR if they decide to adjust --target-colorspace-hint-strict=no --target-trc=.

Cannot opt out? You can set target-contrast=1000 or anything to opt out. Also there is no contrast hinting, contrast has always been there. Indeed sometime ago there was a change to use the black level also in SDR mode, but like I said before, I'm yet to see when it causes a real problem.

I think there is confusion about this and other overlapping changes that has happened. There was some breakage. Mostly because we switched to sRGB output by default to be compatible with color correction that can happen in compositors. Previously we would default to bt.1886 output, which has more well behaving curve near black, additionally. It's kinda in the middle between sRGB piecewise and gamma2.2. Nevertheless, there were many shortcuts, and depending on compositor behavior our output was not that correct. For example in HDR mode on Windows, when you did output SDR and let Windows convert to PQ, this were looking very bad. I understand that may be confusing for the user that is only looking at single case, but we have bigger picture to care about. Currently I'm not aware of cases where we are doing incorrect thing, while maybe in some cases not perfect.

However it's not relevant to what you say, in default config there is no conversion of sRGB input, as you seem to imply.

You are correct. I think the background getting washed out made it seem like the image gamma was being adjusted on my end.

At the the end of the day, mpv is a developer-driven project and it's under no obligation to be user friendly. But over the past few weeks of development, I feel like too much onus has been put on the user to manually adjust everything.

Quite on the contrary. Many if not all of those changes are to made mpv work out of the box in various modes and compositors. Limiting user interactions to the minimum. Which previously required specifying all the transfer parameters if you wanted HDR output for example. I put user experience first, which is often frown upon by mpv community which often want thier software to be exclusive to them and not accessible.

I asked for examples of what is currently not working or where we can improve. Instead, you went on a rant that things are changing, without bringing us closer to fixing your grievances. There is a lot of confusion in those threads and people attribute issues to wrong causes, that's why I need exact examples, when something is not possible or doesn't work, so we can evaluate and improve on case by case basis.

@llyyr

llyyr commented Nov 6, 2025

Copy link
Copy Markdown
Contributor Author

@atrxia1 please open an issue with the exact problem you're seeing, as well as the options required to set to get to the "correct" output with current mpv options/defaults. Mixing up a bunch of different issues doesn't really help figure out what you're talking about.

@na-na-hi

na-na-hi commented Nov 7, 2025

Copy link
Copy Markdown
Contributor

Could you elaborate what do you mean by this sentence? sRGB encoding (OETF) is meant to be displayed on gamma2.2 (EOTF) display. This is what spec says, including the paragraph about the mismatch that this encoding brings, but spec assumes that difference wouldn't be significant enough.

I have already done this at #16915 (comment):

The sRGB reference display has an EOTF of a pure gamma 2.2 function. This is for the reference display ONLY - it is intended to be used by the sRGB reference display to map the sRGB encoded values to light intensity.

Do you convert G2.2 to sRGB just because the display is "sRGB compliant"?

Yes if sdr-adjust-gamma=yes, otherwise no.

We are not bound with aRGB piecewise OETF encoding, this is not relevant in our usecase.

We are. Again I said this already:

The piecewise function is used for everything else: converting between sRGB and other color representations like XYZ, which requires the function to be invertible.

And IEC 61966 Annex C.4.6 says that images that is not sRGB with ICC profile (in the context of the standard, it means a known non-sRGB colorspace, so HDR videos with defined colorspace fall into this category) needs to be converted to sRGB colorspace for display, using sRGB as the destination ICC profile.

In Annex C, the ICC pipeline is effectively active for all cases, and sRGB profile is used when there is no explicit ICC profile. Thus, this conversion has nothing to do with reference display EOTF and should be done with the piecewise function.

@ghost

ghost commented Nov 7, 2025

Copy link
Copy Markdown

I think you're inferring too much from my comments or previous comments I've made in this repository. I'm not saying that any of these changes were done out of malice towards the end-user, nor do I have any fermenting "grievances". I simply disagree that they provide a better out-of-the-box experience than mpv's old defaults. I thought the original intention of this PR would've been an improvement over the current default, so I expressed my support. I'm personally not interested in litigating this further, as I don't think talking about mpv's defaults will lead to a productive conversation.

I already made the scope of the discussion as narrow as possible by providing an exact example at the start. But it was rebuked because it's not "that big" of a difference. If everyone agrees, then there isn't much else to discuss.

@kasper93

kasper93 commented Nov 7, 2025

Copy link
Copy Markdown
Member

@atrxia1: if you are talking about the target-contrast clamp, we can have that. If that's the only issue with new defaults, than I'm happy to be honest.

@na-na-hi: We can litigate this spec all day, the fact is outputting sRGB piecewise curve to gamma2.2 display is too dark, I will not make this default. display EOTF is gamma2.2 and we target that. We never targeted sRGB piecewise.

@ghost

ghost commented Nov 7, 2025

Copy link
Copy Markdown

Yes, I feel like cherry-picking the 0.203 clamping from this PR would be an improvement.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants