[FFmpeg-devel] [PATCH v4 05/13] swscale: expose SwsContext publicly
Niklas Haas
ffmpeg at haasn.xyz
Thu Oct 24 13:25:15 EEST 2024
From: Niklas Haas <git at haasn.dev>
Following in the footsteps of the work in the previous commit, it's now
relatively straightforward to expose the options struct publicly as
SwsContext. This is a step towards making this more user friendly, as
well as following API conventions established elsewhere.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git at haasn.dev>
---
libswscale/swscale.h | 93 +++++++++++++++++++++++--
libswscale/swscale_internal.h | 45 +------------
libswscale/utils.c | 123 +++++++++++++++-------------------
3 files changed, 144 insertions(+), 117 deletions(-)
diff --git a/libswscale/swscale.h b/libswscale/swscale.h
index 50c705ae06..4baef532b6 100644
--- a/libswscale/swscale.h
+++ b/libswscale/swscale.h
@@ -42,8 +42,6 @@
#include "version.h"
#endif
-typedef struct SwsContext SwsContext;
-
/**
* @defgroup libsws libswscale
* Color conversion and scaling library.
@@ -65,17 +63,98 @@ const char *swscale_configuration(void);
const char *swscale_license(void);
/**
- * Get the AVClass for swsContext. It can be used in combination with
+ * Get the AVClass for SwsContext. It can be used in combination with
* AV_OPT_SEARCH_FAKE_OBJ for examining options.
*
* @see av_opt_find().
*/
const AVClass *sws_get_class(void);
-/**
- * Allocate an empty SwsContext. This must be filled and passed to
- * sws_init_context(). For filling see AVOptions, options.c and
- * sws_setColorspaceDetails().
+/******************************
+ * Flags and quality settings *
+ ******************************/
+
+typedef enum SwsDither {
+ SWS_DITHER_NONE = 0, /* disable dithering */
+ SWS_DITHER_AUTO, /* auto-select from preset */
+ SWS_DITHER_BAYER, /* ordered dither matrix */
+ SWS_DITHER_ED, /* error diffusion */
+ SWS_DITHER_A_DITHER, /* arithmetic addition */
+ SWS_DITHER_X_DITHER, /* arithmetic xor */
+ SWS_DITHER_NB, /* not part of the ABI */
+} SwsDither;
+
+typedef enum SwsAlphaBlend {
+ SWS_ALPHA_BLEND_NONE = 0,
+ SWS_ALPHA_BLEND_UNIFORM,
+ SWS_ALPHA_BLEND_CHECKERBOARD,
+ SWS_ALPHA_BLEND_NB, /* not part of the ABI */
+} SwsAlphaBlend;
+
+/***********************************
+ * Context creation and management *
+ ***********************************/
+
+/**
+ * Main external API structure. New fields can be added to the end with
+ * minor version bumps. Removal, reordering and changes to existing fields
+ * require a major version bump. sizeof(SwsContext) is not part of the ABI.
+ */
+typedef struct SwsContext {
+ const AVClass *av_class;
+
+ /**
+ * Private data of the user, can be used to carry app specific stuff.
+ */
+ void *opaque;
+
+ /**
+ * Bitmask of SWS_*.
+ */
+ unsigned flags;
+
+ /**
+ * Extra parameters for fine-tuning certain scalers.
+ */
+ double scaler_params[2];
+
+ /**
+ * How many threads to use for processing, or 0 for automatic selection.
+ */
+ int threads;
+
+ /**
+ * Dither mode.
+ */
+ SwsDither dither;
+
+ /**
+ * Alpha blending mode. See `SwsAlphaBlend` for details.
+ */
+ SwsAlphaBlend alpha_blend;
+
+ /**
+ * Use gamma correct scaling.
+ */
+ int gamma_flag;
+
+ /**
+ * Frame property overrides.
+ */
+ int src_w, src_h; ///< Width and height of the source frame
+ int dst_w, dst_h; ///< Width and height of the destination frame
+ int src_format; ///< Source pixel format
+ int dst_format; ///< Destination pixel format
+ int src_range; ///< Source is full range
+ int dst_range; ///< Destination is full range
+ int src_v_chr_pos; ///< Source vertical chroma position in luma grid / 256
+ int src_h_chr_pos; ///< Source horizontal chroma position
+ int dst_v_chr_pos; ///< Destination vertical chroma position
+ int dst_h_chr_pos; ///< Destination horizontal chroma position
+} SwsContext;
+
+/**
+ * Allocate an empty SwsContext and set its fields to default values.
*/
SwsContext *sws_alloc_context(void);
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index d459b79af3..12fa406e2c 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -73,23 +73,6 @@ static inline SwsInternal *sws_internal(const SwsContext *sws)
return (SwsInternal *) sws;
}
-typedef enum SwsDither {
- SWS_DITHER_NONE = 0,
- SWS_DITHER_AUTO,
- SWS_DITHER_BAYER,
- SWS_DITHER_ED,
- SWS_DITHER_A_DITHER,
- SWS_DITHER_X_DITHER,
- SWS_DITHER_NB,
-} SwsDither;
-
-typedef enum SwsAlphaBlend {
- SWS_ALPHA_BLEND_NONE = 0,
- SWS_ALPHA_BLEND_UNIFORM,
- SWS_ALPHA_BLEND_CHECKERBOARD,
- SWS_ALPHA_BLEND_NB,
-} SwsAlphaBlend;
-
typedef struct Range {
unsigned int start;
unsigned int len;
@@ -329,32 +312,10 @@ struct SwsFilterDescriptor;
/* This struct should be aligned on at least a 32-byte boundary. */
struct SwsInternal {
- /* Currently active user-facing options. */
- struct {
- const AVClass *av_class;
-
- double scaler_params[2]; ///< Input parameters for scaling algorithms that need them.
- int flags; ///< Flags passed by the user to select scaler algorithm, optimizations, subsampling, etc...
- int threads; ///< Number of threads used for scaling
-
- int src_w; ///< Width of source luma/alpha planes.
- int src_h; ///< Height of source luma/alpha planes.
- int dst_w; ///< Width of destination luma/alpha planes.
- int dst_h; ///< Height of destination luma/alpha planes.
- enum AVPixelFormat src_format; ///< Source pixel format.
- enum AVPixelFormat dst_format; ///< Destination pixel format.
- int src_range; ///< 0 = MPG YUV range, 1 = JPG YUV range (source image).
- int dst_range; ///< 0 = MPG YUV range, 1 = JPG YUV range (destination image).
- int src_h_chr_pos;
- int dst_h_chr_pos;
- int src_v_chr_pos;
- int dst_v_chr_pos;
- int gamma_flag;
-
- SwsDither dither;
- SwsAlphaBlend alpha_blend;
- } opts;
+ /* Currently active user-facing options. Also contains AVClass */
+ SwsContext opts;
+ /* Parent context (for slice contexts) */
SwsContext *parent;
AVSliceThread *slicethread;
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 4bddcb43d8..aee1153d4e 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -291,22 +291,20 @@ static SwsContext *alloc_set_opts(int srcW, int srcH, enum AVPixelFormat srcForm
int flags, const double *param)
{
SwsContext *sws = sws_alloc_context();
- SwsInternal *c = sws_internal(sws);
-
- if (!c)
+ if (!sws)
return NULL;
- c->opts.flags = flags;
- c->opts.src_w = srcW;
- c->opts.src_h = srcH;
- c->opts.dst_w = dstW;
- c->opts.dst_h = dstH;
- c->opts.src_format = srcFormat;
- c->opts.dst_format = dstFormat;
+ sws->flags = flags;
+ sws->src_w = srcW;
+ sws->src_h = srcH;
+ sws->dst_w = dstW;
+ sws->dst_h = dstH;
+ sws->src_format = srcFormat;
+ sws->dst_format = dstFormat;
if (param) {
- c->opts.scaler_params[0] = param[0];
- c->opts.scaler_params[1] = param[1];
+ sws->scaler_params[0] = param[0];
+ sws->scaler_params[1] = param[1];
}
return sws;
@@ -1234,16 +1232,16 @@ int sws_getColorspaceDetails(SwsContext *sws, int **inv_table,
SwsContext *sws_alloc_context(void)
{
- SwsInternal *c = av_mallocz(sizeof(SwsInternal));
+ SwsInternal *c = (SwsInternal *) av_mallocz(sizeof(SwsInternal));
+ if (!c)
+ return NULL;
- if (c) {
- c->opts.av_class = &ff_sws_context_class;
- av_opt_set_defaults(c);
- atomic_init(&c->stride_unaligned_warned, 0);
- atomic_init(&c->data_unaligned_warned, 0);
- }
+ c->opts.av_class = &ff_sws_context_class;
+ av_opt_set_defaults(c);
+ atomic_init(&c->stride_unaligned_warned, 0);
+ atomic_init(&c->data_unaligned_warned, 0);
- return (SwsContext *) c;
+ return &c->opts;
}
static uint16_t * alloc_gamma_tbl(double e)
@@ -2527,7 +2525,7 @@ void sws_freeContext(SwsContext *sws)
ff_free_filters(c);
- av_free(sws);
+ av_free(c);
}
void sws_free_context(SwsContext **pctx)
@@ -2540,7 +2538,7 @@ void sws_free_context(SwsContext **pctx)
*pctx = NULL;
}
-SwsContext *sws_getCachedContext(SwsContext *sws, int srcW,
+SwsContext *sws_getCachedContext(SwsContext *prev, int srcW,
int srcH, enum AVPixelFormat srcFormat,
int dstW, int dstH,
enum AVPixelFormat dstFormat, int flags,
@@ -2548,59 +2546,48 @@ SwsContext *sws_getCachedContext(SwsContext *sws, int srcW,
SwsFilter *dstFilter,
const double *param)
{
- SwsInternal *context;
-
+ SwsContext *sws;
static const double default_param[2] = { SWS_PARAM_DEFAULT,
SWS_PARAM_DEFAULT };
- int64_t src_h_chr_pos = -513, dst_h_chr_pos = -513,
- src_v_chr_pos = -513, dst_v_chr_pos = -513;
if (!param)
param = default_param;
- if ((context = sws_internal(sws)) &&
- (context->opts.src_w != srcW ||
- context->opts.src_h != srcH ||
- context->opts.src_format != srcFormat ||
- context->opts.dst_w != dstW ||
- context->opts.dst_h != dstH ||
- context->opts.dst_format != dstFormat ||
- context->opts.flags != flags ||
- context->opts.scaler_params[0] != param[0] ||
- context->opts.scaler_params[1] != param[1])) {
-
- av_opt_get_int(context, "src_h_chr_pos", 0, &src_h_chr_pos);
- av_opt_get_int(context, "src_v_chr_pos", 0, &src_v_chr_pos);
- av_opt_get_int(context, "dst_h_chr_pos", 0, &dst_h_chr_pos);
- av_opt_get_int(context, "dst_v_chr_pos", 0, &dst_v_chr_pos);
- sws_freeContext(sws);
- sws = NULL;
- }
-
- if (!sws) {
- if (!(sws = sws_alloc_context()))
- return NULL;
- context = sws_internal(sws);
- context->opts.src_w = srcW;
- context->opts.src_h = srcH;
- context->opts.src_format = srcFormat;
- context->opts.dst_w = dstW;
- context->opts.dst_h = dstH;
- context->opts.dst_format = dstFormat;
- context->opts.flags = flags;
- context->opts.scaler_params[0] = param[0];
- context->opts.scaler_params[1] = param[1];
-
- av_opt_set_int(context, "src_h_chr_pos", src_h_chr_pos, 0);
- av_opt_set_int(context, "src_v_chr_pos", src_v_chr_pos, 0);
- av_opt_set_int(context, "dst_h_chr_pos", dst_h_chr_pos, 0);
- av_opt_set_int(context, "dst_v_chr_pos", dst_v_chr_pos, 0);
-
- if (sws_init_context(sws, srcFilter, dstFilter) < 0) {
- sws_freeContext(sws);
- return NULL;
- }
+ if (prev && (prev->src_w == srcW ||
+ prev->src_h == srcH ||
+ prev->src_format == srcFormat ||
+ prev->dst_w == dstW ||
+ prev->dst_h == dstH ||
+ prev->dst_format == dstFormat ||
+ prev->flags == flags ||
+ prev->scaler_params[0] == param[0] ||
+ prev->scaler_params[1] == param[1])) {
+ return prev;
}
+
+ if (!(sws = sws_alloc_context())) {
+ sws_free_context(&prev);
+ return NULL;
+ }
+
+ if (prev) {
+ av_opt_copy(sws, prev);
+ sws_free_context(&prev);
+ }
+
+ sws->src_w = srcW;
+ sws->src_h = srcH;
+ sws->src_format = srcFormat;
+ sws->dst_w = dstW;
+ sws->dst_h = dstH;
+ sws->dst_format = dstFormat;
+ sws->flags = flags;
+ sws->scaler_params[0] = param[0];
+ sws->scaler_params[1] = param[1];
+
+ if (sws_init_context(sws, srcFilter, dstFilter) < 0)
+ sws_free_context(&sws);
+
return sws;
}
--
2.46.1
More information about the ffmpeg-devel
mailing list