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).
This commit is contained in:
wm4 2015-01-21 19:29:18 +01:00
parent 30ca30c0a1
commit a0caadd512
7 changed files with 26 additions and 21 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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},

View File

@ -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]);

View File

@ -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

View File

@ -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;
}

View File

@ -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));