Statistics
| Branch: | Revision:

ffmpeg / libavcodec / pthread.c @ 94d85eaf

History | View | Annotate | Download (4.6 KB)

1 9c3d33d6 Michael Niedermayer
/*
2 a8eb52a8 Roman Shaposhnik
 * Copyright (c) 2004 Roman Shaposhnik.
3 115329f1 Diego Biurrun
 *
4 a8eb52a8 Roman Shaposhnik
 * Many thanks to Steven M. Schultz for providing clever ideas and
5
 * to Michael Niedermayer <michaelni@gmx.at> for writing initial
6
 * implementation.
7 9c3d33d6 Michael Niedermayer
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20 5509bffa Diego Biurrun
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 9c3d33d6 Michael Niedermayer
 *
22
 */
23
#include <pthread.h>
24
25
#include "avcodec.h"
26
#include "common.h"
27
28 a8eb52a8 Roman Shaposhnik
typedef int (action_t)(AVCodecContext *c, void *arg);
29 399cec2f Michael Niedermayer
30 a8eb52a8 Roman Shaposhnik
typedef struct ThreadContext {
31
    pthread_t *workers;
32
    action_t *func;
33
    void **args;
34
    int *rets;
35
    int rets_count;
36 399cec2f Michael Niedermayer
    int job_count;
37 115329f1 Diego Biurrun
38 a8eb52a8 Roman Shaposhnik
    pthread_cond_t last_job_cond;
39
    pthread_cond_t current_job_cond;
40
    pthread_mutex_t current_job_lock;
41
    int current_job;
42
    int done;
43
} ThreadContext;
44
45 115329f1 Diego Biurrun
static void* worker(void *v)
46 a8eb52a8 Roman Shaposhnik
{
47
    AVCodecContext *avctx = v;
48
    ThreadContext *c = avctx->thread_opaque;
49
    int our_job = c->job_count;
50
    int thread_count = avctx->thread_count;
51
    int self_id;
52
53
    pthread_mutex_lock(&c->current_job_lock);
54
    self_id = c->current_job++;
55 115329f1 Diego Biurrun
    for (;;){
56 bb270c08 Diego Biurrun
        while (our_job >= c->job_count) {
57
            if (c->current_job == thread_count + c->job_count)
58
                pthread_cond_signal(&c->last_job_cond);
59 115329f1 Diego Biurrun
60 bb270c08 Diego Biurrun
            pthread_cond_wait(&c->current_job_cond, &c->current_job_lock);
61 a8eb52a8 Roman Shaposhnik
            our_job = self_id;
62 115329f1 Diego Biurrun
63 bb270c08 Diego Biurrun
            if (c->done) {
64
                pthread_mutex_unlock(&c->current_job_lock);
65
                return NULL;
66
            }
67
        }
68
        pthread_mutex_unlock(&c->current_job_lock);
69 115329f1 Diego Biurrun
70 bb270c08 Diego Biurrun
        c->rets[our_job%c->rets_count] = c->func(avctx, c->args[our_job]);
71 115329f1 Diego Biurrun
72 bb270c08 Diego Biurrun
        pthread_mutex_lock(&c->current_job_lock);
73
        our_job = c->current_job++;
74 9c3d33d6 Michael Niedermayer
    }
75
}
76
77 a8eb52a8 Roman Shaposhnik
static always_inline void avcodec_thread_park_workers(ThreadContext *c, int thread_count)
78
{
79
    pthread_cond_wait(&c->last_job_cond, &c->current_job_lock);
80
    pthread_mutex_unlock(&c->current_job_lock);
81 9c3d33d6 Michael Niedermayer
}
82
83 115329f1 Diego Biurrun
void avcodec_thread_free(AVCodecContext *avctx)
84 a8eb52a8 Roman Shaposhnik
{
85
    ThreadContext *c = avctx->thread_opaque;
86
    int i;
87 115329f1 Diego Biurrun
88 a8eb52a8 Roman Shaposhnik
    pthread_mutex_lock(&c->current_job_lock);
89
    c->done = 1;
90 12013f67 Michael Niedermayer
    pthread_cond_broadcast(&c->current_job_cond);
91 a8eb52a8 Roman Shaposhnik
    pthread_mutex_unlock(&c->current_job_lock);
92
93
    for (i=0; i<avctx->thread_count; i++)
94
         pthread_join(c->workers[i], NULL);
95
96
    pthread_mutex_destroy(&c->current_job_lock);
97
    pthread_cond_destroy(&c->current_job_cond);
98
    pthread_cond_destroy(&c->last_job_cond);
99
    av_free(c->workers);
100 12013f67 Michael Niedermayer
    av_free(c);
101 a8eb52a8 Roman Shaposhnik
}
102 399cec2f Michael Niedermayer
103 115329f1 Diego Biurrun
int avcodec_thread_execute(AVCodecContext *avctx, action_t* func, void **arg, int *ret, int job_count)
104 a8eb52a8 Roman Shaposhnik
{
105
    ThreadContext *c= avctx->thread_opaque;
106
    int dummy_ret;
107 115329f1 Diego Biurrun
108 a8eb52a8 Roman Shaposhnik
    if (job_count <= 0)
109
        return 0;
110 115329f1 Diego Biurrun
111 a8eb52a8 Roman Shaposhnik
    pthread_mutex_lock(&c->current_job_lock);
112
113
    c->current_job = avctx->thread_count;
114
    c->job_count = job_count;
115
    c->args = arg;
116
    c->func = func;
117
    if (ret) {
118
        c->rets = ret;
119 bb270c08 Diego Biurrun
        c->rets_count = job_count;
120 115329f1 Diego Biurrun
    } else {
121 a8eb52a8 Roman Shaposhnik
        c->rets = &dummy_ret;
122 bb270c08 Diego Biurrun
        c->rets_count = 1;
123 9c3d33d6 Michael Niedermayer
    }
124 a8eb52a8 Roman Shaposhnik
    pthread_cond_broadcast(&c->current_job_cond);
125 399cec2f Michael Niedermayer
126 a8eb52a8 Roman Shaposhnik
    avcodec_thread_park_workers(c, avctx->thread_count);
127 115329f1 Diego Biurrun
128 9c3d33d6 Michael Niedermayer
    return 0;
129
}
130
131 115329f1 Diego Biurrun
int avcodec_thread_init(AVCodecContext *avctx, int thread_count)
132 a8eb52a8 Roman Shaposhnik
{
133 9c3d33d6 Michael Niedermayer
    int i;
134
    ThreadContext *c;
135
136 a8eb52a8 Roman Shaposhnik
    c = av_mallocz(sizeof(ThreadContext));
137
    if (!c)
138
        return -1;
139 115329f1 Diego Biurrun
140 a8eb52a8 Roman Shaposhnik
    c->workers = av_mallocz(sizeof(pthread_t)*thread_count);
141
    if (!c->workers) {
142
        av_free(c);
143
        return -1;
144
    }
145 9c3d33d6 Michael Niedermayer
146 a8eb52a8 Roman Shaposhnik
    avctx->thread_opaque = c;
147
    avctx->thread_count = thread_count;
148
    c->current_job = 0;
149
    c->job_count = 0;
150
    c->done = 0;
151 115329f1 Diego Biurrun
    pthread_cond_init(&c->current_job_cond, NULL);
152 a8eb52a8 Roman Shaposhnik
    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 115329f1 Diego Biurrun
    for (i=0; i<thread_count; i++) {
156 a8eb52a8 Roman Shaposhnik
        if(pthread_create(&c->workers[i], NULL, worker, avctx)) {
157 bb270c08 Diego Biurrun
           avctx->thread_count = i;
158
           pthread_mutex_unlock(&c->current_job_lock);
159 a8eb52a8 Roman Shaposhnik
           avcodec_thread_free(avctx);
160
           return -1;
161
        }
162 9c3d33d6 Michael Niedermayer
    }
163 115329f1 Diego Biurrun
164 a8eb52a8 Roman Shaposhnik
    avcodec_thread_park_workers(c, thread_count);
165 115329f1 Diego Biurrun
166 a8eb52a8 Roman Shaposhnik
    avctx->execute = avcodec_thread_execute;
167 9c3d33d6 Michael Niedermayer
    return 0;
168
}