Libav
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavfilter
pthread.c
Go to the documentation of this file.
1
/*
2
*
3
* This file is part of Libav.
4
*
5
* Libav 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
* Libav 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 Libav; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
*/
19
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
avfilter_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
unsigned
int
current_execute
;
60
int
done
;
61
}
ThreadContext
;
62
63
static
void
*
attribute_align_arg
worker
(
void
*v)
64
{
65
ThreadContext
*c = v;
66
int
our_job = c->
nb_jobs
;
67
int
nb_threads = c->
nb_threads
;
68
unsigned
int
last_execute = 0;
69
int
self_id;
70
71
pthread_mutex_lock
(&c->
current_job_lock
);
72
self_id = c->
current_job
++;
73
for
(;;) {
74
while
(our_job >= c->
nb_jobs
) {
75
if
(c->
current_job
== nb_threads + c->
nb_jobs
)
76
pthread_cond_signal
(&c->
last_job_cond
);
77
78
while
(last_execute == c->
current_execute
&& !c->
done
)
79
pthread_cond_wait
(&c->
current_job_cond
, &c->
current_job_lock
);
80
last_execute = c->
current_execute
;
81
our_job = self_id;
82
83
if
(c->
done
) {
84
pthread_mutex_unlock
(&c->
current_job_lock
);
85
return
NULL
;
86
}
87
}
88
pthread_mutex_unlock
(&c->
current_job_lock
);
89
90
c->
rets
[our_job % c->
nb_rets
] = c->
func
(c->
ctx
, c->
arg
, our_job, c->
nb_jobs
);
91
92
pthread_mutex_lock
(&c->
current_job_lock
);
93
our_job = c->
current_job
++;
94
}
95
}
96
97
static
void
slice_thread_uninit
(
ThreadContext
*c)
98
{
99
int
i;
100
101
pthread_mutex_lock
(&c->
current_job_lock
);
102
c->
done
= 1;
103
pthread_cond_broadcast
(&c->
current_job_cond
);
104
pthread_mutex_unlock
(&c->
current_job_lock
);
105
106
for
(i = 0; i < c->
nb_threads
; i++)
107
pthread_join
(c->
workers
[i],
NULL
);
108
109
pthread_mutex_destroy
(&c->
current_job_lock
);
110
pthread_cond_destroy
(&c->
current_job_cond
);
111
pthread_cond_destroy
(&c->
last_job_cond
);
112
av_freep
(&c->
workers
);
113
}
114
115
static
void
slice_thread_park_workers
(
ThreadContext
*c)
116
{
117
while
(c->
current_job
!= c->
nb_threads
+ c->
nb_jobs
)
118
pthread_cond_wait
(&c->
last_job_cond
, &c->
current_job_lock
);
119
pthread_mutex_unlock
(&c->
current_job_lock
);
120
}
121
122
static
int
thread_execute
(
AVFilterContext
*ctx,
avfilter_action_func
*func,
123
void
*arg,
int
*ret,
int
nb_jobs)
124
{
125
ThreadContext
*c = ctx->
graph
->
internal
->
thread
;
126
int
dummy_ret;
127
128
if
(nb_jobs <= 0)
129
return
0;
130
131
pthread_mutex_lock
(&c->
current_job_lock
);
132
133
c->
current_job
= c->
nb_threads
;
134
c->
nb_jobs
= nb_jobs;
135
c->
ctx
= ctx;
136
c->
arg
= arg;
137
c->
func
= func;
138
if
(ret) {
139
c->
rets
= ret;
140
c->
nb_rets
= nb_jobs;
141
}
else
{
142
c->
rets
= &dummy_ret;
143
c->
nb_rets
= 1;
144
}
145
c->
current_execute
++;
146
147
pthread_cond_broadcast
(&c->
current_job_cond
);
148
149
slice_thread_park_workers
(c);
150
151
return
0;
152
}
153
154
static
int
thread_init_internal
(
ThreadContext
*c,
int
nb_threads)
155
{
156
int
i, ret;
157
158
if
(!nb_threads) {
159
int
nb_cpus =
av_cpu_count
();
160
av_log
(c->
graph
,
AV_LOG_DEBUG
,
"Detected %d logical cores.\n"
, nb_cpus);
161
// use number of cores + 1 as thread count if there is more than one
162
if
(nb_cpus > 1)
163
nb_threads = nb_cpus + 1;
164
else
165
nb_threads = 1;
166
}
167
168
if
(nb_threads <= 1)
169
return
1;
170
171
c->
nb_threads
= nb_threads;
172
c->
workers
=
av_mallocz
(
sizeof
(*c->
workers
) * nb_threads);
173
if
(!c->
workers
)
174
return
AVERROR
(ENOMEM);
175
176
c->
current_job
= 0;
177
c->
nb_jobs
= 0;
178
c->
done
= 0;
179
180
pthread_cond_init
(&c->
current_job_cond
,
NULL
);
181
pthread_cond_init
(&c->
last_job_cond
,
NULL
);
182
183
pthread_mutex_init
(&c->
current_job_lock
,
NULL
);
184
pthread_mutex_lock
(&c->
current_job_lock
);
185
for
(i = 0; i < nb_threads; i++) {
186
ret =
pthread_create
(&c->
workers
[i],
NULL
,
worker
, c);
187
if
(ret) {
188
pthread_mutex_unlock
(&c->
current_job_lock
);
189
c->
nb_threads
= i;
190
slice_thread_uninit
(c);
191
return
AVERROR
(ret);
192
}
193
}
194
195
slice_thread_park_workers
(c);
196
197
return
c->
nb_threads
;
198
}
199
200
int
ff_graph_thread_init
(
AVFilterGraph
*graph)
201
{
202
int
ret;
203
204
#if HAVE_W32THREADS
205
w32thread_init
();
206
#endif
207
208
if
(graph->
nb_threads
== 1) {
209
graph->
thread_type
= 0;
210
return
0;
211
}
212
213
graph->
internal
->
thread
=
av_mallocz
(
sizeof
(
ThreadContext
));
214
if
(!graph->
internal
->
thread
)
215
return
AVERROR
(ENOMEM);
216
217
ret =
thread_init_internal
(graph->
internal
->
thread
, graph->
nb_threads
);
218
if
(ret <= 1) {
219
av_freep
(&graph->
internal
->
thread
);
220
graph->
thread_type
= 0;
221
graph->
nb_threads
= 1;
222
return
(ret < 0) ? ret : 0;
223
}
224
graph->
nb_threads
= ret;
225
226
graph->
internal
->
thread_execute
=
thread_execute
;
227
228
return
0;
229
}
230
231
void
ff_graph_thread_free
(
AVFilterGraph
*graph)
232
{
233
if
(graph->
internal
->
thread
)
234
slice_thread_uninit
(graph->
internal
->
thread
);
235
av_freep
(&graph->
internal
->
thread
);
236
}
Generated on Tue Mar 1 2016 21:14:44 for Libav by
1.8.4