summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorNiklas Haas <git@nand.wakku.to>2016-06-26 19:28:06 +0200
committerwm4 <wm4@nowhere>2016-06-28 19:48:29 +0200
commitf3b6966d14e8cb34477474b85c83beb46e542e70 (patch)
tree23b0e2c0fd892c5d57a7b3ca73805cf31b8e6fad /video
parent740fdc139fae87144deb3cfe5897649ba2571b27 (diff)
downloadmpv-f3b6966d14e8cb34477474b85c83beb46e542e70.tar.bz2
mpv-f3b6966d14e8cb34477474b85c83beb46e542e70.tar.xz
vo_opengl: implement the Panasonic V-Log function
User request and not that hard. Closes #3157. Note that FFmpeg doesn't support this and there's no signalling in HEVC etc., so the only way users can access it is by using vf_format manually. Mind: This encoding uses full range values, not TV range.
Diffstat (limited to 'video')
-rw-r--r--video/csputils.c1
-rw-r--r--video/csputils.h1
-rw-r--r--video/mp_image.c9
-rw-r--r--video/out/opengl/video.c7
-rw-r--r--video/out/opengl/video_shaders.c24
5 files changed, 39 insertions, 3 deletions
diff --git a/video/csputils.c b/video/csputils.c
index b85b1f28f2..65b26acb3a 100644
--- a/video/csputils.c
+++ b/video/csputils.c
@@ -80,6 +80,7 @@ const struct m_opt_choice_alternatives mp_csp_trc_names[] = {
{"prophoto", MP_CSP_TRC_PRO_PHOTO},
{"st2084", MP_CSP_TRC_SMPTE_ST2084},
{"std-b67", MP_CSP_TRC_ARIB_STD_B67},
+ {"v-log", MP_CSP_TRC_V_LOG},
{0}
};
diff --git a/video/csputils.h b/video/csputils.h
index 100e3c13d9..90c5483a05 100644
--- a/video/csputils.h
+++ b/video/csputils.h
@@ -81,6 +81,7 @@ enum mp_csp_trc {
MP_CSP_TRC_PRO_PHOTO,
MP_CSP_TRC_SMPTE_ST2084,
MP_CSP_TRC_ARIB_STD_B67,
+ MP_CSP_TRC_V_LOG,
MP_CSP_TRC_COUNT
};
diff --git a/video/mp_image.c b/video/mp_image.c
index d5b97481e8..0b46f947bc 100644
--- a/video/mp_image.c
+++ b/video/mp_image.c
@@ -611,8 +611,13 @@ void mp_image_params_guess_csp(struct mp_image_params *params)
}
if (params->colorspace == MP_CSP_AUTO)
params->colorspace = mp_csp_guess_colorspace(params->w, params->h);
- if (params->colorlevels == MP_CSP_LEVELS_AUTO)
- params->colorlevels = MP_CSP_LEVELS_TV;
+ if (params->colorlevels == MP_CSP_LEVELS_AUTO) {
+ if (params->gamma == MP_CSP_TRC_V_LOG) {
+ params->colorlevels = MP_CSP_LEVELS_PC;
+ } else {
+ params->colorlevels = MP_CSP_LEVELS_TV;
+ }
+ }
if (params->primaries == MP_CSP_PRIM_AUTO) {
// Guess based on the colormatrix as a first priority
if (params->colorspace == MP_CSP_BT_2020_NC ||
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index 6fd92ddb29..a870fe0e4f 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -2177,7 +2177,8 @@ static void pass_colormanage(struct gl_video *p, float peak_src,
// 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_ARIB_STD_B67 ||
+ trc_orig == MP_CSP_TRC_V_LOG)
{
trc_orig = MP_CSP_TRC_GAMMA22;
}
@@ -2224,6 +2225,10 @@ static void pass_colormanage(struct gl_video *p, float peak_src,
// target's reference peak
if (trc_src == MP_CSP_TRC_ARIB_STD_B67)
peak_src = 12 * peak_dst;
+
+ // Similar deal for V-Log
+ if (trc_src == MP_CSP_TRC_V_LOG)
+ peak_src = 46.0855 * 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 4a15b6ceed..7b736f1d5d 100644
--- a/video/out/opengl/video_shaders.c
+++ b/video/out/opengl/video_shaders.c
@@ -232,6 +232,12 @@ static const float B67_A = 0.17883277,
B67_B = 0.28466892,
B67_C = 0.55991073;
+// Common constants for Panasonic V-Log
+static const float VLOG_B = 0.00873,
+ VLOG_C = 0.241514,
+ VLOG_D = 0.598206,
+ VLOG_R = 46.085527; // nominal peak
+
// Linearize (expand), given a TRC as input
void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
{
@@ -281,6 +287,16 @@ void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
// assume 1.0 is the maximum brightness, not the reference peak)
GLSL(color.rgb /= vec3(12.0);)
break;
+ case MP_CSP_TRC_V_LOG:
+ GLSLF("color.rgb = mix((color.rgb - vec3(0.125)) / vec3(5.6), \n"
+ " pow(vec3(10.0), (color.rgb - vec3(%f)) / vec3(%f)) \n"
+ " - vec3(%f), \n"
+ " lessThanEqual(vec3(0.181), color.rgb)); \n",
+ VLOG_D, VLOG_C, VLOG_B);
+ // Same deal as with the B67 function, renormalize to texture range
+ GLSLF("color.rgb /= vec3(%f);\n", VLOG_R);
+ GLSL(color.rgb = clamp(color.rgb, 0.0, 1.0);)
+ break;
default:
abort();
}
@@ -331,6 +347,14 @@ void pass_delinearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
" lessThan(vec3(1.0), color.rgb));\n",
B67_A, B67_B, B67_C);
break;
+ case MP_CSP_TRC_V_LOG:
+ GLSLF("color.rgb *= vec3(%f);\n", VLOG_R);
+ GLSLF("color.rgb = mix(vec3(5.6) * color.rgb + vec3(0.125), \n"
+ " vec3(%f) * log(color.rgb + vec3(%f)) \n"
+ " + vec3(%f), \n"
+ " lessThanEqual(vec3(0.01), color.rgb)); \n",
+ VLOG_C / M_LN10, VLOG_B, VLOG_D);
+ break;
default:
abort();
}