From a0caadd512a6f531fd01638570883e629f9dc6e5 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 21 Jan 2015 19:29:18 +0100 Subject: [PATCH] vo_opengl: handle grayscale input better, add YA16 support Simply clamp off the U/V components in the colormatrix, instead of doing something special in the shader. Also, since YA8/YA16 gave a plane_bits value of 16/32, and a colormatrix calculation overflowed with 32, add a component_bits field to the image format descriptor, which for YA8/YA16 returns 8/16 (the wrong value had no bad consequences otherwise). --- video/csputils.c | 4 ++-- video/csputils.h | 2 ++ video/fmt-conversion.c | 4 ++++ video/img_format.c | 8 ++++++-- video/img_format.h | 2 ++ video/out/gl_video.c | 22 ++++++++++------------ video/out/gl_video_shaders.glsl | 5 ----- 7 files changed, 26 insertions(+), 21 deletions(-) diff --git a/video/csputils.c b/video/csputils.c index ea83739e8e..922f3ee80f 100644 --- a/video/csputils.c +++ b/video/csputils.c @@ -564,8 +564,8 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, struct mp_cmat *m) // Hue is equivalent to rotating input [U, V] subvector around the origin. // Saturation scales [U, V]. - float huecos = params->saturation * cos(params->hue); - float huesin = params->saturation * sin(params->hue); + float huecos = params->gray ? 0 : params->saturation * cos(params->hue); + float huesin = params->gray ? 0 : params->saturation * sin(params->hue); for (int i = 0; i < 3; i++) { float u = m->m[i][1], v = m->m[i][2]; m->m[i][1] = huecos * u - huesin * v; diff --git a/video/csputils.h b/video/csputils.h index 3f61721b12..f973117751 100644 --- a/video/csputils.h +++ b/video/csputils.h @@ -116,6 +116,8 @@ struct mp_csp_params { float rgamma; float ggamma; float bgamma; + // discard U/V components + bool gray; // texture_bits/input_bits is for rescaling fixed point input to range [0,1] int texture_bits; int input_bits; diff --git a/video/fmt-conversion.c b/video/fmt-conversion.c index eb6b31cc71..dc278054f3 100644 --- a/video/fmt-conversion.c +++ b/video/fmt-conversion.c @@ -113,6 +113,10 @@ static const struct { {IMGFMT_BGR0, AV_PIX_FMT_BGRA}, #endif +#ifdef AV_PIX_FMT_YA16 + {IMGFMT_YA16, AV_PIX_FMT_YA16}, +#endif + {IMGFMT_VDPAU, AV_PIX_FMT_VDPAU}, #if HAVE_VDA_HWACCEL {IMGFMT_VDA, AV_PIX_FMT_VDA}, diff --git a/video/img_format.c b/video/img_format.c index 92851c0339..db130ad67e 100644 --- a/video/img_format.c +++ b/video/img_format.c @@ -142,6 +142,7 @@ struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt) .avformat = fmt, .chroma_xs = pd->log2_chroma_w, .chroma_ys = pd->log2_chroma_h, + .component_bits = pd->comp[0].depth_minus1 + 1, }; int planedepth[4] = {0}; @@ -154,6 +155,8 @@ struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt) desc.bpp[d.plane] = (d.step_minus1 + 1) * el_size; planedepth[d.plane] += d.depth_minus1 + 1; need_endian |= (d.depth_minus1 + 1 + d.shift) > 8; + if (d.depth_minus1 + 1 != desc.component_bits) + desc.component_bits = 0; } for (int p = 0; p < 4; p++) { @@ -315,8 +318,9 @@ int main(int argc, char **argv) FLAG(MP_IMGFLAG_PAL, "pal") FLAG(MP_IMGFLAG_HWACCEL, "hw") printf("\n"); - printf(" planes=%d, chroma=%d:%d align=%d:%d bits=%d\n", d.num_planes, - d.chroma_xs, d.chroma_ys, d.align_x, d.align_y, d.plane_bits); + printf(" planes=%d, chroma=%d:%d align=%d:%d bits=%d cbits=%d\n", + d.num_planes, d.chroma_xs, d.chroma_ys, d.align_x, d.align_y, + d.plane_bits, d.component_bits); printf(" {"); for (int n = 0; n < MP_MAX_PLANES; n++) printf("%d/%d/[%d:%d] ", d.bytes[n], d.bpp[n], d.xs[n], d.ys[n]); diff --git a/video/img_format.h b/video/img_format.h index b93e0fe974..7d0762c3ce 100644 --- a/video/img_format.h +++ b/video/img_format.h @@ -82,6 +82,7 @@ struct mp_imgfmt_desc { int8_t bytes[MP_MAX_PLANES]; // bytes per pixel (MP_IMGFLAG_BYTE_ALIGNED) int8_t bpp[MP_MAX_PLANES]; // bits per pixel int8_t plane_bits; // number of bits in use for plane 0 + int8_t component_bits; // number of bits per component (0 if uneven) // chroma shifts per plane (provided for convenience with planar formats) int8_t xs[MP_MAX_PLANES]; int8_t ys[MP_MAX_PLANES]; @@ -135,6 +136,7 @@ enum mp_imgfmt { // Gray with alpha (packed) IMGFMT_YA8, + IMGFMT_YA16, // Packed YUV formats (components are byte-accessed) IMGFMT_YUYV, // Y0 U Y1 V diff --git a/video/out/gl_video.c b/video/out/gl_video.c index e991c85857..50be85d3fe 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -168,8 +168,7 @@ struct gl_video { float input_gamma, conv_gamma; - // per pixel (full pixel when packed, each component when planar) - int plane_bits; + int component_bits; // color bit depth for all components; 0 if unknown int plane_count; struct video_image image; @@ -291,10 +290,11 @@ struct packed_fmt_entry { }; static const struct packed_fmt_entry mp_packed_formats[] = { - // R G B A + // w R G B A {IMGFMT_Y8, 1, {1, 0, 0, 0}}, {IMGFMT_Y16, 2, {1, 0, 0, 0}}, {IMGFMT_YA8, 1, {1, 0, 0, 2}}, + {IMGFMT_YA16, 2, {1, 0, 0, 2}}, {IMGFMT_ARGB, 1, {2, 3, 4, 1}}, {IMGFMT_0RGB, 1, {2, 3, 4, 0}}, {IMGFMT_BGRA, 1, {3, 2, 1, 4}}, @@ -652,8 +652,9 @@ static void update_uniforms(struct gl_video *p, GLuint program) gl->UseProgram(program); struct mp_csp_params cparams = MP_CSP_PARAMS_DEFAULTS; - cparams.input_bits = p->plane_bits; - cparams.texture_bits = (p->plane_bits + 7) & ~7; + cparams.gray = p->is_yuv && !p->is_packed_yuv && p->plane_count == 1; + cparams.input_bits = p->component_bits; + cparams.texture_bits = (cparams.input_bits + 7) & ~7; mp_csp_set_image_params(&cparams, &p->image_params); mp_csp_copy_equalizer_values(&cparams, &p->video_eq); if (p->image_desc.flags & MP_IMGFLAG_XYZ) { @@ -1132,8 +1133,6 @@ static void compile_shaders(struct gl_video *p) if (p->color_swizzle[0]) shader_def(&header_conv, "USE_COLOR_SWIZZLE", p->color_swizzle); - shader_def_opt(&header_conv, "USE_YGRAY", p->is_yuv && !p->is_packed_yuv - && p->plane_count == 1); shader_def_opt(&header_conv, "USE_INPUT_GAMMA", use_input_gamma); shader_def_opt(&header_conv, "USE_COLORMATRIX", !p->is_rgb); shader_def_opt(&header_conv, "USE_CONV_GAMMA", use_conv_gamma); @@ -2413,15 +2412,14 @@ static bool init_format(int fmt, struct gl_video *init) const struct fmt_entry *plane_format[4] = {0}; init->image_format = fmt; - init->plane_bits = desc.bpp[0]; + init->component_bits = desc.component_bits; init->color_swizzle[0] = '\0'; init->has_alpha = false; // YUV/planar formats if (desc.flags & MP_IMGFLAG_YUV_P) { - int bits = desc.plane_bits; + int bits = desc.component_bits; if ((desc.flags & MP_IMGFLAG_NE) && bits >= 8 && bits <= 16) { - init->plane_bits = bits; init->has_alpha = desc.num_planes > 3; plane_format[0] = find_tex_format(gl, (bits + 7) / 8, 1); for (int p = 1; p < desc.num_planes; p++) @@ -2494,10 +2492,10 @@ static bool init_format(int fmt, struct gl_video *init) supported: // Stuff like IMGFMT_420AP10. Untested, most likely insane. - if (desc.num_planes == 4 && (init->plane_bits % 8) != 0) + if (desc.num_planes == 4 && (init->component_bits % 8) != 0) return false; - if (init->plane_bits > 8 && init->plane_bits < 16) { + if (init->component_bits > 8 && init->component_bits < 16) { if (init->texture_16bit_depth < 16) return false; } diff --git a/video/out/gl_video_shaders.glsl b/video/out/gl_video_shaders.glsl index 2f2986c9fa..51c444aa2e 100644 --- a/video/out/gl_video_shaders.glsl +++ b/video/out/gl_video_shaders.glsl @@ -381,11 +381,6 @@ void main() { #endif vec3 color = acolor.rgb; float alpha = acolor.a; -#ifdef USE_YGRAY - // NOTE: actually slightly wrong for 16 bit input video, and completely - // wrong for 9/10 bit input - color.gb = vec2(128.0/255.0); -#endif #ifdef USE_INPUT_GAMMA // Pre-colormatrix input gamma correction (eg. for MP_IMGFLAG_XYZ) color = pow(color, vec3(input_gamma));