History

Merge commit '129bb238430ec45a3b5f8f1d384df590ddf7b62f'

* commit '129bb238430ec45a3b5f8f1d384df590ddf7b62f': lavfi: add a slice threading infrastructure Conflicts: Changelog cmdutils.c doc/APIchanges libavfilter/Makefile libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/avfiltergraph.c libavfilter/internal.h libavfilter/version.h

Michael Niedermayer committed 13 years ago

Commit 8d4e9692 parents fe40a9f 129bb2311 files · +447 −14Browse files

Unified · Split

11 files
  1. Changelog +1 −0
  2. cmdutils.c +4 −0
  3. doc/APIchanges +7 −0
  4. libavfilter/Makefile +2 −0
  5. libavfilter/avfilter.c +42 −3
  6. libavfilter/avfilter.h +64 −0
  7. libavfilter/avfiltergraph.c +53 −9
  8. libavfilter/internal.h +12 −0
  9. libavfilter/pthread.c +229 −0
  10. libavfilter/thread.h +31 −0
  11. libavfilter/version.h +2 −2
Changelog+1−0
@@ -54,6 +54,7 @@ version <next>: · 53 unmodified lines
5454 - V4L2 output device
5555 - 3D LUT filter (lut3d)
5656 - SMPTE 302M audio encoder
57+- support for slice multithreading in libavfilter
5758
5859
5960 version 1.2:
cmdutils.c+4−0
@@ -1660,6 +1660,10 @@ static void show_help_filter(const char *name) · 1659 unmodified lines
16601660 printf("Filter %s\n", f->name);
16611661 if (f->description)
16621662 printf(" %s\n", f->description);
1663+
1664+ if (f->flags & AVFILTER_FLAG_SLICE_THREADS)
1665+ printf(" slice threading supported\n");
1666+
16631667 printf(" Inputs:\n");
16641668 count = avfilter_pad_count(f->inputs);
16651669 for (i = 0; i < count; i++) {
doc/APIchanges+7−0
@@ -16,6 +16,13 @@ libavutil: 2012-10-22 · 15 unmodified lines
1616 API changes, most recent first:
1717
1818
19+2013-05-24 - xxxxxxx - lavfi 3.70.100 - avfilter.h
20+ Add support for slice multithreading to lavfi. Filters supporting threading
21+ are marked with AVFILTER_FLAG_SLICE_THREADS.
22+ New fields AVFilterContext.thread_type, AVFilterGraph.thread_type and
23+ AVFilterGraph.nb_threads (accessible directly or through AVOptions) may be
24+ used to configure multithreading.
25+
1926 2013-05-24 - xxxxxxx - lavu 52.34.100 - cpu.h
2027 Add av_cpu_count() function for getting the number of logical CPUs.
2128
libavfilter/Makefile+2−0
@@ -240,6 +240,8 @@ OBJS-$(CONFIG_MOVIE_FILTER) += src_movie.o · 239 unmodified lines
240240 SKIPHEADERS-$(CONFIG_LIBVIDSTAB) += vidstabutils.h
241241 SKIPHEADERS-$(CONFIG_OPENCL) += opencl_internal.h deshake_opencl_kernel.h unsharp_opencl_kernel.h
242242
243+OBJS-$(HAVE_THREADS) += pthread.o
244+
243245 TOOLS = graph2dot
244246 TESTPROGS = drawutils filtfmts formats
245247
libavfilter/avfilter.c+42−3
@@ -538,9 +538,12 @@ static const AVClass *filter_child_class_next(const AVClass *prev) · 537 unmodified lines
538538
539539 #define OFFSET(x) offsetof(AVFilterContext, x)
540540 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM
541−static const AVOption filters_common_options[] = {
541+static const AVOption options[] = {
542+ { "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS,
543+ { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, "thread_type" },
544+ { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .unit = "thread_type" },
542545 { "enable", "set enable expression", OFFSET(enable_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
543− { NULL }
546+ { NULL },
544547 };
545548
546549 static const AVClass avfilter_class = {
@@ -549,10 +552,23 @@ static const AVClass avfilter_class = { · 2 unmodified lines
549552 .version = LIBAVUTIL_VERSION_INT,
550553 .category = AV_CLASS_CATEGORY_FILTER,
551554 .child_next = filter_child_next,
552− .option = filters_common_options,
553555 .child_class_next = filter_child_class_next,
556+ .option = options,
554557 };
555558
559+static int default_execute(AVFilterContext *ctx, action_func *func, void *arg,
560+ int *ret, int nb_jobs)
561+{
562+ int i;
563+
564+ for (i = 0; i < nb_jobs; i++) {
565+ int r = func(ctx, arg, i, nb_jobs);
566+ if (ret)
567+ ret[i] = r;
568+ }
569+ return 0;
570+}
571+
556572 AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name)
557573 {
558574 AVFilterContext *ret;
@@ -573,11 +589,17 @@ AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name) · 14 unmodified lines
573589 goto err;
574590 }
575591
592+ av_opt_set_defaults(ret);
576593 if (filter->priv_class) {
577594 *(const AVClass**)ret->priv = filter->priv_class;
578595 av_opt_set_defaults(ret->priv);
579596 }
580597
598+ ret->internal = av_mallocz(sizeof(*ret->internal));
599+ if (!ret->internal)
600+ goto err;
601+ ret->internal->execute = default_execute;
602+
581603 ret->nb_inputs = avfilter_pad_count(filter->inputs);
582604 if (ret->nb_inputs ) {
583605 ret->input_pads = av_malloc(sizeof(AVFilterPad) * ret->nb_inputs);
@@ -614,6 +636,7 @@ err: · 30 unmodified lines
614636 av_freep(&ret->output_pads);
615637 ret->nb_outputs = 0;
616638 av_freep(&ret->priv);
639+ av_freep(&ret->internal);
617640 av_free(ret);
618641 return NULL;
619642 }
@@ -681,6 +704,7 @@ void avfilter_free(AVFilterContext *filter) · 61 unmodified lines
681704 av_expr_free(filter->enable);
682705 filter->enable = NULL;
683706 av_freep(&filter->var_values);
707+ av_freep(&filter->internal);
684708 av_free(filter);
685709 }
686710
@@ -772,6 +796,21 @@ int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options) · 85 unmodified lines
772796 {
773797 int ret = 0;
774798
799+ ret = av_opt_set_dict(ctx, options);
800+ if (ret < 0) {
801+ av_log(ctx, AV_LOG_ERROR, "Error applying generic filter options.\n");
802+ return ret;
803+ }
804+
805+ if (ctx->filter->flags & AVFILTER_FLAG_SLICE_THREADS &&
806+ ctx->thread_type & ctx->graph->thread_type & AVFILTER_THREAD_SLICE &&
807+ ctx->graph->internal->thread_execute) {
808+ ctx->thread_type = AVFILTER_THREAD_SLICE;
809+ ctx->internal->execute = ctx->graph->internal->thread_execute;
810+ } else {
811+ ctx->thread_type = 0;
812+ }
813+
775814 if (ctx->filter->priv_class) {
776815 ret = av_opt_set_dict(ctx->priv, options);
777816 if (ret < 0) {
libavfilter/avfilter.h+64−0
@@ -428,6 +428,11 @@ enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx); · 427 unmodified lines
428428 * the options supplied to it.
429429 */
430430 #define AVFILTER_FLAG_DYNAMIC_OUTPUTS (1 << 1)
431+/**
432+ * The filter supports multithreading by splitting frames into multiple parts
433+ * and processing them concurrently.
434+ */
435+#define AVFILTER_FLAG_SLICE_THREADS (1 << 2)
431436 /**
432437 * Some filters support a generic "enable" expression option that can be used
433438 * to enable or disable a filter in the timeline. Filters supporting this
@@ -542,6 +547,13 @@ typedef struct AVFilter { · 108 unmodified lines
542547 int (*init_opaque)(AVFilterContext *ctx, void *opaque);
543548 } AVFilter;
544549
550+/**
551+ * Process multiple parts of the frame concurrently.
552+ */
553+#define AVFILTER_THREAD_SLICE (1 << 0)
554+
555+typedef struct AVFilterInternal AVFilterInternal;
556+
545557 /** An instance of a filter */
546558 struct AVFilterContext {
547559 const AVClass *av_class; ///< needed for av_log() and filters common options
@@ -568,6 +580,29 @@ struct AVFilterContext { · 20 unmodified lines
568580
569581 struct AVFilterGraph *graph; ///< filtergraph this filter belongs to
570582
583+ /**
584+ * Type of multithreading being allowed/used. A combination of
585+ * AVFILTER_THREAD_* flags.
586+ *
587+ * May be set by the caller before initializing the filter to forbid some
588+ * or all kinds of multithreading for this filter. The default is allowing
589+ * everything.
590+ *
591+ * When the filter is initialized, this field is combined using bit AND with
592+ * AVFilterGraph.thread_type to get the final mask used for determining
593+ * allowed threading types. I.e. a threading type needs to be set in both
594+ * to be allowed.
595+ *
596+ * After the filter is initialzed, libavfilter sets this field to the
597+ * threading type that is actually used (0 for no multithreading).
598+ */
599+ int thread_type;
600+
601+ /**
602+ * An opaque struct for libavfilter internal use.
603+ */
604+ AVFilterInternal *internal;
605+
571606 struct AVFilterCommand *command_queue;
572607
573608 char *enable_str; ///< enable expression string
@@ -1020,6 +1055,8 @@ int avfilter_copy_buf_props(AVFrame *dst, const AVFilterBufferRef *src); · 446 unmodified lines
10201055 */
10211056 const AVClass *avfilter_get_class(void);
10221057
1058+typedef struct AVFilterGraphInternal AVFilterGraphInternal;
1059+
10231060 typedef struct AVFilterGraph {
10241061 const AVClass *av_class;
10251062 #if FF_API_FOO_COUNT
@@ -1036,6 +1073,33 @@ typedef struct AVFilterGraph { · 10 unmodified lines
10361073 #if FF_API_FOO_COUNT
10371074 unsigned nb_filters;
10381075 #endif
1076+
1077+ /**
1078+ * Type of multithreading allowed for filters in this graph. A combination
1079+ * of AVFILTER_THREAD_* flags.
1080+ *
1081+ * May be set by the caller at any point, the setting will apply to all
1082+ * filters initialized after that. The default is allowing everything.
1083+ *
1084+ * When a filter in this graph is initialized, this field is combined using
1085+ * bit AND with AVFilterContext.thread_type to get the final mask used for
1086+ * determining allowed threading types. I.e. a threading type needs to be
1087+ * set in both to be allowed.
1088+ */
1089+ int thread_type;
1090+
1091+ /**
1092+ * Maximum number of threads used by filters in this graph. May be set by
1093+ * the caller before adding any filters to the filtergraph. Zero (the
1094+ * default) means that the number of threads is determined automatically.
1095+ */
1096+ int nb_threads;
1097+
1098+ /**
1099+ * Opaque object for libavfilter internal use.
1100+ */
1101+ AVFilterGraphInternal *internal;
1102+
10391103 char *aresample_swr_opts; ///< swr options to use for the auto-inserted aresample filters, Access ONLY through AVOptions
10401104
10411105 /**
libavfilter/avfiltergraph.c+53−9
@@ -20,6 +20,8 @@ · 19 unmodified lines
2020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2121 */
2222
23+#include "config.h"
24+
2325 #include <string.h>
2426
2527 #include "libavutil/avassert.h"
@@ -29,33 +31,63 @@ · 3 unmodified lines
2931 #include "libavutil/opt.h"
3032 #include "libavutil/pixdesc.h"
3133 #include "libavcodec/avcodec.h" // avcodec_find_best_pix_fmt_of_2()
34+
3235 #include "avfilter.h"
3336 #include "formats.h"
3437 #include "internal.h"
35−
36−#define OFFSET(x) offsetof(AVFilterGraph,x)
37−
38−static const AVOption options[]={
39−{"scale_sws_opts" , "default scale filter options" , OFFSET(scale_sws_opts) , AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, 0 },
40−{"aresample_swr_opts" , "default aresample filter options" , OFFSET(aresample_swr_opts) , AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, 0 },
41−{0}
38+#include "thread.h"
39+
40+#define OFFSET(x) offsetof(AVFilterGraph, x)
41+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
42+static const AVOption filtergraph_options[] = {
43+ { "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS,
44+ { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, "thread_type" },
45+ { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .flags = FLAGS, .unit = "thread_type" },
46+ { "threads", "Maximum number of threads", OFFSET(nb_threads),
47+ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
48+ {"scale_sws_opts" , "default scale filter options" , OFFSET(scale_sws_opts) ,
49+ AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
50+ {"aresample_swr_opts" , "default aresample filter options" , OFFSET(aresample_swr_opts) ,
51+ AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
52+ { NULL },
4253 };
4354
44−
4555 static const AVClass filtergraph_class = {
4656 .class_name = "AVFilterGraph",
4757 .item_name = av_default_item_name,
48− .option = options,
4958 .version = LIBAVUTIL_VERSION_INT,
59+ .option = filtergraph_options,
5060 .category = AV_CLASS_CATEGORY_FILTER,
5161 };
5262
63+#if !HAVE_THREADS
64+void ff_graph_thread_free(AVFilterGraph *graph)
65+{
66+}
67+
68+int ff_graph_thread_init(AVFilterGraph *graph)
69+{
70+ graph->thread_type = 0;
71+ graph->nb_threads = 1;
72+ return 0;
73+}
74+#endif
75+
5376 AVFilterGraph *avfilter_graph_alloc(void)
5477 {
5578 AVFilterGraph *ret = av_mallocz(sizeof(*ret));
5679 if (!ret)
5780 return NULL;
81+
82+ ret->internal = av_mallocz(sizeof(*ret->internal));
83+ if (!ret->internal) {
84+ av_freep(&ret);
85+ return NULL;
86+ }
87+
5888 ret->av_class = &filtergraph_class;
89+ av_opt_set_defaults(ret);
90+
5991 return ret;
6092 }
6193
@@ -80,11 +112,15 @@ void avfilter_graph_free(AVFilterGraph **graph) · 18 unmodified lines
80112 while ((*graph)->nb_filters)
81113 avfilter_free((*graph)->filters[0]);
82114
115+ ff_graph_thread_free(*graph);
116+
83117 av_freep(&(*graph)->sink_links);
118+
84119 av_freep(&(*graph)->scale_sws_opts);
85120 av_freep(&(*graph)->aresample_swr_opts);
86121 av_freep(&(*graph)->resample_lavr_opts);
87122 av_freep(&(*graph)->filters);
123+ av_freep(&(*graph)->internal);
88124 av_freep(graph);
89125 }
90126
@@ -143,6 +179,14 @@ AVFilterContext *avfilter_graph_alloc_filter(AVFilterGraph *graph, · 52 unmodified lines
143179 {
144180 AVFilterContext **filters, *s;
145181
182+ if (graph->thread_type && !graph->internal->thread) {
183+ int ret = ff_graph_thread_init(graph);
184+ if (ret < 0) {
185+ av_log(graph, AV_LOG_ERROR, "Error initializing threading.\n");
186+ return NULL;
187+ }
188+ }
189+
146190 s = ff_filter_alloc(filter, name);
147191 if (!s)
148192 return NULL;
libavfilter/internal.h+12−0
@@ -27,6 +27,7 @@ · 26 unmodified lines
2727 #include "avfilter.h"
2828 #include "avfiltergraph.h"
2929 #include "formats.h"
30+#include "thread.h"
3031 #include "video.h"
3132
3233 #define POOL_SIZE 32
@@ -141,6 +142,17 @@ struct AVFilterPad { · 108 unmodified lines
141142 };
142143 #endif
143144
145+struct AVFilterGraphInternal {
146+ void *thread;
147+ int (*thread_execute)(AVFilterContext *ctx, action_func *func, void *arg,
148+ int *ret, int nb_jobs);
149+};
150+
151+struct AVFilterInternal {
152+ int (*execute)(AVFilterContext *ctx, action_func *func, void *arg,
153+ int *ret, int nb_jobs);
154+};
155+
144156 /** default handler for freeing audio/video buffer when there are no references left */
145157 void ff_avfilter_default_free_buffer(AVFilterBuffer *buf);
146158
libavfilter/pthread.c+229−0
@@ -0,0 +1,229 @@
1+/*
2+ *
3+ * This file is part of FFmpeg.
4+ *
5+ * FFmpeg is free software; you can redistribute it and/or
6+ * modify it under the terms of the GNU Lesser General Public
7+ * License as published by the Free Software Foundation; either
8+ * version 2.1 of the License, or (at your option) any later version.
9+ *
10+ * FFmpeg is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+ * Lesser General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU Lesser General Public
16+ * License along with FFmpeg; if not, write to the Free Software
17+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+ */
19+
20+/**
21+ * @file
22+ * Libavfilter multithreading support
23+ */
24+
25+#include "config.h"
26+
27+#include "libavutil/common.h"
28+#include "libavutil/cpu.h"
29+#include "libavutil/mem.h"
30+
31+#include "avfilter.h"
32+#include "internal.h"
33+#include "thread.h"
34+
35+#if HAVE_PTHREADS
36+#include <pthread.h>
37+#elif HAVE_W32THREADS
38+#include "compat/w32pthreads.h"
39+#endif
40+
41+typedef struct ThreadContext {
42+ AVFilterGraph *graph;
43+
44+ int nb_threads;
45+ pthread_t *workers;
46+ action_func *func;
47+
48+ /* per-execute perameters */
49+ AVFilterContext *ctx;
50+ void *arg;
51+ int *rets;
52+ int nb_rets;
53+ int nb_jobs;
54+
55+ pthread_cond_t last_job_cond;
56+ pthread_cond_t current_job_cond;
57+ pthread_mutex_t current_job_lock;
58+ int current_job;
59+ int done;
60+} ThreadContext;
61+
62+static void* attribute_align_arg worker(void *v)
63+{
64+ ThreadContext *c = v;
65+ int our_job = c->nb_jobs;
66+ int nb_threads = c->nb_threads;
67+ int self_id;
68+
69+ pthread_mutex_lock(&c->current_job_lock);
70+ self_id = c->current_job++;
71+ for (;;) {
72+ while (our_job >= c->nb_jobs) {
73+ if (c->current_job == nb_threads + c->nb_jobs)
74+ pthread_cond_signal(&c->last_job_cond);
75+
76+ pthread_cond_wait(&c->current_job_cond, &c->current_job_lock);
77+ our_job = self_id;
78+
79+ if (c->done) {
80+ pthread_mutex_unlock(&c->current_job_lock);
81+ return NULL;
82+ }
83+ }
84+ pthread_mutex_unlock(&c->current_job_lock);
85+
86+ c->rets[our_job % c->nb_rets] = c->func(c->ctx, c->arg, our_job, c->nb_jobs);
87+
88+ pthread_mutex_lock(&c->current_job_lock);
89+ our_job = c->current_job++;
90+ }
91+}
92+
93+static void slice_thread_uninit(ThreadContext *c)
94+{
95+ int i;
96+
97+ pthread_mutex_lock(&c->current_job_lock);
98+ c->done = 1;
99+ pthread_cond_broadcast(&c->current_job_cond);
100+ pthread_mutex_unlock(&c->current_job_lock);
101+
102+ for (i = 0; i < c->nb_threads; i++)
103+ pthread_join(c->workers[i], NULL);
104+
105+ pthread_mutex_destroy(&c->current_job_lock);
106+ pthread_cond_destroy(&c->current_job_cond);
107+ pthread_cond_destroy(&c->last_job_cond);
108+ av_freep(&c->workers);
109+}
110+
111+static void slice_thread_park_workers(ThreadContext *c)
112+{
113+ pthread_cond_wait(&c->last_job_cond, &c->current_job_lock);
114+ pthread_mutex_unlock(&c->current_job_lock);
115+}
116+
117+static int thread_execute(AVFilterContext *ctx, action_func *func,
118+ void *arg, int *ret, int nb_jobs)
119+{
120+ ThreadContext *c = ctx->graph->internal->thread;
121+ int dummy_ret;
122+
123+ if (nb_jobs <= 0)
124+ return 0;
125+
126+ pthread_mutex_lock(&c->current_job_lock);
127+
128+ c->current_job = c->nb_threads;
129+ c->nb_jobs = nb_jobs;
130+ c->ctx = ctx;
131+ c->arg = arg;
132+ c->func = func;
133+ if (ret) {
134+ c->rets = ret;
135+ c->nb_rets = nb_jobs;
136+ } else {
137+ c->rets = &dummy_ret;
138+ c->nb_rets = 1;
139+ }
140+ pthread_cond_broadcast(&c->current_job_cond);
141+
142+ slice_thread_park_workers(c);
143+
144+ return 0;
145+}
146+
147+static int thread_init(ThreadContext *c, int nb_threads)
148+{
149+ int i, ret;
150+
151+ if (!nb_threads) {
152+ int nb_cpus = av_cpu_count();
153+ av_log(c->graph, AV_LOG_DEBUG, "Detected %d logical cores.\n", nb_cpus);
154+ // use number of cores + 1 as thread count if there is more than one
155+ if (nb_cpus > 1)
156+ nb_threads = nb_cpus + 1;
157+ else
158+ nb_threads = 1;
159+ }
160+
161+ if (nb_threads <= 1)
162+ return 1;
163+
164+ c->nb_threads = nb_threads;
165+ c->workers = av_mallocz(sizeof(*c->workers) * nb_threads);
166+ if (!c->workers)
167+ return AVERROR(ENOMEM);
168+
169+ c->current_job = 0;
170+ c->nb_jobs = 0;
171+ c->done = 0;
172+
173+ pthread_cond_init(&c->current_job_cond, NULL);
174+ pthread_cond_init(&c->last_job_cond, NULL);
175+
176+ pthread_mutex_init(&c->current_job_lock, NULL);
177+ pthread_mutex_lock(&c->current_job_lock);
178+ for (i = 0; i < nb_threads; i++) {
179+ ret = pthread_create(&c->workers[i], NULL, worker, c);
180+ if (ret) {
181+ pthread_mutex_unlock(&c->current_job_lock);
182+ c->nb_threads = i;
183+ slice_thread_uninit(c);
184+ return AVERROR(ret);
185+ }
186+ }
187+
188+ slice_thread_park_workers(c);
189+
190+ return c->nb_threads;
191+}
192+
193+int ff_graph_thread_init(AVFilterGraph *graph)
194+{
195+ int ret;
196+
197+#if HAVE_W32THREADS
198+ w32thread_init();
199+#endif
200+
201+ if (graph->nb_threads == 1) {
202+ graph->thread_type = 0;
203+ return 0;
204+ }
205+
206+ graph->internal->thread = av_mallocz(sizeof(ThreadContext));
207+ if (!graph->internal->thread)
208+ return AVERROR(ENOMEM);
209+
210+ ret = thread_init(graph->internal->thread, graph->nb_threads);
211+ if (ret <= 1) {
212+ av_freep(&graph->internal->thread);
213+ graph->thread_type = 0;
214+ graph->nb_threads = 1;
215+ return (ret < 0) ? ret : 0;
216+ }
217+ graph->nb_threads = ret;
218+
219+ graph->internal->thread_execute = thread_execute;
220+
221+ return 0;
222+}
223+
224+void ff_graph_thread_free(AVFilterGraph *graph)
225+{
226+ if (graph->internal->thread)
227+ slice_thread_uninit(graph->internal->thread);
228+ av_freep(&graph->internal->thread);
229+}
libavfilter/thread.h+31−0
@@ -0,0 +1,31 @@
1+/*
2+ *
3+ * This file is part of FFmpeg.
4+ *
5+ * FFmpeg is free software; you can redistribute it and/or
6+ * modify it under the terms of the GNU Lesser General Public
7+ * License as published by the Free Software Foundation; either
8+ * version 2.1 of the License, or (at your option) any later version.
9+ *
10+ * FFmpeg is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+ * Lesser General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU Lesser General Public
16+ * License along with FFmpeg; if not, write to the Free Software
17+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+ */
19+
20+#ifndef AVFILTER_THREAD_H
21+#define AVFILTER_THREAD_H
22+
23+#include "avfilter.h"
24+
25+typedef int (action_func)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
26+
27+int ff_graph_thread_init(AVFilterGraph *graph);
28+
29+void ff_graph_thread_free(AVFilterGraph *graph);
30+
31+#endif /* AVFILTER_THREAD_H */
libavfilter/version.h+2−2
@@ -30,8 +30,8 @@ · 29 unmodified lines
3030 #include "libavutil/avutil.h"
3131
3232 #define LIBAVFILTER_VERSION_MAJOR 3
33−#define LIBAVFILTER_VERSION_MINOR 69
34−#define LIBAVFILTER_VERSION_MICRO 101
33+#define LIBAVFILTER_VERSION_MINOR 70
34+#define LIBAVFILTER_VERSION_MICRO 100
3535
3636 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
3737 LIBAVFILTER_VERSION_MINOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t