swscale/format: pass SwsFormat by ref instead of by value where possible

The one exception is in adapt_colors(), which mutates these structs on
its own stack anyways.
This commit is contained in:
Niklas Haas
2026-02-20 17:39:46 +01:00
committed by Niklas Haas
parent 4e36265dea
commit 841ca7a2cb
6 changed files with 80 additions and 78 deletions

View File

@@ -1080,7 +1080,7 @@ static inline AVRational av_neg_q(AVRational x)
return (AVRational) { -x.num, x.den };
}
static SwsLinearOp fmt_encode_range(const SwsFormat fmt, bool *incomplete)
static SwsLinearOp fmt_encode_range(const SwsFormat *fmt, bool *incomplete)
{
SwsLinearOp c = { .m = {
{ Q1, Q0, Q0, Q0, Q0 },
@@ -1089,22 +1089,22 @@ static SwsLinearOp fmt_encode_range(const SwsFormat fmt, bool *incomplete)
{ Q0, Q0, Q0, Q1, Q0 },
}};
const int depth0 = fmt.desc->comp[0].depth;
const int depth1 = fmt.desc->comp[1].depth;
const int depth2 = fmt.desc->comp[2].depth;
const int depth3 = fmt.desc->comp[3].depth;
const int depth0 = fmt->desc->comp[0].depth;
const int depth1 = fmt->desc->comp[1].depth;
const int depth2 = fmt->desc->comp[2].depth;
const int depth3 = fmt->desc->comp[3].depth;
if (fmt.desc->flags & AV_PIX_FMT_FLAG_FLOAT)
if (fmt->desc->flags & AV_PIX_FMT_FLAG_FLOAT)
return c; /* floats are directly output as-is */
if (fmt.csp == AVCOL_SPC_RGB || (fmt.desc->flags & AV_PIX_FMT_FLAG_XYZ)) {
if (fmt->csp == AVCOL_SPC_RGB || (fmt->desc->flags & AV_PIX_FMT_FLAG_XYZ)) {
c.m[0][0] = Q((1 << depth0) - 1);
c.m[1][1] = Q((1 << depth1) - 1);
c.m[2][2] = Q((1 << depth2) - 1);
} else if (fmt.range == AVCOL_RANGE_JPEG) {
} else if (fmt->range == AVCOL_RANGE_JPEG) {
/* Full range YUV */
c.m[0][0] = Q((1 << depth0) - 1);
if (fmt.desc->nb_components >= 3) {
if (fmt->desc->nb_components >= 3) {
/* This follows the ITU-R convention, which is slightly different
* from the JFIF convention. */
c.m[1][1] = Q((1 << depth1) - 1);
@@ -1114,11 +1114,11 @@ static SwsLinearOp fmt_encode_range(const SwsFormat fmt, bool *incomplete)
}
} else {
/* Limited range YUV */
if (fmt.range == AVCOL_RANGE_UNSPECIFIED)
if (fmt->range == AVCOL_RANGE_UNSPECIFIED)
*incomplete = true;
c.m[0][0] = Q(219 << (depth0 - 8));
c.m[0][4] = Q( 16 << (depth0 - 8));
if (fmt.desc->nb_components >= 3) {
if (fmt->desc->nb_components >= 3) {
c.m[1][1] = Q(224 << (depth1 - 8));
c.m[2][2] = Q(224 << (depth2 - 8));
c.m[1][4] = Q(128 << (depth1 - 8));
@@ -1126,12 +1126,12 @@ static SwsLinearOp fmt_encode_range(const SwsFormat fmt, bool *incomplete)
}
}
if (fmt.desc->flags & AV_PIX_FMT_FLAG_ALPHA) {
const bool is_ya = fmt.desc->nb_components == 2;
if (fmt->desc->flags & AV_PIX_FMT_FLAG_ALPHA) {
const bool is_ya = fmt->desc->nb_components == 2;
c.m[3][3] = Q((1 << (is_ya ? depth1 : depth3)) - 1);
}
if (fmt.format == AV_PIX_FMT_MONOWHITE) {
if (fmt->format == AV_PIX_FMT_MONOWHITE) {
/* This format is inverted, 0 = white, 1 = black */
c.m[0][4] = av_add_q(c.m[0][4], c.m[0][0]);
c.m[0][0] = av_neg_q(c.m[0][0]);
@@ -1141,7 +1141,7 @@ static SwsLinearOp fmt_encode_range(const SwsFormat fmt, bool *incomplete)
return c;
}
static SwsLinearOp fmt_decode_range(const SwsFormat fmt, bool *incomplete)
static SwsLinearOp fmt_decode_range(const SwsFormat *fmt, bool *incomplete)
{
SwsLinearOp c = fmt_encode_range(fmt, incomplete);
@@ -1153,7 +1153,7 @@ static SwsLinearOp fmt_decode_range(const SwsFormat fmt, bool *incomplete)
}
/* Explicitly initialize alpha for sanity */
if (!(fmt.desc->flags & AV_PIX_FMT_FLAG_ALPHA))
if (!(fmt->desc->flags & AV_PIX_FMT_FLAG_ALPHA))
c.m[3][4] = Q1;
c.mask = ff_sws_linear_mask(c);
@@ -1219,15 +1219,15 @@ static bool trc_is_hdr(enum AVColorTransferCharacteristic trc)
static int fmt_dither(SwsContext *ctx, SwsOpList *ops,
const SwsPixelType type,
const SwsFormat src, const SwsFormat dst)
const SwsFormat *src, const SwsFormat *dst)
{
SwsDither mode = ctx->dither;
SwsDitherOp dither;
const int bpc = dst.desc->comp[0].depth;
const int bpc = dst->desc->comp[0].depth;
if (mode == SWS_DITHER_AUTO) {
/* Visual threshold of perception: 12 bits for SDR, 14 bits for HDR */
const int jnd_bits = trc_is_hdr(dst.color.trc) ? 14 : 12;
const int jnd_bits = trc_is_hdr(dst->color.trc) ? 14 : 12;
mode = bpc >= jnd_bits ? SWS_DITHER_NONE : SWS_DITHER_BAYER;
}
@@ -1266,7 +1266,7 @@ static int fmt_dither(SwsContext *ctx, SwsOpList *ops,
dither.y_offset[i] = offsets_16x16[i];
}
if (src.desc->nb_components < 3 && bpc >= 8) {
if (src->desc->nb_components < 3 && bpc >= 8) {
/**
* For high-bit-depth sources without chroma, use same matrix
* offset for all color channels. This prevents introducing color
@@ -1316,13 +1316,13 @@ linear_mat3(const AVRational m00, const AVRational m01, const AVRational m02,
}
int ff_sws_decode_colors(SwsContext *ctx, SwsPixelType type,
SwsOpList *ops, const SwsFormat fmt, bool *incomplete)
SwsOpList *ops, const SwsFormat *fmt, bool *incomplete)
{
const AVLumaCoefficients *c = av_csp_luma_coeffs_from_avcsp(fmt.csp);
const AVLumaCoefficients *c = av_csp_luma_coeffs_from_avcsp(fmt->csp);
RET(ff_sws_op_list_append(ops, &(SwsOp) {
.op = SWS_OP_CONVERT,
.type = fmt_pixel_type(fmt.format),
.type = fmt_pixel_type(fmt->format),
.convert.to = type,
}));
@@ -1334,7 +1334,7 @@ int ff_sws_decode_colors(SwsContext *ctx, SwsPixelType type,
}));
/* Final step, decode colorspace */
switch (fmt.csp) {
switch (fmt->csp) {
case AVCOL_SPC_RGB:
return 0;
case AVCOL_SPC_UNSPECIFIED:
@@ -1398,12 +1398,12 @@ int ff_sws_decode_colors(SwsContext *ctx, SwsPixelType type,
}
int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType type,
SwsOpList *ops, const SwsFormat src,
const SwsFormat dst, bool *incomplete)
SwsOpList *ops, const SwsFormat *src,
const SwsFormat *dst, bool *incomplete)
{
const AVLumaCoefficients *c = av_csp_luma_coeffs_from_avcsp(dst.csp);
const AVLumaCoefficients *c = av_csp_luma_coeffs_from_avcsp(dst->csp);
switch (dst.csp) {
switch (dst->csp) {
case AVCOL_SPC_RGB:
break;
case AVCOL_SPC_UNSPECIFIED:
@@ -1469,14 +1469,14 @@ int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType type,
.lin = fmt_encode_range(dst, incomplete),
}));
if (!(dst.desc->flags & AV_PIX_FMT_FLAG_FLOAT)) {
if (!(dst->desc->flags & AV_PIX_FMT_FLAG_FLOAT)) {
SwsConst range = {0};
const bool is_ya = dst.desc->nb_components == 2;
for (int i = 0; i < dst.desc->nb_components; i++) {
const bool is_ya = dst->desc->nb_components == 2;
for (int i = 0; i < dst->desc->nb_components; i++) {
/* Clamp to legal pixel range */
const int idx = i * (is_ya ? 3 : 1);
range.q4[idx] = Q((1 << dst.desc->comp[i].depth) - 1);
range.q4[idx] = Q((1 << dst->desc->comp[i].depth) - 1);
}
RET(fmt_dither(ctx, ops, type, src, dst));
@@ -1496,7 +1496,7 @@ int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType type,
return ff_sws_op_list_append(ops, &(SwsOp) {
.type = type,
.op = SWS_OP_CONVERT,
.convert.to = fmt_pixel_type(dst.format),
.convert.to = fmt_pixel_type(dst->format),
});
}

View File

@@ -168,9 +168,9 @@ int ff_sws_encode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt);
* Returns 0 on success, or a negative error code on failure.
*/
int ff_sws_decode_colors(SwsContext *ctx, SwsPixelType type, SwsOpList *ops,
const SwsFormat fmt, bool *incomplete);
const SwsFormat *fmt, bool *incomplete);
int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType type, SwsOpList *ops,
const SwsFormat src, const SwsFormat dst,
const SwsFormat *src, const SwsFormat *dst,
bool *incomplete);
#endif /* SWSCALE_FORMAT_H */

View File

@@ -457,12 +457,13 @@ static int init_legacy_subpass(SwsGraph *graph, SwsContext *sws,
return 0;
}
static int add_legacy_sws_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
SwsPass *input, SwsPass **output)
static int add_legacy_sws_pass(SwsGraph *graph, const SwsFormat *src,
const SwsFormat *dst, SwsPass *input,
SwsPass **output)
{
int ret, warned = 0;
SwsContext *const ctx = graph->ctx;
if (src.hw_format != AV_PIX_FMT_NONE || dst.hw_format != AV_PIX_FMT_NONE)
if (src->hw_format != AV_PIX_FMT_NONE || dst->hw_format != AV_PIX_FMT_NONE)
return AVERROR(ENOTSUP);
SwsContext *sws = sws_alloc_context();
@@ -474,20 +475,20 @@ static int add_legacy_sws_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
sws->alpha_blend = ctx->alpha_blend;
sws->gamma_flag = ctx->gamma_flag;
sws->src_w = src.width;
sws->src_h = src.height;
sws->src_format = src.format;
sws->src_range = src.range == AVCOL_RANGE_JPEG;
sws->src_w = src->width;
sws->src_h = src->height;
sws->src_format = src->format;
sws->src_range = src->range == AVCOL_RANGE_JPEG;
sws->dst_w = dst.width;
sws->dst_h = dst.height;
sws->dst_format = dst.format;
sws->dst_range = dst.range == AVCOL_RANGE_JPEG;
get_chroma_pos(graph, &sws->src_h_chr_pos, &sws->src_v_chr_pos, &src);
get_chroma_pos(graph, &sws->dst_h_chr_pos, &sws->dst_v_chr_pos, &dst);
sws->dst_w = dst->width;
sws->dst_h = dst->height;
sws->dst_format = dst->format;
sws->dst_range = dst->range == AVCOL_RANGE_JPEG;
get_chroma_pos(graph, &sws->src_h_chr_pos, &sws->src_v_chr_pos, src);
get_chroma_pos(graph, &sws->dst_h_chr_pos, &sws->dst_v_chr_pos, dst);
graph->incomplete |= src.range == AVCOL_RANGE_UNSPECIFIED;
graph->incomplete |= dst.range == AVCOL_RANGE_UNSPECIFIED;
graph->incomplete |= src->range == AVCOL_RANGE_UNSPECIFIED;
graph->incomplete |= dst->range == AVCOL_RANGE_UNSPECIFIED;
/* Allow overriding chroma position with the legacy API */
legacy_chr_pos(graph, &sws->src_h_chr_pos, ctx->src_h_chr_pos, &warned);
@@ -512,12 +513,12 @@ static int add_legacy_sws_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
(int **)&table, &out_full,
&brightness, &contrast, &saturation);
inv_table = sws_getCoefficients(src.csp);
table = sws_getCoefficients(dst.csp);
inv_table = sws_getCoefficients(src->csp);
table = sws_getCoefficients(dst->csp);
graph->incomplete |= src.csp != dst.csp &&
(src.csp == AVCOL_SPC_UNSPECIFIED ||
dst.csp == AVCOL_SPC_UNSPECIFIED);
graph->incomplete |= src->csp != dst->csp &&
(src->csp == AVCOL_SPC_UNSPECIFIED ||
dst->csp == AVCOL_SPC_UNSPECIFIED);
sws_setColorspaceDetails(sws, inv_table, in_full, table, out_full,
brightness, contrast, saturation);
@@ -531,8 +532,9 @@ static int add_legacy_sws_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
*********************/
#if CONFIG_UNSTABLE
static int add_convert_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
SwsPass *input, SwsPass **output)
static int add_convert_pass(SwsGraph *graph, const SwsFormat *src,
const SwsFormat *dst, SwsPass *input,
SwsPass **output)
{
const SwsPixelType type = SWS_PIXEL_F32;
@@ -545,23 +547,23 @@ static int add_convert_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
goto fail;
/* The new format conversion layer cannot scale for now */
if (src.width != dst.width || src.height != dst.height ||
src.desc->log2_chroma_h || src.desc->log2_chroma_w ||
dst.desc->log2_chroma_h || dst.desc->log2_chroma_w)
if (src->width != dst->width || src->height != dst->height ||
src->desc->log2_chroma_h || src->desc->log2_chroma_w ||
dst->desc->log2_chroma_h || dst->desc->log2_chroma_w)
goto fail;
/* The new code does not yet support alpha blending */
if (src.desc->flags & AV_PIX_FMT_FLAG_ALPHA &&
if (src->desc->flags & AV_PIX_FMT_FLAG_ALPHA &&
ctx->alpha_blend != SWS_ALPHA_BLEND_NONE)
goto fail;
ops = ff_sws_op_list_alloc();
if (!ops)
return AVERROR(ENOMEM);
ops->src = src;
ops->dst = dst;
ops->src = *src;
ops->dst = *dst;
ret = ff_sws_decode_pixfmt(ops, src.format);
ret = ff_sws_decode_pixfmt(ops, src->format);
if (ret < 0)
goto fail;
ret = ff_sws_decode_colors(ctx, type, ops, src, &graph->incomplete);
@@ -570,12 +572,12 @@ static int add_convert_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
ret = ff_sws_encode_colors(ctx, type, ops, src, dst, &graph->incomplete);
if (ret < 0)
goto fail;
ret = ff_sws_encode_pixfmt(ops, dst.format);
ret = ff_sws_encode_pixfmt(ops, dst->format);
if (ret < 0)
goto fail;
av_log(ctx, AV_LOG_VERBOSE, "Conversion pass for %s -> %s:\n",
av_get_pix_fmt_name(src.format), av_get_pix_fmt_name(dst.format));
av_get_pix_fmt_name(src->format), av_get_pix_fmt_name(dst->format));
av_log(ctx, AV_LOG_DEBUG, "Unoptimized operation list:\n");
ff_sws_op_list_print(ctx, AV_LOG_DEBUG, AV_LOG_TRACE, ops);
@@ -673,7 +675,7 @@ static int adapt_colors(SwsGraph *graph, SwsFormat src, SwsFormat dst,
if (fmt_in != src.format) {
SwsFormat tmp = src;
tmp.format = fmt_in;
ret = add_convert_pass(graph, src, tmp, input, &input);
ret = add_convert_pass(graph, &src, &tmp, input, &input);
if (ret < 0)
return ret;
}
@@ -715,7 +717,7 @@ static int init_passes(SwsGraph *graph)
src.color = dst.color;
if (!ff_fmt_equal(&src, &dst)) {
ret = add_convert_pass(graph, src, dst, pass, &pass);
ret = add_convert_pass(graph, &src, &dst, pass, &pass);
if (ret < 0)
return ret;
}

View File

@@ -1153,8 +1153,8 @@ static int rw_pixel_bits(const SwsOp *op)
return elems * size * bits;
}
int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags, SwsFormat dst,
SwsPass *input, SwsPass **output)
int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags,
const SwsFormat *dst, SwsPass *input, SwsPass **output)
{
SwsContext *ctx = graph->ctx;
SwsOpPass *p = NULL;
@@ -1198,8 +1198,8 @@ int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags, SwsFormat ds
p->pixel_bits_in = rw_pixel_bits(read);
p->pixel_bits_out = rw_pixel_bits(write);
p->exec_base = (SwsOpExec) {
.width = dst.width,
.height = dst.height,
.width = dst->width,
.height = dst->height,
.block_size_in = p->comp.block_size * p->pixel_bits_in >> 3,
.block_size_out = p->comp.block_size * p->pixel_bits_out >> 3,
};
@@ -1209,8 +1209,8 @@ int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags, SwsFormat ds
p->idx_out[i] = i < p->planes_out ? ops->order_dst.in[i] : -1;
}
pass = ff_sws_graph_add_pass(graph, dst.format, dst.width, dst.height, input,
p->comp.slice_align, p, op_pass_run);
pass = ff_sws_graph_add_pass(graph, dst->format, dst->width, dst->height,
input, p->comp.slice_align, p, op_pass_run);
if (!pass) {
ret = AVERROR(ENOMEM);
goto fail;

View File

@@ -297,7 +297,7 @@ enum SwsOpCompileFlags {
*
* Note: `ops` may be modified by this function.
*/
int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags, SwsFormat dst,
SwsPass *input, SwsPass **output);
int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags,
const SwsFormat *dst, SwsPass *input, SwsPass **output);
#endif

View File

@@ -46,9 +46,9 @@ static int run_test(SwsContext *const ctx, AVFrame *frame,
if (ff_sws_decode_pixfmt(ops, src.format) < 0)
goto fail;
if (ff_sws_decode_colors(ctx, SWS_PIXEL_F32, ops, src, &incomplete) < 0)
if (ff_sws_decode_colors(ctx, SWS_PIXEL_F32, ops, &src, &incomplete) < 0)
goto fail;
if (ff_sws_encode_colors(ctx, SWS_PIXEL_F32, ops, src, dst, &incomplete) < 0)
if (ff_sws_encode_colors(ctx, SWS_PIXEL_F32, ops, &src, &dst, &incomplete) < 0)
goto fail;
if (ff_sws_encode_pixfmt(ops, dst.format) < 0)
goto fail;