diff --git a/libavcodec/vulkan_av1.c b/libavcodec/vulkan_av1.c index fcc9a4f03b..49cd69d051 100644 --- a/libavcodec/vulkan_av1.c +++ b/libavcodec/vulkan_av1.c @@ -97,9 +97,14 @@ static int vk_av1_fill_pict(AVCodecContext *avctx, const AV1Frame **ref_src, .RefFrameSignBias = hp->ref_frame_sign_bias_mask, }; - if (saved_order_hints) - for (int i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) - vkav1_std_ref->SavedOrderHints[i] = saved_order_hints[i]; + if (saved_order_hints) { + if (dec->quirk_av1_offset) + for (int i = 1; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++) + vkav1_std_ref->SavedOrderHints[i - 1] = saved_order_hints[i]; + else + for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++) + vkav1_std_ref->SavedOrderHints[i] = saved_order_hints[i]; + } *vkav1_ref = (VkVideoDecodeAV1DpbSlotInfoKHR) { .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_DPB_SLOT_INFO_KHR, @@ -490,8 +495,14 @@ static int vk_av1_start_frame(AVCodecContext *avctx, } } + if (dec->quirk_av1_offset) + for (int i = 1; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++) + ap->std_pic_info.OrderHints[i - 1] = pic->order_hints[i]; + else + for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++) + ap->std_pic_info.OrderHints[i] = pic->order_hints[i]; + for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++) { - ap->std_pic_info.OrderHints[i] = pic->order_hints[i]; ap->loop_filter.loop_filter_ref_deltas[i] = frame_header->loop_filter_ref_deltas[i]; ap->global_motion.GmType[i] = s->cur_frame.gm_type[i]; for (int j = 0; j < STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS; j++) { diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index 9c6c2d4efb..d8c75cd0e6 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -1115,6 +1115,7 @@ int ff_vk_decode_init(AVCodecContext *avctx) FFVulkanFunctions *vk; const VkVideoProfileInfoKHR *profile; const FFVulkanDecodeDescriptor *vk_desc; + const VkPhysicalDeviceDriverProperties *driver_props; VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = { .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR, @@ -1276,6 +1277,14 @@ int ff_vk_decode_init(AVCodecContext *avctx) return AVERROR_EXTERNAL; } + driver_props = &dec->shared_ctx->s.driver_props; + if (driver_props->driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY && + driver_props->conformanceVersion.major == 1 && + driver_props->conformanceVersion.minor == 3 && + driver_props->conformanceVersion.subminor == 8 && + driver_props->conformanceVersion.patch < 3) + dec->quirk_av1_offset = 1; + ff_vk_decode_flush(avctx); av_log(avctx, AV_LOG_VERBOSE, "Vulkan decoder initialization sucessful\n"); diff --git a/libavcodec/vulkan_decode.h b/libavcodec/vulkan_decode.h index 7ba8b239cb..076af93499 100644 --- a/libavcodec/vulkan_decode.h +++ b/libavcodec/vulkan_decode.h @@ -72,6 +72,10 @@ typedef struct FFVulkanDecodeContext { int external_fg; /* Oddity #2 - hardware can't apply film grain */ uint32_t frame_id_alloc_mask; /* For AV1 only */ + /* Workaround for NVIDIA drivers tested with CTS version 1.3.8 for AV1. + * The tests were incorrect as the OrderHints were offset by 1. */ + int quirk_av1_offset; + /* Thread-local state below */ struct HEVCHeaderSet *hevc_headers; size_t hevc_headers_size;