From: Niklas Haas <g...@haasn.dev> Logic is loosely on equivalent decisions in libplacebo. The basic idea is to try and be a bit conservative by treating AVCOL_*_UNSPECIFIED as a no-op, unless the other primaries set are non-standard / wide-gamut or HDR. This helps avoid unintended or unexpected colorspace conversions, while forcing it in cases where we are almost certain it is needed. The major departure from libplacebo semantics is that we no default to a 1000:1 contrast ration for SDR displays, instead modelling them as idealized devices with an infinite contrast ratio.
In either case, setting SWS_STRICT overrides this behavior in favor of always requiring explicit colorspace metadata. --- libswscale/utils.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++ libswscale/utils.h | 3 ++ 2 files changed, 72 insertions(+) diff --git a/libswscale/utils.c b/libswscale/utils.c index 02bd0ed010..e80caa708a 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -2802,6 +2802,75 @@ skip_hdr10: return fmt; } +static int infer_prim_ref(SwsColor *csp, const SwsColor *ref) +{ + if (csp->prim != AVCOL_PRI_UNSPECIFIED) + return 0; + + /* Re-use the reference gamut only for "safe", similar primaries */ + switch (ref->prim) { + case AVCOL_PRI_BT709: + case AVCOL_PRI_BT470M: + case AVCOL_PRI_BT470BG: + case AVCOL_PRI_SMPTE170M: + case AVCOL_PRI_SMPTE240M: + csp->prim = ref->prim; + csp->gamut = ref->gamut; + break; + default: + csp->prim = AVCOL_PRI_BT709; + csp->gamut = av_csp_primaries_desc_from_id(csp->prim)->prim; + break; + } + + return 1; +} + +static int infer_trc_ref(SwsColor *csp, const SwsColor *ref) +{ + if (csp->trc != AVCOL_TRC_UNSPECIFIED) + return 0; + + /* Pick a suitable SDR transfer function, to try and minimize conversions */ + switch (ref->trc) { + case AVCOL_TRC_SMPTE2084: + case AVCOL_TRC_ARIB_STD_B67: + /* HDR curves, never default to these */ + csp->trc = AVCOL_TRC_BT709; + csp->min_luma = av_make_q(0, 1); + csp->max_luma = av_make_q(203, 1); + break; + default: + csp->trc = ref->trc; + csp->min_luma = ref->min_luma; + csp->max_luma = ref->max_luma; + break; + } + + return 1; +} + +int ff_infer_colors(SwsColor *src, SwsColor *dst) +{ + int incomplete = 0; + + if (src->prim != dst->prim) { + incomplete |= infer_prim_ref(dst, src); + incomplete |= infer_prim_ref(src, dst); + av_assert0(src->prim != AVCOL_PRI_UNSPECIFIED); + av_assert0(dst->prim != AVCOL_PRI_UNSPECIFIED); + } + + if (src->trc != dst->trc) { + incomplete |= infer_trc_ref(dst, src); + incomplete |= infer_trc_ref(src, dst); + av_assert0(src->trc != AVCOL_TRC_UNSPECIFIED); + av_assert0(dst->trc != AVCOL_TRC_UNSPECIFIED); + } + + return incomplete; +} + int sws_test_format(enum AVPixelFormat format, int output) { return output ? sws_isSupportedOutput(format) : sws_isSupportedInput(format); diff --git a/libswscale/utils.h b/libswscale/utils.h index a8481922d3..a115c46cf6 100644 --- a/libswscale/utils.h +++ b/libswscale/utils.h @@ -106,4 +106,7 @@ static inline int ff_fmt_align(enum AVPixelFormat fmt) int ff_test_fmt(const SwsFormat *fmt, int output); +/* Returns 1 if the formats are incomplete, 0 otherwise */ +int ff_infer_colors(SwsColor *src, SwsColor *dst); + #endif /* SWSCALE_UTILS_H */ -- 2.47.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".