This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

The following commit(s) were added to refs/heads/master by this push:
     new a9cbcc2bbb hwcontext_vulkan: support frames with negative linesizes
a9cbcc2bbb is described below

commit a9cbcc2bbb9f64256834af2a22e31dd465a81f9d
Author:     Lynne <[email protected]>
AuthorDate: Mon Sep 21 11:49:31 2026 +0900
Commit:     Lynne <[email protected]>
CommitDate: Mon Sep 21 12:20:41 2026 +0900

    hwcontext_vulkan: support frames with negative linesizes
    
    None of the transfer paths handled a bottom-up software frame. The
    staging buffer path stored the linesize in the unsigned row length, so
    the buffer size wrapped to several gigabytes per plane, and passed it as
    the byte width of av_image_copy_plane(), a negative length for memcpy.
    The host image copy path did the same with memoryRowLength, and host
    mapping rejected the frame, which only led to the staging buffer.
    
    Use the absolute linesize for the buffer row length and copy width, as
    av_image_copy_plane() walks a negative stride itself, and skip host
    copies and host mapping for such frames, as neither can address rows
    downwards from the plane pointer.
---
 libavutil/hwcontext_vulkan.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 2859ee17c3..736b44a05a 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -4686,7 +4686,7 @@ static int copy_buffer_data(AVHWFramesContext *hwfc, 
FFVkBuffer *vkbuf,
                                 region[i].bufferRowLength,
                                 swf->data[i],
                                 swf->linesize[i],
-                                swf->linesize[i],
+                                FFABS(swf->linesize[i]),
                                 region[i].imageExtent.height);
 
         err = ff_vk_flush_buffer(&p->vkctx, vkbuf, 0, VK_WHOLE_SIZE, 1);
@@ -4708,7 +4708,7 @@ static int copy_buffer_data(AVHWFramesContext *hwfc, 
FFVkBuffer *vkbuf,
                                 swf->linesize[i],
                                 vkbuf->mapped_mem + region[i].bufferOffset,
                                 region[i].bufferRowLength,
-                                swf->linesize[i],
+                                FFABS(swf->linesize[i]),
                                 region[i].imageExtent.height);
     }
 
@@ -4732,7 +4732,7 @@ static int get_plane_buf(AVHWFramesContext *hwfc, 
FFVkBuffer **dst,
 
         region[i] = (VkBufferImageCopy) {
             .bufferOffset = buf_offset,
-            .bufferRowLength = FFALIGN(swf->linesize[i],
+            .bufferRowLength = FFALIGN(FFABS(swf->linesize[i]),
                                        
p->props.properties.limits.optimalBufferCopyRowPitchAlignment),
             .bufferImageHeight = p_h,
             .imageSubresource.layerCount = 1,
@@ -4765,11 +4765,6 @@ static int host_map_frame(AVHWFramesContext *hwfc, 
FFVkBuffer **dst, int *nb_buf
     VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
                                             VK_BUFFER_USAGE_TRANSFER_DST_BIT;
 
-    /* We can't host map images with negative strides */
-    for (int i = 0; i < planes; i++)
-        if (swf->linesize[i] < 0)
-            return AVERROR(EINVAL);
-
     /* Count the number of buffers in the software frame */
     nb_src_bufs = 0;
     while (swf->buf[nb_src_bufs])
@@ -4970,6 +4965,14 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
         return AVERROR(EINVAL);
 
     int host_copy = hwctx->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
+    int host_map = p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY &&
+                   !p->avoid_host_import;
+
+    /* Host image copies and host mapping address rows upwards from the plane
+     * pointer, so a bottom-up frame goes through the staging buffer */
+    for (int i = 0; i < planes; i++)
+        if (swf->linesize[i] < 0)
+            host_copy = host_map = 0;
 
     /* Host layout transitions may only originate from a host-copyable layout 
*/
     if (!upload && host_copy) {
@@ -4998,7 +5001,7 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
         /* Buffer region for this plane */
         region[i] = (VkBufferImageCopy) {
             .bufferOffset = 0,
-            .bufferRowLength = swf->linesize[i],
+            .bufferRowLength = FFABS(swf->linesize[i]),
             .bufferImageHeight = p_h,
             .imageSubresource.layerCount = 1,
             .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
@@ -5007,7 +5010,7 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
     }
 
     /* Setup buffers first */
-    if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY && 
!p->avoid_host_import) {
+    if (host_map) {
         err = host_map_frame(hwfc, bufs, &nb_bufs, swf, region, upload);
         if (err >= 0)
             host_mapped = 1;

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to