summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-02-10 17:57:01 +0100
committerwm4 <wm4@nowhere>2020-02-10 17:57:01 +0100
commita9116ddd3841ddc1d644e302a9f732cac2675d6d (patch)
tree376b3ecefead7ee1745a60fb5de0a392c9469cc2
parentc31661466b8a7efcad418a0ba49f632ea035b2e4 (diff)
downloadmpv-a9116ddd3841ddc1d644e302a9f732cac2675d6d.tar.bz2
mpv-a9116ddd3841ddc1d644e302a9f732cac2675d6d.tar.xz
zimg: support gray/alpha conversion
The special thing about this format is 1. mpv assigns the component ID 4 to alpha, and component IDs 2 and 3 are not present, which causes some messy details. 2. zimg always wants the alpha plane as plane 3, and plane 1 and 2 are not present, while FFmpeg/mpv put the alpha plane as plane 1. In theory, 2. could be avoided, since FFmpeg actually doesn't have a any 2 plane formats (alpha is either packed, or plane 3). But having to skip "empty" planes would break expectations. zplanes is not equivalent to the mpv plane count (actually it was always used this way), while zimg does not really have a plane count, but does, in this case, only use plane 0 and 3, while 2 and 3 are unused and unset. z_planes[] (not zplanes) is now always valid for all 4 array entries (because it uses zimg indexes), but a -1 entry means it's an unused plane. I wonder if these conventions taken by mpv/zimg are not just causing extra work. Maybe component IDs should just be indexes by the "natural" order (e.g. R-G-B-A, Y-U-V-A, Y-A), and alpha should be represented as a field that specifies the component ID for it, or just strictly assume that 2/4 component formats always use the last component for alpha.
-rw-r--r--video/zimg.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/video/zimg.c b/video/zimg.c
index 1ed5ca41da..0f729f9f92 100644
--- a/video/zimg.c
+++ b/video/zimg.c
@@ -74,7 +74,7 @@ struct mp_zimg_repack {
bool pack; // if false, this is for unpacking
struct mp_image_params fmt; // original mp format (possibly packed format)
int zimgfmt; // zimg equivalent unpacked format
- int zplanes; // number of planes (zimgfmt)
+ int zplanes; // number of planes involved
unsigned zmask[4]; // zmask[mp_index] = zimg mask (using mp index!)
int z_planes[4]; // z_planes[zimg_index] = mp_index (or -1)
bool pass_through_y; // luma plane optimization for e.g. nv12
@@ -464,12 +464,14 @@ static void wrap_buffer(struct mp_zimg_repack *r,
!(mpi->stride[n] % ZIMG_ALIGN);
}
- for (int n = 0; n < r->zplanes; n++) {
+ for (int n = 0; n < MP_ARRAY_SIZE(buf->plane); n++) {
// Note: this is really the only place we have to care about plane
// permutation (zimg_image_buffer may have a different plane order
// than the shadow mpi like r->tmp). We never use the zimg indexes
// in other places.
int mplane = r->z_planes[n];
+ if (mplane < 0)
+ continue;
r->use_buf[mplane] = !plane_aligned[mplane];
if (!(r->pass_through_y && mplane == 0))
@@ -582,13 +584,15 @@ static void setup_regular_rgb_packer(struct mp_zimg_repack *r)
if (!mp_get_regular_imgfmt(&desc, r->zimgfmt))
return;
- if (desc.num_planes != 1 || desc.planes[0].num_components < 3)
+ if (desc.num_planes != 1 || desc.planes[0].num_components < 2)
return;
struct mp_regular_imgfmt_plane *p = &desc.planes[0];
int num_real_components = 0;
+ bool has_alpha = false;
for (int n = 0; n < p->num_components; n++) {
if (p->components[n]) {
+ has_alpha |= p->components[n] == 4;
num_real_components += 1;
} else {
// padding must be in MSB or LSB
@@ -609,6 +613,8 @@ static void setup_regular_rgb_packer(struct mp_zimg_repack *r)
desc2.planes[n].num_components = 1;
desc2.planes[n].components[0] = n + 1;
}
+ if (has_alpha)
+ desc2.planes[desc2.num_planes - 1].components[0] = 4;
int planar_fmt = mp_find_regular_imgfmt(&desc2);
if (!planar_fmt)
return;
@@ -634,8 +640,12 @@ static void setup_regular_rgb_packer(struct mp_zimg_repack *r)
r->repack = packed_repack;
r->packed_repack_scanline = repack_cb;
r->zimgfmt = planar_fmt;
- for (int n = 0; n < num_real_components; n++)
- r->components[n] = p->components[first_comp + n] - 1;
+ for (int n = 0; n < num_real_components; n++) {
+ // Determine permutation that maps component order between the two
+ // formats, with has_alpha special case (see above).
+ int c = p->components[first_comp + n];
+ r->components[n] = c == 4 ? num_real_components - 1 : c - 1;
+ }
return;
}
}
@@ -667,6 +677,9 @@ static bool setup_format(zimg_image_format *zfmt, struct mp_zimg_repack *r,
!MP_IS_POWER_OF_2(desc.chroma_h))
return false;
+ for (int n = 0; n < 4; n++)
+ r->z_planes[n] = -1;
+
// Accept only true planar formats.
for (int n = 0; n < desc.num_planes; n++) {
if (desc.planes[n].num_components != 1)
@@ -705,7 +718,7 @@ static bool setup_format(zimg_image_format *zfmt, struct mp_zimg_repack *r,
zfmt->subsample_h = mp_log2(desc.chroma_h);
zfmt->color_family = ZIMG_COLOR_YUV;
- if (desc.num_planes == 1) {
+ if (desc.num_planes <= 2) {
zfmt->color_family = ZIMG_COLOR_GREY;
} else if (fmt.color.space == MP_CSP_RGB || fmt.color.space == MP_CSP_XYZ) {
zfmt->color_family = ZIMG_COLOR_RGB;