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_t
)(AVCodecContext
*c
, void *arg
);
30 typedef struct ThreadContext
{
38 pthread_cond_t last_job_cond
;
39 pthread_cond_t current_job_cond
;
40 pthread_mutex_t current_job_lock
;
45 static void* attribute_align_arg
worker(void *v
)
47 AVCodecContext
*avctx
= v
;
48 ThreadContext
*c
= avctx
->thread_opaque
;
49 int our_job
= c
->job_count
;
50 int thread_count
= avctx
->thread_count
;
53 pthread_mutex_lock(&c
->current_job_lock
);
54 self_id
= c
->current_job
++;
56 while (our_job
>= c
->job_count
) {
57 if (c
->current_job
== thread_count
+ c
->job_count
)
58 pthread_cond_signal(&c
->last_job_cond
);
60 pthread_cond_wait(&c
->current_job_cond
, &c
->current_job_lock
);
64 pthread_mutex_unlock(&c
->current_job_lock
);
68 pthread_mutex_unlock(&c
->current_job_lock
);
70 c
->rets
[our_job
%c
->rets_count
] = c
->func(avctx
, c
->args
[our_job
]);
72 pthread_mutex_lock(&c
->current_job_lock
);
73 our_job
= c
->current_job
++;
77 static av_always_inline
void avcodec_thread_park_workers(ThreadContext
*c
, int thread_count
)
79 pthread_cond_wait(&c
->last_job_cond
, &c
->current_job_lock
);
80 pthread_mutex_unlock(&c
->current_job_lock
);
83 void avcodec_thread_free(AVCodecContext
*avctx
)
85 ThreadContext
*c
= avctx
->thread_opaque
;
88 pthread_mutex_lock(&c
->current_job_lock
);
90 pthread_cond_broadcast(&c
->current_job_cond
);
91 pthread_mutex_unlock(&c
->current_job_lock
);
93 for (i
=0; i
<avctx
->thread_count
; i
++)
94 pthread_join(c
->workers
[i
], NULL
);
96 pthread_mutex_destroy(&c
->current_job_lock
);
97 pthread_cond_destroy(&c
->current_job_cond
);
98 pthread_cond_destroy(&c
->last_job_cond
);
100 av_freep(&avctx
->thread_opaque
);
103 int avcodec_thread_execute(AVCodecContext
*avctx
, action_t
* func
, void **arg
, int *ret
, int job_count
)
105 ThreadContext
*c
= avctx
->thread_opaque
;
111 pthread_mutex_lock(&c
->current_job_lock
);
113 c
->current_job
= avctx
->thread_count
;
114 c
->job_count
= job_count
;
119 c
->rets_count
= job_count
;
121 c
->rets
= &dummy_ret
;
124 pthread_cond_broadcast(&c
->current_job_cond
);
126 avcodec_thread_park_workers(c
, avctx
->thread_count
);
131 int avcodec_thread_init(AVCodecContext
*avctx
, int thread_count
)
136 c
= av_mallocz(sizeof(ThreadContext
));
140 c
->workers
= av_mallocz(sizeof(pthread_t
)*thread_count
);
146 avctx
->thread_opaque
= c
;
147 avctx
->thread_count
= thread_count
;
151 pthread_cond_init(&c
->current_job_cond
, NULL
);
152 pthread_cond_init(&c
->last_job_cond
, NULL
);
153 pthread_mutex_init(&c
->current_job_lock
, NULL
);
154 pthread_mutex_lock(&c
->current_job_lock
);
155 for (i
=0; i
<thread_count
; i
++) {
156 if(pthread_create(&c
->workers
[i
], NULL
, worker
, avctx
)) {
157 avctx
->thread_count
= i
;
158 pthread_mutex_unlock(&c
->current_job_lock
);
159 avcodec_thread_free(avctx
);
164 avcodec_thread_park_workers(c
, thread_count
);
166 avctx
->execute
= avcodec_thread_execute
;