FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
•
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavfilter
pthread.c
Go to the documentation of this file.
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_OS2THREADS
38
#include "
compat/os2threads.h
"
39
#elif HAVE_W32THREADS
40
#include "
compat/w32pthreads.h
"
41
#endif
42
43
typedef
struct
ThreadContext
{
44
AVFilterGraph
*
graph
;
45
46
int
nb_threads
;
47
pthread_t
*
workers
;
48
avfilter_action_func
*
func
;
49
50
/* per-execute perameters */
51
AVFilterContext
*
ctx
;
52
void
*
arg
;
53
int
*
rets
;
54
int
nb_rets
;
55
int
nb_jobs
;
56
57
pthread_cond_t
last_job_cond
;
58
pthread_cond_t
current_job_cond
;
59
pthread_mutex_t
current_job_lock
;
60
int
current_job
;
61
unsigned
int
current_execute
;
62
int
done
;
63
}
ThreadContext
;
64
65
static
void
* attribute_align_arg
worker
(
void
*
v
)
66
{
67
ThreadContext
*
c
=
v
;
68
int
our_job = c->
nb_jobs
;
69
int
nb_threads = c->
nb_threads
;
70
unsigned
int
last_execute = 0;
71
int
self_id;
72
73
pthread_mutex_lock
(&c->
current_job_lock
);
74
self_id = c->
current_job
++;
75
for
(;;) {
76
while
(our_job >= c->
nb_jobs
) {
77
if
(c->
current_job
== nb_threads + c->
nb_jobs
)
78
pthread_cond_signal
(&c->
last_job_cond
);
79
80
while
(last_execute == c->
current_execute
&& !c->
done
)
81
pthread_cond_wait
(&c->
current_job_cond
, &c->
current_job_lock
);
82
last_execute = c->
current_execute
;
83
our_job = self_id;
84
85
if
(c->
done
) {
86
pthread_mutex_unlock
(&c->
current_job_lock
);
87
return
NULL;
88
}
89
}
90
pthread_mutex_unlock
(&c->
current_job_lock
);
91
92
c->
rets
[our_job % c->
nb_rets
] = c->
func
(c->
ctx
, c->
arg
, our_job, c->
nb_jobs
);
93
94
pthread_mutex_lock
(&c->
current_job_lock
);
95
our_job = c->
current_job
++;
96
}
97
}
98
99
static
void
slice_thread_uninit
(
ThreadContext
*
c
)
100
{
101
int
i;
102
103
pthread_mutex_lock
(&c->
current_job_lock
);
104
c->
done
= 1;
105
pthread_cond_broadcast
(&c->
current_job_cond
);
106
pthread_mutex_unlock
(&c->
current_job_lock
);
107
108
for
(i = 0; i < c->
nb_threads
; i++)
109
pthread_join
(c->
workers
[i], NULL);
110
111
pthread_mutex_destroy
(&c->
current_job_lock
);
112
pthread_cond_destroy
(&c->
current_job_cond
);
113
pthread_cond_destroy
(&c->
last_job_cond
);
114
av_freep
(&c->
workers
);
115
}
116
117
static
void
slice_thread_park_workers
(
ThreadContext
*
c
)
118
{
119
while
(c->
current_job
!= c->
nb_threads
+ c->
nb_jobs
)
120
pthread_cond_wait
(&c->
last_job_cond
, &c->
current_job_lock
);
121
pthread_mutex_unlock
(&c->
current_job_lock
);
122
}
123
124
static
int
thread_execute
(
AVFilterContext
*ctx,
avfilter_action_func
*
func
,
125
void
*
arg
,
int
*
ret
,
int
nb_jobs)
126
{
127
ThreadContext
*
c
= ctx->
graph
->
internal
->
thread
;
128
int
dummy_ret;
129
130
if
(nb_jobs <= 0)
131
return
0;
132
133
pthread_mutex_lock
(&c->
current_job_lock
);
134
135
c->
current_job
= c->
nb_threads
;
136
c->
nb_jobs
= nb_jobs;
137
c->
ctx
= ctx;
138
c->
arg
=
arg
;
139
c->
func
=
func
;
140
if
(ret) {
141
c->
rets
=
ret
;
142
c->
nb_rets
= nb_jobs;
143
}
else
{
144
c->
rets
= &dummy_ret;
145
c->
nb_rets
= 1;
146
}
147
c->
current_execute
++;
148
149
pthread_cond_broadcast
(&c->
current_job_cond
);
150
151
slice_thread_park_workers
(c);
152
153
return
0;
154
}
155
156
static
int
thread_init_internal
(
ThreadContext
*
c
,
int
nb_threads)
157
{
158
int
i,
ret
;
159
160
if
(!nb_threads) {
161
int
nb_cpus =
av_cpu_count
();
162
// use number of cores + 1 as thread count if there is more than one
163
if
(nb_cpus > 1)
164
nb_threads = nb_cpus + 1;
165
else
166
nb_threads = 1;
167
}
168
169
if
(nb_threads <= 1)
170
return
1;
171
172
c->
nb_threads
= nb_threads;
173
c->
workers
=
av_mallocz
(
sizeof
(*c->
workers
) * nb_threads);
174
if
(!c->
workers
)
175
return
AVERROR
(ENOMEM);
176
177
c->
current_job
= 0;
178
c->
nb_jobs
= 0;
179
c->
done
= 0;
180
181
pthread_cond_init
(&c->
current_job_cond
, NULL);
182
pthread_cond_init
(&c->
last_job_cond
, NULL);
183
184
pthread_mutex_init
(&c->
current_job_lock
, NULL);
185
pthread_mutex_lock
(&c->
current_job_lock
);
186
for
(i = 0; i < nb_threads; i++) {
187
ret =
pthread_create
(&c->
workers
[i], NULL,
worker
, c);
188
if
(ret) {
189
pthread_mutex_unlock
(&c->
current_job_lock
);
190
c->
nb_threads
= i;
191
slice_thread_uninit
(c);
192
return
AVERROR
(ret);
193
}
194
}
195
196
slice_thread_park_workers
(c);
197
198
return
c->
nb_threads
;
199
}
200
201
int
ff_graph_thread_init
(
AVFilterGraph
*graph)
202
{
203
int
ret
;
204
205
#if HAVE_W32THREADS
206
w32thread_init
();
207
#endif
208
209
if
(graph->
nb_threads
== 1) {
210
graph->
thread_type
= 0;
211
return
0;
212
}
213
214
graph->
internal
->
thread
=
av_mallocz
(
sizeof
(
ThreadContext
));
215
if
(!graph->
internal
->
thread
)
216
return
AVERROR
(ENOMEM);
217
218
ret =
thread_init_internal
(graph->
internal
->
thread
, graph->
nb_threads
);
219
if
(ret <= 1) {
220
av_freep
(&graph->
internal
->
thread
);
221
graph->
thread_type
= 0;
222
graph->
nb_threads
= 1;
223
return
(ret < 0) ? ret : 0;
224
}
225
graph->
nb_threads
=
ret
;
226
227
graph->
internal
->
thread_execute
=
thread_execute
;
228
229
return
0;
230
}
231
232
void
ff_graph_thread_free
(
AVFilterGraph
*graph)
233
{
234
if
(graph->
internal
->
thread
)
235
slice_thread_uninit
(graph->
internal
->
thread
);
236
av_freep
(&graph->
internal
->
thread
);
237
}
Generated on Sun Mar 23 2014 23:50:01 for FFmpeg by
1.8.2