diff mbox series

[FFmpeg-devel,v2,06/19] swscale: add new frame testing API

Message ID 20241014134354.180848-7-ffmpeg@haasn.xyz
State New
Headers show
Series swscale: major refactoring and new API | expand

Checks

Context Check Description
yinshiyou/configure_loongarch64 warning Failed to apply patch

Commit Message

Niklas Haas Oct. 14, 2024, 1:37 p.m. UTC
From: Niklas Haas <git@haasn.dev>

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 <git@haasn.dev>
---
 libswscale/swscale.h | 55 +++++++++++++++++++++++++++++++++++
 libswscale/utils.c   | 68 ++++++++++++++++++++++++++++++++++++++++++++
 libswscale/utils.h   |  2 ++
 3 files changed, 125 insertions(+)
diff mbox series

Patch

diff --git a/libswscale/swscale.h b/libswscale/swscale.h
index f9fd340240..ba944cdc6f 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 464f3e24b7..682372456d 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -2711,3 +2711,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 */