diff options
Diffstat (limited to 'video')
-rw-r--r-- | video/csputils.c | 28 | ||||
-rw-r--r-- | video/csputils.h | 2 | ||||
-rw-r--r-- | video/img_format.c | 6 | ||||
-rw-r--r-- | video/img_format.h | 2 | ||||
-rw-r--r-- | video/out/opengl/video.c | 12 |
5 files changed, 39 insertions, 11 deletions
diff --git a/video/csputils.c b/video/csputils.c index 60cdc54746..1f0fa7d90e 100644 --- a/video/csputils.c +++ b/video/csputils.c @@ -552,6 +552,27 @@ void mp_get_xyz2rgb_coeffs(struct mp_csp_params *params, m->c[i] = brightness; } +// Get multiplication factor required if image data is fit within the LSBs of a +// higher smaller bit depth isfixed-point texture data. +double mp_get_csp_mul(enum mp_csp csp, int input_bits, int texture_bits) +{ + assert(texture_bits >= input_bits); + + // Convenience for some irrelevant cases, e.g. rgb565 or disabling expansion. + if (!input_bits) + return 1; + + // RGB always uses the full range available. + if (csp == MP_CSP_RGB) + return ((1LL << input_bits) - 1.) / ((1LL << texture_bits) - 1.); + + if (csp == MP_CSP_XYZ) + return 1; + + // High bit depth YUV uses a range shifted from 8 bit. + return (1LL << input_bits) / ((1LL << texture_bits) - 1.) * 255 / 256; +} + /* Fill in the Y, U, V vectors of a yuv2rgb conversion matrix * based on the given luma weights of the R, G and B components (lr, lg, lb). * lr+lg+lb is assumed to equal 1. @@ -642,10 +663,9 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, struct mp_cmat *m) m->m[i][2] = huesin * u + huecos * v; } - assert(params->input_bits >= 8); - assert(params->texture_bits >= params->input_bits); - double s = (1 << (params->input_bits-8)) / ((1<<params->texture_bits)-1.); - // The values below are written in 0-255 scale + // The values below are written in 0-255 scale - thus bring s into range. + double s = + mp_get_csp_mul(colorspace, params->input_bits, params->texture_bits) / 255; struct yuvlevels { double ymin, ymax, cmin, cmid; } yuvlim = { 16*s, 235*s, 16*s, 128*s }, yuvfull = { 0*s, 255*s, 1*s, 128*s }, // '1' for symmetry around 128 diff --git a/video/csputils.h b/video/csputils.h index df5da4a1c6..0a9b11af9d 100644 --- a/video/csputils.h +++ b/video/csputils.h @@ -251,6 +251,8 @@ struct mp_cmat { 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]); +double mp_get_csp_mul(enum mp_csp csp, int input_bits, int texture_bits); + void mp_get_xyz2rgb_coeffs(struct mp_csp_params *params, struct mp_csp_primaries prim, enum mp_render_intent intent, struct mp_cmat *xyz2rgb); void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, struct mp_cmat *yuv2rgb); diff --git a/video/img_format.c b/video/img_format.c index 332bf3676f..42b4df45ab 100644 --- a/video/img_format.c +++ b/video/img_format.c @@ -174,6 +174,7 @@ struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt) } desc.plane_bits = planedepth[0]; + desc.component_full_bits = desc.component_bits; // Check whether any components overlap other components (per plane). // We're cheating/simplifying here: we assume that this happens if a shift @@ -241,6 +242,7 @@ struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt) desc.bpp[p] == desc.bpp[0]; } if (same_depth && pd->nb_components == desc.num_planes) { + desc.component_full_bits = (desc.component_bits + 7) / 8 * 8; if (desc.flags & MP_IMGFLAG_YUV) { desc.flags |= MP_IMGFLAG_YUV_P; } else { @@ -262,7 +264,9 @@ struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt) if (pd->flags & AV_PIX_FMT_FLAG_HWACCEL) { desc.flags |= MP_IMGFLAG_HWACCEL; - desc.plane_bits = 8; // usually restricted to 8 bit; may change + desc.component_bits = 8; // usually restricted to 8 bit; may change + desc.component_full_bits = desc.component_bits; + desc.plane_bits = desc.component_bits; } if (desc.chroma_xs || desc.chroma_ys) diff --git a/video/img_format.h b/video/img_format.h index cd2ebf5360..0d8c699850 100644 --- a/video/img_format.h +++ b/video/img_format.h @@ -86,6 +86,8 @@ struct mp_imgfmt_desc { 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) + int8_t component_full_bits; // number of bits per component including + // internal padding (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]; diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c index 790ced1e42..17fc809fe4 100644 --- a/video/out/opengl/video.c +++ b/video/out/opengl/video.c @@ -1327,9 +1327,9 @@ static void pass_read_video(struct gl_video *p) struct gl_transform chromafix; pass_set_image_textures(p, &p->image, &chromafix); - int in_bits = p->image_desc.component_bits, - tx_bits = (in_bits + 7) & ~7; - float tex_mul = ((1 << tx_bits) - 1.0) / ((1 << in_bits) - 1.0); + float tex_mul = 1 / mp_get_csp_mul(p->image_params.colorspace, + p->image_desc.component_bits, + p->image_desc.component_full_bits); struct src_tex prescaled_tex; struct gl_transform offset = {{{0}}}; @@ -1465,7 +1465,7 @@ static void pass_convert_yuv(struct gl_video *p) struct mp_csp_params cparams = MP_CSP_PARAMS_DEFAULTS; cparams.gray = p->is_yuv && !p->is_packed_yuv && p->plane_count == 1; cparams.input_bits = p->image_desc.component_bits; - cparams.texture_bits = (cparams.input_bits + 7) & ~7; + cparams.texture_bits = p->image_desc.component_full_bits; mp_csp_set_image_params(&cparams, &p->image_params); mp_csp_copy_equalizer_values(&cparams, &p->video_eq); p->user_gamma = 1.0 / (cparams.gamma * p->opts.gamma); @@ -1484,9 +1484,9 @@ static void pass_convert_yuv(struct gl_video *p) GLSL(color.rgb = pow(color.rgb, vec3(2.6));) } - // Something already took care of expansion + // Something already took care of expansion - disable it. if (p->use_normalized_range) - cparams.input_bits = cparams.texture_bits; + cparams.input_bits = cparams.texture_bits = 0; // Conversion from Y'CbCr or other linear spaces to RGB if (!p->is_rgb) { |