Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH] vulkan_decode: do not reset session state when flushing decoder (PR #21183)
@ 2025-12-13  2:06 Lynne via ffmpeg-devel
  0 siblings, 0 replies; only message in thread
From: Lynne via ffmpeg-devel @ 2025-12-13  2:06 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Lynne

PR #21183 opened by Lynne
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21183
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21183.patch

The issue is that .flush gets called asynchronously, and modifies the video session state while its being used for decoding. This did not result in issues since all known implementation do not keep important state there, but its not compliant with the specs.
    
Its not necessary to flush the decoder when seeking, so simply don't.


>From c9299de723a42e2ec8b6fb53b898a79b68d7ffd7 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 13 Dec 2025 02:40:43 +0100
Subject: [PATCH 1/2] vulkan_decode: do not reset the decoder when flushing

The issue is that .flush gets called asynchronously, and modifies the
video session state while its being used for decoding. This did not
result in issues since all known vendors do not keep important state
there, but its not compliant with the specs.

Its not necessary to flush the decoder at all when seeking,
so simply don't.
---
 libavcodec/vulkan_av1.c        | 1 -
 libavcodec/vulkan_dpx.c        | 1 -
 libavcodec/vulkan_ffv1.c       | 1 -
 libavcodec/vulkan_h264.c       | 1 -
 libavcodec/vulkan_hevc.c       | 1 -
 libavcodec/vulkan_prores.c     | 1 -
 libavcodec/vulkan_prores_raw.c | 1 -
 libavcodec/vulkan_vp9.c        | 1 -
 8 files changed, 8 deletions(-)

diff --git a/libavcodec/vulkan_av1.c b/libavcodec/vulkan_av1.c
index 3a52d1f33a..3bee784a4f 100644
--- a/libavcodec/vulkan_av1.c
+++ b/libavcodec/vulkan_av1.c
@@ -662,7 +662,6 @@ const FFHWAccel ff_av1_vulkan_hwaccel = {
     .init                  = &ff_vk_decode_init,
     .update_thread_context = &ff_vk_update_thread_context,
     .decode_params         = &ff_vk_params_invalidate,
-    .flush                 = &ff_vk_decode_flush,
     .uninit                = &ff_vk_decode_uninit,
     .frame_params          = &ff_vk_frame_params,
     .priv_data_size        = sizeof(FFVulkanDecodeContext),
diff --git a/libavcodec/vulkan_dpx.c b/libavcodec/vulkan_dpx.c
index 16ac10c5b8..d0466891fa 100644
--- a/libavcodec/vulkan_dpx.c
+++ b/libavcodec/vulkan_dpx.c
@@ -466,7 +466,6 @@ const FFHWAccel ff_dpx_vulkan_hwaccel = {
     .init                  = &vk_decode_dpx_init,
     .update_thread_context = &ff_vk_update_thread_context,
     .decode_params         = &ff_vk_params_invalidate,
-    .flush                 = &ff_vk_decode_flush,
     .uninit                = &ff_vk_decode_uninit,
     .frame_params          = &ff_vk_frame_params,
     .priv_data_size        = sizeof(FFVulkanDecodeContext),
diff --git a/libavcodec/vulkan_ffv1.c b/libavcodec/vulkan_ffv1.c
index 7d1e0c9ba7..643da9c551 100644
--- a/libavcodec/vulkan_ffv1.c
+++ b/libavcodec/vulkan_ffv1.c
@@ -1147,7 +1147,6 @@ const FFHWAccel ff_ffv1_vulkan_hwaccel = {
     .init                  = &vk_decode_ffv1_init,
     .update_thread_context = &ff_vk_update_thread_context,
     .decode_params         = &ff_vk_params_invalidate,
-    .flush                 = &ff_vk_decode_flush,
     .uninit                = &ff_vk_decode_uninit,
     .frame_params          = &ff_vk_frame_params,
     .priv_data_size        = sizeof(FFVulkanDecodeContext),
diff --git a/libavcodec/vulkan_h264.c b/libavcodec/vulkan_h264.c
index 8293f7ece9..5fc0f4c4cf 100644
--- a/libavcodec/vulkan_h264.c
+++ b/libavcodec/vulkan_h264.c
@@ -584,7 +584,6 @@ const FFHWAccel ff_h264_vulkan_hwaccel = {
     .init                  = &ff_vk_decode_init,
     .update_thread_context = &ff_vk_update_thread_context,
     .decode_params         = &ff_vk_params_invalidate,
-    .flush                 = &ff_vk_decode_flush,
     .uninit                = &ff_vk_decode_uninit,
     .frame_params          = &ff_vk_frame_params,
     .priv_data_size        = sizeof(FFVulkanDecodeContext),
diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c
index f609c4301f..8f0d1f6636 100644
--- a/libavcodec/vulkan_hevc.c
+++ b/libavcodec/vulkan_hevc.c
@@ -949,7 +949,6 @@ const FFHWAccel ff_hevc_vulkan_hwaccel = {
     .init                  = &ff_vk_decode_init,
     .update_thread_context = &ff_vk_update_thread_context,
     .decode_params         = &ff_vk_params_invalidate,
-    .flush                 = &ff_vk_decode_flush,
     .uninit                = &ff_vk_decode_uninit,
     .frame_params          = &ff_vk_frame_params,
     .priv_data_size        = sizeof(FFVulkanDecodeContext),
diff --git a/libavcodec/vulkan_prores.c b/libavcodec/vulkan_prores.c
index 12e66876f2..e8c74b7863 100644
--- a/libavcodec/vulkan_prores.c
+++ b/libavcodec/vulkan_prores.c
@@ -567,7 +567,6 @@ const FFHWAccel ff_prores_vulkan_hwaccel = {
     .init                  = &vk_decode_prores_init,
     .update_thread_context = &ff_vk_update_thread_context,
     .decode_params         = &ff_vk_params_invalidate,
-    .flush                 = &ff_vk_decode_flush,
     .uninit                = &ff_vk_decode_uninit,
     .frame_params          = &ff_vk_frame_params,
     .priv_data_size        = sizeof(FFVulkanDecodeContext),
diff --git a/libavcodec/vulkan_prores_raw.c b/libavcodec/vulkan_prores_raw.c
index cd025d25e6..0c7a97fa60 100644
--- a/libavcodec/vulkan_prores_raw.c
+++ b/libavcodec/vulkan_prores_raw.c
@@ -474,7 +474,6 @@ const FFHWAccel ff_prores_raw_vulkan_hwaccel = {
     .init                  = &vk_decode_prores_raw_init,
     .update_thread_context = &ff_vk_update_thread_context,
     .decode_params         = &ff_vk_params_invalidate,
-    .flush                 = &ff_vk_decode_flush,
     .uninit                = &ff_vk_decode_uninit,
     .frame_params          = &ff_vk_frame_params,
     .priv_data_size        = sizeof(FFVulkanDecodeContext),
diff --git a/libavcodec/vulkan_vp9.c b/libavcodec/vulkan_vp9.c
index 6d0a5ce46f..5aeec3fb21 100644
--- a/libavcodec/vulkan_vp9.c
+++ b/libavcodec/vulkan_vp9.c
@@ -365,7 +365,6 @@ const FFHWAccel ff_vp9_vulkan_hwaccel = {
     .frame_priv_data_size  = sizeof(VP9VulkanDecodePicture),
     .init                  = &ff_vk_decode_init,
     .update_thread_context = &ff_vk_update_thread_context,
-    .flush                 = &ff_vk_decode_flush,
     .uninit                = &ff_vk_decode_uninit,
     .frame_params          = &ff_vk_frame_params,
     .priv_data_size        = sizeof(FFVulkanDecodeContext),
-- 
2.49.1


>From 9da2129a992551ff19d9fb1df1cb3532c56eb7c9 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 13 Dec 2025 02:53:23 +0100
Subject: [PATCH 2/2] vulkan_decode: clean up decoder initialization

Now that we don't reset on every seek, we can simplify it.
---
 libavcodec/vulkan_decode.c | 149 +++++++++++++++++++------------------
 libavcodec/vulkan_decode.h |   7 --
 2 files changed, 76 insertions(+), 80 deletions(-)

diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c
index 654149851d..b1e4b989ce 100644
--- a/libavcodec/vulkan_decode.c
+++ b/libavcodec/vulkan_decode.c
@@ -372,17 +372,66 @@ int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp,
     return 0;
 }
 
-void ff_vk_decode_flush(AVCodecContext *avctx)
+static int create_empty_session_parameters(AVCodecContext *avctx,
+                                           FFVulkanDecodeShared *ctx,
+                                           VkVideoSessionParametersKHR *empty_session_params)
 {
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    VkResult ret;
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
+    };
+    VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
+    };
+    StdVideoAV1SequenceHeader av1_empty_seq = { 0 };
+    VkVideoDecodeAV1SessionParametersCreateInfoKHR av1_params = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .pStdSequenceHeader = &av1_empty_seq,
+    };
+    VkVideoSessionParametersCreateInfoKHR session_params_create = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .pNext = avctx->codec_id == AV_CODEC_ID_H264 ? (void *)&h264_params :
+                 avctx->codec_id == AV_CODEC_ID_HEVC ? (void *)&h265_params :
+                 avctx->codec_id == AV_CODEC_ID_AV1  ? (void *)&av1_params  :
+                 NULL,
+        .videoSession = ctx->common.session,
+    };
+
+    if (avctx->codec_id == AV_CODEC_ID_VP9)
+        return 0;
+
+    ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
+                                              s->hwctx->alloc, empty_session_params);
+    if (ret != VK_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to create empty Vulkan video session parameters: %s!\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static int decode_reset(AVCodecContext *avctx, FFVulkanDecodeShared *ctx)
+{
+    int err;
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &s->vkfn;
 
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
     VkVideoBeginCodingInfoKHR decode_start = {
         .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
         .videoSession = ctx->common.session,
-        .videoSessionParameters = ctx->empty_session_params,
     };
+
+    if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) {
+        err = create_empty_session_parameters(avctx, ctx,
+                                              &decode_start.videoSessionParameters);
+        if (err < 0)
+            return err;
+    }
+
     VkVideoCodingControlInfoKHR decode_ctrl = {
         .sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
         .flags = VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
@@ -391,21 +440,25 @@ void ff_vk_decode_flush(AVCodecContext *avctx)
         .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
     };
 
-    VkCommandBuffer cmd_buf;
-    FFVkExecContext *exec;
-
-    /* Non-video queues do not need to be reset */
-    if (!(get_codecdesc(avctx->codec_id)->decode_op))
-        return;
-
-    exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
+    FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
     ff_vk_exec_start(&ctx->s, exec);
-    cmd_buf = exec->buf;
 
-    vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);
-    vk->CmdControlVideoCodingKHR(cmd_buf, &decode_ctrl);
-    vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);
-    ff_vk_exec_submit(&ctx->s, exec);
+    vk->CmdBeginVideoCodingKHR(exec->buf, &decode_start);
+    vk->CmdControlVideoCodingKHR(exec->buf, &decode_ctrl);
+    vk->CmdEndVideoCodingKHR(exec->buf, &decode_end);
+
+    err = ff_vk_exec_submit(&ctx->s, exec);
+
+    if (decode_start.videoSessionParameters) {
+        /* Wait to complete to delete the temporary session parameters */
+        if (err >= 0)
+            ff_vk_exec_wait(&ctx->s, exec);
+        vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
+                                             decode_start.videoSessionParameters,
+                                             s->hwctx->alloc);
+    }
+
+    return err;
 }
 
 int ff_vk_decode_frame(AVCodecContext *avctx,
@@ -651,7 +704,6 @@ static void free_common(AVRefStructOpaque unused, void *obj)
 {
     FFVulkanDecodeShared *ctx = obj;
     FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
 
     /* Wait on and free execution pool */
     ff_vk_exec_pool_free(&ctx->s, &ctx->exec_pool);
@@ -659,12 +711,6 @@ static void free_common(AVRefStructOpaque unused, void *obj)
     /* This also frees all references from this pool */
     av_frame_free(&ctx->common.layered_frame);
 
-    /* Destroy parameters */
-    if (ctx->empty_session_params)
-        vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
-                                             ctx->empty_session_params,
-                                             s->hwctx->alloc);
-
     av_buffer_pool_uninit(&ctx->buf_pool);
 
     ff_vk_video_common_uninit(s, &ctx->common);
@@ -1237,47 +1283,6 @@ int ff_vk_decode_uninit(AVCodecContext *avctx)
     return 0;
 }
 
-static int create_empty_session_parameters(AVCodecContext *avctx,
-                                           FFVulkanDecodeShared *ctx)
-{
-    VkResult ret;
-    FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
-    };
-    VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
-    };
-    StdVideoAV1SequenceHeader av1_empty_seq = { 0 };
-    VkVideoDecodeAV1SessionParametersCreateInfoKHR av1_params = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .pStdSequenceHeader = &av1_empty_seq,
-    };
-    VkVideoSessionParametersCreateInfoKHR session_params_create = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .pNext = avctx->codec_id == AV_CODEC_ID_H264 ? (void *)&h264_params :
-                 avctx->codec_id == AV_CODEC_ID_HEVC ? (void *)&h265_params :
-                 avctx->codec_id == AV_CODEC_ID_AV1  ? (void *)&av1_params  :
-                 NULL,
-        .videoSession = ctx->common.session,
-    };
-
-    if (avctx->codec_id == AV_CODEC_ID_VP9)
-        return 0;
-
-    ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
-                                              s->hwctx->alloc, &ctx->empty_session_params);
-    if (ret != VK_SUCCESS) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to create empty Vulkan video session parameters: %s!\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    return 0;
-}
-
 int ff_vk_decode_init(AVCodecContext *avctx)
 {
     int err;
@@ -1405,11 +1410,11 @@ int ff_vk_decode_init(AVCodecContext *avctx)
     }
 
     if (!DECODER_IS_SDR(avctx->codec_id)) {
-        if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) {
-            err = create_empty_session_parameters(avctx, ctx);
-            if (err < 0)
-                return err;
-        }
+        err = decode_reset(avctx, ctx);
+        if (err < 0)
+            return err;
+
+
     } else {
         /* For SDR decoders, this alignment value will be 0. Since this will make
          * add_slice() malfunction, set it to a sane default value. */
@@ -1424,8 +1429,6 @@ int ff_vk_decode_init(AVCodecContext *avctx)
         driver_props->conformanceVersion.patch < 3)
         dec->quirk_av1_offset = 1;
 
-    ff_vk_decode_flush(avctx);
-
     av_log(avctx, AV_LOG_VERBOSE, "Vulkan decoder initialization successful\n");
 
     return 0;
diff --git a/libavcodec/vulkan_decode.h b/libavcodec/vulkan_decode.h
index e32468f317..c75f0710db 100644
--- a/libavcodec/vulkan_decode.h
+++ b/libavcodec/vulkan_decode.h
@@ -46,8 +46,6 @@ typedef struct FFVulkanDecodeShared {
     VkVideoCapabilitiesKHR caps;
     VkVideoDecodeCapabilitiesKHR dec_caps;
 
-    VkVideoSessionParametersKHR empty_session_params;
-
     /* Software-defined decoder context */
     void *sd_ctx;
     void (*sd_ctx_free)(struct FFVulkanDecodeShared *ctx);
@@ -176,11 +174,6 @@ int ff_vk_get_decode_buffer(FFVulkanDecodeContext *ctx, AVBufferRef **buf,
 int ff_vk_decode_create_params(AVBufferRef **par_ref, void *logctx, FFVulkanDecodeShared *ctx,
                                const VkVideoSessionParametersCreateInfoKHR *session_params_create);
 
-/**
- * Flush decoder.
- */
-void ff_vk_decode_flush(AVCodecContext *avctx);
-
 /**
  * Free decoder.
  */
-- 
2.49.1

_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2025-12-13  2:07 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-13  2:06 [FFmpeg-devel] [PATCH] vulkan_decode: do not reset session state when flushing decoder (PR #21183) Lynne via ffmpeg-devel

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git