lavfi: allow user-provided execute() callbacks
authorAnton Khirnov <anton@khirnov.net>
Thu, 8 Aug 2013 14:28:41 +0000 (16:28 +0200)
committerAnton Khirnov <anton@khirnov.net>
Sat, 28 Sep 2013 06:06:19 +0000 (08:06 +0200)
doc/APIchanges
libavfilter/avfilter.c
libavfilter/avfilter.h
libavfilter/avfiltergraph.c
libavfilter/internal.h
libavfilter/pthread.c
libavfilter/thread.h
libavfilter/version.h

index 85c02d6..20fb16e 100644 (file)
@@ -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.
index bfbc038..88e39bf 100644 (file)
@@ -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;
index c5efdb8..ca11be9 100644 (file)
@@ -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;
 
 /**
index de82735..0fc385c 100644 (file)
@@ -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;
+            }
         }
     }
 
index 12655bc..44e7583 100644 (file)
@@ -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
index 2af0936..a4f45c8 100644 (file)
@@ -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;
index 49134d9..1cfea3e 100644 (file)
@@ -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);
index cb69228..9c84e0f 100644 (file)
@@ -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, \