From 5e50a56b9c4998838005ddaaed1422a9d717c50f Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Wed, 9 Oct 2024 23:33:44 +0200 Subject: [PATCH] swscale: add new frame testing API Replacing the old sws_isSupported* API with a more consistent family of functions that follows the same signature and naming convention, including a placeholder for testing the color space parameters that we don't currently implement conversions for. These functions also perform some extra basic sanity checking. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- doc/APIchanges | 8 ++++++ libswscale/swscale.h | 55 +++++++++++++++++++++++++++++++++++ libswscale/utils.c | 68 ++++++++++++++++++++++++++++++++++++++++++++ libswscale/utils.h | 2 ++ libswscale/version.h | 2 +- 5 files changed, 134 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index c1336d4e40..7d94b7bf97 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,14 @@ The last version increases of all libraries were on 2024-03-07 API changes, most recent first: +2024-10-23 - xxxxxxxxxx - lsws 8.8.100 - swscale.h + Add frame property testing API: + - sws_test_format() + - sws_test_colorspace() + - sws_test_primaries() + - sws_test_transfer() + - sws_test_frame() + 2024-10-23 - xxxxxxxxxx - lsws 8.7.100 - swscale.h Add sws_free_context(). diff --git a/libswscale/swscale.h b/libswscale/swscale.h index 763c1dbccf..e3362d5328 100644 --- a/libswscale/swscale.h +++ b/libswscale/swscale.h @@ -85,6 +85,61 @@ SwsContext *sws_alloc_context(void); */ void sws_free_context(SwsContext **ctx); +/*************************** + * Supported frame formats * + ***************************/ + +/** + * Test if a given pixel format is supported. + * + * @param output If 0, test if compatible with the source/input frame; + * otherwise, with the destination/output frame. + * @param format The format to check. + * + * @return A positive integer if supported, 0 otherwise. + */ +int sws_test_format(enum AVPixelFormat format, int output); + +/** + * Test if a given color space is supported. + * + * @param output If 0, test if compatible with the source/input frame; + * otherwise, with the destination/output frame. + * @param colorspace The colorspace to check. + * + * @return A positive integer if supported, 0 otherwise. + */ +int sws_test_colorspace(enum AVColorSpace colorspace, int output); + +/** + * Test if a given set of color primaries is supported. + * + * @param output If 0, test if compatible with the source/input frame; + * otherwise, with the destination/output frame. + * @param primaries The color primaries to check. + * + * @return A positive integer if supported, 0 otherwise. + */ +int sws_test_primaries(enum AVColorPrimaries primaries, int output); + +/** + * Test if a given color transfer function is supported. + * + * @param output If 0, test if compatible with the source/input frame; + * otherwise, with the destination/output frame. + * @param trc The color transfer function to check. + * + * @return A positive integer if supported, 0 otherwise. + */ +int sws_test_transfer(enum AVColorTransferCharacteristic trc, int output); + +/** + * Helper function to run all sws_test_* against a frame, as well as testing + * the basic frame properties for sanity. Ignores irrelevant properties - for + * example, AVColorSpace is not checked for RGB frames. + */ +int sws_test_frame(const AVFrame *frame, int output); + /* values for the flags, the stuff on the command line is different */ #define SWS_FAST_BILINEAR 1 #define SWS_BILINEAR 2 diff --git a/libswscale/utils.c b/libswscale/utils.c index 4419e3e627..c9c80fdb79 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -2709,3 +2709,71 @@ SwsFormat ff_fmt_from_frame(const AVFrame *frame, int field) return fmt; } + +int sws_test_format(enum AVPixelFormat format, int output) +{ + return output ? sws_isSupportedOutput(format) : sws_isSupportedInput(format); +} + +int sws_test_colorspace(enum AVColorSpace csp, int output) +{ + switch (csp) { + case AVCOL_SPC_UNSPECIFIED: + case AVCOL_SPC_RGB: + case AVCOL_SPC_BT709: + case AVCOL_SPC_BT470BG: + case AVCOL_SPC_SMPTE170M: + case AVCOL_SPC_FCC: + case AVCOL_SPC_SMPTE240M: + case AVCOL_SPC_BT2020_NCL: + return 1; + default: + return 0; + } +} + +int sws_test_primaries(enum AVColorPrimaries prim, int output) +{ + return prim > AVCOL_PRI_RESERVED0 && prim < AVCOL_PRI_NB && + prim != AVCOL_PRI_RESERVED; +} + +int sws_test_transfer(enum AVColorTransferCharacteristic trc, int output) +{ + return trc > AVCOL_TRC_RESERVED0 && trc < AVCOL_TRC_NB && + trc != AVCOL_TRC_RESERVED; +} + +static int test_range(enum AVColorRange range) +{ + return range >= 0 && range < AVCOL_RANGE_NB; +} + +static int test_loc(enum AVChromaLocation loc) +{ + return loc >= 0 && loc < AVCHROMA_LOC_NB; +} + +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) && + test_loc (fmt->loc); +} + +int sws_test_frame(const AVFrame *frame, int output) +{ + for (int field = 0; field < 2; field++) { + const SwsFormat fmt = ff_fmt_from_frame(frame, field); + if (!ff_test_fmt(&fmt, output)) + return 0; + if (!fmt.interlaced) + break; + } + + return 1; +} diff --git a/libswscale/utils.h b/libswscale/utils.h index a210b646b0..4d204ef6cc 100644 --- a/libswscale/utils.h +++ b/libswscale/utils.h @@ -72,4 +72,6 @@ static inline int ff_fmt_align(enum AVPixelFormat fmt) } } +int ff_test_fmt(const SwsFormat *fmt, int output); + #endif /* SWSCALE_UTILS_H */ diff --git a/libswscale/version.h b/libswscale/version.h index 4c6af261e6..c0610fec1e 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -28,7 +28,7 @@ #include "version_major.h" -#define LIBSWSCALE_VERSION_MINOR 7 +#define LIBSWSCALE_VERSION_MINOR 8 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \