diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 96634acfd6..931834a374 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -1442,7 +1442,8 @@ int sws_frame_setup(SwsContext *ctx, const AVFrame *dst, const AVFrame *src) } /* TODO: remove once implemented */ - if ((dst_fmt.prim != src_fmt.prim || dst_fmt.trc != src_fmt.trc) && + if ((dst_fmt.color.prim != src_fmt.color.prim || + dst_fmt.color.trc != src_fmt.color.trc) && !s->color_conversion_warned) { av_log(ctx, AV_LOG_WARNING, "Conversions between different primaries / " @@ -1487,9 +1488,9 @@ int sws_frame_setup(SwsContext *ctx, const AVFrame *dst, const AVFrame *src) " fmt:%s csp:%s prim:%s trc:%s\n", err_msg, av_err2str(ret), av_get_pix_fmt_name(src_fmt.format), av_color_space_name(src_fmt.csp), - av_color_primaries_name(src_fmt.prim), av_color_transfer_name(src_fmt.trc), + av_color_primaries_name(src_fmt.color.prim), av_color_transfer_name(src_fmt.color.trc), av_get_pix_fmt_name(dst_fmt.format), av_color_space_name(dst_fmt.csp), - av_color_primaries_name(dst_fmt.prim), av_color_transfer_name(dst_fmt.trc)); + av_color_primaries_name(dst_fmt.color.prim), av_color_transfer_name(dst_fmt.color.trc)); for (int i = 0; i < FF_ARRAY_ELEMS(s->graph); i++) sws_graph_free(&s->graph[i]); diff --git a/libswscale/utils.c b/libswscale/utils.c index dc0f30aa3a..f8ad093631 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -2659,11 +2659,13 @@ SwsFormat ff_fmt_from_frame(const AVFrame *frame, int field) .height = frame->height, .format = frame->format, .range = frame->color_range, - .prim = frame->color_primaries, - .trc = frame->color_trc, .csp = frame->colorspace, .loc = frame->chroma_location, .desc = desc, + .color = { + .prim = frame->color_primaries, + .trc = frame->color_trc, + }, }; av_assert1(fmt.width > 0); @@ -2676,12 +2678,14 @@ SwsFormat ff_fmt_from_frame(const AVFrame *frame, int field) fmt.range = AVCOL_RANGE_JPEG; } else if (desc->flags & AV_PIX_FMT_FLAG_XYZ) { fmt.csp = AVCOL_SPC_UNSPECIFIED; - fmt.prim = AVCOL_PRI_SMPTE428; - fmt.trc = AVCOL_TRC_SMPTE428; + fmt.color = (SwsColor) { + .prim = AVCOL_PRI_SMPTE428, + .trc = AVCOL_TRC_SMPTE428, + }; } else if (desc->nb_components < 3) { /* Grayscale formats */ - fmt.prim = AVCOL_PRI_UNSPECIFIED; - fmt.csp = AVCOL_SPC_UNSPECIFIED; + fmt.color.prim = AVCOL_PRI_UNSPECIFIED; + fmt.csp = AVCOL_SPC_UNSPECIFIED; if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) fmt.range = AVCOL_RANGE_UNSPECIFIED; else @@ -2756,12 +2760,12 @@ static int test_loc(enum AVChromaLocation loc) int ff_test_fmt(const SwsFormat *fmt, int output) { - return fmt->width > 0 && fmt->height > 0 && - sws_test_format (fmt->format, output) && - sws_test_colorspace(fmt->csp, output) && - sws_test_primaries (fmt->prim, output) && - sws_test_transfer (fmt->trc, output) && - test_range (fmt->range) && + return fmt->width > 0 && fmt->height > 0 && + sws_test_format (fmt->format, output) && + sws_test_colorspace(fmt->csp, output) && + sws_test_primaries (fmt->color.prim, output) && + sws_test_transfer (fmt->color.trc, output) && + test_range (fmt->range) && test_loc (fmt->loc); } diff --git a/libswscale/utils.h b/libswscale/utils.h index 4d204ef6cc..0ab526b20b 100644 --- a/libswscale/utils.h +++ b/libswscale/utils.h @@ -21,26 +21,60 @@ #ifndef SWSCALE_UTILS_H #define SWSCALE_UTILS_H +#include "libavutil/csp.h" #include "libavutil/pixdesc.h" #include "swscale.h" +static inline int ff_q_isnan(const AVRational a) +{ + return !a.num && !a.den; +} + +/* Like av_cmp_q but considers NaN == NaN */ +static inline int ff_q_equal(const AVRational a, const AVRational b) +{ + return (ff_q_isnan(a) && ff_q_isnan(b)) || !av_cmp_q(a, b); +} + +static inline int ff_cie_xy_equal(const AVCIExy a, const AVCIExy b) +{ + return ff_q_equal(a.x, b.x) && ff_q_equal(a.y, b.y); +} + +static inline int ff_prim_equal(const AVPrimaryCoefficients *a, + const AVPrimaryCoefficients *b) +{ + return ff_cie_xy_equal(a->r, b->r) && + ff_cie_xy_equal(a->g, b->g) && + ff_cie_xy_equal(a->b, b->b); +} + enum { FIELD_TOP, /* top/even rows, or progressive */ FIELD_BOTTOM, /* bottom/odd rows */ }; +typedef struct SwsColor { + enum AVColorPrimaries prim; + enum AVColorTransferCharacteristic trc; + AVPrimaryCoefficients gamut; /* mastering display gamut */ + AVRational min_luma; /* minimum luminance in nits */ + AVRational max_luma; /* maximum luminance in nits */ + AVRational frame_peak; /* per-frame/scene peak luminance, or 0 */ + AVRational frame_avg; /* per-frame/scene average luminance, or 0 */ +} SwsColor; + /* Subset of AVFrame parameters that uniquely determine pixel representation */ typedef struct SwsFormat { int width, height; int interlaced; enum AVPixelFormat format; enum AVColorRange range; - enum AVColorPrimaries prim; - enum AVColorTransferCharacteristic trc; enum AVColorSpace csp; enum AVChromaLocation loc; const AVPixFmtDescriptor *desc; /* convenience */ + SwsColor color; } SwsFormat; /** @@ -49,6 +83,16 @@ typedef struct SwsFormat { */ SwsFormat ff_fmt_from_frame(const AVFrame *frame, int field); +static inline int ff_color_equal(const SwsColor *c1, const SwsColor *c2) +{ + return c1->prim == c2->prim && + c1->trc == c2->trc && + ff_q_equal(c1->min_luma, c2->min_luma) && + ff_q_equal(c1->max_luma, c2->max_luma) && + ff_prim_equal(&c1->gamut, &c2->gamut); +} + +/* Tests only the static components of a colorspace, ignoring per-frame data */ static inline int ff_fmt_equal(const SwsFormat *fmt1, const SwsFormat *fmt2) { return fmt1->width == fmt2->width && @@ -56,10 +100,9 @@ static inline int ff_fmt_equal(const SwsFormat *fmt1, const SwsFormat *fmt2) fmt1->interlaced == fmt2->interlaced && fmt1->format == fmt2->format && fmt1->range == fmt2->range && - fmt1->prim == fmt2->prim && - fmt1->trc == fmt2->trc && fmt1->csp == fmt2->csp && - fmt1->loc == fmt2->loc; + fmt1->loc == fmt2->loc && + ff_color_equal(&fmt1->color, &fmt2->color); } static inline int ff_fmt_align(enum AVPixelFormat fmt)