summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-01-06 16:49:53 +0100
committerwm4 <wm4@nowhere>2015-01-06 16:51:06 +0100
commitd42d60bc1e0a1c3b472b21d3cd203279879f7d95 (patch)
tree5e3cc92bc64309acae00dc67312b56cc5873822c /video
parent5410a5b2c55b5c7d9889451c1d6e56c697325a2c (diff)
downloadmpv-d42d60bc1e0a1c3b472b21d3cd203279879f7d95.tar.bz2
mpv-d42d60bc1e0a1c3b472b21d3cd203279879f7d95.tar.xz
csputils: replace float[3][4] with a struct
Not being able to use the 3x3 part of the matrix was annoying, so split it into a float[3][3] matrix and a separate float[3] constant vector.
Diffstat (limited to 'video')
-rw-r--r--video/csputils.c124
-rw-r--r--video/csputils.h37
-rw-r--r--video/out/gl_video.c16
-rw-r--r--video/out/vo_opengl_old.c13
-rw-r--r--video/vdpau_mixer.c11
5 files changed, 100 insertions, 101 deletions
diff --git a/video/csputils.c b/video/csputils.c
index 70edbfa6a3..6e8c76f6d8 100644
--- a/video/csputils.c
+++ b/video/csputils.c
@@ -459,17 +459,17 @@ void mp_get_cms_matrix(struct mp_csp_primaries src, struct mp_csp_primaries dest
// intent = the rendering intent used to convert to the target primaries
void mp_get_xyz2rgb_coeffs(struct mp_csp_params *params,
struct mp_csp_primaries prim,
- enum mp_render_intent intent, float m[3][4])
+ enum mp_render_intent intent, struct mp_cmat *m)
{
- float tmp[3][3], brightness = params->brightness;
- mp_get_rgb2xyz_matrix(prim, tmp);
- mp_invert_matrix3x3(tmp);
+ float brightness = params->brightness;
+ mp_get_rgb2xyz_matrix(prim, m->m);
+ mp_invert_matrix3x3(m->m);
// All non-absolute mappings want to map source white to target white
if (intent != MP_INTENT_ABSOLUTE_COLORIMETRIC) {
// SMPTE 428-1 defines the calibration white point as CIE xy (0.314, 0.351)
static const struct mp_csp_col_xy smpte428 = {0.314, 0.351};
- mp_apply_chromatic_adaptation(smpte428, prim.white, tmp);
+ mp_apply_chromatic_adaptation(smpte428, prim.white, m->m);
}
// Since this outputs linear RGB rather than companded RGB, we
@@ -482,12 +482,8 @@ void mp_get_xyz2rgb_coeffs(struct mp_csp_params *params,
brightness *= brightness;
}
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++)
- m[i][j] = tmp[i][j];
-
- m[i][COL_C] = brightness;
- }
+ for (int i = 0; i < 3; i++)
+ m->c[i] = brightness;
}
/* Fill in the Y, U, V vectors of a yuv2rgb conversion matrix
@@ -510,21 +506,19 @@ void mp_get_xyz2rgb_coeffs(struct mp_csp_params *params,
* Under these conditions the given parameters lr, lg, lb uniquely
* determine the mapping of Y, U, V to R, G, B.
*/
-static void luma_coeffs(float m[3][4], float lr, float lg, float lb)
+static void luma_coeffs(struct mp_cmat *mat, float lr, float lg, float lb)
{
assert(fabs(lr+lg+lb - 1) < 1e-6);
- m[0][0] = m[1][0] = m[2][0] = 1;
- m[0][1] = 0;
- m[1][1] = -2 * (1-lb) * lb/lg;
- m[2][1] = 2 * (1-lb);
- m[0][2] = 2 * (1-lr);
- m[1][2] = -2 * (1-lr) * lr/lg;
- m[2][2] = 0;
- // Constant coefficients (m[x][3]) not set here
+ *mat = (struct mp_cmat) {
+ { {1, 0, 2 * (1-lr) },
+ {1, -2 * (1-lb) * lb/lg, -2 * (1-lr) * lr/lg },
+ {1, 2 * (1-lb), 0 } },
+ // Constant coefficients (mat->c) not set here
+ };
}
// get the coefficients of the yuv -> rgb conversion matrix
-void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
+void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, struct mp_cmat *m)
{
int colorspace = params->colorspace;
if (colorspace <= MP_CSP_AUTO || colorspace >= MP_CSP_COUNT)
@@ -543,13 +537,11 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
// If this clips on any VO, a constant 0.5 coefficient can be added
// to the chroma channels to normalize them into [0,1]. This is not
// currently needed by anything, though.
- static const float ycbcr_to_crycb[3][4] = {{0, 0, 1}, {1, 0, 0}, {0, 1, 0}};
- memcpy(m, ycbcr_to_crycb, sizeof(ycbcr_to_crycb));
+ *m = (struct mp_cmat){{{0, 0, 1}, {1, 0, 0}, {0, 1, 0}}};
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));
+ *m = (struct mp_cmat){{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}};
levels_in = -1;
break;
}
@@ -563,12 +555,11 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
break;
}
case MP_CSP_YCGCO: {
- static const float ycgco_to_rgb[3][4] = {
- {1, -1, 1},
- {1, 1, 0},
- {1, -1, -1},
+ *m = (struct mp_cmat) {
+ {{1, -1, 1},
+ {1, 1, 0},
+ {1, -1, -1}},
};
- memcpy(m, ycgco_to_rgb, sizeof(ycgco_to_rgb));
break;
}
default:
@@ -580,9 +571,9 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
float huecos = params->saturation * cos(params->hue);
float huesin = params->saturation * sin(params->hue);
for (int i = 0; i < 3; i++) {
- float u = m[i][COL_U];
- m[i][COL_U] = huecos * u - huesin * m[i][COL_V];
- m[i][COL_V] = huesin * u + huecos * m[i][COL_V];
+ float u = m->m[i][1], v = m->m[i][2];
+ m->m[i][1] = huecos * u - huesin * v;
+ m->m[i][2] = huesin * u + huecos * v;
}
assert(params->input_bits >= 8);
@@ -619,20 +610,20 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
double ymul = (rgblev.max - rgblev.min) / (yuvlev.ymax - yuvlev.ymin);
double cmul = (rgblev.max - rgblev.min) / (yuvlev.cmid - yuvlev.cmin) / 2;
for (int i = 0; i < 3; i++) {
- m[i][COL_Y] *= ymul;
- m[i][COL_U] *= cmul;
- m[i][COL_V] *= cmul;
- // Set COL_C so that Y=umin,UV=cmid maps to RGB=min (black to black)
- m[i][COL_C] = rgblev.min - m[i][COL_Y] * yuvlev.ymin
- -(m[i][COL_U] + m[i][COL_V]) * yuvlev.cmid;
+ m->m[i][0] *= ymul;
+ m->m[i][1] *= cmul;
+ m->m[i][2] *= cmul;
+ // Set c so that Y=umin,UV=cmid maps to RGB=min (black to black)
+ m->c[i] = rgblev.min - m->m[i][0] * yuvlev.ymin
+ -(m->m[i][1] + m->m[i][2]) * yuvlev.cmid;
}
// Brightness adds a constant to output R,G,B.
// Contrast scales Y around 1/2 (not 0 in this implementation).
for (int i = 0; i < 3; i++) {
- m[i][COL_C] += params->brightness;
- m[i][COL_Y] *= params->contrast;
- m[i][COL_C] += (rgblev.max-rgblev.min) * (1 - params->contrast)/2;
+ m->c[i] += params->brightness;
+ m->m[i][0] *= params->contrast;
+ m->c[i] += (rgblev.max-rgblev.min) * (1 - params->contrast)/2;
}
int in_bits = FFMAX(params->int_bits_in, 1);
@@ -640,9 +631,9 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4])
double in_scale = (1 << in_bits) - 1.0;
double out_scale = (1 << out_bits) - 1.0;
for (int i = 0; i < 3; i++) {
- m[i][COL_C] *= out_scale; // constant is 1.0
+ m->c[i] *= out_scale; // constant is 1.0
for (int x = 0; x < 3; x++)
- m[i][x] *= out_scale / in_scale;
+ m->m[i][x] *= out_scale / in_scale;
}
}
@@ -655,15 +646,17 @@ void mp_gen_yuv2rgb_map(struct mp_csp_params *params, unsigned char *map, int si
int i, j, k, l;
float step = 1.0 / size;
float y, u, v;
- float yuv2rgb[3][4];
+ struct mp_cmat yuv2rgb;
unsigned char gmaps[3][GMAP_SIZE];
mp_gen_gamma_map(gmaps[0], GMAP_SIZE, params->rgamma);
mp_gen_gamma_map(gmaps[1], GMAP_SIZE, params->ggamma);
mp_gen_gamma_map(gmaps[2], GMAP_SIZE, params->bgamma);
- mp_get_yuv2rgb_coeffs(params, yuv2rgb);
- for (i = 0; i < 3; i++)
- for (j = 0; j < 4; j++)
- yuv2rgb[i][j] *= GMAP_SIZE - 1;
+ mp_get_yuv2rgb_coeffs(params, &yuv2rgb);
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 3; j++)
+ yuv2rgb.m[i][j] *= GMAP_SIZE - 1;
+ yuv2rgb.c[i] *= GMAP_SIZE - 1;
+ }
v = 0;
for (i = -1; i <= size; i++) {
u = 0;
@@ -671,8 +664,8 @@ void mp_gen_yuv2rgb_map(struct mp_csp_params *params, unsigned char *map, int si
y = 0;
for (k = -1; k <= size; k++) {
for (l = 0; l < 3; l++) {
- float rgb = yuv2rgb[l][COL_Y] * y + yuv2rgb[l][COL_U] * u +
- yuv2rgb[l][COL_V] * v + yuv2rgb[l][COL_C];
+ float rgb = yuv2rgb.m[l][0] * y + yuv2rgb.m[l][1] * u +
+ yuv2rgb.m[l][2] * v + yuv2rgb.c[l];
*map++ = gmaps[l][av_clip(rgb, 0, GMAP_SIZE - 1)];
}
y += (k == -1 || k == size - 1) ? step / 2 : step;
@@ -741,42 +734,31 @@ int mp_csp_equalizer_set(struct mp_csp_equalizer *eq, const char *property,
return 1;
}
-void mp_invert_yuv2rgb(float out[3][4], float in[3][4])
+void mp_invert_yuv2rgb(struct mp_cmat *out, struct mp_cmat *in)
{
- float tmp[3][3];
-
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++)
- tmp[i][j] = in[i][j];
- }
-
- mp_invert_matrix3x3(tmp);
-
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++)
- out[i][j] = tmp[i][j];
- }
+ *out = *in;
+ mp_invert_matrix3x3(out->m);
// fix the constant coefficient
// rgb = M * yuv + C
// M^-1 * rgb = yuv + M^-1 * C
// yuv = M^-1 * rgb - M^-1 * C
// ^^^^^^^^^^
- out[0][3] = -(out[0][0] * in[0][3] + out[0][1] * in[1][3] + out[0][2] * in[2][3]);
- out[1][3] = -(out[1][0] * in[0][3] + out[1][1] * in[1][3] + out[1][2] * in[2][3]);
- out[2][3] = -(out[2][0] * in[0][3] + out[2][1] * in[1][3] + out[2][2] * in[2][3]);
+ out->c[0] = -(out->m[0][0] * in->c[0] + out->m[0][1] * in->c[1] + out->m[0][2] * in->c[2]);
+ out->c[1] = -(out->m[1][0] * in->c[0] + out->m[1][1] * in->c[1] + out->m[1][2] * in->c[2]);
+ out->c[2] = -(out->m[2][0] * in->c[0] + out->m[2][1] * in->c[1] + out->m[2][2] * in->c[2]);
}
// Multiply the color in c with the given matrix.
// c is {R, G, B} or {Y, U, V} (depending on input/output and matrix).
// Output is clipped to the given number of bits.
-void mp_map_int_color(float matrix[3][4], int clip_bits, int c[3])
+void mp_map_int_color(struct mp_cmat *matrix, int clip_bits, int c[3])
{
int in[3] = {c[0], c[1], c[2]};
for (int i = 0; i < 3; i++) {
- double val = matrix[i][3];
+ double val = matrix->c[i];
for (int x = 0; x < 3; x++)
- val += matrix[i][x] * in[x];
+ val += matrix->m[i][x] * in[x];
int ival = lrint(val);
c[i] = av_clip(ival, 0, (1 << clip_bits) - 1);
}
diff --git a/video/csputils.h b/video/csputils.h
index 51de50c4b6..8e8d18e7df 100644
--- a/video/csputils.h
+++ b/video/csputils.h
@@ -214,28 +214,41 @@ int mp_chroma_location_to_av(enum mp_chroma_location mploc);
void mp_get_chroma_location(enum mp_chroma_location loc, int *x, int *y);
void mp_gen_gamma_map(unsigned char *map, int size, float gamma);
-#define ROW_R 0
-#define ROW_G 1
-#define ROW_B 2
-#define COL_Y 0
-#define COL_U 1
-#define COL_V 2
-#define COL_C 3
+
struct mp_csp_primaries mp_get_csp_primaries(enum mp_csp_prim csp);
-void mp_apply_chromatic_adaptation(struct mp_csp_col_xy src, struct mp_csp_col_xy dest, float m[3][3]);
+/* Color conversion matrix: RGB = m * YUV + c
+ * m is in row-major matrix, with m[row][col], e.g.:
+ * [ a11 a12 a13 ] float m[3][3] = { { a11, a12, a13 },
+ * [ a21 a22 a23 ] { a21, a22, a23 },
+ * [ a31 a32 a33 ] { a31, a32, a33 } };
+ * This is accessed as e.g.: m[2-1][1-1] = a21
+ * In particular, each row contains all the coefficients for one of R, G, B,
+ * while each column contains all the coefficients for one of Y, U, V:
+ * m[r,g,b][y,u,v] = ...
+ * The matrix could also be viewed as group of 3 vectors, e.g. the 1st column
+ * is the Y vector (1, 1, 1), the 2nd is the U vector, the 3rd the V vector.
+ * The matrix might also be used for other conversions and colorspaces.
+ */
+struct mp_cmat {
+ float m[3][3];
+ float c[3];
+};
+
+void mp_apply_chromatic_adaptation(struct mp_csp_col_xy src,
+ struct mp_csp_col_xy dest, float m[3][3]);
void mp_get_cms_matrix(struct mp_csp_primaries src, struct mp_csp_primaries dest,
enum mp_render_intent intent, float cms_matrix[3][3]);
void mp_get_rgb2xyz_matrix(struct mp_csp_primaries space, float m[3][3]);
void mp_get_xyz2rgb_coeffs(struct mp_csp_params *params, struct mp_csp_primaries prim,
- enum mp_render_intent intent, float xyz2rgb[3][4]);
-void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float yuv2rgb[3][4]);
+ enum mp_render_intent intent, struct mp_cmat *xyz2rgb);
+void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, struct mp_cmat *yuv2rgb);
void mp_gen_yuv2rgb_map(struct mp_csp_params *params, uint8_t *map, int size);
void mp_mul_matrix3x3(float a[3][3], float b[3][3]);
void mp_invert_matrix3x3(float m[3][3]);
-void mp_invert_yuv2rgb(float out[3][4], float in[3][4]);
-void mp_map_int_color(float matrix[3][4], int clip_bits, int c[3]);
+void mp_invert_yuv2rgb(struct mp_cmat *out, struct mp_cmat *in);
+void mp_map_int_color(struct mp_cmat *matrix, int clip_bits, int c[3]);
#endif /* MPLAYER_CSPUTILS_H */
diff --git a/video/out/gl_video.c b/video/out/gl_video.c
index 672fb5dafb..88de5eeffb 100644
--- a/video/out/gl_video.c
+++ b/video/out/gl_video.c
@@ -661,24 +661,20 @@ static void update_uniforms(struct gl_video *p, GLuint program)
loc = gl->GetUniformLocation(program, "colormatrix");
if (loc >= 0) {
- float m[3][4] = {{0}};
+ struct mp_cmat m = {{{0}}};
if (p->image_desc.flags & MP_IMGFLAG_XYZ) {
// Hard-coded as relative colorimetric for now, since this transforms
// from the source file's D55 material to whatever color space our
// projector/display lives in, which should be D55 for a proper
// home cinema setup either way.
- mp_get_xyz2rgb_coeffs(&cparams, p->csp_src, MP_INTENT_RELATIVE_COLORIMETRIC, m);
+ mp_get_xyz2rgb_coeffs(&cparams, p->csp_src,
+ MP_INTENT_RELATIVE_COLORIMETRIC, &m);
} else {
- mp_get_yuv2rgb_coeffs(&cparams, m);
+ mp_get_yuv2rgb_coeffs(&cparams, &m);
}
- float transposed[3][3];
- for (int a = 0; a < 3; a++) {
- for (int b = 0; b < 3; b++)
- transposed[a][b] = m[b][a];
- }
- gl->UniformMatrix3fv(loc, 1, GL_FALSE, &transposed[0][0]);
+ gl->UniformMatrix3fv(loc, 1, GL_TRUE, &m.m[0][0]);
loc = gl->GetUniformLocation(program, "colormatrix_c");
- gl->Uniform3f(loc, m[0][3], m[1][3], m[2][3]);
+ gl->Uniform3f(loc, m.c[0], m.c[1], m.c[2]);
}
gl->Uniform1f(gl->GetUniformLocation(program, "input_gamma"),
diff --git a/video/out/vo_opengl_old.c b/video/out/vo_opengl_old.c
index 6c9bfb62a0..f39f5709cf 100644
--- a/video/out/vo_opengl_old.c
+++ b/video/out/vo_opengl_old.c
@@ -1070,7 +1070,7 @@ static void glSetupYUVFragprog(struct vo *vo, GL *gl,
GLint i;
// this is the conversion matrix, with y, u, v factors
// for red, green, blue and the constant offsets
- float yuv2rgb[3][4];
+ struct mp_cmat yuv2rgb;
int noise = params->noise_strength != 0;
create_conv_textures(vo, gl, params, &cur_texu, conv_texs);
create_scaler_textures(vo, gl, YUV_LUM_SCALER(type), &cur_texu, lum_scale_texs);
@@ -1102,7 +1102,7 @@ static void glSetupYUVFragprog(struct vo *vo, GL *gl,
add_scaler(YUV_CHROM_SCALER(type), prog,
chrom_scale_texs, '2', 'b', rect, params->chrom_texw,
params->chrom_texh, params->filter_strength);
- mp_get_yuv2rgb_coeffs(&params->csp_params, yuv2rgb);
+ mp_get_yuv2rgb_coeffs(&params->csp_params, &yuv2rgb);
switch (YUV_CONVERSION(type)) {
case YUV_CONVERSION_FRAGMENT:
append_template(prog, yuv_prog_template);
@@ -1121,11 +1121,14 @@ static void glSetupYUVFragprog(struct vo *vo, GL *gl,
break;
}
for (int r = 0; r < 3; r++) {
- for (int c = 0; c < 4; c++) {
- // "cmRC"
+ for (int c = 0; c < 3; c++) {
+ // "mRC"
char var[] = { 'c', 'm', '1' + r, '1' + c, '\0' };
- replace_var_float(prog, var, yuv2rgb[r][c]);
+ replace_var_float(prog, var, yuv2rgb.m[r][c]);
}
+ // "mR4"
+ char var[] = { 'c', 'm', '1' + r, '4', '\0' };
+ replace_var_float(prog, var, yuv2rgb.c[r]);
}
replace_var_float(prog, "gamma_r", (float)1.0 / params->csp_params.rgamma);
replace_var_float(prog, "gamma_g", (float)1.0 / params->csp_params.ggamma);
diff --git a/video/vdpau_mixer.c b/video/vdpau_mixer.c
index 182e1fd40a..d3a4a02457 100644
--- a/video/vdpau_mixer.c
+++ b/video/vdpau_mixer.c
@@ -192,14 +192,19 @@ static int create_vdp_mixer(struct mp_vdpau_mixer *mixer)
if (!opts->chroma_deint)
SET_VIDEO_ATTR(SKIP_CHROMA_DEINTERLACE, uint8_t, 1);
- // VdpCSCMatrix happens to be compatible with mpv's CSC matrix type
- // both are float[3][4]
+ struct mp_cmat yuv2rgb;
VdpCSCMatrix matrix;
struct mp_csp_params cparams = MP_CSP_PARAMS_DEFAULTS;
mp_csp_set_image_params(&cparams, &mixer->image_params);
mp_csp_copy_equalizer_values(&cparams, &mixer->video_eq);
- mp_get_yuv2rgb_coeffs(&cparams, matrix);
+ mp_get_yuv2rgb_coeffs(&cparams, &yuv2rgb);
+
+ for (int r = 0; r < 3; r++) {
+ for (int c = 0; c < 3; c++)
+ matrix[r][c] = yuv2rgb.m[r][c];
+ matrix[r][3] = yuv2rgb.c[r];
+ }
set_video_attribute(mixer, VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX,
&matrix, "CSC matrix");