From 71295fb872ba6593c8591cff7398498e05afb298 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 24 Apr 2020 14:41:50 +0200 Subject: video: add alpha type metadata This is mostly for testing. It adds passing through the metadata through the video chain. The metadata can be manipulated with vf_format. Support for zimg alpha conversion (if built with zimg after it gained alpha support) is implemented. Support premultiplied input in vo_gpu. Some things still seem to be buggy. --- DOCS/man/vf.rst | 8 ++++++++ video/csputils.c | 7 +++++++ video/csputils.h | 8 ++++++++ video/filter/vf_format.c | 4 ++++ video/mp_image.c | 9 ++++++++- video/mp_image.h | 1 + video/out/gpu/video.c | 6 ++++-- video/zimg.c | 3 ++- 8 files changed, 42 insertions(+), 4 deletions(-) diff --git a/DOCS/man/vf.rst b/DOCS/man/vf.rst index 4f9268256c..3797ad26bd 100644 --- a/DOCS/man/vf.rst +++ b/DOCS/man/vf.rst @@ -339,6 +339,14 @@ Available mpv-only filters are: Force a specific scaler backend, if applicable. This is a debug option and could go away any time. + ```` + Set the kind of alpha the video uses. Undefined effect if the image + format has no alpha channel (could be ignored or cause an error, + depending on how mpv internals evolve). Setting this may or may not + cause downstream image processing to treat alpha differently, depending + on support. With ``convert`` and zimg used, this will convert the alpha. + libswscale and other FFmpeg components completely ignore this. + ``lavfi=graph[:sws-flags[:o=opts]]`` Filter video using FFmpeg's libavfilter. diff --git a/video/csputils.c b/video/csputils.c index cc9aa4d64a..ef26813af0 100644 --- a/video/csputils.c +++ b/video/csputils.c @@ -108,6 +108,13 @@ const struct m_opt_choice_alternatives mp_chroma_names[] = { {0} }; +const struct m_opt_choice_alternatives mp_alpha_names[] = { + {"auto", MP_ALPHA_AUTO}, + {"straight", MP_ALPHA_STRAIGHT}, + {"premul", MP_ALPHA_PREMUL}, + {0} +}; + void mp_colorspace_merge(struct mp_colorspace *orig, struct mp_colorspace *new) { if (!orig->space) diff --git a/video/csputils.h b/video/csputils.h index f817779584..fc6f04db6a 100644 --- a/video/csputils.h +++ b/video/csputils.h @@ -189,6 +189,14 @@ enum mp_chroma_location { extern const struct m_opt_choice_alternatives mp_chroma_names[]; +enum mp_alpha_type { + MP_ALPHA_AUTO, + MP_ALPHA_STRAIGHT, + MP_ALPHA_PREMUL, +}; + +extern const struct m_opt_choice_alternatives mp_alpha_names[]; + extern const struct m_sub_options mp_csp_equalizer_conf; enum mp_csp_equalizer_param { diff --git a/video/filter/vf_format.c b/video/filter/vf_format.c index 793e37bc4a..8687db783b 100644 --- a/video/filter/vf_format.c +++ b/video/filter/vf_format.c @@ -50,6 +50,7 @@ struct vf_format_opts { int chroma_location; int stereo_in; int rotate; + int alpha; int w, h; int dw, dh; double dar; @@ -87,6 +88,8 @@ static void set_params(struct vf_format_opts *p, struct mp_image_params *out, out->stereo3d = p->stereo_in; if (p->rotate >= 0) out->rotate = p->rotate; + if (p->alpha) + out->alpha = p->alpha; if (p->w > 0 && set_size) out->w = p->w; @@ -196,6 +199,7 @@ static const m_option_t vf_opts_fields[] = { {"chroma-location", OPT_CHOICE_C(chroma_location, mp_chroma_names)}, {"stereo-in", OPT_CHOICE_C(stereo_in, mp_stereo3d_names)}, {"rotate", OPT_INT(rotate), M_RANGE(-1, 359)}, + {"alpha", OPT_CHOICE_C(alpha, mp_alpha_names)}, {"w", OPT_INT(w)}, {"h", OPT_INT(h)}, {"dw", OPT_INT(dw)}, diff --git a/video/mp_image.c b/video/mp_image.c index ea04bab26e..dba787452e 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -512,6 +512,7 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src) dst->params.p_h = src->params.p_h; dst->params.color = src->params.color; dst->params.chroma_location = src->params.chroma_location; + dst->params.alpha = src->params.alpha; dst->nominal_fps = src->nominal_fps; // ensure colorspace consistency if (mp_image_params_get_forced_csp(&dst->params) != @@ -643,6 +644,10 @@ char *mp_image_params_to_str_buf(char *b, size_t bs, mp_snprintf_cat(b, bs, " stereo=%s", MP_STEREO3D_NAME_DEF(p->stereo3d, "?")); } + if (p->alpha) { + mp_snprintf_cat(b, bs, " A=%s", + m_opt_choice_str(mp_alpha_names, p->alpha)); + } } else { snprintf(b, bs, "???"); } @@ -687,7 +692,8 @@ bool mp_image_params_equal(const struct mp_image_params *p1, mp_colorspace_equal(p1->color, p2->color) && p1->chroma_location == p2->chroma_location && p1->rotate == p2->rotate && - p1->stereo3d == p2->stereo3d; + p1->stereo3d == p2->stereo3d && + p1->alpha == p2->alpha; } // Set most image parameters, but not image format or size. @@ -862,6 +868,7 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *src) dst->params.stereo3d = p->stereo3d; // Might be incorrect if colorspace changes. dst->params.color.light = p->color.light; + dst->params.alpha = p->alpha; } sd = av_frame_get_side_data(src, AV_FRAME_DATA_ICC_PROFILE); diff --git a/video/mp_image.h b/video/mp_image.h index 16bae6e7d9..e51022dd5c 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -51,6 +51,7 @@ struct mp_image_params { // The image should be rotated clockwise (0-359 degrees). int rotate; enum mp_stereo3d_mode stereo3d; // image is encoded with this mode + enum mp_alpha_type alpha; // usually auto; only set if explicitly known }; /* Memory management: diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c index 9d5df7c739..4d14eb8019 100644 --- a/video/out/gpu/video.c +++ b/video/out/gpu/video.c @@ -2357,9 +2357,11 @@ static void pass_convert_yuv(struct gl_video *p) p->components = 3; if (!p->has_alpha || p->opts.alpha_mode == ALPHA_NO) { GLSL(color.a = 1.0;) - } else { // alpha present in image + } else if (p->image_params.alpha == MP_ALPHA_PREMUL) { p->components = 4; - GLSL(color = vec4(color.rgb * color.a, color.a);) + } else { + p->components = 4; + GLSL(color = vec4(color.rgb * color.a, color.a);) // straight -> premul } } diff --git a/video/zimg.c b/video/zimg.c index 635696f686..2f52537c07 100644 --- a/video/zimg.c +++ b/video/zimg.c @@ -1137,7 +1137,8 @@ static bool setup_format_ne(zimg_image_format *zfmt, struct mp_zimg_repack *r, r->z_planes[3] = n; // alpha, always plane 4 in zimg #if HAVE_ZIMG_ALPHA - zfmt->alpha = ZIMG_ALPHA_STRAIGHT; + zfmt->alpha = fmt.alpha == MP_ALPHA_PREMUL + ? ZIMG_ALPHA_PREMULTIPLIED : ZIMG_ALPHA_STRAIGHT; #else return false; #endif -- cgit v1.2.3