mp_image: split colorimetry metadata into its own struct

This has two reasons:

1. I tend to add new fields to this metadata, and every time I've done
so I've consistently forgotten to update all of the dozens of places in
which this colorimetry metadata might end up getting used. While most
usages don't really care about most of the metadata, sometimes the
intend was simply to “copy” the colorimetry metadata from one struct to
another. With this being inside a substruct, those lines of code can now
simply read a.color = b.color without having to care about added or
removed fields.

2. It makes the type definitions nicer for upcoming refactors.

In going through all of the usages, I also expanded a few where I felt
that omitting the “young” fields was a bug.
This commit is contained in:
Niklas Haas 2016-06-29 09:16:13 +02:00 committed by wm4
parent 3abf9c9204
commit d81fb97f45
22 changed files with 160 additions and 151 deletions

View File

@ -2569,13 +2569,13 @@ static int property_imgparams(struct mp_image_params p, int action, void *arg)
{"aspect", SUB_PROP_FLOAT(d_w / (double)d_h)},
{"par", SUB_PROP_FLOAT(p.p_w / (double)p.p_h)},
{"colormatrix",
SUB_PROP_STR(m_opt_choice_str(mp_csp_names, p.colorspace))},
SUB_PROP_STR(m_opt_choice_str(mp_csp_names, p.color.space))},
{"colorlevels",
SUB_PROP_STR(m_opt_choice_str(mp_csp_levels_names, p.colorlevels))},
SUB_PROP_STR(m_opt_choice_str(mp_csp_levels_names, p.color.levels))},
{"primaries",
SUB_PROP_STR(m_opt_choice_str(mp_csp_prim_names, p.primaries))},
SUB_PROP_STR(m_opt_choice_str(mp_csp_prim_names, p.color.primaries))},
{"gamma",
SUB_PROP_STR(m_opt_choice_str(mp_csp_trc_names, p.gamma))},
SUB_PROP_STR(m_opt_choice_str(mp_csp_trc_names, p.color.gamma))},
{"chroma-location",
SUB_PROP_STR(m_opt_choice_str(mp_chroma_names, p.chroma_location))},
{"stereo-in",

View File

@ -193,8 +193,7 @@ static void scale_sb_rgba(struct sub_bitmap *sb, struct mp_image *dst_format,
mp_image_swscale(sbisrc2, &sbisrc, SWS_BILINEAR);
unpremultiply_and_split_BGR32(sbisrc2, sba);
sbi->params.colorspace = dst_format->params.colorspace;
sbi->params.colorlevels = dst_format->params.colorlevels;
sbi->params.color = dst_format->params.color;
mp_image_swscale(sbi, sbisrc2, SWS_BILINEAR);
talloc_free(sbisrc2);
@ -367,8 +366,8 @@ static struct part *get_cache(struct mp_draw_sub_cache *cache,
if (part) {
if (part->change_id != sbs->change_id
|| part->imgfmt != format->imgfmt
|| part->colorspace != format->params.colorspace
|| part->levels != format->params.colorlevels)
|| part->colorspace != format->params.color.space
|| part->levels != format->params.color.levels)
{
talloc_free(part);
part = NULL;
@ -380,8 +379,8 @@ static struct part *get_cache(struct mp_draw_sub_cache *cache,
.change_id = sbs->change_id,
.num_imgs = sbs->num_parts,
.imgfmt = format->imgfmt,
.levels = format->params.colorlevels,
.colorspace = format->params.colorspace,
.levels = format->params.color.levels,
.colorspace = format->params.color.space,
};
part->imgs = talloc_zero_array(part, struct sub_cache,
part->num_imgs);
@ -436,10 +435,8 @@ static struct mp_image *chroma_up(struct mp_draw_sub_cache *cache, int imgfmt,
// The temp image is always YUV, but src not necessarily.
// Reduce amount of conversions in YUV case (upsampling/shifting only)
if (src->fmt.flags & MP_IMGFLAG_YUV) {
temp->params.colorspace = src->params.colorspace;
temp->params.colorlevels = src->params.colorlevels;
}
if (src->fmt.flags & MP_IMGFLAG_YUV)
temp->params.color = src->params.color;
if (src->imgfmt == IMGFMT_420P) {
assert(imgfmt == IMGFMT_444P);

View File

@ -733,15 +733,17 @@ static void mangle_colors(struct sd *sd, struct sub_bitmaps *parts)
struct mp_image_params params = ctx->video_params;
if (force_601) {
params.colorspace = MP_CSP_BT_709;
params.colorlevels = MP_CSP_LEVELS_TV;
params.color = (struct mp_colorspace){
.space = MP_CSP_BT_709,
.levels = MP_CSP_LEVELS_TV,
};
}
if (csp == params.colorspace && levels == params.colorlevels)
if (csp == params.color.space && levels == params.color.levels)
return;
bool basic_conv = params.colorspace == MP_CSP_BT_709 &&
params.colorlevels == MP_CSP_LEVELS_TV &&
bool basic_conv = params.color.space == MP_CSP_BT_709 &&
params.color.levels == MP_CSP_LEVELS_TV &&
csp == MP_CSP_BT_601 &&
levels == MP_CSP_LEVELS_TV;
@ -749,8 +751,8 @@ static void mangle_colors(struct sd *sd, struct sub_bitmaps *parts)
if (opts->ass_vsfilter_color_compat == 1 && !basic_conv)
return;
if (params.colorspace != ctx->last_params.colorspace ||
params.colorlevels != ctx->last_params.colorlevels)
if (params.color.space != ctx->last_params.color.space ||
params.color.levels != ctx->last_params.color.levels)
{
int msgl = basic_conv ? MSGL_V : MSGL_WARN;
ctx->last_params = params;
@ -758,22 +760,21 @@ static void mangle_colors(struct sd *sd, struct sub_bitmaps *parts)
"RGB -> %s %s -> %s %s -> RGB\n",
m_opt_choice_str(mp_csp_names, csp),
m_opt_choice_str(mp_csp_levels_names, levels),
m_opt_choice_str(mp_csp_names, params.colorspace),
m_opt_choice_str(mp_csp_names, params.colorlevels));
m_opt_choice_str(mp_csp_names, params.color.space),
m_opt_choice_str(mp_csp_names, params.color.levels));
}
// Conversion that VSFilter would use
struct mp_csp_params vs_params = MP_CSP_PARAMS_DEFAULTS;
vs_params.colorspace = csp;
vs_params.levels_in = levels;
vs_params.color.space = csp;
vs_params.color.levels = levels;
struct mp_cmat vs_yuv2rgb, vs_rgb2yuv;
mp_get_csp_matrix(&vs_params, &vs_yuv2rgb);
mp_invert_cmat(&vs_rgb2yuv, &vs_yuv2rgb);
// Proper conversion to RGB
struct mp_csp_params rgb_params = MP_CSP_PARAMS_DEFAULTS;
rgb_params.colorspace = params.colorspace;
rgb_params.levels_in = params.colorlevels;
rgb_params.color = params.color;
struct mp_cmat vs2rgb;
mp_get_csp_matrix(&rgb_params, &vs2rgb);

View File

@ -581,7 +581,7 @@ void mp_get_cms_matrix(struct mp_csp_primaries src, struct mp_csp_primaries dest
static void mp_get_xyz2rgb_coeffs(struct mp_csp_params *params,
enum mp_render_intent intent, struct mp_cmat *m)
{
struct mp_csp_primaries prim = mp_get_csp_primaries(params->primaries);
struct mp_csp_primaries prim = mp_get_csp_primaries(params->color.primaries);
float brightness = params->brightness;
mp_get_rgb2xyz_matrix(prim, m->m);
mp_invert_matrix3x3(m->m);
@ -658,10 +658,10 @@ static void luma_coeffs(struct mp_cmat *mat, float lr, float lg, float lb)
// get the coefficients of the yuv -> rgb conversion matrix
void mp_get_csp_matrix(struct mp_csp_params *params, struct mp_cmat *m)
{
int colorspace = params->colorspace;
enum mp_csp colorspace = params->color.space;
if (colorspace <= MP_CSP_AUTO || colorspace >= MP_CSP_COUNT)
colorspace = MP_CSP_BT_601;
int levels_in = params->levels_in;
enum mp_csp_levels levels_in = params->color.levels;
if (levels_in <= MP_CSP_LEVELS_AUTO || levels_in >= MP_CSP_LEVELS_COUNT)
levels_in = MP_CSP_LEVELS_TV;
@ -772,9 +772,16 @@ void mp_csp_set_image_params(struct mp_csp_params *params,
{
struct mp_image_params p = *imgparams;
mp_image_params_guess_csp(&p); // ensure consistency
params->colorspace = p.colorspace;
params->levels_in = p.colorlevels;
params->primaries = p.primaries;
params->color = p.color;
}
bool mp_colorspace_equal(struct mp_colorspace c1, struct mp_colorspace c2)
{
return c1.space == c2.space &&
c1.levels == c2.levels &&
c1.primaries == c2.primaries &&
c1.gamma == c2.gamma &&
c1.peak == c2.peak;
}
// Copy settings from eq into params.

View File

@ -116,11 +116,17 @@ extern const struct m_opt_choice_alternatives mp_stereo3d_names[];
#define MP_STEREO3D_NAME_DEF(x, def) \
(MP_STEREO3D_NAME(x) ? MP_STEREO3D_NAME(x) : (def))
struct mp_csp_params {
enum mp_csp colorspace;
enum mp_csp_levels levels_in; // encoded video
enum mp_csp_levels levels_out; // output device
struct mp_colorspace {
enum mp_csp space;
enum mp_csp_levels levels;
enum mp_csp_prim primaries;
enum mp_csp_trc gamma;
float peak; // 0 = auto/unknown
};
struct mp_csp_params {
struct mp_colorspace color; // input colorspace
enum mp_csp_levels levels_out; // output device
float brightness;
float contrast;
float hue;
@ -134,9 +140,8 @@ struct mp_csp_params {
};
#define MP_CSP_PARAMS_DEFAULTS { \
.colorspace = MP_CSP_BT_601, \
.levels_in = MP_CSP_LEVELS_TV, \
.primaries = MP_CSP_PRIM_AUTO, \
.color = { .space = MP_CSP_BT_601, \
.levels = MP_CSP_LEVELS_TV }, \
.levels_out = MP_CSP_LEVELS_PC, \
.brightness = 0, .contrast = 1, .hue = 0, .saturation = 1, \
.gamma = 1, .texture_bits = 8, .input_bits = 8}
@ -145,6 +150,8 @@ struct mp_image_params;
void mp_csp_set_image_params(struct mp_csp_params *params,
const struct mp_image_params *imgparams);
bool mp_colorspace_equal(struct mp_colorspace c1, struct mp_colorspace c2);
enum mp_chroma_location {
MP_CHROMA_AUTO,
MP_CHROMA_LEFT, // mpeg2/4, h264

View File

@ -578,10 +578,12 @@ static void update_image_params(struct dec_video *vd, AVFrame *frame,
.h = frame->height,
.p_w = frame->sample_aspect_ratio.num,
.p_h = frame->sample_aspect_ratio.den,
.colorspace = avcol_spc_to_mp_csp(ctx->avctx->colorspace),
.colorlevels = avcol_range_to_mp_csp_levels(ctx->avctx->color_range),
.primaries = avcol_pri_to_mp_csp_prim(ctx->avctx->color_primaries),
.gamma = avcol_trc_to_mp_csp_trc(ctx->avctx->color_trc),
.color = {
.space = avcol_spc_to_mp_csp(ctx->avctx->colorspace),
.levels = avcol_range_to_mp_csp_levels(ctx->avctx->color_range),
.primaries = avcol_pri_to_mp_csp_prim(ctx->avctx->color_primaries),
.gamma = avcol_trc_to_mp_csp_trc(ctx->avctx->color_trc),
},
.chroma_location =
avchroma_location_to_mp(ctx->avctx->chroma_sample_location),
.rotate = vd->codec->rotate,

View File

@ -211,21 +211,21 @@ static int recreate_video_proc(struct vf_instance *vf)
FALSE, 0);
D3D11_VIDEO_PROCESSOR_COLOR_SPACE csp = {
.YCbCr_Matrix = p->params.colorspace != MP_CSP_BT_601,
.Nominal_Range = p->params.colorlevels == MP_CSP_LEVELS_TV ? 1 : 2,
.YCbCr_Matrix = p->params.color.space != MP_CSP_BT_601,
.Nominal_Range = p->params.color.levels == MP_CSP_LEVELS_TV ? 1 : 2,
};
ID3D11VideoContext_VideoProcessorSetStreamColorSpace(p->video_ctx,
p->video_proc,
0, &csp);
if (p->out_rgb) {
if (p->params.colorspace != MP_CSP_BT_601 &&
p->params.colorspace != MP_CSP_BT_709)
if (p->params.color.space != MP_CSP_BT_601 &&
p->params.color.space != MP_CSP_BT_709)
{
MP_WARN(vf, "Unsupported video colorspace (%s/%s). Consider "
"disabling hardware decoding, or using "
"--hwdec=d3d11va-copy to get correct output.\n",
m_opt_choice_str(mp_csp_names, p->params.colorspace),
m_opt_choice_str(mp_csp_levels_names, p->params.colorlevels));
m_opt_choice_str(mp_csp_names, p->params.color.space),
m_opt_choice_str(mp_csp_levels_names, p->params.color.levels));
}
} else {
ID3D11VideoContext_VideoProcessorSetOutputColorSpace(p->video_ctx,

View File

@ -88,15 +88,15 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
if (p->outfmt)
out->imgfmt = p->outfmt;
if (p->colormatrix)
out->colorspace = p->colormatrix;
out->color.space = p->colormatrix;
if (p->colorlevels)
out->colorlevels = p->colorlevels;
out->color.levels = p->colorlevels;
if (p->primaries)
out->primaries = p->primaries;
out->color.primaries = p->primaries;
if (p->gamma)
out->gamma = p->gamma;
out->color.gamma = p->gamma;
if (p->peak)
out->peak = p->peak;
out->color.peak = p->peak;
if (p->chroma_location)
out->chroma_location = p->chroma_location;
if (p->stereo_in)

View File

@ -166,8 +166,8 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
struct mp_imgfmt_desc d_fmt = mp_imgfmt_get_desc(out->imgfmt);
// keep colorspace settings if the data stays in yuv
if (!(s_fmt.flags & MP_IMGFLAG_YUV) || !(d_fmt.flags & MP_IMGFLAG_YUV)) {
out->colorspace = MP_CSP_AUTO;
out->colorlevels = MP_CSP_LEVELS_AUTO;
out->color.space = MP_CSP_AUTO;
out->color.levels = MP_CSP_LEVELS_AUTO;
}
mp_image_params_guess_csp(out);

View File

@ -143,13 +143,13 @@ static void copy_mp_to_vs_frame_props_map(struct vf_priv_s *p, VSMap *map,
struct mp_image_params *params = &img->params;
p->vsapi->propSetInt(map, "_SARNum", params->p_w, 0);
p->vsapi->propSetInt(map, "_SARDen", params->p_h, 0);
if (params->colorlevels) {
if (params->color.levels) {
p->vsapi->propSetInt(map, "_ColorRange",
params->colorlevels == MP_CSP_LEVELS_TV, 0);
params->color.levels == MP_CSP_LEVELS_TV, 0);
}
// The docs explicitly say it uses libavcodec values.
p->vsapi->propSetInt(map, "_ColorSpace",
mp_csp_to_avcol_spc(params->colorspace), 0);
mp_csp_to_avcol_spc(params->color.space), 0);
if (params->chroma_location) {
p->vsapi->propSetInt(map, "_ChromaLocation",
params->chroma_location == MP_CHROMA_CENTER, 0);

View File

@ -168,7 +168,7 @@ static struct mp_image *render(struct vf_instance *vf)
mp_image_set_size(img, in->w, in->h);
mp_image_copy_attributes(img, in);
unsigned int flags = va_get_colorspace_flag(p->params.colorspace);
unsigned int flags = va_get_colorspace_flag(p->params.color.space);
if (!mp_refqueue_is_interlaced(p->queue)) {
flags |= VA_FRAME_PICTURE;
} else if (mp_refqueue_is_top_field(p->queue)) {

View File

@ -133,8 +133,8 @@ static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp
pic->width = avctx->width;
pic->height = avctx->height;
if (ctx->opts->tag_csp) {
pic->color_primaries = mp_csp_prim_to_avcol_pri(image->params.primaries);
pic->color_trc = mp_csp_trc_to_avcol_trc(image->params.gamma);
pic->color_primaries = mp_csp_prim_to_avcol_pri(image->params.color.primaries);
pic->color_trc = mp_csp_trc_to_avcol_trc(image->params.color.gamma);
}
#if HAVE_AVCODEC_NEW_CODEC_API

View File

@ -393,11 +393,12 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src)
dst->params.p_w = src->params.p_w;
dst->params.p_h = src->params.p_h;
}
dst->params.primaries = src->params.primaries;
dst->params.gamma = src->params.gamma;
dst->params.color.primaries = src->params.color.primaries;
dst->params.color.gamma = src->params.color.gamma;
dst->params.color.peak = src->params.color.peak;
if ((dst->fmt.flags & MP_IMGFLAG_YUV) == (src->fmt.flags & MP_IMGFLAG_YUV)) {
dst->params.colorspace = src->params.colorspace;
dst->params.colorlevels = src->params.colorlevels;
dst->params.color.space = src->params.color.space;
dst->params.color.levels = src->params.color.levels;
dst->params.chroma_location = src->params.chroma_location;
}
mp_image_params_guess_csp(&dst->params); // ensure colorspace consistency
@ -512,8 +513,8 @@ char *mp_image_params_to_str_buf(char *b, size_t bs,
if (p->hw_subfmt)
mp_snprintf_cat(b, bs, "[%llu]", (unsigned long long)(p->hw_subfmt));
mp_snprintf_cat(b, bs, " %s/%s",
m_opt_choice_str(mp_csp_names, p->colorspace),
m_opt_choice_str(mp_csp_levels_names, p->colorlevels));
m_opt_choice_str(mp_csp_names, p->color.space),
m_opt_choice_str(mp_csp_levels_names, p->color.levels));
mp_snprintf_cat(b, bs, " CL=%s",
m_opt_choice_str(mp_chroma_names, p->chroma_location));
if (p->rotate)
@ -564,11 +565,7 @@ bool mp_image_params_equal(const struct mp_image_params *p1,
p1->hw_subfmt == p2->hw_subfmt &&
p1->w == p2->w && p1->h == p2->h &&
p1->p_w == p2->p_w && p1->p_h == p2->p_h &&
p1->colorspace == p2->colorspace &&
p1->colorlevels == p2->colorlevels &&
p1->primaries == p2->primaries &&
p1->gamma == p2->gamma &&
p1->peak == p2->peak &&
mp_colorspace_equal(p1->color, p2->color) &&
p1->chroma_location == p2->chroma_location &&
p1->rotate == p2->rotate &&
p1->stereo_in == p2->stereo_in &&
@ -598,56 +595,56 @@ void mp_image_params_guess_csp(struct mp_image_params *params)
if (!fmt.id)
return;
if (fmt.flags & MP_IMGFLAG_YUV) {
if (params->colorspace != MP_CSP_BT_601 &&
params->colorspace != MP_CSP_BT_709 &&
params->colorspace != MP_CSP_BT_2020_NC &&
params->colorspace != MP_CSP_BT_2020_C &&
params->colorspace != MP_CSP_SMPTE_240M &&
params->colorspace != MP_CSP_YCGCO)
if (params->color.space != MP_CSP_BT_601 &&
params->color.space != MP_CSP_BT_709 &&
params->color.space != MP_CSP_BT_2020_NC &&
params->color.space != MP_CSP_BT_2020_C &&
params->color.space != MP_CSP_SMPTE_240M &&
params->color.space != MP_CSP_YCGCO)
{
// Makes no sense, so guess instead
// YCGCO should be separate, but libavcodec disagrees
params->colorspace = MP_CSP_AUTO;
params->color.space = MP_CSP_AUTO;
}
if (params->colorspace == MP_CSP_AUTO)
params->colorspace = mp_csp_guess_colorspace(params->w, params->h);
if (params->colorlevels == MP_CSP_LEVELS_AUTO) {
if (params->gamma == MP_CSP_TRC_V_LOG) {
params->colorlevels = MP_CSP_LEVELS_PC;
if (params->color.space == MP_CSP_AUTO)
params->color.space = mp_csp_guess_colorspace(params->w, params->h);
if (params->color.levels == MP_CSP_LEVELS_AUTO) {
if (params->color.gamma == MP_CSP_TRC_V_LOG) {
params->color.levels = MP_CSP_LEVELS_PC;
} else {
params->colorlevels = MP_CSP_LEVELS_TV;
params->color.levels = MP_CSP_LEVELS_TV;
}
}
if (params->primaries == MP_CSP_PRIM_AUTO) {
if (params->color.primaries == MP_CSP_PRIM_AUTO) {
// Guess based on the colormatrix as a first priority
if (params->colorspace == MP_CSP_BT_2020_NC ||
params->colorspace == MP_CSP_BT_2020_C) {
params->primaries = MP_CSP_PRIM_BT_2020;
} else if (params->colorspace == MP_CSP_BT_709) {
params->primaries = MP_CSP_PRIM_BT_709;
if (params->color.space == MP_CSP_BT_2020_NC ||
params->color.space == MP_CSP_BT_2020_C) {
params->color.primaries = MP_CSP_PRIM_BT_2020;
} else if (params->color.space == MP_CSP_BT_709) {
params->color.primaries = MP_CSP_PRIM_BT_709;
} else {
// Ambiguous colormatrix for BT.601, guess based on res
params->primaries = mp_csp_guess_primaries(params->w, params->h);
params->color.primaries = mp_csp_guess_primaries(params->w, params->h);
}
}
if (params->gamma == MP_CSP_TRC_AUTO)
params->gamma = MP_CSP_TRC_BT_1886;
if (params->color.gamma == MP_CSP_TRC_AUTO)
params->color.gamma = MP_CSP_TRC_BT_1886;
} else if (fmt.flags & MP_IMGFLAG_RGB) {
params->colorspace = MP_CSP_RGB;
params->colorlevels = MP_CSP_LEVELS_PC;
params->color.space = MP_CSP_RGB;
params->color.levels = MP_CSP_LEVELS_PC;
// The majority of RGB content is either sRGB or (rarely) some other
// color space which we don't even handle, like AdobeRGB or
// ProPhotoRGB. The only reasonable thing we can do is assume it's
// sRGB and hope for the best, which should usually just work out fine.
// Note: sRGB primaries = BT.709 primaries
if (params->primaries == MP_CSP_PRIM_AUTO)
params->primaries = MP_CSP_PRIM_BT_709;
if (params->gamma == MP_CSP_TRC_AUTO)
params->gamma = MP_CSP_TRC_SRGB;
if (params->color.primaries == MP_CSP_PRIM_AUTO)
params->color.primaries = MP_CSP_PRIM_BT_709;
if (params->color.gamma == MP_CSP_TRC_AUTO)
params->color.gamma = MP_CSP_TRC_SRGB;
} else if (fmt.flags & MP_IMGFLAG_XYZ) {
params->colorspace = MP_CSP_XYZ;
params->colorlevels = MP_CSP_LEVELS_PC;
params->color.space = MP_CSP_XYZ;
params->color.levels = MP_CSP_LEVELS_PC;
// The default XYZ matrix converts it to BT.709 color space
// since that's the most likely scenario. Proper VOs should ignore
@ -657,22 +654,22 @@ void mp_image_params_guess_csp(struct mp_image_params *params)
// gamut for VOs which *do* use the specialized XYZ matrix but don't
// know any better output gamut other than whatever the source is
// tagged with.
if (params->primaries == MP_CSP_PRIM_AUTO)
params->primaries = MP_CSP_PRIM_BT_709;
if (params->gamma == MP_CSP_TRC_AUTO)
params->gamma = MP_CSP_TRC_LINEAR;
if (params->color.primaries == MP_CSP_PRIM_AUTO)
params->color.primaries = MP_CSP_PRIM_BT_709;
if (params->color.gamma == MP_CSP_TRC_AUTO)
params->color.gamma = MP_CSP_TRC_LINEAR;
} else {
// We have no clue.
params->colorspace = MP_CSP_AUTO;
params->colorlevels = MP_CSP_LEVELS_AUTO;
params->primaries = MP_CSP_PRIM_AUTO;
params->gamma = MP_CSP_TRC_AUTO;
params->color.space = MP_CSP_AUTO;
params->color.levels = MP_CSP_LEVELS_AUTO;
params->color.primaries = MP_CSP_PRIM_AUTO;
params->color.gamma = MP_CSP_TRC_AUTO;
}
// Guess the reference peak (independent of the colorspace)
if (params->gamma == MP_CSP_TRC_SMPTE_ST2084) {
if (!params->peak)
params->peak = 10000; // As per the spec
// Guess the nominal peak (independent of the colorspace)
if (params->color.gamma == MP_CSP_TRC_SMPTE_ST2084) {
if (!params->color.peak)
params->color.peak = 10000; // As per the spec
}
}
@ -729,8 +726,8 @@ static void mp_image_copy_fields_to_av_frame(struct AVFrame *dst,
if (src->fields & MP_IMGFIELD_REPEAT_FIRST)
dst->repeat_pict = 1;
dst->colorspace = mp_csp_to_avcol_spc(src->params.colorspace);
dst->color_range = mp_csp_levels_to_avcol_range(src->params.colorlevels);
dst->colorspace = mp_csp_to_avcol_spc(src->params.color.space);
dst->color_range = mp_csp_levels_to_avcol_range(src->params.color.levels);
}
// Create a new mp_image reference to av_frame.

View File

@ -43,11 +43,7 @@ struct mp_image_params {
// (will use the HW API's format identifiers)
int w, h; // image dimensions
int p_w, p_h; // define pixel aspect ratio (undefined: 0/0)
enum mp_csp colorspace;
enum mp_csp_levels colorlevels;
enum mp_csp_prim primaries;
enum mp_csp_trc gamma;
float peak; // 0 = auto/unknown
struct mp_colorspace color;
enum mp_chroma_location chroma_location;
// The image should be rotated clockwise (0-359 degrees).
int rotate;

View File

@ -185,7 +185,7 @@ static int map_frame(struct gl_hwdec *hw, struct mp_image *hw_image,
0, 0, hw_image->w, hw_image->h,
0, 0, hw_image->w, hw_image->h,
NULL, 0,
va_get_colorspace_flag(hw_image->params.colorspace));
va_get_colorspace_flag(hw_image->params.color.space));
CHECK_VA_STATUS(p, "vaPutSurface()");
va_unlock(p->ctx);

View File

@ -729,7 +729,7 @@ static void pass_get_img_tex(struct gl_video *p, struct video_image *vimg,
// The existing code assumes we just have a single tex multiplier for
// all of the planes. This may change in the future
float tex_mul = 1.0 / mp_get_csp_mul(p->image_params.colorspace,
float tex_mul = 1.0 / mp_get_csp_mul(p->image_params.color.space,
p->image_desc.component_bits,
p->image_desc.component_full_bits);
@ -793,7 +793,7 @@ static void init_video(struct gl_video *p)
mp_image_params_guess_csp(&p->image_params);
int eq_caps = MP_CSP_EQ_CAPS_GAMMA;
if (p->image_params.colorspace != MP_CSP_BT_2020_C)
if (p->image_params.color.space != MP_CSP_BT_2020_C)
eq_caps |= MP_CSP_EQ_CAPS_COLORMATRIX;
if (p->image_desc.flags & MP_IMGFLAG_XYZ)
eq_caps |= MP_CSP_EQ_CAPS_BRIGHTNESS;
@ -1985,7 +1985,7 @@ static void pass_convert_yuv(struct gl_video *p)
GLSLF("color = color.%s;\n", p->color_swizzle);
// Pre-colormatrix input gamma correction
if (cparams.colorspace == MP_CSP_XYZ)
if (cparams.color.space == MP_CSP_XYZ)
GLSL(color.rgb = pow(color.rgb, vec3(2.6));) // linear light
// We always explicitly normalize the range in pass_read_video
@ -2000,7 +2000,7 @@ static void pass_convert_yuv(struct gl_video *p)
GLSL(color.rgb = mat3(colormatrix) * color.rgb + colormatrix_c;)
if (p->image_params.colorspace == MP_CSP_BT_2020_C) {
if (p->image_params.color.space == MP_CSP_BT_2020_C) {
// Conversion for C'rcY'cC'bc via the BT.2020 CL system:
// C'bc = (B'-Y'c) / 1.9404 | C'bc <= 0
// = (B'-Y'c) / 1.5816 | C'bc > 0
@ -2111,7 +2111,7 @@ static void pass_scale_main(struct gl_video *p)
// Pre-conversion, like linear light/sigmoidization
GLSLF("// scaler pre-conversion\n");
if (p->use_linear) {
pass_linearize(p->sc, p->image_params.gamma);
pass_linearize(p->sc, p->image_params.color.gamma);
pass_opt_hook_point(p, "LINEAR", NULL);
}
@ -2171,8 +2171,8 @@ static void pass_colormanage(struct gl_video *p, float peak_src,
if (p->use_lut_3d) {
// The 3DLUT is always generated against the original source space
enum mp_csp_prim prim_orig = p->image_params.primaries;
enum mp_csp_trc trc_orig = p->image_params.gamma;
enum mp_csp_prim prim_orig = p->image_params.color.primaries;
enum mp_csp_trc trc_orig = p->image_params.color.gamma;
// One exception: HDR is not implemented by LittleCMS for technical
// limitation reasons, so we use a gamma 2.2 input curve here instead.
@ -2196,14 +2196,14 @@ static void pass_colormanage(struct gl_video *p, float peak_src,
// this as the default output color space.
prim_dst = MP_CSP_PRIM_BT_709;
if (p->image_params.primaries == MP_CSP_PRIM_BT_601_525 ||
p->image_params.primaries == MP_CSP_PRIM_BT_601_625)
if (p->image_params.color.primaries == MP_CSP_PRIM_BT_601_525 ||
p->image_params.color.primaries == MP_CSP_PRIM_BT_601_625)
{
// Since we auto-pick BT.601 and BT.709 based on the dimensions,
// combined with the fact that they're very similar to begin with,
// and to avoid confusing the average user, just don't adapt BT.601
// content automatically at all.
prim_dst = p->image_params.primaries;
prim_dst = p->image_params.color.primaries;
}
}
@ -2213,7 +2213,7 @@ static void pass_colormanage(struct gl_video *p, float peak_src,
// altogether by default. The only exceptions to this rule apply to
// very unusual TRCs, which even hardcode technoluddites would probably
// not enjoy viewing unaltered.
trc_dst = p->image_params.gamma;
trc_dst = p->image_params.color.gamma;
// Avoid outputting linear light or HDR content "by default". For these
// just pick gamma 2.2 as a default, since it's a good estimate for
@ -2225,7 +2225,7 @@ static void pass_colormanage(struct gl_video *p, float peak_src,
if (!peak_src) {
// If the source has no information known, it's display-referred
// (and should be treated relative to the specified desired peak_dst)
peak_src = peak_dst * mp_csp_trc_rel_peak(p->image_params.gamma);
peak_src = peak_dst * mp_csp_trc_rel_peak(p->image_params.color.gamma);
}
// All operations from here on require linear light as a starting point,
@ -2513,7 +2513,7 @@ static void pass_render_frame(struct gl_video *p)
rect.mt *= scale[1]; rect.mb *= scale[1];
// We should always blend subtitles in non-linear light
if (p->use_linear) {
pass_delinearize(p->sc, p->image_params.gamma);
pass_delinearize(p->sc, p->image_params.color.gamma);
p->use_linear = false;
}
finish_pass_fbo(p, &p->blend_subs_fbo, p->texture_w, p->texture_h,
@ -2542,8 +2542,8 @@ static void pass_draw_to_screen(struct gl_video *p, int fbo)
GLSL(color.rgb = pow(color.rgb, vec3(user_gamma));)
}
pass_colormanage(p, p->image_params.peak, p->image_params.primaries,
p->use_linear ? MP_CSP_TRC_LINEAR : p->image_params.gamma);
pass_colormanage(p, p->image_params.color.peak, p->image_params.color.primaries,
p->use_linear ? MP_CSP_TRC_LINEAR : p->image_params.color.gamma);
// Draw checkerboard pattern to indicate transparency
if (p->has_alpha && p->opts.alpha_mode == ALPHA_BLEND_TILES) {

View File

@ -155,8 +155,8 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
vc->codec->height = height;
vc->codec->pix_fmt = pix_fmt;
encode_lavc_set_csp(vo->encode_lavc_ctx, vc->codec, params->colorspace);
encode_lavc_set_csp_levels(vo->encode_lavc_ctx, vc->codec, params->colorlevels);
encode_lavc_set_csp(vo->encode_lavc_ctx, vc->codec, params->color.space);
encode_lavc_set_csp_levels(vo->encode_lavc_ctx, vc->codec, params->color.levels);
if (encode_lavc_open_codec(vo->encode_lavc_ctx, vc->codec) < 0)
goto error;

View File

@ -305,8 +305,10 @@ static int control(struct vo *vo, uint32_t request, void *data)
struct mp_image *screen = gl_read_window_contents(p->gl);
// set image parameters according to the display, if possible
if (screen) {
screen->params.primaries = p->renderer_opts->target_prim;
screen->params.gamma = p->renderer_opts->target_trc;
screen->params.color = (struct mp_colorspace) {
.primaries = p->renderer_opts->target_prim,
.gamma = p->renderer_opts->target_trc,
};
if (p->glctx->flip_v)
mp_image_vflip(screen);
}

View File

@ -529,7 +529,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
input->format->es->video.height = MP_ALIGN_UP(params->h, ALIGN_H);
input->format->es->video.crop = (MMAL_RECT_T){0, 0, params->w, params->h};
input->format->es->video.par = (MMAL_RATIONAL_T){params->p_w, params->p_h};
input->format->es->video.color_space = map_csp(params->colorspace);
input->format->es->video.color_space = map_csp(params->color.space);
if (mmal_port_format_commit(input))
return -1;

View File

@ -225,7 +225,7 @@ static bool render_to_screen(struct priv *p, struct mp_image *mpi)
}
}
int flags = va_get_colorspace_flag(p->image_params.colorspace) |
int flags = va_get_colorspace_flag(p->image_params.color.space) |
p->scaling | VA_FRAME_PICTURE;
status = vaPutSurface(p->display,
surface,

View File

@ -518,7 +518,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
ctx->current_buf = 0;
ctx->current_ip_buf = 0;
int is_709 = params->colorspace == MP_CSP_BT_709;
int is_709 = params->color.space == MP_CSP_BT_709;
xv_set_eq(vo, ctx->xv_port, "bt_709", is_709 * 200 - 100);
read_xv_csp(vo);
@ -661,7 +661,7 @@ static struct mp_image get_xv_buffer(struct vo *vo, int buf_index)
if (vo->params) {
struct mp_image_params params = *vo->params;
if (ctx->cached_csp)
params.colorspace = ctx->cached_csp;
params.color.space = ctx->cached_csp;
mp_image_set_attributes(&img, &params);
}

View File

@ -192,11 +192,11 @@ int mp_sws_reinit(struct mp_sws_context *ctx)
return -1;
}
int s_csp = mp_csp_to_sws_colorspace(src->colorspace);
int s_range = src->colorlevels == MP_CSP_LEVELS_PC;
int s_csp = mp_csp_to_sws_colorspace(src->color.space);
int s_range = src->color.levels == MP_CSP_LEVELS_PC;
int d_csp = mp_csp_to_sws_colorspace(dst->colorspace);
int d_range = dst->colorlevels == MP_CSP_LEVELS_PC;
int d_csp = mp_csp_to_sws_colorspace(dst->color.space);
int d_range = dst->color.levels == MP_CSP_LEVELS_PC;
// Work around libswscale bug #1852 (fixed in ffmpeg commit 8edf9b1fa):
// setting range flags for RGB gives random bogus results.