2 * This file is part of Libav.
4 * Libav 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.
9 * Libav 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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with Libav; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Slice multithreading support functions
22 * @see doc/multithreading.txt
30 #include "compat/w32pthreads.h"
35 #include "pthread_internal.h"
38 #include "libavutil/common.h"
39 #include "libavutil/cpu.h"
40 #include "libavutil/mem.h"
42 typedef int (action_func
)(AVCodecContext
*c
, void *arg
);
43 typedef int (action_func2
)(AVCodecContext
*c
, void *arg
, int jobnr
, int threadnr
);
45 typedef struct SliceThreadContext
{
55 pthread_cond_t last_job_cond
;
56 pthread_cond_t current_job_cond
;
57 pthread_mutex_t current_job_lock
;
58 unsigned current_execute
;
63 static void* attribute_align_arg
worker(void *v
)
65 AVCodecContext
*avctx
= v
;
66 SliceThreadContext
*c
= avctx
->internal
->thread_ctx
;
67 unsigned last_execute
= 0;
68 int our_job
= c
->job_count
;
69 int thread_count
= avctx
->thread_count
;
72 pthread_mutex_lock(&c
->current_job_lock
);
73 self_id
= c
->current_job
++;
75 while (our_job
>= c
->job_count
) {
76 if (c
->current_job
== thread_count
+ c
->job_count
)
77 pthread_cond_signal(&c
->last_job_cond
);
79 while (last_execute
== c
->current_execute
&& !c
->done
)
80 pthread_cond_wait(&c
->current_job_cond
, &c
->current_job_lock
);
81 last_execute
= c
->current_execute
;
85 pthread_mutex_unlock(&c
->current_job_lock
);
89 pthread_mutex_unlock(&c
->current_job_lock
);
91 c
->rets
[our_job
%c
->rets_count
] = c
->func
? c
->func(avctx
, (char*)c
->args
+ our_job
*c
->job_size
):
92 c
->func2(avctx
, c
->args
, our_job
, self_id
);
94 pthread_mutex_lock(&c
->current_job_lock
);
95 our_job
= c
->current_job
++;
99 void ff_slice_thread_free(AVCodecContext
*avctx
)
101 SliceThreadContext
*c
= avctx
->internal
->thread_ctx
;
104 pthread_mutex_lock(&c
->current_job_lock
);
106 pthread_cond_broadcast(&c
->current_job_cond
);
107 pthread_mutex_unlock(&c
->current_job_lock
);
109 for (i
=0; i
<avctx
->thread_count
; i
++)
110 pthread_join(c
->workers
[i
], NULL
);
112 pthread_mutex_destroy(&c
->current_job_lock
);
113 pthread_cond_destroy(&c
->current_job_cond
);
114 pthread_cond_destroy(&c
->last_job_cond
);
116 av_freep(&avctx
->internal
->thread_ctx
);
119 static av_always_inline
void thread_park_workers(SliceThreadContext
*c
, int thread_count
)
121 while (c
->current_job
!= thread_count
+ c
->job_count
)
122 pthread_cond_wait(&c
->last_job_cond
, &c
->current_job_lock
);
123 pthread_mutex_unlock(&c
->current_job_lock
);
126 static int thread_execute(AVCodecContext
*avctx
, action_func
* func
, void *arg
, int *ret
, int job_count
, int job_size
)
128 SliceThreadContext
*c
= avctx
->internal
->thread_ctx
;
131 if (!(avctx
->active_thread_type
&FF_THREAD_SLICE
) || avctx
->thread_count
<= 1)
132 return avcodec_default_execute(avctx
, func
, arg
, ret
, job_count
, job_size
);
137 pthread_mutex_lock(&c
->current_job_lock
);
139 c
->current_job
= avctx
->thread_count
;
140 c
->job_count
= job_count
;
141 c
->job_size
= job_size
;
146 c
->rets_count
= job_count
;
148 c
->rets
= &dummy_ret
;
151 c
->current_execute
++;
152 pthread_cond_broadcast(&c
->current_job_cond
);
154 thread_park_workers(c
, avctx
->thread_count
);
159 static int thread_execute2(AVCodecContext
*avctx
, action_func2
* func2
, void *arg
, int *ret
, int job_count
)
161 SliceThreadContext
*c
= avctx
->internal
->thread_ctx
;
163 return thread_execute(avctx
, NULL
, arg
, ret
, job_count
, 0);
166 int ff_slice_thread_init(AVCodecContext
*avctx
)
169 SliceThreadContext
*c
;
170 int thread_count
= avctx
->thread_count
;
173 int nb_cpus
= av_cpu_count();
174 av_log(avctx
, AV_LOG_DEBUG
, "detected %d logical cores\n", nb_cpus
);
175 // use number of cores + 1 as thread count if there is more than one
177 thread_count
= avctx
->thread_count
= FFMIN(nb_cpus
+ 1, MAX_AUTO_THREADS
);
179 thread_count
= avctx
->thread_count
= 1;
182 if (thread_count
<= 1) {
183 avctx
->active_thread_type
= 0;
187 c
= av_mallocz(sizeof(SliceThreadContext
));
191 c
->workers
= av_mallocz(sizeof(pthread_t
)*thread_count
);
197 avctx
->internal
->thread_ctx
= c
;
202 pthread_cond_init(&c
->current_job_cond
, NULL
);
203 pthread_cond_init(&c
->last_job_cond
, NULL
);
204 pthread_mutex_init(&c
->current_job_lock
, NULL
);
205 pthread_mutex_lock(&c
->current_job_lock
);
206 for (i
=0; i
<thread_count
; i
++) {
207 if(pthread_create(&c
->workers
[i
], NULL
, worker
, avctx
)) {
208 avctx
->thread_count
= i
;
209 pthread_mutex_unlock(&c
->current_job_lock
);
210 ff_thread_free(avctx
);
215 thread_park_workers(c
, thread_count
);
217 avctx
->execute
= thread_execute
;
218 avctx
->execute2
= thread_execute2
;