From d81fb97f4587f73f62a760b99f686139f9b8d966 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Wed, 29 Jun 2016 09:16:13 +0200 Subject: mp_image: split colorimetry metadata into its own struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- player/command.c | 8 +-- sub/draw_bmp.c | 17 +++---- sub/sd_ass.c | 27 ++++++----- video/csputils.c | 19 +++++--- video/csputils.h | 21 +++++--- video/decode/vd_lavc.c | 10 ++-- video/filter/vf_d3d11vpp.c | 12 ++--- video/filter/vf_format.c | 10 ++-- video/filter/vf_scale.c | 4 +- video/filter/vf_vapoursynth.c | 6 +-- video/filter/vf_vavpp.c | 2 +- video/image_writer.c | 4 +- video/mp_image.c | 107 ++++++++++++++++++++--------------------- video/mp_image.h | 6 +-- video/out/opengl/hwdec_vaglx.c | 2 +- video/out/opengl/video.c | 30 ++++++------ video/out/vo_lavc.c | 4 +- video/out/vo_opengl.c | 6 ++- video/out/vo_rpi.c | 2 +- video/out/vo_vaapi.c | 2 +- video/out/vo_xv.c | 4 +- video/sws_utils.c | 8 +-- 22 files changed, 160 insertions(+), 151 deletions(-) diff --git a/player/command.c b/player/command.c index caca0c32ec..85f453e0ef 100644 --- a/player/command.c +++ b/player/command.c @@ -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", diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index 5356a8fa99..b79810ce9a 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -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); diff --git a/sub/sd_ass.c b/sub/sd_ass.c index 7abeea9eeb..34a49c1501 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -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); diff --git a/video/csputils.c b/video/csputils.c index d419152e2c..4c9cfbeebd 100644 --- a/video/csputils.c +++ b/video/csputils.c @@ -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. diff --git a/video/csputils.h b/video/csputils.h index 274b548381..0743f2bee5 100644 --- a/video/csputils.h +++ b/video/csputils.h @@ -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 diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index be6aceb662..62fc4ff280 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -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, diff --git a/video/filter/vf_d3d11vpp.c b/video/filter/vf_d3d11vpp.c index a0aa0edae2..658aec25b8 100644 --- a/video/filter/vf_d3d11vpp.c +++ b/video/filter/vf_d3d11vpp.c @@ -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, diff --git a/video/filter/vf_format.c b/video/filter/vf_format.c index 109fda4053..36388e6288 100644 --- a/video/filter/vf_format.c +++ b/video/filter/vf_format.c @@ -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) diff --git a/video/filter/vf_scale.c b/video/filter/vf_scale.c index 518ff41beb..0b233e7098 100644 --- a/video/filter/vf_scale.c +++ b/video/filter/vf_scale.c @@ -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); diff --git a/video/filter/vf_vapoursynth.c b/video/filter/vf_vapoursynth.c index 5592e032e4..625d539dc4 100644 --- a/video/filter/vf_vapoursynth.c +++ b/video/filter/vf_vapoursynth.c @@ -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); diff --git a/video/filter/vf_vavpp.c b/video/filter/vf_vavpp.c index 0365b55fb3..b24f886241 100644 --- a/video/filter/vf_vavpp.c +++ b/video/filter/vf_vavpp.c @@ -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)) { diff --git a/video/image_writer.c b/video/image_writer.c index 5ba89c8167..6b2f0f9a92 100644 --- a/video/image_writer.c +++ b/video/image_writer.c @@ -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 diff --git a/video/mp_image.c b/video/mp_image.c index 0b46f947bc..286e40bf62 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -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. diff --git a/video/mp_image.h b/video/mp_image.h index 18d25968c0..dfbe4ee0ba 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -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; diff --git a/video/out/opengl/hwdec_vaglx.c b/video/out/opengl/hwdec_vaglx.c index 2e3017c193..0400604067 100644 --- a/video/out/opengl/hwdec_vaglx.c +++ b/video/out/opengl/hwdec_vaglx.c @@ -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); diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c index 6c7646bef4..59dd64cb65 100644 --- a/video/out/opengl/video.c +++ b/video/out/opengl/video.c @@ -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) { diff --git a/video/out/vo_lavc.c b/video/out/vo_lavc.c index 7003bd17bd..1721136f8b 100644 --- a/video/out/vo_lavc.c +++ b/video/out/vo_lavc.c @@ -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; diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index 08b9b11fe0..095308f9b5 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -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); } diff --git a/video/out/vo_rpi.c b/video/out/vo_rpi.c index cd37362a30..947e63037e 100644 --- a/video/out/vo_rpi.c +++ b/video/out/vo_rpi.c @@ -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; diff --git a/video/out/vo_vaapi.c b/video/out/vo_vaapi.c index 8380771e27..11bb469b24 100644 --- a/video/out/vo_vaapi.c +++ b/video/out/vo_vaapi.c @@ -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, diff --git a/video/out/vo_xv.c b/video/out/vo_xv.c index a5a4728085..f450eb2df9 100644 --- a/video/out/vo_xv.c +++ b/video/out/vo_xv.c @@ -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, ¶ms); } diff --git a/video/sws_utils.c b/video/sws_utils.c index ce44c67eeb..45918b19d1 100644 --- a/video/sws_utils.c +++ b/video/sws_utils.c @@ -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. -- cgit v1.2.3