The branch, master has been updated
via 01b105bb06f30d275c3a1932de4d03a4767f8a18 (commit)
via 9a386078cc0484f064e6cc4309a2a9048bd25fae (commit)
via 84b365d522a59c5e80fb0b3f960d1c36a2674797 (commit)
via 6c3a63112be927526b08c0154b2df786fa7bce3d (commit)
via 7b564e2efc295ca205642c5c2ddfe5d8e77ecf08 (commit)
via ad5b151f88aed49b4c36e764186214c13e0788ac (commit)
via f5bc9704edb3254e65c108509052f19eb77622c1 (commit)
via c1717cb6669f986a8bd04c8bfc5e37927c12769d (commit)
from c9710dae3c6151a22f0fff60f0a9b4514f6a3b97 (commit)
- Log -----------------------------------------------------------------
commit 01b105bb06f30d275c3a1932de4d03a4767f8a18
Author: Niklas Haas <[email protected]>
AuthorDate: Thu Nov 6 17:00:04 2025 +0100
Commit: Niklas Haas <[email protected]>
CommitDate: Thu Nov 6 20:34:51 2025 +0000
tests/fate/swscale: add swscale self-test
This one takes about 2.93s on my machine, but ensures that every pixel
format conversion roundtrips correctly. Note that due to existing bugs in
libswscale, this one only passes when using the new format conversion code.
Restrict the test to -v 16 (AV_LOG_ERROR) to avoid excess amounts of output.
diff --git a/tests/fate/libswscale.mak b/tests/fate/libswscale.mak
index 4c29220e6f..59da506648 100644
--- a/tests/fate/libswscale.mak
+++ b/tests/fate/libswscale.mak
@@ -31,6 +31,11 @@ fate-sws-yuv-range: CMD = framecrc \
-frames 1 \
-vf
scale=in_color_matrix=bt601:in_range=limited:out_color_matrix=bt601:out_range=full:flags=+accurate_rnd+bitexact
+# This self-check currently fails for legacy swscale, so pass SWS_UNSTABLE to
use the new code
+FATE_LIBSWSCALE-$(CONFIG_UNSTABLE) += fate-sws-unscaled
+fate-sws-unscaled: libswscale/tests/swscale$(EXESUF)
+fate-sws-unscaled: CMD = run libswscale/tests/swscale$(EXESUF) -unscaled 1
-flags 0x100000 -v 16
+
FATE_LIBSWSCALE += $(FATE_LIBSWSCALE-yes)
FATE_LIBSWSCALE_SAMPLES += $(FATE_LIBSWSCALE_SAMPLES-yes)
FATE-$(CONFIG_SWSCALE) += $(FATE_LIBSWSCALE)
diff --git a/tests/ref/fate/sws-unscaled b/tests/ref/fate/sws-unscaled
new file mode 100644
index 0000000000..e69de29bb2
commit 9a386078cc0484f064e6cc4309a2a9048bd25fae
Author: Niklas Haas <[email protected]>
AuthorDate: Thu Nov 6 19:03:22 2025 +0100
Commit: Niklas Haas <[email protected]>
CommitDate: Thu Nov 6 20:34:51 2025 +0000
tests/swscale: use av_log() where appropriate
We can't use ANSI color codes inside av_log(), so fall back to printf()
for these; but match the INFO verbosity level.
Also change the format slightly to drop SSIM numbers down to just below
VERBOSE level, since VERBOSE tends to generate a lot of swscale related
spam.
diff --git a/libswscale/tests/swscale.c b/libswscale/tests/swscale.c
index 564f38af2e..8a85bef94e 100644
--- a/libswscale/tests/swscale.c
+++ b/libswscale/tests/swscale.c
@@ -264,8 +264,8 @@ static int run_test(enum AVPixelFormat src_fmt, enum
AVPixelFormat dst_fmt,
dst->height = dst_h;
if (sws_scale_frame(sws[0], src, ref) < 0) {
- fprintf(stderr, "Failed %s ---> %s\n",
av_get_pix_fmt_name(ref->format),
- av_get_pix_fmt_name(src->format));
+ av_log(NULL, AV_LOG_ERROR, "Failed %s ---> %s\n",
+ av_get_pix_fmt_name(ref->format),
av_get_pix_fmt_name(src->format));
goto error;
}
@@ -277,8 +277,8 @@ static int run_test(enum AVPixelFormat src_fmt, enum
AVPixelFormat dst_fmt,
for (int i = 0; i < opts.iters; i++) {
if (sws_scale_frame(sws[1], dst, src) < 0) {
- fprintf(stderr, "Failed %s ---> %s\n",
av_get_pix_fmt_name(src->format),
- av_get_pix_fmt_name(dst->format));
+ av_log(NULL, AV_LOG_ERROR, "Failed %s ---> %s\n",
+ av_get_pix_fmt_name(src->format),
av_get_pix_fmt_name(dst->format));
goto error;
}
}
@@ -286,23 +286,29 @@ static int run_test(enum AVPixelFormat src_fmt, enum
AVPixelFormat dst_fmt,
time = av_gettime_relative() - time;
if (sws_scale_frame(sws[2], out, dst) < 0) {
- fprintf(stderr, "Failed %s ---> %s\n",
av_get_pix_fmt_name(dst->format),
- av_get_pix_fmt_name(out->format));
+ av_log(NULL, AV_LOG_ERROR, "Failed %s ---> %s\n",
+ av_get_pix_fmt_name(dst->format),
av_get_pix_fmt_name(out->format));
goto error;
}
get_ssim(ssim, out, ref, comps);
- printf("%s %dx%d -> %s %3dx%3d, flags=0x%x dither=%u, "
- "SSIM {Y=%f U=%f V=%f A=%f}\n",
+ av_log(NULL, AV_LOG_INFO, "%s %dx%d -> %s %3dx%3d, flags=0x%x dither=%u\n",
av_get_pix_fmt_name(src->format), src->width, src->height,
av_get_pix_fmt_name(dst->format), dst->width, dst->height,
- mode.flags, mode.dither,
+ mode.flags, mode.dither);
+
+ av_log(NULL, AV_LOG_VERBOSE - 4, " SSIM {Y=%f U=%f V=%f A=%f}\n",
ssim[0], ssim[1], ssim[2], ssim[3]);
loss = get_loss(ssim);
if (loss - expected_loss > 1e-4 && dst_w >= ref->width && dst_h >=
ref->height) {
- int bad = loss - expected_loss > 1e-2;
- printf("\033[1;31m loss %g is %s by %g, expected loss %g\033[0m\n",
+ const int bad = loss - expected_loss > 1e-2;
+ const int level = bad ? AV_LOG_ERROR : AV_LOG_WARNING;
+ av_log(NULL, level, "%s %dx%d -> %s %3dx%3d, flags=0x%x dither=%u\n",
+ av_get_pix_fmt_name(src->format), src->width, src->height,
+ av_get_pix_fmt_name(dst->format), dst->width, dst->height,
+ mode.flags, mode.dither);
+ av_log(NULL, level, " loss %g is %s by %g, expected loss %g\n",
loss, bad ? "WORSE" : "worse", loss - expected_loss,
expected_loss);
if (bad)
goto error;
@@ -312,8 +318,8 @@ static int run_test(enum AVPixelFormat src_fmt, enum
AVPixelFormat dst_fmt,
/* Compare against the legacy swscale API as a reference */
time_ref = av_gettime_relative();
if (scale_legacy(dst, src, mode, opts) < 0) {
- fprintf(stderr, "Failed ref %s ---> %s\n",
av_get_pix_fmt_name(src->format),
- av_get_pix_fmt_name(dst->format));
+ av_log(NULL, AV_LOG_ERROR, "Failed ref %s ---> %s\n",
+ av_get_pix_fmt_name(src->format),
av_get_pix_fmt_name(dst->format));
goto error;
}
time_ref = av_gettime_relative() - time_ref;
@@ -341,8 +347,9 @@ static int run_test(enum AVPixelFormat src_fmt, enum
AVPixelFormat dst_fmt,
const float loss_ref = get_loss(ssim_ref);
if (loss - loss_ref > 1e-4) {
int bad = loss - loss_ref > 1e-2;
- printf("\033[1;31m loss %g is %s by %g, ref loss %g, "
- "SSIM {Y=%f U=%f V=%f A=%f}\033[0m\n",
+ av_log(NULL, bad ? AV_LOG_ERROR : AV_LOG_WARNING,
+ " loss %g is %s by %g, ref loss %g, "
+ "SSIM {Y=%f U=%f V=%f A=%f}\n",
loss, bad ? "WORSE" : "worse", loss - loss_ref, loss_ref,
ssim_ref[0], ssim_ref[1], ssim_ref[2], ssim_ref[3]);
if (bad)
@@ -359,11 +366,13 @@ static int run_test(enum AVPixelFormat src_fmt, enum
AVPixelFormat dst_fmt,
speedup_count++;
}
- printf(" time=%"PRId64" us, ref=%"PRId64" us, speedup=%.3fx
%s%s\033[0m\n",
- time / opts.iters, time_ref / opts.iters, ratio,
- speedup_color(ratio), ratio >= 1.0 ? "faster" : "slower");
+ if (av_log_get_level() >= AV_LOG_INFO) {
+ printf(" time=%"PRId64" us, ref=%"PRId64" us, speedup=%.3fx
%s%s\033[0m\n",
+ time / opts.iters, time_ref / opts.iters, ratio,
+ speedup_color(ratio), ratio >= 1.0 ? "faster" : "slower");
+ }
} else if (opts.bench) {
- printf(" time=%"PRId64" us\n", time / opts.iters);
+ av_log(NULL, AV_LOG_INFO, " time=%"PRId64" us\n", time / opts.iters);
}
fflush(stdout);
@@ -466,7 +475,7 @@ static int run_file_tests(const AVFrame *ref, FILE *fp,
struct options opts)
if (src_fmt == AV_PIX_FMT_NONE || dst_fmt == AV_PIX_FMT_NONE ||
sw != ref->width || sh != ref->height || dw > 8192 || dh > 8192 ||
mode.dither >= SWS_DITHER_NB) {
- fprintf(stderr, "malformed input file\n");
+ av_log(NULL, AV_LOG_FATAL, "malformed input file\n");
return -1;
}
commit 84b365d522a59c5e80fb0b3f960d1c36a2674797
Author: Niklas Haas <[email protected]>
AuthorDate: Thu Nov 6 18:16:10 2025 +0100
Commit: Niklas Haas <[email protected]>
CommitDate: Thu Nov 6 18:16:10 2025 +0100
avfilter/avfiltergraph: print both failing links on conversion error
This is more informative than the current behavior, because when the first
MERGE() succeeds but the second fails, the original link already has
merged formats and thus the error message is confusing.
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index 285a701d09..a46a7bd408 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -692,7 +692,8 @@ retry:
av_log(log_ctx, AV_LOG_ERROR,
"Impossible to convert between the formats
supported by the filter "
"'%s' and the filter '%s'\n", link->src->name,
link->dst->name);
- print_link_formats(log_ctx, AV_LOG_ERROR, link, &m, 1);
+ print_link_formats(log_ctx, AV_LOG_ERROR, inlink, &m,
1);
+ print_link_formats(log_ctx, AV_LOG_ERROR, outlink, &m,
1);
return AVERROR(ENOSYS);
} else {
count_merged += 2;
commit 6c3a63112be927526b08c0154b2df786fa7bce3d
Author: Niklas Haas <[email protected]>
AuthorDate: Thu Nov 6 18:09:36 2025 +0100
Commit: Niklas Haas <[email protected]>
CommitDate: Thu Nov 6 18:09:36 2025 +0100
avfilter/avfiltergraph: only print format lists for failing mergers
Instead of printing all format lists on a link negotiation error, just print
the relevant/failing format lists.
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index 15978fc7a8..285a701d09 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -443,7 +443,9 @@ static int formats_declared(AVFilterContext *f)
return 1;
}
-static void print_link_formats(void *log_ctx, int level, const AVFilterLink *l)
+static void print_link_formats(void *log_ctx, int level, const AVFilterLink *l,
+ const AVFilterFormatsMerger *mergers[],
+ int nb_mergers)
{
if (av_log_get_level() < level)
return;
@@ -454,9 +456,8 @@ static void print_link_formats(void *log_ctx, int level,
const AVFilterLink *l)
av_log(log_ctx, level, "Link '%s.%s' -> '%s.%s':\n",
l->src->name, l->srcpad->name, l->dst->name, l->dstpad->name);
- const AVFilterNegotiation *neg = ff_filter_get_negotiation(l);
- for (unsigned i = 0; i < neg->nb_mergers; i++) {
- const AVFilterFormatsMerger *m = &neg->mergers[i];
+ for (unsigned i = 0; i < nb_mergers; i++) {
+ const AVFilterFormatsMerger *m = mergers[i];
av_log(log_ctx, level, " %s:\n", m->name);
m->print_list(&bp, FF_FIELD_AT(void *, m->offset, l->incfg));
if (av_bprint_is_complete(&bp))
@@ -554,8 +555,9 @@ retry:
AVFilterLink *link = filter->inputs[j];
const AVFilterNegotiation *neg;
AVFilterContext *conv[4];
+ const AVFilterFormatsMerger *mergers[4]; /* triggered mergers */
const char *conv_filters[4], *conv_opts[4] = {0};
- unsigned neg_step, num_conv = 0;
+ unsigned neg_step, num_conv = 0, num_mergers = 0;
if (!link)
continue;
@@ -578,6 +580,8 @@ retry:
conv_opts[num_conv] = FF_FIELD_AT(char *,
m->conversion_opts_offset, *graph);
num_conv++;
}
+ av_assert1(num_mergers < FF_ARRAY_ELEMS(mergers));
+ mergers[num_mergers++] = m;
}
}
for (neg_step = 0; neg_step < neg->nb_mergers; neg_step++) {
@@ -594,6 +598,7 @@ retry:
if (ret < 0)
return ret;
if (!ret) {
+ mergers[num_mergers++] = m;
conv_filters[num_conv] = m->conversion_filter;
if (m->conversion_opts_offset)
conv_opts[num_conv] = FF_FIELD_AT(char *,
m->conversion_opts_offset, *graph);
@@ -616,7 +621,7 @@ retry:
"The filters '%s' and '%s' do not have a common
format "
"and automatic conversion is disabled.\n",
link->src->name, link->dst->name);
- print_link_formats(log_ctx, AV_LOG_ERROR, link);
+ print_link_formats(log_ctx, AV_LOG_ERROR, link, mergers,
num_mergers);
return AVERROR(EINVAL);
}
@@ -624,7 +629,7 @@ retry:
av_log(log_ctx, AV_LOG_ERROR,
"'%s' filter not present, cannot convert
formats.\n",
conv_filters[k]);
- print_link_formats(log_ctx, AV_LOG_ERROR, link);
+ print_link_formats(log_ctx, AV_LOG_ERROR, link, mergers,
num_mergers);
return AVERROR(EINVAL);
}
snprintf(inst_name, sizeof(inst_name), "auto_%s_%d",
@@ -687,7 +692,7 @@ retry:
av_log(log_ctx, AV_LOG_ERROR,
"Impossible to convert between the formats
supported by the filter "
"'%s' and the filter '%s'\n", link->src->name,
link->dst->name);
- print_link_formats(log_ctx, AV_LOG_ERROR, link);
+ print_link_formats(log_ctx, AV_LOG_ERROR, link, &m, 1);
return AVERROR(ENOSYS);
} else {
count_merged += 2;
commit 7b564e2efc295ca205642c5c2ddfe5d8e77ecf08
Author: Niklas Haas <[email protected]>
AuthorDate: Thu Nov 6 18:01:37 2025 +0100
Commit: Niklas Haas <[email protected]>
CommitDate: Thu Nov 6 18:01:37 2025 +0100
avfilter/avfiltergraph: print all format lists on config failure
Instead of just printing the pixel/sample formats.
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index 4c80204f01..15978fc7a8 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -443,60 +443,73 @@ static int formats_declared(AVFilterContext *f)
return 1;
}
-static void print_formats(void *log_ctx, int level, enum AVMediaType type,
- const AVFilterFormats *formats)
+static void print_link_formats(void *log_ctx, int level, const AVFilterLink *l)
{
+ if (av_log_get_level() < level)
+ return;
+
AVBPrint bp;
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
- switch (type) {
- case AVMEDIA_TYPE_VIDEO:
- for (unsigned i = 0; i < formats->nb_formats; i++)
- av_bprintf(&bp, "%s%s", bp.len ? " " : "",
av_get_pix_fmt_name(formats->formats[i]));
- break;
- case AVMEDIA_TYPE_AUDIO:
- for (unsigned i = 0; i < formats->nb_formats; i++)
- av_bprintf(&bp, "%s%s", bp.len ? " " : "",
av_get_sample_fmt_name(formats->formats[i]));
- break;
- default:
- av_bprintf(&bp, "(unknown)");
- break;
+ av_log(log_ctx, level, "Link '%s.%s' -> '%s.%s':\n",
+ l->src->name, l->srcpad->name, l->dst->name, l->dstpad->name);
+
+ const AVFilterNegotiation *neg = ff_filter_get_negotiation(l);
+ for (unsigned i = 0; i < neg->nb_mergers; i++) {
+ const AVFilterFormatsMerger *m = &neg->mergers[i];
+ av_log(log_ctx, level, " %s:\n", m->name);
+ m->print_list(&bp, FF_FIELD_AT(void *, m->offset, l->incfg));
+ if (av_bprint_is_complete(&bp))
+ av_log(log_ctx, level, " src: %s\n", bp.str);
+ av_bprint_clear(&bp);
+
+ m->print_list(&bp, FF_FIELD_AT(void *, m->offset, l->outcfg));
+ if (av_bprint_is_complete(&bp))
+ av_log(log_ctx, level, " dst: %s\n", bp.str);
+ av_bprint_clear(&bp);
}
- if (av_bprint_is_complete(&bp)) {
- av_log(log_ctx, level, "%s\n", bp.str);
- } else {
- av_log(log_ctx, level, "(out of memory)\n");
- }
av_bprint_finalize(&bp, NULL);
}
-static void print_link_formats(void *log_ctx, int level, const AVFilterLink *l)
-{
- if (av_log_get_level() < level)
- return;
-
- av_log(log_ctx, level, "Link '%s.%s' -> '%s.%s':\n"
- " src: ", l->src->name, l->srcpad->name,
l->dst->name, l->dstpad->name);
- print_formats(log_ctx, level, l->type, l->incfg.formats);
- av_log(log_ctx, level, " dst: ");
- print_formats(log_ctx, level, l->type, l->outcfg.formats);
-}
-
static void print_filter_formats(void *log_ctx, int level, const
AVFilterContext *f)
{
if (av_log_get_level() < level)
return;
+ AVBPrint bp;
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+
av_log(log_ctx, level, "Filter '%s' formats:\n", f->name);
for (int i = 0; i < f->nb_inputs; i++) {
- av_log(log_ctx, level, " in[%d] '%s': ", i, f->input_pads[i].name);
- print_formats(log_ctx, level, f->inputs[i]->type,
f->inputs[i]->outcfg.formats);
+ const AVFilterLink *in = f->inputs[i];
+ const AVFilterNegotiation *neg = ff_filter_get_negotiation(in);
+ av_log(log_ctx, level, " in[%d] '%s':", i, f->input_pads[i].name);
+
+ for (unsigned i = 0; i < neg->nb_mergers; i++) {
+ const AVFilterFormatsMerger *m = &neg->mergers[i];
+ m->print_list(&bp, FF_FIELD_AT(void *, m->offset, in->outcfg));
+ if (av_bprint_is_complete(&bp))
+ av_log(log_ctx, level, " %s: %s", m->name, bp.str);
+ av_bprint_clear(&bp);
+ }
}
+
for (int i = 0; i < f->nb_outputs; i++) {
- av_log(log_ctx, level, " out[%d] '%s': ", i, f->output_pads[i].name);
- print_formats(log_ctx, level, f->outputs[i]->type,
f->outputs[i]->incfg.formats);
+ const AVFilterLink *out = f->outputs[i];
+ const AVFilterNegotiation *neg = ff_filter_get_negotiation(out);
+ av_log(log_ctx, level, " out[%d] '%s':", i, f->output_pads[i].name);
+
+ for (unsigned i = 0; i < neg->nb_mergers; i++) {
+ const AVFilterFormatsMerger *m = &neg->mergers[i];
+ m->print_list(&bp, FF_FIELD_AT(void *, m->offset, out->incfg));
+ if (av_bprint_is_complete(&bp))
+ av_log(log_ctx, level, " %s: %s", m->name, bp.str);
+ av_bprint_clear(&bp);
+ }
}
+
+ av_bprint_finalize(&bp, NULL);
}
/**
commit ad5b151f88aed49b4c36e764186214c13e0788ac
Author: Niklas Haas <[email protected]>
AuthorDate: Thu Nov 6 17:58:10 2025 +0100
Commit: Niklas Haas <[email protected]>
CommitDate: Thu Nov 6 18:01:33 2025 +0100
avfilter/formats: add name field to AVFilterFormatMerger
Needed to properly print format lists on format configuration failure.
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index 36e45c53c1..5ba961f059 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -389,6 +389,7 @@ static void print_sample_rate(AVBPrint *bp, const void
*ratesp)
static const AVFilterFormatsMerger mergers_video[] = {
{
+ .name = "Pixel formats",
.offset = offsetof(AVFilterFormatsConfig, formats),
.merge = merge_pix_fmts,
.can_merge = can_merge_pix_fmts,
@@ -396,6 +397,7 @@ static const AVFilterFormatsMerger mergers_video[] = {
CONVERSION_FILTER_SWSCALE
},
{
+ .name = "Color spaces",
.offset = offsetof(AVFilterFormatsConfig, color_spaces),
.merge = merge_generic,
.can_merge = can_merge_generic,
@@ -403,6 +405,7 @@ static const AVFilterFormatsMerger mergers_video[] = {
CONVERSION_FILTER_SWSCALE
},
{
+ .name = "Color ranges",
.offset = offsetof(AVFilterFormatsConfig, color_ranges),
.merge = merge_generic,
.can_merge = can_merge_generic,
@@ -410,6 +413,7 @@ static const AVFilterFormatsMerger mergers_video[] = {
CONVERSION_FILTER_SWSCALE
},
{
+ .name = "Alpha modes",
.offset = offsetof(AVFilterFormatsConfig, alpha_modes),
.merge = merge_generic,
.can_merge = can_merge_generic,
@@ -420,6 +424,7 @@ static const AVFilterFormatsMerger mergers_video[] = {
static const AVFilterFormatsMerger mergers_audio[] = {
{
+ .name = "Channel layouts",
.offset = offsetof(AVFilterFormatsConfig, channel_layouts),
.merge = merge_channel_layouts,
.can_merge = can_merge_channel_layouts,
@@ -427,6 +432,7 @@ static const AVFilterFormatsMerger mergers_audio[] = {
CONVERSION_FILTER_ARESAMPLE
},
{
+ .name = "Sample rates",
.offset = offsetof(AVFilterFormatsConfig, samplerates),
.merge = merge_samplerates,
.can_merge = can_merge_samplerates,
@@ -434,6 +440,7 @@ static const AVFilterFormatsMerger mergers_audio[] = {
CONVERSION_FILTER_ARESAMPLE
},
{
+ .name = "Sample formats",
.offset = offsetof(AVFilterFormatsConfig, formats),
.merge = merge_sample_fmts,
.can_merge = can_merge_sample_fmts,
diff --git a/libavfilter/formats.h b/libavfilter/formats.h
index 4fe96187ba..969bb230f1 100644
--- a/libavfilter/formats.h
+++ b/libavfilter/formats.h
@@ -516,6 +516,7 @@ int ff_formats_check_alpha_modes(void *log, const
AVFilterFormats *fmts);
struct AVBPrint;
typedef struct AVFilterFormatMerger {
+ const char *name;
unsigned offset;
int (*merge)(void *a, void *b);
int (*can_merge)(const void *a, const void *b);
commit f5bc9704edb3254e65c108509052f19eb77622c1
Author: Niklas Haas <[email protected]>
AuthorDate: Thu Nov 6 17:48:32 2025 +0100
Commit: Niklas Haas <[email protected]>
CommitDate: Thu Nov 6 17:48:50 2025 +0100
avfilter/formats: constify ff_filter_get_negotiation
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index b9487fe0cf..36e45c53c1 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -452,7 +452,7 @@ static const AVFilterNegotiation negotiate_audio = {
.mergers = mergers_audio,
};
-const AVFilterNegotiation *ff_filter_get_negotiation(AVFilterLink *link)
+const AVFilterNegotiation *ff_filter_get_negotiation(const AVFilterLink *link)
{
switch (link->type) {
case AVMEDIA_TYPE_VIDEO: return &negotiate_video;
diff --git a/libavfilter/formats.h b/libavfilter/formats.h
index d0b2a0b96a..4fe96187ba 100644
--- a/libavfilter/formats.h
+++ b/libavfilter/formats.h
@@ -614,6 +614,6 @@ typedef struct AVFilterNegotiation {
const AVFilterFormatsMerger *mergers;
} AVFilterNegotiation;
-const AVFilterNegotiation *ff_filter_get_negotiation(AVFilterLink *link);
+const AVFilterNegotiation *ff_filter_get_negotiation(const AVFilterLink *link);
#endif /* AVFILTER_FORMATS_H */
commit c1717cb6669f986a8bd04c8bfc5e37927c12769d
Author: Niklas Haas <[email protected]>
AuthorDate: Thu Nov 6 17:26:19 2025 +0100
Commit: Niklas Haas <[email protected]>
CommitDate: Thu Nov 6 17:34:43 2025 +0100
avfilter/format: add print_list() to AVFilterFormatsMerger
So that the generic code can correctly print format lists for failing
mergers.
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index 847199dda1..b9487fe0cf 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -20,6 +20,7 @@
*/
#include "libavutil/avassert.h"
+#include "libavutil/bprint.h"
#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/mem.h"
@@ -345,6 +346,39 @@ static int merge_generic(void *a, void *b)
return merge_generic_internal(a, b, 0);
}
+#define PRINT_NAME(type, type_name)
\
+static void print_##type_name(AVBPrint *bp, const void *fmtsp)
\
+{
\
+ const AVFilterFormats *fmts = fmtsp;
\
+ for (int i = 0; i < fmts->nb_formats; i++) {
\
+ const char *name = av_##type_name(fmts->formats[i]);
\
+ av_bprint_chars(bp, ' ', i ? 1 : 0);
\
+ av_bprint_append_data(bp, name, name ? strlen(name) : 0);
\
+ }
\
+}
+
+PRINT_NAME(enum AVSampleFormat, get_sample_fmt_name)
+PRINT_NAME(enum AVPixelFormat, get_pix_fmt_name)
+PRINT_NAME(enum AVColorSpace, color_space_name)
+PRINT_NAME(enum AVColorRange, color_range_name)
+PRINT_NAME(enum AVAlphaMode, alpha_mode_name)
+
+static void print_channel_layout_desc(AVBPrint *bp, const void *layoutsp)
+{
+ const AVFilterChannelLayouts *layouts = layoutsp;
+ for (int i = 0; i < layouts->nb_channel_layouts; i++) {
+ av_bprint_chars(bp, ' ', i ? 1 : 0);
+ av_channel_layout_describe_bprint(&layouts->channel_layouts[i], bp);
+ }
+}
+
+static void print_sample_rate(AVBPrint *bp, const void *ratesp)
+{
+ const AVFilterFormats *rates = ratesp;
+ for (int i = 0; i < rates->nb_formats; i++)
+ av_bprintf(bp, "%s%d", i ? " " : "", rates->formats[i]);
+}
+
#define CONVERSION_FILTER_SWSCALE \
.conversion_filter = "scale", \
.conversion_opts_offset = offsetof(AVFilterGraph, scale_sws_opts),
@@ -358,24 +392,28 @@ static const AVFilterFormatsMerger mergers_video[] = {
.offset = offsetof(AVFilterFormatsConfig, formats),
.merge = merge_pix_fmts,
.can_merge = can_merge_pix_fmts,
+ .print_list = print_get_pix_fmt_name,
CONVERSION_FILTER_SWSCALE
},
{
.offset = offsetof(AVFilterFormatsConfig, color_spaces),
.merge = merge_generic,
.can_merge = can_merge_generic,
+ .print_list = print_color_space_name,
CONVERSION_FILTER_SWSCALE
},
{
.offset = offsetof(AVFilterFormatsConfig, color_ranges),
.merge = merge_generic,
.can_merge = can_merge_generic,
+ .print_list = print_color_range_name,
CONVERSION_FILTER_SWSCALE
},
{
.offset = offsetof(AVFilterFormatsConfig, alpha_modes),
.merge = merge_generic,
.can_merge = can_merge_generic,
+ .print_list = print_alpha_mode_name,
.conversion_filter = "premultiply_dynamic",
},
};
@@ -385,18 +423,21 @@ static const AVFilterFormatsMerger mergers_audio[] = {
.offset = offsetof(AVFilterFormatsConfig, channel_layouts),
.merge = merge_channel_layouts,
.can_merge = can_merge_channel_layouts,
+ .print_list = print_channel_layout_desc,
CONVERSION_FILTER_ARESAMPLE
},
{
.offset = offsetof(AVFilterFormatsConfig, samplerates),
.merge = merge_samplerates,
.can_merge = can_merge_samplerates,
+ .print_list = print_sample_rate,
CONVERSION_FILTER_ARESAMPLE
},
{
.offset = offsetof(AVFilterFormatsConfig, formats),
.merge = merge_sample_fmts,
.can_merge = can_merge_sample_fmts,
+ .print_list = print_get_sample_fmt_name,
CONVERSION_FILTER_ARESAMPLE
},
};
diff --git a/libavfilter/formats.h b/libavfilter/formats.h
index 0c92ecad3f..d0b2a0b96a 100644
--- a/libavfilter/formats.h
+++ b/libavfilter/formats.h
@@ -513,10 +513,13 @@ int ff_formats_check_color_ranges(void *log, const
AVFilterFormats *fmts);
*/
int ff_formats_check_alpha_modes(void *log, const AVFilterFormats *fmts);
+struct AVBPrint;
+
typedef struct AVFilterFormatMerger {
unsigned offset;
int (*merge)(void *a, void *b);
int (*can_merge)(const void *a, const void *b);
+ void (*print_list)(struct AVBPrint *bp, const void *fmts);
const char *conversion_filter;
unsigned conversion_opts_offset;
} AVFilterFormatsMerger;
-----------------------------------------------------------------------
Summary of changes:
libavfilter/avfiltergraph.c | 97 +++++++++++++---------
libavfilter/formats.c | 50 ++++++++++-
libavfilter/formats.h | 6 +-
libswscale/tests/swscale.c | 49 ++++++-----
tests/fate/libswscale.mak | 5 ++
.../fate/{ffmpeg-error-rate-fail => sws-unscaled} | 0
6 files changed, 146 insertions(+), 61 deletions(-)
copy tests/ref/fate/{ffmpeg-error-rate-fail => sws-unscaled} (100%)
hooks/post-receive
--
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]