summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-04-13 20:05:38 +0200
committerwm4 <wm4@nowhere>2020-04-13 20:05:38 +0200
commitafedaf3b61287b43b5ee4123b94b1ffcd7a506d4 (patch)
tree4312e68d06b006c29903f2dcb7f38a84628716fc
parent30855638df313fd2d13739107c2ed39935a52eb3 (diff)
downloadmpv-afedaf3b61287b43b5ee4123b94b1ffcd7a506d4.tar.bz2
mpv-afedaf3b61287b43b5ee4123b94b1ffcd7a506d4.tar.xz
zimg: add packed YUV bullshit
Just lazily tested. The comment on AV_PIX_FMT_Y210LE seems to be wrong. It claims it's "like YUYV422", bit it seems more like YVYU422, at last the way libswscale input treats it. Maybe Intel pays its developers too much? The repacker inner lop is probably rather inefficient. In theory we could optimize it by reading the packed pixels as words, doing the component reshuffling using compile time values etc., but I'd rather keep the code size small. It's already bad enough that we have to support 16 bit per component variants, just because this one Intel guy couldn't keep it in his pants. In general, I can't be bothered to spend time on optimizing it; I'm only doing this for fun (i.e. masochistic obligation).
-rw-r--r--test/ref/zimg_formats.txt10
-rw-r--r--video/zimg.c112
2 files changed, 116 insertions, 6 deletions
diff --git a/test/ref/zimg_formats.txt b/test/ref/zimg_formats.txt
index 8d8300fc2a..ef5b650a3f 100644
--- a/test/ref/zimg_formats.txt
+++ b/test/ref/zimg_formats.txt
@@ -107,7 +107,7 @@
rgba Zin Zout SWSin SWSout |
rgba64 Zin Zout SWSin SWSout |
rgba64be Zin Zout SWSin SWSout |
- uyvy422 SWSin SWSout |
+ uyvy422 Zin Zout SWSin SWSout |
uyyvyy411 |
vaapi |
vaapi_idct |
@@ -119,8 +119,8 @@
xvmc |
xyz12 Zin Zout SWSin SWSout |
xyz12be Zin Zout SWSin SWSout |
- y210 SWSin |
- y210be |
+ y210 Zin Zout SWSin |
+ y210be Zin Zout |
ya16 Zin Zout SWSin SWSout |
ya16be Zin Zout SWSin SWSout |
ya8 Zin Zout SWSin SWSout |
@@ -194,5 +194,5 @@
yuvj411p Zin Zout SWSin SWSout |
yuvj422p Zin Zout SWSin SWSout |
yuvj440p Zin Zout SWSin SWSout |
- yuyv422 SWSin SWSout |
- yvyu422 SWSin SWSout |
+ yuyv422 Zin Zout SWSin SWSout |
+ yvyu422 Zin Zout SWSin SWSout |
diff --git a/video/zimg.c b/video/zimg.c
index 1a0c4e3b0b..951cf2c907 100644
--- a/video/zimg.c
+++ b/video/zimg.c
@@ -101,8 +101,9 @@ struct mp_zimg_repack {
// unpack: p1 is src, p2 is dst
void (*packed_repack_scanline)(void *p1, void *p2[], int x0, int x1);
- // Fringe RGB.
+ // Fringe RGB/YUV.
uint8_t comp_size;
+ uint8_t *comp_map;
uint8_t comp_shifts[3];
uint8_t *comp_lut; // 256 * 3
@@ -585,6 +586,75 @@ static int unpack_pal(void *user, unsigned i, unsigned x0, unsigned x1)
return 0;
}
+struct fringe_yuv422_repacker {
+ // To avoid making a mess of IMGFMT_*, we use av formats directly.
+ enum AVPixelFormat avfmt;
+ // In bits (depth/8 rounded up gives byte size)
+ int8_t depth;
+ // Word index of each sample: {y0, y1, cr, cb}
+ uint8_t comp[4];
+ bool be;
+};
+
+static const struct fringe_yuv422_repacker fringe_yuv422_repackers[] = {
+ {AV_PIX_FMT_YUYV422, 8, {0, 2, 3, 1}},
+ {AV_PIX_FMT_UYVY422, 8, {1, 3, 2, 0}},
+ {AV_PIX_FMT_YVYU422, 8, {0, 2, 1, 3}},
+ {AV_PIX_FMT_Y210LE, 10, {0, 2, 1, 3}},
+ {AV_PIX_FMT_Y210BE, 10, {0, 2, 1, 3}, .be = true},
+};
+
+#define PA_P422(name, comp_t) \
+ static void name(void *dst, void *src[], int x0, int x1, uint8_t *c) { \
+ for (int x = x0; x < x1; 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]; \
+ } \
+ }
+
+
+#define UN_P422(name, comp_t) \
+ static void name(void *src, void *dst[], int x0, int x1, uint8_t *c) { \
+ for (int x = x0; x < x1; 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]]; \
+ } \
+ }
+
+PA_P422(pa_p422_8, uint8_t)
+PA_P422(pa_p422_16, uint16_t)
+UN_P422(un_p422_8, uint8_t)
+UN_P422(un_p422_16, uint16_t)
+
+static int fringe_yuv422_repack(void *user, unsigned i, unsigned x0, unsigned x1)
+{
+ struct mp_zimg_repack *r = user;
+
+ void *p1 = r->mpi->planes[0] + r->mpi->stride[0] * (ptrdiff_t)(i - r->mpi_y0);
+
+ void *p2[4] = {0};
+ for (int p = 0; p < r->num_planes; p++) {
+ p2[p] = r->tmp->planes[p] +
+ r->tmp->stride[p] * (ptrdiff_t)(i & r->zmask[p]);
+ }
+
+ assert(r->comp_size == 1 || r->comp_size == 2);
+
+ void (*repack)(void *p1, void *p2[], int x0, int x1, uint8_t *c) = NULL;
+ if (r->pack) {
+ repack = r->comp_size == 1 ? pa_p422_8 : pa_p422_16;
+ } else {
+ repack = r->comp_size == 1 ? un_p422_8 : un_p422_16;
+ }
+ repack(p1, p2, x0, x1, r->comp_map);
+
+ return 0;
+}
+
static int repack_nv(void *user, unsigned i, unsigned x0, unsigned x1)
{
struct mp_zimg_repack *r = user;
@@ -758,6 +828,44 @@ static void setup_fringe_rgb_packer(struct mp_zimg_repack *r,
}
}
+static void setup_fringe_yuv422_packer(struct mp_zimg_repack *r)
+{
+ enum AVPixelFormat avfmt = imgfmt2pixfmt(r->zimgfmt);
+
+ const struct fringe_yuv422_repacker *fmt = NULL;
+ for (int n = 0; n < MP_ARRAY_SIZE(fringe_yuv422_repackers); n++) {
+ if (fringe_yuv422_repackers[n].avfmt == avfmt) {
+ fmt = &fringe_yuv422_repackers[n];
+ break;
+ }
+ }
+
+ if (!fmt)
+ return;
+
+ r->comp_size = (fmt->depth + 7) / 8;
+ assert(r->comp_size == 1 || r->comp_size == 2);
+
+ struct mp_regular_imgfmt yuvfmt = {
+ .component_type = MP_COMPONENT_TYPE_UINT,
+ // NB: same problem with P010 and not clearing padding.
+ .component_size = r->comp_size,
+ .num_planes = 3,
+ .planes = { {1, {1}}, {1, {2}}, {1, {3}} },
+ .chroma_w = 2,
+ .chroma_h = 1,
+ };
+ r->zimgfmt = mp_find_regular_imgfmt(&yuvfmt);
+ r->repack = fringe_yuv422_repack;
+ r->comp_map = (uint8_t *)fmt->comp;
+
+ if (fmt->be) {
+ assert(r->comp_size == 2);
+ r->endian_size = 2;
+ r->endian_items[0] = 4;
+ }
+}
+
static void setup_nv_packer(struct mp_zimg_repack *r)
{
struct mp_regular_imgfmt desc;
@@ -954,6 +1062,8 @@ static bool setup_format_ne(zimg_image_format *zfmt, struct mp_zimg_repack *r,
setup_regular_rgb_packer(r);
if (!r->repack)
setup_fringe_rgb_packer(r, ctx);
+ if (!r->repack)
+ setup_fringe_yuv422_packer(r);
struct mp_regular_imgfmt desc;
if (!mp_get_regular_imgfmt(&desc, r->zimgfmt))