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