From 0767bfd1994c4bf22e167ffadb8f823a950aad18 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 8 Aug 2013 16:28:41 +0200 Subject: [PATCH] lavfi: allow user-provided execute() callbacks --- doc/APIchanges | 4 +++ libavfilter/avfilter.c | 2 +- libavfilter/avfilter.h | 50 +++++++++++++++++++++++++++++++++++++ libavfilter/avfiltergraph.c | 14 +++++++---- libavfilter/internal.h | 6 ++--- libavfilter/pthread.c | 4 +-- libavfilter/thread.h | 2 -- libavfilter/version.h | 2 +- 8 files changed, 69 insertions(+), 15 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 85c02d670e..20fb16e28d 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,10 @@ libavutil: 2012-10-22 API changes, most recent first: +2013-08-xx - xxxxxxx - lavfi 3.11.0 - avfilter.h + Add AVFilterGraph.execute and AVFilterGraph.opaque for custom slice threading + implementations. + 2013-09-21 - xxxxxxx - lavu 52.16.0 - pixfmt.h Add interleaved 4:2:2 8/10-bit formats AV_PIX_FMT_NV16 and AV_PIX_FMT_NV20. diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index bfbc0389a9..88e39bf720 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -371,7 +371,7 @@ static const AVClass avfilter_class = { .option = avfilter_options, }; -static int default_execute(AVFilterContext *ctx, action_func *func, void *arg, +static int default_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs) { int i; diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index c5efdb8374..ca11be9bc6 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -899,6 +899,35 @@ const AVClass *avfilter_get_class(void); typedef struct AVFilterGraphInternal AVFilterGraphInternal; +/** + * A function pointer passed to the @ref AVFilterGraph.execute callback to be + * executed multiple times, possibly in parallel. + * + * @param ctx the filter context the job belongs to + * @param arg an opaque parameter passed through from @ref + * AVFilterGraph.execute + * @param jobnr the index of the job being executed + * @param nb_jobs the total number of jobs + * + * @return 0 on success, a negative AVERROR on error + */ +typedef int (avfilter_action_func)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + +/** + * A function executing multiple jobs, possibly in parallel. + * + * @param ctx the filter context to which the jobs belong + * @param func the function to be called multiple times + * @param arg the argument to be passed to func + * @param ret a nb_jobs-sized array to be filled with return values from each + * invocation of func + * @param nb_jobs the number of jobs to execute + * + * @return 0 on success, a negative AVERROR on error + */ +typedef int (avfilter_execute_func)(AVFilterContext *ctx, avfilter_action_func *func, + void *arg, int *ret, int nb_jobs); + typedef struct AVFilterGraph { const AVClass *av_class; #if FF_API_FOO_COUNT @@ -941,6 +970,27 @@ typedef struct AVFilterGraph { * Opaque object for libavfilter internal use. */ AVFilterGraphInternal *internal; + + /** + * Opaque user data. May be set by the caller to an arbitrary value, e.g. to + * be used from callbacks like @ref AVFilterGraph.execute. + * Libavfilter will not touch this field in any way. + */ + void *opaque; + + /** + * This callback may be set by the caller immediately after allocating the + * graph and before adding any filters to it, to provide a custom + * multithreading implementation. + * + * If set, filters with slice threading capability will call this callback + * to execute multiple jobs in parallel. + * + * If this field is left unset, libavfilter will use its internal + * implementation, which may or may not be multithreaded depending on the + * platform and build options. + */ + avfilter_execute_func *execute; } AVFilterGraph; /** diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index de827355b8..0fc385c3a6 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -168,11 +168,15 @@ AVFilterContext *avfilter_graph_alloc_filter(AVFilterGraph *graph, { AVFilterContext **filters, *s; - if (graph->thread_type && !graph->internal->thread) { - int ret = ff_graph_thread_init(graph); - if (ret < 0) { - av_log(graph, AV_LOG_ERROR, "Error initializing threading.\n"); - return NULL; + if (graph->thread_type && !graph->internal->thread_execute) { + if (graph->execute) { + graph->internal->thread_execute = graph->execute; + } else { + int ret = ff_graph_thread_init(graph); + if (ret < 0) { + av_log(graph, AV_LOG_ERROR, "Error initializing threading.\n"); + return NULL; + } } } diff --git a/libavfilter/internal.h b/libavfilter/internal.h index 12655bc3e6..44e75832d0 100644 --- a/libavfilter/internal.h +++ b/libavfilter/internal.h @@ -122,13 +122,11 @@ struct AVFilterPad { struct AVFilterGraphInternal { void *thread; - int (*thread_execute)(AVFilterContext *ctx, action_func *func, void *arg, - int *ret, int nb_jobs); + avfilter_execute_func *thread_execute; }; struct AVFilterInternal { - int (*execute)(AVFilterContext *ctx, action_func *func, void *arg, - int *ret, int nb_jobs); + avfilter_execute_func *execute; }; #if FF_API_AVFILTERBUFFER diff --git a/libavfilter/pthread.c b/libavfilter/pthread.c index 2af0936ab5..a4f45c82cd 100644 --- a/libavfilter/pthread.c +++ b/libavfilter/pthread.c @@ -43,7 +43,7 @@ typedef struct ThreadContext { int nb_threads; pthread_t *workers; - action_func *func; + avfilter_action_func *func; /* per-execute perameters */ AVFilterContext *ctx; @@ -114,7 +114,7 @@ static void slice_thread_park_workers(ThreadContext *c) pthread_mutex_unlock(&c->current_job_lock); } -static int thread_execute(AVFilterContext *ctx, action_func *func, +static int thread_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs) { ThreadContext *c = ctx->graph->internal->thread; diff --git a/libavfilter/thread.h b/libavfilter/thread.h index 49134d948a..1cfea3e7ba 100644 --- a/libavfilter/thread.h +++ b/libavfilter/thread.h @@ -22,8 +22,6 @@ #include "avfilter.h" -typedef int (action_func)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); - int ff_graph_thread_init(AVFilterGraph *graph); void ff_graph_thread_free(AVFilterGraph *graph); diff --git a/libavfilter/version.h b/libavfilter/version.h index cb69228213..9c84e0f85a 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/avutil.h" #define LIBAVFILTER_VERSION_MAJOR 3 -#define LIBAVFILTER_VERSION_MINOR 10 +#define LIBAVFILTER_VERSION_MINOR 11 #define LIBAVFILTER_VERSION_MICRO 0 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \