Mercurial > mplayer.hg
changeset 18655:6aa0b26d584b
Add yuv to rgb conversion using a 3D lookup texture
author | reimar |
---|---|
date | Thu, 08 Jun 2006 19:02:56 +0000 |
parents | 9fb5e9cdcae8 |
children | e30061e7e1f8 |
files | DOCS/man/en/mplayer.1 libvo/gl_common.c libvo/gl_common.h |
diffstat | 3 files changed, 84 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/DOCS/man/en/mplayer.1 Thu Jun 08 18:56:33 2006 +0000 +++ b/DOCS/man/en/mplayer.1 Thu Jun 08 19:02:56 2006 +0000 @@ -3076,6 +3076,12 @@ At least three texture units are needed. Provides saturation and hue control. This method is fast but inexact. +.br +6: Use a 3D texture to do conversion via lookup. +Needs the GL_ARB_fragment_program extension and at least four texture units. +Provides brightness, contrast, saturation, hue and gamma control. +Gamma can also be set independently for red, green and blue. +Speed depends more on GPU memory bandwidth than other methods. .RE .IPs [l|c]scaler=<n> Select the scaling function to use (seperately for luma and chroma).
--- a/libvo/gl_common.c Thu Jun 08 18:56:33 2006 +0000 +++ b/libvo/gl_common.c Thu Jun 08 19:02:56 2006 +0000 @@ -723,6 +723,10 @@ "TEX result.color.b, res.baaa, texture[%c], 2D;" "END"; +static const char *yuv_lookup3d_prog_template = + "TEX result.color, yuv, texture[%c], 3D;" + "END"; + static void create_scaler_textures(int scaler, int *texu, char *texs) { switch (scaler) { case YUV_SCALER_BILIN: @@ -737,10 +741,50 @@ } } +static void gen_yuv2rgb_map(unsigned char *map, int size, float brightness, + float contrast, float uvcos, float uvsin, + float rgamma, float ggamma, float bgamma) { + int i, j, k; + float step = 1.0 / size; + float y, u, v, u_, v_; + float r, g, b; + v = -0.5; + for (i = -1; i <= size; i++) { + u = -0.5; + for (j = -1; j <= size; j++) { + y = -(16.0 / 255.0); + for (k = -1; k <= size; k++) { + u_ = uvcos * u + uvsin * v; + v_ = uvcos * v + uvsin * u; + r = 1.164 * y + 1.596 * v_; + g = 1.164 * y - 0.391 * u_ - 0.813 * v_; + b = 1.164 * y + 2.018 * u_ ; + r = pow(contrast * (r - 0.5) + 0.5 + brightness, 1.0 / rgamma); + g = pow(contrast * (g - 0.5) + 0.5 + brightness, 1.0 / ggamma); + b = pow(contrast * (b - 0.5) + 0.5 + brightness, 1.0 / bgamma); + if (r > 1) r = 1; + if (r < 0) r = 0; + if (g > 1) g = 1; + if (g < 0) g = 0; + if (b > 1) b = 1; + if (b < 0) b = 0; + *map++ = 255 * r; + *map++ = 255 * g; + *map++ = 255 * b; + y += (k == -1 || k == size - 1) ? step / 2 : step; + } + u += (j == -1 || j == size - 1) ? step / 2 : step; + } + v += (i == -1 || i == size - 1) ? step / 2 : step; + } +} + static void gen_gamma_map(unsigned char *map, int size, float gamma); //! resolution of texture for gamma lookup table #define LOOKUP_RES 512 +//! resolution for 3D yuv->rgb conversion lookup table +#define LOOKUP_3DRES 32 static void create_conv_textures(int conv, int *texu, char *texs, int brightness, int contrast, int uvcos, int uvsin, int rgamma, int ggamma, int bgamma) { @@ -763,6 +807,32 @@ ActiveTexture(GL_TEXTURE0); texs[0] += '0'; break; + case YUV_CONVERSION_FRAGMENT_LOOKUP3D: + { + int sz = LOOKUP_3DRES + 2; // texture size including borders + if (!TexImage3D) { + mp_msg(MSGT_VO, MSGL_ERR, "[gl] Missing 3D texture function!\n"); + break; + } + texs[0] = (*texu)++; + ActiveTexture(GL_TEXTURE0 + texs[0]); + lookup_data = malloc(3 * sz * sz * sz); + gen_yuv2rgb_map(lookup_data, LOOKUP_3DRES, brightness, contrast, + uvcos, uvsin, rgamma, ggamma, bgamma); + glAdjustAlignment(sz); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + TexImage3D(GL_TEXTURE_3D, 0, 3, sz, sz, sz, 1, + GL_RGB, GL_UNSIGNED_BYTE, lookup_data); + glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_PRIORITY, 1.0); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP); + ActiveTexture(GL_TEXTURE0); + texs[0] += '0'; + } + break; default: mp_msg(MSGT_VO, MSGL_ERR, "[gl] unknown conversion type %i\n", conv); } @@ -929,6 +999,9 @@ ry, gy, by, ru, gu, bu, rv, gv, bv, rc, gc, bc, conv_texs[0], conv_texs[0], conv_texs[0]); break; + case YUV_CONVERSION_FRAGMENT_LOOKUP3D: + snprintf(prog_pos, prog_remain, yuv_lookup3d_prog_template, conv_texs[0]); + break; default: mp_msg(MSGT_VO, MSGL_ERR, "[gl] unknown conversion type %i\n", YUV_CONVERSION(type)); break; @@ -983,6 +1056,7 @@ glSetupYUVCombinersATI(uvcos, uvsin); break; case YUV_CONVERSION_FRAGMENT_LOOKUP: + case YUV_CONVERSION_FRAGMENT_LOOKUP3D: case YUV_CONVERSION_FRAGMENT: case YUV_CONVERSION_FRAGMENT_POW: glSetupYUVFragprog(brightness, contrast, uvcos, uvsin, @@ -1020,6 +1094,7 @@ ActiveTexture(GL_TEXTURE0); glEnable(GL_FRAGMENT_SHADER_ATI); break; + case YUV_CONVERSION_FRAGMENT_LOOKUP3D: case YUV_CONVERSION_FRAGMENT_LOOKUP: case YUV_CONVERSION_FRAGMENT_POW: case YUV_CONVERSION_FRAGMENT: @@ -1053,6 +1128,7 @@ ActiveTexture(GL_TEXTURE0); glDisable(GL_FRAGMENT_SHADER_ATI); break; + case YUV_CONVERSION_FRAGMENT_LOOKUP3D: case YUV_CONVERSION_FRAGMENT_LOOKUP: case YUV_CONVERSION_FRAGMENT_POW: case YUV_CONVERSION_FRAGMENT:
--- a/libvo/gl_common.h Thu Jun 08 18:56:33 2006 +0000 +++ b/libvo/gl_common.h Thu Jun 08 19:02:56 2006 +0000 @@ -227,6 +227,8 @@ #define YUV_CONVERSION_FRAGMENT_LOOKUP 4 //! use ATI specific register combiners ("fragment program") #define YUV_CONVERSION_COMBINERS_ATI 5 +//! use a fragment program with 3D table lookup for YUV conversion +#define YUV_CONVERSION_FRAGMENT_LOOKUP3D 6 //! use normal bilinear scaling for textures #define YUV_SCALER_BILIN 0 //! use higher quality bicubic scaling for textures