FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/pthread_frame.c
Date: 2024-04-25 05:10:44
Exec Total Coverage
Lines: 371 489 75.9%
Functions: 22 23 95.7%
Branches: 168 290 57.9%

Line Branch Exec Source
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 <stdatomic.h>
28 #include <stdint.h>
29
30 #include "avcodec.h"
31 #include "avcodec_internal.h"
32 #include "codec_internal.h"
33 #include "decode.h"
34 #include "hwaccel_internal.h"
35 #include "hwconfig.h"
36 #include "internal.h"
37 #include "pthread_internal.h"
38 #include "refstruct.h"
39 #include "thread.h"
40 #include "threadframe.h"
41 #include "version_major.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 #include "libavutil/opt.h"
52 #include "libavutil/thread.h"
53
54 enum {
55 /// Set when the thread is awaiting a packet.
56 STATE_INPUT_READY,
57 /// Set before the codec has called ff_thread_finish_setup().
58 STATE_SETTING_UP,
59 /// Set after the codec has called ff_thread_finish_setup().
60 STATE_SETUP_FINISHED,
61 };
62
63 enum {
64 UNINITIALIZED, ///< Thread has not been created, AVCodec->close mustn't be called
65 NEEDS_CLOSE, ///< FFCodec->close needs to be called
66 INITIALIZED, ///< Thread has been properly set up
67 };
68
69 typedef struct ThreadFrameProgress {
70 atomic_int progress[2];
71 } ThreadFrameProgress;
72
73 /**
74 * Context used by codec threads and stored in their AVCodecInternal thread_ctx.
75 */
76 typedef struct PerThreadContext {
77 struct FrameThreadContext *parent;
78
79 pthread_t thread;
80 int thread_init;
81 unsigned pthread_init_cnt;///< Number of successfully initialized mutexes/conditions
82 pthread_cond_t input_cond; ///< Used to wait for a new packet from the main thread.
83 pthread_cond_t progress_cond; ///< Used by child threads to wait for progress to change.
84 pthread_cond_t output_cond; ///< Used by the main thread to wait for frames to finish.
85
86 pthread_mutex_t mutex; ///< Mutex used to protect the contents of the PerThreadContext.
87 pthread_mutex_t progress_mutex; ///< Mutex used to protect frame progress values and progress_cond.
88
89 AVCodecContext *avctx; ///< Context used to decode packets passed to this thread.
90
91 AVPacket *avpkt; ///< Input packet (for decoding) or output (for encoding).
92
93 AVFrame *frame; ///< Output frame (for decoding) or input (for encoding).
94 int got_frame; ///< The output of got_picture_ptr from the last avcodec_decode_video() call.
95 int result; ///< The result of the last codec decode/encode() call.
96
97 atomic_int state;
98
99 int die; ///< Set when the thread should exit.
100
101 int hwaccel_serializing;
102 int async_serializing;
103
104 // set to 1 in ff_thread_finish_setup() when a threadsafe hwaccel is used;
105 // cannot check hwaccel caps directly, because
106 // worked threads clear hwaccel state for thread-unsafe hwaccels
107 // after each decode call
108 int hwaccel_threadsafe;
109
110 atomic_int debug_threads; ///< Set if the FF_DEBUG_THREADS option is set.
111 } PerThreadContext;
112
113 /**
114 * Context stored in the client AVCodecInternal thread_ctx.
115 */
116 typedef struct FrameThreadContext {
117 PerThreadContext *threads; ///< The contexts for each thread.
118 PerThreadContext *prev_thread; ///< The last thread submit_packet() was called on.
119
120 unsigned pthread_init_cnt; ///< Number of successfully initialized mutexes/conditions
121 pthread_mutex_t buffer_mutex; ///< Mutex used to protect get/release_buffer().
122 /**
123 * This lock is used for ensuring threads run in serial when thread-unsafe
124 * hwaccel is used.
125 */
126 pthread_mutex_t hwaccel_mutex;
127 pthread_mutex_t async_mutex;
128 pthread_cond_t async_cond;
129 int async_lock;
130
131 int next_decoding; ///< The next context to submit a packet to.
132 int next_finished; ///< The next context to return output from.
133
134 int delaying; /**<
135 * Set for the first N packets, where N is the number of threads.
136 * While it is set, ff_thread_en/decode_frame won't return any results.
137 */
138
139 /* hwaccel state for thread-unsafe hwaccels is temporarily stored here in
140 * order to transfer its ownership to the next decoding thread without the
141 * need for extra synchronization */
142 const AVHWAccel *stash_hwaccel;
143 void *stash_hwaccel_context;
144 void *stash_hwaccel_priv;
145 } FrameThreadContext;
146
147 1707 static int hwaccel_serial(const AVCodecContext *avctx)
148 {
149
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1707 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1707 return avctx->hwaccel && !(ffhwaccel(avctx->hwaccel)->caps_internal & HWACCEL_CAP_THREAD_SAFE);
150 }
151
152 620 static void async_lock(FrameThreadContext *fctx)
153 {
154 620 pthread_mutex_lock(&fctx->async_mutex);
155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 620 times.
620 while (fctx->async_lock)
156 pthread_cond_wait(&fctx->async_cond, &fctx->async_mutex);
157 620 fctx->async_lock = 1;
158 620 pthread_mutex_unlock(&fctx->async_mutex);
159 620 }
160
161 620 static void async_unlock(FrameThreadContext *fctx)
162 {
163 620 pthread_mutex_lock(&fctx->async_mutex);
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 620 times.
620 av_assert0(fctx->async_lock);
165 620 fctx->async_lock = 0;
166 620 pthread_cond_broadcast(&fctx->async_cond);
167 620 pthread_mutex_unlock(&fctx->async_mutex);
168 620 }
169
170 76 static void thread_set_name(PerThreadContext *p)
171 {
172 76 AVCodecContext *avctx = p->avctx;
173 76 int idx = p - p->parent->threads;
174 char name[16];
175
176 76 snprintf(name, sizeof(name), "av:%.7s:df%d", avctx->codec->name, idx);
177
178 76 ff_thread_setname(name);
179 76 }
180
181 /**
182 * Codec worker thread.
183 *
184 * Automatically calls ff_thread_finish_setup() if the codec does
185 * not provide an update_thread_context method, or if the codec returns
186 * before calling it.
187 */
188 76 static attribute_align_arg void *frame_worker_thread(void *arg)
189 {
190 76 PerThreadContext *p = arg;
191 76 AVCodecContext *avctx = p->avctx;
192 76 const FFCodec *codec = ffcodec(avctx->codec);
193
194 76 thread_set_name(p);
195
196 76 pthread_mutex_lock(&p->mutex);
197 while (1) {
198
4/4
✓ Branch 0 taken 702 times.
✓ Branch 1 taken 569 times.
✓ Branch 2 taken 626 times.
✓ Branch 3 taken 76 times.
1271 while (atomic_load(&p->state) == STATE_INPUT_READY && !p->die)
199 626 pthread_cond_wait(&p->input_cond, &p->mutex);
200
201
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 569 times.
645 if (p->die) break;
202
203
2/2
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 116 times.
569 if (!codec->update_thread_context)
204 453 ff_thread_finish_setup(avctx);
205
206 /* If a decoder supports hwaccel, then it must call ff_get_format().
207 * Since that call must happen before ff_thread_finish_setup(), the
208 * decoder is required to implement update_thread_context() and call
209 * ff_thread_finish_setup() manually. Therefore the above
210 * ff_thread_finish_setup() call did not happen and hwaccel_serializing
211 * cannot be true here. */
212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 av_assert0(!p->hwaccel_serializing);
213
214 /* if the previous thread uses thread-unsafe hwaccel then we take the
215 * lock to ensure the threads don't run concurrently */
216
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 569 times.
569 if (hwaccel_serial(avctx)) {
217 pthread_mutex_lock(&p->parent->hwaccel_mutex);
218 p->hwaccel_serializing = 1;
219 }
220
221 569 av_frame_unref(p->frame);
222 569 p->got_frame = 0;
223 569 p->result = codec->cb.decode(avctx, p->frame, &p->got_frame, p->avpkt);
224
225
4/6
✓ Branch 0 taken 569 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 538 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 31 times.
569 if ((p->result < 0 || !p->got_frame) && p->frame->buf[0])
226 av_frame_unref(p->frame);
227
228
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 538 times.
569 if (atomic_load(&p->state) == STATE_SETTING_UP)
229 31 ff_thread_finish_setup(avctx);
230
231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 if (p->hwaccel_serializing) {
232 /* wipe hwaccel state for thread-unsafe hwaccels to avoid stale
233 * pointers lying around;
234 * the state was transferred to FrameThreadContext in
235 * ff_thread_finish_setup(), so nothing is leaked */
236 avctx->hwaccel = NULL;
237 avctx->hwaccel_context = NULL;
238 avctx->internal->hwaccel_priv_data = NULL;
239
240 p->hwaccel_serializing = 0;
241 pthread_mutex_unlock(&p->parent->hwaccel_mutex);
242 }
243
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
569 av_assert0(!avctx->hwaccel ||
244 (ffhwaccel(avctx->hwaccel)->caps_internal & HWACCEL_CAP_THREAD_SAFE));
245
246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 if (p->async_serializing) {
247 p->async_serializing = 0;
248
249 async_unlock(p->parent);
250 }
251
252 569 pthread_mutex_lock(&p->progress_mutex);
253
254 569 atomic_store(&p->state, STATE_INPUT_READY);
255
256 569 pthread_cond_broadcast(&p->progress_cond);
257 569 pthread_cond_signal(&p->output_cond);
258 569 pthread_mutex_unlock(&p->progress_mutex);
259 }
260 76 pthread_mutex_unlock(&p->mutex);
261
262 76 return NULL;
263 }
264
265 /**
266 * Update the next thread's AVCodecContext with values from the reference thread's context.
267 *
268 * @param dst The destination context.
269 * @param src The source context.
270 * @param for_user 0 if the destination is a codec thread, 1 if the destination is the user's thread
271 * @return 0 on success, negative error code on failure
272 */
273 1119 static int update_context_from_thread(AVCodecContext *dst, const AVCodecContext *src, int for_user)
274 {
275 1119 const FFCodec *const codec = ffcodec(dst->codec);
276 1119 int err = 0;
277
278
5/6
✓ Branch 0 taken 1119 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 559 times.
✓ Branch 3 taken 560 times.
✓ Branch 4 taken 112 times.
✓ Branch 5 taken 447 times.
1119 if (dst != src && (for_user || codec->update_thread_context)) {
279 672 dst->time_base = src->time_base;
280 672 dst->framerate = src->framerate;
281 672 dst->width = src->width;
282 672 dst->height = src->height;
283 672 dst->pix_fmt = src->pix_fmt;
284 672 dst->sw_pix_fmt = src->sw_pix_fmt;
285
286 672 dst->coded_width = src->coded_width;
287 672 dst->coded_height = src->coded_height;
288
289 672 dst->has_b_frames = src->has_b_frames;
290 672 dst->idct_algo = src->idct_algo;
291 672 dst->properties = src->properties;
292
293 672 dst->bits_per_coded_sample = src->bits_per_coded_sample;
294 672 dst->sample_aspect_ratio = src->sample_aspect_ratio;
295
296 672 dst->profile = src->profile;
297 672 dst->level = src->level;
298
299 672 dst->bits_per_raw_sample = src->bits_per_raw_sample;
300 #if FF_API_TICKS_PER_FRAME
301 FF_DISABLE_DEPRECATION_WARNINGS
302 672 dst->ticks_per_frame = src->ticks_per_frame;
303 FF_ENABLE_DEPRECATION_WARNINGS
304 #endif
305 672 dst->color_primaries = src->color_primaries;
306
307 672 dst->color_trc = src->color_trc;
308 672 dst->colorspace = src->colorspace;
309 672 dst->color_range = src->color_range;
310 672 dst->chroma_sample_location = src->chroma_sample_location;
311
312 672 dst->sample_rate = src->sample_rate;
313 672 dst->sample_fmt = src->sample_fmt;
314 672 err = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout);
315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 672 times.
672 if (err < 0)
316 return err;
317
318
1/2
✓ Branch 0 taken 672 times.
✗ Branch 1 not taken.
672 if (!!dst->hw_frames_ctx != !!src->hw_frames_ctx ||
319
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 672 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
672 (dst->hw_frames_ctx && dst->hw_frames_ctx->data != src->hw_frames_ctx->data)) {
320 av_buffer_unref(&dst->hw_frames_ctx);
321
322 if (src->hw_frames_ctx) {
323 dst->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx);
324 if (!dst->hw_frames_ctx)
325 return AVERROR(ENOMEM);
326 }
327 }
328
329 672 dst->hwaccel_flags = src->hwaccel_flags;
330
331 672 ff_refstruct_replace(&dst->internal->pool, src->internal->pool);
332 }
333
334
2/2
✓ Branch 0 taken 560 times.
✓ Branch 1 taken 559 times.
1119 if (for_user) {
335
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 498 times.
560 if (codec->update_thread_context_for_user)
336 62 err = codec->update_thread_context_for_user(dst, src);
337 } else {
338 559 const PerThreadContext *p_src = src->internal->thread_ctx;
339 559 PerThreadContext *p_dst = dst->internal->thread_ctx;
340
341
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 447 times.
559 if (codec->update_thread_context) {
342 112 err = codec->update_thread_context(dst, src);
343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (err < 0)
344 return err;
345 }
346
347 // reset dst hwaccel state if needed
348
3/6
✓ Branch 0 taken 559 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 559 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 559 times.
559 av_assert0(p_dst->hwaccel_threadsafe ||
349 (!dst->hwaccel && !dst->internal->hwaccel_priv_data));
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 559 times.
559 if (p_dst->hwaccel_threadsafe &&
351 (!p_src->hwaccel_threadsafe || dst->hwaccel != src->hwaccel)) {
352 ff_hwaccel_uninit(dst);
353 p_dst->hwaccel_threadsafe = 0;
354 }
355
356 // propagate hwaccel state for threadsafe hwaccels
357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 559 times.
559 if (p_src->hwaccel_threadsafe) {
358 const FFHWAccel *hwaccel = ffhwaccel(src->hwaccel);
359 if (!dst->hwaccel) {
360 if (hwaccel->priv_data_size) {
361 av_assert0(hwaccel->update_thread_context);
362
363 dst->internal->hwaccel_priv_data =
364 av_mallocz(hwaccel->priv_data_size);
365 if (!dst->internal->hwaccel_priv_data)
366 return AVERROR(ENOMEM);
367 }
368 dst->hwaccel = src->hwaccel;
369 }
370 av_assert0(dst->hwaccel == src->hwaccel);
371
372 if (hwaccel->update_thread_context) {
373 err = hwaccel->update_thread_context(dst, src);
374 if (err < 0) {
375 av_log(dst, AV_LOG_ERROR, "Error propagating hwaccel state\n");
376 ff_hwaccel_uninit(dst);
377 return err;
378 }
379 }
380 p_dst->hwaccel_threadsafe = 1;
381 }
382 }
383
384 1119 return err;
385 }
386
387 /**
388 * Update the next thread's AVCodecContext with values set by the user.
389 *
390 * @param dst The destination context.
391 * @param src The source context.
392 * @return 0 on success, negative error code on failure
393 */
394 569 static int update_context_from_user(AVCodecContext *dst, const AVCodecContext *src)
395 {
396 int err;
397
398 569 dst->flags = src->flags;
399
400 569 dst->draw_horiz_band= src->draw_horiz_band;
401 569 dst->get_buffer2 = src->get_buffer2;
402
403 569 dst->opaque = src->opaque;
404 569 dst->debug = src->debug;
405
406 569 dst->slice_flags = src->slice_flags;
407 569 dst->flags2 = src->flags2;
408 569 dst->export_side_data = src->export_side_data;
409
410 569 dst->skip_loop_filter = src->skip_loop_filter;
411 569 dst->skip_idct = src->skip_idct;
412 569 dst->skip_frame = src->skip_frame;
413
414 569 dst->frame_num = src->frame_num;
415
416 569 av_packet_unref(dst->internal->last_pkt_props);
417 569 err = av_packet_copy_props(dst->internal->last_pkt_props, src->internal->last_pkt_props);
418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 if (err < 0)
419 return err;
420
421 569 return 0;
422 }
423
424 610 static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx,
425 AVPacket *avpkt)
426 {
427 610 FrameThreadContext *fctx = p->parent;
428 610 PerThreadContext *prev_thread = fctx->prev_thread;
429 610 const AVCodec *codec = p->avctx->codec;
430 int ret;
431
432
4/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 538 times.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 31 times.
610 if (!avpkt->size && !(codec->capabilities & AV_CODEC_CAP_DELAY))
433 41 return 0;
434
435 569 pthread_mutex_lock(&p->mutex);
436
437 569 ret = update_context_from_user(p->avctx, user_avctx);
438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 if (ret) {
439 pthread_mutex_unlock(&p->mutex);
440 return ret;
441 }
442 569 atomic_store_explicit(&p->debug_threads,
443 (p->avctx->debug & FF_DEBUG_THREADS) != 0,
444 memory_order_relaxed);
445
446
2/2
✓ Branch 0 taken 559 times.
✓ Branch 1 taken 10 times.
569 if (prev_thread) {
447 int err;
448
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 436 times.
559 if (atomic_load(&prev_thread->state) == STATE_SETTING_UP) {
449 123 pthread_mutex_lock(&prev_thread->progress_mutex);
450
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 123 times.
246 while (atomic_load(&prev_thread->state) == STATE_SETTING_UP)
451 123 pthread_cond_wait(&prev_thread->progress_cond, &prev_thread->progress_mutex);
452 123 pthread_mutex_unlock(&prev_thread->progress_mutex);
453 }
454
455 559 err = update_context_from_thread(p->avctx, prev_thread->avctx, 0);
456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 559 times.
559 if (err) {
457 pthread_mutex_unlock(&p->mutex);
458 return err;
459 }
460 }
461
462 /* transfer the stashed hwaccel state, if any */
463
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
569 av_assert0(!p->avctx->hwaccel || p->hwaccel_threadsafe);
464
1/2
✓ Branch 0 taken 569 times.
✗ Branch 1 not taken.
569 if (!p->hwaccel_threadsafe) {
465 569 FFSWAP(const AVHWAccel*, p->avctx->hwaccel, fctx->stash_hwaccel);
466 569 FFSWAP(void*, p->avctx->hwaccel_context, fctx->stash_hwaccel_context);
467 569 FFSWAP(void*, p->avctx->internal->hwaccel_priv_data, fctx->stash_hwaccel_priv);
468 }
469
470 569 av_packet_unref(p->avpkt);
471 569 ret = av_packet_ref(p->avpkt, avpkt);
472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 if (ret < 0) {
473 pthread_mutex_unlock(&p->mutex);
474 av_log(p->avctx, AV_LOG_ERROR, "av_packet_ref() failed in submit_packet()\n");
475 return ret;
476 }
477
478 569 atomic_store(&p->state, STATE_SETTING_UP);
479 569 pthread_cond_signal(&p->input_cond);
480 569 pthread_mutex_unlock(&p->mutex);
481
482 569 fctx->prev_thread = p;
483 569 fctx->next_decoding++;
484
485 569 return 0;
486 }
487
488 610 int ff_thread_decode_frame(AVCodecContext *avctx,
489 AVFrame *picture, int *got_picture_ptr,
490 AVPacket *avpkt)
491 {
492 610 FrameThreadContext *fctx = avctx->internal->thread_ctx;
493 610 int finished = fctx->next_finished;
494 PerThreadContext *p;
495 int err;
496
497 /* release the async lock, permitting blocked hwaccel threads to
498 * go forward while we are in this function */
499 610 async_unlock(fctx);
500
501 /*
502 * Submit a packet to the next decoding thread.
503 */
504
505 610 p = &fctx->threads[fctx->next_decoding];
506 610 err = submit_packet(p, avctx, avpkt);
507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 610 times.
610 if (err)
508 goto finish;
509
510 /*
511 * If we're still receiving the initial packets, don't return a frame.
512 */
513
514
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 488 times.
610 if (fctx->next_decoding > (avctx->thread_count-1-(avctx->codec_id == AV_CODEC_ID_FFV1)))
515 122 fctx->delaying = 0;
516
517
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 538 times.
610 if (fctx->delaying) {
518 72 *got_picture_ptr=0;
519
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 12 times.
72 if (avpkt->size) {
520 60 err = avpkt->size;
521 60 goto finish;
522 }
523 }
524
525 /*
526 * Return the next available frame from the oldest thread.
527 * If we're at the end of the stream, then we have to skip threads that
528 * didn't output a frame/error, because we don't want to accidentally signal
529 * EOF (avpkt->size == 0 && *got_picture_ptr == 0 && err >= 0).
530 */
531
532 do {
533 615 p = &fctx->threads[finished++];
534
535
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 476 times.
615 if (atomic_load(&p->state) != STATE_INPUT_READY) {
536 139 pthread_mutex_lock(&p->progress_mutex);
537
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 139 times.
278 while (atomic_load_explicit(&p->state, memory_order_relaxed) != STATE_INPUT_READY)
538 139 pthread_cond_wait(&p->output_cond, &p->progress_mutex);
539 139 pthread_mutex_unlock(&p->progress_mutex);
540 }
541
542 615 av_frame_move_ref(picture, p->frame);
543 615 *got_picture_ptr = p->got_frame;
544 615 picture->pkt_dts = p->avpkt->dts;
545 615 err = p->result;
546
547 /*
548 * A later call with avkpt->size == 0 may loop over all threads,
549 * including this one, searching for a frame/error to return before being
550 * stopped by the "finished != fctx->next_finished" condition.
551 * Make sure we don't mistakenly return the same frame/error again.
552 */
553 615 p->got_frame = 0;
554 615 p->result = 0;
555
556
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 487 times.
615 if (finished >= avctx->thread_count) finished = 0;
557
7/8
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 478 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 63 times.
✓ Branch 4 taken 74 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 65 times.
✓ Branch 7 taken 9 times.
615 } while (!avpkt->size && !*got_picture_ptr && err >= 0 && finished != fctx->next_finished);
558
559 550 update_context_from_thread(avctx, p->avctx, 1);
560
561
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 428 times.
550 if (fctx->next_decoding >= avctx->thread_count) fctx->next_decoding = 0;
562
563 550 fctx->next_finished = finished;
564
565 /* return the size of the consumed packet if no error occurred */
566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 550 times.
550 if (err >= 0)
567 550 err = avpkt->size;
568 finish:
569 610 async_lock(fctx);
570 610 return err;
571 }
572
573 417781 void ff_thread_report_progress(ThreadFrame *f, int n, int field)
574 {
575 PerThreadContext *p;
576
2/2
✓ Branch 0 taken 2450 times.
✓ Branch 1 taken 415331 times.
417781 atomic_int *progress = f->progress ? f->progress->progress : NULL;
577
578
2/2
✓ Branch 0 taken 2450 times.
✓ Branch 1 taken 415331 times.
417781 if (!progress ||
579
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 2423 times.
2450 atomic_load_explicit(&progress[field], memory_order_relaxed) >= n)
580 415358 return;
581
582 2423 p = f->owner[field]->internal->thread_ctx;
583
584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2423 times.
2423 if (atomic_load_explicit(&p->debug_threads, memory_order_relaxed))
585 av_log(f->owner[field], AV_LOG_DEBUG,
586 "%p finished %d field %d\n", progress, n, field);
587
588 2423 pthread_mutex_lock(&p->progress_mutex);
589
590 2423 atomic_store_explicit(&progress[field], n, memory_order_release);
591
592 2423 pthread_cond_broadcast(&p->progress_cond);
593 2423 pthread_mutex_unlock(&p->progress_mutex);
594 }
595
596 229975 void ff_thread_await_progress(const ThreadFrame *f, int n, int field)
597 {
598 PerThreadContext *p;
599
2/2
✓ Branch 0 taken 210326 times.
✓ Branch 1 taken 19649 times.
229975 atomic_int *progress = f->progress ? f->progress->progress : NULL;
600
601
2/2
✓ Branch 0 taken 210326 times.
✓ Branch 1 taken 19649 times.
229975 if (!progress ||
602
2/2
✓ Branch 0 taken 208892 times.
✓ Branch 1 taken 1434 times.
210326 atomic_load_explicit(&progress[field], memory_order_acquire) >= n)
603 228541 return;
604
605 1434 p = f->owner[field]->internal->thread_ctx;
606
607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1434 times.
1434 if (atomic_load_explicit(&p->debug_threads, memory_order_relaxed))
608 av_log(f->owner[field], AV_LOG_DEBUG,
609 "thread awaiting %d field %d from %p\n", n, field, progress);
610
611 1434 pthread_mutex_lock(&p->progress_mutex);
612
2/2
✓ Branch 0 taken 1442 times.
✓ Branch 1 taken 1434 times.
2876 while (atomic_load_explicit(&progress[field], memory_order_relaxed) < n)
613 1442 pthread_cond_wait(&p->progress_cond, &p->progress_mutex);
614 1434 pthread_mutex_unlock(&p->progress_mutex);
615 }
616
617 23214 void ff_thread_finish_setup(AVCodecContext *avctx) {
618 PerThreadContext *p;
619
620
2/2
✓ Branch 0 taken 22645 times.
✓ Branch 1 taken 569 times.
23214 if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return;
621
622 569 p = avctx->internal->thread_ctx;
623
624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 p->hwaccel_threadsafe = avctx->hwaccel &&
625 (ffhwaccel(avctx->hwaccel)->caps_internal & HWACCEL_CAP_THREAD_SAFE);
626
627
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 569 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
569 if (hwaccel_serial(avctx) && !p->hwaccel_serializing) {
628 pthread_mutex_lock(&p->parent->hwaccel_mutex);
629 p->hwaccel_serializing = 1;
630 }
631
632 /* this assumes that no hwaccel calls happen before ff_thread_finish_setup() */
633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 if (avctx->hwaccel &&
634 !(ffhwaccel(avctx->hwaccel)->caps_internal & HWACCEL_CAP_ASYNC_SAFE)) {
635 p->async_serializing = 1;
636
637 async_lock(p->parent);
638 }
639
640 /* thread-unsafe hwaccels share a single private data instance, so we
641 * save hwaccel state for passing to the next thread;
642 * this is done here so that this worker thread can wipe its own hwaccel
643 * state after decoding, without requiring synchronization */
644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 av_assert0(!p->parent->stash_hwaccel);
645
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 569 times.
569 if (hwaccel_serial(avctx)) {
646 p->parent->stash_hwaccel = avctx->hwaccel;
647 p->parent->stash_hwaccel_context = avctx->hwaccel_context;
648 p->parent->stash_hwaccel_priv = avctx->internal->hwaccel_priv_data;
649 }
650
651 569 pthread_mutex_lock(&p->progress_mutex);
652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 569 times.
569 if(atomic_load(&p->state) == STATE_SETUP_FINISHED){
653 av_log(avctx, AV_LOG_WARNING, "Multiple ff_thread_finish_setup() calls\n");
654 }
655
656 569 atomic_store(&p->state, STATE_SETUP_FINISHED);
657
658 569 pthread_cond_broadcast(&p->progress_cond);
659 569 pthread_mutex_unlock(&p->progress_mutex);
660 }
661
662 /// Waits for all threads to finish.
663 10 static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count)
664 {
665 int i;
666
667 10 async_unlock(fctx);
668
669
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 10 times.
86 for (i = 0; i < thread_count; i++) {
670 76 PerThreadContext *p = &fctx->threads[i];
671
672
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 75 times.
76 if (atomic_load(&p->state) != STATE_INPUT_READY) {
673 1 pthread_mutex_lock(&p->progress_mutex);
674
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 while (atomic_load(&p->state) != STATE_INPUT_READY)
675 1 pthread_cond_wait(&p->output_cond, &p->progress_mutex);
676 1 pthread_mutex_unlock(&p->progress_mutex);
677 }
678 76 p->got_frame = 0;
679 }
680
681 10 async_lock(fctx);
682 10 }
683
684 #define OFF(member) offsetof(FrameThreadContext, member)
685 DEFINE_OFFSET_ARRAY(FrameThreadContext, thread_ctx, pthread_init_cnt,
686 (OFF(buffer_mutex), OFF(hwaccel_mutex), OFF(async_mutex)),
687 (OFF(async_cond)));
688 #undef OFF
689
690 #define OFF(member) offsetof(PerThreadContext, member)
691 DEFINE_OFFSET_ARRAY(PerThreadContext, per_thread, pthread_init_cnt,
692 (OFF(progress_mutex), OFF(mutex)),
693 (OFF(input_cond), OFF(progress_cond), OFF(output_cond)));
694 #undef OFF
695
696 10 void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
697 {
698 10 FrameThreadContext *fctx = avctx->internal->thread_ctx;
699 10 const FFCodec *codec = ffcodec(avctx->codec);
700 int i;
701
702 10 park_frame_worker_threads(fctx, thread_count);
703
704
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 10 times.
86 for (i = 0; i < thread_count; i++) {
705 76 PerThreadContext *p = &fctx->threads[i];
706 76 AVCodecContext *ctx = p->avctx;
707
708
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 if (ctx->internal) {
709
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 if (p->thread_init == INITIALIZED) {
710 76 pthread_mutex_lock(&p->mutex);
711 76 p->die = 1;
712 76 pthread_cond_signal(&p->input_cond);
713 76 pthread_mutex_unlock(&p->mutex);
714
715 76 pthread_join(p->thread, NULL);
716 }
717
2/4
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✗ Branch 3 not taken.
76 if (codec->close && p->thread_init != UNINITIALIZED)
718 76 codec->close(ctx);
719
720 /* When using a threadsafe hwaccel, this is where
721 * each thread's context is uninit'd and freed. */
722 76 ff_hwaccel_uninit(ctx);
723
724
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 if (ctx->priv_data) {
725
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 18 times.
76 if (codec->p.priv_class)
726 58 av_opt_free(ctx->priv_data);
727 76 av_freep(&ctx->priv_data);
728 }
729
730 76 ff_refstruct_unref(&ctx->internal->pool);
731 76 av_packet_free(&ctx->internal->last_pkt_props);
732 76 av_freep(&ctx->internal);
733 76 av_buffer_unref(&ctx->hw_frames_ctx);
734 76 av_frame_side_data_free(&ctx->decoded_side_data,
735 &ctx->nb_decoded_side_data);
736 }
737
738 76 av_frame_free(&p->frame);
739
740 76 ff_pthread_free(p, per_thread_offsets);
741 76 av_packet_free(&p->avpkt);
742
743 76 av_freep(&p->avctx);
744 }
745
746 10 av_freep(&fctx->threads);
747 10 ff_pthread_free(fctx, thread_ctx_offsets);
748
749 /* if we have stashed hwaccel state, move it to the user-facing context,
750 * so it will be freed in ff_codec_close() */
751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 av_assert0(!avctx->hwaccel);
752 10 FFSWAP(const AVHWAccel*, avctx->hwaccel, fctx->stash_hwaccel);
753 10 FFSWAP(void*, avctx->hwaccel_context, fctx->stash_hwaccel_context);
754 10 FFSWAP(void*, avctx->internal->hwaccel_priv_data, fctx->stash_hwaccel_priv);
755
756 10 av_freep(&avctx->internal->thread_ctx);
757 10 }
758
759 76 static av_cold int init_thread(PerThreadContext *p, int *threads_to_free,
760 FrameThreadContext *fctx, AVCodecContext *avctx,
761 const FFCodec *codec, int first)
762 {
763 AVCodecContext *copy;
764 int err;
765
766 76 atomic_init(&p->state, STATE_INPUT_READY);
767
768 76 copy = av_memdup(avctx, sizeof(*avctx));
769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (!copy)
770 return AVERROR(ENOMEM);
771 76 copy->priv_data = NULL;
772 76 copy->decoded_side_data = NULL;
773 76 copy->nb_decoded_side_data = 0;
774
775 /* From now on, this PerThreadContext will be cleaned up by
776 * ff_frame_thread_free in case of errors. */
777 76 (*threads_to_free)++;
778
779 76 p->parent = fctx;
780 76 p->avctx = copy;
781
782 76 copy->internal = ff_decode_internal_alloc();
783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (!copy->internal)
784 return AVERROR(ENOMEM);
785 76 copy->internal->thread_ctx = p;
786 76 copy->internal->progress_frame_pool = avctx->internal->progress_frame_pool;
787
788 76 copy->delay = avctx->delay;
789
790
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 if (codec->priv_data_size) {
791 76 copy->priv_data = av_mallocz(codec->priv_data_size);
792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (!copy->priv_data)
793 return AVERROR(ENOMEM);
794
795
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 18 times.
76 if (codec->p.priv_class) {
796 58 *(const AVClass **)copy->priv_data = codec->p.priv_class;
797 58 err = av_opt_copy(copy->priv_data, avctx->priv_data);
798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (err < 0)
799 return err;
800 }
801 }
802
803 76 err = ff_pthread_init(p, per_thread_offsets);
804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (err < 0)
805 return err;
806
807
1/2
✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
76 if (!(p->frame = av_frame_alloc()) ||
808
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
76 !(p->avpkt = av_packet_alloc()))
809 return AVERROR(ENOMEM);
810
811
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 10 times.
76 if (!first)
812 66 copy->internal->is_copy = 1;
813
814 76 copy->internal->last_pkt_props = av_packet_alloc();
815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (!copy->internal->last_pkt_props)
816 return AVERROR(ENOMEM);
817
818
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 if (codec->init) {
819 76 err = codec->init(copy);
820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (err < 0) {
821 if (codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP)
822 p->thread_init = NEEDS_CLOSE;
823 return err;
824 }
825 }
826 76 p->thread_init = NEEDS_CLOSE;
827
828
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 66 times.
76 if (first) {
829 10 update_context_from_thread(avctx, copy, 1);
830
831 10 av_frame_side_data_free(&avctx->decoded_side_data, &avctx->nb_decoded_side_data);
832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 for (int i = 0; i < copy->nb_decoded_side_data; i++) {
833 err = av_frame_side_data_clone(&avctx->decoded_side_data,
834 &avctx->nb_decoded_side_data,
835 copy->decoded_side_data[i], 0);
836 if (err < 0)
837 return err;
838 }
839 }
840
841 76 atomic_init(&p->debug_threads, (copy->debug & FF_DEBUG_THREADS) != 0);
842
843 76 err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p));
844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (err < 0)
845 return err;
846 76 p->thread_init = INITIALIZED;
847
848 76 return 0;
849 }
850
851 10 int ff_frame_thread_init(AVCodecContext *avctx)
852 {
853 10 int thread_count = avctx->thread_count;
854 10 const FFCodec *codec = ffcodec(avctx->codec);
855 FrameThreadContext *fctx;
856 10 int err, i = 0;
857
858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!thread_count) {
859 int nb_cpus = av_cpu_count();
860 // use number of cores + 1 as thread count if there is more than one
861 if (nb_cpus > 1)
862 thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS);
863 else
864 thread_count = avctx->thread_count = 1;
865 }
866
867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (thread_count <= 1) {
868 avctx->active_thread_type = 0;
869 return 0;
870 }
871
872 10 avctx->internal->thread_ctx = fctx = av_mallocz(sizeof(FrameThreadContext));
873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!fctx)
874 return AVERROR(ENOMEM);
875
876 10 err = ff_pthread_init(fctx, thread_ctx_offsets);
877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (err < 0) {
878 ff_pthread_free(fctx, thread_ctx_offsets);
879 av_freep(&avctx->internal->thread_ctx);
880 return err;
881 }
882
883 10 fctx->async_lock = 1;
884 10 fctx->delaying = 1;
885
886
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 if (codec->p.type == AVMEDIA_TYPE_VIDEO)
887 6 avctx->delay = avctx->thread_count - 1;
888
889 10 fctx->threads = av_calloc(thread_count, sizeof(*fctx->threads));
890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!fctx->threads) {
891 err = AVERROR(ENOMEM);
892 goto error;
893 }
894
895
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 10 times.
86 for (; i < thread_count; ) {
896 76 PerThreadContext *p = &fctx->threads[i];
897 76 int first = !i;
898
899 76 err = init_thread(p, &i, fctx, avctx, codec, first);
900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (err < 0)
901 goto error;
902 }
903
904 10 return 0;
905
906 error:
907 ff_frame_thread_free(avctx, i);
908 return err;
909 }
910
911 void ff_thread_flush(AVCodecContext *avctx)
912 {
913 int i;
914 FrameThreadContext *fctx = avctx->internal->thread_ctx;
915
916 if (!fctx) return;
917
918 park_frame_worker_threads(fctx, avctx->thread_count);
919 if (fctx->prev_thread) {
920 if (fctx->prev_thread != &fctx->threads[0])
921 update_context_from_thread(fctx->threads[0].avctx, fctx->prev_thread->avctx, 0);
922 }
923
924 fctx->next_decoding = fctx->next_finished = 0;
925 fctx->delaying = 1;
926 fctx->prev_thread = NULL;
927 for (i = 0; i < avctx->thread_count; i++) {
928 PerThreadContext *p = &fctx->threads[i];
929 // Make sure decode flush calls with size=0 won't return old frames
930 p->got_frame = 0;
931 av_frame_unref(p->frame);
932 p->result = 0;
933
934 if (ffcodec(avctx->codec)->flush)
935 ffcodec(avctx->codec)->flush(p->avctx);
936 }
937 }
938
939 36824 int ff_thread_can_start_frame(AVCodecContext *avctx)
940 {
941
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 36772 times.
36824 if ((avctx->active_thread_type & FF_THREAD_FRAME) &&
942
1/2
✓ Branch 1 taken 52 times.
✗ Branch 2 not taken.
52 ffcodec(avctx->codec)->update_thread_context) {
943 52 PerThreadContext *p = avctx->internal->thread_ctx;
944
945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (atomic_load(&p->state) != STATE_SETTING_UP)
946 return 0;
947 }
948
949 36824 return 1;
950 }
951
952 39653 static int thread_get_buffer_internal(AVCodecContext *avctx, AVFrame *f, int flags)
953 {
954 PerThreadContext *p;
955 int err;
956
957
2/2
✓ Branch 0 taken 39115 times.
✓ Branch 1 taken 538 times.
39653 if (!(avctx->active_thread_type & FF_THREAD_FRAME))
958 39115 return ff_get_buffer(avctx, f, flags);
959
960 538 p = avctx->internal->thread_ctx;
961
2/2
✓ Branch 0 taken 453 times.
✓ Branch 1 taken 85 times.
538 if (atomic_load(&p->state) != STATE_SETTING_UP &&
962
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 453 times.
453 ffcodec(avctx->codec)->update_thread_context) {
963 av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n");
964 return -1;
965 }
966
967 538 pthread_mutex_lock(&p->parent->buffer_mutex);
968 538 err = ff_get_buffer(avctx, f, flags);
969
970 538 pthread_mutex_unlock(&p->parent->buffer_mutex);
971
972 538 return err;
973 }
974
975 39653 int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags)
976 {
977 39653 int ret = thread_get_buffer_internal(avctx, f, flags);
978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39653 times.
39653 if (ret < 0)
979 av_log(avctx, AV_LOG_ERROR, "thread_get_buffer() failed\n");
980 39653 return ret;
981 }
982
983 36748 int ff_thread_get_ext_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags)
984 {
985 int ret;
986
987 36748 f->owner[0] = f->owner[1] = avctx;
988 /* Hint: It is possible for this function to be called with codecs
989 * that don't support frame threading at all, namely in case
990 * a frame-threaded decoder shares code with codecs that are not.
991 * This currently affects non-MPEG-4 mpegvideo codecs.
992 * The following check will always be true for them. */
993
2/2
✓ Branch 0 taken 36696 times.
✓ Branch 1 taken 52 times.
36748 if (!(avctx->active_thread_type & FF_THREAD_FRAME))
994 36696 return ff_get_buffer(avctx, f->f, flags);
995
996 52 f->progress = ff_refstruct_allocz(sizeof(*f->progress));
997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (!f->progress)
998 return AVERROR(ENOMEM);
999
1000 52 atomic_init(&f->progress->progress[0], -1);
1001 52 atomic_init(&f->progress->progress[1], -1);
1002
1003 52 ret = ff_thread_get_buffer(avctx, f->f, flags);
1004
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (ret)
1005 ff_refstruct_unref(&f->progress);
1006 52 return ret;
1007 }
1008
1009 907539 void ff_thread_release_ext_buffer(ThreadFrame *f)
1010 {
1011 907539 ff_refstruct_unref(&f->progress);
1012 907539 f->owner[0] = f->owner[1] = NULL;
1013
2/2
✓ Branch 0 taken 907437 times.
✓ Branch 1 taken 102 times.
907539 if (f->f)
1014 907437 av_frame_unref(f->f);
1015 907539 }
1016
1017 68 enum ThreadingStatus ff_thread_sync_ref(AVCodecContext *avctx, size_t offset)
1018 {
1019 PerThreadContext *p;
1020 const void *ref;
1021
1022
1/2
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
68 if (!avctx->internal->is_copy)
1023 68 return avctx->active_thread_type & FF_THREAD_FRAME ?
1024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 FF_THREAD_IS_FIRST_THREAD : FF_THREAD_NO_FRAME_THREADING;
1025
1026 p = avctx->internal->thread_ctx;
1027
1028 av_assert1(memcpy(&ref, (char*)avctx->priv_data + offset, sizeof(ref)) && ref == NULL);
1029
1030 memcpy(&ref, (const char*)p->parent->threads[0].avctx->priv_data + offset, sizeof(ref));
1031 av_assert1(ref);
1032 ff_refstruct_replace((char*)avctx->priv_data + offset, ref);
1033
1034 return FF_THREAD_IS_COPY;
1035 }
1036