Commit | Line | Data |
---|---|---|
cc14ee03 AK |
1 | /* |
2 | * This file is part of Libav. | |
3 | * | |
4 | * Libav is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU Lesser General Public | |
6 | * License as published by the Free Software Foundation; either | |
7 | * version 2.1 of the License, or (at your option) any later version. | |
8 | * | |
9 | * Libav is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | * Lesser General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU Lesser General Public | |
15 | * License along with Libav; if not, write to the Free Software | |
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
17 | */ | |
18 | ||
19 | /** | |
20 | * @file | |
21 | * Frame multithreading support functions | |
22 | * @see doc/multithreading.txt | |
23 | */ | |
24 | ||
25 | #include "config.h" | |
26 | ||
27 | #include <stdint.h> | |
28 | ||
29 | #if HAVE_PTHREADS | |
30 | #include <pthread.h> | |
31 | #elif HAVE_W32THREADS | |
32 | #include "compat/w32pthreads.h" | |
33 | #endif | |
34 | ||
35 | #include "avcodec.h" | |
36 | #include "internal.h" | |
37 | #include "pthread_internal.h" | |
38 | #include "thread.h" | |
39 | ||
40 | #include "libavutil/avassert.h" | |
41 | #include "libavutil/buffer.h" | |
42 | #include "libavutil/common.h" | |
43 | #include "libavutil/cpu.h" | |
44 | #include "libavutil/frame.h" | |
45 | #include "libavutil/log.h" | |
46 | #include "libavutil/mem.h" | |
47 | ||
48 | /** | |
38ecc370 | 49 | * Context used by codec threads and stored in their AVCodecInternal thread_ctx. |
cc14ee03 AK |
50 | */ |
51 | typedef struct PerThreadContext { | |
52 | struct FrameThreadContext *parent; | |
53 | ||
54 | pthread_t thread; | |
55 | int thread_init; | |
56 | pthread_cond_t input_cond; ///< Used to wait for a new packet from the main thread. | |
57 | pthread_cond_t progress_cond; ///< Used by child threads to wait for progress to change. | |
58 | pthread_cond_t output_cond; ///< Used by the main thread to wait for frames to finish. | |
59 | ||
60 | pthread_mutex_t mutex; ///< Mutex used to protect the contents of the PerThreadContext. | |
61 | pthread_mutex_t progress_mutex; ///< Mutex used to protect frame progress values and progress_cond. | |
62 | ||
63 | AVCodecContext *avctx; ///< Context used to decode packets passed to this thread. | |
64 | ||
65 | AVPacket avpkt; ///< Input packet (for decoding) or output (for encoding). | |
66 | uint8_t *buf; ///< backup storage for packet data when the input packet is not refcounted | |
67 | int allocated_buf_size; ///< Size allocated for buf | |
68 | ||
d351ef47 | 69 | AVFrame *frame; ///< Output frame (for decoding) or input (for encoding). |
cc14ee03 AK |
70 | int got_frame; ///< The output of got_picture_ptr from the last avcodec_decode_video() call. |
71 | int result; ///< The result of the last codec decode/encode() call. | |
72 | ||
73 | enum { | |
74 | STATE_INPUT_READY, ///< Set when the thread is awaiting a packet. | |
75 | STATE_SETTING_UP, ///< Set before the codec has called ff_thread_finish_setup(). | |
76 | STATE_GET_BUFFER, /**< | |
77 | * Set when the codec calls get_buffer(). | |
78 | * State is returned to STATE_SETTING_UP afterwards. | |
79 | */ | |
80 | STATE_SETUP_FINISHED ///< Set after the codec has called ff_thread_finish_setup(). | |
81 | } state; | |
82 | ||
83 | /** | |
84 | * Array of frames passed to ff_thread_release_buffer(). | |
85 | * Frames are released after all threads referencing them are finished. | |
86 | */ | |
87 | AVFrame *released_buffers; | |
88 | int num_released_buffers; | |
89 | int released_buffers_allocated; | |
90 | ||
91 | AVFrame *requested_frame; ///< AVFrame the codec passed to get_buffer() | |
92 | int requested_flags; ///< flags passed to get_buffer() for requested_frame | |
93 | } PerThreadContext; | |
94 | ||
95 | /** | |
38ecc370 | 96 | * Context stored in the client AVCodecInternal thread_ctx. |
cc14ee03 AK |
97 | */ |
98 | typedef struct FrameThreadContext { | |
99 | PerThreadContext *threads; ///< The contexts for each thread. | |
100 | PerThreadContext *prev_thread; ///< The last thread submit_packet() was called on. | |
101 | ||
102 | pthread_mutex_t buffer_mutex; ///< Mutex used to protect get/release_buffer(). | |
103 | ||
104 | int next_decoding; ///< The next context to submit a packet to. | |
105 | int next_finished; ///< The next context to return output from. | |
106 | ||
107 | int delaying; /**< | |
108 | * Set for the first N packets, where N is the number of threads. | |
109 | * While it is set, ff_thread_en/decode_frame won't return any results. | |
110 | */ | |
111 | ||
112 | int die; ///< Set when threads should exit. | |
113 | } FrameThreadContext; | |
114 | ||
115 | /** | |
116 | * Codec worker thread. | |
117 | * | |
118 | * Automatically calls ff_thread_finish_setup() if the codec does | |
119 | * not provide an update_thread_context method, or if the codec returns | |
120 | * before calling it. | |
121 | */ | |
122 | static attribute_align_arg void *frame_worker_thread(void *arg) | |
123 | { | |
124 | PerThreadContext *p = arg; | |
125 | FrameThreadContext *fctx = p->parent; | |
126 | AVCodecContext *avctx = p->avctx; | |
127 | const AVCodec *codec = avctx->codec; | |
128 | ||
129 | while (1) { | |
130 | if (p->state == STATE_INPUT_READY && !fctx->die) { | |
131 | pthread_mutex_lock(&p->mutex); | |
132 | while (p->state == STATE_INPUT_READY && !fctx->die) | |
133 | pthread_cond_wait(&p->input_cond, &p->mutex); | |
134 | pthread_mutex_unlock(&p->mutex); | |
135 | } | |
136 | ||
137 | if (fctx->die) break; | |
138 | ||
139 | if (!codec->update_thread_context && avctx->thread_safe_callbacks) | |
140 | ff_thread_finish_setup(avctx); | |
141 | ||
142 | pthread_mutex_lock(&p->mutex); | |
d351ef47 | 143 | av_frame_unref(p->frame); |
cc14ee03 | 144 | p->got_frame = 0; |
d351ef47 | 145 | p->result = codec->decode(avctx, p->frame, &p->got_frame, &p->avpkt); |
cc14ee03 | 146 | |
9cbf2d78 AK |
147 | if ((p->result < 0 || !p->got_frame) && p->frame->buf[0]) { |
148 | if (avctx->internal->allocate_progress) | |
149 | av_log(avctx, AV_LOG_ERROR, "A frame threaded decoder did not " | |
150 | "free the frame on failure. This is a bug, please report it.\n"); | |
151 | av_frame_unref(p->frame); | |
152 | } | |
153 | ||
cc14ee03 AK |
154 | if (p->state == STATE_SETTING_UP) ff_thread_finish_setup(avctx); |
155 | ||
156 | p->state = STATE_INPUT_READY; | |
157 | ||
158 | pthread_mutex_lock(&p->progress_mutex); | |
159 | pthread_cond_signal(&p->output_cond); | |
160 | pthread_mutex_unlock(&p->progress_mutex); | |
161 | ||
162 | pthread_mutex_unlock(&p->mutex); | |
163 | } | |
164 | ||
165 | return NULL; | |
166 | } | |
167 | ||
168 | /** | |
169 | * Update the next thread's AVCodecContext with values from the reference thread's context. | |
170 | * | |
171 | * @param dst The destination context. | |
172 | * @param src The source context. | |
173 | * @param for_user 0 if the destination is a codec thread, 1 if the destination is the user's thread | |
174 | */ | |
175 | static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, int for_user) | |
176 | { | |
177 | int err = 0; | |
178 | ||
179 | if (dst != src) { | |
180 | dst->time_base = src->time_base; | |
181 | dst->width = src->width; | |
182 | dst->height = src->height; | |
183 | dst->pix_fmt = src->pix_fmt; | |
184 | ||
185 | dst->coded_width = src->coded_width; | |
186 | dst->coded_height = src->coded_height; | |
187 | ||
188 | dst->has_b_frames = src->has_b_frames; | |
189 | dst->idct_algo = src->idct_algo; | |
190 | ||
191 | dst->bits_per_coded_sample = src->bits_per_coded_sample; | |
192 | dst->sample_aspect_ratio = src->sample_aspect_ratio; | |
193 | dst->dtg_active_format = src->dtg_active_format; | |
194 | ||
195 | dst->profile = src->profile; | |
196 | dst->level = src->level; | |
197 | ||
198 | dst->bits_per_raw_sample = src->bits_per_raw_sample; | |
199 | dst->ticks_per_frame = src->ticks_per_frame; | |
200 | dst->color_primaries = src->color_primaries; | |
201 | ||
202 | dst->color_trc = src->color_trc; | |
203 | dst->colorspace = src->colorspace; | |
204 | dst->color_range = src->color_range; | |
205 | dst->chroma_sample_location = src->chroma_sample_location; | |
206 | ||
207 | dst->hwaccel = src->hwaccel; | |
208 | dst->hwaccel_context = src->hwaccel_context; | |
209 | } | |
210 | ||
211 | if (for_user) { | |
212 | dst->coded_frame = src->coded_frame; | |
213 | } else { | |
214 | if (dst->codec->update_thread_context) | |
215 | err = dst->codec->update_thread_context(dst, src); | |
216 | } | |
217 | ||
218 | return err; | |
219 | } | |
220 | ||
221 | /** | |
222 | * Update the next thread's AVCodecContext with values set by the user. | |
223 | * | |
224 | * @param dst The destination context. | |
225 | * @param src The source context. | |
226 | * @return 0 on success, negative error code on failure | |
227 | */ | |
228 | static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) | |
229 | { | |
230 | #define copy_fields(s, e) memcpy(&dst->s, &src->s, (char*)&dst->e - (char*)&dst->s); | |
231 | dst->flags = src->flags; | |
232 | ||
233 | dst->draw_horiz_band= src->draw_horiz_band; | |
234 | dst->get_buffer2 = src->get_buffer2; | |
235 | #if FF_API_GET_BUFFER | |
236 | FF_DISABLE_DEPRECATION_WARNINGS | |
237 | dst->get_buffer = src->get_buffer; | |
238 | dst->release_buffer = src->release_buffer; | |
239 | FF_ENABLE_DEPRECATION_WARNINGS | |
240 | #endif | |
241 | ||
242 | dst->opaque = src->opaque; | |
243 | dst->debug = src->debug; | |
244 | ||
245 | dst->slice_flags = src->slice_flags; | |
246 | dst->flags2 = src->flags2; | |
247 | ||
248 | copy_fields(skip_loop_filter, subtitle_header); | |
249 | ||
250 | dst->frame_number = src->frame_number; | |
251 | dst->reordered_opaque = src->reordered_opaque; | |
252 | ||
253 | if (src->slice_count && src->slice_offset) { | |
254 | if (dst->slice_count < src->slice_count) { | |
255 | int *tmp = av_realloc(dst->slice_offset, src->slice_count * | |
256 | sizeof(*dst->slice_offset)); | |
257 | if (!tmp) { | |
258 | av_free(dst->slice_offset); | |
259 | return AVERROR(ENOMEM); | |
260 | } | |
261 | dst->slice_offset = tmp; | |
262 | } | |
263 | memcpy(dst->slice_offset, src->slice_offset, | |
264 | src->slice_count * sizeof(*dst->slice_offset)); | |
265 | } | |
266 | dst->slice_count = src->slice_count; | |
267 | return 0; | |
268 | #undef copy_fields | |
269 | } | |
270 | ||
271 | /// Releases the buffers that this decoding thread was the last user of. | |
272 | static void release_delayed_buffers(PerThreadContext *p) | |
273 | { | |
274 | FrameThreadContext *fctx = p->parent; | |
275 | ||
276 | while (p->num_released_buffers > 0) { | |
277 | AVFrame *f; | |
278 | ||
279 | pthread_mutex_lock(&fctx->buffer_mutex); | |
280 | ||
281 | // fix extended data in case the caller screwed it up | |
282 | av_assert0(p->avctx->codec_type == AVMEDIA_TYPE_VIDEO); | |
283 | f = &p->released_buffers[--p->num_released_buffers]; | |
284 | f->extended_data = f->data; | |
285 | av_frame_unref(f); | |
286 | ||
287 | pthread_mutex_unlock(&fctx->buffer_mutex); | |
288 | } | |
289 | } | |
290 | ||
291 | static int submit_packet(PerThreadContext *p, AVPacket *avpkt) | |
292 | { | |
293 | FrameThreadContext *fctx = p->parent; | |
294 | PerThreadContext *prev_thread = fctx->prev_thread; | |
295 | const AVCodec *codec = p->avctx->codec; | |
296 | ||
297 | if (!avpkt->size && !(codec->capabilities & CODEC_CAP_DELAY)) return 0; | |
298 | ||
299 | pthread_mutex_lock(&p->mutex); | |
300 | ||
301 | release_delayed_buffers(p); | |
302 | ||
303 | if (prev_thread) { | |
304 | int err; | |
305 | if (prev_thread->state == STATE_SETTING_UP) { | |
306 | pthread_mutex_lock(&prev_thread->progress_mutex); | |
307 | while (prev_thread->state == STATE_SETTING_UP) | |
308 | pthread_cond_wait(&prev_thread->progress_cond, &prev_thread->progress_mutex); | |
309 | pthread_mutex_unlock(&prev_thread->progress_mutex); | |
310 | } | |
311 | ||
312 | err = update_context_from_thread(p->avctx, prev_thread->avctx, 0); | |
313 | if (err) { | |
314 | pthread_mutex_unlock(&p->mutex); | |
315 | return err; | |
316 | } | |
317 | } | |
318 | ||
319 | av_buffer_unref(&p->avpkt.buf); | |
320 | p->avpkt = *avpkt; | |
321 | if (avpkt->buf) | |
322 | p->avpkt.buf = av_buffer_ref(avpkt->buf); | |
323 | else { | |
324 | av_fast_malloc(&p->buf, &p->allocated_buf_size, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); | |
325 | p->avpkt.data = p->buf; | |
326 | memcpy(p->buf, avpkt->data, avpkt->size); | |
327 | memset(p->buf + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); | |
328 | } | |
329 | ||
330 | p->state = STATE_SETTING_UP; | |
331 | pthread_cond_signal(&p->input_cond); | |
332 | pthread_mutex_unlock(&p->mutex); | |
333 | ||
334 | /* | |
335 | * If the client doesn't have a thread-safe get_buffer(), | |
336 | * then decoding threads call back to the main thread, | |
337 | * and it calls back to the client here. | |
338 | */ | |
339 | ||
340 | FF_DISABLE_DEPRECATION_WARNINGS | |
341 | if (!p->avctx->thread_safe_callbacks && ( | |
342 | #if FF_API_GET_BUFFER | |
343 | p->avctx->get_buffer || | |
344 | #endif | |
345 | p->avctx->get_buffer2 != avcodec_default_get_buffer2)) { | |
346 | FF_ENABLE_DEPRECATION_WARNINGS | |
347 | while (p->state != STATE_SETUP_FINISHED && p->state != STATE_INPUT_READY) { | |
348 | pthread_mutex_lock(&p->progress_mutex); | |
349 | while (p->state == STATE_SETTING_UP) | |
350 | pthread_cond_wait(&p->progress_cond, &p->progress_mutex); | |
351 | ||
352 | if (p->state == STATE_GET_BUFFER) { | |
353 | p->result = ff_get_buffer(p->avctx, p->requested_frame, p->requested_flags); | |
354 | p->state = STATE_SETTING_UP; | |
355 | pthread_cond_signal(&p->progress_cond); | |
356 | } | |
357 | pthread_mutex_unlock(&p->progress_mutex); | |
358 | } | |
359 | } | |
360 | ||
361 | fctx->prev_thread = p; | |
362 | fctx->next_decoding++; | |
363 | ||
364 | return 0; | |
365 | } | |
366 | ||
367 | int ff_thread_decode_frame(AVCodecContext *avctx, | |
368 | AVFrame *picture, int *got_picture_ptr, | |
369 | AVPacket *avpkt) | |
370 | { | |
38ecc370 | 371 | FrameThreadContext *fctx = avctx->internal->thread_ctx; |
cc14ee03 AK |
372 | int finished = fctx->next_finished; |
373 | PerThreadContext *p; | |
374 | int err; | |
375 | ||
376 | /* | |
377 | * Submit a packet to the next decoding thread. | |
378 | */ | |
379 | ||
380 | p = &fctx->threads[fctx->next_decoding]; | |
381 | err = update_context_from_user(p->avctx, avctx); | |
382 | if (err) return err; | |
383 | err = submit_packet(p, avpkt); | |
384 | if (err) return err; | |
385 | ||
386 | /* | |
387 | * If we're still receiving the initial packets, don't return a frame. | |
388 | */ | |
389 | ||
390 | if (fctx->delaying) { | |
391 | if (fctx->next_decoding >= (avctx->thread_count-1)) fctx->delaying = 0; | |
392 | ||
393 | *got_picture_ptr=0; | |
394 | if (avpkt->size) | |
395 | return avpkt->size; | |
396 | } | |
397 | ||
398 | /* | |
399 | * Return the next available frame from the oldest thread. | |
400 | * If we're at the end of the stream, then we have to skip threads that | |
401 | * didn't output a frame, because we don't want to accidentally signal | |
402 | * EOF (avpkt->size == 0 && *got_picture_ptr == 0). | |
403 | */ | |
404 | ||
405 | do { | |
406 | p = &fctx->threads[finished++]; | |
407 | ||
408 | if (p->state != STATE_INPUT_READY) { | |
409 | pthread_mutex_lock(&p->progress_mutex); | |
410 | while (p->state != STATE_INPUT_READY) | |
411 | pthread_cond_wait(&p->output_cond, &p->progress_mutex); | |
412 | pthread_mutex_unlock(&p->progress_mutex); | |
413 | } | |
414 | ||
d351ef47 | 415 | av_frame_move_ref(picture, p->frame); |
cc14ee03 AK |
416 | *got_picture_ptr = p->got_frame; |
417 | picture->pkt_dts = p->avpkt.dts; | |
418 | ||
419 | /* | |
420 | * A later call with avkpt->size == 0 may loop over all threads, | |
421 | * including this one, searching for a frame to return before being | |
422 | * stopped by the "finished != fctx->next_finished" condition. | |
423 | * Make sure we don't mistakenly return the same frame again. | |
424 | */ | |
425 | p->got_frame = 0; | |
426 | ||
427 | if (finished >= avctx->thread_count) finished = 0; | |
428 | } while (!avpkt->size && !*got_picture_ptr && finished != fctx->next_finished); | |
429 | ||
430 | update_context_from_thread(avctx, p->avctx, 1); | |
431 | ||
432 | if (fctx->next_decoding >= avctx->thread_count) fctx->next_decoding = 0; | |
433 | ||
434 | fctx->next_finished = finished; | |
435 | ||
436 | /* return the size of the consumed packet if no error occurred */ | |
437 | return (p->result >= 0) ? avpkt->size : p->result; | |
438 | } | |
439 | ||
440 | void ff_thread_report_progress(ThreadFrame *f, int n, int field) | |
441 | { | |
442 | PerThreadContext *p; | |
443 | int *progress = f->progress ? (int*)f->progress->data : NULL; | |
444 | ||
445 | if (!progress || progress[field] >= n) return; | |
446 | ||
38ecc370 | 447 | p = f->owner->internal->thread_ctx; |
cc14ee03 AK |
448 | |
449 | if (f->owner->debug&FF_DEBUG_THREADS) | |
450 | av_log(f->owner, AV_LOG_DEBUG, "%p finished %d field %d\n", progress, n, field); | |
451 | ||
452 | pthread_mutex_lock(&p->progress_mutex); | |
453 | progress[field] = n; | |
454 | pthread_cond_broadcast(&p->progress_cond); | |
455 | pthread_mutex_unlock(&p->progress_mutex); | |
456 | } | |
457 | ||
458 | void ff_thread_await_progress(ThreadFrame *f, int n, int field) | |
459 | { | |
460 | PerThreadContext *p; | |
461 | int *progress = f->progress ? (int*)f->progress->data : NULL; | |
462 | ||
463 | if (!progress || progress[field] >= n) return; | |
464 | ||
38ecc370 | 465 | p = f->owner->internal->thread_ctx; |
cc14ee03 AK |
466 | |
467 | if (f->owner->debug&FF_DEBUG_THREADS) | |
468 | av_log(f->owner, AV_LOG_DEBUG, "thread awaiting %d field %d from %p\n", n, field, progress); | |
469 | ||
470 | pthread_mutex_lock(&p->progress_mutex); | |
471 | while (progress[field] < n) | |
472 | pthread_cond_wait(&p->progress_cond, &p->progress_mutex); | |
473 | pthread_mutex_unlock(&p->progress_mutex); | |
474 | } | |
475 | ||
476 | void ff_thread_finish_setup(AVCodecContext *avctx) { | |
38ecc370 | 477 | PerThreadContext *p = avctx->internal->thread_ctx; |
cc14ee03 AK |
478 | |
479 | if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return; | |
480 | ||
481 | pthread_mutex_lock(&p->progress_mutex); | |
482 | p->state = STATE_SETUP_FINISHED; | |
483 | pthread_cond_broadcast(&p->progress_cond); | |
484 | pthread_mutex_unlock(&p->progress_mutex); | |
485 | } | |
486 | ||
487 | /// Waits for all threads to finish. | |
488 | static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count) | |
489 | { | |
490 | int i; | |
491 | ||
492 | for (i = 0; i < thread_count; i++) { | |
493 | PerThreadContext *p = &fctx->threads[i]; | |
494 | ||
495 | if (p->state != STATE_INPUT_READY) { | |
496 | pthread_mutex_lock(&p->progress_mutex); | |
497 | while (p->state != STATE_INPUT_READY) | |
498 | pthread_cond_wait(&p->output_cond, &p->progress_mutex); | |
499 | pthread_mutex_unlock(&p->progress_mutex); | |
500 | } | |
501 | } | |
502 | } | |
503 | ||
504 | void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) | |
505 | { | |
38ecc370 | 506 | FrameThreadContext *fctx = avctx->internal->thread_ctx; |
cc14ee03 AK |
507 | const AVCodec *codec = avctx->codec; |
508 | int i; | |
509 | ||
510 | park_frame_worker_threads(fctx, thread_count); | |
511 | ||
512 | if (fctx->prev_thread && fctx->prev_thread != fctx->threads) | |
513 | update_context_from_thread(fctx->threads->avctx, fctx->prev_thread->avctx, 0); | |
514 | ||
515 | fctx->die = 1; | |
516 | ||
517 | for (i = 0; i < thread_count; i++) { | |
518 | PerThreadContext *p = &fctx->threads[i]; | |
519 | ||
520 | pthread_mutex_lock(&p->mutex); | |
521 | pthread_cond_signal(&p->input_cond); | |
522 | pthread_mutex_unlock(&p->mutex); | |
523 | ||
524 | if (p->thread_init) | |
525 | pthread_join(p->thread, NULL); | |
526 | ||
527 | if (codec->close) | |
528 | codec->close(p->avctx); | |
529 | ||
530 | avctx->codec = NULL; | |
531 | ||
532 | release_delayed_buffers(p); | |
d351ef47 | 533 | av_frame_free(&p->frame); |
cc14ee03 AK |
534 | } |
535 | ||
536 | for (i = 0; i < thread_count; i++) { | |
537 | PerThreadContext *p = &fctx->threads[i]; | |
538 | ||
539 | pthread_mutex_destroy(&p->mutex); | |
540 | pthread_mutex_destroy(&p->progress_mutex); | |
541 | pthread_cond_destroy(&p->input_cond); | |
542 | pthread_cond_destroy(&p->progress_cond); | |
543 | pthread_cond_destroy(&p->output_cond); | |
544 | av_buffer_unref(&p->avpkt.buf); | |
545 | av_freep(&p->buf); | |
546 | av_freep(&p->released_buffers); | |
547 | ||
548 | if (i) { | |
549 | av_freep(&p->avctx->priv_data); | |
cc14ee03 AK |
550 | av_freep(&p->avctx->slice_offset); |
551 | } | |
552 | ||
38ecc370 | 553 | av_freep(&p->avctx->internal); |
cc14ee03 AK |
554 | av_freep(&p->avctx); |
555 | } | |
556 | ||
557 | av_freep(&fctx->threads); | |
558 | pthread_mutex_destroy(&fctx->buffer_mutex); | |
38ecc370 | 559 | av_freep(&avctx->internal->thread_ctx); |
cc14ee03 AK |
560 | } |
561 | ||
562 | int ff_frame_thread_init(AVCodecContext *avctx) | |
563 | { | |
564 | int thread_count = avctx->thread_count; | |
565 | const AVCodec *codec = avctx->codec; | |
566 | AVCodecContext *src = avctx; | |
567 | FrameThreadContext *fctx; | |
568 | int i, err = 0; | |
569 | ||
570 | #if HAVE_W32THREADS | |
571 | w32thread_init(); | |
572 | #endif | |
573 | ||
574 | if (!thread_count) { | |
575 | int nb_cpus = av_cpu_count(); | |
576 | av_log(avctx, AV_LOG_DEBUG, "detected %d logical cores\n", nb_cpus); | |
577 | // use number of cores + 1 as thread count if there is more than one | |
578 | if (nb_cpus > 1) | |
579 | thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS); | |
580 | else | |
581 | thread_count = avctx->thread_count = 1; | |
582 | } | |
583 | ||
584 | if (thread_count <= 1) { | |
585 | avctx->active_thread_type = 0; | |
586 | return 0; | |
587 | } | |
588 | ||
38ecc370 | 589 | avctx->internal->thread_ctx = fctx = av_mallocz(sizeof(FrameThreadContext)); |
cc14ee03 AK |
590 | |
591 | fctx->threads = av_mallocz(sizeof(PerThreadContext) * thread_count); | |
592 | pthread_mutex_init(&fctx->buffer_mutex, NULL); | |
593 | fctx->delaying = 1; | |
594 | ||
595 | for (i = 0; i < thread_count; i++) { | |
596 | AVCodecContext *copy = av_malloc(sizeof(AVCodecContext)); | |
597 | PerThreadContext *p = &fctx->threads[i]; | |
598 | ||
599 | pthread_mutex_init(&p->mutex, NULL); | |
600 | pthread_mutex_init(&p->progress_mutex, NULL); | |
601 | pthread_cond_init(&p->input_cond, NULL); | |
602 | pthread_cond_init(&p->progress_cond, NULL); | |
603 | pthread_cond_init(&p->output_cond, NULL); | |
604 | ||
d351ef47 AK |
605 | p->frame = av_frame_alloc(); |
606 | if (!p->frame) { | |
607 | err = AVERROR(ENOMEM); | |
608 | goto error; | |
609 | } | |
610 | ||
cc14ee03 AK |
611 | p->parent = fctx; |
612 | p->avctx = copy; | |
613 | ||
614 | if (!copy) { | |
615 | err = AVERROR(ENOMEM); | |
616 | goto error; | |
617 | } | |
618 | ||
619 | *copy = *src; | |
cc14ee03 | 620 | |
38ecc370 AK |
621 | copy->internal = av_malloc(sizeof(AVCodecInternal)); |
622 | if (!copy->internal) { | |
623 | err = AVERROR(ENOMEM); | |
624 | goto error; | |
625 | } | |
626 | *copy->internal = *src->internal; | |
627 | copy->internal->thread_ctx = p; | |
da6506c6 | 628 | copy->internal->pkt = &p->avpkt; |
38ecc370 | 629 | |
cc14ee03 AK |
630 | if (!i) { |
631 | src = copy; | |
632 | ||
633 | if (codec->init) | |
634 | err = codec->init(copy); | |
635 | ||
636 | update_context_from_thread(avctx, copy, 1); | |
637 | } else { | |
638 | copy->priv_data = av_malloc(codec->priv_data_size); | |
639 | if (!copy->priv_data) { | |
640 | err = AVERROR(ENOMEM); | |
641 | goto error; | |
642 | } | |
643 | memcpy(copy->priv_data, src->priv_data, codec->priv_data_size); | |
cc14ee03 AK |
644 | copy->internal->is_copy = 1; |
645 | ||
646 | if (codec->init_thread_copy) | |
647 | err = codec->init_thread_copy(copy); | |
648 | } | |
649 | ||
650 | if (err) goto error; | |
651 | ||
652 | if (!pthread_create(&p->thread, NULL, frame_worker_thread, p)) | |
653 | p->thread_init = 1; | |
654 | } | |
655 | ||
656 | return 0; | |
657 | ||
658 | error: | |
659 | ff_frame_thread_free(avctx, i+1); | |
660 | ||
661 | return err; | |
662 | } | |
663 | ||
664 | void ff_thread_flush(AVCodecContext *avctx) | |
665 | { | |
666 | int i; | |
38ecc370 | 667 | FrameThreadContext *fctx = avctx->internal->thread_ctx; |
cc14ee03 | 668 | |
38ecc370 | 669 | if (!fctx) return; |
cc14ee03 AK |
670 | |
671 | park_frame_worker_threads(fctx, avctx->thread_count); | |
672 | if (fctx->prev_thread) { | |
673 | if (fctx->prev_thread != &fctx->threads[0]) | |
674 | update_context_from_thread(fctx->threads[0].avctx, fctx->prev_thread->avctx, 0); | |
cc14ee03 AK |
675 | } |
676 | ||
677 | fctx->next_decoding = fctx->next_finished = 0; | |
678 | fctx->delaying = 1; | |
679 | fctx->prev_thread = NULL; | |
680 | for (i = 0; i < avctx->thread_count; i++) { | |
681 | PerThreadContext *p = &fctx->threads[i]; | |
682 | // Make sure decode flush calls with size=0 won't return old frames | |
683 | p->got_frame = 0; | |
d351ef47 | 684 | av_frame_unref(p->frame); |
cc14ee03 AK |
685 | |
686 | release_delayed_buffers(p); | |
d1f9563d AK |
687 | |
688 | if (avctx->codec->flush) | |
689 | avctx->codec->flush(p->avctx); | |
cc14ee03 AK |
690 | } |
691 | } | |
692 | ||
693 | int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) | |
694 | { | |
38ecc370 | 695 | PerThreadContext *p = avctx->internal->thread_ctx; |
cc14ee03 AK |
696 | int err; |
697 | ||
698 | f->owner = avctx; | |
699 | ||
700 | if (!(avctx->active_thread_type & FF_THREAD_FRAME)) | |
701 | return ff_get_buffer(avctx, f->f, flags); | |
702 | ||
703 | if (p->state != STATE_SETTING_UP && | |
704 | (avctx->codec->update_thread_context || !avctx->thread_safe_callbacks)) { | |
705 | av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n"); | |
706 | return -1; | |
707 | } | |
708 | ||
709 | if (avctx->internal->allocate_progress) { | |
710 | int *progress; | |
711 | f->progress = av_buffer_alloc(2 * sizeof(int)); | |
712 | if (!f->progress) { | |
713 | return AVERROR(ENOMEM); | |
714 | } | |
715 | progress = (int*)f->progress->data; | |
716 | ||
717 | progress[0] = progress[1] = -1; | |
718 | } | |
719 | ||
720 | pthread_mutex_lock(&p->parent->buffer_mutex); | |
721 | FF_DISABLE_DEPRECATION_WARNINGS | |
722 | if (avctx->thread_safe_callbacks || ( | |
723 | #if FF_API_GET_BUFFER | |
724 | !avctx->get_buffer && | |
725 | #endif | |
726 | avctx->get_buffer2 == avcodec_default_get_buffer2)) { | |
727 | FF_ENABLE_DEPRECATION_WARNINGS | |
728 | err = ff_get_buffer(avctx, f->f, flags); | |
729 | } else { | |
730 | p->requested_frame = f->f; | |
731 | p->requested_flags = flags; | |
732 | p->state = STATE_GET_BUFFER; | |
733 | pthread_mutex_lock(&p->progress_mutex); | |
734 | pthread_cond_signal(&p->progress_cond); | |
735 | ||
736 | while (p->state != STATE_SETTING_UP) | |
737 | pthread_cond_wait(&p->progress_cond, &p->progress_mutex); | |
738 | ||
739 | err = p->result; | |
740 | ||
741 | pthread_mutex_unlock(&p->progress_mutex); | |
742 | ||
743 | } | |
744 | if (!avctx->thread_safe_callbacks && !avctx->codec->update_thread_context) | |
745 | ff_thread_finish_setup(avctx); | |
746 | ||
747 | if (err) | |
748 | av_buffer_unref(&f->progress); | |
749 | ||
750 | pthread_mutex_unlock(&p->parent->buffer_mutex); | |
751 | ||
752 | return err; | |
753 | } | |
754 | ||
755 | void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) | |
756 | { | |
38ecc370 | 757 | PerThreadContext *p = avctx->internal->thread_ctx; |
cc14ee03 AK |
758 | FrameThreadContext *fctx; |
759 | AVFrame *dst, *tmp; | |
760 | FF_DISABLE_DEPRECATION_WARNINGS | |
761 | int can_direct_free = !(avctx->active_thread_type & FF_THREAD_FRAME) || | |
762 | avctx->thread_safe_callbacks || | |
763 | ( | |
764 | #if FF_API_GET_BUFFER | |
765 | !avctx->get_buffer && | |
766 | #endif | |
767 | avctx->get_buffer2 == avcodec_default_get_buffer2); | |
768 | FF_ENABLE_DEPRECATION_WARNINGS | |
769 | ||
a553c6a3 | 770 | if (!f->f->buf[0]) |
cc14ee03 AK |
771 | return; |
772 | ||
773 | if (avctx->debug & FF_DEBUG_BUFFERS) | |
774 | av_log(avctx, AV_LOG_DEBUG, "thread_release_buffer called on pic %p\n", f); | |
775 | ||
776 | av_buffer_unref(&f->progress); | |
777 | f->owner = NULL; | |
778 | ||
779 | if (can_direct_free) { | |
780 | av_frame_unref(f->f); | |
781 | return; | |
782 | } | |
783 | ||
784 | fctx = p->parent; | |
785 | pthread_mutex_lock(&fctx->buffer_mutex); | |
786 | ||
787 | if (p->num_released_buffers + 1 >= INT_MAX / sizeof(*p->released_buffers)) | |
788 | goto fail; | |
789 | tmp = av_fast_realloc(p->released_buffers, &p->released_buffers_allocated, | |
790 | (p->num_released_buffers + 1) * | |
791 | sizeof(*p->released_buffers)); | |
792 | if (!tmp) | |
793 | goto fail; | |
794 | p->released_buffers = tmp; | |
795 | ||
796 | dst = &p->released_buffers[p->num_released_buffers]; | |
797 | av_frame_move_ref(dst, f->f); | |
798 | ||
799 | p->num_released_buffers++; | |
800 | ||
801 | fail: | |
802 | pthread_mutex_unlock(&fctx->buffer_mutex); | |
803 | } |