summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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))