From 320fa3bbe73c57e2ba5633a865b6997c1901b4b2 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 22 May 2020 02:25:23 +0200 Subject: video: add AV_PIX_FMT_UYYVYY411 conversion support It may be completely useless, and I can't verify it as no known samples or other known/accessible software using it, but why not? Putting this together with he 422 code requires making it slightly more generic. I'm still staying with a "huge" if tree instead of a table to select the scanline worker callback, because it's actually small and not huge (although it not being generic still feels slightly painful). --- test/ref/repack.txt | 3 +- test/ref/zimg_formats.txt | 2 +- test/repack.c | 7 ++-- video/repack.c | 82 ++++++++++++++++++++++++++++++----------------- 4 files changed, 60 insertions(+), 34 deletions(-) diff --git a/test/ref/repack.txt b/test/ref/repack.txt index ec7a242315..6f0f5b281d 100644 --- a/test/ref/repack.txt +++ b/test/ref/repack.txt @@ -200,7 +200,8 @@ rgba64be => [pa] [un] gbrap16 | a=1:1 [tu] [tp] rgba64be => [pa] [un] gbrapf32 | a=1:1 [planar-f32] uyvy422 => [pa] [un] yuv422p | a=2:1 [tu] [tp] uyvy422 => [pa] [un] yuv422pf | a=2:1 [planar-f32] -uyyvyy411 => no +uyyvyy411 => [pa] [un] yuv411p | a=4:1 [tu] [tp] +uyyvyy411 => [pa] [un] yuv411pf | a=4:1 [planar-f32] vaapi => no vaapi_idct => no vaapi_moco => no diff --git a/test/ref/zimg_formats.txt b/test/ref/zimg_formats.txt index 94a348e782..a80ff8936e 100644 --- a/test/ref/zimg_formats.txt +++ b/test/ref/zimg_formats.txt @@ -115,7 +115,7 @@ rgba64 Zin Zout SWSin SWSout | rgba64be Zin Zout SWSin SWSout | uyvy422 Zin Zout SWSin SWSout | - uyyvyy411 | + uyyvyy411 Zin Zout | vaapi | vaapi_idct | vaapi_moco | diff --git a/test/repack.c b/test/repack.c index 00ff0cdc8b..f4b5c9c12a 100644 --- a/test/repack.c +++ b/test/repack.c @@ -141,8 +141,8 @@ static const struct entry repack_tests[] = { -AV_PIX_FMT_YUVA444P16, {P16(2), P16(3), P16(4), P16(1)}}, {1, 1, -AV_PIX_FMT_AYUV64BE, {P16(0x0100, 0x0200, 0x0300, 0x0400)}, -AV_PIX_FMT_YUVA444P16, {P16(2), P16(3), P16(4), P16(1)}}, - {2, 1, -AV_PIX_FMT_YUYV422, {P8(1, 2, 3, 4)}, - -AV_PIX_FMT_YUV422P, {P8(1, 3), P8(2), P8(4)}}, + {4, 1, -AV_PIX_FMT_YUYV422, {P8(1, 2, 3, 4, 5, 6, 7, 8)}, + -AV_PIX_FMT_YUV422P, {P8(1, 3, 5, 7), P8(2, 6), P8(4, 8)}}, {2, 1, -AV_PIX_FMT_YVYU422, {P8(1, 2, 3, 4)}, -AV_PIX_FMT_YUV422P, {P8(1, 3), P8(4), P8(2)}}, {2, 1, -AV_PIX_FMT_UYVY422, {P8(1, 2, 3, 4)}, @@ -159,6 +159,9 @@ static const struct entry repack_tests[] = { P16(0x4a4b)}, -AV_PIX_FMT_YUV422P16, {P16(0x1b1a, 0x2b2a), P16(0x3b3a), P16(0x4b4a)}}, + {8, 1, -AV_PIX_FMT_UYYVYY411, {P8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)}, + -AV_PIX_FMT_YUV411P, {P8(2, 3, 5, 6, 8, 9, 11, 12), + P8(1, 7), P8(4, 10)}}, }; static bool is_true_planar(int imgfmt) diff --git a/video/repack.c b/video/repack.c index c50131c138..e323d63a06 100644 --- a/video/repack.c +++ b/video/repack.c @@ -67,9 +67,10 @@ struct mp_repack { // Fringe RGB/YUV. uint8_t comp_size; - uint8_t comp_map[4]; + uint8_t comp_map[6]; uint8_t comp_shifts[3]; uint8_t *comp_lut; + void (*repack_fringe_yuv)(void *dst, void *src[], int w, uint8_t *c); // F32 repacking. int f32_comp_size; @@ -596,8 +597,8 @@ static void setup_misc_packer(struct mp_repack *rp) for (int x = 0; x < w; x += 2) { \ ((comp_t *)dst)[x * 2 + c[0]] = ((comp_t *)src[0])[x + 0]; \ ((comp_t *)dst)[x * 2 + c[1]] = ((comp_t *)src[0])[x + 1]; \ - ((comp_t *)dst)[x * 2 + c[2]] = ((comp_t *)src[1])[x >> 1]; \ - ((comp_t *)dst)[x * 2 + c[3]] = ((comp_t *)src[2])[x >> 1]; \ + ((comp_t *)dst)[x * 2 + c[4]] = ((comp_t *)src[1])[x >> 1]; \ + ((comp_t *)dst)[x * 2 + c[5]] = ((comp_t *)src[2])[x >> 1]; \ } \ } @@ -607,8 +608,8 @@ static void setup_misc_packer(struct mp_repack *rp) for (int x = 0; x < w; x += 2) { \ ((comp_t *)dst[0])[x + 0] = ((comp_t *)src)[x * 2 + c[0]]; \ ((comp_t *)dst[0])[x + 1] = ((comp_t *)src)[x * 2 + c[1]]; \ - ((comp_t *)dst[1])[x >> 1] = ((comp_t *)src)[x * 2 + c[2]]; \ - ((comp_t *)dst[2])[x >> 1] = ((comp_t *)src)[x * 2 + c[3]]; \ + ((comp_t *)dst[1])[x >> 1] = ((comp_t *)src)[x * 2 + c[4]]; \ + ((comp_t *)dst[2])[x >> 1] = ((comp_t *)src)[x * 2 + c[5]]; \ } \ } @@ -617,9 +618,34 @@ PA_P422(pa_p422_16, uint16_t) UN_P422(un_p422_8, uint8_t) UN_P422(un_p422_16, uint16_t) -static void fringe_yuv422_repack(struct mp_repack *rp, - struct mp_image *a, int a_x, int a_y, - struct mp_image *b, int b_x, int b_y, int w) +static void pa_p411_8(void *dst, void *src[], int w, uint8_t *c) +{ + for (int x = 0; x < w; x += 4) { + ((uint8_t *)dst)[x / 4 * 6 + c[0]] = ((uint8_t *)src[0])[x + 0]; + ((uint8_t *)dst)[x / 4 * 6 + c[1]] = ((uint8_t *)src[0])[x + 1]; + ((uint8_t *)dst)[x / 4 * 6 + c[2]] = ((uint8_t *)src[0])[x + 2]; + ((uint8_t *)dst)[x / 4 * 6 + c[3]] = ((uint8_t *)src[0])[x + 3]; + ((uint8_t *)dst)[x / 4 * 6 + c[4]] = ((uint8_t *)src[1])[x >> 2]; + ((uint8_t *)dst)[x / 4 * 6 + c[5]] = ((uint8_t *)src[2])[x >> 2]; + } +} + + +static void un_p411_8(void *src, void *dst[], int w, uint8_t *c) +{ + for (int x = 0; x < w; x += 4) { + ((uint8_t *)dst[0])[x + 0] = ((uint8_t *)src)[x / 4 * 6 + c[0]]; + ((uint8_t *)dst[0])[x + 1] = ((uint8_t *)src)[x / 4 * 6 + c[1]]; + ((uint8_t *)dst[0])[x + 2] = ((uint8_t *)src)[x / 4 * 6 + c[2]]; + ((uint8_t *)dst[0])[x + 3] = ((uint8_t *)src)[x / 4 * 6 + c[3]]; + ((uint8_t *)dst[1])[x >> 2] = ((uint8_t *)src)[x / 4 * 6 + c[4]]; + ((uint8_t *)dst[2])[x >> 2] = ((uint8_t *)src)[x / 4 * 6 + c[5]]; + } +} + +static void fringe_yuv_repack(struct mp_repack *rp, + struct mp_image *a, int a_x, int a_y, + struct mp_image *b, int b_x, int b_y, int w) { void *pa = mp_image_pixel_ptr(a, 0, a_x, a_y); @@ -627,26 +653,18 @@ static void fringe_yuv422_repack(struct mp_repack *rp, for (int p = 0; p < b->num_planes; p++) pb[p] = mp_image_pixel_ptr(b, p, b_x, b_y); - assert(rp->comp_size == 1 || rp->comp_size == 2); - - void (*repack)(void *a, void *b[], int w, uint8_t *c) = NULL; - if (rp->pack) { - repack = rp->comp_size == 1 ? pa_p422_8 : pa_p422_16; - } else { - repack = rp->comp_size == 1 ? un_p422_8 : un_p422_16; - } - repack(pa, pb, w, rp->comp_map); + rp->repack_fringe_yuv(pa, pb, w, rp->comp_map); } -static void setup_fringe_yuv422_packer(struct mp_repack *rp) +static void setup_fringe_yuv_packer(struct mp_repack *rp) { struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(rp->imgfmt_a); if (!(desc.flags & MP_IMGFLAG_PACKED_SS_YUV) || mp_imgfmt_desc_get_num_comps(&desc) != 3 || - desc.align_x != 2) + desc.align_x > 4) return; - uint8_t y_loc[2]; + uint8_t y_loc[4]; if (!mp_imgfmt_get_packed_yuv_locations(desc.id, y_loc)) return; @@ -658,7 +676,7 @@ static void setup_fringe_yuv422_packer(struct mp_repack *rp) desc.comps[n].offset % desc.comps[0].size) return; if (n == 1 || n == 2) { - rp->comp_map[n - 1 + desc.align_x] = + rp->comp_map[4 + (n - 1)] = desc.comps[n].offset / desc.comps[0].size; } } @@ -668,24 +686,28 @@ static void setup_fringe_yuv422_packer(struct mp_repack *rp) rp->comp_map[n] = y_loc[n] / desc.comps[0].size; } - int depth = desc.comps[0].size; - if (depth != 8 && depth != 16) - return; + if (desc.comps[0].size == 8 && desc.align_x == 2) { + rp->repack_fringe_yuv = rp->pack ? pa_p422_8 : un_p422_8; + } else if (desc.comps[0].size == 16 && desc.align_x == 2) { + rp->repack_fringe_yuv = rp->pack ? pa_p422_16 : un_p422_16; + } else if (desc.comps[0].size == 8 && desc.align_x == 4) { + rp->repack_fringe_yuv = rp->pack ? pa_p411_8 : un_p411_8; + } - rp->comp_size = depth / 8u; - assert(rp->comp_size == 1 || rp->comp_size == 2); + if (!rp->repack_fringe_yuv) + return; struct mp_regular_imgfmt yuvfmt = { .component_type = MP_COMPONENT_TYPE_UINT, // NB: same problem with P010 and not clearing padding. - .component_size = rp->comp_size, + .component_size = desc.comps[0].size / 8u, .num_planes = 3, .planes = { {1, {1}}, {1, {2}}, {1, {3}} }, - .chroma_xs = 1, + .chroma_xs = desc.chroma_xs, .chroma_ys = 0, }; rp->imgfmt_b = mp_find_regular_imgfmt(&yuvfmt); - rp->repack = fringe_yuv422_repack; + rp->repack = fringe_yuv_repack; if (desc.endian_shift) { rp->endian_size = 1 << desc.endian_shift; @@ -913,7 +935,7 @@ static bool setup_format_ne(struct mp_repack *rp) if (!rp->imgfmt_b) setup_fringe_rgb_packer(rp); if (!rp->imgfmt_b) - setup_fringe_yuv422_packer(rp); + setup_fringe_yuv_packer(rp); if (!rp->imgfmt_b) rp->imgfmt_b = rp->imgfmt_a; // maybe it was planar after all -- cgit v1.2.3