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; | |
f6fa7814 | 201 | dst->framerate = src->framerate; |
2ba45a60 DM |
202 | dst->width = src->width; |
203 | dst->height = src->height; | |
204 | dst->pix_fmt = src->pix_fmt; | |
205 | ||
206 | dst->coded_width = src->coded_width; | |
207 | dst->coded_height = src->coded_height; | |
208 | ||
209 | dst->has_b_frames = src->has_b_frames; | |
210 | dst->idct_algo = src->idct_algo; | |
211 | ||
212 | dst->bits_per_coded_sample = src->bits_per_coded_sample; | |
213 | dst->sample_aspect_ratio = src->sample_aspect_ratio; | |
214 | #if FF_API_AFD | |
215 | FF_DISABLE_DEPRECATION_WARNINGS | |
216 | dst->dtg_active_format = src->dtg_active_format; | |
217 | FF_ENABLE_DEPRECATION_WARNINGS | |
218 | #endif /* FF_API_AFD */ | |
219 | ||
220 | dst->profile = src->profile; | |
221 | dst->level = src->level; | |
222 | ||
223 | dst->bits_per_raw_sample = src->bits_per_raw_sample; | |
224 | dst->ticks_per_frame = src->ticks_per_frame; | |
225 | dst->color_primaries = src->color_primaries; | |
226 | ||
227 | dst->color_trc = src->color_trc; | |
228 | dst->colorspace = src->colorspace; | |
229 | dst->color_range = src->color_range; | |
230 | dst->chroma_sample_location = src->chroma_sample_location; | |
231 | ||
232 | dst->hwaccel = src->hwaccel; | |
233 | dst->hwaccel_context = src->hwaccel_context; | |
234 | ||
235 | dst->channels = src->channels; | |
236 | dst->sample_rate = src->sample_rate; | |
237 | dst->sample_fmt = src->sample_fmt; | |
238 | dst->channel_layout = src->channel_layout; | |
239 | dst->internal->hwaccel_priv_data = src->internal->hwaccel_priv_data; | |
240 | } | |
241 | ||
242 | if (for_user) { | |
243 | dst->delay = src->thread_count - 1; | |
244 | dst->coded_frame = src->coded_frame; | |
245 | } else { | |
246 | if (dst->codec->update_thread_context) | |
247 | err = dst->codec->update_thread_context(dst, src); | |
248 | } | |
249 | ||
250 | return err; | |
251 | } | |
252 | ||
253 | /** | |
254 | * Update the next thread's AVCodecContext with values set by the user. | |
255 | * | |
256 | * @param dst The destination context. | |
257 | * @param src The source context. | |
258 | * @return 0 on success, negative error code on failure | |
259 | */ | |
260 | static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) | |
261 | { | |
262 | #define copy_fields(s, e) memcpy(&dst->s, &src->s, (char*)&dst->e - (char*)&dst->s); | |
263 | dst->flags = src->flags; | |
264 | ||
265 | dst->draw_horiz_band= src->draw_horiz_band; | |
266 | dst->get_buffer2 = src->get_buffer2; | |
267 | #if FF_API_GET_BUFFER | |
268 | FF_DISABLE_DEPRECATION_WARNINGS | |
269 | dst->get_buffer = src->get_buffer; | |
270 | dst->release_buffer = src->release_buffer; | |
271 | FF_ENABLE_DEPRECATION_WARNINGS | |
272 | #endif | |
273 | ||
274 | dst->opaque = src->opaque; | |
275 | dst->debug = src->debug; | |
276 | dst->debug_mv = src->debug_mv; | |
277 | ||
278 | dst->slice_flags = src->slice_flags; | |
279 | dst->flags2 = src->flags2; | |
280 | ||
281 | copy_fields(skip_loop_filter, subtitle_header); | |
282 | ||
283 | dst->frame_number = src->frame_number; | |
284 | dst->reordered_opaque = src->reordered_opaque; | |
285 | dst->thread_safe_callbacks = src->thread_safe_callbacks; | |
286 | ||
287 | if (src->slice_count && src->slice_offset) { | |
288 | if (dst->slice_count < src->slice_count) { | |
f6fa7814 DM |
289 | int err = av_reallocp_array(&dst->slice_offset, src->slice_count, |
290 | sizeof(*dst->slice_offset)); | |
291 | if (err < 0) | |
292 | return err; | |
2ba45a60 DM |
293 | } |
294 | memcpy(dst->slice_offset, src->slice_offset, | |
295 | src->slice_count * sizeof(*dst->slice_offset)); | |
296 | } | |
297 | dst->slice_count = src->slice_count; | |
298 | return 0; | |
299 | #undef copy_fields | |
300 | } | |
301 | ||
302 | /// Releases the buffers that this decoding thread was the last user of. | |
303 | static void release_delayed_buffers(PerThreadContext *p) | |
304 | { | |
305 | FrameThreadContext *fctx = p->parent; | |
306 | ||
307 | while (p->num_released_buffers > 0) { | |
308 | AVFrame *f; | |
309 | ||
310 | pthread_mutex_lock(&fctx->buffer_mutex); | |
311 | ||
312 | // fix extended data in case the caller screwed it up | |
313 | av_assert0(p->avctx->codec_type == AVMEDIA_TYPE_VIDEO || | |
314 | p->avctx->codec_type == AVMEDIA_TYPE_AUDIO); | |
315 | f = &p->released_buffers[--p->num_released_buffers]; | |
316 | f->extended_data = f->data; | |
317 | av_frame_unref(f); | |
318 | ||
319 | pthread_mutex_unlock(&fctx->buffer_mutex); | |
320 | } | |
321 | } | |
322 | ||
323 | static int submit_packet(PerThreadContext *p, AVPacket *avpkt) | |
324 | { | |
325 | FrameThreadContext *fctx = p->parent; | |
326 | PerThreadContext *prev_thread = fctx->prev_thread; | |
327 | const AVCodec *codec = p->avctx->codec; | |
328 | ||
329 | if (!avpkt->size && !(codec->capabilities & CODEC_CAP_DELAY)) return 0; | |
330 | ||
331 | pthread_mutex_lock(&p->mutex); | |
332 | ||
333 | release_delayed_buffers(p); | |
334 | ||
335 | if (prev_thread) { | |
336 | int err; | |
337 | if (prev_thread->state == STATE_SETTING_UP) { | |
338 | pthread_mutex_lock(&prev_thread->progress_mutex); | |
339 | while (prev_thread->state == STATE_SETTING_UP) | |
340 | pthread_cond_wait(&prev_thread->progress_cond, &prev_thread->progress_mutex); | |
341 | pthread_mutex_unlock(&prev_thread->progress_mutex); | |
342 | } | |
343 | ||
344 | err = update_context_from_thread(p->avctx, prev_thread->avctx, 0); | |
345 | if (err) { | |
346 | pthread_mutex_unlock(&p->mutex); | |
347 | return err; | |
348 | } | |
349 | } | |
350 | ||
351 | av_packet_unref(&p->avpkt); | |
352 | av_packet_ref(&p->avpkt, avpkt); | |
353 | ||
354 | p->state = STATE_SETTING_UP; | |
355 | pthread_cond_signal(&p->input_cond); | |
356 | pthread_mutex_unlock(&p->mutex); | |
357 | ||
358 | /* | |
359 | * If the client doesn't have a thread-safe get_buffer(), | |
360 | * then decoding threads call back to the main thread, | |
361 | * and it calls back to the client here. | |
362 | */ | |
363 | ||
364 | FF_DISABLE_DEPRECATION_WARNINGS | |
365 | if (!p->avctx->thread_safe_callbacks && ( | |
366 | p->avctx->get_format != avcodec_default_get_format || | |
367 | #if FF_API_GET_BUFFER | |
368 | p->avctx->get_buffer || | |
369 | #endif | |
370 | p->avctx->get_buffer2 != avcodec_default_get_buffer2)) { | |
371 | FF_ENABLE_DEPRECATION_WARNINGS | |
372 | while (p->state != STATE_SETUP_FINISHED && p->state != STATE_INPUT_READY) { | |
373 | int call_done = 1; | |
374 | pthread_mutex_lock(&p->progress_mutex); | |
375 | while (p->state == STATE_SETTING_UP) | |
376 | pthread_cond_wait(&p->progress_cond, &p->progress_mutex); | |
377 | ||
378 | switch (p->state) { | |
379 | case STATE_GET_BUFFER: | |
380 | p->result = ff_get_buffer(p->avctx, p->requested_frame, p->requested_flags); | |
381 | break; | |
382 | case STATE_GET_FORMAT: | |
383 | p->result_format = ff_get_format(p->avctx, p->available_formats); | |
384 | break; | |
385 | default: | |
386 | call_done = 0; | |
387 | break; | |
388 | } | |
389 | if (call_done) { | |
390 | p->state = STATE_SETTING_UP; | |
391 | pthread_cond_signal(&p->progress_cond); | |
392 | } | |
393 | pthread_mutex_unlock(&p->progress_mutex); | |
394 | } | |
395 | } | |
396 | ||
397 | fctx->prev_thread = p; | |
398 | fctx->next_decoding++; | |
399 | ||
400 | return 0; | |
401 | } | |
402 | ||
403 | int ff_thread_decode_frame(AVCodecContext *avctx, | |
404 | AVFrame *picture, int *got_picture_ptr, | |
405 | AVPacket *avpkt) | |
406 | { | |
407 | FrameThreadContext *fctx = avctx->internal->thread_ctx; | |
408 | int finished = fctx->next_finished; | |
409 | PerThreadContext *p; | |
410 | int err; | |
411 | ||
412 | /* | |
413 | * Submit a packet to the next decoding thread. | |
414 | */ | |
415 | ||
416 | p = &fctx->threads[fctx->next_decoding]; | |
417 | err = update_context_from_user(p->avctx, avctx); | |
418 | if (err) return err; | |
419 | err = submit_packet(p, avpkt); | |
420 | if (err) return err; | |
421 | ||
422 | /* | |
423 | * If we're still receiving the initial packets, don't return a frame. | |
424 | */ | |
425 | ||
426 | if (fctx->next_decoding > (avctx->thread_count-1-(avctx->codec_id == AV_CODEC_ID_FFV1))) | |
427 | fctx->delaying = 0; | |
428 | ||
429 | if (fctx->delaying) { | |
430 | *got_picture_ptr=0; | |
431 | if (avpkt->size) | |
432 | return avpkt->size; | |
433 | } | |
434 | ||
435 | /* | |
436 | * Return the next available frame from the oldest thread. | |
437 | * If we're at the end of the stream, then we have to skip threads that | |
438 | * didn't output a frame, because we don't want to accidentally signal | |
439 | * EOF (avpkt->size == 0 && *got_picture_ptr == 0). | |
440 | */ | |
441 | ||
442 | do { | |
443 | p = &fctx->threads[finished++]; | |
444 | ||
445 | if (p->state != STATE_INPUT_READY) { | |
446 | pthread_mutex_lock(&p->progress_mutex); | |
447 | while (p->state != STATE_INPUT_READY) | |
448 | pthread_cond_wait(&p->output_cond, &p->progress_mutex); | |
449 | pthread_mutex_unlock(&p->progress_mutex); | |
450 | } | |
451 | ||
452 | av_frame_move_ref(picture, p->frame); | |
453 | *got_picture_ptr = p->got_frame; | |
454 | picture->pkt_dts = p->avpkt.dts; | |
455 | ||
456 | /* | |
457 | * A later call with avkpt->size == 0 may loop over all threads, | |
458 | * including this one, searching for a frame to return before being | |
459 | * stopped by the "finished != fctx->next_finished" condition. | |
460 | * Make sure we don't mistakenly return the same frame again. | |
461 | */ | |
462 | p->got_frame = 0; | |
463 | ||
464 | if (finished >= avctx->thread_count) finished = 0; | |
465 | } while (!avpkt->size && !*got_picture_ptr && finished != fctx->next_finished); | |
466 | ||
467 | update_context_from_thread(avctx, p->avctx, 1); | |
468 | ||
469 | if (fctx->next_decoding >= avctx->thread_count) fctx->next_decoding = 0; | |
470 | ||
471 | fctx->next_finished = finished; | |
472 | ||
473 | /* return the size of the consumed packet if no error occurred */ | |
474 | return (p->result >= 0) ? avpkt->size : p->result; | |
475 | } | |
476 | ||
477 | void ff_thread_report_progress(ThreadFrame *f, int n, int field) | |
478 | { | |
479 | PerThreadContext *p; | |
480 | volatile int *progress = f->progress ? (int*)f->progress->data : NULL; | |
481 | ||
482 | if (!progress || progress[field] >= n) return; | |
483 | ||
484 | p = f->owner->internal->thread_ctx; | |
485 | ||
486 | if (f->owner->debug&FF_DEBUG_THREADS) | |
487 | av_log(f->owner, AV_LOG_DEBUG, "%p finished %d field %d\n", progress, n, field); | |
488 | ||
489 | pthread_mutex_lock(&p->progress_mutex); | |
490 | progress[field] = n; | |
491 | pthread_cond_broadcast(&p->progress_cond); | |
492 | pthread_mutex_unlock(&p->progress_mutex); | |
493 | } | |
494 | ||
495 | void ff_thread_await_progress(ThreadFrame *f, int n, int field) | |
496 | { | |
497 | PerThreadContext *p; | |
498 | volatile int *progress = f->progress ? (int*)f->progress->data : NULL; | |
499 | ||
500 | if (!progress || progress[field] >= n) return; | |
501 | ||
502 | p = f->owner->internal->thread_ctx; | |
503 | ||
504 | if (f->owner->debug&FF_DEBUG_THREADS) | |
505 | av_log(f->owner, AV_LOG_DEBUG, "thread awaiting %d field %d from %p\n", n, field, progress); | |
506 | ||
507 | pthread_mutex_lock(&p->progress_mutex); | |
508 | while (progress[field] < n) | |
509 | pthread_cond_wait(&p->progress_cond, &p->progress_mutex); | |
510 | pthread_mutex_unlock(&p->progress_mutex); | |
511 | } | |
512 | ||
513 | void ff_thread_finish_setup(AVCodecContext *avctx) { | |
514 | PerThreadContext *p = avctx->internal->thread_ctx; | |
515 | ||
516 | if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return; | |
517 | ||
518 | if(p->state == STATE_SETUP_FINISHED){ | |
519 | av_log(avctx, AV_LOG_WARNING, "Multiple ff_thread_finish_setup() calls\n"); | |
520 | } | |
521 | ||
522 | pthread_mutex_lock(&p->progress_mutex); | |
523 | p->state = STATE_SETUP_FINISHED; | |
524 | pthread_cond_broadcast(&p->progress_cond); | |
525 | pthread_mutex_unlock(&p->progress_mutex); | |
526 | } | |
527 | ||
528 | /// Waits for all threads to finish. | |
529 | static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count) | |
530 | { | |
531 | int i; | |
532 | ||
533 | for (i = 0; i < thread_count; i++) { | |
534 | PerThreadContext *p = &fctx->threads[i]; | |
535 | ||
536 | if (p->state != STATE_INPUT_READY) { | |
537 | pthread_mutex_lock(&p->progress_mutex); | |
538 | while (p->state != STATE_INPUT_READY) | |
539 | pthread_cond_wait(&p->output_cond, &p->progress_mutex); | |
540 | pthread_mutex_unlock(&p->progress_mutex); | |
541 | } | |
542 | p->got_frame = 0; | |
543 | } | |
544 | } | |
545 | ||
546 | void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) | |
547 | { | |
548 | FrameThreadContext *fctx = avctx->internal->thread_ctx; | |
549 | const AVCodec *codec = avctx->codec; | |
550 | int i; | |
551 | ||
552 | park_frame_worker_threads(fctx, thread_count); | |
553 | ||
554 | if (fctx->prev_thread && fctx->prev_thread != fctx->threads) | |
555 | if (update_context_from_thread(fctx->threads->avctx, fctx->prev_thread->avctx, 0) < 0) { | |
556 | av_log(avctx, AV_LOG_ERROR, "Final thread update failed\n"); | |
557 | fctx->prev_thread->avctx->internal->is_copy = fctx->threads->avctx->internal->is_copy; | |
558 | fctx->threads->avctx->internal->is_copy = 1; | |
559 | } | |
560 | ||
561 | fctx->die = 1; | |
562 | ||
563 | for (i = 0; i < thread_count; i++) { | |
564 | PerThreadContext *p = &fctx->threads[i]; | |
565 | ||
566 | pthread_mutex_lock(&p->mutex); | |
567 | pthread_cond_signal(&p->input_cond); | |
568 | pthread_mutex_unlock(&p->mutex); | |
569 | ||
570 | if (p->thread_init) | |
571 | pthread_join(p->thread, NULL); | |
572 | p->thread_init=0; | |
573 | ||
574 | if (codec->close) | |
575 | codec->close(p->avctx); | |
576 | ||
577 | avctx->codec = NULL; | |
578 | ||
579 | release_delayed_buffers(p); | |
580 | av_frame_free(&p->frame); | |
581 | } | |
582 | ||
583 | for (i = 0; i < thread_count; i++) { | |
584 | PerThreadContext *p = &fctx->threads[i]; | |
585 | ||
586 | pthread_mutex_destroy(&p->mutex); | |
587 | pthread_mutex_destroy(&p->progress_mutex); | |
588 | pthread_cond_destroy(&p->input_cond); | |
589 | pthread_cond_destroy(&p->progress_cond); | |
590 | pthread_cond_destroy(&p->output_cond); | |
591 | av_packet_unref(&p->avpkt); | |
592 | av_freep(&p->released_buffers); | |
593 | ||
594 | if (i) { | |
595 | av_freep(&p->avctx->priv_data); | |
596 | av_freep(&p->avctx->slice_offset); | |
597 | } | |
598 | ||
599 | av_freep(&p->avctx->internal); | |
600 | av_freep(&p->avctx); | |
601 | } | |
602 | ||
603 | av_freep(&fctx->threads); | |
604 | pthread_mutex_destroy(&fctx->buffer_mutex); | |
605 | av_freep(&avctx->internal->thread_ctx); | |
606 | } | |
607 | ||
608 | int ff_frame_thread_init(AVCodecContext *avctx) | |
609 | { | |
610 | int thread_count = avctx->thread_count; | |
611 | const AVCodec *codec = avctx->codec; | |
612 | AVCodecContext *src = avctx; | |
613 | FrameThreadContext *fctx; | |
614 | int i, err = 0; | |
615 | ||
616 | #if HAVE_W32THREADS | |
617 | w32thread_init(); | |
618 | #endif | |
619 | ||
620 | if (!thread_count) { | |
621 | int nb_cpus = av_cpu_count(); | |
622 | if ((avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || avctx->debug_mv) | |
623 | nb_cpus = 1; | |
624 | // use number of cores + 1 as thread count if there is more than one | |
625 | if (nb_cpus > 1) | |
626 | thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS); | |
627 | else | |
628 | thread_count = avctx->thread_count = 1; | |
629 | } | |
630 | ||
631 | if (thread_count <= 1) { | |
632 | avctx->active_thread_type = 0; | |
633 | return 0; | |
634 | } | |
635 | ||
636 | avctx->internal->thread_ctx = fctx = av_mallocz(sizeof(FrameThreadContext)); | |
637 | ||
638 | fctx->threads = av_mallocz_array(thread_count, sizeof(PerThreadContext)); | |
639 | pthread_mutex_init(&fctx->buffer_mutex, NULL); | |
640 | fctx->delaying = 1; | |
641 | ||
642 | for (i = 0; i < thread_count; i++) { | |
643 | AVCodecContext *copy = av_malloc(sizeof(AVCodecContext)); | |
644 | PerThreadContext *p = &fctx->threads[i]; | |
645 | ||
646 | pthread_mutex_init(&p->mutex, NULL); | |
647 | pthread_mutex_init(&p->progress_mutex, NULL); | |
648 | pthread_cond_init(&p->input_cond, NULL); | |
649 | pthread_cond_init(&p->progress_cond, NULL); | |
650 | pthread_cond_init(&p->output_cond, NULL); | |
651 | ||
652 | p->frame = av_frame_alloc(); | |
653 | if (!p->frame) { | |
2ba45a60 | 654 | av_freep(©); |
f6fa7814 | 655 | err = AVERROR(ENOMEM); |
2ba45a60 DM |
656 | goto error; |
657 | } | |
658 | ||
659 | p->parent = fctx; | |
660 | p->avctx = copy; | |
661 | ||
662 | if (!copy) { | |
663 | err = AVERROR(ENOMEM); | |
664 | goto error; | |
665 | } | |
666 | ||
667 | *copy = *src; | |
668 | ||
669 | copy->internal = av_malloc(sizeof(AVCodecInternal)); | |
670 | if (!copy->internal) { | |
671 | err = AVERROR(ENOMEM); | |
672 | goto error; | |
673 | } | |
674 | *copy->internal = *src->internal; | |
675 | copy->internal->thread_ctx = p; | |
676 | copy->internal->pkt = &p->avpkt; | |
677 | ||
678 | if (!i) { | |
679 | src = copy; | |
680 | ||
681 | if (codec->init) | |
682 | err = codec->init(copy); | |
683 | ||
684 | update_context_from_thread(avctx, copy, 1); | |
685 | } else { | |
686 | copy->priv_data = av_malloc(codec->priv_data_size); | |
687 | if (!copy->priv_data) { | |
688 | err = AVERROR(ENOMEM); | |
689 | goto error; | |
690 | } | |
691 | memcpy(copy->priv_data, src->priv_data, codec->priv_data_size); | |
692 | copy->internal->is_copy = 1; | |
693 | ||
694 | if (codec->init_thread_copy) | |
695 | err = codec->init_thread_copy(copy); | |
696 | } | |
697 | ||
698 | if (err) goto error; | |
699 | ||
700 | err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p)); | |
701 | p->thread_init= !err; | |
702 | if(!p->thread_init) | |
703 | goto error; | |
704 | } | |
705 | ||
706 | return 0; | |
707 | ||
708 | error: | |
709 | ff_frame_thread_free(avctx, i+1); | |
710 | ||
711 | return err; | |
712 | } | |
713 | ||
714 | void ff_thread_flush(AVCodecContext *avctx) | |
715 | { | |
716 | int i; | |
717 | FrameThreadContext *fctx = avctx->internal->thread_ctx; | |
718 | ||
719 | if (!fctx) return; | |
720 | ||
721 | park_frame_worker_threads(fctx, avctx->thread_count); | |
722 | if (fctx->prev_thread) { | |
723 | if (fctx->prev_thread != &fctx->threads[0]) | |
724 | update_context_from_thread(fctx->threads[0].avctx, fctx->prev_thread->avctx, 0); | |
725 | } | |
726 | ||
727 | fctx->next_decoding = fctx->next_finished = 0; | |
728 | fctx->delaying = 1; | |
729 | fctx->prev_thread = NULL; | |
730 | for (i = 0; i < avctx->thread_count; i++) { | |
731 | PerThreadContext *p = &fctx->threads[i]; | |
732 | // Make sure decode flush calls with size=0 won't return old frames | |
733 | p->got_frame = 0; | |
734 | av_frame_unref(p->frame); | |
735 | ||
736 | release_delayed_buffers(p); | |
737 | ||
738 | if (avctx->codec->flush) | |
739 | avctx->codec->flush(p->avctx); | |
740 | } | |
741 | } | |
742 | ||
743 | int ff_thread_can_start_frame(AVCodecContext *avctx) | |
744 | { | |
745 | PerThreadContext *p = avctx->internal->thread_ctx; | |
746 | if ((avctx->active_thread_type&FF_THREAD_FRAME) && p->state != STATE_SETTING_UP && | |
747 | (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) { | |
748 | return 0; | |
749 | } | |
750 | return 1; | |
751 | } | |
752 | ||
753 | static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int flags) | |
754 | { | |
755 | PerThreadContext *p = avctx->internal->thread_ctx; | |
756 | int err; | |
757 | ||
758 | f->owner = avctx; | |
759 | ||
760 | ff_init_buffer_info(avctx, f->f); | |
761 | ||
762 | if (!(avctx->active_thread_type & FF_THREAD_FRAME)) | |
763 | return ff_get_buffer(avctx, f->f, flags); | |
764 | ||
765 | if (p->state != STATE_SETTING_UP && | |
766 | (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) { | |
767 | av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n"); | |
768 | return -1; | |
769 | } | |
770 | ||
771 | if (avctx->internal->allocate_progress) { | |
772 | int *progress; | |
773 | f->progress = av_buffer_alloc(2 * sizeof(int)); | |
774 | if (!f->progress) { | |
775 | return AVERROR(ENOMEM); | |
776 | } | |
777 | progress = (int*)f->progress->data; | |
778 | ||
779 | progress[0] = progress[1] = -1; | |
780 | } | |
781 | ||
782 | pthread_mutex_lock(&p->parent->buffer_mutex); | |
783 | FF_DISABLE_DEPRECATION_WARNINGS | |
784 | if (avctx->thread_safe_callbacks || ( | |
785 | #if FF_API_GET_BUFFER | |
786 | !avctx->get_buffer && | |
787 | #endif | |
788 | avctx->get_buffer2 == avcodec_default_get_buffer2)) { | |
789 | FF_ENABLE_DEPRECATION_WARNINGS | |
790 | err = ff_get_buffer(avctx, f->f, flags); | |
791 | } else { | |
792 | pthread_mutex_lock(&p->progress_mutex); | |
793 | p->requested_frame = f->f; | |
794 | p->requested_flags = flags; | |
795 | p->state = STATE_GET_BUFFER; | |
796 | pthread_cond_broadcast(&p->progress_cond); | |
797 | ||
798 | while (p->state != STATE_SETTING_UP) | |
799 | pthread_cond_wait(&p->progress_cond, &p->progress_mutex); | |
800 | ||
801 | err = p->result; | |
802 | ||
803 | pthread_mutex_unlock(&p->progress_mutex); | |
804 | ||
805 | } | |
806 | if (!THREAD_SAFE_CALLBACKS(avctx) && !avctx->codec->update_thread_context) | |
807 | ff_thread_finish_setup(avctx); | |
808 | ||
809 | if (err) | |
810 | av_buffer_unref(&f->progress); | |
811 | ||
812 | pthread_mutex_unlock(&p->parent->buffer_mutex); | |
813 | ||
814 | return err; | |
815 | } | |
816 | ||
817 | enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) | |
818 | { | |
819 | enum AVPixelFormat res; | |
820 | PerThreadContext *p = avctx->internal->thread_ctx; | |
821 | if (!(avctx->active_thread_type & FF_THREAD_FRAME) || avctx->thread_safe_callbacks || | |
822 | avctx->get_format == avcodec_default_get_format) | |
823 | return ff_get_format(avctx, fmt); | |
824 | if (p->state != STATE_SETTING_UP) { | |
825 | av_log(avctx, AV_LOG_ERROR, "get_format() cannot be called after ff_thread_finish_setup()\n"); | |
826 | return -1; | |
827 | } | |
828 | pthread_mutex_lock(&p->progress_mutex); | |
829 | p->available_formats = fmt; | |
830 | p->state = STATE_GET_FORMAT; | |
831 | pthread_cond_broadcast(&p->progress_cond); | |
832 | ||
833 | while (p->state != STATE_SETTING_UP) | |
834 | pthread_cond_wait(&p->progress_cond, &p->progress_mutex); | |
835 | ||
836 | res = p->result_format; | |
837 | ||
838 | pthread_mutex_unlock(&p->progress_mutex); | |
839 | ||
840 | return res; | |
841 | } | |
842 | ||
843 | int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) | |
844 | { | |
845 | int ret = thread_get_buffer_internal(avctx, f, flags); | |
846 | if (ret < 0) | |
847 | av_log(avctx, AV_LOG_ERROR, "thread_get_buffer() failed\n"); | |
848 | return ret; | |
849 | } | |
850 | ||
851 | void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) | |
852 | { | |
853 | PerThreadContext *p = avctx->internal->thread_ctx; | |
854 | FrameThreadContext *fctx; | |
855 | AVFrame *dst, *tmp; | |
856 | FF_DISABLE_DEPRECATION_WARNINGS | |
857 | int can_direct_free = !(avctx->active_thread_type & FF_THREAD_FRAME) || | |
858 | avctx->thread_safe_callbacks || | |
859 | ( | |
860 | #if FF_API_GET_BUFFER | |
861 | !avctx->get_buffer && | |
862 | #endif | |
863 | avctx->get_buffer2 == avcodec_default_get_buffer2); | |
864 | FF_ENABLE_DEPRECATION_WARNINGS | |
865 | ||
866 | if (!f->f || !f->f->buf[0]) | |
867 | return; | |
868 | ||
869 | if (avctx->debug & FF_DEBUG_BUFFERS) | |
870 | av_log(avctx, AV_LOG_DEBUG, "thread_release_buffer called on pic %p\n", f); | |
871 | ||
872 | av_buffer_unref(&f->progress); | |
873 | f->owner = NULL; | |
874 | ||
875 | if (can_direct_free) { | |
876 | av_frame_unref(f->f); | |
877 | return; | |
878 | } | |
879 | ||
880 | fctx = p->parent; | |
881 | pthread_mutex_lock(&fctx->buffer_mutex); | |
882 | ||
883 | if (p->num_released_buffers + 1 >= INT_MAX / sizeof(*p->released_buffers)) | |
884 | goto fail; | |
885 | tmp = av_fast_realloc(p->released_buffers, &p->released_buffers_allocated, | |
886 | (p->num_released_buffers + 1) * | |
887 | sizeof(*p->released_buffers)); | |
888 | if (!tmp) | |
889 | goto fail; | |
890 | p->released_buffers = tmp; | |
891 | ||
892 | dst = &p->released_buffers[p->num_released_buffers]; | |
893 | av_frame_move_ref(dst, f->f); | |
894 | ||
895 | p->num_released_buffers++; | |
896 | ||
897 | fail: | |
898 | pthread_mutex_unlock(&fctx->buffer_mutex); | |
899 | } |