Commit 67d2f0820b for ffmpeg
commit 67d2f0820b060f23de6a96be1b00db492da3869c
Author: Marcos Ashton Iglesias <marcosashiglesias@gmail.com>
Date: Fri Oct 16 16:08:45 2026 +0100
avcodec/vulkan_decode: retry the AV1 profile query without filmGrainSupport
Drivers without it, like ANV, rejected every AV1 stream by default;
sequences with film grain still fail there unless it is exported.
diff --git a/libavcodec/vulkan_av1.c b/libavcodec/vulkan_av1.c
index 99bdac46e5..d02e892d66 100644
--- a/libavcodec/vulkan_av1.c
+++ b/libavcodec/vulkan_av1.c
@@ -271,6 +271,12 @@ static int vk_av1_start_frame(AVCodecContext *avctx,
STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_WIENER,
STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SGRPROJ };
+ if (apply_grain && dec->external_fg) {
+ av_log(avctx, AV_LOG_ERROR, "The decode session has no filmGrainSupport, "
+ "but this frame needs film grain\n");
+ return AVERROR(ENOTSUP);
+ }
+
/* Use the current frame_ids in ref[] to decide occupied frame_ids */
for (int i = 0; i < STD_VIDEO_AV1_NUM_REF_FRAMES; i++) {
const AV1VulkanDecodePicture* rp = s->ref[i].hwaccel_picture_private;
diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c
index f3c93492f7..55c34d92f9 100644
--- a/libavcodec/vulkan_decode.c
+++ b/libavcodec/vulkan_decode.c
@@ -24,6 +24,7 @@
#include "libavutil/avassert.h"
#include "libavutil/mem.h"
#include "libavutil/vulkan_loader.h"
+#include "av1dec.h"
#include "h264dec.h"
#define DECODER_IS_SDR(codec_id) \
@@ -781,7 +782,6 @@ static VkResult vulkan_setup_profile(AVCodecContext *avctx,
usage->pNext = av1_profile;
av1_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR;
av1_profile->stdProfile = cur_profile;
- av1_profile->filmGrainSupport = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN);
}
usage->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR;
@@ -895,8 +895,35 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_
else if (avctx->codec_id == AV_CODEC_ID_AV1)
dec_caps->pNext = &av1_caps;
+ if (avctx->codec_id == AV_CODEC_ID_AV1)
+ prof->av1_profile.filmGrainSupport =
+ !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN);
+
ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc, caps, dec_caps,
cur_profile);
+
+ /* ANV returns OPERATION_NOT_SUPPORTED when it lacks filmGrainSupport */
+ if (profile_unsupported(ret) && prof->av1_profile.filmGrainSupport) {
+ const AV1DecContext *s = avctx->priv_data;
+
+ av_log(avctx, AV_LOG_VERBOSE, "%s profile %s not supported, "
+ "attempting again without filmGrainSupport\n",
+ avcodec_get_name(avctx->codec_id),
+ profile_name(avctx->codec_id, cur_profile));
+ prof->av1_profile.filmGrainSupport = 0;
+ if (vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc, caps,
+ dec_caps, cur_profile) != VK_SUCCESS) {
+ prof->av1_profile.filmGrainSupport = 1;
+ } else if (s->raw_seq->film_grain_params_present) {
+ av_log(avctx, AV_LOG_ERROR, "The device does not support film "
+ "grain; set export_side_data to film_grain to export it as "
+ "side data instead\n");
+ return AVERROR(ENOTSUP);
+ } else {
+ ret = VK_SUCCESS;
+ }
+ }
+
if (profile_unsupported(ret) &&
avctx->hwaccel_flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH &&
avctx->profile != base_profile) {
@@ -1292,6 +1319,13 @@ int ff_vk_decode_init(AVCodecContext *avctx)
return AVERROR(EINVAL);
}
+ if (avctx->codec_id == AV_CODEC_ID_AV1) {
+ const VkVideoDecodeAV1ProfileInfoKHR *av1_profile =
+ ff_vk_find_struct(profile->pNext,
+ VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR);
+ dec->external_fg = !av1_profile->filmGrainSupport;
+ }
+
/* Create queue context */
vk_desc = get_codecdesc(avctx->codec_id);
ctx->qf = ff_vk_qf_find(s, vk_desc->queue_flags, vk_desc->decode_op);
diff --git a/libavcodec/vulkan_decode.h b/libavcodec/vulkan_decode.h
index eb334ea1ae..2f8a2b714c 100644
--- a/libavcodec/vulkan_decode.h
+++ b/libavcodec/vulkan_decode.h
@@ -56,7 +56,7 @@ typedef struct FFVulkanDecodeContext {
VkVideoSessionParametersKHR *session_params;
int dedicated_dpb; /* Oddity #1 - separate DPB images */
- int external_fg; /* Oddity #2 - hardware can't apply film grain */
+ int external_fg; /* Oddity #2 - the session can't apply film grain */
/* Workaround for NVIDIA drivers tested with CTS version 1.3.8 for AV1.
* The tests were incorrect as the OrderHints were offset by 1. */