diff options
author | Anton Khirnov <anton@khirnov.net> | 2020-05-22 15:59:46 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2020-11-27 15:46:50 +0100 |
commit | a83098ab03a47179d54a9b9c8bcefc81b9c6aafd (patch) | |
tree | 3f12682fa2917e3e83b4a3a6459a4be9cf51210d /libavcodec/pthread_frame.c | |
parent | 551ca67afe7555368758c4aab476978689380a6d (diff) | |
download | ffmpeg-a83098ab03a47179d54a9b9c8bcefc81b9c6aafd.tar.gz |
avcodec: deprecate thread_safe_callbacks
They add considerable complexity to frame-threading implementation,
which includes an unavoidably leaking error path, while the advantages
of this option to the users are highly dubious.
It should be always possible and desirable for the callers to make their
get_buffer2() implementation thread-safe, so deprecate this option.
Diffstat (limited to 'libavcodec/pthread_frame.c')
-rw-r--r-- | libavcodec/pthread_frame.c | 68 |
1 files changed, 63 insertions, 5 deletions
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index f8a01ad8cd..c9d2e00ce3 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -89,6 +89,7 @@ typedef struct PerThreadContext { atomic_int state; +#if FF_API_THREAD_SAFE_CALLBACKS /** * Array of frames passed to ff_thread_release_buffer(). * Frames are released after all threads referencing them are finished. @@ -102,6 +103,7 @@ typedef struct PerThreadContext { const enum AVPixelFormat *available_formats; ///< Format array for get_format() enum AVPixelFormat result_format; ///< get_format() result +#endif int die; ///< Set when the thread should exit. @@ -137,8 +139,10 @@ typedef struct FrameThreadContext { */ } FrameThreadContext; +#if FF_API_THREAD_SAFE_CALLBACKS #define THREAD_SAFE_CALLBACKS(avctx) \ ((avctx)->thread_safe_callbacks || (avctx)->get_buffer2 == avcodec_default_get_buffer2) +#endif static void async_lock(FrameThreadContext *fctx) { @@ -178,8 +182,14 @@ static attribute_align_arg void *frame_worker_thread(void *arg) if (p->die) break; - if (!codec->update_thread_context && THREAD_SAFE_CALLBACKS(avctx)) +FF_DISABLE_DEPRECATION_WARNINGS + if (!codec->update_thread_context +#if FF_API_THREAD_SAFE_CALLBACKS + && THREAD_SAFE_CALLBACKS(avctx) +#endif + ) ff_thread_finish_setup(avctx); +FF_ENABLE_DEPRECATION_WARNINGS /* If a decoder supports hwaccel, then it must call ff_get_format(). * Since that call must happen before ff_thread_finish_setup(), the @@ -344,7 +354,11 @@ static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) dst->frame_number = src->frame_number; dst->reordered_opaque = src->reordered_opaque; +#if FF_API_THREAD_SAFE_CALLBACKS +FF_DISABLE_DEPRECATION_WARNINGS dst->thread_safe_callbacks = src->thread_safe_callbacks; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (src->slice_count && src->slice_offset) { if (dst->slice_count < src->slice_count) { @@ -360,6 +374,7 @@ static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) return 0; } +#if FF_API_THREAD_SAFE_CALLBACKS /// Releases the buffers that this decoding thread was the last user of. static void release_delayed_buffers(PerThreadContext *p) { @@ -380,6 +395,7 @@ static void release_delayed_buffers(PerThreadContext *p) pthread_mutex_unlock(&fctx->buffer_mutex); } } +#endif static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx, AVPacket *avpkt) @@ -403,7 +419,9 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx, (p->avctx->debug & FF_DEBUG_THREADS) != 0, memory_order_relaxed); +#if FF_API_THREAD_SAFE_CALLBACKS release_delayed_buffers(p); +#endif if (prev_thread) { int err; @@ -433,6 +451,8 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx, pthread_cond_signal(&p->input_cond); pthread_mutex_unlock(&p->mutex); +#if FF_API_THREAD_SAFE_CALLBACKS +FF_DISABLE_DEPRECATION_WARNINGS /* * If the client doesn't have a thread-safe get_buffer(), * then decoding threads call back to the main thread, @@ -466,6 +486,8 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx, pthread_mutex_unlock(&p->progress_mutex); } } +FF_ENABLE_DEPRECATION_WARNINGS +#endif fctx->prev_thread = p; fctx->next_decoding++; @@ -657,7 +679,7 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) { FrameThreadContext *fctx = avctx->internal->thread_ctx; const AVCodec *codec = avctx->codec; - int i, j; + int i; park_frame_worker_threads(fctx, thread_count); @@ -690,7 +712,9 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) if (codec->close && p->avctx) codec->close(p->avctx); +#if FF_API_THREAD_SAFE_CALLBACKS release_delayed_buffers(p); +#endif av_frame_free(&p->frame); } @@ -704,9 +728,11 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) pthread_cond_destroy(&p->output_cond); av_packet_unref(&p->avpkt); - for (j = 0; j < p->released_buffers_allocated; j++) +#if FF_API_THREAD_SAFE_CALLBACKS + for (int j = 0; j < p->released_buffers_allocated; j++) av_frame_free(&p->released_buffers[j]); av_freep(&p->released_buffers); +#endif if (p->avctx) { if (codec->priv_class) @@ -889,7 +915,9 @@ void ff_thread_flush(AVCodecContext *avctx) av_frame_unref(p->frame); p->result = 0; +#if FF_API_THREAD_SAFE_CALLBACKS release_delayed_buffers(p); +#endif if (avctx->codec->flush) avctx->codec->flush(p->avctx); @@ -899,10 +927,16 @@ void ff_thread_flush(AVCodecContext *avctx) int ff_thread_can_start_frame(AVCodecContext *avctx) { PerThreadContext *p = avctx->internal->thread_ctx; +FF_DISABLE_DEPRECATION_WARNINGS if ((avctx->active_thread_type&FF_THREAD_FRAME) && atomic_load(&p->state) != STATE_SETTING_UP && - (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) { + (avctx->codec->update_thread_context +#if FF_API_THREAD_SAFE_CALLBACKS + || !THREAD_SAFE_CALLBACKS(avctx) +#endif + )) { return 0; } +FF_ENABLE_DEPRECATION_WARNINGS return 1; } @@ -916,8 +950,14 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int if (!(avctx->active_thread_type & FF_THREAD_FRAME)) return ff_get_buffer(avctx, f->f, flags); +FF_DISABLE_DEPRECATION_WARNINGS if (atomic_load(&p->state) != STATE_SETTING_UP && - (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) { + (avctx->codec->update_thread_context +#if FF_API_THREAD_SAFE_CALLBACKS + || !THREAD_SAFE_CALLBACKS(avctx) +#endif + )) { +FF_ENABLE_DEPRECATION_WARNINGS av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n"); return -1; } @@ -935,6 +975,10 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int } pthread_mutex_lock(&p->parent->buffer_mutex); +#if !FF_API_THREAD_SAFE_CALLBACKS + err = ff_get_buffer(avctx, f->f, flags); +#else +FF_DISABLE_DEPRECATION_WARNINGS if (THREAD_SAFE_CALLBACKS(avctx)) { err = ff_get_buffer(avctx, f->f, flags); } else { @@ -954,6 +998,8 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int } if (!THREAD_SAFE_CALLBACKS(avctx) && !avctx->codec->update_thread_context) ff_thread_finish_setup(avctx); +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (err) av_buffer_unref(&f->progress); @@ -962,6 +1008,8 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int return err; } +#if FF_API_THREAD_SAFE_CALLBACKS +FF_DISABLE_DEPRECATION_WARNINGS enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) { enum AVPixelFormat res; @@ -987,6 +1035,8 @@ enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixe return res; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) { @@ -998,12 +1048,16 @@ int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) { +#if FF_API_THREAD_SAFE_CALLBACKS +FF_DISABLE_DEPRECATION_WARNINGS PerThreadContext *p = avctx->internal->thread_ctx; FrameThreadContext *fctx; AVFrame *dst; int ret = 0; int can_direct_free = !(avctx->active_thread_type & FF_THREAD_FRAME) || THREAD_SAFE_CALLBACKS(avctx); +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (!f->f) return; @@ -1014,6 +1068,9 @@ void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) av_buffer_unref(&f->progress); f->owner[0] = f->owner[1] = NULL; +#if !FF_API_THREAD_SAFE_CALLBACKS + av_frame_unref(f->f); +#else // when the frame buffers are not allocated, just reset it to clean state if (can_direct_free || !f->f->buf[0]) { av_frame_unref(f->f); @@ -1055,4 +1112,5 @@ fail: memset(f->f->extended_buf, 0, f->f->nb_extended_buf * sizeof(*f->f->extended_buf)); av_frame_unref(f->f); } +#endif } |