aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.dev>2023-02-07 15:09:18 +0100
committerNiklas Haas <git@haasn.dev>2023-02-07 15:11:49 +0100
commit62dfa546886d55109f0ba0afb1c13e59157e524c (patch)
tree62c3d65dac4843306385a28f622b48e00ff43fc1
parent58d6426870ed10e5eeed98418dc3b7b2d4efe2c6 (diff)
downloadffmpeg-62dfa546886d55109f0ba0afb1c13e59157e524c.tar.gz
avfilter/vf_libplacebo: fix format query
We need to construct the output format list separatedly from the input format list, because we need to adhere to two extra requirements: 1. Big-endian output formats are always unsupported (runtime error) 2. Combining 'vulkan' with an explicit out_format that is not supported by the vulkan frame allocation code is illegal and will crash (abort) As a free side benefit, this rewrite fixes a possible memory leak in the `fail` path that was present in the old code. Signed-off-by: Niklas Haas <git@haasn.dev>
-rw-r--r--libavfilter/vf_libplacebo.c52
1 files changed, 35 insertions, 17 deletions
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 12abca4cc7..5b31077107 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -547,10 +547,10 @@ fail:
static int libplacebo_query_format(AVFilterContext *ctx)
{
- int err = 0;
+ int err;
LibplaceboContext *s = ctx->priv;
const AVPixFmtDescriptor *desc = NULL;
- AVFilterFormats *formats = NULL;
+ AVFilterFormats *infmts = NULL, *outfmts = NULL;
RET(init_vulkan(ctx));
@@ -564,29 +564,47 @@ static int libplacebo_query_format(AVFilterContext *ctx)
continue;
#endif
- if (pl_test_pixfmt(s->gpu, pixfmt)) {
- if ((err = ff_add_format(&formats, pixfmt)) < 0)
- return err;
+ if (!pl_test_pixfmt(s->gpu, pixfmt))
+ continue;
+
+ RET(ff_add_format(&infmts, pixfmt));
+
+ /* Filter for supported output pixel formats */
+ if (desc->flags & AV_PIX_FMT_FLAG_BE)
+ continue; /* BE formats are not supported by pl_download_avframe */
+
+ /* Mask based on user specified format */
+ if (s->out_format != AV_PIX_FMT_NONE) {
+ if (pixfmt == AV_PIX_FMT_VULKAN && av_vkfmt_from_pixfmt(s->out_format)) {
+ /* OK */
+ } else if (pixfmt == s->out_format) {
+ /* OK */
+ } else {
+ continue; /* Not OK */
+ }
}
- }
- RET(ff_formats_ref(formats, &ctx->inputs[0]->outcfg.formats));
+ RET(ff_add_format(&outfmts, pixfmt));
+ }
- if (s->out_format != AV_PIX_FMT_NONE) {
- /* Support only requested format, and hwaccel (vulkan) */
- const enum AVPixelFormat out_fmts[] = {
- s->out_format, AV_PIX_FMT_VULKAN, AV_PIX_FMT_NONE,
- };
- RET(ff_formats_ref(ff_make_format_list(out_fmts),
- &ctx->outputs[0]->incfg.formats));
- } else {
- /* Support all formats */
- RET(ff_formats_ref(formats, &ctx->outputs[0]->incfg.formats));
+ if (!infmts || !outfmts) {
+ if (s->out_format) {
+ av_log(s, AV_LOG_ERROR, "Invalid output format '%s'!\n",
+ av_get_pix_fmt_name(s->out_format));
+ }
+ err = AVERROR(EINVAL);
+ goto fail;
}
+ RET(ff_formats_ref(infmts, &ctx->inputs[0]->outcfg.formats));
+ RET(ff_formats_ref(outfmts, &ctx->outputs[0]->incfg.formats));
return 0;
fail:
+ if (infmts && !infmts->refcount)
+ ff_formats_unref(&infmts);
+ if (outfmts && !outfmts->refcount)
+ ff_formats_unref(&outfmts);
return err;
}