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