| @@ -41,6 +41,11 @@ typedef int (action_func)(AVCodecContext *c, void *arg); · 40 unmodified lines |
| 41 | 41 | typedef int (action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr); |
| 42 | 42 | typedef int (main_func)(AVCodecContext *c); |
| 43 | 43 | |
| 44 | +typedef struct Progress { |
| 45 | + pthread_cond_t cond; |
| 46 | + pthread_mutex_t mutex; |
| 47 | +} Progress; |
| 48 | + |
| 44 | 49 | typedef struct SliceThreadContext { |
| 45 | 50 | AVSliceThread *thread; |
| 46 | 51 | action_func *func; |
| @@ -53,8 +58,7 @@ typedef struct SliceThreadContext { · 6 unmodified lines |
| 53 | 58 | int *entries; |
| 54 | 59 | int entries_count; |
| 55 | 60 | int thread_count; |
| 56 | | − pthread_cond_t *progress_cond; |
| 57 | | − pthread_mutex_t *progress_mutex; |
| 61 | + Progress *progress; |
| 58 | 62 | } SliceThreadContext; |
| 59 | 63 | |
| 60 | 64 | static void main_function(void *priv) { |
| @@ -83,13 +87,13 @@ void ff_slice_thread_free(AVCodecContext *avctx) · 22 unmodified lines |
| 83 | 87 | avpriv_slicethread_free(&c->thread); |
| 84 | 88 | |
| 85 | 89 | for (i = 0; i < c->thread_count; i++) { |
| 86 | | − pthread_mutex_destroy(&c->progress_mutex[i]); |
| 87 | | − pthread_cond_destroy(&c->progress_cond[i]); |
| 90 | + Progress *const progress = &c->progress[i]; |
| 91 | + pthread_mutex_destroy(&progress->mutex); |
| 92 | + pthread_cond_destroy(&progress->cond); |
| 88 | 93 | } |
| 89 | 94 | |
| 90 | 95 | av_freep(&c->entries); |
| 91 | | − av_freep(&c->progress_mutex); |
| 92 | | − av_freep(&c->progress_cond); |
| 96 | + av_freep(&c->progress); |
| 93 | 97 | av_freep(&avctx->internal->thread_ctx); |
| 94 | 98 | } |
| 95 | 99 | |
| @@ -172,65 +176,82 @@ int ff_slice_thread_init(AVCodecContext *avctx) · 76 unmodified lines |
| 172 | 176 | return 0; |
| 173 | 177 | } |
| 174 | 178 | |
| 179 | +int av_cold ff_slice_thread_init_progress(AVCodecContext *avctx) |
| 180 | +{ |
| 181 | + SliceThreadContext *const p = avctx->internal->thread_ctx; |
| 182 | + int err, i = 0, thread_count = avctx->thread_count; |
| 183 | + |
| 184 | + p->progress = av_calloc(thread_count, sizeof(*p->progress)); |
| 185 | + if (!p->progress) { |
| 186 | + err = AVERROR(ENOMEM); |
| 187 | + goto fail; |
| 188 | + } |
| 189 | + |
| 190 | + for (; i < thread_count; i++) { |
| 191 | + Progress *const progress = &p->progress[i]; |
| 192 | + err = pthread_mutex_init(&progress->mutex, NULL); |
| 193 | + if (err) { |
| 194 | + err = AVERROR(err); |
| 195 | + goto fail; |
| 196 | + } |
| 197 | + err = pthread_cond_init (&progress->cond, NULL); |
| 198 | + if (err) { |
| 199 | + err = AVERROR(err); |
| 200 | + pthread_mutex_destroy(&progress->mutex); |
| 201 | + goto fail; |
| 202 | + } |
| 203 | + } |
| 204 | + err = 0; |
| 205 | +fail: |
| 206 | + p->thread_count = i; |
| 207 | + return err; |
| 208 | +} |
| 209 | + |
| 175 | 210 | void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n) |
| 176 | 211 | { |
| 177 | 212 | SliceThreadContext *p = avctx->internal->thread_ctx; |
| 213 | + Progress *const progress = &p->progress[thread]; |
| 178 | 214 | int *entries = p->entries; |
| 179 | 215 | |
| 180 | | − pthread_mutex_lock(&p->progress_mutex[thread]); |
| 216 | + pthread_mutex_lock(&progress->mutex); |
| 181 | 217 | entries[field] +=n; |
| 182 | | − pthread_cond_signal(&p->progress_cond[thread]); |
| 183 | | − pthread_mutex_unlock(&p->progress_mutex[thread]); |
| 218 | + pthread_cond_signal(&progress->cond); |
| 219 | + pthread_mutex_unlock(&progress->mutex); |
| 184 | 220 | } |
| 185 | 221 | |
| 186 | 222 | void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift) |
| 187 | 223 | { |
| 188 | 224 | SliceThreadContext *p = avctx->internal->thread_ctx; |
| 225 | + Progress *progress; |
| 189 | 226 | int *entries = p->entries; |
| 190 | 227 | |
| 191 | 228 | if (!entries || !field) return; |
| 192 | 229 | |
| 193 | 230 | thread = thread ? thread - 1 : p->thread_count - 1; |
| 231 | + progress = &p->progress[thread]; |
| 194 | 232 | |
| 195 | | − pthread_mutex_lock(&p->progress_mutex[thread]); |
| 233 | + pthread_mutex_lock(&progress->mutex); |
| 196 | 234 | while ((entries[field - 1] - entries[field]) < shift){ |
| 197 | | − pthread_cond_wait(&p->progress_cond[thread], &p->progress_mutex[thread]); |
| 235 | + pthread_cond_wait(&progress->cond, &progress->mutex); |
| 198 | 236 | } |
| 199 | | − pthread_mutex_unlock(&p->progress_mutex[thread]); |
| 237 | + pthread_mutex_unlock(&progress->mutex); |
| 200 | 238 | } |
| 201 | 239 | |
| 202 | 240 | int ff_alloc_entries(AVCodecContext *avctx, int count) |
| 203 | 241 | { |
| 204 | | − int i; |
| 205 | | − |
| 206 | 242 | if (avctx->active_thread_type & FF_THREAD_SLICE) { |
| 207 | 243 | SliceThreadContext *p = avctx->internal->thread_ctx; |
| 208 | 244 | |
| 209 | 245 | if (p->entries) { |
| 210 | | − av_assert0(p->thread_count == avctx->thread_count); |
| 211 | 246 | av_freep(&p->entries); |
| 212 | 247 | } |
| 213 | 248 | |
| 214 | | − p->thread_count = avctx->thread_count; |
| 215 | 249 | p->entries = av_calloc(count, sizeof(*p->entries)); |
| 216 | | − |
| 217 | | − if (!p->progress_mutex) { |
| 218 | | − p->progress_mutex = av_malloc_array(p->thread_count, sizeof(pthread_mutex_t)); |
| 219 | | − p->progress_cond = av_malloc_array(p->thread_count, sizeof(pthread_cond_t)); |
| 220 | | − } |
| 221 | | − |
| 222 | | − if (!p->entries || !p->progress_mutex || !p->progress_cond) { |
| 223 | | − av_freep(&p->entries); |
| 224 | | − av_freep(&p->progress_mutex); |
| 225 | | − av_freep(&p->progress_cond); |
| 250 | + if (!p->entries) { |
| 251 | + p->entries_count = 0; |
| 226 | 252 | return AVERROR(ENOMEM); |
| 227 | 253 | } |
| 228 | 254 | p->entries_count = count; |
| 229 | | − |
| 230 | | − for (i = 0; i < p->thread_count; i++) { |
| 231 | | − pthread_mutex_init(&p->progress_mutex[i], NULL); |
| 232 | | − pthread_cond_init(&p->progress_cond[i], NULL); |
| 233 | | − } |
| 234 | 255 | } |
| 235 | 256 | |
| 236 | 257 | return 0; |