swscale: add FFFramePool and use it for allocating planes

The major consequence of this is that we start allocating buffers per plane,
instead of allocating one contiguous buffer. This makes the no-op/refcopy
case slightly slower, but doesn't meaningfully affect the rest:

yuva444p -> yuva444p, time=157/1000 us (ref=78/1000 us), speedup=0.497x slower
Overall speedup=1.016x faster, min=0.983x max=1.092x

However, this is a necessary consequence of the desire to allow partial plane
allocations / single plane refcopies. This slowdown also does not affect
vf_scale, which already uses avfilter/framepool.c (via ff_get_video_buffer).

Signed-off-by: Niklas Haas <git@haasn.dev>
This commit is contained in:
Niklas Haas
2026-04-10 15:12:18 +02:00
parent fe2691b3bb
commit 6c89a30ecd
5 changed files with 49 additions and 1 deletions
+1
View File
@@ -12,6 +12,7 @@ OBJS = alphablend.o \
hscale_fast_bilinear.o \
filters.o \
format.o \
framepool.o \
gamma.o \
graph.o \
input.o \
+19
View File
@@ -0,0 +1,19 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavfilter/framepool.c"
+25 -1
View File
@@ -1215,6 +1215,24 @@ void sws_frame_end(SwsContext *sws)
c->src_ranges.nb_ranges = 0;
}
static int frame_alloc_buffers(SwsContext *sws, AVFrame *frame)
{
SwsInternal *c = sws_internal(sws);
FFFramePool *pool = &c->frame_pool;
av_assert0(!frame->hw_frames_ctx);
const int nb_planes = av_pix_fmt_count_planes(frame->format);
for (int i = 0; i < nb_planes; i++) {
frame->linesize[i] = pool->linesize[i];
frame->buf[i] = av_buffer_pool_get(pool->pools[i]);
if (!frame->buf[i])
return AVERROR(ENOMEM);
frame->data[i] = frame->buf[i]->data;
}
return 0;
}
int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src)
{
SwsInternal *c = sws_internal(sws);
@@ -1390,7 +1408,7 @@ int sws_scale_frame(SwsContext *sws, AVFrame *dst, const AVFrame *src)
if (src->buf[0] && top->noop && (!bot || bot->noop))
return frame_ref(dst, src);
ret = av_frame_get_buffer(dst, 0);
ret = frame_alloc_buffers(sws, dst);
if (ret < 0)
return ret;
@@ -1457,6 +1475,12 @@ int sws_frame_setup(SwsContext *ctx, const AVFrame *dst, const AVFrame *src)
if (ret < 0)
return ret;
#endif
} else {
/* Software frames */
ret = ff_frame_pool_video_reinit(&s->frame_pool, dst->width, dst->height,
dst->format, av_cpu_max_align());
if (ret < 0)
return ret;
}
for (int field = 0; field < 2; field++) {
+3
View File
@@ -28,6 +28,7 @@
#include "swscale.h"
#include "graph.h"
#include "libavfilter/framepool.h"
#include "libavutil/avassert.h"
#include "libavutil/common.h"
#include "libavutil/frame.h"
@@ -699,6 +700,8 @@ struct SwsInternal {
void *hw_priv; /* refstruct */
int is_legacy_init;
FFFramePool frame_pool; /* for sws_scale_frame() data allocations */
};
//FIXME check init (where 0)
+1
View File
@@ -2293,6 +2293,7 @@ void sws_freeContext(SwsContext *sws)
for (i = 0; i < FF_ARRAY_ELEMS(c->graph); i++)
ff_sws_graph_free(&c->graph[i]);
ff_frame_pool_uninit(&c->frame_pool);
for (i = 0; i < c->nb_slice_ctx; i++)
sws_freeContext(c->slice_ctx[i]);