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