Commit e9d2baffa4 for ffmpeg

commit e9d2baffa48b4d7e91d99d5a20c0b67dd4a25b3f
Author: Michael Niedermayer <michael@niedermayer.cc>
Date:   Sun Oct 4 03:34:47 2026 +0200

    avutil/hwcontext: let the hardware context type allocate transfer buffers

    A device may transfer faster to or from memory it allocated itself
    than ordinary memory.

    Assisted-by: Claude

diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index d5cf6dc012..297cc5dd85 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -405,6 +405,12 @@ int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref,
     return ctxi->hw_type->transfer_get_formats(&ctxi->p, dir, formats);
 }

+static void transfer_pool_free(void *opaque)
+{
+    AVBufferRef *device_ref = opaque;
+    av_buffer_unref(&device_ref);
+}
+
 static AVBufferRef *transfer_buffer_alloc(void *opaque, size_t size)
 {
     FFHWFramesContext *ctxi = opaque;
@@ -412,15 +418,25 @@ static AVBufferRef *transfer_buffer_alloc(void *opaque, size_t size)

     ff_mutex_lock(&ctxi->transfer_pool_lock);
     if (ctxi->transfer_pool_size != size) {
+        /* buffers of the hardware context type need the device to be freed */
+        AVBufferRef *device_ref = ctxi->hw_type->transfer_buffer_alloc ?
+                                  av_buffer_ref(ctxi->p.device_ref) : NULL;
+
         av_buffer_pool_uninit(&ctxi->transfer_pool);
-        ctxi->transfer_pool      = av_buffer_pool_init(size, NULL);
+        ctxi->transfer_pool      = device_ref ?
+            av_buffer_pool_init2(size, device_ref,
+                                 ctxi->hw_type->transfer_buffer_alloc,
+                                 transfer_pool_free) :
+            av_buffer_pool_init(size, NULL);
         ctxi->transfer_pool_size = ctxi->transfer_pool ? size : 0;
+        if (!ctxi->transfer_pool)
+            av_buffer_unref(&device_ref);
     }
     if (ctxi->transfer_pool)
         buf = av_buffer_pool_get(ctxi->transfer_pool);
     ff_mutex_unlock(&ctxi->transfer_pool_lock);

-    return buf;
+    return buf ? buf : av_buffer_alloc(size);
 }

 int av_hwframe_get_transfer_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame)
diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h
index 33e34b9d65..e100233e35 100644
--- a/libavutil/hwcontext_internal.h
+++ b/libavutil/hwcontext_internal.h
@@ -72,6 +72,14 @@ typedef struct HWContextType {
     void             (*frames_uninit)(AVHWFramesContext *ctx);

     int              (*frames_get_buffer)(AVHWFramesContext *ctx, AVFrame *frame);
+
+    /**
+     * Allocate a buffer of size bytes for av_hwframe_get_transfer_buffer(),
+     * av_buffer_alloc() is used if this is not set or returns NULL.
+     *
+     * @param device_ref the AVBufferRef of the AVHWDeviceContext
+     */
+    AVBufferRef     *(*transfer_buffer_alloc)(void *device_ref, size_t size);
     int              (*transfer_get_formats)(AVHWFramesContext *ctx,
                                              enum AVHWFrameTransferDirection dir,
                                              enum AVPixelFormat **formats);