video: separate repacking code from zimg and make it independent

For whatever purpose. If anything, this makes the zimg wrapper cleaner.

The added tests are not particular exhaustive, but nice to have. This
also makes the scale_zimg.c test pretty useless, because it only tests
repacking (going through the zimg wrapper). In theory, the repack_tests
things could also be used on scalers, but I guess it doesn't matter.

Some things are added over the previous zimg wrapper code. For example,
some fringe formats can now be expanded to 8 bit per component for
convenience.
This commit is contained in:
wm4
2020-05-09 18:02:57 +02:00
parent d61ced37ae
commit d8002f1dde
9 changed files with 1697 additions and 904 deletions
+163
View File
@@ -0,0 +1,163 @@
0bgr => [pa] [un] gbrp | a=1:1 [tu] [tp]
0rgb => [pa] [un] gbrp | a=1:1 [tu] [tp]
abgr => [pa] [un] gbrap | a=1:1 [tu] [tp]
argb => [pa] [un] gbrap | a=1:1 [tu] [tp]
ayuv64 => [pa] [un] yuva444p16 | a=1:1 [tu] [tp]
ayuv64be => [pa] [un] yuva444p16 | a=1:1 [tu] [tp]
bayer_bggr16 => no
bayer_bggr16be => no
bayer_bggr8 => no
bayer_gbrg16 => no
bayer_gbrg16be => no
bayer_gbrg8 => no
bayer_grbg16 => no
bayer_grbg16be => no
bayer_grbg8 => no
bayer_rggb16 => no
bayer_rggb16be => no
bayer_rggb8 => no
bgr0 => [pa] [un] gbrp | a=1:1 [tu] [tp]
bgr24 => [pa] [un] gbrp | a=1:1
bgr4 => no
bgr444 => [pa] [un] gbrp4 | a=1:1
bgr444 => [pa] [un] gbrp | a=1:1 [expand-8bit]
bgr444be => [pa] [un] gbrp4 | a=1:1
bgr444be => [pa] [un] gbrp | a=1:1 [expand-8bit]
bgr48 => [pa] [un] gbrp16 | a=1:1
bgr48be => [pa] [un] gbrp16 | a=1:1
bgr4_byte => [pa] [un] gbrp2 | a=1:1
bgr4_byte => [pa] [un] gbrp1 | a=1:1 [round-down]
bgr4_byte => [pa] [un] gbrp | a=1:1 [expand-8bit]
bgr555 => [pa] [un] gbrp5 | a=1:1
bgr555 => [pa] [un] gbrp | a=1:1 [expand-8bit]
bgr555be => [pa] [un] gbrp5 | a=1:1
bgr555be => [pa] [un] gbrp | a=1:1 [expand-8bit]
bgr565 => [pa] [un] gbrp6 | a=1:1
bgr565 => [pa] [un] gbrp5 | a=1:1 [round-down]
bgr565 => [pa] [un] gbrp | a=1:1 [expand-8bit]
bgr565be => [pa] [un] gbrp6 | a=1:1
bgr565be => [pa] [un] gbrp5 | a=1:1 [round-down]
bgr565be => [pa] [un] gbrp | a=1:1 [expand-8bit]
bgr8 => [pa] [un] gbrp3 | a=1:1
bgr8 => [pa] [un] gbrp2 | a=1:1 [round-down]
bgr8 => [pa] [un] gbrp | a=1:1 [expand-8bit]
bgra => [pa] [un] gbrap | a=1:1 [tu] [tp]
bgra64 => [pa] [un] gbrap16 | a=1:1
bgra64be => [pa] [un] gbrap16 | a=1:1
cuda => no
d3d11 => no
d3d11va_vld => no
drm_prime => no
dxva2_vld => no
gbrap10be => [pa] [un] gbrap10 | a=1:1
gbrap12be => [pa] [un] gbrap12 | a=1:1
gbrap16be => [pa] [un] gbrap16 | a=1:1
gbrapf32be => [pa] [un] gbrapf32 | a=1:1
gbrp10be => [pa] [un] gbrp10 | a=1:1
gbrp12be => [pa] [un] gbrp12 | a=1:1
gbrp14be => [pa] [un] gbrp14 | a=1:1
gbrp16be => [pa] [un] gbrp16 | a=1:1
gbrp9be => [pa] [un] gbrp9 | a=1:1
gbrpf32be => [pa] [un] gbrpf32 | a=1:1
gray10be => [pa] [un] gray10 | a=1:1
gray12be => [pa] [un] gray12 | a=1:1
gray14be => [pa] [un] gray14 | a=1:1
gray16be => [pa] [un] gray16 | a=1:1
gray9be => [pa] [un] gray9 | a=1:1
grayf32be => [pa] [un] grayf32 | a=1:1
mediacodec => no
mmal => no
monob => [pa] [un] y1 | a=8:1 [tu] [tp]
monob => [pa] [un] gray | a=8:1 [expand-8bit]
monow => [pa] [un] y1 | a=8:1 [tu] [tp]
monow => [pa] [un] gray | a=8:1 [expand-8bit]
nv12 => [pa] [un] yuv420p | a=2:2 [tu] [tp]
nv16 => [pa] [un] yuv422p | a=2:1
nv20 => [pa] [un] yuv422p10 | a=2:1
nv20be => [pa] [un] yuv422p10 | a=2:1
nv21 => [pa] [un] yuv420p | a=2:2 [tu] [tp]
nv24 => [pa] [un] yuv444p | a=1:1
nv42 => [pa] [un] yuv444p | a=1:1
opencl => no
p010 => [pa] [un] yuv420p16 | a=2:2
p010be => [pa] [un] yuv420p16 | a=2:2
p016 => [pa] [un] yuv420p16 | a=2:2
p016be => [pa] [un] yuv420p16 | a=2:2
pal8 => [un] gbrap | a=1:1
qsv => no
rgb0 => [pa] [un] gbrp | a=1:1 [tu] [tp]
rgb24 => [pa] [un] gbrp | a=1:1
rgb30 => [pa] [un] gbrp10 | a=1:1
rgb4 => no
rgb444 => [pa] [un] gbrp4 | a=1:1
rgb444 => [pa] [un] gbrp | a=1:1 [expand-8bit]
rgb444be => [pa] [un] gbrp4 | a=1:1
rgb444be => [pa] [un] gbrp | a=1:1 [expand-8bit]
rgb48 => [pa] [un] gbrp16 | a=1:1
rgb48be => [pa] [un] gbrp16 | a=1:1 [tu] [tp]
rgb4_byte => [pa] [un] gbrp2 | a=1:1
rgb4_byte => [pa] [un] gbrp1 | a=1:1 [round-down]
rgb4_byte => [pa] [un] gbrp | a=1:1 [expand-8bit]
rgb555 => [pa] [un] gbrp5 | a=1:1
rgb555 => [pa] [un] gbrp | a=1:1 [expand-8bit]
rgb555be => [pa] [un] gbrp5 | a=1:1
rgb555be => [pa] [un] gbrp | a=1:1 [expand-8bit]
rgb565 => [pa] [un] gbrp6 | a=1:1
rgb565 => [pa] [un] gbrp5 | a=1:1 [round-down]
rgb565 => [pa] [un] gbrp | a=1:1 [expand-8bit]
rgb565be => [pa] [un] gbrp6 | a=1:1
rgb565be => [pa] [un] gbrp5 | a=1:1 [round-down]
rgb565be => [pa] [un] gbrp | a=1:1 [expand-8bit]
rgb8 => [pa] [un] gbrp3 | a=1:1
rgb8 => [pa] [un] gbrp2 | a=1:1 [round-down]
rgb8 => [pa] [un] gbrp | a=1:1 [expand-8bit]
rgba => [pa] [un] gbrap | a=1:1 [tu] [tp]
rgba64 => [pa] [un] gbrap16 | a=1:1 [tu] [tp]
rgba64be => [pa] [un] gbrap16 | a=1:1
uyvy422 => [pa] [un] yuv422p | a=2:1
uyyvyy411 => no
vaapi => no
vaapi_idct => no
vaapi_moco => no
vdpau => no
vdpau_output => no
videotoolbox => no
vulkan => no
xvmc => no
xyz12 => [pa] [un] gbrp16 | a=1:1
xyz12be => [pa] [un] gbrp16 | a=1:1
y210 => [pa] [un] yuv422p16 | a=2:1
y210be => [pa] [un] yuv422p16 | a=2:1
ya16 => [pa] [un] yap16 | a=1:1 [tu] [tp]
ya16be => [pa] [un] yap16 | a=1:1
ya8 => [pa] [un] yap8 | a=1:1
yuv420p10be => [pa] [un] yuv420p10 | a=2:2
yuv420p12be => [pa] [un] yuv420p12 | a=2:2
yuv420p14be => [pa] [un] yuv420p14 | a=2:2
yuv420p16be => [pa] [un] yuv420p16 | a=2:2
yuv420p9be => [pa] [un] yuv420p9 | a=2:2
yuv422p10be => [pa] [un] yuv422p10 | a=2:1
yuv422p12be => [pa] [un] yuv422p12 | a=2:1
yuv422p14be => [pa] [un] yuv422p14 | a=2:1
yuv422p16be => [pa] [un] yuv422p16 | a=2:1 [tu] [tp]
yuv422p9be => [pa] [un] yuv422p9 | a=2:1
yuv440p10be => [pa] [un] yuv440p10 | a=1:2
yuv440p12be => [pa] [un] yuv440p12 | a=1:2
yuv444p10be => [pa] [un] yuv444p10 | a=1:1
yuv444p12be => [pa] [un] yuv444p12 | a=1:1
yuv444p14be => [pa] [un] yuv444p14 | a=1:1
yuv444p16be => [pa] [un] yuv444p16 | a=1:1
yuv444p9be => [pa] [un] yuv444p9 | a=1:1
yuva420p10be => [pa] [un] yuva420p10 | a=2:2
yuva420p16be => [pa] [un] yuva420p16 | a=2:2
yuva420p9be => [pa] [un] yuva420p9 | a=2:2
yuva422p10be => [pa] [un] yuva422p10 | a=2:1
yuva422p12be => [pa] [un] yuva422p12 | a=2:1
yuva422p16be => [pa] [un] yuva422p16 | a=2:1
yuva422p9be => [pa] [un] yuva422p9 | a=2:1
yuva444p10be => [pa] [un] yuva444p10 | a=1:1
yuva444p12be => [pa] [un] yuva444p12 | a=1:1
yuva444p16be => [pa] [un] yuva444p16 | a=1:1
yuva444p9be => [pa] [un] yuva444p9 | a=1:1
yuyv422 => [pa] [un] yuv422p | a=2:1
yvyu422 => [pa] [un] yuv422p | a=2:1 [tu] [tp]
+249
View File
@@ -0,0 +1,249 @@
#include <libavutil/pixfmt.h>
#include "common/common.h"
#include "tests.h"
#include "video/fmt-conversion.h"
#include "video/img_format.h"
#include "video/repack.h"
#include "video/zimg.h"
// Excuse the utter stupidity.
#define UNFUCK(v) ((v) > 0 ? (v) : pixfmt2imgfmt(-(v)))
static_assert(IMGFMT_START > 0, "");
#define IMGFMT_GBRP (-AV_PIX_FMT_GBRP)
#define IMGFMT_GBRAP (-AV_PIX_FMT_GBRAP)
struct entry {
int w, h;
int fmt_a;
const void *const a[4];
int fmt_b;
const void *const b[4];
int flags;
};
#define P8(...) (const uint8_t[]){__VA_ARGS__}
#define P16(...) (const uint16_t[]){__VA_ARGS__}
// Warning: only entries that match existing conversions are tested.
static const struct entry repack_tests[] = {
// Note: the '0' tests rely on 0 being written, although by definition the
// contents of this padding is undefined. The repacker always writes
// it this way, though.
{1, 1, IMGFMT_RGB0, {P8(1, 2, 3, 0)},
IMGFMT_GBRP, {P8(2), P8(3), P8(1)}},
{1, 1, IMGFMT_BGR0, {P8(1, 2, 3, 0)},
IMGFMT_GBRP, {P8(2), P8(1), P8(3)}},
{1, 1, IMGFMT_0RGB, {P8(0, 1, 2, 3)},
IMGFMT_GBRP, {P8(2), P8(3), P8(1)}},
{1, 1, IMGFMT_0BGR, {P8(0, 1, 2, 3)},
IMGFMT_GBRP, {P8(2), P8(1), P8(3)}},
{1, 1, IMGFMT_RGBA, {P8(1, 2, 3, 4)},
IMGFMT_GBRAP, {P8(2), P8(3), P8(1), P8(4)}},
{1, 1, IMGFMT_BGRA, {P8(1, 2, 3, 4)},
IMGFMT_GBRAP, {P8(2), P8(1), P8(3), P8(4)}},
{1, 1, IMGFMT_ARGB, {P8(4, 1, 2, 3)},
IMGFMT_GBRAP, {P8(2), P8(3), P8(1), P8(4)}},
{1, 1, IMGFMT_ABGR, {P8(4, 1, 2, 3)},
IMGFMT_GBRAP, {P8(2), P8(1), P8(3), P8(4)}},
{1, 1, IMGFMT_RGBA64, {P16(0x1a1b, 0x2a2b, 0x3a3b, 0x4a4b)},
-AV_PIX_FMT_GBRAP16, {P16(0x2a2b), P16(0x3a3b),
P16(0x1a1b), P16(0x4a4b)}},
{1, 1, -AV_PIX_FMT_RGB48BE, {P16(0x1a1b, 0x2a2b, 0x3a3b)},
-AV_PIX_FMT_GBRP16, {P16(0x2b2a), P16(0x3b3a),
P16(0x1b1a)}},
{8, 1, -AV_PIX_FMT_MONOWHITE, {P8(0xAA)},
IMGFMT_Y1, {P8(0, 1, 0, 1, 0, 1, 0, 1)}},
{8, 1, -AV_PIX_FMT_MONOBLACK, {P8(0xAA)},
IMGFMT_Y1, {P8(1, 0, 1, 0, 1, 0, 1, 0)}},
{2, 2, IMGFMT_NV12, {P8(1, 2, 3, 4), P8(5, 6)},
IMGFMT_420P, {P8(1, 2, 3, 4), P8(5), P8(6)}},
{2, 2, -AV_PIX_FMT_NV21, {P8(1, 2, 3, 4), P8(5, 6)},
IMGFMT_420P, {P8(1, 2, 3, 4), P8(6), P8(5)}},
{1, 1, -AV_PIX_FMT_AYUV64, {P16(1, 2, 3, 4)},
-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_YVYU422, {P8(1, 2, 3, 4)},
-AV_PIX_FMT_YUV422P, {P8(1, 3), P8(4), P8(2)}},
{1, 1, -AV_PIX_FMT_YA16, {P16(1, 2)},
IMGFMT_YAP16, {P16(1), P16(2)}},
{2, 1, -AV_PIX_FMT_YUV422P16BE, {P16(0x1a1b, 0x2a2b), P16(0x3a3b),
P16(0x4a4b)},
-AV_PIX_FMT_YUV422P16, {P16(0x1b1a, 0x2b2a), P16(0x3b3a),
P16(0x4b4a)}},
};
static bool is_true_planar(int imgfmt)
{
struct mp_regular_imgfmt desc;
if (!mp_get_regular_imgfmt(&desc, imgfmt))
return false;
for (int n = 0; n < desc.num_planes; n++) {
if (desc.planes[n].num_components != 1)
return false;
}
return true;
}
static int try_repack(struct test_ctx *ctx, FILE *f, int imgfmt, int flags,
int not_if_fmt)
{
char *head = mp_tprintf(80, "%-15s =>", mp_imgfmt_to_name(imgfmt));
struct mp_repack *un = mp_repack_create_planar(imgfmt, false, flags);
struct mp_repack *pa = mp_repack_create_planar(imgfmt, true, flags);
// If both exists, they must be always symmetric.
if (un && pa) {
assert(mp_repack_get_format_src(pa) == mp_repack_get_format_dst(un));
assert(mp_repack_get_format_src(un) == mp_repack_get_format_dst(pa));
assert(mp_repack_get_align_x(pa) == mp_repack_get_align_x(un));
assert(mp_repack_get_align_y(pa) == mp_repack_get_align_y(un));
}
int a = 0;
int b = 0;
if (un) {
a = mp_repack_get_format_src(un);
b = mp_repack_get_format_dst(un);
} else if (pa) {
a = mp_repack_get_format_dst(pa);
b = mp_repack_get_format_src(pa);
}
// Skip the identity ones because they're uninteresting, and add too much
// noise. But still make sure they behave as expected.
if (is_true_planar(imgfmt)) {
// (note that we require alpha-enabled zimg)
assert(mp_zimg_supports_in_format(imgfmt));
assert(un && pa);
assert(a == imgfmt && b == imgfmt);
talloc_free(pa);
talloc_free(un);
return 0;
}
struct mp_repack *rp = pa ? pa : un;
if (!rp) {
if (!flags)
fprintf(f, "%s no\n", head);
return 0;
}
assert(a == imgfmt);
if (b && b == not_if_fmt) {
talloc_free(pa);
talloc_free(un);
return 0;
}
fprintf(f, "%s %4s %4s %-15s |", head, pa ? "[pa]" : "", un ? "[un]" : "",
mp_imgfmt_to_name(b));
fprintf(f, " a=%d:%d", mp_repack_get_align_x(rp), mp_repack_get_align_y(rp));
if (flags & REPACK_CREATE_ROUND_DOWN)
fprintf(f, " [round-down]");
if (flags & REPACK_CREATE_EXPAND_8BIT)
fprintf(f, " [expand-8bit]");
// LCM of alignment of all packers.
int ax = mp_repack_get_align_x(rp);
int ay = mp_repack_get_align_y(rp);
if (pa && un) {
ax = MPMAX(mp_repack_get_align_x(pa), mp_repack_get_align_x(un));
ay = MPMAX(mp_repack_get_align_y(pa), mp_repack_get_align_y(un));
}
for (int n = 0; n < MP_ARRAY_SIZE(repack_tests); n++) {
const struct entry *e = &repack_tests[n];
int fmt_a = UNFUCK(e->fmt_a);
int fmt_b = UNFUCK(e->fmt_b);
if (!(fmt_a == a && fmt_b == b && e->flags == flags))
continue;
// We convert a "random" macro pixel to catch potential addressing bugs
// that might be ignored with (0, 0) origins.
struct mp_image *ia = mp_image_alloc(fmt_a, e->w * 5 * ax, e->h * 5 * ay);
struct mp_image *ib = mp_image_alloc(fmt_b, e->w * 7 * ax, e->h * 6 * ay);
int sx = 4 * ax, sy = 3 * ay, dx = 3 * ax, dy = 2 * ay;
assert(ia && ib);
for (int pack = 0; pack < 2; pack++) {
struct mp_repack *repacker = pack ? pa : un;
if (!repacker)
continue;
mp_image_clear(ia, 0, 0, ia->w, ia->h);
mp_image_clear(ib, 0, 0, ib->w, ib->h);
const void *const *dstd = pack ? e->a : e->b;
const void *const *srcd = pack ? e->b : e->a;
struct mp_image *dsti = pack ? ia : ib;
struct mp_image *srci = pack ? ib : ia;
bool r = repack_config_buffers(repacker, 0, dsti, 0, srci, NULL);
assert(r);
for (int p = 0; p < srci->num_planes; p++) {
uint8_t *ptr = mp_image_pixel_ptr(srci, p, sx, sy);
for (int y = 0; y < e->h >> srci->fmt.ys[p]; y++) {
int w = e->w >> srci->fmt.xs[p];
int wb = (w * srci->fmt.bpp[p] + 7) / 8;
const void *cptr = (uint8_t *)srcd[p] + wb * y;
memcpy(ptr + srci->stride[p] * y, cptr, wb);
}
}
repack_line(repacker, dx, dy, sx, sy, e->w);
for (int p = 0; p < dsti->num_planes; p++) {
uint8_t *ptr = mp_image_pixel_ptr(dsti, p, dx, dy);
for (int y = 0; y < e->h >> dsti->fmt.ys[p]; y++) {
int w = e->w >> dsti->fmt.xs[p];
int wb = (w * dsti->fmt.bpp[p] + 7) / 8;
const void *cptr = (uint8_t *)dstd[p] + wb * y;
assert_memcmp(ptr + dsti->stride[p] * y, cptr, wb);
}
}
fprintf(f, " [t%s]", pack ? "p" : "u");
}
talloc_free(ia);
talloc_free(ib);
}
fprintf(f, "\n");
talloc_free(pa);
talloc_free(un);
return b;
}
static void run(struct test_ctx *ctx)
{
FILE *f = test_open_out(ctx, "repack.txt");
init_imgfmts_list();
for (int n = 0; n < num_imgfmts; n++) {
int imgfmt = imgfmts[n];
int other = try_repack(ctx, f, imgfmt, 0, 0);
try_repack(ctx, f, imgfmt, REPACK_CREATE_ROUND_DOWN, other);
try_repack(ctx, f, imgfmt, REPACK_CREATE_EXPAND_8BIT, other);
}
fclose(f);
assert_text_files_equal(ctx, "repack.txt", "repack.txt",
"This can fail if FFmpeg/libswscale adds or removes pixfmts.");
}
const struct unittest test_repack = {
.name = "repack",
.run = run,
};
+23
View File
@@ -12,6 +12,7 @@ static const struct unittest *unittests[] = {
&test_paths,
&test_repack_sws,
#if HAVE_ZIMG
&test_repack, // zimg only due to cross-checking with zimg.c
&test_repack_zimg,
#endif
NULL
@@ -128,3 +129,25 @@ void assert_text_files_equal_impl(const char *file, int line,
abort();
}
}
static void hexdump(const uint8_t *d, size_t size)
{
printf("|");
while (size--) {
printf(" %02x", d[0]);
d++;
}
printf(" |\n");
}
void assert_memcmp_impl(const char *file, int line,
const void *a, const void *b, size_t size)
{
if (memcmp(a, b, size) == 0)
return;
printf("%s:%d: mismatching data:\n", file, line);
hexdump(a, size);
hexdump(b, size);
abort();
}
+7
View File
@@ -43,6 +43,7 @@ extern const struct unittest test_json;
extern const struct unittest test_linked_list;
extern const struct unittest test_repack_sws;
extern const struct unittest test_repack_zimg;
extern const struct unittest test_repack;
extern const struct unittest test_paths;
#define assert_true(x) assert(x)
@@ -54,6 +55,10 @@ extern const struct unittest test_paths;
#define assert_float_equal(a, b, tolerance) \
assert_float_equal_impl(__FILE__, __LINE__, (a), (b), (tolerance))
// Assert that memcmp(a,b,s)==0, or hexdump output on failure.
#define assert_memcmp(a, b, s) \
assert_memcmp_impl(__FILE__, __LINE__, (a), (b), (s))
// Require that the files "ref" and "new" are the same. The paths can be
// relative to ref_path and out_path respectively. If they're not the same,
// the output of "diff" is shown, the err message (if not NULL), and the test
@@ -69,6 +74,8 @@ void assert_float_equal_impl(const char *file, int line,
void assert_text_files_equal_impl(const char *file, int line,
struct test_ctx *ctx, const char *ref,
const char *new, const char *err);
void assert_memcmp_impl(const char *file, int line,
const void *a, const void *b, size_t size);
// Open a new file in the out_path. Always succeeds.
FILE *test_open_out(struct test_ctx *ctx, const char *name);
+2 -1
View File
@@ -69,8 +69,9 @@ struct mp_imgfmt_desc {
int flags; // MP_IMGFLAG_* bitfield
int8_t num_planes;
int8_t chroma_xs, chroma_ys; // chroma shift (i.e. log2 of chroma pixel size)
int8_t align_x, align_y; // pixel size to get byte alignment and to get
int8_t align_x, align_y; // pixel count to get byte alignment and to get
// to a pixel pos where luma & chroma aligns
// always power of 2
int8_t bytes[MP_MAX_PLANES]; // bytes per pixel (MP_IMGFLAG_BYTE_ALIGNED)
int8_t bpp[MP_MAX_PLANES]; // bits per pixel
int8_t plane_bits; // number of bits in use for plane 0
+1110
View File
File diff suppressed because it is too large Load Diff
+72
View File
@@ -0,0 +1,72 @@
#pragma once
#include <stdbool.h>
enum {
// This controls bheavior with different bit widths per component (like
// RGB565). If ROUND_DOWN is specified, the planar format will use the min.
// bit width of all components, otherwise the transformation is lossless.
REPACK_CREATE_ROUND_DOWN = (1 << 0),
// Expand some (not all) low bit depth fringe formats to 8 bit on unpack.
REPACK_CREATE_EXPAND_8BIT = (1 << 1),
};
struct mp_repack;
struct mp_image;
// Create a repacker between any format (imgfmt parameter) and an equivalent
// planar format (that is native endian). If pack==true, imgfmt is the output,
// otherwise it is the input. The respective other input/output is the planar
// format. The planar format can be queried with mp_repack_get_format_*().
// Note that some formats may change the "implied" colorspace (for example,
// packed xyz unpacks as rgb).
// If imgfmt is already planar, a passthrough repacker may be created.
// imgfmt: src or dst format (usually packed, non-planar, etc.)
// pack: true if imgfmt is dst, false if imgfmt is src
// flags: any of REPACK_CREATE_* flags
// returns: NULL on failure, otherwise free with talloc_free().
struct mp_repack *mp_repack_create_planar(int imgfmt, bool pack, int flags);
// Return input and output formats for which rp was created.
int mp_repack_get_format_src(struct mp_repack *rp);
int mp_repack_get_format_dst(struct mp_repack *rp);
// Return pixel alignment. For x, this is a lowest pixel count at which there is
// a byte boundary and a full chroma pixel (horizontal subsampling) on src/dst.
// For y, this is the pixel height of the vertical subsampling.
// Always returns a power of 2.
int mp_repack_get_align_x(struct mp_repack *rp);
int mp_repack_get_align_y(struct mp_repack *rp);
// Repack a single line from dst to src, as set in repack_config_buffers().
// For subsampled chroma formats, this copies as many luma/alpha rows as needed
// for a complete line (e.g. 2 luma lines, 1 chroma line for 4:2:0).
// dst_x, src_x, y must be aligned to the pixel alignment. w may be unaligned
// if at the right crop-border of the image, but must be always aligned to
// horiz. sub-sampling. y is subject to hslice.
void repack_line(struct mp_repack *rp, int dst_x, int dst_y,
int src_x, int src_y, int w);
// Configure with a source and target buffer. The rp instance will keep the
// mp_image pointers and access them on repack_line() calls. Refcounting is
// not respected - the caller needs to make sure dst is always writable.
// The images can have different sizes (as repack_line() lets you use different
// target coordinates for dst/src).
// This also allocaters potentially required temporary buffers.
// dst_flags: REPACK_BUF_* flags for dst
// dst: where repack_line() writes to
// src_flags: REPACK_BUF_* flags for src
// src: where repack_line() reads from
// enable_passthrough: if non-NULL, an bool array of size MP_MAX_PLANES indexed
// by plane; a true entry requests disabling copying the
// plane data to the dst plane. The function will write to
// this array whether the plane can really be passed through
// (i.e. will set array entries from true to false if pass-
// through is not possible). It writes to all MP_MAX_PLANES
// entries. If NULL, all entries are implicitly false.
// returns: success (fails on OOM)
bool repack_config_buffers(struct mp_repack *rp,
int dst_flags, struct mp_image *dst,
int src_flags, struct mp_image *src,
bool *enable_passthrough);
+69 -903
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -402,6 +402,7 @@ def build(ctx):
( "test/json.c", "tests" ),
( "test/linked_list.c", "tests" ),
( "test/paths.c", "tests" ),
( "test/repack.c", "tests && zimg" ),
( "test/scale_sws.c", "tests" ),
( "test/scale_test.c", "tests" ),
( "test/scale_zimg.c", "tests && zimg" ),
@@ -529,6 +530,7 @@ def build(ctx):
( "video/out/win32/droptarget.c", "win32-desktop" ),
( "video/out/win_state.c"),
( "video/out/x11_common.c", "x11" ),
( "video/repack.c" ),
( "video/sws_utils.c" ),
( "video/zimg.c", "zimg" ),
( "video/vaapi.c", "vaapi" ),