From 577c00510b7d42b209a51be60c135eec73b60015 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 20 Oct 2019 16:13:50 +0200 Subject: zimg: avoid theoretical FFmpeg planar RGB/YUV mixup The RGB pack/unpack code in theory supports packed, non-subsampled YUV, although in practice FFmpeg defines no such formats. (Only one with alpha, but all alpha input is rejected by the current code.) This would in theory have failed, because we would have selected a GBRP format (instead of YUV), which makes no sense and would either have been rejected by zimg (inconsistent parameters), or lead to broken output (wrong permutation of planes). Select the correct format and don't permute the planes in the YUV case. --- video/zimg.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/video/zimg.c b/video/zimg.c index 142e561303..c5b0d07b62 100644 --- a/video/zimg.c +++ b/video/zimg.c @@ -321,15 +321,27 @@ static void setup_regular_rgb_packer(struct mp_zimg_repack *r) return; } + // Component ID to plane, with 0 (padding) just mapping to plane 0. + const int *corder = NULL; + + int typeflag = 0; + enum mp_csp forced_csp = mp_imgfmt_get_forced_csp(r->zimgfmt); + if (forced_csp == MP_CSP_RGB || forced_csp == MP_CSP_XYZ) { + typeflag = MP_IMGFLAG_RGB_P; + static const int gbrp[4] = {0, 2, 0, 1}; + corder = gbrp; + } else { + typeflag = MP_IMGFLAG_YUV_P; + static const int yuv[4] = {0, 0, 1, 2}; + corder = yuv; + } + // Find a compatible planar format (typically AV_PIX_FMT_GBRP). int depth = desc.component_size * 8 + MPMIN(0, desc.component_pad); - int planar_fmt = mp_imgfmt_find(0, 0, 3, depth, MP_IMGFLAG_RGB_P); + int planar_fmt = mp_imgfmt_find(0, 0, 3, depth, typeflag); if (!planar_fmt) return; - // Component ID to plane, implied by MP_IMGFLAG_RGB_P. - static int gbrp[4] = {0, 2, 0, 1}; - if (desc.component_size == 1 && p->num_components == 4) { if (!r->pack) // no unpacker yet return; @@ -342,7 +354,7 @@ static void setup_regular_rgb_packer(struct mp_zimg_repack *r) r->packed_repack_scanline = p->components[0] ? cccx8_pack : xccc8_pack; r->zimgfmt = planar_fmt; for (int n = 0; n < 3; n++) - r->components[n] = gbrp[p->components[first + n]]; + r->components[n] = corder[p->components[first + n]]; return; } } -- cgit v1.2.3