~ubuntu-branches/ubuntu/jaunty/xvidcap/jaunty-proposed

« back to all changes in this revision

Viewing changes to ffmpeg/libavcodec/pthread.c

  • Committer: Bazaar Package Importer
  • Author(s): John Dong
  • Date: 2008-02-25 15:47:12 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080225154712-qvr11ekcea4c9ry8
Tags: 1.1.6-0.1ubuntu1
* Merge from debian-multimedia (LP: #120003), Ubuntu Changes:
 - For ffmpeg-related build-deps, remove cvs from package names.
 - Standards-Version 3.7.3
 - Maintainer Spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2004 Roman Shaposhnik.
 
3
 *
 
4
 * Many thanks to Steven M. Schultz for providing clever ideas and
 
5
 * to Michael Niedermayer <michaelni@gmx.at> for writing initial
 
6
 * implementation.
 
7
 *
 
8
 * This file is part of FFmpeg.
 
9
 *
 
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.
 
14
 *
 
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.
 
19
 *
 
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
 
23
 *
 
24
 */
 
25
#include <pthread.h>
 
26
 
 
27
#include "avcodec.h"
 
28
#include "common.h"
 
29
 
 
30
typedef int (action_t)(AVCodecContext *c, void *arg);
 
31
 
 
32
typedef struct ThreadContext {
 
33
    pthread_t *workers;
 
34
    action_t *func;
 
35
    void **args;
 
36
    int *rets;
 
37
    int rets_count;
 
38
    int job_count;
 
39
 
 
40
    pthread_cond_t last_job_cond;
 
41
    pthread_cond_t current_job_cond;
 
42
    pthread_mutex_t current_job_lock;
 
43
    int current_job;
 
44
    int done;
 
45
} ThreadContext;
 
46
 
 
47
static void* worker(void *v)
 
48
{
 
49
    AVCodecContext *avctx = v;
 
50
    ThreadContext *c = avctx->thread_opaque;
 
51
    int our_job = c->job_count;
 
52
    int thread_count = avctx->thread_count;
 
53
    int self_id;
 
54
 
 
55
    pthread_mutex_lock(&c->current_job_lock);
 
56
    self_id = c->current_job++;
 
57
    for (;;){
 
58
        while (our_job >= c->job_count) {
 
59
            if (c->current_job == thread_count + c->job_count)
 
60
                pthread_cond_signal(&c->last_job_cond);
 
61
 
 
62
            pthread_cond_wait(&c->current_job_cond, &c->current_job_lock);
 
63
            our_job = self_id;
 
64
 
 
65
            if (c->done) {
 
66
                pthread_mutex_unlock(&c->current_job_lock);
 
67
                return NULL;
 
68
            }
 
69
        }
 
70
        pthread_mutex_unlock(&c->current_job_lock);
 
71
 
 
72
        c->rets[our_job%c->rets_count] = c->func(avctx, c->args[our_job]);
 
73
 
 
74
        pthread_mutex_lock(&c->current_job_lock);
 
75
        our_job = c->current_job++;
 
76
    }
 
77
}
 
78
 
 
79
static av_always_inline void avcodec_thread_park_workers(ThreadContext *c, int thread_count)
 
80
{
 
81
    pthread_cond_wait(&c->last_job_cond, &c->current_job_lock);
 
82
    pthread_mutex_unlock(&c->current_job_lock);
 
83
}
 
84
 
 
85
void avcodec_thread_free(AVCodecContext *avctx)
 
86
{
 
87
    ThreadContext *c = avctx->thread_opaque;
 
88
    int i;
 
89
 
 
90
    pthread_mutex_lock(&c->current_job_lock);
 
91
    c->done = 1;
 
92
    pthread_cond_broadcast(&c->current_job_cond);
 
93
    pthread_mutex_unlock(&c->current_job_lock);
 
94
 
 
95
    for (i=0; i<avctx->thread_count; i++)
 
96
         pthread_join(c->workers[i], NULL);
 
97
 
 
98
    pthread_mutex_destroy(&c->current_job_lock);
 
99
    pthread_cond_destroy(&c->current_job_cond);
 
100
    pthread_cond_destroy(&c->last_job_cond);
 
101
    av_free(c->workers);
 
102
    av_free(c);
 
103
}
 
104
 
 
105
int avcodec_thread_execute(AVCodecContext *avctx, action_t* func, void **arg, int *ret, int job_count)
 
106
{
 
107
    ThreadContext *c= avctx->thread_opaque;
 
108
    int dummy_ret;
 
109
 
 
110
    if (job_count <= 0)
 
111
        return 0;
 
112
 
 
113
    pthread_mutex_lock(&c->current_job_lock);
 
114
 
 
115
    c->current_job = avctx->thread_count;
 
116
    c->job_count = job_count;
 
117
    c->args = arg;
 
118
    c->func = func;
 
119
    if (ret) {
 
120
        c->rets = ret;
 
121
        c->rets_count = job_count;
 
122
    } else {
 
123
        c->rets = &dummy_ret;
 
124
        c->rets_count = 1;
 
125
    }
 
126
    pthread_cond_broadcast(&c->current_job_cond);
 
127
 
 
128
    avcodec_thread_park_workers(c, avctx->thread_count);
 
129
 
 
130
    return 0;
 
131
}
 
132
 
 
133
int avcodec_thread_init(AVCodecContext *avctx, int thread_count)
 
134
{
 
135
    int i;
 
136
    ThreadContext *c;
 
137
 
 
138
    c = av_mallocz(sizeof(ThreadContext));
 
139
    if (!c)
 
140
        return -1;
 
141
 
 
142
    c->workers = av_mallocz(sizeof(pthread_t)*thread_count);
 
143
    if (!c->workers) {
 
144
        av_free(c);
 
145
        return -1;
 
146
    }
 
147
 
 
148
    avctx->thread_opaque = c;
 
149
    avctx->thread_count = thread_count;
 
150
    c->current_job = 0;
 
151
    c->job_count = 0;
 
152
    c->done = 0;
 
153
    pthread_cond_init(&c->current_job_cond, NULL);
 
154
    pthread_cond_init(&c->last_job_cond, NULL);
 
155
    pthread_mutex_init(&c->current_job_lock, NULL);
 
156
    pthread_mutex_lock(&c->current_job_lock);
 
157
    for (i=0; i<thread_count; i++) {
 
158
        if(pthread_create(&c->workers[i], NULL, worker, avctx)) {
 
159
           avctx->thread_count = i;
 
160
           pthread_mutex_unlock(&c->current_job_lock);
 
161
           avcodec_thread_free(avctx);
 
162
           return -1;
 
163
        }
 
164
    }
 
165
 
 
166
    avcodec_thread_park_workers(c, thread_count);
 
167
 
 
168
    avctx->execute = avcodec_thread_execute;
 
169
    return 0;
 
170
}