summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/vf.rst1
-rw-r--r--DOCS/man/vo.rst2
-rw-r--r--video/csputils.c7
-rw-r--r--video/csputils.h1
-rw-r--r--video/out/opengl/video.c18
-rw-r--r--video/out/opengl/video_shaders.c23
-rw-r--r--wscript7
7 files changed, 49 insertions, 10 deletions
diff --git a/DOCS/man/vf.rst b/DOCS/man/vf.rst
index b4e4438f78..7f60da9385 100644
--- a/DOCS/man/vf.rst
+++ b/DOCS/man/vf.rst
@@ -311,6 +311,7 @@ Available filters are:
:gamma2.8: Pure power curve (gamma 2.8)
:prophoto: ProPhoto RGB (ROMM) curve
:st2084: SMPTE ST2084 (HDR) curve
+ :std-b67: ARIB STD-B67 (Hybrid Log-gamma) curve
``<peak>``
Reference peak illumination for the video file. This is mostly
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst
index bdc317fc8f..a4d42e48c3 100644
--- a/DOCS/man/vo.rst
+++ b/DOCS/man/vo.rst
@@ -1003,6 +1003,8 @@ Available video output drivers are:
ProPhoto RGB (ROMM)
st2084
SMPTE ST2084 (HDR) curve, PQ OETF
+ std-b67
+ ARIB STD-B67 (Hybrid Log-gamma) curve, also known as BBC/NHK HDR
``target-brightness=<1..100000>``
Specifies the display's approximate brightness in cd/m^2. When playing
diff --git a/video/csputils.c b/video/csputils.c
index ffa1f82a6d..e9e6772ac8 100644
--- a/video/csputils.c
+++ b/video/csputils.c
@@ -78,6 +78,7 @@ const struct m_opt_choice_alternatives mp_csp_trc_names[] = {
{"gamma2.8", MP_CSP_TRC_GAMMA28},
{"prophoto", MP_CSP_TRC_PRO_PHOTO},
{"st2084", MP_CSP_TRC_SMPTE_ST2084},
+ {"std-b67", MP_CSP_TRC_ARIB_STD_B67},
{0}
};
@@ -171,8 +172,9 @@ enum mp_csp_trc avcol_trc_to_mp_csp_trc(int avtrc)
case AVCOL_TRC_LINEAR: return MP_CSP_TRC_LINEAR;
case AVCOL_TRC_GAMMA22: return MP_CSP_TRC_GAMMA22;
case AVCOL_TRC_GAMMA28: return MP_CSP_TRC_GAMMA28;
-#if HAVE_AVUTIL_ST2084
+#if HAVE_AVUTIL_HDR
case AVCOL_TRC_SMPTEST2084: return MP_CSP_TRC_SMPTE_ST2084;
+ case AVCOL_TRC_ARIB_STD_B67: return MP_CSP_TRC_ARIB_STD_B67;
#endif
default: return MP_CSP_TRC_AUTO;
}
@@ -222,8 +224,9 @@ int mp_csp_trc_to_avcol_trc(enum mp_csp_trc trc)
case MP_CSP_TRC_LINEAR: return AVCOL_TRC_LINEAR;
case MP_CSP_TRC_GAMMA22: return AVCOL_TRC_GAMMA22;
case MP_CSP_TRC_GAMMA28: return AVCOL_TRC_GAMMA28;
-#if HAVE_AVUTIL_ST2084
+#if HAVE_AVUTIL_HDR
case MP_CSP_TRC_SMPTE_ST2084: return AVCOL_TRC_SMPTEST2084;
+ case MP_CSP_TRC_ARIB_STD_B67: return AVCOL_TRC_ARIB_STD_B67;
#endif
default: return AVCOL_TRC_UNSPECIFIED;
}
diff --git a/video/csputils.h b/video/csputils.h
index 19dd88f145..f64c42e6c8 100644
--- a/video/csputils.h
+++ b/video/csputils.h
@@ -79,6 +79,7 @@ enum mp_csp_trc {
MP_CSP_TRC_GAMMA28,
MP_CSP_TRC_PRO_PHOTO,
MP_CSP_TRC_SMPTE_ST2084,
+ MP_CSP_TRC_ARIB_STD_B67,
MP_CSP_TRC_COUNT
};
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index 4387208ead..6fd92ddb29 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -2172,12 +2172,15 @@ static void pass_colormanage(struct gl_video *p, float peak_src,
enum mp_csp_prim prim_orig = p->image_params.primaries;
enum mp_csp_trc trc_orig = p->image_params.gamma;
- // One exception: SMPTE ST.2084 is not implemented by LittleCMS
- // for technical limitation reasons, so we use a gamma 2.2 input curve
- // here instead. We could pick any value we want here, the difference
- // is just coding efficiency.
- if (trc_orig == MP_CSP_TRC_SMPTE_ST2084)
+ // One exception: HDR is not implemented by LittleCMS for technical
+ // limitation reasons, so we use a gamma 2.2 input curve here instead.
+ // We could pick any value we want here, the difference is just coding
+ // efficiency.
+ if (trc_orig == MP_CSP_TRC_SMPTE_ST2084 ||
+ trc_orig == MP_CSP_TRC_ARIB_STD_B67)
+ {
trc_orig = MP_CSP_TRC_GAMMA22;
+ }
if (gl_video_get_lut3d(p, prim_orig, trc_orig)) {
prim_dst = prim_orig;
@@ -2216,6 +2219,11 @@ static void pass_colormanage(struct gl_video *p, float peak_src,
// If the source has no information known, it's display-referred
// (and should be treated relative to the specified desired peak_dst)
peak_src = peak_dst;
+
+ // Exception: ARIB STD-B67's nominal peak is exactly 12 times the
+ // target's reference peak
+ if (trc_src == MP_CSP_TRC_ARIB_STD_B67)
+ peak_src = 12 * peak_dst;
}
// All operations from here on require linear light as a starting point,
diff --git a/video/out/opengl/video_shaders.c b/video/out/opengl/video_shaders.c
index 1f37f4fed1..4a15b6ceed 100644
--- a/video/out/opengl/video_shaders.c
+++ b/video/out/opengl/video_shaders.c
@@ -227,6 +227,11 @@ static const float HDR_M1 = 2610./4096 * 1./4,
HDR_C2 = 2413./4096 * 32,
HDR_C3 = 2392./4096 * 32;
+// Common constants for ARIB STD-B67 (Hybrid Log-gamma)
+static const float B67_A = 0.17883277,
+ B67_B = 0.28466892,
+ B67_C = 0.55991073;
+
// Linearize (expand), given a TRC as input
void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
{
@@ -265,6 +270,17 @@ void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
HDR_C1, HDR_C2, HDR_C3);
GLSLF("color.rgb = pow(color.rgb, vec3(1.0/%f));\n", HDR_M1);
break;
+ case MP_CSP_TRC_ARIB_STD_B67:
+ GLSLF("color.rgb = mix(vec3(4.0) * color.rgb * color.rgb,\n"
+ " exp((color.rgb - vec3(%f)) / vec3(%f)) + vec3(%f),\n"
+ " lessThan(vec3(0.5), color.rgb));\n",
+ B67_C, B67_A, B67_B);
+ // Since the ARIB function's signal value of 1.0 corresponds to
+ // a peak of 12.0, we need to renormalize to prevent GL textures
+ // from clipping. (In general, mpv's internal conversions always
+ // assume 1.0 is the maximum brightness, not the reference peak)
+ GLSL(color.rgb /= vec3(12.0);)
+ break;
default:
abort();
}
@@ -308,6 +324,13 @@ void pass_delinearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
HDR_C1, HDR_C2, HDR_C3);
GLSLF("color.rgb = pow(color.rgb, vec3(%f));\n", HDR_M2);
break;
+ case MP_CSP_TRC_ARIB_STD_B67:
+ GLSL(color.rgb *= vec3(12.0);)
+ GLSLF("color.rgb = mix(vec3(0.5) * sqrt(color.rgb),\n"
+ " vec3(%f) * log(color.rgb - vec3(%f)) + vec3(%f),\n"
+ " lessThan(vec3(1.0), color.rgb));\n",
+ B67_A, B67_B, B67_C);
+ break;
default:
abort();
}
diff --git a/wscript b/wscript
index 1915f7cd67..e29d1ab403 100644
--- a/wscript
+++ b/wscript
@@ -498,10 +498,11 @@ FFmpeg/Libav libraries. You need at least {0}. Aborting.".format(libav_versions_
'(void)offsetof(AVFrame, hw_frames_ctx)',
use='libav'),
}, {
- 'name': 'avutil-st2084',
- 'desc': 'libavutil AVCOL_TRC_SMPTEST2084',
+ 'name': 'avutil-hdr',
+ 'desc': 'libavutil HDR TRCs',
'func': check_statement('libavutil/pixfmt.h',
- 'AVCOL_TRC_SMPTEST2084',
+ 'AVCOL_TRC_SMPTEST2084,'
+ 'AVCOL_TRC_ARIB_STD_B67',
use='libav'),
}
]