Commit b8249f73a7 for ffmpeg
commit b8249f73a7c74c28d84c080978ac264ec3eb70b0
Author: Michael Niedermayer <michael@niedermayer.cc>
Date: Sun Oct 4 03:34:44 2026 +0200
avutil/hwcontext: add av_hwframe_get_transfer_buffer()
It allocates the buffers of a software frame used for a transfer to or
from a hardware frames context out of a pool kept by that context.
Assisted-by: Claude
diff --git a/doc/APIchanges b/doc/APIchanges
index 42d539990f..323b88af8f 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2026-06-23.
API changes, most recent first:
+2026-10-xx - xxxxxxxxxx - lavu 61.16.100 - hwcontext.h
+ Add av_hwframe_get_transfer_buffer().
+
2026-10-xx - xxxxxxxxxx - lavu 61.15.100 - encryption_info.h
Add av_encryption_init_info_append_side_data().
diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index c9e7d99f1d..2c3bd2eeaa 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -21,6 +21,7 @@
#include "avassert.h"
#include "buffer.h"
#include "common.h"
+#include "frame_internal.h"
#include "hwcontext.h"
#include "hwcontext_internal.h"
#include "imgutils.h"
@@ -246,6 +247,9 @@ static void hwframe_ctx_free(void *opaque, uint8_t *data)
if (ctxi->pool_internal)
av_buffer_pool_uninit(&ctxi->pool_internal);
+ av_buffer_pool_uninit(&ctxi->transfer_pool);
+ ff_mutex_destroy(&ctxi->transfer_pool_lock);
+
if (ctxi->hw_type->frames_uninit)
ctxi->hw_type->frames_uninit(ctx);
@@ -273,6 +277,11 @@ AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
return NULL;
ctx = &ctxi->p;
+ if (ff_mutex_init(&ctxi->transfer_pool_lock, NULL)) {
+ av_free(ctxi);
+ return NULL;
+ }
+
if (hw_type->frames_hwctx_size) {
ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size);
if (!ctx->hwctx)
@@ -301,6 +310,7 @@ AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
fail:
av_buffer_unref(&device_ref);
+ ff_mutex_destroy(&ctxi->transfer_pool_lock);
av_freep(&ctx->hwctx);
av_freep(&ctx);
return NULL;
@@ -395,6 +405,30 @@ int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref,
return ctxi->hw_type->transfer_get_formats(&ctxi->p, dir, formats);
}
+static AVBufferRef *transfer_buffer_alloc(void *opaque, size_t size)
+{
+ FFHWFramesContext *ctxi = opaque;
+ AVBufferRef *buf = NULL;
+
+ ff_mutex_lock(&ctxi->transfer_pool_lock);
+ if (ctxi->transfer_pool_size != size) {
+ av_buffer_pool_uninit(&ctxi->transfer_pool);
+ ctxi->transfer_pool = av_buffer_pool_init(size, NULL);
+ ctxi->transfer_pool_size = ctxi->transfer_pool ? size : 0;
+ }
+ if (ctxi->transfer_pool)
+ buf = av_buffer_pool_get(ctxi->transfer_pool);
+ ff_mutex_unlock(&ctxi->transfer_pool_lock);
+
+ return buf;
+}
+
+int av_hwframe_get_transfer_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame)
+{
+ return ff_frame_get_video_buffer(frame, 0, transfer_buffer_alloc,
+ hwframe_ctx->data);
+}
+
static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags)
{
AVHWFramesContext *ctx;
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index 29374cf0a7..5a73f368a1 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -372,6 +372,21 @@ int av_hwframe_ctx_init(AVBufferRef *ref);
*/
int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags);
+/**
+ * Allocate the buffers of a software frame that data is transferred to or
+ * from frames of the given AVHWFramesContext.
+ *
+ * Frames allocated otherwise can be transferred as well, as described for
+ * av_hwframe_transfer_data(). The buffers allocated here are pooled, and may be
+ * in memory that the device transfers faster.
+ *
+ * @param hwframe_ctx a reference to an AVHWFramesContext
+ * @param frame a video frame with format, width and height set and no
+ * data buffers
+ * @return 0 on success, a negative AVERROR code on failure
+ */
+int av_hwframe_get_transfer_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame);
+
/**
* Copy data to or from a hw surface. At least one of dst/src must have an
* AVHWFramesContext attached.
diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h
index dcfdc2016a..33e34b9d65 100644
--- a/libavutil/hwcontext_internal.h
+++ b/libavutil/hwcontext_internal.h
@@ -23,6 +23,7 @@
#include "buffer.h"
#include "hwcontext.h"
+#include "thread.h"
#include "frame.h"
#include "pixfmt.h"
@@ -100,6 +101,14 @@ typedef struct FFHWFramesContext {
AVBufferPool *pool_internal;
+ /**
+ * Buffers of transfer_pool_size bytes for av_hwframe_get_transfer_buffer(),
+ * both guarded by transfer_pool_lock.
+ */
+ AVBufferPool *transfer_pool;
+ size_t transfer_pool_size;
+ AVMutex transfer_pool_lock;
+
/**
* For a derived context, a reference to the original frames
* context it was derived from.
diff --git a/libavutil/version.h b/libavutil/version.h
index 9f1429987a..812815937b 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 61
-#define LIBAVUTIL_VERSION_MINOR 15
+#define LIBAVUTIL_VERSION_MINOR 16
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \