forked from FFmpeg/FFmpeg
swscale/utils: add helper function to infer colorspace metadata
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.
This commit is contained in:
parent
9084d581e8
commit
1f0c500784
2 changed files with 69 additions and 0 deletions
|
@ -2805,6 +2805,72 @@ 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_UNSPECIFIED:
|
||||
/* HDR curves, never default to these */
|
||||
case AVCOL_TRC_SMPTE2084:
|
||||
case AVCOL_TRC_ARIB_STD_B67:
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
|
|
@ -117,4 +117,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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue