2 * Copyright (c) 2004 Roman Shaposhnik
4 * Many thanks to Steven M. Schultz for providing clever ideas and
5 * to Michael Niedermayer <michaelni@gmx.at> for writing initial
8 * This file is part of FFmpeg.
10 * FFmpeg is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * FFmpeg is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with FFmpeg; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 typedef int (action_func
)(AVCodecContext
*c
, void *arg
);
29 typedef int (action_func2
)(AVCodecContext
*c
, void *arg
, int jobnr
, int threadnr
);
31 typedef struct ThreadContext
{
41 pthread_cond_t last_job_cond
;
42 pthread_cond_t current_job_cond
;
43 pthread_mutex_t current_job_lock
;
48 static void* attribute_align_arg
worker(void *v
)
50 AVCodecContext
*avctx
= v
;
51 ThreadContext
*c
= avctx
->thread_opaque
;
52 int our_job
= c
->job_count
;
53 int thread_count
= avctx
->thread_count
;
56 pthread_mutex_lock(&c
->current_job_lock
);
57 self_id
= c
->current_job
++;
59 while (our_job
>= c
->job_count
) {
60 if (c
->current_job
== thread_count
+ c
->job_count
)
61 pthread_cond_signal(&c
->last_job_cond
);
63 pthread_cond_wait(&c
->current_job_cond
, &c
->current_job_lock
);
67 pthread_mutex_unlock(&c
->current_job_lock
);
71 pthread_mutex_unlock(&c
->current_job_lock
);
73 c
->rets
[our_job
%c
->rets_count
] = c
->func
? c
->func(avctx
, (char*)c
->args
+ our_job
*c
->job_size
):
74 c
->func2(avctx
, c
->args
, our_job
, self_id
);
76 pthread_mutex_lock(&c
->current_job_lock
);
77 our_job
= c
->current_job
++;
81 static av_always_inline
void avcodec_thread_park_workers(ThreadContext
*c
, int thread_count
)
83 pthread_cond_wait(&c
->last_job_cond
, &c
->current_job_lock
);
84 pthread_mutex_unlock(&c
->current_job_lock
);
87 void avcodec_thread_free(AVCodecContext
*avctx
)
89 ThreadContext
*c
= avctx
->thread_opaque
;
92 pthread_mutex_lock(&c
->current_job_lock
);
94 pthread_cond_broadcast(&c
->current_job_cond
);
95 pthread_mutex_unlock(&c
->current_job_lock
);
97 for (i
=0; i
<avctx
->thread_count
; i
++)
98 pthread_join(c
->workers
[i
], NULL
);
100 pthread_mutex_destroy(&c
->current_job_lock
);
101 pthread_cond_destroy(&c
->current_job_cond
);
102 pthread_cond_destroy(&c
->last_job_cond
);
104 av_freep(&avctx
->thread_opaque
);
107 int avcodec_thread_execute(AVCodecContext
*avctx
, action_func
* func
, void *arg
, int *ret
, int job_count
, int job_size
)
109 ThreadContext
*c
= avctx
->thread_opaque
;
115 pthread_mutex_lock(&c
->current_job_lock
);
117 c
->current_job
= avctx
->thread_count
;
118 c
->job_count
= job_count
;
119 c
->job_size
= job_size
;
124 c
->rets_count
= job_count
;
126 c
->rets
= &dummy_ret
;
129 pthread_cond_broadcast(&c
->current_job_cond
);
131 avcodec_thread_park_workers(c
, avctx
->thread_count
);
136 int avcodec_thread_execute2(AVCodecContext
*avctx
, action_func2
* func2
, void *arg
, int *ret
, int job_count
)
138 ThreadContext
*c
= avctx
->thread_opaque
;
140 return avcodec_thread_execute(avctx
, NULL
, arg
, ret
, job_count
, 0);
143 int avcodec_thread_init(AVCodecContext
*avctx
, int thread_count
)
148 c
= av_mallocz(sizeof(ThreadContext
));
152 c
->workers
= av_mallocz(sizeof(pthread_t
)*thread_count
);
158 avctx
->thread_opaque
= c
;
159 avctx
->thread_count
= thread_count
;
164 pthread_cond_init(&c
->current_job_cond
, NULL
);
165 pthread_cond_init(&c
->last_job_cond
, NULL
);
166 pthread_mutex_init(&c
->current_job_lock
, NULL
);
167 pthread_mutex_lock(&c
->current_job_lock
);
168 for (i
=0; i
<thread_count
; i
++) {
169 if(pthread_create(&c
->workers
[i
], NULL
, worker
, avctx
)) {
170 avctx
->thread_count
= i
;
171 pthread_mutex_unlock(&c
->current_job_lock
);
172 avcodec_thread_free(avctx
);
177 avcodec_thread_park_workers(c
, thread_count
);
179 avctx
->execute
= avcodec_thread_execute
;
180 avctx
->execute2
= avcodec_thread_execute2
;