PR #24958 opened by Kyle Swanson (kylophone)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24958
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24958.patch

Signed-off-by: Kyle Swanson <[email protected]>

# Summary of changes

This wraps AVFrame buffers instead of copying them. Gives a good throughput 
boost at higher libvmaf thread counts.

| Clip | 1 thread | 2 threads | 4 threads | 8 threads | 16 threads |
|---|---|---|---|---|---|
| 1080p 8-bit | 56.7 -> 57.0 (+0.5%) | 108.4 -> 110.6 (+2.0%) | 194.0 -> 199.6 
(+2.9%) | 302.5 -> 291.9 (-3.5%) | 309.6 -> 336.7 (+8.8%) |
| 1080p 10-bit | 54.5 -> 55.2 (+1.3%) | 103.8 -> 103.5 (-0.3%) | 176.9 -> 186.1 
(+5.2%) | 251.1 -> 278.7 (+11.0%) | 215.0 -> 298.7 (+39.0%) |
| 4K 8-bit | 15.0 -> 14.9 (-0.3%) | 28.9 -> 29.3 (+1.5%) | 52.5 -> 54.6 (+4.0%) 
| 77.7 -> 81.1 (+4.4%) | 85.1 -> 93.1 (+9.5%) |
| 4K 10-bit | 14.3 -> 14.3 (+0.0%) | 27.4 -> 27.8 (+1.5%) | 47.3 -> 50.0 
(+5.7%) | 63.2 -> 73.3 (+15.9%) | 52.0 -> 77.1 (+48.1%) |




>From b9cbed4b411ffc4f0231574579e2fa45294db651 Mon Sep 17 00:00:00 2001
From: Kyle Swanson <[email protected]>
Date: Thu, 8 Oct 2026 20:11:29 +0000
Subject: [PATCH] avfilter/vf_libvmaf: use vmaf_picture_wrap() if available

Signed-off-by: Kyle Swanson <[email protected]>
---
 configure                |  2 ++
 libavfilter/vf_libvmaf.c | 48 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 08ff6892fb..977e8b19cd 100755
--- a/configure
+++ b/configure
@@ -2488,6 +2488,7 @@ INTRINSICS_LIST="
 SYSTEM_FEATURES="
     dos_paths
     libc_msvcrt
+    libvmaf_picture_wrap
     MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS
     section_data_rel_ro
     threads
@@ -7355,6 +7356,7 @@ enabled libv4l2           && require_pkg_config libv4l2 
libv4l2 libv4l2.h v4l2_i
 enabled libvidstab        && require_pkg_config libvidstab "vidstab >= 0.98" 
vid.stab/libvidstab.h vsMotionDetectInit
 enabled libvmaf           && require_pkg_config libvmaf "libvmaf >= 2.0.0" 
libvmaf.h vmaf_init
 enabled libvmaf           && check_pkg_config libvmaf_cuda "libvmaf >= 2.0.0" 
libvmaf_cuda.h vmaf_cuda_state_init
+enabled libvmaf           && check_pkg_config libvmaf_picture_wrap "libvmaf >= 
2.0.0" libvmaf.h vmaf_picture_wrap
 enabled libvo_amrwbenc    && { check_pkg_config libvo_amrwbenc vo-amrwbenc 
vo-amrwbenc/enc_if.h E_IF_init ||
                                require libvo_amrwbenc vo-amrwbenc/enc_if.h 
E_IF_init -lvo-amrwbenc; }
 enabled libvorbis         && require_pkg_config libvorbis vorbis 
vorbis/codec.h vorbis_info_init &&
diff --git a/libavfilter/vf_libvmaf.c b/libavfilter/vf_libvmaf.c
index 3ab67d3dba..068e4fcbf1 100644
--- a/libavfilter/vf_libvmaf.c
+++ b/libavfilter/vf_libvmaf.c
@@ -24,6 +24,7 @@
  * Calculate the VMAF between two input videos.
  */
 
+#include "config.h"
 #include "config_components.h"
 
 #include <libvmaf.h>
@@ -105,6 +106,39 @@ static enum VmafPixelFormat pix_fmt_map(enum AVPixelFormat 
av_pix_fmt)
     }
 }
 
+#if HAVE_LIBVMAF_PICTURE_WRAP
+static int release_frame(VmafPicture *pic, void *cookie)
+{
+    AVFrame *frame = cookie;
+    av_frame_free(&frame);
+    return 0;
+}
+
+static int wrap_picture_data(AVFrame *src, VmafPicture *dst, unsigned bpc)
+{
+    AVFrame *ref = av_frame_clone(src);
+    if (!ref)
+        return AVERROR(ENOMEM);
+
+    VmafPictureWrapped cfg = {
+        .pix_fmt = pix_fmt_map(src->format),
+        .bpc = bpc,
+        .w = src->width,
+        .h = src->height,
+        .data = { src->data[0], src->data[1], src->data[2] },
+        .stride = { src->linesize[0], src->linesize[1], src->linesize[2] },
+        .cookie = ref,
+        .release_picture = release_frame,
+    };
+
+    if (vmaf_picture_wrap(dst, cfg)) {
+        av_frame_free(&ref);
+        return AVERROR(ENOMEM);
+    }
+
+    return 0;
+}
+#else
 static int copy_picture_data(AVFrame *src, VmafPicture *dst, unsigned bpc)
 {
     const int bytes_per_value = bpc > 8 ? 2 : 1;
@@ -125,6 +159,16 @@ static int copy_picture_data(AVFrame *src, VmafPicture 
*dst, unsigned bpc)
 
     return 0;
 }
+#endif
+
+static int get_picture(AVFrame *src, VmafPicture *dst, unsigned bpc)
+{
+#if HAVE_LIBVMAF_PICTURE_WRAP
+    return wrap_picture_data(src, dst, bpc);
+#else
+    return copy_picture_data(src, dst, bpc);
+#endif
+}
 
 static int do_vmaf(FFFrameSync *fs)
 {
@@ -147,13 +191,13 @@ static int do_vmaf(FFFrameSync *fs)
                av_color_range_name(ref->color_range));
     }
 
-    err = copy_picture_data(ref, &pic_ref, s->bpc);
+    err = get_picture(ref, &pic_ref, s->bpc);
     if (err) {
         av_log(ctx, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n");
         return AVERROR(ENOMEM);
     }
 
-    err = copy_picture_data(dist, &pic_dist, s->bpc);
+    err = get_picture(dist, &pic_dist, s->bpc);
     if (err) {
         av_log(ctx, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n");
         vmaf_picture_unref(&pic_ref);
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to