[FFmpeg-devel] [PATCH 11/11] avcodec/frame_thread_encoder: Stop serializing unreferencing AVFrames
Andreas Rheinhardt
andreas.rheinhardt at outlook.com
Mon Aug 29 00:19:57 EEST 2022
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 at outlook.com>
---
libavcodec/encode.c | 8 +++++++-
libavcodec/encode.h | 2 +-
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;
}
--
2.34.1
More information about the ffmpeg-devel
mailing list