diff options
Diffstat (limited to 'libvo/csputils.c')
-rw-r--r-- | libvo/csputils.c | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/libvo/csputils.c b/libvo/csputils.c index ed74b9ae74..23eb099f69 100644 --- a/libvo/csputils.c +++ b/libvo/csputils.c @@ -3,6 +3,8 @@ * * Copyleft (C) 2009 Reimar Döffinger <Reimar.Doeffinger@gmx.de> * + * mp_invert_yuv2rgb based on DarkPlaces engine, original code (GPL2 or later) + * * This file is part of MPlayer. * * MPlayer is free software; you can redistribute it and/or modify @@ -37,6 +39,7 @@ char * const mp_csp_names[MP_CSP_COUNT] = { "BT.601 (SD)", "BT.709 (HD)", "SMPTE-240M", + "RGB", }; char * const mp_csp_equalizer_names[MP_CSP_EQ_COUNT] = { @@ -54,6 +57,7 @@ enum mp_csp avcol_spc_to_mp_csp(enum AVColorSpace colorspace) case AVCOL_SPC_BT470BG: return MP_CSP_BT_601; case AVCOL_SPC_SMPTE170M: return MP_CSP_BT_601; case AVCOL_SPC_SMPTE240M: return MP_CSP_SMPTE_240M; + case AVCOL_SPC_RGB: return MP_CSP_RGB; default: return MP_CSP_AUTO; } } @@ -73,7 +77,8 @@ enum AVColorSpace mp_csp_to_avcol_spc(enum mp_csp colorspace) case MP_CSP_BT_709: return AVCOL_SPC_BT709; case MP_CSP_BT_601: return AVCOL_SPC_BT470BG; case MP_CSP_SMPTE_240M: return AVCOL_SPC_SMPTE240M; - default: return AVCOL_SPC_RGB; + case MP_CSP_RGB: return AVCOL_SPC_RGB; + default: return AVCOL_SPC_UNSPECIFIED; } } @@ -228,6 +233,16 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4]) m[i][COL_Y] *= params->contrast; m[i][COL_C] += (rgblev.max-rgblev.min) * (1 - params->contrast)/2; } + + int in_bits = FFMAX(params->int_bits_in, 1); + int out_bits = FFMAX(params->int_bits_out, 1); + 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 + for (int x = 0; x < 3; x++) + m[i][x] *= out_scale / in_scale; + } } //! size of gamma map use to avoid slow exp function in gen_yuv2rgb_map @@ -317,3 +332,60 @@ 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]) +{ + float m00 = in[0][0], m01 = in[0][1], m02 = in[0][2], m03 = in[0][3], + m10 = in[1][0], m11 = in[1][1], m12 = in[1][2], m13 = in[1][3], + m20 = in[2][0], m21 = in[2][1], m22 = in[2][2], m23 = in[2][3]; + + // calculate the adjoint + out[0][0] = (m11 * m22 - m21 * m12); + out[0][1] = -(m01 * m22 - m21 * m02); + out[0][2] = (m01 * m12 - m11 * m02); + out[1][0] = -(m10 * m22 - m20 * m12); + out[1][1] = (m00 * m22 - m20 * m02); + out[1][2] = -(m00 * m12 - m10 * m02); + out[2][0] = (m10 * m21 - m20 * m11); + out[2][1] = -(m00 * m21 - m20 * m01); + out[2][2] = (m00 * m11 - m10 * m01); + + // calculate the determinant (as inverse == 1/det * adjoint, + // adjoint * m == identity * det, so this calculates the det) + float det = m00 * out[0][0] + m10 * out[0][1] + m20 * out[0][2]; + det = 1.0f / det; + + out[0][0] *= det; + out[0][1] *= det; + out[0][2] *= det; + out[1][0] *= det; + out[1][1] *= det; + out[1][2] *= det; + out[2][0] *= det; + out[2][1] *= det; + out[2][2] *= det; + + // 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] * m03 + out[0][1] * m13 + out[0][2] * m23); + out[1][3] = -(out[1][0] * m03 + out[1][1] * m13 + out[1][2] * m23); + out[2][3] = -(out[2][0] * m03 + out[2][1] * m13 + out[2][2] * m23); +} + +// 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]) +{ + int in[3] = {c[0], c[1], c[2]}; + for (int i = 0; i < 3; i++) { + double val = matrix[i][3]; + for (int x = 0; x < 3; x++) + val += matrix[i][x] * in[x]; + int ival = lrint(val); + c[i] = av_clip(ival, 0, (1 << clip_bits) - 1); + } +} |