1
0
mirror of https://git.ffmpeg.org/ffmpeg.git synced 2026-10-24 02:09:03 +03:00
Files
ffmpeg/libavfilter/pthread.c
Niklas Haas dab32dcc21 avutil/slicethread: add return value to slicethread callbacks
Several places in the code currently manually roll the return value
saving. This small signature change allows slicethread.c to collect
return values directly. Unlike the existing solutions which mostly
rely on collecting the return values in an array, we can just use an
atomic CAS to set the error iff no error has been set already.

We need a slight bit of extra complication to avoid breaking the ABI,
which requires keeping around the old names as deprecated aliases that
just set up the appropriate wrappers. However, fortunately, the way I
implemented the deprecated signatures allows callers to freely mix
avpriv_slicethread_execute() and avpriv_slicethread_execute2(), even
on contexts created with one or the other.

It's worth pointing out that this commit just changes the signatures,
but doesn't yet update the various to use the return value.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-08-14 10:41:40 +02:00

117 lines
3.0 KiB
C

/*
* 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
*/
/**
* @file
* Libavfilter multithreading support
*/
#include <stddef.h>
#include "libavutil/error.h"
#include "libavutil/macros.h"
#include "libavutil/mem.h"
#include "libavutil/slicethread.h"
#include "avfilter.h"
#include "avfilter_internal.h"
typedef struct ThreadContext {
AVFilterGraph *graph;
AVSliceThread *thread;
avfilter_action_func *func;
/* per-execute parameters */
AVFilterContext *ctx;
void *arg;
int *rets;
} ThreadContext;
static int worker_func(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads)
{
ThreadContext *c = priv;
int ret = c->func(c->ctx, c->arg, jobnr, nb_jobs);
if (c->rets)
c->rets[jobnr] = ret;
return 0;
}
static void slice_thread_uninit(ThreadContext *c)
{
avpriv_slicethread_free(&c->thread);
}
static int thread_execute(AVFilterContext *ctx, avfilter_action_func *func,
void *arg, int *ret, int nb_jobs)
{
ThreadContext *c = fffiltergraph(ctx->graph)->thread;
if (nb_jobs <= 0)
return 0;
c->ctx = ctx;
c->arg = arg;
c->func = func;
c->rets = ret;
avpriv_slicethread_execute2(c->thread, nb_jobs, 0);
return 0;
}
static int thread_init_internal(ThreadContext *c, int nb_threads)
{
nb_threads = avpriv_slicethread_create2(&c->thread, c, worker_func, NULL, nb_threads);
if (nb_threads <= 1)
avpriv_slicethread_free(&c->thread);
return FFMAX(nb_threads, 1);
}
int ff_graph_thread_init(FFFilterGraph *graphi)
{
AVFilterGraph *graph = &graphi->p;
int ret;
if (graph->nb_threads == 1) {
graph->thread_type = 0;
return 0;
}
graphi->thread = av_mallocz(sizeof(ThreadContext));
if (!graphi->thread)
return AVERROR(ENOMEM);
ret = thread_init_internal(graphi->thread, graph->nb_threads);
if (ret <= 1) {
av_freep(&graphi->thread);
graph->thread_type = 0;
graph->nb_threads = 1;
return (ret < 0) ? ret : 0;
}
graph->nb_threads = ret;
graphi->thread_execute = thread_execute;
return 0;
}
void ff_graph_thread_free(FFFilterGraph *graph)
{
if (graph->thread)
slice_thread_uninit(graph->thread);
av_freep(&graph->thread);
}