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
libavcodec
pthread_slice.c
Go to the documentation of this file.
1
/*
2
* This file is part of FFmpeg.
3
*
4
* FFmpeg is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
8
*
9
* FFmpeg is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
13
*
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with FFmpeg; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
*/
18
19
/**
20
* @file
21
* Slice multithreading support functions
22
* @see doc/multithreading.txt
23
*/
24
25
#include "config.h"
26
27
#if HAVE_PTHREADS
28
#include <pthread.h>
29
#elif HAVE_W32THREADS
30
#include "
compat/w32pthreads.h
"
31
#elif HAVE_OS2THREADS
32
#include "
compat/os2threads.h
"
33
#endif
34
35
#include "
avcodec.h
"
36
#include "
internal.h
"
37
#include "
pthread_internal.h
"
38
#include "
thread.h
"
39
40
#include "
libavutil/common.h
"
41
#include "
libavutil/cpu.h
"
42
#include "
libavutil/mem.h
"
43
44
typedef
int (
action_func
)(
AVCodecContext
*
c
,
void
*
arg
);
45
typedef
int (
action_func2
)(
AVCodecContext
*
c
,
void
*
arg
,
int
jobnr,
int
threadnr);
46
47
typedef
struct
SliceThreadContext
{
48
pthread_t
*
workers
;
49
action_func
*
func
;
50
action_func2
*
func2
;
51
void
*
args
;
52
int
*
rets
;
53
int
rets_count
;
54
int
job_count
;
55
int
job_size
;
56
57
pthread_cond_t
last_job_cond
;
58
pthread_cond_t
current_job_cond
;
59
pthread_mutex_t
current_job_lock
;
60
unsigned
current_execute
;
61
int
current_job
;
62
int
done
;
63
64
int
*
entries
;
65
int
entries_count
;
66
int
thread_count
;
67
pthread_cond_t
*
progress_cond
;
68
pthread_mutex_t
*
progress_mutex
;
69
}
SliceThreadContext
;
70
71
static
void
* attribute_align_arg
worker
(
void
*
v
)
72
{
73
AVCodecContext
*avctx =
v
;
74
SliceThreadContext
*
c
= avctx->
internal
->
thread_ctx
;
75
unsigned
last_execute = 0;
76
int
our_job = c->
job_count
;
77
int
thread_count = avctx->
thread_count
;
78
int
self_id;
79
80
pthread_mutex_lock
(&c->
current_job_lock
);
81
self_id = c->
current_job
++;
82
for
(;;){
83
while
(our_job >= c->
job_count
) {
84
if
(c->
current_job
== thread_count + c->
job_count
)
85
pthread_cond_signal
(&c->
last_job_cond
);
86
87
while
(last_execute == c->
current_execute
&& !c->
done
)
88
pthread_cond_wait
(&c->
current_job_cond
, &c->
current_job_lock
);
89
last_execute = c->
current_execute
;
90
our_job = self_id;
91
92
if
(c->
done
) {
93
pthread_mutex_unlock
(&c->
current_job_lock
);
94
return
NULL
;
95
}
96
}
97
pthread_mutex_unlock
(&c->
current_job_lock
);
98
99
c->
rets
[our_job%c->
rets_count
] = c->
func
? c->
func
(avctx, (
char
*)c->
args
+ our_job*c->
job_size
):
100
c->
func2
(avctx, c->
args
, our_job, self_id);
101
102
pthread_mutex_lock
(&c->
current_job_lock
);
103
our_job = c->
current_job
++;
104
}
105
}
106
107
void
ff_slice_thread_free
(
AVCodecContext
*avctx)
108
{
109
SliceThreadContext
*
c
= avctx->
internal
->
thread_ctx
;
110
int
i;
111
112
pthread_mutex_lock
(&c->
current_job_lock
);
113
c->
done
= 1;
114
pthread_cond_broadcast
(&c->
current_job_cond
);
115
for
(i = 0; i < c->
thread_count
; i++)
116
pthread_cond_broadcast
(&c->
progress_cond
[i]);
117
pthread_mutex_unlock
(&c->
current_job_lock
);
118
119
for
(i=0; i<avctx->
thread_count
; i++)
120
pthread_join
(c->
workers
[i],
NULL
);
121
122
for
(i = 0; i < c->
thread_count
; i++) {
123
pthread_mutex_destroy
(&c->
progress_mutex
[i]);
124
pthread_cond_destroy
(&c->
progress_cond
[i]);
125
}
126
127
pthread_mutex_destroy
(&c->
current_job_lock
);
128
pthread_cond_destroy
(&c->
current_job_cond
);
129
pthread_cond_destroy
(&c->
last_job_cond
);
130
131
av_freep
(&c->
entries
);
132
av_freep
(&c->
progress_mutex
);
133
av_freep
(&c->
progress_cond
);
134
135
av_freep
(&c->
workers
);
136
av_freep
(&avctx->
internal
->
thread_ctx
);
137
}
138
139
static
av_always_inline
void
thread_park_workers
(
SliceThreadContext
*
c
,
int
thread_count)
140
{
141
while
(c->
current_job
!= thread_count + c->
job_count
)
142
pthread_cond_wait
(&c->
last_job_cond
, &c->
current_job_lock
);
143
pthread_mutex_unlock
(&c->
current_job_lock
);
144
}
145
146
static
int
thread_execute
(
AVCodecContext
*avctx,
action_func
*
func
,
void
*
arg
,
int
*
ret
,
int
job_count,
int
job_size)
147
{
148
SliceThreadContext
*
c
= avctx->
internal
->
thread_ctx
;
149
int
dummy_ret;
150
151
if
(!(avctx->
active_thread_type
&
FF_THREAD_SLICE
) || avctx->
thread_count
<= 1)
152
return
avcodec_default_execute
(avctx, func, arg, ret, job_count, job_size);
153
154
if
(job_count <= 0)
155
return
0;
156
157
pthread_mutex_lock
(&c->
current_job_lock
);
158
159
c->
current_job
= avctx->
thread_count
;
160
c->
job_count
= job_count;
161
c->
job_size
= job_size;
162
c->
args
=
arg
;
163
c->
func
=
func
;
164
if
(ret) {
165
c->
rets
=
ret
;
166
c->
rets_count
= job_count;
167
}
else
{
168
c->
rets
= &dummy_ret;
169
c->
rets_count
= 1;
170
}
171
c->
current_execute
++;
172
pthread_cond_broadcast
(&c->
current_job_cond
);
173
174
thread_park_workers
(c, avctx->
thread_count
);
175
176
return
0;
177
}
178
179
static
int
thread_execute2
(
AVCodecContext
*avctx,
action_func2
* func2,
void
*
arg
,
int
*
ret
,
int
job_count)
180
{
181
SliceThreadContext
*
c
= avctx->
internal
->
thread_ctx
;
182
c->
func2
= func2;
183
return
thread_execute
(avctx,
NULL
, arg, ret, job_count, 0);
184
}
185
186
int
ff_slice_thread_init
(
AVCodecContext
*avctx)
187
{
188
int
i;
189
SliceThreadContext
*
c
;
190
int
thread_count = avctx->
thread_count
;
191
192
#if HAVE_W32THREADS
193
w32thread_init
();
194
#endif
195
196
if
(!thread_count) {
197
int
nb_cpus =
av_cpu_count
();
198
if
(avctx->
height
)
199
nb_cpus =
FFMIN
(nb_cpus, (avctx->
height
+15)/16);
200
// use number of cores + 1 as thread count if there is more than one
201
if
(nb_cpus > 1)
202
thread_count = avctx->
thread_count
=
FFMIN
(nb_cpus + 1,
MAX_AUTO_THREADS
);
203
else
204
thread_count = avctx->
thread_count
= 1;
205
}
206
207
if
(thread_count <= 1) {
208
avctx->
active_thread_type
= 0;
209
return
0;
210
}
211
212
c =
av_mallocz
(
sizeof
(
SliceThreadContext
));
213
if
(!c)
214
return
-1;
215
216
c->
workers
=
av_mallocz_array
(thread_count,
sizeof
(
pthread_t
));
217
if
(!c->
workers
) {
218
av_free
(c);
219
return
-1;
220
}
221
222
avctx->
internal
->
thread_ctx
=
c
;
223
c->
current_job
= 0;
224
c->
job_count
= 0;
225
c->
job_size
= 0;
226
c->
done
= 0;
227
pthread_cond_init
(&c->
current_job_cond
,
NULL
);
228
pthread_cond_init
(&c->
last_job_cond
,
NULL
);
229
pthread_mutex_init
(&c->
current_job_lock
,
NULL
);
230
pthread_mutex_lock
(&c->
current_job_lock
);
231
for
(i=0; i<thread_count; i++) {
232
if
(
pthread_create
(&c->
workers
[i],
NULL
,
worker
, avctx)) {
233
avctx->
thread_count
= i;
234
pthread_mutex_unlock
(&c->
current_job_lock
);
235
ff_thread_free
(avctx);
236
return
-1;
237
}
238
}
239
240
thread_park_workers
(c, thread_count);
241
242
avctx->
execute
=
thread_execute
;
243
avctx->
execute2
=
thread_execute2
;
244
return
0;
245
}
246
247
void
ff_thread_report_progress2
(
AVCodecContext
*avctx,
int
field,
int
thread,
int
n
)
248
{
249
SliceThreadContext
*p = avctx->
internal
->
thread_ctx
;
250
int
*entries = p->
entries
;
251
252
pthread_mutex_lock
(&p->
progress_mutex
[thread]);
253
entries[field] +=
n
;
254
pthread_cond_signal
(&p->
progress_cond
[thread]);
255
pthread_mutex_unlock
(&p->
progress_mutex
[thread]);
256
}
257
258
void
ff_thread_await_progress2
(
AVCodecContext
*avctx,
int
field,
int
thread,
int
shift
)
259
{
260
SliceThreadContext
*p = avctx->
internal
->
thread_ctx
;
261
int
*entries = p->
entries
;
262
263
if
(!entries || !field)
return
;
264
265
thread = thread ? thread - 1 : p->
thread_count
- 1;
266
267
pthread_mutex_lock
(&p->
progress_mutex
[thread]);
268
while
((entries[field - 1] - entries[field]) < shift){
269
pthread_cond_wait
(&p->
progress_cond
[thread], &p->
progress_mutex
[thread]);
270
}
271
pthread_mutex_unlock
(&p->
progress_mutex
[thread]);
272
}
273
274
int
ff_alloc_entries
(
AVCodecContext
*avctx,
int
count
)
275
{
276
int
i;
277
278
if
(avctx->
active_thread_type
&
FF_THREAD_SLICE
) {
279
SliceThreadContext
*p = avctx->
internal
->
thread_ctx
;
280
p->
thread_count
= avctx->
thread_count
;
281
p->
entries
=
av_mallocz_array
(count,
sizeof
(
int
));
282
283
p->
progress_mutex
=
av_malloc_array
(p->
thread_count
,
sizeof
(
pthread_mutex_t
));
284
p->
progress_cond
=
av_malloc_array
(p->
thread_count
,
sizeof
(
pthread_cond_t
));
285
286
if
(!p->
entries
|| !p->
progress_mutex
|| !p->
progress_cond
) {
287
av_freep
(&p->
entries
);
288
av_freep
(&p->
progress_mutex
);
289
av_freep
(&p->
progress_cond
);
290
return
AVERROR
(ENOMEM);
291
}
292
p->
entries_count
=
count
;
293
294
for
(i = 0; i < p->
thread_count
; i++) {
295
pthread_mutex_init
(&p->
progress_mutex
[i],
NULL
);
296
pthread_cond_init
(&p->
progress_cond
[i],
NULL
);
297
}
298
}
299
300
return
0;
301
}
302
303
void
ff_reset_entries
(
AVCodecContext
*avctx)
304
{
305
SliceThreadContext
*p = avctx->
internal
->
thread_ctx
;
306
memset(p->
entries
, 0, p->
entries_count
*
sizeof
(
int
));
307
}
Generated on Sun Mar 8 2015 02:34:58 for FFmpeg by
1.8.2