~ubuntu-branches/ubuntu/vivid/gstreamer-vaapi/vivid

« back to all changes in this revision

Viewing changes to ext/libvpx/upstream/vp9/decoder/vp9_thread.c

  • Committer: Package Import Robot
  • Author(s): Vincent Cheng
  • Date: 2014-08-06 23:56:00 UTC
  • mfrom: (0.1.4 sid) (1.1.3)
  • Revision ID: package-import@ubuntu.com-20140806235600-fg1kcmiu67k315q5
Tags: 0.5.9-2
* Remove spurious build-deps: libva-drm1, libavcodec-dev. (Closes: #757283)
* Drop Build-Depends-Indep and build docs unconditionally on all archs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2013 Google Inc. All Rights Reserved.
 
2
//
 
3
// Use of this source code is governed by a BSD-style license
 
4
// that can be found in the COPYING file in the root of the source
 
5
// tree. An additional intellectual property rights grant can be found
 
6
// in the file PATENTS. All contributing project authors may
 
7
// be found in the AUTHORS file in the root of the source tree.
 
8
// -----------------------------------------------------------------------------
 
9
//
 
10
// Multi-threaded worker
 
11
//
 
12
// Original source:
 
13
//  http://git.chromium.org/webm/libwebp.git
 
14
//  100644 blob eff8f2a8c20095aade3c292b0e9292dac6cb3587  src/utils/thread.c
 
15
 
 
16
 
 
17
#include <assert.h>
 
18
#include <string.h>   // for memset()
 
19
#include "./vp9_thread.h"
 
20
 
 
21
#if defined(__cplusplus) || defined(c_plusplus)
 
22
extern "C" {
 
23
#endif
 
24
 
 
25
#if CONFIG_MULTITHREAD
 
26
 
 
27
#if defined(_WIN32)
 
28
 
 
29
//------------------------------------------------------------------------------
 
30
// simplistic pthread emulation layer
 
31
 
 
32
#include <process.h>  // NOLINT
 
33
 
 
34
// _beginthreadex requires __stdcall
 
35
#define THREADFN unsigned int __stdcall
 
36
#define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val)
 
37
 
 
38
static int pthread_create(pthread_t* const thread, const void* attr,
 
39
                          unsigned int (__stdcall *start)(void*), void* arg) {
 
40
  (void)attr;
 
41
  *thread = (pthread_t)_beginthreadex(NULL,   /* void *security */
 
42
                                      0,      /* unsigned stack_size */
 
43
                                      start,
 
44
                                      arg,
 
45
                                      0,      /* unsigned initflag */
 
46
                                      NULL);  /* unsigned *thrdaddr */
 
47
  if (*thread == NULL) return 1;
 
48
  SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL);
 
49
  return 0;
 
50
}
 
51
 
 
52
static int pthread_join(pthread_t thread, void** value_ptr) {
 
53
  (void)value_ptr;
 
54
  return (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0 ||
 
55
          CloseHandle(thread) == 0);
 
56
}
 
57
 
 
58
// Mutex
 
59
static int pthread_mutex_init(pthread_mutex_t* const mutex, void* mutexattr) {
 
60
  (void)mutexattr;
 
61
  InitializeCriticalSection(mutex);
 
62
  return 0;
 
63
}
 
64
 
 
65
static int pthread_mutex_lock(pthread_mutex_t* const mutex) {
 
66
  EnterCriticalSection(mutex);
 
67
  return 0;
 
68
}
 
69
 
 
70
static int pthread_mutex_unlock(pthread_mutex_t* const mutex) {
 
71
  LeaveCriticalSection(mutex);
 
72
  return 0;
 
73
}
 
74
 
 
75
static int pthread_mutex_destroy(pthread_mutex_t* const mutex) {
 
76
  DeleteCriticalSection(mutex);
 
77
  return 0;
 
78
}
 
79
 
 
80
// Condition
 
81
static int pthread_cond_destroy(pthread_cond_t* const condition) {
 
82
  int ok = 1;
 
83
  ok &= (CloseHandle(condition->waiting_sem_) != 0);
 
84
  ok &= (CloseHandle(condition->received_sem_) != 0);
 
85
  ok &= (CloseHandle(condition->signal_event_) != 0);
 
86
  return !ok;
 
87
}
 
88
 
 
89
static int pthread_cond_init(pthread_cond_t* const condition, void* cond_attr) {
 
90
  (void)cond_attr;
 
91
  condition->waiting_sem_ = CreateSemaphore(NULL, 0, 1, NULL);
 
92
  condition->received_sem_ = CreateSemaphore(NULL, 0, 1, NULL);
 
93
  condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL);
 
94
  if (condition->waiting_sem_ == NULL ||
 
95
      condition->received_sem_ == NULL ||
 
96
      condition->signal_event_ == NULL) {
 
97
    pthread_cond_destroy(condition);
 
98
    return 1;
 
99
  }
 
100
  return 0;
 
101
}
 
102
 
 
103
static int pthread_cond_signal(pthread_cond_t* const condition) {
 
104
  int ok = 1;
 
105
  if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) {
 
106
    // a thread is waiting in pthread_cond_wait: allow it to be notified
 
107
    ok = SetEvent(condition->signal_event_);
 
108
    // wait until the event is consumed so the signaler cannot consume
 
109
    // the event via its own pthread_cond_wait.
 
110
    ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) !=
 
111
           WAIT_OBJECT_0);
 
112
  }
 
113
  return !ok;
 
114
}
 
115
 
 
116
static int pthread_cond_wait(pthread_cond_t* const condition,
 
117
                             pthread_mutex_t* const mutex) {
 
118
  int ok;
 
119
  // note that there is a consumer available so the signal isn't dropped in
 
120
  // pthread_cond_signal
 
121
  if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL))
 
122
    return 1;
 
123
  // now unlock the mutex so pthread_cond_signal may be issued
 
124
  pthread_mutex_unlock(mutex);
 
125
  ok = (WaitForSingleObject(condition->signal_event_, INFINITE) ==
 
126
        WAIT_OBJECT_0);
 
127
  ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL);
 
128
  pthread_mutex_lock(mutex);
 
129
  return !ok;
 
130
}
 
131
 
 
132
#else  // _WIN32
 
133
# define THREADFN void*
 
134
# define THREAD_RETURN(val) val
 
135
#endif
 
136
 
 
137
//------------------------------------------------------------------------------
 
138
 
 
139
static THREADFN thread_loop(void *ptr) {    // thread loop
 
140
  VP9Worker* const worker = (VP9Worker*)ptr;
 
141
  int done = 0;
 
142
  while (!done) {
 
143
    pthread_mutex_lock(&worker->mutex_);
 
144
    while (worker->status_ == OK) {   // wait in idling mode
 
145
      pthread_cond_wait(&worker->condition_, &worker->mutex_);
 
146
    }
 
147
    if (worker->status_ == WORK) {
 
148
      vp9_worker_execute(worker);
 
149
      worker->status_ = OK;
 
150
    } else if (worker->status_ == NOT_OK) {   // finish the worker
 
151
      done = 1;
 
152
    }
 
153
    // signal to the main thread that we're done (for Sync())
 
154
    pthread_cond_signal(&worker->condition_);
 
155
    pthread_mutex_unlock(&worker->mutex_);
 
156
  }
 
157
  return THREAD_RETURN(NULL);    // Thread is finished
 
158
}
 
159
 
 
160
// main thread state control
 
161
static void change_state(VP9Worker* const worker,
 
162
                         VP9WorkerStatus new_status) {
 
163
  // no-op when attempting to change state on a thread that didn't come up
 
164
  if (worker->status_ < OK) return;
 
165
 
 
166
  pthread_mutex_lock(&worker->mutex_);
 
167
  // wait for the worker to finish
 
168
  while (worker->status_ != OK) {
 
169
    pthread_cond_wait(&worker->condition_, &worker->mutex_);
 
170
  }
 
171
  // assign new status and release the working thread if needed
 
172
  if (new_status != OK) {
 
173
    worker->status_ = new_status;
 
174
    pthread_cond_signal(&worker->condition_);
 
175
  }
 
176
  pthread_mutex_unlock(&worker->mutex_);
 
177
}
 
178
 
 
179
#endif  // CONFIG_MULTITHREAD
 
180
 
 
181
//------------------------------------------------------------------------------
 
182
 
 
183
void vp9_worker_init(VP9Worker* const worker) {
 
184
  memset(worker, 0, sizeof(*worker));
 
185
  worker->status_ = NOT_OK;
 
186
}
 
187
 
 
188
int vp9_worker_sync(VP9Worker* const worker) {
 
189
#if CONFIG_MULTITHREAD
 
190
  change_state(worker, OK);
 
191
#endif
 
192
  assert(worker->status_ <= OK);
 
193
  return !worker->had_error;
 
194
}
 
195
 
 
196
int vp9_worker_reset(VP9Worker* const worker) {
 
197
  int ok = 1;
 
198
  worker->had_error = 0;
 
199
  if (worker->status_ < OK) {
 
200
#if CONFIG_MULTITHREAD
 
201
    if (pthread_mutex_init(&worker->mutex_, NULL) ||
 
202
        pthread_cond_init(&worker->condition_, NULL)) {
 
203
      return 0;
 
204
    }
 
205
    pthread_mutex_lock(&worker->mutex_);
 
206
    ok = !pthread_create(&worker->thread_, NULL, thread_loop, worker);
 
207
    if (ok) worker->status_ = OK;
 
208
    pthread_mutex_unlock(&worker->mutex_);
 
209
#else
 
210
    worker->status_ = OK;
 
211
#endif
 
212
  } else if (worker->status_ > OK) {
 
213
    ok = vp9_worker_sync(worker);
 
214
  }
 
215
  assert(!ok || (worker->status_ == OK));
 
216
  return ok;
 
217
}
 
218
 
 
219
void vp9_worker_execute(VP9Worker* const worker) {
 
220
  if (worker->hook != NULL) {
 
221
    worker->had_error |= !worker->hook(worker->data1, worker->data2);
 
222
  }
 
223
}
 
224
 
 
225
void vp9_worker_launch(VP9Worker* const worker) {
 
226
#if CONFIG_MULTITHREAD
 
227
  change_state(worker, WORK);
 
228
#else
 
229
  vp9_worker_execute(worker);
 
230
#endif
 
231
}
 
232
 
 
233
void vp9_worker_end(VP9Worker* const worker) {
 
234
  if (worker->status_ >= OK) {
 
235
#if CONFIG_MULTITHREAD
 
236
    change_state(worker, NOT_OK);
 
237
    pthread_join(worker->thread_, NULL);
 
238
    pthread_mutex_destroy(&worker->mutex_);
 
239
    pthread_cond_destroy(&worker->condition_);
 
240
#else
 
241
    worker->status_ = NOT_OK;
 
242
#endif
 
243
  }
 
244
  assert(worker->status_ == NOT_OK);
 
245
}
 
246
 
 
247
//------------------------------------------------------------------------------
 
248
 
 
249
#if defined(__cplusplus) || defined(c_plusplus)
 
250
}    // extern "C"
 
251
#endif