lavfi/vf_libplacebo: allow operation without avhwdevice

Recent versions of libplacebo have required Vulkan versions incompatible
with lavu Vulkan hwcontexts. While this is expected to change
eventually, breaking vf_libplacebo every time there is such a transition
period is obviously undesired behavior, as the following sea of bug
reports shows.

This commit adds a fallback path for init_vulkan failures which simply
creates an internal device if there was no user-supplied Vulkan hwaccel.
Useful when no interop with lavu vulkan hwframes is needed or desired,
and makes using this filter easier inside certain applications.

Fixes: https://github.com/haasn/libplacebo/issues/170
Fixes: https://github.com/mpv-player/mpv/issues/9589#issuecomment-1535432185
Fixes: https://github.com/mpv-player/mpv/issues/11363
Fixes: https://github.com/mpv-player/mpv/issues/11685#issuecomment-1546627082
Closes: https://code.videolan.org/videolan/libplacebo/-/issues/270
pull/389/head
Niklas Haas 2 years ago
parent e076d8a9b3
commit c65e481330
  1. 41
      libavfilter/vf_libplacebo.c

@ -351,29 +351,14 @@ fail:
return err; return err;
} }
static int init_vulkan(AVFilterContext *avctx) static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwctx)
{ {
int err = 0; int err = 0;
LibplaceboContext *s = avctx->priv; LibplaceboContext *s = avctx->priv;
const AVHWDeviceContext *avhwctx;
const AVVulkanDeviceContext *hwctx;
uint8_t *buf = NULL; uint8_t *buf = NULL;
size_t buf_len; size_t buf_len;
if (!avctx->hw_device_ctx) { if (hwctx) {
av_log(s, AV_LOG_ERROR, "Missing vulkan hwdevice for vf_libplacebo.\n");
return AVERROR(EINVAL);
}
avhwctx = (AVHWDeviceContext *) avctx->hw_device_ctx->data;
if (avhwctx->type != AV_HWDEVICE_TYPE_VULKAN) {
av_log(s, AV_LOG_ERROR, "Expected vulkan hwdevice for vf_libplacebo, got %s.\n",
av_hwdevice_get_type_name(avhwctx->type));
return AVERROR(EINVAL);
}
hwctx = avhwctx->hwctx;
/* Import libavfilter vulkan context into libplacebo */ /* Import libavfilter vulkan context into libplacebo */
s->vulkan = pl_vulkan_import(s->log, pl_vulkan_import_params( s->vulkan = pl_vulkan_import(s->log, pl_vulkan_import_params(
.instance = hwctx->inst, .instance = hwctx->inst,
@ -398,9 +383,15 @@ static int init_vulkan(AVFilterContext *avctx)
/* This is the highest version created by hwcontext_vulkan.c */ /* This is the highest version created by hwcontext_vulkan.c */
.max_api_version = VK_API_VERSION_1_2, .max_api_version = VK_API_VERSION_1_2,
)); ));
} else {
s->vulkan = pl_vulkan_create(s->log, pl_vulkan_params(
.queue_count = 0, /* enable all queues for parallelization */
));
}
if (!s->vulkan) { if (!s->vulkan) {
av_log(s, AV_LOG_ERROR, "Failed importing vulkan device to libplacebo!\n"); av_log(s, AV_LOG_ERROR, "Failed %s Vulkan device!\n",
hwctx ? "importing" : "creating");
err = AVERROR_EXTERNAL; err = AVERROR_EXTERNAL;
goto fail; goto fail;
} }
@ -695,10 +686,17 @@ static int libplacebo_query_format(AVFilterContext *ctx)
{ {
int err; int err;
LibplaceboContext *s = ctx->priv; LibplaceboContext *s = ctx->priv;
const AVVulkanDeviceContext *vkhwctx = NULL;
const AVPixFmtDescriptor *desc = NULL; const AVPixFmtDescriptor *desc = NULL;
AVFilterFormats *infmts = NULL, *outfmts = NULL; AVFilterFormats *infmts = NULL, *outfmts = NULL;
RET(init_vulkan(ctx)); if (ctx->hw_device_ctx) {
const AVHWDeviceContext *avhwctx = (void *) ctx->hw_device_ctx->data;
if (avhwctx->type == AV_HWDEVICE_TYPE_VULKAN)
vkhwctx = avhwctx->hwctx;
}
RET(init_vulkan(ctx, vkhwctx));
while ((desc = av_pix_fmt_desc_next(desc))) { while ((desc = av_pix_fmt_desc_next(desc))) {
enum AVPixelFormat pixfmt = av_pix_fmt_desc_get_id(desc); enum AVPixelFormat pixfmt = av_pix_fmt_desc_get_id(desc);
@ -710,6 +708,11 @@ static int libplacebo_query_format(AVFilterContext *ctx)
continue; continue;
#endif #endif
if (pixfmt == AV_PIX_FMT_VULKAN) {
if (!vkhwctx || vkhwctx->act_dev != s->vulkan->device)
continue;
}
if (!pl_test_pixfmt(s->gpu, pixfmt)) if (!pl_test_pixfmt(s->gpu, pixfmt))
continue; continue;

Loading…
Cancel
Save