* commit 'cc14ee03a7b91c69343f8d60c9e089a1950eeadb':
lavc: split slice and frame threading functions into separate files
Conflicts:
libavcodec/Makefile
libavcodec/pthread.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
... | ... |
@@ -801,9 +801,9 @@ OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o |
801 | 801 |
OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o |
802 | 802 |
|
803 | 803 |
# thread libraries |
804 |
-OBJS-$(HAVE_PTHREADS) += pthread.o |
|
805 |
-OBJS-$(HAVE_W32THREADS) += pthread.o |
|
806 |
-OBJS-$(HAVE_OS2THREADS) += pthread.o |
|
804 |
+OBJS-$(HAVE_PTHREADS) += pthread.o pthread_slice.o pthread_frame.o |
|
805 |
+OBJS-$(HAVE_W32THREADS) += pthread.o pthread_slice.o pthread_frame.o |
|
806 |
+OBJS-$(HAVE_OS2THREADS) += pthread.o pthread_slice.o pthread_frame.o |
|
807 | 807 |
|
808 | 808 |
OBJS-$(CONFIG_FRAME_THREAD_ENCODER) += frame_thread_encoder.o |
809 | 809 |
|
... | ... |
@@ -29,1052 +29,10 @@ |
29 | 29 |
* @see doc/multithreading.txt |
30 | 30 |
*/ |
31 | 31 |
|
32 |
-#include "config.h" |
|
33 |
- |
|
34 | 32 |
#include "avcodec.h" |
35 | 33 |
#include "internal.h" |
34 |
+#include "pthread_internal.h" |
|
36 | 35 |
#include "thread.h" |
37 |
-#include "libavutil/avassert.h" |
|
38 |
-#include "libavutil/common.h" |
|
39 |
-#include "libavutil/cpu.h" |
|
40 |
-#include "libavutil/internal.h" |
|
41 |
- |
|
42 |
-#if HAVE_PTHREADS |
|
43 |
-#include <pthread.h> |
|
44 |
-#elif HAVE_W32THREADS |
|
45 |
-#include "compat/w32pthreads.h" |
|
46 |
-#elif HAVE_OS2THREADS |
|
47 |
-#include "compat/os2threads.h" |
|
48 |
-#endif |
|
49 |
- |
|
50 |
-typedef int (action_func)(AVCodecContext *c, void *arg); |
|
51 |
-typedef int (action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr); |
|
52 |
- |
|
53 |
-typedef struct ThreadContext { |
|
54 |
- pthread_t *workers; |
|
55 |
- action_func *func; |
|
56 |
- action_func2 *func2; |
|
57 |
- void *args; |
|
58 |
- int *rets; |
|
59 |
- int rets_count; |
|
60 |
- int job_count; |
|
61 |
- int job_size; |
|
62 |
- |
|
63 |
- pthread_cond_t last_job_cond; |
|
64 |
- pthread_cond_t current_job_cond; |
|
65 |
- pthread_mutex_t current_job_lock; |
|
66 |
- unsigned current_execute; |
|
67 |
- int current_job; |
|
68 |
- int done; |
|
69 |
- |
|
70 |
- int *entries; |
|
71 |
- int entries_count; |
|
72 |
- int thread_count; |
|
73 |
- pthread_cond_t *progress_cond; |
|
74 |
- pthread_mutex_t *progress_mutex; |
|
75 |
-} ThreadContext; |
|
76 |
- |
|
77 |
-/** |
|
78 |
- * Context used by codec threads and stored in their AVCodecContext thread_opaque. |
|
79 |
- */ |
|
80 |
-typedef struct PerThreadContext { |
|
81 |
- struct FrameThreadContext *parent; |
|
82 |
- |
|
83 |
- pthread_t thread; |
|
84 |
- int thread_init; |
|
85 |
- pthread_cond_t input_cond; ///< Used to wait for a new packet from the main thread. |
|
86 |
- pthread_cond_t progress_cond; ///< Used by child threads to wait for progress to change. |
|
87 |
- pthread_cond_t output_cond; ///< Used by the main thread to wait for frames to finish. |
|
88 |
- |
|
89 |
- pthread_mutex_t mutex; ///< Mutex used to protect the contents of the PerThreadContext. |
|
90 |
- pthread_mutex_t progress_mutex; ///< Mutex used to protect frame progress values and progress_cond. |
|
91 |
- |
|
92 |
- AVCodecContext *avctx; ///< Context used to decode packets passed to this thread. |
|
93 |
- |
|
94 |
- AVPacket avpkt; ///< Input packet (for decoding) or output (for encoding). |
|
95 |
- uint8_t *buf; ///< backup storage for packet data when the input packet is not refcounted |
|
96 |
- int allocated_buf_size; ///< Size allocated for buf |
|
97 |
- |
|
98 |
- AVFrame frame; ///< Output frame (for decoding) or input (for encoding). |
|
99 |
- int got_frame; ///< The output of got_picture_ptr from the last avcodec_decode_video() call. |
|
100 |
- int result; ///< The result of the last codec decode/encode() call. |
|
101 |
- |
|
102 |
- enum { |
|
103 |
- STATE_INPUT_READY, ///< Set when the thread is awaiting a packet. |
|
104 |
- STATE_SETTING_UP, ///< Set before the codec has called ff_thread_finish_setup(). |
|
105 |
- STATE_GET_BUFFER, /**< |
|
106 |
- * Set when the codec calls get_buffer(). |
|
107 |
- * State is returned to STATE_SETTING_UP afterwards. |
|
108 |
- */ |
|
109 |
- STATE_GET_FORMAT, /**< |
|
110 |
- * Set when the codec calls get_format(). |
|
111 |
- * State is returned to STATE_SETTING_UP afterwards. |
|
112 |
- */ |
|
113 |
- STATE_SETUP_FINISHED ///< Set after the codec has called ff_thread_finish_setup(). |
|
114 |
- } state; |
|
115 |
- |
|
116 |
- /** |
|
117 |
- * Array of frames passed to ff_thread_release_buffer(). |
|
118 |
- * Frames are released after all threads referencing them are finished. |
|
119 |
- */ |
|
120 |
- AVFrame *released_buffers; |
|
121 |
- int num_released_buffers; |
|
122 |
- int released_buffers_allocated; |
|
123 |
- |
|
124 |
- AVFrame *requested_frame; ///< AVFrame the codec passed to get_buffer() |
|
125 |
- int requested_flags; ///< flags passed to get_buffer() for requested_frame |
|
126 |
- |
|
127 |
- const enum AVPixelFormat *available_formats; ///< Format array for get_format() |
|
128 |
- enum AVPixelFormat result_format; ///< get_format() result |
|
129 |
-} PerThreadContext; |
|
130 |
- |
|
131 |
-/** |
|
132 |
- * Context stored in the client AVCodecContext thread_opaque. |
|
133 |
- */ |
|
134 |
-typedef struct FrameThreadContext { |
|
135 |
- PerThreadContext *threads; ///< The contexts for each thread. |
|
136 |
- PerThreadContext *prev_thread; ///< The last thread submit_packet() was called on. |
|
137 |
- |
|
138 |
- pthread_mutex_t buffer_mutex; ///< Mutex used to protect get/release_buffer(). |
|
139 |
- |
|
140 |
- int next_decoding; ///< The next context to submit a packet to. |
|
141 |
- int next_finished; ///< The next context to return output from. |
|
142 |
- |
|
143 |
- int delaying; /**< |
|
144 |
- * Set for the first N packets, where N is the number of threads. |
|
145 |
- * While it is set, ff_thread_en/decode_frame won't return any results. |
|
146 |
- */ |
|
147 |
- |
|
148 |
- int die; ///< Set when threads should exit. |
|
149 |
-} FrameThreadContext; |
|
150 |
- |
|
151 |
- |
|
152 |
-/* H264 slice threading seems to be buggy with more than 16 threads, |
|
153 |
- * limit the number of threads to 16 for automatic detection */ |
|
154 |
-#define MAX_AUTO_THREADS 16 |
|
155 |
- |
|
156 |
-static void* attribute_align_arg worker(void *v) |
|
157 |
-{ |
|
158 |
- AVCodecContext *avctx = v; |
|
159 |
- ThreadContext *c = avctx->thread_opaque; |
|
160 |
- unsigned last_execute = 0; |
|
161 |
- int our_job = c->job_count; |
|
162 |
- int thread_count = avctx->thread_count; |
|
163 |
- int self_id; |
|
164 |
- |
|
165 |
- pthread_mutex_lock(&c->current_job_lock); |
|
166 |
- self_id = c->current_job++; |
|
167 |
- for (;;){ |
|
168 |
- while (our_job >= c->job_count) { |
|
169 |
- if (c->current_job == thread_count + c->job_count) |
|
170 |
- pthread_cond_signal(&c->last_job_cond); |
|
171 |
- |
|
172 |
- while (last_execute == c->current_execute && !c->done) |
|
173 |
- pthread_cond_wait(&c->current_job_cond, &c->current_job_lock); |
|
174 |
- last_execute = c->current_execute; |
|
175 |
- our_job = self_id; |
|
176 |
- |
|
177 |
- if (c->done) { |
|
178 |
- pthread_mutex_unlock(&c->current_job_lock); |
|
179 |
- return NULL; |
|
180 |
- } |
|
181 |
- } |
|
182 |
- pthread_mutex_unlock(&c->current_job_lock); |
|
183 |
- |
|
184 |
- c->rets[our_job%c->rets_count] = c->func ? c->func(avctx, (char*)c->args + our_job*c->job_size): |
|
185 |
- c->func2(avctx, c->args, our_job, self_id); |
|
186 |
- |
|
187 |
- pthread_mutex_lock(&c->current_job_lock); |
|
188 |
- our_job = c->current_job++; |
|
189 |
- } |
|
190 |
-} |
|
191 |
- |
|
192 |
-static av_always_inline void thread_park_workers(ThreadContext *c, int thread_count) |
|
193 |
-{ |
|
194 |
- while (c->current_job != thread_count + c->job_count) |
|
195 |
- pthread_cond_wait(&c->last_job_cond, &c->current_job_lock); |
|
196 |
- pthread_mutex_unlock(&c->current_job_lock); |
|
197 |
-} |
|
198 |
- |
|
199 |
-static void thread_free(AVCodecContext *avctx) |
|
200 |
-{ |
|
201 |
- ThreadContext *c = avctx->thread_opaque; |
|
202 |
- int i; |
|
203 |
- |
|
204 |
- pthread_mutex_lock(&c->current_job_lock); |
|
205 |
- c->done = 1; |
|
206 |
- pthread_cond_broadcast(&c->current_job_cond); |
|
207 |
- pthread_mutex_unlock(&c->current_job_lock); |
|
208 |
- |
|
209 |
- for (i=0; i<avctx->thread_count; i++) |
|
210 |
- pthread_join(c->workers[i], NULL); |
|
211 |
- |
|
212 |
- pthread_mutex_destroy(&c->current_job_lock); |
|
213 |
- pthread_cond_destroy(&c->current_job_cond); |
|
214 |
- pthread_cond_destroy(&c->last_job_cond); |
|
215 |
- av_free(c->workers); |
|
216 |
- av_freep(&avctx->thread_opaque); |
|
217 |
-} |
|
218 |
- |
|
219 |
-static int thread_execute(AVCodecContext *avctx, action_func* func, void *arg, int *ret, int job_count, int job_size) |
|
220 |
-{ |
|
221 |
- ThreadContext *c= avctx->thread_opaque; |
|
222 |
- int dummy_ret; |
|
223 |
- |
|
224 |
- if (!(avctx->active_thread_type&FF_THREAD_SLICE) || avctx->thread_count <= 1) |
|
225 |
- return avcodec_default_execute(avctx, func, arg, ret, job_count, job_size); |
|
226 |
- |
|
227 |
- if (job_count <= 0) |
|
228 |
- return 0; |
|
229 |
- |
|
230 |
- pthread_mutex_lock(&c->current_job_lock); |
|
231 |
- |
|
232 |
- c->current_job = avctx->thread_count; |
|
233 |
- c->job_count = job_count; |
|
234 |
- c->job_size = job_size; |
|
235 |
- c->args = arg; |
|
236 |
- c->func = func; |
|
237 |
- if (ret) { |
|
238 |
- c->rets = ret; |
|
239 |
- c->rets_count = job_count; |
|
240 |
- } else { |
|
241 |
- c->rets = &dummy_ret; |
|
242 |
- c->rets_count = 1; |
|
243 |
- } |
|
244 |
- c->current_execute++; |
|
245 |
- pthread_cond_broadcast(&c->current_job_cond); |
|
246 |
- |
|
247 |
- thread_park_workers(c, avctx->thread_count); |
|
248 |
- |
|
249 |
- return 0; |
|
250 |
-} |
|
251 |
- |
|
252 |
-static int thread_execute2(AVCodecContext *avctx, action_func2* func2, void *arg, int *ret, int job_count) |
|
253 |
-{ |
|
254 |
- ThreadContext *c= avctx->thread_opaque; |
|
255 |
- c->func2 = func2; |
|
256 |
- return thread_execute(avctx, NULL, arg, ret, job_count, 0); |
|
257 |
-} |
|
258 |
- |
|
259 |
-static int thread_init_internal(AVCodecContext *avctx) |
|
260 |
-{ |
|
261 |
- int i; |
|
262 |
- ThreadContext *c; |
|
263 |
- int thread_count = avctx->thread_count; |
|
264 |
- |
|
265 |
- if (!thread_count) { |
|
266 |
- int nb_cpus = av_cpu_count(); |
|
267 |
- if (avctx->height) |
|
268 |
- nb_cpus = FFMIN(nb_cpus, (avctx->height+15)/16); |
|
269 |
- // use number of cores + 1 as thread count if there is more than one |
|
270 |
- if (nb_cpus > 1) |
|
271 |
- thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS); |
|
272 |
- else |
|
273 |
- thread_count = avctx->thread_count = 1; |
|
274 |
- } |
|
275 |
- |
|
276 |
- if (thread_count <= 1) { |
|
277 |
- avctx->active_thread_type = 0; |
|
278 |
- return 0; |
|
279 |
- } |
|
280 |
- |
|
281 |
- c = av_mallocz(sizeof(ThreadContext)); |
|
282 |
- if (!c) |
|
283 |
- return -1; |
|
284 |
- |
|
285 |
- c->workers = av_mallocz(sizeof(pthread_t)*thread_count); |
|
286 |
- if (!c->workers) { |
|
287 |
- av_free(c); |
|
288 |
- return -1; |
|
289 |
- } |
|
290 |
- |
|
291 |
- avctx->thread_opaque = c; |
|
292 |
- c->current_job = 0; |
|
293 |
- c->job_count = 0; |
|
294 |
- c->job_size = 0; |
|
295 |
- c->done = 0; |
|
296 |
- pthread_cond_init(&c->current_job_cond, NULL); |
|
297 |
- pthread_cond_init(&c->last_job_cond, NULL); |
|
298 |
- pthread_mutex_init(&c->current_job_lock, NULL); |
|
299 |
- pthread_mutex_lock(&c->current_job_lock); |
|
300 |
- for (i=0; i<thread_count; i++) { |
|
301 |
- if(pthread_create(&c->workers[i], NULL, worker, avctx)) { |
|
302 |
- avctx->thread_count = i; |
|
303 |
- pthread_mutex_unlock(&c->current_job_lock); |
|
304 |
- ff_thread_free(avctx); |
|
305 |
- return -1; |
|
306 |
- } |
|
307 |
- } |
|
308 |
- |
|
309 |
- thread_park_workers(c, thread_count); |
|
310 |
- |
|
311 |
- avctx->execute = thread_execute; |
|
312 |
- avctx->execute2 = thread_execute2; |
|
313 |
- return 0; |
|
314 |
-} |
|
315 |
- |
|
316 |
-#define THREAD_SAFE_CALLBACKS(avctx) \ |
|
317 |
-((avctx)->thread_safe_callbacks || (!(avctx)->get_buffer && (avctx)->get_buffer2 == avcodec_default_get_buffer2)) |
|
318 |
- |
|
319 |
-/** |
|
320 |
- * Codec worker thread. |
|
321 |
- * |
|
322 |
- * Automatically calls ff_thread_finish_setup() if the codec does |
|
323 |
- * not provide an update_thread_context method, or if the codec returns |
|
324 |
- * before calling it. |
|
325 |
- */ |
|
326 |
-static attribute_align_arg void *frame_worker_thread(void *arg) |
|
327 |
-{ |
|
328 |
- PerThreadContext *p = arg; |
|
329 |
- FrameThreadContext *fctx = p->parent; |
|
330 |
- AVCodecContext *avctx = p->avctx; |
|
331 |
- const AVCodec *codec = avctx->codec; |
|
332 |
- |
|
333 |
- pthread_mutex_lock(&p->mutex); |
|
334 |
- while (1) { |
|
335 |
- while (p->state == STATE_INPUT_READY && !fctx->die) |
|
336 |
- pthread_cond_wait(&p->input_cond, &p->mutex); |
|
337 |
- |
|
338 |
- if (fctx->die) break; |
|
339 |
- |
|
340 |
- if (!codec->update_thread_context && THREAD_SAFE_CALLBACKS(avctx)) |
|
341 |
- ff_thread_finish_setup(avctx); |
|
342 |
- |
|
343 |
- avcodec_get_frame_defaults(&p->frame); |
|
344 |
- p->got_frame = 0; |
|
345 |
- p->result = codec->decode(avctx, &p->frame, &p->got_frame, &p->avpkt); |
|
346 |
- |
|
347 |
- /* many decoders assign whole AVFrames, thus overwriting extended_data; |
|
348 |
- * make sure it's set correctly */ |
|
349 |
- p->frame.extended_data = p->frame.data; |
|
350 |
- |
|
351 |
- if (p->state == STATE_SETTING_UP) ff_thread_finish_setup(avctx); |
|
352 |
- |
|
353 |
- pthread_mutex_lock(&p->progress_mutex); |
|
354 |
-#if 0 //BUFREF-FIXME |
|
355 |
- for (i = 0; i < MAX_BUFFERS; i++) |
|
356 |
- if (p->progress_used[i] && (p->got_frame || p->result<0 || avctx->codec_id != AV_CODEC_ID_H264)) { |
|
357 |
- p->progress[i][0] = INT_MAX; |
|
358 |
- p->progress[i][1] = INT_MAX; |
|
359 |
- } |
|
360 |
-#endif |
|
361 |
- p->state = STATE_INPUT_READY; |
|
362 |
- |
|
363 |
- pthread_cond_broadcast(&p->progress_cond); |
|
364 |
- pthread_cond_signal(&p->output_cond); |
|
365 |
- pthread_mutex_unlock(&p->progress_mutex); |
|
366 |
- } |
|
367 |
- pthread_mutex_unlock(&p->mutex); |
|
368 |
- |
|
369 |
- return NULL; |
|
370 |
-} |
|
371 |
- |
|
372 |
-/** |
|
373 |
- * Update the next thread's AVCodecContext with values from the reference thread's context. |
|
374 |
- * |
|
375 |
- * @param dst The destination context. |
|
376 |
- * @param src The source context. |
|
377 |
- * @param for_user 0 if the destination is a codec thread, 1 if the destination is the user's thread |
|
378 |
- */ |
|
379 |
-static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, int for_user) |
|
380 |
-{ |
|
381 |
- int err = 0; |
|
382 |
- |
|
383 |
- if (dst != src) { |
|
384 |
- dst->time_base = src->time_base; |
|
385 |
- dst->width = src->width; |
|
386 |
- dst->height = src->height; |
|
387 |
- dst->pix_fmt = src->pix_fmt; |
|
388 |
- |
|
389 |
- dst->coded_width = src->coded_width; |
|
390 |
- dst->coded_height = src->coded_height; |
|
391 |
- |
|
392 |
- dst->has_b_frames = src->has_b_frames; |
|
393 |
- dst->idct_algo = src->idct_algo; |
|
394 |
- |
|
395 |
- dst->bits_per_coded_sample = src->bits_per_coded_sample; |
|
396 |
- dst->sample_aspect_ratio = src->sample_aspect_ratio; |
|
397 |
- dst->dtg_active_format = src->dtg_active_format; |
|
398 |
- |
|
399 |
- dst->profile = src->profile; |
|
400 |
- dst->level = src->level; |
|
401 |
- |
|
402 |
- dst->bits_per_raw_sample = src->bits_per_raw_sample; |
|
403 |
- dst->ticks_per_frame = src->ticks_per_frame; |
|
404 |
- dst->color_primaries = src->color_primaries; |
|
405 |
- |
|
406 |
- dst->color_trc = src->color_trc; |
|
407 |
- dst->colorspace = src->colorspace; |
|
408 |
- dst->color_range = src->color_range; |
|
409 |
- dst->chroma_sample_location = src->chroma_sample_location; |
|
410 |
- |
|
411 |
- dst->hwaccel = src->hwaccel; |
|
412 |
- dst->hwaccel_context = src->hwaccel_context; |
|
413 |
- |
|
414 |
- dst->channels = src->channels; |
|
415 |
- dst->sample_rate = src->sample_rate; |
|
416 |
- dst->sample_fmt = src->sample_fmt; |
|
417 |
- dst->channel_layout = src->channel_layout; |
|
418 |
- } |
|
419 |
- |
|
420 |
- if (for_user) { |
|
421 |
- dst->delay = src->thread_count - 1; |
|
422 |
- dst->coded_frame = src->coded_frame; |
|
423 |
- } else { |
|
424 |
- if (dst->codec->update_thread_context) |
|
425 |
- err = dst->codec->update_thread_context(dst, src); |
|
426 |
- } |
|
427 |
- |
|
428 |
- return err; |
|
429 |
-} |
|
430 |
- |
|
431 |
-/** |
|
432 |
- * Update the next thread's AVCodecContext with values set by the user. |
|
433 |
- * |
|
434 |
- * @param dst The destination context. |
|
435 |
- * @param src The source context. |
|
436 |
- * @return 0 on success, negative error code on failure |
|
437 |
- */ |
|
438 |
-static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) |
|
439 |
-{ |
|
440 |
-#define copy_fields(s, e) memcpy(&dst->s, &src->s, (char*)&dst->e - (char*)&dst->s); |
|
441 |
- dst->flags = src->flags; |
|
442 |
- |
|
443 |
- dst->draw_horiz_band= src->draw_horiz_band; |
|
444 |
- dst->get_buffer2 = src->get_buffer2; |
|
445 |
-#if FF_API_GET_BUFFER |
|
446 |
-FF_DISABLE_DEPRECATION_WARNINGS |
|
447 |
- dst->get_buffer = src->get_buffer; |
|
448 |
- dst->release_buffer = src->release_buffer; |
|
449 |
-FF_ENABLE_DEPRECATION_WARNINGS |
|
450 |
-#endif |
|
451 |
- |
|
452 |
- dst->opaque = src->opaque; |
|
453 |
- dst->debug = src->debug; |
|
454 |
- dst->debug_mv = src->debug_mv; |
|
455 |
- |
|
456 |
- dst->slice_flags = src->slice_flags; |
|
457 |
- dst->flags2 = src->flags2; |
|
458 |
- |
|
459 |
- copy_fields(skip_loop_filter, subtitle_header); |
|
460 |
- |
|
461 |
- dst->frame_number = src->frame_number; |
|
462 |
- dst->reordered_opaque = src->reordered_opaque; |
|
463 |
- dst->thread_safe_callbacks = src->thread_safe_callbacks; |
|
464 |
- |
|
465 |
- if (src->slice_count && src->slice_offset) { |
|
466 |
- if (dst->slice_count < src->slice_count) { |
|
467 |
- int *tmp = av_realloc(dst->slice_offset, src->slice_count * |
|
468 |
- sizeof(*dst->slice_offset)); |
|
469 |
- if (!tmp) { |
|
470 |
- av_free(dst->slice_offset); |
|
471 |
- return AVERROR(ENOMEM); |
|
472 |
- } |
|
473 |
- dst->slice_offset = tmp; |
|
474 |
- } |
|
475 |
- memcpy(dst->slice_offset, src->slice_offset, |
|
476 |
- src->slice_count * sizeof(*dst->slice_offset)); |
|
477 |
- } |
|
478 |
- dst->slice_count = src->slice_count; |
|
479 |
- return 0; |
|
480 |
-#undef copy_fields |
|
481 |
-} |
|
482 |
- |
|
483 |
-/// Releases the buffers that this decoding thread was the last user of. |
|
484 |
-static void release_delayed_buffers(PerThreadContext *p) |
|
485 |
-{ |
|
486 |
- FrameThreadContext *fctx = p->parent; |
|
487 |
- |
|
488 |
- while (p->num_released_buffers > 0) { |
|
489 |
- AVFrame *f; |
|
490 |
- |
|
491 |
- pthread_mutex_lock(&fctx->buffer_mutex); |
|
492 |
- |
|
493 |
- // fix extended data in case the caller screwed it up |
|
494 |
- av_assert0(p->avctx->codec_type == AVMEDIA_TYPE_VIDEO || |
|
495 |
- p->avctx->codec_type == AVMEDIA_TYPE_AUDIO); |
|
496 |
- f = &p->released_buffers[--p->num_released_buffers]; |
|
497 |
- f->extended_data = f->data; |
|
498 |
- av_frame_unref(f); |
|
499 |
- |
|
500 |
- pthread_mutex_unlock(&fctx->buffer_mutex); |
|
501 |
- } |
|
502 |
-} |
|
503 |
- |
|
504 |
-static int submit_packet(PerThreadContext *p, AVPacket *avpkt) |
|
505 |
-{ |
|
506 |
- FrameThreadContext *fctx = p->parent; |
|
507 |
- PerThreadContext *prev_thread = fctx->prev_thread; |
|
508 |
- const AVCodec *codec = p->avctx->codec; |
|
509 |
- |
|
510 |
- if (!avpkt->size && !(codec->capabilities & CODEC_CAP_DELAY)) return 0; |
|
511 |
- |
|
512 |
- pthread_mutex_lock(&p->mutex); |
|
513 |
- |
|
514 |
- release_delayed_buffers(p); |
|
515 |
- |
|
516 |
- if (prev_thread) { |
|
517 |
- int err; |
|
518 |
- if (prev_thread->state == STATE_SETTING_UP) { |
|
519 |
- pthread_mutex_lock(&prev_thread->progress_mutex); |
|
520 |
- while (prev_thread->state == STATE_SETTING_UP) |
|
521 |
- pthread_cond_wait(&prev_thread->progress_cond, &prev_thread->progress_mutex); |
|
522 |
- pthread_mutex_unlock(&prev_thread->progress_mutex); |
|
523 |
- } |
|
524 |
- |
|
525 |
- err = update_context_from_thread(p->avctx, prev_thread->avctx, 0); |
|
526 |
- if (err) { |
|
527 |
- pthread_mutex_unlock(&p->mutex); |
|
528 |
- return err; |
|
529 |
- } |
|
530 |
- } |
|
531 |
- |
|
532 |
- av_buffer_unref(&p->avpkt.buf); |
|
533 |
- p->avpkt = *avpkt; |
|
534 |
- if (avpkt->buf) |
|
535 |
- p->avpkt.buf = av_buffer_ref(avpkt->buf); |
|
536 |
- else { |
|
537 |
- av_fast_malloc(&p->buf, &p->allocated_buf_size, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); |
|
538 |
- p->avpkt.data = p->buf; |
|
539 |
- memcpy(p->buf, avpkt->data, avpkt->size); |
|
540 |
- memset(p->buf + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); |
|
541 |
- } |
|
542 |
- |
|
543 |
- p->state = STATE_SETTING_UP; |
|
544 |
- pthread_cond_signal(&p->input_cond); |
|
545 |
- pthread_mutex_unlock(&p->mutex); |
|
546 |
- |
|
547 |
- /* |
|
548 |
- * If the client doesn't have a thread-safe get_buffer(), |
|
549 |
- * then decoding threads call back to the main thread, |
|
550 |
- * and it calls back to the client here. |
|
551 |
- */ |
|
552 |
- |
|
553 |
-FF_DISABLE_DEPRECATION_WARNINGS |
|
554 |
- if (!p->avctx->thread_safe_callbacks && ( |
|
555 |
- p->avctx->get_format != avcodec_default_get_format || |
|
556 |
-#if FF_API_GET_BUFFER |
|
557 |
- p->avctx->get_buffer || |
|
558 |
-#endif |
|
559 |
- p->avctx->get_buffer2 != avcodec_default_get_buffer2)) { |
|
560 |
-FF_ENABLE_DEPRECATION_WARNINGS |
|
561 |
- while (p->state != STATE_SETUP_FINISHED && p->state != STATE_INPUT_READY) { |
|
562 |
- int call_done = 1; |
|
563 |
- pthread_mutex_lock(&p->progress_mutex); |
|
564 |
- while (p->state == STATE_SETTING_UP) |
|
565 |
- pthread_cond_wait(&p->progress_cond, &p->progress_mutex); |
|
566 |
- |
|
567 |
- switch (p->state) { |
|
568 |
- case STATE_GET_BUFFER: |
|
569 |
- p->result = ff_get_buffer(p->avctx, p->requested_frame, p->requested_flags); |
|
570 |
- break; |
|
571 |
- case STATE_GET_FORMAT: |
|
572 |
- p->result_format = p->avctx->get_format(p->avctx, p->available_formats); |
|
573 |
- break; |
|
574 |
- default: |
|
575 |
- call_done = 0; |
|
576 |
- break; |
|
577 |
- } |
|
578 |
- if (call_done) { |
|
579 |
- p->state = STATE_SETTING_UP; |
|
580 |
- pthread_cond_signal(&p->progress_cond); |
|
581 |
- } |
|
582 |
- pthread_mutex_unlock(&p->progress_mutex); |
|
583 |
- } |
|
584 |
- } |
|
585 |
- |
|
586 |
- fctx->prev_thread = p; |
|
587 |
- fctx->next_decoding++; |
|
588 |
- |
|
589 |
- return 0; |
|
590 |
-} |
|
591 |
- |
|
592 |
-int ff_thread_decode_frame(AVCodecContext *avctx, |
|
593 |
- AVFrame *picture, int *got_picture_ptr, |
|
594 |
- AVPacket *avpkt) |
|
595 |
-{ |
|
596 |
- FrameThreadContext *fctx = avctx->thread_opaque; |
|
597 |
- int finished = fctx->next_finished; |
|
598 |
- PerThreadContext *p; |
|
599 |
- int err; |
|
600 |
- |
|
601 |
- /* |
|
602 |
- * Submit a packet to the next decoding thread. |
|
603 |
- */ |
|
604 |
- |
|
605 |
- p = &fctx->threads[fctx->next_decoding]; |
|
606 |
- err = update_context_from_user(p->avctx, avctx); |
|
607 |
- if (err) return err; |
|
608 |
- err = submit_packet(p, avpkt); |
|
609 |
- if (err) return err; |
|
610 |
- |
|
611 |
- /* |
|
612 |
- * If we're still receiving the initial packets, don't return a frame. |
|
613 |
- */ |
|
614 |
- |
|
615 |
- if (fctx->next_decoding > (avctx->thread_count-1-(avctx->codec_id == AV_CODEC_ID_FFV1))) |
|
616 |
- fctx->delaying = 0; |
|
617 |
- |
|
618 |
- if (fctx->delaying) { |
|
619 |
- *got_picture_ptr=0; |
|
620 |
- if (avpkt->size) |
|
621 |
- return avpkt->size; |
|
622 |
- } |
|
623 |
- |
|
624 |
- /* |
|
625 |
- * Return the next available frame from the oldest thread. |
|
626 |
- * If we're at the end of the stream, then we have to skip threads that |
|
627 |
- * didn't output a frame, because we don't want to accidentally signal |
|
628 |
- * EOF (avpkt->size == 0 && *got_picture_ptr == 0). |
|
629 |
- */ |
|
630 |
- |
|
631 |
- do { |
|
632 |
- p = &fctx->threads[finished++]; |
|
633 |
- |
|
634 |
- if (p->state != STATE_INPUT_READY) { |
|
635 |
- pthread_mutex_lock(&p->progress_mutex); |
|
636 |
- while (p->state != STATE_INPUT_READY) |
|
637 |
- pthread_cond_wait(&p->output_cond, &p->progress_mutex); |
|
638 |
- pthread_mutex_unlock(&p->progress_mutex); |
|
639 |
- } |
|
640 |
- |
|
641 |
- av_frame_move_ref(picture, &p->frame); |
|
642 |
- *got_picture_ptr = p->got_frame; |
|
643 |
- picture->pkt_dts = p->avpkt.dts; |
|
644 |
- |
|
645 |
- /* |
|
646 |
- * A later call with avkpt->size == 0 may loop over all threads, |
|
647 |
- * including this one, searching for a frame to return before being |
|
648 |
- * stopped by the "finished != fctx->next_finished" condition. |
|
649 |
- * Make sure we don't mistakenly return the same frame again. |
|
650 |
- */ |
|
651 |
- p->got_frame = 0; |
|
652 |
- |
|
653 |
- if (finished >= avctx->thread_count) finished = 0; |
|
654 |
- } while (!avpkt->size && !*got_picture_ptr && finished != fctx->next_finished); |
|
655 |
- |
|
656 |
- update_context_from_thread(avctx, p->avctx, 1); |
|
657 |
- |
|
658 |
- if (fctx->next_decoding >= avctx->thread_count) fctx->next_decoding = 0; |
|
659 |
- |
|
660 |
- fctx->next_finished = finished; |
|
661 |
- |
|
662 |
- /* return the size of the consumed packet if no error occurred */ |
|
663 |
- return (p->result >= 0) ? avpkt->size : p->result; |
|
664 |
-} |
|
665 |
- |
|
666 |
-void ff_thread_report_progress(ThreadFrame *f, int n, int field) |
|
667 |
-{ |
|
668 |
- PerThreadContext *p; |
|
669 |
- volatile int *progress = f->progress ? (int*)f->progress->data : NULL; |
|
670 |
- |
|
671 |
- if (!progress || progress[field] >= n) return; |
|
672 |
- |
|
673 |
- p = f->owner->thread_opaque; |
|
674 |
- |
|
675 |
- if (f->owner->debug&FF_DEBUG_THREADS) |
|
676 |
- av_log(f->owner, AV_LOG_DEBUG, "%p finished %d field %d\n", progress, n, field); |
|
677 |
- |
|
678 |
- pthread_mutex_lock(&p->progress_mutex); |
|
679 |
- progress[field] = n; |
|
680 |
- pthread_cond_broadcast(&p->progress_cond); |
|
681 |
- pthread_mutex_unlock(&p->progress_mutex); |
|
682 |
-} |
|
683 |
- |
|
684 |
-void ff_thread_await_progress(ThreadFrame *f, int n, int field) |
|
685 |
-{ |
|
686 |
- PerThreadContext *p; |
|
687 |
- volatile int *progress = f->progress ? (int*)f->progress->data : NULL; |
|
688 |
- |
|
689 |
- if (!progress || progress[field] >= n) return; |
|
690 |
- |
|
691 |
- p = f->owner->thread_opaque; |
|
692 |
- |
|
693 |
- if (f->owner->debug&FF_DEBUG_THREADS) |
|
694 |
- av_log(f->owner, AV_LOG_DEBUG, "thread awaiting %d field %d from %p\n", n, field, progress); |
|
695 |
- |
|
696 |
- pthread_mutex_lock(&p->progress_mutex); |
|
697 |
- while (progress[field] < n) |
|
698 |
- pthread_cond_wait(&p->progress_cond, &p->progress_mutex); |
|
699 |
- pthread_mutex_unlock(&p->progress_mutex); |
|
700 |
-} |
|
701 |
- |
|
702 |
-void ff_thread_finish_setup(AVCodecContext *avctx) { |
|
703 |
- PerThreadContext *p = avctx->thread_opaque; |
|
704 |
- |
|
705 |
- if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return; |
|
706 |
- |
|
707 |
- if(p->state == STATE_SETUP_FINISHED){ |
|
708 |
- av_log(avctx, AV_LOG_WARNING, "Multiple ff_thread_finish_setup() calls\n"); |
|
709 |
- } |
|
710 |
- |
|
711 |
- pthread_mutex_lock(&p->progress_mutex); |
|
712 |
- p->state = STATE_SETUP_FINISHED; |
|
713 |
- pthread_cond_broadcast(&p->progress_cond); |
|
714 |
- pthread_mutex_unlock(&p->progress_mutex); |
|
715 |
-} |
|
716 |
- |
|
717 |
-/// Waits for all threads to finish. |
|
718 |
-static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count) |
|
719 |
-{ |
|
720 |
- int i; |
|
721 |
- |
|
722 |
- for (i = 0; i < thread_count; i++) { |
|
723 |
- PerThreadContext *p = &fctx->threads[i]; |
|
724 |
- |
|
725 |
- if (p->state != STATE_INPUT_READY) { |
|
726 |
- pthread_mutex_lock(&p->progress_mutex); |
|
727 |
- while (p->state != STATE_INPUT_READY) |
|
728 |
- pthread_cond_wait(&p->output_cond, &p->progress_mutex); |
|
729 |
- pthread_mutex_unlock(&p->progress_mutex); |
|
730 |
- } |
|
731 |
- p->got_frame = 0; |
|
732 |
- } |
|
733 |
-} |
|
734 |
- |
|
735 |
-static void frame_thread_free(AVCodecContext *avctx, int thread_count) |
|
736 |
-{ |
|
737 |
- FrameThreadContext *fctx = avctx->thread_opaque; |
|
738 |
- const AVCodec *codec = avctx->codec; |
|
739 |
- int i; |
|
740 |
- |
|
741 |
- park_frame_worker_threads(fctx, thread_count); |
|
742 |
- |
|
743 |
- if (fctx->prev_thread && fctx->prev_thread != fctx->threads) |
|
744 |
- if (update_context_from_thread(fctx->threads->avctx, fctx->prev_thread->avctx, 0) < 0) { |
|
745 |
- av_log(avctx, AV_LOG_ERROR, "Final thread update failed\n"); |
|
746 |
- fctx->prev_thread->avctx->internal->is_copy = fctx->threads->avctx->internal->is_copy; |
|
747 |
- fctx->threads->avctx->internal->is_copy = 1; |
|
748 |
- } |
|
749 |
- |
|
750 |
- fctx->die = 1; |
|
751 |
- |
|
752 |
- for (i = 0; i < thread_count; i++) { |
|
753 |
- PerThreadContext *p = &fctx->threads[i]; |
|
754 |
- |
|
755 |
- pthread_mutex_lock(&p->mutex); |
|
756 |
- pthread_cond_signal(&p->input_cond); |
|
757 |
- pthread_mutex_unlock(&p->mutex); |
|
758 |
- |
|
759 |
- if (p->thread_init) |
|
760 |
- pthread_join(p->thread, NULL); |
|
761 |
- p->thread_init=0; |
|
762 |
- |
|
763 |
- if (codec->close) |
|
764 |
- codec->close(p->avctx); |
|
765 |
- |
|
766 |
- avctx->codec = NULL; |
|
767 |
- |
|
768 |
- release_delayed_buffers(p); |
|
769 |
- av_frame_unref(&p->frame); |
|
770 |
- } |
|
771 |
- |
|
772 |
- for (i = 0; i < thread_count; i++) { |
|
773 |
- PerThreadContext *p = &fctx->threads[i]; |
|
774 |
- |
|
775 |
- pthread_mutex_destroy(&p->mutex); |
|
776 |
- pthread_mutex_destroy(&p->progress_mutex); |
|
777 |
- pthread_cond_destroy(&p->input_cond); |
|
778 |
- pthread_cond_destroy(&p->progress_cond); |
|
779 |
- pthread_cond_destroy(&p->output_cond); |
|
780 |
- av_buffer_unref(&p->avpkt.buf); |
|
781 |
- av_freep(&p->buf); |
|
782 |
- av_freep(&p->released_buffers); |
|
783 |
- |
|
784 |
- if (i) { |
|
785 |
- av_freep(&p->avctx->priv_data); |
|
786 |
- av_freep(&p->avctx->internal); |
|
787 |
- av_freep(&p->avctx->slice_offset); |
|
788 |
- } |
|
789 |
- |
|
790 |
- av_freep(&p->avctx); |
|
791 |
- } |
|
792 |
- |
|
793 |
- av_freep(&fctx->threads); |
|
794 |
- pthread_mutex_destroy(&fctx->buffer_mutex); |
|
795 |
- av_freep(&avctx->thread_opaque); |
|
796 |
-} |
|
797 |
- |
|
798 |
-static int frame_thread_init(AVCodecContext *avctx) |
|
799 |
-{ |
|
800 |
- int thread_count = avctx->thread_count; |
|
801 |
- const AVCodec *codec = avctx->codec; |
|
802 |
- AVCodecContext *src = avctx; |
|
803 |
- FrameThreadContext *fctx; |
|
804 |
- int i, err = 0; |
|
805 |
- |
|
806 |
- if (!thread_count) { |
|
807 |
- int nb_cpus = av_cpu_count(); |
|
808 |
- if ((avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || avctx->debug_mv) |
|
809 |
- nb_cpus = 1; |
|
810 |
- // use number of cores + 1 as thread count if there is more than one |
|
811 |
- if (nb_cpus > 1) |
|
812 |
- thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS); |
|
813 |
- else |
|
814 |
- thread_count = avctx->thread_count = 1; |
|
815 |
- } |
|
816 |
- |
|
817 |
- if (thread_count <= 1) { |
|
818 |
- avctx->active_thread_type = 0; |
|
819 |
- return 0; |
|
820 |
- } |
|
821 |
- |
|
822 |
- avctx->thread_opaque = fctx = av_mallocz(sizeof(FrameThreadContext)); |
|
823 |
- |
|
824 |
- fctx->threads = av_mallocz(sizeof(PerThreadContext) * thread_count); |
|
825 |
- pthread_mutex_init(&fctx->buffer_mutex, NULL); |
|
826 |
- fctx->delaying = 1; |
|
827 |
- |
|
828 |
- for (i = 0; i < thread_count; i++) { |
|
829 |
- AVCodecContext *copy = av_malloc(sizeof(AVCodecContext)); |
|
830 |
- PerThreadContext *p = &fctx->threads[i]; |
|
831 |
- |
|
832 |
- pthread_mutex_init(&p->mutex, NULL); |
|
833 |
- pthread_mutex_init(&p->progress_mutex, NULL); |
|
834 |
- pthread_cond_init(&p->input_cond, NULL); |
|
835 |
- pthread_cond_init(&p->progress_cond, NULL); |
|
836 |
- pthread_cond_init(&p->output_cond, NULL); |
|
837 |
- |
|
838 |
- p->parent = fctx; |
|
839 |
- p->avctx = copy; |
|
840 |
- |
|
841 |
- if (!copy) { |
|
842 |
- err = AVERROR(ENOMEM); |
|
843 |
- goto error; |
|
844 |
- } |
|
845 |
- |
|
846 |
- *copy = *src; |
|
847 |
- copy->thread_opaque = p; |
|
848 |
- copy->pkt = &p->avpkt; |
|
849 |
- |
|
850 |
- if (!i) { |
|
851 |
- src = copy; |
|
852 |
- |
|
853 |
- if (codec->init) |
|
854 |
- err = codec->init(copy); |
|
855 |
- |
|
856 |
- update_context_from_thread(avctx, copy, 1); |
|
857 |
- } else { |
|
858 |
- copy->priv_data = av_malloc(codec->priv_data_size); |
|
859 |
- if (!copy->priv_data) { |
|
860 |
- err = AVERROR(ENOMEM); |
|
861 |
- goto error; |
|
862 |
- } |
|
863 |
- memcpy(copy->priv_data, src->priv_data, codec->priv_data_size); |
|
864 |
- copy->internal = av_malloc(sizeof(AVCodecInternal)); |
|
865 |
- if (!copy->internal) { |
|
866 |
- err = AVERROR(ENOMEM); |
|
867 |
- goto error; |
|
868 |
- } |
|
869 |
- *copy->internal = *src->internal; |
|
870 |
- copy->internal->is_copy = 1; |
|
871 |
- |
|
872 |
- if (codec->init_thread_copy) |
|
873 |
- err = codec->init_thread_copy(copy); |
|
874 |
- } |
|
875 |
- |
|
876 |
- if (err) goto error; |
|
877 |
- |
|
878 |
- err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p)); |
|
879 |
- p->thread_init= !err; |
|
880 |
- if(!p->thread_init) |
|
881 |
- goto error; |
|
882 |
- } |
|
883 |
- |
|
884 |
- return 0; |
|
885 |
- |
|
886 |
-error: |
|
887 |
- frame_thread_free(avctx, i+1); |
|
888 |
- |
|
889 |
- return err; |
|
890 |
-} |
|
891 |
- |
|
892 |
-void ff_thread_flush(AVCodecContext *avctx) |
|
893 |
-{ |
|
894 |
- int i; |
|
895 |
- FrameThreadContext *fctx = avctx->thread_opaque; |
|
896 |
- |
|
897 |
- if (!avctx->thread_opaque) return; |
|
898 |
- |
|
899 |
- park_frame_worker_threads(fctx, avctx->thread_count); |
|
900 |
- if (fctx->prev_thread) { |
|
901 |
- if (fctx->prev_thread != &fctx->threads[0]) |
|
902 |
- update_context_from_thread(fctx->threads[0].avctx, fctx->prev_thread->avctx, 0); |
|
903 |
- if (avctx->codec->flush) |
|
904 |
- avctx->codec->flush(fctx->threads[0].avctx); |
|
905 |
- } |
|
906 |
- |
|
907 |
- fctx->next_decoding = fctx->next_finished = 0; |
|
908 |
- fctx->delaying = 1; |
|
909 |
- fctx->prev_thread = NULL; |
|
910 |
- for (i = 0; i < avctx->thread_count; i++) { |
|
911 |
- PerThreadContext *p = &fctx->threads[i]; |
|
912 |
- // Make sure decode flush calls with size=0 won't return old frames |
|
913 |
- p->got_frame = 0; |
|
914 |
- av_frame_unref(&p->frame); |
|
915 |
- |
|
916 |
- release_delayed_buffers(p); |
|
917 |
- } |
|
918 |
-} |
|
919 |
- |
|
920 |
-int ff_thread_can_start_frame(AVCodecContext *avctx) |
|
921 |
-{ |
|
922 |
- PerThreadContext *p = avctx->thread_opaque; |
|
923 |
- if ((avctx->active_thread_type&FF_THREAD_FRAME) && p->state != STATE_SETTING_UP && |
|
924 |
- (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) { |
|
925 |
- return 0; |
|
926 |
- } |
|
927 |
- return 1; |
|
928 |
-} |
|
929 |
- |
|
930 |
-static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int flags) |
|
931 |
-{ |
|
932 |
- PerThreadContext *p = avctx->thread_opaque; |
|
933 |
- int err; |
|
934 |
- |
|
935 |
- f->owner = avctx; |
|
936 |
- |
|
937 |
- ff_init_buffer_info(avctx, f->f); |
|
938 |
- |
|
939 |
- if (!(avctx->active_thread_type & FF_THREAD_FRAME)) |
|
940 |
- return ff_get_buffer(avctx, f->f, flags); |
|
941 |
- |
|
942 |
- if (p->state != STATE_SETTING_UP && |
|
943 |
- (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) { |
|
944 |
- av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n"); |
|
945 |
- return -1; |
|
946 |
- } |
|
947 |
- |
|
948 |
- if (avctx->internal->allocate_progress) { |
|
949 |
- int *progress; |
|
950 |
- f->progress = av_buffer_alloc(2 * sizeof(int)); |
|
951 |
- if (!f->progress) { |
|
952 |
- return AVERROR(ENOMEM); |
|
953 |
- } |
|
954 |
- progress = (int*)f->progress->data; |
|
955 |
- |
|
956 |
- progress[0] = progress[1] = -1; |
|
957 |
- } |
|
958 |
- |
|
959 |
- pthread_mutex_lock(&p->parent->buffer_mutex); |
|
960 |
- |
|
961 |
-FF_DISABLE_DEPRECATION_WARNINGS |
|
962 |
- if (avctx->thread_safe_callbacks || ( |
|
963 |
-#if FF_API_GET_BUFFER |
|
964 |
- !avctx->get_buffer && |
|
965 |
-#endif |
|
966 |
- avctx->get_buffer2 == avcodec_default_get_buffer2)) { |
|
967 |
-FF_ENABLE_DEPRECATION_WARNINGS |
|
968 |
- err = ff_get_buffer(avctx, f->f, flags); |
|
969 |
- } else { |
|
970 |
- pthread_mutex_lock(&p->progress_mutex); |
|
971 |
- p->requested_frame = f->f; |
|
972 |
- p->requested_flags = flags; |
|
973 |
- p->state = STATE_GET_BUFFER; |
|
974 |
- pthread_cond_broadcast(&p->progress_cond); |
|
975 |
- |
|
976 |
- while (p->state != STATE_SETTING_UP) |
|
977 |
- pthread_cond_wait(&p->progress_cond, &p->progress_mutex); |
|
978 |
- |
|
979 |
- err = p->result; |
|
980 |
- |
|
981 |
- pthread_mutex_unlock(&p->progress_mutex); |
|
982 |
- |
|
983 |
- } |
|
984 |
- if (!THREAD_SAFE_CALLBACKS(avctx) && !avctx->codec->update_thread_context) |
|
985 |
- ff_thread_finish_setup(avctx); |
|
986 |
- |
|
987 |
- if (err) |
|
988 |
- av_buffer_unref(&f->progress); |
|
989 |
- |
|
990 |
- pthread_mutex_unlock(&p->parent->buffer_mutex); |
|
991 |
- |
|
992 |
- return err; |
|
993 |
-} |
|
994 |
- |
|
995 |
-enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) |
|
996 |
-{ |
|
997 |
- enum AVPixelFormat res; |
|
998 |
- PerThreadContext *p = avctx->thread_opaque; |
|
999 |
- if (!(avctx->active_thread_type & FF_THREAD_FRAME) || avctx->thread_safe_callbacks || |
|
1000 |
- avctx->get_format == avcodec_default_get_format) |
|
1001 |
- return avctx->get_format(avctx, fmt); |
|
1002 |
- if (p->state != STATE_SETTING_UP) { |
|
1003 |
- av_log(avctx, AV_LOG_ERROR, "get_format() cannot be called after ff_thread_finish_setup()\n"); |
|
1004 |
- return -1; |
|
1005 |
- } |
|
1006 |
- pthread_mutex_lock(&p->progress_mutex); |
|
1007 |
- p->available_formats = fmt; |
|
1008 |
- p->state = STATE_GET_FORMAT; |
|
1009 |
- pthread_cond_broadcast(&p->progress_cond); |
|
1010 |
- |
|
1011 |
- while (p->state != STATE_SETTING_UP) |
|
1012 |
- pthread_cond_wait(&p->progress_cond, &p->progress_mutex); |
|
1013 |
- |
|
1014 |
- res = p->result_format; |
|
1015 |
- |
|
1016 |
- pthread_mutex_unlock(&p->progress_mutex); |
|
1017 |
- |
|
1018 |
- return res; |
|
1019 |
-} |
|
1020 |
- |
|
1021 |
-int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) |
|
1022 |
-{ |
|
1023 |
- int ret = thread_get_buffer_internal(avctx, f, flags); |
|
1024 |
- if (ret < 0) |
|
1025 |
- av_log(avctx, AV_LOG_ERROR, "thread_get_buffer() failed\n"); |
|
1026 |
- return ret; |
|
1027 |
-} |
|
1028 |
- |
|
1029 |
-void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) |
|
1030 |
-{ |
|
1031 |
- PerThreadContext *p = avctx->thread_opaque; |
|
1032 |
- FrameThreadContext *fctx; |
|
1033 |
- AVFrame *dst, *tmp; |
|
1034 |
-FF_DISABLE_DEPRECATION_WARNINGS |
|
1035 |
- int can_direct_free = !(avctx->active_thread_type & FF_THREAD_FRAME) || |
|
1036 |
- avctx->thread_safe_callbacks || |
|
1037 |
- ( |
|
1038 |
-#if FF_API_GET_BUFFER |
|
1039 |
- !avctx->get_buffer && |
|
1040 |
-#endif |
|
1041 |
- avctx->get_buffer2 == avcodec_default_get_buffer2); |
|
1042 |
-FF_ENABLE_DEPRECATION_WARNINGS |
|
1043 |
- |
|
1044 |
- if (!f->f->data[0]) |
|
1045 |
- return; |
|
1046 |
- |
|
1047 |
- if (avctx->debug & FF_DEBUG_BUFFERS) |
|
1048 |
- av_log(avctx, AV_LOG_DEBUG, "thread_release_buffer called on pic %p\n", f); |
|
1049 |
- |
|
1050 |
- av_buffer_unref(&f->progress); |
|
1051 |
- f->owner = NULL; |
|
1052 |
- |
|
1053 |
- if (can_direct_free) { |
|
1054 |
- av_frame_unref(f->f); |
|
1055 |
- return; |
|
1056 |
- } |
|
1057 |
- |
|
1058 |
- fctx = p->parent; |
|
1059 |
- pthread_mutex_lock(&fctx->buffer_mutex); |
|
1060 |
- |
|
1061 |
- if (p->num_released_buffers + 1 >= INT_MAX / sizeof(*p->released_buffers)) |
|
1062 |
- goto fail; |
|
1063 |
- tmp = av_fast_realloc(p->released_buffers, &p->released_buffers_allocated, |
|
1064 |
- (p->num_released_buffers + 1) * |
|
1065 |
- sizeof(*p->released_buffers)); |
|
1066 |
- if (!tmp) |
|
1067 |
- goto fail; |
|
1068 |
- p->released_buffers = tmp; |
|
1069 |
- |
|
1070 |
- dst = &p->released_buffers[p->num_released_buffers]; |
|
1071 |
- av_frame_move_ref(dst, f->f); |
|
1072 |
- |
|
1073 |
- p->num_released_buffers++; |
|
1074 |
- |
|
1075 |
-fail: |
|
1076 |
- pthread_mutex_unlock(&fctx->buffer_mutex); |
|
1077 |
-} |
|
1078 | 36 |
|
1079 | 37 |
/** |
1080 | 38 |
* Set the threading algorithms used. |
... | ... |
@@ -1111,16 +69,12 @@ static void validate_thread_parameters(AVCodecContext *avctx) |
1111 | 1111 |
|
1112 | 1112 |
int ff_thread_init(AVCodecContext *avctx) |
1113 | 1113 |
{ |
1114 |
-#if HAVE_W32THREADS |
|
1115 |
- w32thread_init(); |
|
1116 |
-#endif |
|
1117 |
- |
|
1118 | 1114 |
validate_thread_parameters(avctx); |
1119 | 1115 |
|
1120 | 1116 |
if (avctx->active_thread_type&FF_THREAD_SLICE) |
1121 |
- return thread_init_internal(avctx); |
|
1117 |
+ return ff_slice_thread_init(avctx); |
|
1122 | 1118 |
else if (avctx->active_thread_type&FF_THREAD_FRAME) |
1123 |
- return frame_thread_init(avctx); |
|
1119 |
+ return ff_frame_thread_init(avctx); |
|
1124 | 1120 |
|
1125 | 1121 |
return 0; |
1126 | 1122 |
} |
... | ... |
@@ -1128,66 +82,7 @@ int ff_thread_init(AVCodecContext *avctx) |
1128 | 1128 |
void ff_thread_free(AVCodecContext *avctx) |
1129 | 1129 |
{ |
1130 | 1130 |
if (avctx->active_thread_type&FF_THREAD_FRAME) |
1131 |
- frame_thread_free(avctx, avctx->thread_count); |
|
1131 |
+ ff_frame_thread_free(avctx, avctx->thread_count); |
|
1132 | 1132 |
else |
1133 |
- thread_free(avctx); |
|
1134 |
-} |
|
1135 |
- |
|
1136 |
-void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n) |
|
1137 |
-{ |
|
1138 |
- ThreadContext *p = avctx->thread_opaque; |
|
1139 |
- int *entries = p->entries; |
|
1140 |
- |
|
1141 |
- pthread_mutex_lock(&p->progress_mutex[thread]); |
|
1142 |
- entries[field] +=n; |
|
1143 |
- pthread_cond_signal(&p->progress_cond[thread]); |
|
1144 |
- pthread_mutex_unlock(&p->progress_mutex[thread]); |
|
1145 |
-} |
|
1146 |
- |
|
1147 |
-void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift) |
|
1148 |
-{ |
|
1149 |
- ThreadContext *p = avctx->thread_opaque; |
|
1150 |
- int *entries = p->entries; |
|
1151 |
- |
|
1152 |
- if (!entries || !field) return; |
|
1153 |
- |
|
1154 |
- thread = thread ? thread - 1 : p->thread_count - 1; |
|
1155 |
- |
|
1156 |
- pthread_mutex_lock(&p->progress_mutex[thread]); |
|
1157 |
- while ((entries[field - 1] - entries[field]) < shift){ |
|
1158 |
- pthread_cond_wait(&p->progress_cond[thread], &p->progress_mutex[thread]); |
|
1159 |
- } |
|
1160 |
- pthread_mutex_unlock(&p->progress_mutex[thread]); |
|
1161 |
-} |
|
1162 |
- |
|
1163 |
-int ff_alloc_entries(AVCodecContext *avctx, int count) |
|
1164 |
-{ |
|
1165 |
- int i; |
|
1166 |
- |
|
1167 |
- if (avctx->active_thread_type & FF_THREAD_SLICE) { |
|
1168 |
- ThreadContext *p = avctx->thread_opaque; |
|
1169 |
- p->thread_count = avctx->thread_count; |
|
1170 |
- p->entries = av_mallocz(count * sizeof(int)); |
|
1171 |
- |
|
1172 |
- if (!p->entries) { |
|
1173 |
- return AVERROR(ENOMEM); |
|
1174 |
- } |
|
1175 |
- |
|
1176 |
- p->entries_count = count; |
|
1177 |
- p->progress_mutex = av_malloc(p->thread_count * sizeof(pthread_mutex_t)); |
|
1178 |
- p->progress_cond = av_malloc(p->thread_count * sizeof(pthread_cond_t)); |
|
1179 |
- |
|
1180 |
- for (i = 0; i < p->thread_count; i++) { |
|
1181 |
- pthread_mutex_init(&p->progress_mutex[i], NULL); |
|
1182 |
- pthread_cond_init(&p->progress_cond[i], NULL); |
|
1183 |
- } |
|
1184 |
- } |
|
1185 |
- |
|
1186 |
- return 0; |
|
1187 |
-} |
|
1188 |
- |
|
1189 |
-void ff_reset_entries(AVCodecContext *avctx) |
|
1190 |
-{ |
|
1191 |
- ThreadContext *p = avctx->thread_opaque; |
|
1192 |
- memset(p->entries, 0, p->entries_count * sizeof(int)); |
|
1133 |
+ ff_slice_thread_free(avctx); |
|
1193 | 1134 |
} |
1194 | 1135 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,888 @@ |
0 |
+/* |
|
1 |
+ * This file is part of FFmpeg. |
|
2 |
+ * |
|
3 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
4 |
+ * modify it under the terms of the GNU Lesser General Public |
|
5 |
+ * License as published by the Free Software Foundation; either |
|
6 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
7 |
+ * |
|
8 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
11 |
+ * Lesser General Public License for more details. |
|
12 |
+ * |
|
13 |
+ * You should have received a copy of the GNU Lesser General Public |
|
14 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
15 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
16 |
+ */ |
|
17 |
+ |
|
18 |
+/** |
|
19 |
+ * @file |
|
20 |
+ * Frame multithreading support functions |
|
21 |
+ * @see doc/multithreading.txt |
|
22 |
+ */ |
|
23 |
+ |
|
24 |
+#include "config.h" |
|
25 |
+ |
|
26 |
+#include <stdint.h> |
|
27 |
+ |
|
28 |
+#if HAVE_PTHREADS |
|
29 |
+#include <pthread.h> |
|
30 |
+#elif HAVE_W32THREADS |
|
31 |
+#include "compat/w32pthreads.h" |
|
32 |
+#elif HAVE_OS2THREADS |
|
33 |
+#include "compat/os2threads.h" |
|
34 |
+#endif |
|
35 |
+ |
|
36 |
+#include "avcodec.h" |
|
37 |
+#include "internal.h" |
|
38 |
+#include "pthread_internal.h" |
|
39 |
+#include "thread.h" |
|
40 |
+ |
|
41 |
+#include "libavutil/avassert.h" |
|
42 |
+#include "libavutil/buffer.h" |
|
43 |
+#include "libavutil/common.h" |
|
44 |
+#include "libavutil/cpu.h" |
|
45 |
+#include "libavutil/frame.h" |
|
46 |
+#include "libavutil/log.h" |
|
47 |
+#include "libavutil/mem.h" |
|
48 |
+ |
|
49 |
+/** |
|
50 |
+ * Context used by codec threads and stored in their AVCodecContext thread_opaque. |
|
51 |
+ */ |
|
52 |
+typedef struct PerThreadContext { |
|
53 |
+ struct FrameThreadContext *parent; |
|
54 |
+ |
|
55 |
+ pthread_t thread; |
|
56 |
+ int thread_init; |
|
57 |
+ pthread_cond_t input_cond; ///< Used to wait for a new packet from the main thread. |
|
58 |
+ pthread_cond_t progress_cond; ///< Used by child threads to wait for progress to change. |
|
59 |
+ pthread_cond_t output_cond; ///< Used by the main thread to wait for frames to finish. |
|
60 |
+ |
|
61 |
+ pthread_mutex_t mutex; ///< Mutex used to protect the contents of the PerThreadContext. |
|
62 |
+ pthread_mutex_t progress_mutex; ///< Mutex used to protect frame progress values and progress_cond. |
|
63 |
+ |
|
64 |
+ AVCodecContext *avctx; ///< Context used to decode packets passed to this thread. |
|
65 |
+ |
|
66 |
+ AVPacket avpkt; ///< Input packet (for decoding) or output (for encoding). |
|
67 |
+ uint8_t *buf; ///< backup storage for packet data when the input packet is not refcounted |
|
68 |
+ int allocated_buf_size; ///< Size allocated for buf |
|
69 |
+ |
|
70 |
+ AVFrame frame; ///< Output frame (for decoding) or input (for encoding). |
|
71 |
+ int got_frame; ///< The output of got_picture_ptr from the last avcodec_decode_video() call. |
|
72 |
+ int result; ///< The result of the last codec decode/encode() call. |
|
73 |
+ |
|
74 |
+ enum { |
|
75 |
+ STATE_INPUT_READY, ///< Set when the thread is awaiting a packet. |
|
76 |
+ STATE_SETTING_UP, ///< Set before the codec has called ff_thread_finish_setup(). |
|
77 |
+ STATE_GET_BUFFER, /**< |
|
78 |
+ * Set when the codec calls get_buffer(). |
|
79 |
+ * State is returned to STATE_SETTING_UP afterwards. |
|
80 |
+ */ |
|
81 |
+ STATE_GET_FORMAT, /**< |
|
82 |
+ * Set when the codec calls get_format(). |
|
83 |
+ * State is returned to STATE_SETTING_UP afterwards. |
|
84 |
+ */ |
|
85 |
+ STATE_SETUP_FINISHED ///< Set after the codec has called ff_thread_finish_setup(). |
|
86 |
+ } state; |
|
87 |
+ |
|
88 |
+ /** |
|
89 |
+ * Array of frames passed to ff_thread_release_buffer(). |
|
90 |
+ * Frames are released after all threads referencing them are finished. |
|
91 |
+ */ |
|
92 |
+ AVFrame *released_buffers; |
|
93 |
+ int num_released_buffers; |
|
94 |
+ int released_buffers_allocated; |
|
95 |
+ |
|
96 |
+ AVFrame *requested_frame; ///< AVFrame the codec passed to get_buffer() |
|
97 |
+ int requested_flags; ///< flags passed to get_buffer() for requested_frame |
|
98 |
+ |
|
99 |
+ const enum AVPixelFormat *available_formats; ///< Format array for get_format() |
|
100 |
+ enum AVPixelFormat result_format; ///< get_format() result |
|
101 |
+} PerThreadContext; |
|
102 |
+ |
|
103 |
+/** |
|
104 |
+ * Context stored in the client AVCodecContext thread_opaque. |
|
105 |
+ */ |
|
106 |
+typedef struct FrameThreadContext { |
|
107 |
+ PerThreadContext *threads; ///< The contexts for each thread. |
|
108 |
+ PerThreadContext *prev_thread; ///< The last thread submit_packet() was called on. |
|
109 |
+ |
|
110 |
+ pthread_mutex_t buffer_mutex; ///< Mutex used to protect get/release_buffer(). |
|
111 |
+ |
|
112 |
+ int next_decoding; ///< The next context to submit a packet to. |
|
113 |
+ int next_finished; ///< The next context to return output from. |
|
114 |
+ |
|
115 |
+ int delaying; /**< |
|
116 |
+ * Set for the first N packets, where N is the number of threads. |
|
117 |
+ * While it is set, ff_thread_en/decode_frame won't return any results. |
|
118 |
+ */ |
|
119 |
+ |
|
120 |
+ int die; ///< Set when threads should exit. |
|
121 |
+} FrameThreadContext; |
|
122 |
+ |
|
123 |
+#define THREAD_SAFE_CALLBACKS(avctx) \ |
|
124 |
+((avctx)->thread_safe_callbacks || (!(avctx)->get_buffer && (avctx)->get_buffer2 == avcodec_default_get_buffer2)) |
|
125 |
+ |
|
126 |
+/** |
|
127 |
+ * Codec worker thread. |
|
128 |
+ * |
|
129 |
+ * Automatically calls ff_thread_finish_setup() if the codec does |
|
130 |
+ * not provide an update_thread_context method, or if the codec returns |
|
131 |
+ * before calling it. |
|
132 |
+ */ |
|
133 |
+static attribute_align_arg void *frame_worker_thread(void *arg) |
|
134 |
+{ |
|
135 |
+ PerThreadContext *p = arg; |
|
136 |
+ FrameThreadContext *fctx = p->parent; |
|
137 |
+ AVCodecContext *avctx = p->avctx; |
|
138 |
+ const AVCodec *codec = avctx->codec; |
|
139 |
+ |
|
140 |
+ pthread_mutex_lock(&p->mutex); |
|
141 |
+ while (1) { |
|
142 |
+ while (p->state == STATE_INPUT_READY && !fctx->die) |
|
143 |
+ pthread_cond_wait(&p->input_cond, &p->mutex); |
|
144 |
+ |
|
145 |
+ if (fctx->die) break; |
|
146 |
+ |
|
147 |
+ if (!codec->update_thread_context && THREAD_SAFE_CALLBACKS(avctx)) |
|
148 |
+ ff_thread_finish_setup(avctx); |
|
149 |
+ |
|
150 |
+ avcodec_get_frame_defaults(&p->frame); |
|
151 |
+ p->got_frame = 0; |
|
152 |
+ p->result = codec->decode(avctx, &p->frame, &p->got_frame, &p->avpkt); |
|
153 |
+ |
|
154 |
+ /* many decoders assign whole AVFrames, thus overwriting extended_data; |
|
155 |
+ * make sure it's set correctly */ |
|
156 |
+ p->frame.extended_data = p->frame.data; |
|
157 |
+ |
|
158 |
+ if (p->state == STATE_SETTING_UP) ff_thread_finish_setup(avctx); |
|
159 |
+ |
|
160 |
+ pthread_mutex_lock(&p->progress_mutex); |
|
161 |
+#if 0 //BUFREF-FIXME |
|
162 |
+ for (i = 0; i < MAX_BUFFERS; i++) |
|
163 |
+ if (p->progress_used[i] && (p->got_frame || p->result<0 || avctx->codec_id != AV_CODEC_ID_H264)) { |
|
164 |
+ p->progress[i][0] = INT_MAX; |
|
165 |
+ p->progress[i][1] = INT_MAX; |
|
166 |
+ } |
|
167 |
+#endif |
|
168 |
+ p->state = STATE_INPUT_READY; |
|
169 |
+ |
|
170 |
+ pthread_cond_broadcast(&p->progress_cond); |
|
171 |
+ pthread_cond_signal(&p->output_cond); |
|
172 |
+ pthread_mutex_unlock(&p->progress_mutex); |
|
173 |
+ } |
|
174 |
+ pthread_mutex_unlock(&p->mutex); |
|
175 |
+ |
|
176 |
+ return NULL; |
|
177 |
+} |
|
178 |
+ |
|
179 |
+/** |
|
180 |
+ * Update the next thread's AVCodecContext with values from the reference thread's context. |
|
181 |
+ * |
|
182 |
+ * @param dst The destination context. |
|
183 |
+ * @param src The source context. |
|
184 |
+ * @param for_user 0 if the destination is a codec thread, 1 if the destination is the user's thread |
|
185 |
+ */ |
|
186 |
+static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, int for_user) |
|
187 |
+{ |
|
188 |
+ int err = 0; |
|
189 |
+ |
|
190 |
+ if (dst != src) { |
|
191 |
+ dst->time_base = src->time_base; |
|
192 |
+ dst->width = src->width; |
|
193 |
+ dst->height = src->height; |
|
194 |
+ dst->pix_fmt = src->pix_fmt; |
|
195 |
+ |
|
196 |
+ dst->coded_width = src->coded_width; |
|
197 |
+ dst->coded_height = src->coded_height; |
|
198 |
+ |
|
199 |
+ dst->has_b_frames = src->has_b_frames; |
|
200 |
+ dst->idct_algo = src->idct_algo; |
|
201 |
+ |
|
202 |
+ dst->bits_per_coded_sample = src->bits_per_coded_sample; |
|
203 |
+ dst->sample_aspect_ratio = src->sample_aspect_ratio; |
|
204 |
+ dst->dtg_active_format = src->dtg_active_format; |
|
205 |
+ |
|
206 |
+ dst->profile = src->profile; |
|
207 |
+ dst->level = src->level; |
|
208 |
+ |
|
209 |
+ dst->bits_per_raw_sample = src->bits_per_raw_sample; |
|
210 |
+ dst->ticks_per_frame = src->ticks_per_frame; |
|
211 |
+ dst->color_primaries = src->color_primaries; |
|
212 |
+ |
|
213 |
+ dst->color_trc = src->color_trc; |
|
214 |
+ dst->colorspace = src->colorspace; |
|
215 |
+ dst->color_range = src->color_range; |
|
216 |
+ dst->chroma_sample_location = src->chroma_sample_location; |
|
217 |
+ |
|
218 |
+ dst->hwaccel = src->hwaccel; |
|
219 |
+ dst->hwaccel_context = src->hwaccel_context; |
|
220 |
+ |
|
221 |
+ dst->channels = src->channels; |
|
222 |
+ dst->sample_rate = src->sample_rate; |
|
223 |
+ dst->sample_fmt = src->sample_fmt; |
|
224 |
+ dst->channel_layout = src->channel_layout; |
|
225 |
+ } |
|
226 |
+ |
|
227 |
+ if (for_user) { |
|
228 |
+ dst->delay = src->thread_count - 1; |
|
229 |
+ dst->coded_frame = src->coded_frame; |
|
230 |
+ } else { |
|
231 |
+ if (dst->codec->update_thread_context) |
|
232 |
+ err = dst->codec->update_thread_context(dst, src); |
|
233 |
+ } |
|
234 |
+ |
|
235 |
+ return err; |
|
236 |
+} |
|
237 |
+ |
|
238 |
+/** |
|
239 |
+ * Update the next thread's AVCodecContext with values set by the user. |
|
240 |
+ * |
|
241 |
+ * @param dst The destination context. |
|
242 |
+ * @param src The source context. |
|
243 |
+ * @return 0 on success, negative error code on failure |
|
244 |
+ */ |
|
245 |
+static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) |
|
246 |
+{ |
|
247 |
+#define copy_fields(s, e) memcpy(&dst->s, &src->s, (char*)&dst->e - (char*)&dst->s); |
|
248 |
+ dst->flags = src->flags; |
|
249 |
+ |
|
250 |
+ dst->draw_horiz_band= src->draw_horiz_band; |
|
251 |
+ dst->get_buffer2 = src->get_buffer2; |
|
252 |
+#if FF_API_GET_BUFFER |
|
253 |
+FF_DISABLE_DEPRECATION_WARNINGS |
|
254 |
+ dst->get_buffer = src->get_buffer; |
|
255 |
+ dst->release_buffer = src->release_buffer; |
|
256 |
+FF_ENABLE_DEPRECATION_WARNINGS |
|
257 |
+#endif |
|
258 |
+ |
|
259 |
+ dst->opaque = src->opaque; |
|
260 |
+ dst->debug = src->debug; |
|
261 |
+ dst->debug_mv = src->debug_mv; |
|
262 |
+ |
|
263 |
+ dst->slice_flags = src->slice_flags; |
|
264 |
+ dst->flags2 = src->flags2; |
|
265 |
+ |
|
266 |
+ copy_fields(skip_loop_filter, subtitle_header); |
|
267 |
+ |
|
268 |
+ dst->frame_number = src->frame_number; |
|
269 |
+ dst->reordered_opaque = src->reordered_opaque; |
|
270 |
+ dst->thread_safe_callbacks = src->thread_safe_callbacks; |
|
271 |
+ |
|
272 |
+ if (src->slice_count && src->slice_offset) { |
|
273 |
+ if (dst->slice_count < src->slice_count) { |
|
274 |
+ int *tmp = av_realloc(dst->slice_offset, src->slice_count * |
|
275 |
+ sizeof(*dst->slice_offset)); |
|
276 |
+ if (!tmp) { |
|
277 |
+ av_free(dst->slice_offset); |
|
278 |
+ return AVERROR(ENOMEM); |
|
279 |
+ } |
|
280 |
+ dst->slice_offset = tmp; |
|
281 |
+ } |
|
282 |
+ memcpy(dst->slice_offset, src->slice_offset, |
|
283 |
+ src->slice_count * sizeof(*dst->slice_offset)); |
|
284 |
+ } |
|
285 |
+ dst->slice_count = src->slice_count; |
|
286 |
+ return 0; |
|
287 |
+#undef copy_fields |
|
288 |
+} |
|
289 |
+ |
|
290 |
+/// Releases the buffers that this decoding thread was the last user of. |
|
291 |
+static void release_delayed_buffers(PerThreadContext *p) |
|
292 |
+{ |
|
293 |
+ FrameThreadContext *fctx = p->parent; |
|
294 |
+ |
|
295 |
+ while (p->num_released_buffers > 0) { |
|
296 |
+ AVFrame *f; |
|
297 |
+ |
|
298 |
+ pthread_mutex_lock(&fctx->buffer_mutex); |
|
299 |
+ |
|
300 |
+ // fix extended data in case the caller screwed it up |
|
301 |
+ av_assert0(p->avctx->codec_type == AVMEDIA_TYPE_VIDEO || |
|
302 |
+ p->avctx->codec_type == AVMEDIA_TYPE_AUDIO); |
|
303 |
+ f = &p->released_buffers[--p->num_released_buffers]; |
|
304 |
+ f->extended_data = f->data; |
|
305 |
+ av_frame_unref(f); |
|
306 |
+ |
|
307 |
+ pthread_mutex_unlock(&fctx->buffer_mutex); |
|
308 |
+ } |
|
309 |
+} |
|
310 |
+ |
|
311 |
+static int submit_packet(PerThreadContext *p, AVPacket *avpkt) |
|
312 |
+{ |
|
313 |
+ FrameThreadContext *fctx = p->parent; |
|
314 |
+ PerThreadContext *prev_thread = fctx->prev_thread; |
|
315 |
+ const AVCodec *codec = p->avctx->codec; |
|
316 |
+ |
|
317 |
+ if (!avpkt->size && !(codec->capabilities & CODEC_CAP_DELAY)) return 0; |
|
318 |
+ |
|
319 |
+ pthread_mutex_lock(&p->mutex); |
|
320 |
+ |
|
321 |
+ release_delayed_buffers(p); |
|
322 |
+ |
|
323 |
+ if (prev_thread) { |
|
324 |
+ int err; |
|
325 |
+ if (prev_thread->state == STATE_SETTING_UP) { |
|
326 |
+ pthread_mutex_lock(&prev_thread->progress_mutex); |
|
327 |
+ while (prev_thread->state == STATE_SETTING_UP) |
|
328 |
+ pthread_cond_wait(&prev_thread->progress_cond, &prev_thread->progress_mutex); |
|
329 |
+ pthread_mutex_unlock(&prev_thread->progress_mutex); |
|
330 |
+ } |
|
331 |
+ |
|
332 |
+ err = update_context_from_thread(p->avctx, prev_thread->avctx, 0); |
|
333 |
+ if (err) { |
|
334 |
+ pthread_mutex_unlock(&p->mutex); |
|
335 |
+ return err; |
|
336 |
+ } |
|
337 |
+ } |
|
338 |
+ |
|
339 |
+ av_buffer_unref(&p->avpkt.buf); |
|
340 |
+ p->avpkt = *avpkt; |
|
341 |
+ if (avpkt->buf) |
|
342 |
+ p->avpkt.buf = av_buffer_ref(avpkt->buf); |
|
343 |
+ else { |
|
344 |
+ av_fast_malloc(&p->buf, &p->allocated_buf_size, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); |
|
345 |
+ p->avpkt.data = p->buf; |
|
346 |
+ memcpy(p->buf, avpkt->data, avpkt->size); |
|
347 |
+ memset(p->buf + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); |
|
348 |
+ } |
|
349 |
+ |
|
350 |
+ p->state = STATE_SETTING_UP; |
|
351 |
+ pthread_cond_signal(&p->input_cond); |
|
352 |
+ pthread_mutex_unlock(&p->mutex); |
|
353 |
+ |
|
354 |
+ /* |
|
355 |
+ * If the client doesn't have a thread-safe get_buffer(), |
|
356 |
+ * then decoding threads call back to the main thread, |
|
357 |
+ * and it calls back to the client here. |
|
358 |
+ */ |
|
359 |
+ |
|
360 |
+FF_DISABLE_DEPRECATION_WARNINGS |
|
361 |
+ if (!p->avctx->thread_safe_callbacks && ( |
|
362 |
+ p->avctx->get_format != avcodec_default_get_format || |
|
363 |
+#if FF_API_GET_BUFFER |
|
364 |
+ p->avctx->get_buffer || |
|
365 |
+#endif |
|
366 |
+ p->avctx->get_buffer2 != avcodec_default_get_buffer2)) { |
|
367 |
+FF_ENABLE_DEPRECATION_WARNINGS |
|
368 |
+ while (p->state != STATE_SETUP_FINISHED && p->state != STATE_INPUT_READY) { |
|
369 |
+ int call_done = 1; |
|
370 |
+ pthread_mutex_lock(&p->progress_mutex); |
|
371 |
+ while (p->state == STATE_SETTING_UP) |
|
372 |
+ pthread_cond_wait(&p->progress_cond, &p->progress_mutex); |
|
373 |
+ |
|
374 |
+ switch (p->state) { |
|
375 |
+ case STATE_GET_BUFFER: |
|
376 |
+ p->result = ff_get_buffer(p->avctx, p->requested_frame, p->requested_flags); |
|
377 |
+ break; |
|
378 |
+ case STATE_GET_FORMAT: |
|
379 |
+ p->result_format = p->avctx->get_format(p->avctx, p->available_formats); |
|
380 |
+ break; |
|
381 |
+ default: |
|
382 |
+ call_done = 0; |
|
383 |
+ break; |
|
384 |
+ } |
|
385 |
+ if (call_done) { |
|
386 |
+ p->state = STATE_SETTING_UP; |
|
387 |
+ pthread_cond_signal(&p->progress_cond); |
|
388 |
+ } |
|
389 |
+ pthread_mutex_unlock(&p->progress_mutex); |
|
390 |
+ } |
|
391 |
+ } |
|
392 |
+ |
|
393 |
+ fctx->prev_thread = p; |
|
394 |
+ fctx->next_decoding++; |
|
395 |
+ |
|
396 |
+ return 0; |
|
397 |
+} |
|
398 |
+ |
|
399 |
+int ff_thread_decode_frame(AVCodecContext *avctx, |
|
400 |
+ AVFrame *picture, int *got_picture_ptr, |
|
401 |
+ AVPacket *avpkt) |
|
402 |
+{ |
|
403 |
+ FrameThreadContext *fctx = avctx->thread_opaque; |
|
404 |
+ int finished = fctx->next_finished; |
|
405 |
+ PerThreadContext *p; |
|
406 |
+ int err; |
|
407 |
+ |
|
408 |
+ /* |
|
409 |
+ * Submit a packet to the next decoding thread. |
|
410 |
+ */ |
|
411 |
+ |
|
412 |
+ p = &fctx->threads[fctx->next_decoding]; |
|
413 |
+ err = update_context_from_user(p->avctx, avctx); |
|
414 |
+ if (err) return err; |
|
415 |
+ err = submit_packet(p, avpkt); |
|
416 |
+ if (err) return err; |
|
417 |
+ |
|
418 |
+ /* |
|
419 |
+ * If we're still receiving the initial packets, don't return a frame. |
|
420 |
+ */ |
|
421 |
+ |
|
422 |
+ if (fctx->next_decoding > (avctx->thread_count-1-(avctx->codec_id == AV_CODEC_ID_FFV1))) |
|
423 |
+ fctx->delaying = 0; |
|
424 |
+ |
|
425 |
+ if (fctx->delaying) { |
|
426 |
+ *got_picture_ptr=0; |
|
427 |
+ if (avpkt->size) |
|
428 |
+ return avpkt->size; |
|
429 |
+ } |
|
430 |
+ |
|
431 |
+ /* |
|
432 |
+ * Return the next available frame from the oldest thread. |
|
433 |
+ * If we're at the end of the stream, then we have to skip threads that |
|
434 |
+ * didn't output a frame, because we don't want to accidentally signal |
|
435 |
+ * EOF (avpkt->size == 0 && *got_picture_ptr == 0). |
|
436 |
+ */ |
|
437 |
+ |
|
438 |
+ do { |
|
439 |
+ p = &fctx->threads[finished++]; |
|
440 |
+ |
|
441 |
+ if (p->state != STATE_INPUT_READY) { |
|
442 |
+ pthread_mutex_lock(&p->progress_mutex); |
|
443 |
+ while (p->state != STATE_INPUT_READY) |
|
444 |
+ pthread_cond_wait(&p->output_cond, &p->progress_mutex); |
|
445 |
+ pthread_mutex_unlock(&p->progress_mutex); |
|
446 |
+ } |
|
447 |
+ |
|
448 |
+ av_frame_move_ref(picture, &p->frame); |
|
449 |
+ *got_picture_ptr = p->got_frame; |
|
450 |
+ picture->pkt_dts = p->avpkt.dts; |
|
451 |
+ |
|
452 |
+ /* |
|
453 |
+ * A later call with avkpt->size == 0 may loop over all threads, |
|
454 |
+ * including this one, searching for a frame to return before being |
|
455 |
+ * stopped by the "finished != fctx->next_finished" condition. |
|
456 |
+ * Make sure we don't mistakenly return the same frame again. |
|
457 |
+ */ |
|
458 |
+ p->got_frame = 0; |
|
459 |
+ |
|
460 |
+ if (finished >= avctx->thread_count) finished = 0; |
|
461 |
+ } while (!avpkt->size && !*got_picture_ptr && finished != fctx->next_finished); |
|
462 |
+ |
|
463 |
+ update_context_from_thread(avctx, p->avctx, 1); |
|
464 |
+ |
|
465 |
+ if (fctx->next_decoding >= avctx->thread_count) fctx->next_decoding = 0; |
|
466 |
+ |
|
467 |
+ fctx->next_finished = finished; |
|
468 |
+ |
|
469 |
+ /* return the size of the consumed packet if no error occurred */ |
|
470 |
+ return (p->result >= 0) ? avpkt->size : p->result; |
|
471 |
+} |
|
472 |
+ |
|
473 |
+void ff_thread_report_progress(ThreadFrame *f, int n, int field) |
|
474 |
+{ |
|
475 |
+ PerThreadContext *p; |
|
476 |
+ volatile int *progress = f->progress ? (int*)f->progress->data : NULL; |
|
477 |
+ |
|
478 |
+ if (!progress || progress[field] >= n) return; |
|
479 |
+ |
|
480 |
+ p = f->owner->thread_opaque; |
|
481 |
+ |
|
482 |
+ if (f->owner->debug&FF_DEBUG_THREADS) |
|
483 |
+ av_log(f->owner, AV_LOG_DEBUG, "%p finished %d field %d\n", progress, n, field); |
|
484 |
+ |
|
485 |
+ pthread_mutex_lock(&p->progress_mutex); |
|
486 |
+ progress[field] = n; |
|
487 |
+ pthread_cond_broadcast(&p->progress_cond); |
|
488 |
+ pthread_mutex_unlock(&p->progress_mutex); |
|
489 |
+} |
|
490 |
+ |
|
491 |
+void ff_thread_await_progress(ThreadFrame *f, int n, int field) |
|
492 |
+{ |
|
493 |
+ PerThreadContext *p; |
|
494 |
+ volatile int *progress = f->progress ? (int*)f->progress->data : NULL; |
|
495 |
+ |
|
496 |
+ if (!progress || progress[field] >= n) return; |
|
497 |
+ |
|
498 |
+ p = f->owner->thread_opaque; |
|
499 |
+ |
|
500 |
+ if (f->owner->debug&FF_DEBUG_THREADS) |
|
501 |
+ av_log(f->owner, AV_LOG_DEBUG, "thread awaiting %d field %d from %p\n", n, field, progress); |
|
502 |
+ |
|
503 |
+ pthread_mutex_lock(&p->progress_mutex); |
|
504 |
+ while (progress[field] < n) |
|
505 |
+ pthread_cond_wait(&p->progress_cond, &p->progress_mutex); |
|
506 |
+ pthread_mutex_unlock(&p->progress_mutex); |
|
507 |
+} |
|
508 |
+ |
|
509 |
+void ff_thread_finish_setup(AVCodecContext *avctx) { |
|
510 |
+ PerThreadContext *p = avctx->thread_opaque; |
|
511 |
+ |
|
512 |
+ if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return; |
|
513 |
+ |
|
514 |
+ if(p->state == STATE_SETUP_FINISHED){ |
|
515 |
+ av_log(avctx, AV_LOG_WARNING, "Multiple ff_thread_finish_setup() calls\n"); |
|
516 |
+ } |
|
517 |
+ |
|
518 |
+ pthread_mutex_lock(&p->progress_mutex); |
|
519 |
+ p->state = STATE_SETUP_FINISHED; |
|
520 |
+ pthread_cond_broadcast(&p->progress_cond); |
|
521 |
+ pthread_mutex_unlock(&p->progress_mutex); |
|
522 |
+} |
|
523 |
+ |
|
524 |
+/// Waits for all threads to finish. |
|
525 |
+static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count) |
|
526 |
+{ |
|
527 |
+ int i; |
|
528 |
+ |
|
529 |
+ for (i = 0; i < thread_count; i++) { |
|
530 |
+ PerThreadContext *p = &fctx->threads[i]; |
|
531 |
+ |
|
532 |
+ if (p->state != STATE_INPUT_READY) { |
|
533 |
+ pthread_mutex_lock(&p->progress_mutex); |
|
534 |
+ while (p->state != STATE_INPUT_READY) |
|
535 |
+ pthread_cond_wait(&p->output_cond, &p->progress_mutex); |
|
536 |
+ pthread_mutex_unlock(&p->progress_mutex); |
|
537 |
+ } |
|
538 |
+ p->got_frame = 0; |
|
539 |
+ } |
|
540 |
+} |
|
541 |
+ |
|
542 |
+void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) |
|
543 |
+{ |
|
544 |
+ FrameThreadContext *fctx = avctx->thread_opaque; |
|
545 |
+ const AVCodec *codec = avctx->codec; |
|
546 |
+ int i; |
|
547 |
+ |
|
548 |
+ park_frame_worker_threads(fctx, thread_count); |
|
549 |
+ |
|
550 |
+ if (fctx->prev_thread && fctx->prev_thread != fctx->threads) |
|
551 |
+ if (update_context_from_thread(fctx->threads->avctx, fctx->prev_thread->avctx, 0) < 0) { |
|
552 |
+ av_log(avctx, AV_LOG_ERROR, "Final thread update failed\n"); |
|
553 |
+ fctx->prev_thread->avctx->internal->is_copy = fctx->threads->avctx->internal->is_copy; |
|
554 |
+ fctx->threads->avctx->internal->is_copy = 1; |
|
555 |
+ } |
|
556 |
+ |
|
557 |
+ fctx->die = 1; |
|
558 |
+ |
|
559 |
+ for (i = 0; i < thread_count; i++) { |
|
560 |
+ PerThreadContext *p = &fctx->threads[i]; |
|
561 |
+ |
|
562 |
+ pthread_mutex_lock(&p->mutex); |
|
563 |
+ pthread_cond_signal(&p->input_cond); |
|
564 |
+ pthread_mutex_unlock(&p->mutex); |
|
565 |
+ |
|
566 |
+ if (p->thread_init) |
|
567 |
+ pthread_join(p->thread, NULL); |
|
568 |
+ p->thread_init=0; |
|
569 |
+ |
|
570 |
+ if (codec->close) |
|
571 |
+ codec->close(p->avctx); |
|
572 |
+ |
|
573 |
+ avctx->codec = NULL; |
|
574 |
+ |
|
575 |
+ release_delayed_buffers(p); |
|
576 |
+ av_frame_unref(&p->frame); |
|
577 |
+ } |
|
578 |
+ |
|
579 |
+ for (i = 0; i < thread_count; i++) { |
|
580 |
+ PerThreadContext *p = &fctx->threads[i]; |
|
581 |
+ |
|
582 |
+ pthread_mutex_destroy(&p->mutex); |
|
583 |
+ pthread_mutex_destroy(&p->progress_mutex); |
|
584 |
+ pthread_cond_destroy(&p->input_cond); |
|
585 |
+ pthread_cond_destroy(&p->progress_cond); |
|
586 |
+ pthread_cond_destroy(&p->output_cond); |
|
587 |
+ av_buffer_unref(&p->avpkt.buf); |
|
588 |
+ av_freep(&p->buf); |
|
589 |
+ av_freep(&p->released_buffers); |
|
590 |
+ |
|
591 |
+ if (i) { |
|
592 |
+ av_freep(&p->avctx->priv_data); |
|
593 |
+ av_freep(&p->avctx->internal); |
|
594 |
+ av_freep(&p->avctx->slice_offset); |
|
595 |
+ } |
|
596 |
+ |
|
597 |
+ av_freep(&p->avctx); |
|
598 |
+ } |
|
599 |
+ |
|
600 |
+ av_freep(&fctx->threads); |
|
601 |
+ pthread_mutex_destroy(&fctx->buffer_mutex); |
|
602 |
+ av_freep(&avctx->thread_opaque); |
|
603 |
+} |
|
604 |
+ |
|
605 |
+int ff_frame_thread_init(AVCodecContext *avctx) |
|
606 |
+{ |
|
607 |
+ int thread_count = avctx->thread_count; |
|
608 |
+ const AVCodec *codec = avctx->codec; |
|
609 |
+ AVCodecContext *src = avctx; |
|
610 |
+ FrameThreadContext *fctx; |
|
611 |
+ int i, err = 0; |
|
612 |
+ |
|
613 |
+#if HAVE_W32THREADS |
|
614 |
+ w32thread_init(); |
|
615 |
+#endif |
|
616 |
+ |
|
617 |
+ if (!thread_count) { |
|
618 |
+ int nb_cpus = av_cpu_count(); |
|
619 |
+ if ((avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || avctx->debug_mv) |
|
620 |
+ nb_cpus = 1; |
|
621 |
+ // use number of cores + 1 as thread count if there is more than one |
|
622 |
+ if (nb_cpus > 1) |
|
623 |
+ thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS); |
|
624 |
+ else |
|
625 |
+ thread_count = avctx->thread_count = 1; |
|
626 |
+ } |
|
627 |
+ |
|
628 |
+ if (thread_count <= 1) { |
|
629 |
+ avctx->active_thread_type = 0; |
|
630 |
+ return 0; |
|
631 |
+ } |
|
632 |
+ |
|
633 |
+ avctx->thread_opaque = fctx = av_mallocz(sizeof(FrameThreadContext)); |
|
634 |
+ |
|
635 |
+ fctx->threads = av_mallocz(sizeof(PerThreadContext) * thread_count); |
|
636 |
+ pthread_mutex_init(&fctx->buffer_mutex, NULL); |
|
637 |
+ fctx->delaying = 1; |
|
638 |
+ |
|
639 |
+ for (i = 0; i < thread_count; i++) { |
|
640 |
+ AVCodecContext *copy = av_malloc(sizeof(AVCodecContext)); |
|
641 |
+ PerThreadContext *p = &fctx->threads[i]; |
|
642 |
+ |
|
643 |
+ pthread_mutex_init(&p->mutex, NULL); |
|
644 |
+ pthread_mutex_init(&p->progress_mutex, NULL); |
|
645 |
+ pthread_cond_init(&p->input_cond, NULL); |
|
646 |
+ pthread_cond_init(&p->progress_cond, NULL); |
|
647 |
+ pthread_cond_init(&p->output_cond, NULL); |
|
648 |
+ |
|
649 |
+ p->parent = fctx; |
|
650 |
+ p->avctx = copy; |
|
651 |
+ |
|
652 |
+ if (!copy) { |
|
653 |
+ err = AVERROR(ENOMEM); |
|
654 |
+ goto error; |
|
655 |
+ } |
|
656 |
+ |
|
657 |
+ *copy = *src; |
|
658 |
+ copy->thread_opaque = p; |
|
659 |
+ copy->pkt = &p->avpkt; |
|
660 |
+ |
|
661 |
+ if (!i) { |
|
662 |
+ src = copy; |
|
663 |
+ |
|
664 |
+ if (codec->init) |
|
665 |
+ err = codec->init(copy); |
|
666 |
+ |
|
667 |
+ update_context_from_thread(avctx, copy, 1); |
|
668 |
+ } else { |
|
669 |
+ copy->priv_data = av_malloc(codec->priv_data_size); |
|
670 |
+ if (!copy->priv_data) { |
|
671 |
+ err = AVERROR(ENOMEM); |
|
672 |
+ goto error; |
|
673 |
+ } |
|
674 |
+ memcpy(copy->priv_data, src->priv_data, codec->priv_data_size); |
|
675 |
+ copy->internal = av_malloc(sizeof(AVCodecInternal)); |
|
676 |
+ if (!copy->internal) { |
|
677 |
+ err = AVERROR(ENOMEM); |
|
678 |
+ goto error; |
|
679 |
+ } |
|
680 |
+ *copy->internal = *src->internal; |
|
681 |
+ copy->internal->is_copy = 1; |
|
682 |
+ |
|
683 |
+ if (codec->init_thread_copy) |
|
684 |
+ err = codec->init_thread_copy(copy); |
|
685 |
+ } |
|
686 |
+ |
|
687 |
+ if (err) goto error; |
|
688 |
+ |
|
689 |
+ err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p)); |
|
690 |
+ p->thread_init= !err; |
|
691 |
+ if(!p->thread_init) |
|
692 |
+ goto error; |
|
693 |
+ } |
|
694 |
+ |
|
695 |
+ return 0; |
|
696 |
+ |
|
697 |
+error: |
|
698 |
+ ff_frame_thread_free(avctx, i+1); |
|
699 |
+ |
|
700 |
+ return err; |
|
701 |
+} |
|
702 |
+ |
|
703 |
+void ff_thread_flush(AVCodecContext *avctx) |
|
704 |
+{ |
|
705 |
+ int i; |
|
706 |
+ FrameThreadContext *fctx = avctx->thread_opaque; |
|
707 |
+ |
|
708 |
+ if (!avctx->thread_opaque) return; |
|
709 |
+ |
|
710 |
+ park_frame_worker_threads(fctx, avctx->thread_count); |
|
711 |
+ if (fctx->prev_thread) { |
|
712 |
+ if (fctx->prev_thread != &fctx->threads[0]) |
|
713 |
+ update_context_from_thread(fctx->threads[0].avctx, fctx->prev_thread->avctx, 0); |
|
714 |
+ if (avctx->codec->flush) |
|
715 |
+ avctx->codec->flush(fctx->threads[0].avctx); |
|
716 |
+ } |
|
717 |
+ |
|
718 |
+ fctx->next_decoding = fctx->next_finished = 0; |
|
719 |
+ fctx->delaying = 1; |
|
720 |
+ fctx->prev_thread = NULL; |
|
721 |
+ for (i = 0; i < avctx->thread_count; i++) { |
|
722 |
+ PerThreadContext *p = &fctx->threads[i]; |
|
723 |
+ // Make sure decode flush calls with size=0 won't return old frames |
|
724 |
+ p->got_frame = 0; |
|
725 |
+ av_frame_unref(&p->frame); |
|
726 |
+ |
|
727 |
+ release_delayed_buffers(p); |
|
728 |
+ } |
|
729 |
+} |
|
730 |
+ |
|
731 |
+int ff_thread_can_start_frame(AVCodecContext *avctx) |
|
732 |
+{ |
|
733 |
+ PerThreadContext *p = avctx->thread_opaque; |
|
734 |
+ if ((avctx->active_thread_type&FF_THREAD_FRAME) && p->state != STATE_SETTING_UP && |
|
735 |
+ (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) { |
|
736 |
+ return 0; |
|
737 |
+ } |
|
738 |
+ return 1; |
|
739 |
+} |
|
740 |
+ |
|
741 |
+static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int flags) |
|
742 |
+{ |
|
743 |
+ PerThreadContext *p = avctx->thread_opaque; |
|
744 |
+ int err; |
|
745 |
+ |
|
746 |
+ f->owner = avctx; |
|
747 |
+ |
|
748 |
+ ff_init_buffer_info(avctx, f->f); |
|
749 |
+ |
|
750 |
+ if (!(avctx->active_thread_type & FF_THREAD_FRAME)) |
|
751 |
+ return ff_get_buffer(avctx, f->f, flags); |
|
752 |
+ |
|
753 |
+ if (p->state != STATE_SETTING_UP && |
|
754 |
+ (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) { |
|
755 |
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n"); |
|
756 |
+ return -1; |
|
757 |
+ } |
|
758 |
+ |
|
759 |
+ if (avctx->internal->allocate_progress) { |
|
760 |
+ int *progress; |
|
761 |
+ f->progress = av_buffer_alloc(2 * sizeof(int)); |
|
762 |
+ if (!f->progress) { |
|
763 |
+ return AVERROR(ENOMEM); |
|
764 |
+ } |
|
765 |
+ progress = (int*)f->progress->data; |
|
766 |
+ |
|
767 |
+ progress[0] = progress[1] = -1; |
|
768 |
+ } |
|
769 |
+ |
|
770 |
+ pthread_mutex_lock(&p->parent->buffer_mutex); |
|
771 |
+FF_DISABLE_DEPRECATION_WARNINGS |
|
772 |
+ if (avctx->thread_safe_callbacks || ( |
|
773 |
+#if FF_API_GET_BUFFER |
|
774 |
+ !avctx->get_buffer && |
|
775 |
+#endif |
|
776 |
+ avctx->get_buffer2 == avcodec_default_get_buffer2)) { |
|
777 |
+FF_ENABLE_DEPRECATION_WARNINGS |
|
778 |
+ err = ff_get_buffer(avctx, f->f, flags); |
|
779 |
+ } else { |
|
780 |
+ pthread_mutex_lock(&p->progress_mutex); |
|
781 |
+ p->requested_frame = f->f; |
|
782 |
+ p->requested_flags = flags; |
|
783 |
+ p->state = STATE_GET_BUFFER; |
|
784 |
+ pthread_cond_broadcast(&p->progress_cond); |
|
785 |
+ |
|
786 |
+ while (p->state != STATE_SETTING_UP) |
|
787 |
+ pthread_cond_wait(&p->progress_cond, &p->progress_mutex); |
|
788 |
+ |
|
789 |
+ err = p->result; |
|
790 |
+ |
|
791 |
+ pthread_mutex_unlock(&p->progress_mutex); |
|
792 |
+ |
|
793 |
+ } |
|
794 |
+ if (!THREAD_SAFE_CALLBACKS(avctx) && !avctx->codec->update_thread_context) |
|
795 |
+ ff_thread_finish_setup(avctx); |
|
796 |
+ |
|
797 |
+ if (err) |
|
798 |
+ av_buffer_unref(&f->progress); |
|
799 |
+ |
|
800 |
+ pthread_mutex_unlock(&p->parent->buffer_mutex); |
|
801 |
+ |
|
802 |
+ return err; |
|
803 |
+} |
|
804 |
+ |
|
805 |
+enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) |
|
806 |
+{ |
|
807 |
+ enum AVPixelFormat res; |
|
808 |
+ PerThreadContext *p = avctx->thread_opaque; |
|
809 |
+ if (!(avctx->active_thread_type & FF_THREAD_FRAME) || avctx->thread_safe_callbacks || |
|
810 |
+ avctx->get_format == avcodec_default_get_format) |
|
811 |
+ return avctx->get_format(avctx, fmt); |
|
812 |
+ if (p->state != STATE_SETTING_UP) { |
|
813 |
+ av_log(avctx, AV_LOG_ERROR, "get_format() cannot be called after ff_thread_finish_setup()\n"); |
|
814 |
+ return -1; |
|
815 |
+ } |
|
816 |
+ pthread_mutex_lock(&p->progress_mutex); |
|
817 |
+ p->available_formats = fmt; |
|
818 |
+ p->state = STATE_GET_FORMAT; |
|
819 |
+ pthread_cond_broadcast(&p->progress_cond); |
|
820 |
+ |
|
821 |
+ while (p->state != STATE_SETTING_UP) |
|
822 |
+ pthread_cond_wait(&p->progress_cond, &p->progress_mutex); |
|
823 |
+ |
|
824 |
+ res = p->result_format; |
|
825 |
+ |
|
826 |
+ pthread_mutex_unlock(&p->progress_mutex); |
|
827 |
+ |
|
828 |
+ return res; |
|
829 |
+} |
|
830 |
+ |
|
831 |
+int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) |
|
832 |
+{ |
|
833 |
+ int ret = thread_get_buffer_internal(avctx, f, flags); |
|
834 |
+ if (ret < 0) |
|
835 |
+ av_log(avctx, AV_LOG_ERROR, "thread_get_buffer() failed\n"); |
|
836 |
+ return ret; |
|
837 |
+} |
|
838 |
+ |
|
839 |
+void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) |
|
840 |
+{ |
|
841 |
+ PerThreadContext *p = avctx->thread_opaque; |
|
842 |
+ FrameThreadContext *fctx; |
|
843 |
+ AVFrame *dst, *tmp; |
|
844 |
+FF_DISABLE_DEPRECATION_WARNINGS |
|
845 |
+ int can_direct_free = !(avctx->active_thread_type & FF_THREAD_FRAME) || |
|
846 |
+ avctx->thread_safe_callbacks || |
|
847 |
+ ( |
|
848 |
+#if FF_API_GET_BUFFER |
|
849 |
+ !avctx->get_buffer && |
|
850 |
+#endif |
|
851 |
+ avctx->get_buffer2 == avcodec_default_get_buffer2); |
|
852 |
+FF_ENABLE_DEPRECATION_WARNINGS |
|
853 |
+ |
|
854 |
+ if (!f->f->data[0]) |
|
855 |
+ return; |
|
856 |
+ |
|
857 |
+ if (avctx->debug & FF_DEBUG_BUFFERS) |
|
858 |
+ av_log(avctx, AV_LOG_DEBUG, "thread_release_buffer called on pic %p\n", f); |
|
859 |
+ |
|
860 |
+ av_buffer_unref(&f->progress); |
|
861 |
+ f->owner = NULL; |
|
862 |
+ |
|
863 |
+ if (can_direct_free) { |
|
864 |
+ av_frame_unref(f->f); |
|
865 |
+ return; |
|
866 |
+ } |
|
867 |
+ |
|
868 |
+ fctx = p->parent; |
|
869 |
+ pthread_mutex_lock(&fctx->buffer_mutex); |
|
870 |
+ |
|
871 |
+ if (p->num_released_buffers + 1 >= INT_MAX / sizeof(*p->released_buffers)) |
|
872 |
+ goto fail; |
|
873 |
+ tmp = av_fast_realloc(p->released_buffers, &p->released_buffers_allocated, |
|
874 |
+ (p->num_released_buffers + 1) * |
|
875 |
+ sizeof(*p->released_buffers)); |
|
876 |
+ if (!tmp) |
|
877 |
+ goto fail; |
|
878 |
+ p->released_buffers = tmp; |
|
879 |
+ |
|
880 |
+ dst = &p->released_buffers[p->num_released_buffers]; |
|
881 |
+ av_frame_move_ref(dst, f->f); |
|
882 |
+ |
|
883 |
+ p->num_released_buffers++; |
|
884 |
+ |
|
885 |
+fail: |
|
886 |
+ pthread_mutex_unlock(&fctx->buffer_mutex); |
|
887 |
+} |
0 | 888 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,34 @@ |
0 |
+/* |
|
1 |
+ * This file is part of FFmpeg. |
|
2 |
+ * |
|
3 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
4 |
+ * modify it under the terms of the GNU Lesser General Public |
|
5 |
+ * License as published by the Free Software Foundation; either |
|
6 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
7 |
+ * |
|
8 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
11 |
+ * Lesser General Public License for more details. |
|
12 |
+ * |
|
13 |
+ * You should have received a copy of the GNU Lesser General Public |
|
14 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
15 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
16 |
+ */ |
|
17 |
+ |
|
18 |
+#ifndef AVCODEC_PTHREAD_INTERNAL_H |
|
19 |
+#define AVCODEC_PTHREAD_INTERNAL_H |
|
20 |
+ |
|
21 |
+#include "avcodec.h" |
|
22 |
+ |
|
23 |
+/* H264 slice threading seems to be buggy with more than 16 threads, |
|
24 |
+ * limit the number of threads to 16 for automatic detection */ |
|
25 |
+#define MAX_AUTO_THREADS 16 |
|
26 |
+ |
|
27 |
+int ff_slice_thread_init(AVCodecContext *avctx); |
|
28 |
+void ff_slice_thread_free(AVCodecContext *avctx); |
|
29 |
+ |
|
30 |
+int ff_frame_thread_init(AVCodecContext *avctx); |
|
31 |
+void ff_frame_thread_free(AVCodecContext *avctx, int thread_count); |
|
32 |
+ |
|
33 |
+#endif // AVCODEC_PTHREAD_INTERNAL_H |
0 | 34 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,292 @@ |
0 |
+/* |
|
1 |
+ * This file is part of FFmpeg. |
|
2 |
+ * |
|
3 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
4 |
+ * modify it under the terms of the GNU Lesser General Public |
|
5 |
+ * License as published by the Free Software Foundation; either |
|
6 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
7 |
+ * |
|
8 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
11 |
+ * Lesser General Public License for more details. |
|
12 |
+ * |
|
13 |
+ * You should have received a copy of the GNU Lesser General Public |
|
14 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
15 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
16 |
+ */ |
|
17 |
+ |
|
18 |
+/** |
|
19 |
+ * @file |
|
20 |
+ * Slice multithreading support functions |
|
21 |
+ * @see doc/multithreading.txt |
|
22 |
+ */ |
|
23 |
+ |
|
24 |
+#include "config.h" |
|
25 |
+ |
|
26 |
+#if HAVE_PTHREADS |
|
27 |
+#include <pthread.h> |
|
28 |
+#elif HAVE_W32THREADS |
|
29 |
+#include "compat/w32pthreads.h" |
|
30 |
+#elif HAVE_OS2THREADS |
|
31 |
+#include "compat/os2threads.h" |
|
32 |
+#endif |
|
33 |
+ |
|
34 |
+#include "avcodec.h" |
|
35 |
+#include "internal.h" |
|
36 |
+#include "pthread_internal.h" |
|
37 |
+#include "thread.h" |
|
38 |
+ |
|
39 |
+#include "libavutil/common.h" |
|
40 |
+#include "libavutil/cpu.h" |
|
41 |
+#include "libavutil/mem.h" |
|
42 |
+ |
|
43 |
+typedef int (action_func)(AVCodecContext *c, void *arg); |
|
44 |
+typedef int (action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr); |
|
45 |
+ |
|
46 |
+typedef struct ThreadContext { |
|
47 |
+ pthread_t *workers; |
|
48 |
+ action_func *func; |
|
49 |
+ action_func2 *func2; |
|
50 |
+ void *args; |
|
51 |
+ int *rets; |
|
52 |
+ int rets_count; |
|
53 |
+ int job_count; |
|
54 |
+ int job_size; |
|
55 |
+ |
|
56 |
+ pthread_cond_t last_job_cond; |
|
57 |
+ pthread_cond_t current_job_cond; |
|
58 |
+ pthread_mutex_t current_job_lock; |
|
59 |
+ unsigned current_execute; |
|
60 |
+ int current_job; |
|
61 |
+ int done; |
|
62 |
+ |
|
63 |
+ int *entries; |
|
64 |
+ int entries_count; |
|
65 |
+ int thread_count; |
|
66 |
+ pthread_cond_t *progress_cond; |
|
67 |
+ pthread_mutex_t *progress_mutex; |
|
68 |
+} ThreadContext; |
|
69 |
+ |
|
70 |
+static void* attribute_align_arg worker(void *v) |
|
71 |
+{ |
|
72 |
+ AVCodecContext *avctx = v; |
|
73 |
+ ThreadContext *c = avctx->thread_opaque; |
|
74 |
+ unsigned last_execute = 0; |
|
75 |
+ int our_job = c->job_count; |
|
76 |
+ int thread_count = avctx->thread_count; |
|
77 |
+ int self_id; |
|
78 |
+ |
|
79 |
+ pthread_mutex_lock(&c->current_job_lock); |
|
80 |
+ self_id = c->current_job++; |
|
81 |
+ for (;;){ |
|
82 |
+ while (our_job >= c->job_count) { |
|
83 |
+ if (c->current_job == thread_count + c->job_count) |
|
84 |
+ pthread_cond_signal(&c->last_job_cond); |
|
85 |
+ |
|
86 |
+ while (last_execute == c->current_execute && !c->done) |
|
87 |
+ pthread_cond_wait(&c->current_job_cond, &c->current_job_lock); |
|
88 |
+ last_execute = c->current_execute; |
|
89 |
+ our_job = self_id; |
|
90 |
+ |
|
91 |
+ if (c->done) { |
|
92 |
+ pthread_mutex_unlock(&c->current_job_lock); |
|
93 |
+ return NULL; |
|
94 |
+ } |
|
95 |
+ } |
|
96 |
+ pthread_mutex_unlock(&c->current_job_lock); |
|
97 |
+ |
|
98 |
+ c->rets[our_job%c->rets_count] = c->func ? c->func(avctx, (char*)c->args + our_job*c->job_size): |
|
99 |
+ c->func2(avctx, c->args, our_job, self_id); |
|
100 |
+ |
|
101 |
+ pthread_mutex_lock(&c->current_job_lock); |
|
102 |
+ our_job = c->current_job++; |
|
103 |
+ } |
|
104 |
+} |
|
105 |
+ |
|
106 |
+void ff_slice_thread_free(AVCodecContext *avctx) |
|
107 |
+{ |
|
108 |
+ ThreadContext *c = avctx->thread_opaque; |
|
109 |
+ int i; |
|
110 |
+ |
|
111 |
+ pthread_mutex_lock(&c->current_job_lock); |
|
112 |
+ c->done = 1; |
|
113 |
+ pthread_cond_broadcast(&c->current_job_cond); |
|
114 |
+ pthread_mutex_unlock(&c->current_job_lock); |
|
115 |
+ |
|
116 |
+ for (i=0; i<avctx->thread_count; i++) |
|
117 |
+ pthread_join(c->workers[i], NULL); |
|
118 |
+ |
|
119 |
+ pthread_mutex_destroy(&c->current_job_lock); |
|
120 |
+ pthread_cond_destroy(&c->current_job_cond); |
|
121 |
+ pthread_cond_destroy(&c->last_job_cond); |
|
122 |
+ av_free(c->workers); |
|
123 |
+ av_freep(&avctx->thread_opaque); |
|
124 |
+} |
|
125 |
+ |
|
126 |
+static av_always_inline void thread_park_workers(ThreadContext *c, int thread_count) |
|
127 |
+{ |
|
128 |
+ while (c->current_job != thread_count + c->job_count) |
|
129 |
+ pthread_cond_wait(&c->last_job_cond, &c->current_job_lock); |
|
130 |
+ pthread_mutex_unlock(&c->current_job_lock); |
|
131 |
+} |
|
132 |
+ |
|
133 |
+static int thread_execute(AVCodecContext *avctx, action_func* func, void *arg, int *ret, int job_count, int job_size) |
|
134 |
+{ |
|
135 |
+ ThreadContext *c= avctx->thread_opaque; |
|
136 |
+ int dummy_ret; |
|
137 |
+ |
|
138 |
+ if (!(avctx->active_thread_type&FF_THREAD_SLICE) || avctx->thread_count <= 1) |
|
139 |
+ return avcodec_default_execute(avctx, func, arg, ret, job_count, job_size); |
|
140 |
+ |
|
141 |
+ if (job_count <= 0) |
|
142 |
+ return 0; |
|
143 |
+ |
|
144 |
+ pthread_mutex_lock(&c->current_job_lock); |
|
145 |
+ |
|
146 |
+ c->current_job = avctx->thread_count; |
|
147 |
+ c->job_count = job_count; |
|
148 |
+ c->job_size = job_size; |
|
149 |
+ c->args = arg; |
|
150 |
+ c->func = func; |
|
151 |
+ if (ret) { |
|
152 |
+ c->rets = ret; |
|
153 |
+ c->rets_count = job_count; |
|
154 |
+ } else { |
|
155 |
+ c->rets = &dummy_ret; |
|
156 |
+ c->rets_count = 1; |
|
157 |
+ } |
|
158 |
+ c->current_execute++; |
|
159 |
+ pthread_cond_broadcast(&c->current_job_cond); |
|
160 |
+ |
|
161 |
+ thread_park_workers(c, avctx->thread_count); |
|
162 |
+ |
|
163 |
+ return 0; |
|
164 |
+} |
|
165 |
+ |
|
166 |
+static int thread_execute2(AVCodecContext *avctx, action_func2* func2, void *arg, int *ret, int job_count) |
|
167 |
+{ |
|
168 |
+ ThreadContext *c= avctx->thread_opaque; |
|
169 |
+ c->func2 = func2; |
|
170 |
+ return thread_execute(avctx, NULL, arg, ret, job_count, 0); |
|
171 |
+} |
|
172 |
+ |
|
173 |
+int ff_slice_thread_init(AVCodecContext *avctx) |
|
174 |
+{ |
|
175 |
+ int i; |
|
176 |
+ ThreadContext *c; |
|
177 |
+ int thread_count = avctx->thread_count; |
|
178 |
+ |
|
179 |
+#if HAVE_W32THREADS |
|
180 |
+ w32thread_init(); |
|
181 |
+#endif |
|
182 |
+ |
|
183 |
+ if (!thread_count) { |
|
184 |
+ int nb_cpus = av_cpu_count(); |
|
185 |
+ if (avctx->height) |
|
186 |
+ nb_cpus = FFMIN(nb_cpus, (avctx->height+15)/16); |
|
187 |
+ // use number of cores + 1 as thread count if there is more than one |
|
188 |
+ if (nb_cpus > 1) |
|
189 |
+ thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS); |
|
190 |
+ else |
|
191 |
+ thread_count = avctx->thread_count = 1; |
|
192 |
+ } |
|
193 |
+ |
|
194 |
+ if (thread_count <= 1) { |
|
195 |
+ avctx->active_thread_type = 0; |
|
196 |
+ return 0; |
|
197 |
+ } |
|
198 |
+ |
|
199 |
+ c = av_mallocz(sizeof(ThreadContext)); |
|
200 |
+ if (!c) |
|
201 |
+ return -1; |
|
202 |
+ |
|
203 |
+ c->workers = av_mallocz(sizeof(pthread_t)*thread_count); |
|
204 |
+ if (!c->workers) { |
|
205 |
+ av_free(c); |
|
206 |
+ return -1; |
|
207 |
+ } |
|
208 |
+ |
|
209 |
+ avctx->thread_opaque = c; |
|
210 |
+ c->current_job = 0; |
|
211 |
+ c->job_count = 0; |
|
212 |
+ c->job_size = 0; |
|
213 |
+ c->done = 0; |
|
214 |
+ pthread_cond_init(&c->current_job_cond, NULL); |
|
215 |
+ pthread_cond_init(&c->last_job_cond, NULL); |
|
216 |
+ pthread_mutex_init(&c->current_job_lock, NULL); |
|
217 |
+ pthread_mutex_lock(&c->current_job_lock); |
|
218 |
+ for (i=0; i<thread_count; i++) { |
|
219 |
+ if(pthread_create(&c->workers[i], NULL, worker, avctx)) { |
|
220 |
+ avctx->thread_count = i; |
|
221 |
+ pthread_mutex_unlock(&c->current_job_lock); |
|
222 |
+ ff_thread_free(avctx); |
|
223 |
+ return -1; |
|
224 |
+ } |
|
225 |
+ } |
|
226 |
+ |
|
227 |
+ thread_park_workers(c, thread_count); |
|
228 |
+ |
|
229 |
+ avctx->execute = thread_execute; |
|
230 |
+ avctx->execute2 = thread_execute2; |
|
231 |
+ return 0; |
|
232 |
+} |
|
233 |
+ |
|
234 |
+void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n) |
|
235 |
+{ |
|
236 |
+ ThreadContext *p = avctx->thread_opaque; |
|
237 |
+ int *entries = p->entries; |
|
238 |
+ |
|
239 |
+ pthread_mutex_lock(&p->progress_mutex[thread]); |
|
240 |
+ entries[field] +=n; |
|
241 |
+ pthread_cond_signal(&p->progress_cond[thread]); |
|
242 |
+ pthread_mutex_unlock(&p->progress_mutex[thread]); |
|
243 |
+} |
|
244 |
+ |
|
245 |
+void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift) |
|
246 |
+{ |
|
247 |
+ ThreadContext *p = avctx->thread_opaque; |
|
248 |
+ int *entries = p->entries; |
|
249 |
+ |
|
250 |
+ if (!entries || !field) return; |
|
251 |
+ |
|
252 |
+ thread = thread ? thread - 1 : p->thread_count - 1; |
|
253 |
+ |
|
254 |
+ pthread_mutex_lock(&p->progress_mutex[thread]); |
|
255 |
+ while ((entries[field - 1] - entries[field]) < shift){ |
|
256 |
+ pthread_cond_wait(&p->progress_cond[thread], &p->progress_mutex[thread]); |
|
257 |
+ } |
|
258 |
+ pthread_mutex_unlock(&p->progress_mutex[thread]); |
|
259 |
+} |
|
260 |
+ |
|
261 |
+int ff_alloc_entries(AVCodecContext *avctx, int count) |
|
262 |
+{ |
|
263 |
+ int i; |
|
264 |
+ |
|
265 |
+ if (avctx->active_thread_type & FF_THREAD_SLICE) { |
|
266 |
+ ThreadContext *p = avctx->thread_opaque; |
|
267 |
+ p->thread_count = avctx->thread_count; |
|
268 |
+ p->entries = av_mallocz(count * sizeof(int)); |
|
269 |
+ |
|
270 |
+ if (!p->entries) { |
|
271 |
+ return AVERROR(ENOMEM); |
|
272 |
+ } |
|
273 |
+ |
|
274 |
+ p->entries_count = count; |
|
275 |
+ p->progress_mutex = av_malloc(p->thread_count * sizeof(pthread_mutex_t)); |
|
276 |
+ p->progress_cond = av_malloc(p->thread_count * sizeof(pthread_cond_t)); |
|
277 |
+ |
|
278 |
+ for (i = 0; i < p->thread_count; i++) { |
|
279 |
+ pthread_mutex_init(&p->progress_mutex[i], NULL); |
|
280 |
+ pthread_cond_init(&p->progress_cond[i], NULL); |
|
281 |
+ } |
|
282 |
+ } |
|
283 |
+ |
|
284 |
+ return 0; |
|
285 |
+} |
|
286 |
+ |
|
287 |
+void ff_reset_entries(AVCodecContext *avctx) |
|
288 |
+{ |
|
289 |
+ ThreadContext *p = avctx->thread_opaque; |
|
290 |
+ memset(p->entries, 0, p->entries_count * sizeof(int)); |
|
291 |
+} |