diff options
author | Andreas Rheinhardt <andreas.rheinhardt@outlook.com> | 2022-08-25 18:59:58 +0200 |
---|---|---|
committer | Andreas Rheinhardt <andreas.rheinhardt@outlook.com> | 2022-09-03 15:41:19 +0200 |
commit | 65f68514486fade5c6ab973c90047a422198ce07 (patch) | |
tree | 3d1f4a0c33c3ac8a119be7fb42660ca60c7e1382 /libavcodec | |
parent | 25ea90b733883d0cbfdb76014b619a1b37489fca (diff) | |
download | ffmpeg-65f68514486fade5c6ab973c90047a422198ce07.tar.gz |
avcodec/frame_thread_encoder: Stop serializing unreferencing AVFrames
Currently, the frame-threaded decoding API still supports thread-unsafe
callbacks. If one uses a thread-unsafe get_buffer2() callback,
calls to av_frame_unref() by the decoder are serialized, because
it is presumed that the underlying deallocator is thread-unsafe.
The frame-threaded encoder seems to have been written with this
restriction in mind: It always serializes unreferencing its AVFrames,
although no documentation forces it to do so.
This commit schedules to change this behaviour as soon as thread-unsafe
callbacks are removed. For this reason, the FF_API_THREAD_SAFE_CALLBACKS
define is reused.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/encode.c | 8 | ||||
-rw-r--r-- | libavcodec/encode.h | 2 | ||||
-rw-r--r-- | libavcodec/frame_thread_encoder.c | 14 |
3 files changed, 22 insertions, 2 deletions
diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 8c6d81286c..ade4d458e7 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -190,7 +190,7 @@ int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame) } int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt, - const AVFrame *frame, int *got_packet) + AVFrame *frame, int *got_packet) { const FFCodec *const codec = ffcodec(avctx->codec); int ret; @@ -227,6 +227,10 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt, unref: av_packet_unref(avpkt); } +#if !FF_API_THREAD_SAFE_CALLBACKS + if (frame) + av_frame_unref(frame); +#endif return ret; } @@ -267,8 +271,10 @@ static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt) ret = ff_thread_video_encode_frame(avctx, avpkt, frame, &got_packet); else { ret = ff_encode_encode_cb(avctx, avpkt, frame, &got_packet); +#if FF_API_THREAD_SAFE_CALLBACKS if (frame) av_frame_unref(frame); +#endif } if (avci->draining && !got_packet) diff --git a/libavcodec/encode.h b/libavcodec/encode.h index 296ffd312e..81d18d6ead 100644 --- a/libavcodec/encode.h +++ b/libavcodec/encode.h @@ -76,7 +76,7 @@ int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size); int ff_encode_preinit(AVCodecContext *avctx); int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt, - const AVFrame *frame, int *got_packet); + AVFrame *frame, int *got_packet); /** * Rescale from sample rate to AVCodecContext.time_base. diff --git a/libavcodec/frame_thread_encoder.c b/libavcodec/frame_thread_encoder.c index 1faaef522e..35775ae823 100644 --- a/libavcodec/frame_thread_encoder.c +++ b/libavcodec/frame_thread_encoder.c @@ -48,7 +48,9 @@ typedef struct{ typedef struct{ AVCodecContext *parent_avctx; +#if FF_API_THREAD_SAFE_CALLBACKS pthread_mutex_t buffer_mutex; +#endif pthread_mutex_t task_fifo_mutex; /* Used to guard (next_)task_index */ pthread_cond_t task_fifo_cond; @@ -68,9 +70,15 @@ typedef struct{ } ThreadContext; #define OFF(member) offsetof(ThreadContext, member) +#if FF_API_THREAD_SAFE_CALLBACKS DEFINE_OFFSET_ARRAY(ThreadContext, thread_ctx, pthread_init_cnt, (OFF(buffer_mutex), OFF(task_fifo_mutex), OFF(finished_task_mutex)), (OFF(task_fifo_cond), OFF(finished_task_cond))); +#else +DEFINE_OFFSET_ARRAY(ThreadContext, thread_ctx, pthread_init_cnt, + (OFF(task_fifo_mutex), OFF(finished_task_mutex)), + (OFF(task_fifo_cond), OFF(finished_task_cond))); +#endif #undef OFF static void * attribute_align_arg worker(void *v){ @@ -104,9 +112,11 @@ static void * attribute_align_arg worker(void *v){ pkt = task->outdata; ret = ff_encode_encode_cb(avctx, pkt, frame, &task->got_packet); +#if FF_API_THREAD_SAFE_CALLBACKS pthread_mutex_lock(&c->buffer_mutex); av_frame_unref(frame); pthread_mutex_unlock(&c->buffer_mutex); +#endif pthread_mutex_lock(&c->finished_task_mutex); task->return_code = ret; task->finished = 1; @@ -114,9 +124,13 @@ static void * attribute_align_arg worker(void *v){ pthread_mutex_unlock(&c->finished_task_mutex); } end: +#if FF_API_THREAD_SAFE_CALLBACKS pthread_mutex_lock(&c->buffer_mutex); +#endif avcodec_close(avctx); +#if FF_API_THREAD_SAFE_CALLBACKS pthread_mutex_unlock(&c->buffer_mutex); +#endif av_freep(&avctx); return NULL; } |