summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/interface-changes.rst3
-rw-r--r--DOCS/man/options.rst17
-rw-r--r--video/out/gpu/lcms.c81
3 files changed, 52 insertions, 49 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst
index 4a36041595..a3539c156e 100644
--- a/DOCS/interface-changes.rst
+++ b/DOCS/interface-changes.rst
@@ -37,6 +37,9 @@ Interface changes
- add an additional optional `albumart` argument to the `video-add` command,
which tells mpv to load the given video as album art.
- undeprecate `--cache-secs` option
+ - remove `--icc-contrast` and introduce `--icc-force-contrast`. The latter
+ defaults to the equivalent of the old `--icc-contrast=inf`, and can
+ instead be used to specifically set the contrast to any value.
--- mpv 0.33.0 ---
- add `--d3d11-exclusive-fs` flag to enable D3D11 exclusive fullscreen mode
when the player enters fullscreen.
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index e07f7a7851..f8f20d6e32 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -6358,14 +6358,15 @@ The following video options are currently all specific to ``--vo=gpu`` and
Size of the 3D LUT generated from the ICC profile in each dimension.
Default is 64x64x64. Sizes may range from 2 to 512.
-``--icc-contrast=<0-1000000|inf>``
- Specifies an upper limit on the target device's contrast ratio. This is
- detected automatically from the profile if possible, but for some profiles
- it might be missing, causing the contrast to be assumed as infinite. As a
- result, video may appear darker than intended. This only affects BT.1886
- content. The default of 0 means no limit if the detected contrast is less
- than 100000, and limits to 1000 otherwise. Use ``--icc-contrast=inf`` to
- preserve the infinite contrast (most likely when using OLED displays).
+``--icc-force-contrast=<no|0-1000000|inf>``
+ Override the target device's detected contrast ratio by a specific value.
+ This is detected automatically from the profile if possible, but for some
+ profiles it might be missing, causing the contrast to be assumed as
+ infinite. As a result, video may appear darker than intended. If this is
+ the case, setting this option might help. This only affects BT.1886
+ content. The default of ``no`` means to use the profile values. The special
+ value ``inf`` causes the BT.1886 curve to be treated as a pure power gamma
+ 2.4 function.
``--blend-subtitles=<yes|video|no>``
Blend subtitles directly onto upscaled video frames, before interpolation
diff --git a/video/out/gpu/lcms.c b/video/out/gpu/lcms.c
index 894506973b..704f1fbf1d 100644
--- a/video/out/gpu/lcms.c
+++ b/video/out/gpu/lcms.c
@@ -84,11 +84,12 @@ const struct m_sub_options mp_icc_conf = {
{"icc-profile-auto", OPT_FLAG(profile_auto)},
{"icc-cache-dir", OPT_STRING(cache_dir), .flags = M_OPT_FILE},
{"icc-intent", OPT_INT(intent)},
- {"icc-contrast", OPT_CHOICE(contrast, {"inf", -1}),
+ {"icc-force-contrast", OPT_CHOICE(contrast, {"no", 0}, {"inf", -1}),
M_RANGE(0, 1000000)},
{"icc-3dlut-size", OPT_STRING_VALIDATE(size_str, validate_3dlut_size_opt)},
{"3dlut-size", OPT_REPLACED("icc-3dlut-size")},
{"icc-cache", OPT_REMOVED("see icc-cache-dir")},
+ {"icc-contrast", OPT_REMOVED("see icc-force-contrast")},
{0}
},
.size = sizeof(struct mp_icc_opts),
@@ -272,48 +273,46 @@ static cmsHPROFILE get_vid_profile(struct gl_lcms *p, cmsContext cms,
break;
case MP_CSP_TRC_BT_1886: {
- // To build an appropriate BT.1886 transformation we need access to
- // the display's black point, so we LittleCMS' detection function.
- // Relative colorimetric is used since we want to approximate the
- // BT.1886 to the target device's actual black point even in e.g.
- // perceptual mode
- const int intent = MP_INTENT_RELATIVE_COLORIMETRIC;
- cmsCIEXYZ bp_XYZ;
- if (!cmsDetectBlackPoint(&bp_XYZ, disp_profile, intent, 0))
- return false;
-
- // Map this XYZ value back into the (linear) source space
- cmsToneCurve *linear = cmsBuildGamma(cms, 1.0);
- cmsHPROFILE rev_profile = cmsCreateRGBProfileTHR(cms, &wp_xyY, &prim_xyY,
- (cmsToneCurve*[3]){linear, linear, linear});
- cmsHPROFILE xyz_profile = cmsCreateXYZProfile();
- cmsHTRANSFORM xyz2src = cmsCreateTransformTHR(cms,
- xyz_profile, TYPE_XYZ_DBL, rev_profile, TYPE_RGB_DBL,
- intent, 0);
- cmsFreeToneCurve(linear);
- cmsCloseProfile(rev_profile);
- cmsCloseProfile(xyz_profile);
- if (!xyz2src)
- return false;
-
double src_black[3];
- cmsDoTransform(xyz2src, &bp_XYZ, src_black, 1);
- cmsDeleteTransform(xyz2src);
-
- // Contrast limiting
- if (p->opts->contrast > 0) {
+ if (p->opts->contrast < 0) {
+ // User requested infinite contrast, return 2.4 profile
+ tonecurve[0] = cmsBuildGamma(cms, 2.4);
+ break;
+ } else if (p->opts->contrast > 0) {
+ MP_VERBOSE(p, "Using specified contrast: %d\n", p->opts->contrast);
for (int i = 0; i < 3; i++)
- src_black[i] = MPMAX(src_black[i], 1.0 / p->opts->contrast);
- }
-
- // Built-in contrast failsafe
- double contrast = 3.0 / (src_black[0] + src_black[1] + src_black[2]);
- MP_VERBOSE(p, "Detected ICC profile contrast: %f\n", contrast);
- if (contrast > 100000 && !p->opts->contrast) {
- MP_WARN(p, "ICC profile detected contrast very high (>100000),"
- " falling back to contrast 1000 for sanity. Set the"
- " icc-contrast option to silence this warning.\n");
- src_black[0] = src_black[1] = src_black[2] = 1.0 / 1000;
+ src_black[i] = 1.0 / p->opts->contrast;
+ } else {
+ // To build an appropriate BT.1886 transformation we need access to
+ // the display's black point, so we use LittleCMS' detection
+ // function. Relative colorimetric is used since we want to
+ // approximate the BT.1886 to the target device's actual black
+ // point even in e.g. perceptual mode
+ const int intent = MP_INTENT_RELATIVE_COLORIMETRIC;
+ cmsCIEXYZ bp_XYZ;
+ if (!cmsDetectBlackPoint(&bp_XYZ, disp_profile, intent, 0))
+ return false;
+
+ // Map this XYZ value back into the (linear) source space
+ cmsHPROFILE rev_profile;
+ cmsToneCurve *linear = cmsBuildGamma(cms, 1.0);
+ rev_profile = cmsCreateRGBProfileTHR(cms, &wp_xyY, &prim_xyY,
+ (cmsToneCurve*[3]){linear, linear, linear});
+ cmsHPROFILE xyz_profile = cmsCreateXYZProfile();
+ cmsHTRANSFORM xyz2src = cmsCreateTransformTHR(cms,
+ xyz_profile, TYPE_XYZ_DBL, rev_profile, TYPE_RGB_DBL,
+ intent, 0);
+ cmsFreeToneCurve(linear);
+ cmsCloseProfile(rev_profile);
+ cmsCloseProfile(xyz_profile);
+ if (!xyz2src)
+ return false;
+
+ cmsDoTransform(xyz2src, &bp_XYZ, src_black, 1);
+ cmsDeleteTransform(xyz2src);
+
+ double contrast = 3.0 / (src_black[0] + src_black[1] + src_black[2]);
+ MP_VERBOSE(p, "Detected ICC profile contrast: %f\n", contrast);
}
// Build the parametric BT.1886 transfer curve, one per channel