video: clean up pixel metadata stuff some more

A repeat of the previous useless commits.

Pondered whether to use separate fields or just a flags integer for
color and component types; the latter won for now.

Functions like mp_imgfmt_get_component_type() are now discouraged, and
mp_imgfmt_desc.flags is back for defining all information. Some days ago
I felt like the opposite would be the better design. Fortunately, it
doesn't matter.

With this, I think all image format properties that mpv needs are
exhaustively defined all in one place.
This commit is contained in:
wm4 2020-05-20 18:25:14 +02:00
parent a078d07ea2
commit 086953a9da
4 changed files with 545 additions and 509 deletions

View File

@ -85,15 +85,20 @@ static void run(struct test_ctx *ctx)
fprintf(f, " Basic desc: ");
#define FLAG(t, c) if (d.flags & (t)) fprintf(f, "[%s]", c);
FLAG(MP_IMGFLAG_BYTE_ALIGNED, "ba")
FLAG(MP_IMGFLAG_BYTES, "bb")
FLAG(MP_IMGFLAG_ALPHA, "a")
FLAG(MP_IMGFLAG_YUV_P, "yuvp")
FLAG(MP_IMGFLAG_YUV_NV, "nv")
FLAG(MP_IMGFLAG_YUV, "yuv")
FLAG(MP_IMGFLAG_RGB, "rgb")
FLAG(MP_IMGFLAG_COLOR_YUV, "yuv")
FLAG(MP_IMGFLAG_COLOR_RGB, "rgb")
FLAG(MP_IMGFLAG_COLOR_XYZ, "xyz")
FLAG(MP_IMGFLAG_GRAY, "gray")
FLAG(MP_IMGFLAG_LE, "le")
FLAG(MP_IMGFLAG_BE, "be")
FLAG(MP_IMGFLAG_PAL, "pal")
FLAG(MP_IMGFLAG_HWACCEL, "hw")
FLAG(MP_IMGFLAG_TYPE_PAL8, "pal")
FLAG(MP_IMGFLAG_TYPE_HW, "hw")
FLAG(MP_IMGFLAG_TYPE_FLOAT, "float")
FLAG(MP_IMGFLAG_TYPE_UINT, "uint")
fprintf(f, "\n");
fprintf(f, " planes=%d, chroma=%d:%d align=%d:%d\n",
d.num_planes, d.chroma_xs, d.chroma_ys, d.align_x, d.align_y);

File diff suppressed because it is too large Load Diff

View File

@ -31,108 +31,90 @@
struct mp_imgfmt_entry {
const char *name;
// valid if desc.id is set
// Valid if flags!=0.
// This can be incomplete, and missing fields are filled in:
// - sets num_planes and bpp[], derived from comps[] (rounds to bytes)
// - sets MP_IMGFLAG_GRAY, derived from comps[]
// - sets MP_IMGFLAG_ALPHA, derived from comps[]
// - sets align_x/y if 0, derived from chroma shift
// - sets xs[]/ys[] always, derived from num_planes/chroma_shift
// - sets MP_IMGFLAG_HAS_COMPS|MP_IMGFLAG_NE if num_planes>0
// - sets MP_IMGFLAG_TYPE_UINT if no other type set
// - sets id to mp_imgfmt_list[] implied format
// - sets avformat to AV_PIX_FMT_NONE
struct mp_imgfmt_desc desc;
// valid if reg_desc.component_size is set
struct mp_regular_imgfmt reg_desc;
// valid if non-0 and no reg_desc
enum mp_csp forced_csp;
enum mp_component_type ctype;
};
#define FRINGE_GBRP(def, dname, bits) \
#define FRINGE_GBRP(def, dname, b) \
[def - IMGFMT_CUST_BASE] = { \
.name = dname, \
.reg_desc = { .component_type = MP_COMPONENT_TYPE_UINT, \
.component_size = 1, .component_pad = bits - 8, \
.num_planes = 3, .forced_csp = MP_CSP_RGB, \
.planes = { {1, {2}}, {1, {3}}, {1, {1}} }, }, }
.desc = { .flags = MP_IMGFLAG_COLOR_RGB, \
.comps = { {2, 0, 8, (b) - 8}, {0, 0, 8, (b) - 8}, \
{1, 0, 8, (b) - 8}, }, }}
#define FLOAT_YUV(def, dname, xs, ys, a_planes) \
#define FLOAT_YUV(def, dname, xs, ys, a) \
[def - IMGFMT_CUST_BASE] = { \
.name = dname, \
.reg_desc = { .component_type = MP_COMPONENT_TYPE_FLOAT, \
.component_size = 4, .num_planes = a_planes, \
.planes = { {1, {1}}, {1, {2}}, {1, {3}}, {1, {4}} }, \
.chroma_xs = xs, .chroma_ys = ys, }}
.desc = { .flags = MP_IMGFLAG_COLOR_YUV | MP_IMGFLAG_TYPE_FLOAT, \
.chroma_xs = xs, .chroma_ys = ys, \
.comps = { {0, 0, 32}, {1, 0, 32}, {2, 0, 32}, \
{3 * (a), 0, 32 * (a)} }, }}
static const struct mp_imgfmt_entry mp_imgfmt_list[] = {
// not in ffmpeg
[IMGFMT_VDPAU_OUTPUT - IMGFMT_CUST_BASE] = {
.name = "vdpau_output",
.desc = {
.id = IMGFMT_VDPAU_OUTPUT,
.avformat = AV_PIX_FMT_NONE,
.flags = MP_IMGFLAG_BE | MP_IMGFLAG_LE | MP_IMGFLAG_RGB |
MP_IMGFLAG_HWACCEL,
.flags = MP_IMGFLAG_NE | MP_IMGFLAG_RGB | MP_IMGFLAG_HWACCEL,
},
},
[IMGFMT_RGB30 - IMGFMT_CUST_BASE] = {
.name = "rgb30",
.desc = {
.id = IMGFMT_RGB30,
.avformat = AV_PIX_FMT_NONE,
.flags = MP_IMGFLAG_BYTE_ALIGNED | MP_IMGFLAG_NE | MP_IMGFLAG_RGB |
MP_IMGFLAG_HAS_COMPS,
.num_planes = 1,
.align_x = 1,
.align_y = 1,
.bpp = {32},
.flags = MP_IMGFLAG_RGB,
.comps = { {0, 20, 10}, {0, 10, 10}, {0, 0, 10} },
},
.forced_csp = MP_CSP_RGB,
.ctype = MP_COMPONENT_TYPE_UINT,
},
[IMGFMT_YAP8 - IMGFMT_CUST_BASE] = {
.name = "yap8",
.reg_desc = {
.component_type = MP_COMPONENT_TYPE_UINT,
.component_size = 1,
.num_planes = 2,
.planes = { {1, {1}}, {1, {4}} },
.desc = {
.flags = MP_IMGFLAG_COLOR_YUV,
.comps = { {0, 0, 8}, {0}, {0}, {1, 0, 8} },
},
},
[IMGFMT_YAP16 - IMGFMT_CUST_BASE] = {
.name = "yap16",
.reg_desc = {
.component_type = MP_COMPONENT_TYPE_UINT,
.component_size = 2,
.num_planes = 2,
.planes = { {1, {1}}, {1, {4}} },
.desc = {
.flags = MP_IMGFLAG_COLOR_YUV,
.comps = { {0, 0, 16}, {0}, {0}, {1, 0, 16} },
},
},
[IMGFMT_Y1 - IMGFMT_CUST_BASE] = {
.name = "y1",
.reg_desc = {
.component_type = MP_COMPONENT_TYPE_UINT,
.component_size = 1,
.component_pad = -7,
.num_planes = 1,
.forced_csp = MP_CSP_RGB,
.planes = { {1, {1}} },
.desc = {
.flags = MP_IMGFLAG_COLOR_RGB,
.comps = { {0, 0, 8, -7} },
},
},
[IMGFMT_YAPF - IMGFMT_CUST_BASE] = {
.name = "grayaf32", // try to mimic ffmpeg naming convention
.reg_desc = {
.component_type = MP_COMPONENT_TYPE_FLOAT,
.component_size = 4,
.num_planes = 2,
.planes = { {1, {1}}, {1, {4}} },
.desc = {
.flags = MP_IMGFLAG_COLOR_YUV | MP_IMGFLAG_TYPE_FLOAT,
.comps = { {0, 0, 32}, {0}, {0}, {1, 0, 32} },
},
},
FLOAT_YUV(IMGFMT_444PF, "yuv444pf", 0, 0, 3),
FLOAT_YUV(IMGFMT_444APF, "yuva444pf", 0, 0, 4),
FLOAT_YUV(IMGFMT_420PF, "yuv420pf", 1, 1, 3),
FLOAT_YUV(IMGFMT_420APF, "yuva420pf", 1, 1, 4),
FLOAT_YUV(IMGFMT_422PF, "yuv422pf", 1, 0, 3),
FLOAT_YUV(IMGFMT_422APF, "yuva422pf", 1, 0, 4),
FLOAT_YUV(IMGFMT_440PF, "yuv440pf", 0, 1, 3),
FLOAT_YUV(IMGFMT_440APF, "yuva440pf", 0, 1, 4),
FLOAT_YUV(IMGFMT_410PF, "yuv410pf", 2, 2, 3),
FLOAT_YUV(IMGFMT_410APF, "yuva410pf", 2, 2, 4),
FLOAT_YUV(IMGFMT_411PF, "yuv411pf", 2, 0, 3),
FLOAT_YUV(IMGFMT_411APF, "yuva411pf", 2, 0, 4),
FLOAT_YUV(IMGFMT_444PF, "yuv444pf", 0, 0, 0),
FLOAT_YUV(IMGFMT_444APF, "yuva444pf", 0, 0, 1),
FLOAT_YUV(IMGFMT_420PF, "yuv420pf", 1, 1, 0),
FLOAT_YUV(IMGFMT_420APF, "yuva420pf", 1, 1, 1),
FLOAT_YUV(IMGFMT_422PF, "yuv422pf", 1, 0, 0),
FLOAT_YUV(IMGFMT_422APF, "yuva422pf", 1, 0, 1),
FLOAT_YUV(IMGFMT_440PF, "yuv440pf", 0, 1, 0),
FLOAT_YUV(IMGFMT_440APF, "yuva440pf", 0, 1, 1),
FLOAT_YUV(IMGFMT_410PF, "yuv410pf", 2, 2, 0),
FLOAT_YUV(IMGFMT_410APF, "yuva410pf", 2, 2, 1),
FLOAT_YUV(IMGFMT_411PF, "yuv411pf", 2, 0, 0),
FLOAT_YUV(IMGFMT_411APF, "yuva411pf", 2, 0, 1),
FRINGE_GBRP(IMGFMT_GBRP1, "gbrp1", 1),
FRINGE_GBRP(IMGFMT_GBRP2, "gbrp2", 2),
FRINGE_GBRP(IMGFMT_GBRP3, "gbrp3", 3),
@ -202,32 +184,6 @@ char *mp_imgfmt_to_name_buf(char *buf, size_t buf_size, int fmt)
return buf;
}
static struct mp_imgfmt_desc to_legacy_desc(int fmt, struct mp_regular_imgfmt reg)
{
struct mp_imgfmt_desc desc = {
.id = fmt,
.avformat = AV_PIX_FMT_NONE,
.flags = MP_IMGFLAG_BYTE_ALIGNED | MP_IMGFLAG_NE |
(reg.forced_csp ? MP_IMGFLAG_RGB | MP_IMGFLAG_RGB_P
: MP_IMGFLAG_YUV | MP_IMGFLAG_YUV_P),
.num_planes = reg.num_planes,
.chroma_xs = reg.chroma_xs,
.chroma_ys = reg.chroma_ys,
};
desc.align_x = 1 << reg.chroma_xs;
desc.align_y = 1 << reg.chroma_ys;
for (int p = 0; p < reg.num_planes; p++) {
desc.bpp[p] = reg.component_size * 8;
desc.xs[p] = p == 1 || p == 2 ? desc.chroma_xs : 0;
desc.ys[p] = p == 1 || p == 2 ? desc.chroma_ys : 0;
for (int c = 0; c < reg.planes[p].num_components; c++) {
if (reg.planes[p].components[c] == 4)
desc.flags |= MP_IMGFLAG_ALPHA;
}
}
return desc;
}
static void fill_pixdesc_layout(struct mp_imgfmt_desc *desc,
enum AVPixelFormat fmt,
const AVPixFmtDescriptor *pd)
@ -254,14 +210,13 @@ static void fill_pixdesc_layout(struct mp_imgfmt_desc *desc,
if (is_packed_ss_yuv)
desc->bpp[0] = pd->comp[1].step * 8;
int num_planes = 0;
int el_bits = (pd->flags & AV_PIX_FMT_FLAG_BITSTREAM) ? 1 : 8;
for (int c = 0; c < pd->nb_components; c++) {
const AVComponentDescriptor *d = &pd->comp[c];
if (d->plane >= MP_MAX_PLANES)
goto fail;
num_planes = MPMAX(num_planes, d->plane + 1);
desc->num_planes = MPMAX(desc->num_planes, d->plane + 1);
int plane_bits = desc->bpp[d->plane];
int c_bits = d->step * el_bits;
@ -340,7 +295,7 @@ static void fill_pixdesc_layout(struct mp_imgfmt_desc *desc,
};
}
for (int p = 0; p < num_planes; p++) {
for (int p = 0; p < desc->num_planes; p++) {
if (!desc->bpp[p])
goto fail; // plane doesn't exist
}
@ -414,7 +369,7 @@ static void fill_pixdesc_layout(struct mp_imgfmt_desc *desc,
if (is_packed_ss_yuv) {
desc->flags |= MP_IMGFLAG_PACKED_SS_YUV;
desc->bpp[0] /= 1 << pd->log2_chroma_w;
} else {
} else if (!any_shared_bits) {
desc->flags |= MP_IMGFLAG_HAS_COMPS;
}
@ -424,26 +379,19 @@ fail:
for (int n = 0; n < 4; n++)
desc->comps[n] = (struct mp_imgfmt_comp_desc){0};
// Average bit size fallback.
int num_av_planes = av_pix_fmt_count_planes(fmt);
for (int p = 0; p < num_av_planes; p++) {
desc->num_planes = av_pix_fmt_count_planes(fmt);
for (int p = 0; p < desc->num_planes; p++) {
int ls = av_image_get_linesize(fmt, 256, p);
desc->bpp[p] = ls > 0 ? ls * 8 / 256 : 0;
}
}
struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt)
static bool mp_imgfmt_get_desc_from_pixdesc(int mpfmt, struct mp_imgfmt_desc *out)
{
const struct mp_imgfmt_entry *mpdesc = get_mp_desc(mpfmt);
if (mpdesc && mpdesc->desc.id)
return mpdesc->desc;
if (mpdesc && mpdesc->reg_desc.component_size)
return to_legacy_desc(mpfmt, mpdesc->reg_desc);
enum AVPixelFormat fmt = imgfmt2pixfmt(mpfmt);
const AVPixFmtDescriptor *pd = av_pix_fmt_desc_get(fmt);
if (!pd || pd->nb_components > 4)
return (struct mp_imgfmt_desc) {0};
bool is_uint = mp_imgfmt_get_component_type(mpfmt) == MP_COMPONENT_TYPE_UINT;
return false;
struct mp_imgfmt_desc desc = {
.id = mpfmt,
@ -452,29 +400,44 @@ struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt)
.chroma_ys = pd->log2_chroma_h,
};
for (int c = 0; c < pd->nb_components; c++)
desc.num_planes = MPMAX(desc.num_planes, pd->comp[c].plane + 1);
if (pd->flags & AV_PIX_FMT_FLAG_ALPHA)
desc.flags |= MP_IMGFLAG_ALPHA;
for (int p = 0; p < desc.num_planes; p++) {
desc.xs[p] = (p == 1 || p == 2) ? desc.chroma_xs : 0;
desc.ys[p] = (p == 1 || p == 2) ? desc.chroma_ys : 0;
if (pd->flags & AV_PIX_FMT_FLAG_HWACCEL)
desc.flags |= MP_IMGFLAG_TYPE_HW;
// Pixdesc does not provide a flag for XYZ, so this is the best we can do.
if (strncmp(pd->name, "xyz", 3) == 0) {
desc.flags |= MP_IMGFLAG_COLOR_XYZ;
} else if (pd->flags & AV_PIX_FMT_FLAG_RGB) {
desc.flags |= MP_IMGFLAG_COLOR_RGB;
} else if (fmt == AV_PIX_FMT_MONOBLACK || fmt == AV_PIX_FMT_MONOWHITE) {
desc.flags |= MP_IMGFLAG_COLOR_RGB;
} else if (fmt == AV_PIX_FMT_PAL8) {
desc.flags |= MP_IMGFLAG_COLOR_RGB | MP_IMGFLAG_TYPE_PAL8;
}
if (pd->flags & AV_PIX_FMT_FLAG_FLOAT)
desc.flags |= MP_IMGFLAG_TYPE_FLOAT;
// Educated guess.
if (!(desc.flags & MP_IMGFLAG_COLOR_MASK) &&
!(desc.flags & MP_IMGFLAG_TYPE_HW))
desc.flags |= MP_IMGFLAG_COLOR_YUV;
desc.align_x = 1 << desc.chroma_xs;
desc.align_y = 1 << desc.chroma_ys;
fill_pixdesc_layout(&desc, fmt, pd);
if (desc.flags & (MP_IMGFLAG_HAS_COMPS | MP_IMGFLAG_PACKED_SS_YUV)) {
if (!(desc.flags & MP_IMGFLAG_TYPE_MASK))
desc.flags |= MP_IMGFLAG_TYPE_UINT;
}
if (desc.bpp[0] % 8u && (pd->flags & AV_PIX_FMT_FLAG_BITSTREAM))
desc.align_x = 8 / desc.bpp[0]; // expect power of 2
bool is_ba = desc.num_planes > 0;
for (int p = 0; p < desc.num_planes; p++)
is_ba = !(desc.bpp[p] % 8u);
if (is_ba)
desc.flags |= MP_IMGFLAG_BYTE_ALIGNED;
// Very heuristical.
bool is_be = desc.endian_shift > 0;
bool need_endian = (desc.comps[0].size % 8u && desc.bpp[0] > 8) ||
@ -486,49 +449,8 @@ struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt)
desc.flags |= MP_IMGFLAG_LE | MP_IMGFLAG_BE;
}
enum mp_csp csp = mp_imgfmt_get_forced_csp(mpfmt);
if ((pd->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
desc.flags |= MP_IMGFLAG_HWACCEL;
} else if (csp == MP_CSP_XYZ) {
/* nothing */
} else if (csp == MP_CSP_RGB) {
desc.flags |= MP_IMGFLAG_RGB;
} else {
desc.flags |= MP_IMGFLAG_YUV;
}
if (pd->flags & AV_PIX_FMT_FLAG_ALPHA)
desc.flags |= MP_IMGFLAG_ALPHA;
if (pd->flags & AV_PIX_FMT_FLAG_PAL)
desc.flags |= MP_IMGFLAG_PAL;
if ((desc.flags & (MP_IMGFLAG_YUV | MP_IMGFLAG_RGB))
&& (desc.flags & MP_IMGFLAG_BYTE_ALIGNED)
&& !(pd->flags & AV_PIX_FMT_FLAG_PAL)
&& is_uint)
{
bool same_depth = true;
for (int p = 0; p < desc.num_planes; p++)
same_depth &= desc.bpp[p] == desc.bpp[0];
if (same_depth && pd->nb_components == desc.num_planes) {
if (desc.flags & MP_IMGFLAG_YUV) {
desc.flags |= MP_IMGFLAG_YUV_P;
} else {
desc.flags |= MP_IMGFLAG_RGB_P;
}
}
if (pd->nb_components == 3 && desc.num_planes == 2 &&
desc.bpp[1] == desc.bpp[0] * 2 &&
(desc.flags & MP_IMGFLAG_YUV))
{
desc.flags |= MP_IMGFLAG_YUV_NV;
}
}
return desc;
*out = desc;
return true;
}
bool mp_imgfmt_get_packed_yuv_locations(int imgfmt, uint8_t *luma_offsets)
@ -574,6 +496,113 @@ bool mp_imgfmt_get_packed_yuv_locations(int imgfmt, uint8_t *luma_offsets)
return true;
}
static bool get_native_desc(int mpfmt, struct mp_imgfmt_desc *desc)
{
const struct mp_imgfmt_entry *p = get_mp_desc(mpfmt);
if (!p || !p->desc.flags)
return false;
*desc = p->desc;
// Fill in some fields mp_imgfmt_entry.desc is not required to set.
desc->id = mpfmt;
desc->avformat = AV_PIX_FMT_NONE;
for (int n = 0; n < MP_NUM_COMPONENTS; n++) {
struct mp_imgfmt_comp_desc *cd = &desc->comps[n];
if (cd->size)
desc->num_planes = MPMAX(desc->num_planes, cd->plane + 1);
desc->bpp[cd->plane] =
MPMAX(desc->bpp[cd->plane], MP_ALIGN_UP(cd->offset + cd->size, 8));
}
if (!desc->align_x && !desc->align_y) {
desc->align_x = 1 << desc->chroma_xs;
desc->align_y = 1 << desc->chroma_ys;
}
if (desc->num_planes)
desc->flags |= MP_IMGFLAG_HAS_COMPS | MP_IMGFLAG_NE;
if (!(desc->flags & MP_IMGFLAG_TYPE_MASK))
desc->flags |= MP_IMGFLAG_TYPE_UINT;
return true;
}
static int num_comps(int flags)
{
if (!(flags & MP_IMGFLAG_COLOR_MASK))
return 0;
return 3 + (flags & MP_IMGFLAG_GRAY ? -2 : 0) + !!(flags & MP_IMGFLAG_ALPHA);
}
struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt)
{
struct mp_imgfmt_desc desc;
if (!get_native_desc(mpfmt, &desc) &&
!mp_imgfmt_get_desc_from_pixdesc(mpfmt, &desc))
return (struct mp_imgfmt_desc){0};
for (int p = 0; p < desc.num_planes; p++) {
desc.xs[p] = (p == 1 || p == 2) ? desc.chroma_xs : 0;
desc.ys[p] = (p == 1 || p == 2) ? desc.chroma_ys : 0;
}
bool is_ba = desc.num_planes > 0;
for (int p = 0; p < desc.num_planes; p++)
is_ba = !(desc.bpp[p] % 8u);
if (is_ba)
desc.flags |= MP_IMGFLAG_BYTE_ALIGNED;
if (desc.flags & MP_IMGFLAG_HAS_COMPS) {
if (desc.comps[3].size)
desc.flags |= MP_IMGFLAG_ALPHA;
// Assuming all colors are (CCC+[A]) or (C+[A]), the latter being gray.
if (!desc.comps[1].size)
desc.flags |= MP_IMGFLAG_GRAY;
bool bb = true;
for (int n = 0; n < MP_NUM_COMPONENTS; n++) {
if (desc.comps[n].offset % 8u || desc.comps[n].size % 8u)
bb = false;
}
if (bb)
desc.flags |= MP_IMGFLAG_BYTES;
}
if ((desc.flags & (MP_IMGFLAG_YUV | MP_IMGFLAG_RGB))
&& (desc.flags & MP_IMGFLAG_HAS_COMPS)
&& (desc.flags & MP_IMGFLAG_BYTES)
&& ((desc.flags & MP_IMGFLAG_TYPE_MASK) == MP_IMGFLAG_TYPE_UINT))
{
int cnt = num_comps(desc.flags);
bool same_depth = true;
for (int p = 0; p < desc.num_planes; p++)
same_depth &= desc.bpp[p] == desc.bpp[0];
if (same_depth && cnt == desc.num_planes) {
if (desc.flags & MP_IMGFLAG_YUV) {
desc.flags |= MP_IMGFLAG_YUV_P;
} else {
desc.flags |= MP_IMGFLAG_RGB_P;
}
}
if (cnt == 3 && desc.num_planes == 2 &&
desc.bpp[1] == desc.bpp[0] * 2 &&
(desc.flags & MP_IMGFLAG_YUV))
{
desc.flags |= MP_IMGFLAG_YUV_NV;
}
}
return desc;
}
static bool validate_regular_imgfmt(const struct mp_regular_imgfmt *fmt)
{
bool present[MP_NUM_COMPONENTS] = {0};
@ -615,53 +644,36 @@ static bool validate_regular_imgfmt(const struct mp_regular_imgfmt *fmt)
return true;
}
enum mp_csp mp_imgfmt_get_forced_csp(int imgfmt)
static enum mp_csp get_forced_csp_from_flags(int flags)
{
const struct mp_imgfmt_entry *p = get_mp_desc(imgfmt);
if (p && p->reg_desc.component_size)
return p->reg_desc.forced_csp;
if (p && p->forced_csp)
return p->forced_csp;
enum AVPixelFormat pixfmt = imgfmt2pixfmt(imgfmt);
const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(pixfmt);
if (pixdesc && (pixdesc->flags & AV_PIX_FMT_FLAG_HWACCEL))
return MP_CSP_AUTO;
// FFmpeg does not provide a flag for XYZ, so this is the best we can do.
if (pixdesc && strncmp(pixdesc->name, "xyz", 3) == 0)
if (flags & MP_IMGFLAG_COLOR_XYZ)
return MP_CSP_XYZ;
if (pixdesc && (pixdesc->flags & AV_PIX_FMT_FLAG_RGB))
return MP_CSP_RGB;
if (pixfmt == AV_PIX_FMT_PAL8 ||
pixfmt == AV_PIX_FMT_MONOBLACK ||
pixfmt == AV_PIX_FMT_MONOWHITE)
if (flags & MP_IMGFLAG_COLOR_RGB)
return MP_CSP_RGB;
return MP_CSP_AUTO;
}
enum mp_component_type mp_imgfmt_get_component_type(int imgfmt)
enum mp_csp mp_imgfmt_get_forced_csp(int imgfmt)
{
const struct mp_imgfmt_entry *p = get_mp_desc(imgfmt);
if (p && p->reg_desc.component_size)
return p->reg_desc.component_type;
if (p && p->ctype)
return p->ctype;
return get_forced_csp_from_flags(mp_imgfmt_get_desc(imgfmt).flags);
}
const AVPixFmtDescriptor *pixdesc =
av_pix_fmt_desc_get(imgfmt2pixfmt(imgfmt));
static enum mp_component_type get_component_type_from_flags(int flags)
{
if (flags & MP_IMGFLAG_TYPE_UINT)
return MP_COMPONENT_TYPE_UINT;
if (!pixdesc || (pixdesc->flags & AV_PIX_FMT_FLAG_HWACCEL))
return MP_COMPONENT_TYPE_UNKNOWN;
if (pixdesc->flags & AV_PIX_FMT_FLAG_FLOAT)
if (flags & MP_IMGFLAG_TYPE_FLOAT)
return MP_COMPONENT_TYPE_FLOAT;
return MP_COMPONENT_TYPE_UINT;
return MP_COMPONENT_TYPE_UNKNOWN;
}
enum mp_component_type mp_imgfmt_get_component_type(int imgfmt)
{
return get_component_type_from_flags(mp_imgfmt_get_desc(imgfmt).flags);
}
int mp_find_other_endian(int imgfmt)
@ -671,12 +683,6 @@ int mp_find_other_endian(int imgfmt)
bool mp_get_regular_imgfmt(struct mp_regular_imgfmt *dst, int imgfmt)
{
const struct mp_imgfmt_entry *p = get_mp_desc(imgfmt);
if (p && p->reg_desc.component_size) {
*dst = p->reg_desc;
return true;
}
struct mp_regular_imgfmt res = {0};
struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(imgfmt);
@ -687,7 +693,7 @@ bool mp_get_regular_imgfmt(struct mp_regular_imgfmt *dst, int imgfmt)
if (desc.endian_shift || !(desc.flags & MP_IMGFLAG_HAS_COMPS))
return false;
res.component_type = mp_imgfmt_get_component_type(imgfmt);
res.component_type = get_component_type_from_flags(desc.flags);
if (!res.component_type)
return false;
@ -730,7 +736,7 @@ bool mp_get_regular_imgfmt(struct mp_regular_imgfmt *dst, int imgfmt)
res.chroma_xs = desc.chroma_xs;
res.chroma_ys = desc.chroma_ys;
res.forced_csp = mp_imgfmt_get_forced_csp(imgfmt);
res.forced_csp = get_forced_csp_from_flags(desc.flags);
if (!validate_regular_imgfmt(&res))
return false;

View File

@ -31,41 +31,53 @@
#endif
#define MP_MAX_PLANES 4
#define MP_NUM_COMPONENTS 4
// All pixels start in byte boundaries
#define MP_IMGFLAG_BYTE_ALIGNED 0x1
// mp_imgfmt_desc.comps[] is set to useful values. Some types of formats will
// use comps[], but not set this flag, because it doesn't cover all requirements
// (for example MP_IMGFLAG_PACKED_SS_YUV).
#define MP_IMGFLAG_HAS_COMPS (1 << 1)
// set if (possibly) alpha is included (might be not definitive for packed RGB)
#define MP_IMGFLAG_ALPHA 0x80
// set if it's YUV colorspace
#define MP_IMGFLAG_YUV 0x200
// set if it's RGB colorspace
#define MP_IMGFLAG_RGB 0x400
// set if the format is in a standard YUV format:
// - planar and yuv colorspace
// - chroma shift 0-2
// - 1-4 planes (1: gray, 2: gray/alpha, 3: yuv, 4: yuv/alpha)
// - 8-16 bit per pixel/plane, all planes have same depth,
// each plane has exactly one component
#define MP_IMGFLAG_YUV_P 0x1000
#define MP_IMGFLAG_HAS_COMPS (1 << 0)
// all components start on byte boundaries
#define MP_IMGFLAG_BYTES (1 << 1)
// all pixels start in byte boundaries
#define MP_IMGFLAG_BYTE_ALIGNED (1 << 2)
// set if in little endian, or endian independent
#define MP_IMGFLAG_LE 0x2000
#define MP_IMGFLAG_LE (1 << 3)
// set if in big endian, or endian independent
#define MP_IMGFLAG_BE 0x4000
#define MP_IMGFLAG_BE (1 << 4)
// set if in native (host) endian, or endian independent
#define MP_IMGFLAG_NE MP_SELECT_LE_BE(MP_IMGFLAG_LE, MP_IMGFLAG_BE)
// Carries a palette in plane[1] (see AV_PIX_FMT_PAL8 for format of the palette).
#define MP_IMGFLAG_PAL 0x8000
// planes don't contain real data
#define MP_IMGFLAG_HWACCEL 0x10000
// Like MP_IMGFLAG_YUV_P, but RGB. This can be e.g. AV_PIX_FMT_GBRP. The planes
// are always shuffled (G - B - R [- A]).
#define MP_IMGFLAG_RGB_P 0x40000
// Semi-planar YUV formats, like AV_PIX_FMT_NV12.
#define MP_IMGFLAG_YUV_NV 0x80000
#define MP_IMGFLAG_NE MP_SELECT_LE_BE(MP_IMGFLAG_LE, MP_IMGFLAG_BE)
// set if an alpha component is included
#define MP_IMGFLAG_ALPHA (1 << 5)
// color class flags - can use via bit tests, or use the mask and compare
#define MP_IMGFLAG_COLOR_MASK (15 << 6)
#define MP_IMGFLAG_COLOR_YUV (1 << 6)
#define MP_IMGFLAG_COLOR_RGB (2 << 6)
#define MP_IMGFLAG_COLOR_XYZ (4 << 6)
// component type flags (same access conventions as MP_IMGFLAG_COLOR_*)
#define MP_IMGFLAG_TYPE_MASK (15 << 10)
#define MP_IMGFLAG_TYPE_UINT (1 << 10)
#define MP_IMGFLAG_TYPE_FLOAT (2 << 10)
#define MP_IMGFLAG_TYPE_PAL8 (4 << 10)
#define MP_IMGFLAG_TYPE_HW (8 << 10)
#define MP_IMGFLAG_YUV MP_IMGFLAG_COLOR_YUV
#define MP_IMGFLAG_RGB MP_IMGFLAG_COLOR_RGB
#define MP_IMGFLAG_PAL MP_IMGFLAG_TYPE_PAL8
#define MP_IMGFLAG_HWACCEL MP_IMGFLAG_TYPE_HW
// 1 component format (or 2 components if MP_IMGFLAG_ALPHA is set).
// This should probably be a separate MP_IMGFLAG_COLOR_GRAY, but for now it
// is too much of a mess.
#define MP_IMGFLAG_GRAY (1 << 14)
// Packed, sub-sampled YUV format. Does not apply to packed non-subsampled YUV.
// These formats pack multiple pixels into one sample with strange organization.
@ -76,9 +88,22 @@
// get their offsets with mp_imgfmt_get_packed_yuv_locations(). Note that the
// component offsets can be >= bpp[0]; the actual range is bpp[0]*align_x.
// These formats have no alpha.
#define MP_IMGFLAG_PACKED_SS_YUV (1 << 20)
#define MP_IMGFLAG_PACKED_SS_YUV (1 << 15)
#define MP_NUM_COMPONENTS 4
// set if the format is in a standard YUV format:
// - planar and yuv colorspace
// - chroma shift 0-2
// - 1-4 planes (1: gray, 2: gray/alpha, 3: yuv, 4: yuv/alpha)
// - 8-16 bit per pixel/plane, all planes have same depth,
// each plane has exactly one component
#define MP_IMGFLAG_YUV_P (1 << 16)
// Like MP_IMGFLAG_YUV_P, but RGB. This can be e.g. AV_PIX_FMT_GBRP. The planes
// are always shuffled (G - B - R [- A]).
#define MP_IMGFLAG_RGB_P (1 << 17)
// Semi-planar YUV formats, like AV_PIX_FMT_NV12.
#define MP_IMGFLAG_YUV_NV (1 << 18)
struct mp_imgfmt_comp_desc {
// Plane on which this component is.
@ -113,8 +138,8 @@ struct mp_imgfmt_desc {
// MP_IMGFLAG_HAS_COMPS set.
// This is indexed by component_type-1 (so 0=R, 1=G, etc.), see
// mp_regular_imgfmt_plane.components[x] for component_type. Components not
// present, or which have an unknown layout, use size=0. Bits not covered by
// any component are random and not interpreted by any software.
// present use size=0. Bits not covered by any component are random and not
// interpreted by any software.
// In particular, don't make the mistake to index this by plane.
struct mp_imgfmt_comp_desc comps[MP_NUM_COMPONENTS];