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
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
int
done
;
62
}
ThreadContext
;
63
64
static
void
*
attribute_align_arg
worker
(
void
*
v
)
65
{
66
ThreadContext
*
c
=
v
;
67
int
our_job = c->
nb_jobs
;
68
int
nb_threads = c->
nb_threads
;
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
pthread_cond_wait
(&c->
current_job_cond
, &c->
current_job_lock
);
79
our_job = self_id;
80
81
if
(c->
done
) {
82
pthread_mutex_unlock
(&c->
current_job_lock
);
83
return
NULL;
84
}
85
}
86
pthread_mutex_unlock
(&c->
current_job_lock
);
87
88
c->
rets
[our_job % c->
nb_rets
] = c->
func
(c->
ctx
, c->
arg
, our_job, c->
nb_jobs
);
89
90
pthread_mutex_lock
(&c->
current_job_lock
);
91
our_job = c->
current_job
++;
92
}
93
}
94
95
static
void
slice_thread_uninit
(
ThreadContext
*
c
)
96
{
97
int
i;
98
99
pthread_mutex_lock
(&c->
current_job_lock
);
100
c->
done
= 1;
101
pthread_cond_broadcast
(&c->
current_job_cond
);
102
pthread_mutex_unlock
(&c->
current_job_lock
);
103
104
for
(i = 0; i < c->
nb_threads
; i++)
105
pthread_join
(c->
workers
[i], NULL);
106
107
pthread_mutex_destroy
(&c->
current_job_lock
);
108
pthread_cond_destroy
(&c->
current_job_cond
);
109
pthread_cond_destroy
(&c->
last_job_cond
);
110
av_freep
(&c->
workers
);
111
}
112
113
static
void
slice_thread_park_workers
(
ThreadContext
*
c
)
114
{
115
pthread_cond_wait
(&c->
last_job_cond
, &c->
current_job_lock
);
116
pthread_mutex_unlock
(&c->
current_job_lock
);
117
}
118
119
static
int
thread_execute
(
AVFilterContext
*ctx,
action_func
*
func
,
120
void
*
arg
,
int
*
ret
,
int
nb_jobs)
121
{
122
ThreadContext
*
c
= ctx->
graph
->
internal
->
thread
;
123
int
dummy_ret;
124
125
if
(nb_jobs <= 0)
126
return
0;
127
128
pthread_mutex_lock
(&c->
current_job_lock
);
129
130
c->
current_job
= c->
nb_threads
;
131
c->
nb_jobs
= nb_jobs;
132
c->
ctx
= ctx;
133
c->
arg
=
arg
;
134
c->
func
=
func
;
135
if
(ret) {
136
c->
rets
=
ret
;
137
c->
nb_rets
= nb_jobs;
138
}
else
{
139
c->
rets
= &dummy_ret;
140
c->
nb_rets
= 1;
141
}
142
pthread_cond_broadcast
(&c->
current_job_cond
);
143
144
slice_thread_park_workers
(c);
145
146
return
0;
147
}
148
149
static
int
avfilter_thread_init
(
ThreadContext
*
c
,
int
nb_threads)
150
{
151
int
i,
ret
;
152
153
if
(!nb_threads) {
154
int
nb_cpus =
av_cpu_count
();
155
// use number of cores + 1 as thread count if there is more than one
156
if
(nb_cpus > 1)
157
nb_threads = nb_cpus + 1;
158
else
159
nb_threads = 1;
160
}
161
162
if
(nb_threads <= 1)
163
return
1;
164
165
c->
nb_threads
= nb_threads;
166
c->
workers
=
av_mallocz
(
sizeof
(*c->
workers
) * nb_threads);
167
if
(!c->
workers
)
168
return
AVERROR
(ENOMEM);
169
170
c->
current_job
= 0;
171
c->
nb_jobs
= 0;
172
c->
done
= 0;
173
174
pthread_cond_init
(&c->
current_job_cond
, NULL);
175
pthread_cond_init
(&c->
last_job_cond
, NULL);
176
177
pthread_mutex_init
(&c->
current_job_lock
, NULL);
178
pthread_mutex_lock
(&c->
current_job_lock
);
179
for
(i = 0; i < nb_threads; i++) {
180
ret =
pthread_create
(&c->
workers
[i], NULL,
worker
, c);
181
if
(ret) {
182
pthread_mutex_unlock
(&c->
current_job_lock
);
183
c->
nb_threads
= i;
184
slice_thread_uninit
(c);
185
return
AVERROR
(ret);
186
}
187
}
188
189
slice_thread_park_workers
(c);
190
191
return
c->
nb_threads
;
192
}
193
194
int
ff_graph_thread_init
(
AVFilterGraph
*graph)
195
{
196
int
ret
;
197
198
#if HAVE_W32THREADS
199
w32thread_init
();
200
#endif
201
202
if
(graph->
nb_threads
== 1) {
203
graph->
thread_type
= 0;
204
return
0;
205
}
206
207
graph->
internal
->
thread
=
av_mallocz
(
sizeof
(
ThreadContext
));
208
if
(!graph->
internal
->
thread
)
209
return
AVERROR
(ENOMEM);
210
211
ret =
avfilter_thread_init
(graph->
internal
->
thread
, graph->
nb_threads
);
212
if
(ret <= 1) {
213
av_freep
(&graph->
internal
->
thread
);
214
graph->
thread_type
= 0;
215
graph->
nb_threads
= 1;
216
return
(ret < 0) ? ret : 0;
217
}
218
graph->
nb_threads
=
ret
;
219
220
graph->
internal
->
thread_execute
=
thread_execute
;
221
222
return
0;
223
}
224
225
void
ff_graph_thread_free
(
AVFilterGraph
*graph)
226
{
227
if
(graph->
internal
->
thread
)
228
slice_thread_uninit
(graph->
internal
->
thread
);
229
av_freep
(&graph->
internal
->
thread
);
230
}
Generated on Wed Jul 10 2013 23:48:03 for FFmpeg by
1.8.2