summaryrefslogtreecommitdiffstats
path: root/video/csputils.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-05-01 23:59:00 +0200
committerwm4 <wm4@nowhere>2013-05-04 01:32:50 +0200
commit872aefaa1521a8cf70c6e14f3356e9d00ed7efa3 (patch)
tree4f04a63b9c31d71a326a112004e8d8e213e739e4 /video/csputils.c
parent16d40828aecf4028acadeeecaf0294756298f970 (diff)
downloadmpv-872aefaa1521a8cf70c6e14f3356e9d00ed7efa3.tar.bz2
mpv-872aefaa1521a8cf70c6e14f3356e9d00ed7efa3.tar.xz
vo_opengl: XYZ input support
Useful for the j2k decoder. Matrix taken from http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html (XYZ to sRGB, whitepoint D65) Gamma conversion follows what libswscale does (2.6 in, 2.2 out). If linear RGB is used internally for scaling, the gamma conversion will be undone by setting the exponent to 1. Unfortunately, the two gamma values don't compensate each others exactly (2.2 vs. 1/0.45=2.22...), so output is a little bit incorrect in sRGB or color-managed mode. But for now try hard to match libswscale output, which may or may not be correct.
Diffstat (limited to 'video/csputils.c')
-rw-r--r--video/csputils.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/video/csputils.c b/video/csputils.c
index 23eb099f69..e7ea5a388b 100644
--- a/video/csputils.c
+++ b/video/csputils.c
@@ -40,6 +40,7 @@ char * const mp_csp_names[MP_CSP_COUNT] = {
"BT.709 (HD)",
"SMPTE-240M",
"RGB",
+ "XYZ",
};
char * const mp_csp_equalizer_names[MP_CSP_EQ_COUNT] = {
@@ -165,10 +166,30 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
int format = params->colorspace.format;
if (format <= MP_CSP_AUTO || format >= MP_CSP_COUNT)
format = MP_CSP_BT_601;
+ int levels_in = params->colorspace.levels_in;
+ if (levels_in <= MP_CSP_LEVELS_AUTO || levels_in >= MP_CSP_LEVELS_COUNT)
+ levels_in = MP_CSP_LEVELS_TV;
+
switch (format) {
case MP_CSP_BT_601: luma_coeffs(m, 0.299, 0.587, 0.114 ); break;
case MP_CSP_BT_709: luma_coeffs(m, 0.2126, 0.7152, 0.0722); break;
case MP_CSP_SMPTE_240M: luma_coeffs(m, 0.2122, 0.7013, 0.0865); break;
+ case MP_CSP_RGB: {
+ static const float ident[3][4] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
+ memcpy(m, ident, sizeof(ident));
+ levels_in = -1;
+ break;
+ }
+ case MP_CSP_XYZ: {
+ static const float xyz_to_rgb[3][4] = {
+ {3.2404542, -1.5371385, -0.4985314},
+ {-0.9692660, 1.8760108, 0.0415560},
+ {0.0556434, -0.2040259, 1.0572252},
+ };
+ memcpy(m, xyz_to_rgb, sizeof(xyz_to_rgb));
+ levels_in = -1;
+ break;
+ }
default:
abort();
};
@@ -183,9 +204,6 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
m[i][COL_V] = huesin * u + huecos * m[i][COL_V];
}
- int levels_in = params->colorspace.levels_in;
- if (levels_in <= MP_CSP_LEVELS_AUTO || levels_in >= MP_CSP_LEVELS_COUNT)
- levels_in = MP_CSP_LEVELS_TV;
assert(params->input_bits >= 8);
assert(params->texture_bits >= params->input_bits);
double s = (1 << params->input_bits-8) / ((1<<params->texture_bits)-1.);
@@ -193,10 +211,12 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
struct yuvlevels { double ymin, ymax, cmin, cmid; }
yuvlim = { 16*s, 235*s, 16*s, 128*s },
yuvfull = { 0*s, 255*s, 1*s, 128*s }, // '1' for symmetry around 128
+ anyfull = { 0*s, 255*s, -255*s/2, 0 },
yuvlev;
switch (levels_in) {
case MP_CSP_LEVELS_TV: yuvlev = yuvlim; break;
case MP_CSP_LEVELS_PC: yuvlev = yuvfull; break;
+ case -1: yuvlev = anyfull; break;
default:
abort();
}