PR #23364 opened by DmitriiGershenkop URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23364 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23364.patch
This PR introduces hardware frame mapping via AMF API, allowing using frames stored in the GPU memory as if it is stored in the system memory. >From ee1c1cb148c5724ccd3ece84d7f6dd1450a15f5f Mon Sep 17 00:00:00 2001 From: Dmitrii Gershenkop <[email protected]> Date: Fri, 5 Jun 2026 13:24:56 +0200 Subject: [PATCH] avutil/hwcontext_amf: Implement AMF hardware memory mapping support. --- Changelog | 1 + libavutil/hwcontext_amf.c | 63 +++++++++++++++++++++++++++++++++++++++ libavutil/version.h | 2 +- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 3c48005026..2ad3ee255f 100644 --- a/Changelog +++ b/Changelog @@ -17,6 +17,7 @@ version <next>: - Remove CELT decoding support (doesn't affect Opus CELT) - Remove ogg/celt parsing - Bitstream filter to split Dolby Vision multi-layer HEVC +- Add AMF hardware memory mapping support. version 8.1: diff --git a/libavutil/hwcontext_amf.c b/libavutil/hwcontext_amf.c index 754b1c60a2..04ea3ef023 100644 --- a/libavutil/hwcontext_amf.c +++ b/libavutil/hwcontext_amf.c @@ -819,6 +819,68 @@ static int amf_device_derive(AVHWDeviceContext *device_ctx, } } +static void amf_unmap_frame(av_unused AVHWFramesContext *unused, HWMapDescriptor *hwmap) +{ + AMFSurface1 *surface1 = hwmap->priv; + AMF_IFACE_CALL(surface1, Unmap); + AMF_IFACE_CALL(surface1, Release); +} + +static int amf_map_frame(AVHWFramesContext *device_ctx, AVFrame *dst, const AVFrame *src, int flags) +{ + AMFSurface *surface = (AMFSurface *)src->data[0]; + AMFSurface1 *surface1 = NULL; + AVAMFDeviceContext *amf_ctx = device_ctx->hwctx; + size_t linesizes[AMF_SURFACE_MAX_PLANES] = {}; + uint8_t *map[AMF_SURFACE_MAX_PLANES] = {}; + int amf_mem_flags = AMF_MEMORY_CPU_NONE; + const AMFGuid guid = IID_AMFSurface1(); + AMF_RESULT res = AMF_FAIL; + int plane_count = -1; + int ret = -1; + + AMF_RETURN_IF_FALSE(device_ctx, surface != NULL, AVERROR(EINVAL) , "Source surface is null"); + + res = AMF_IFACE_CALL(surface, QueryInterface, &guid, (void**)&surface1); + AMF_RETURN_IF_FALSE(device_ctx, res == AMF_OK, AVERROR_UNKNOWN, "QueryInterface(AMFSurface1) failed with error %d\n", res); + + if (flags & AV_HWFRAME_MAP_READ) + amf_mem_flags |= AMF_MEMORY_CPU_READ; + + if (flags & AV_HWFRAME_MAP_WRITE) + amf_mem_flags |= AMF_MEMORY_CPU_WRITE; + + plane_count = AMF_IFACE_CALL(surface, GetPlanesCount); + dst->format = av_amf_to_av_format(AMF_IFACE_CALL(surface, GetFormat)); + + res = AMF_IFACE_CALL(surface1, Map, amf_mem_flags, plane_count, linesizes, (void**)map); + AMF_GOTO_FAIL_IF_FALSE(device_ctx, res == AMF_OK, AVERROR_UNKNOWN, "AMFSurface1->Map() failed with error %d\n", res); + + ret = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, &amf_unmap_frame, surface1); + AMF_GOTO_FAIL_IF_FALSE(device_ctx, ret >= 0, ret, "ff_hwframe_map_create failed with error %d\n", ret); + + dst->width = src->width; + dst->height = src->height; + av_frame_copy_props(dst, src); + + // The dst frame is no longer a hardware frame, from the perspective of any dst frame consumer. + av_buffer_unref(&dst->hw_frames_ctx); + + for (int plane = 0; plane < plane_count; ++plane) + { + dst->data[plane] = map[plane]; + dst->linesize[plane] = linesizes[plane]; + } + + return 0; + +fail: + if (surface1 != NULL) + AMF_IFACE_CALL(surface1, Release); + + return ret; +} + const HWContextType ff_hwcontext_type_amf = { .type = AV_HWDEVICE_TYPE_AMF, .name = "AMF", @@ -836,6 +898,7 @@ const HWContextType ff_hwcontext_type_amf = { .transfer_get_formats = amf_transfer_get_formats, .transfer_data_to = amf_transfer_data_to, .transfer_data_from = amf_transfer_data_from, + .map_from = amf_map_frame, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_AMF_SURFACE, AV_PIX_FMT_NONE }, }; diff --git a/libavutil/version.h b/libavutil/version.h index e7aeab9995..4392f77220 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -80,7 +80,7 @@ #define LIBAVUTIL_VERSION_MAJOR 60 #define LIBAVUTIL_VERSION_MINOR 32 -#define LIBAVUTIL_VERSION_MICRO 100 +#define LIBAVUTIL_VERSION_MICRO 101 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
