aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2023-10-09 01:30:00 +0200
committerAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2024-04-19 13:18:04 +0200
commit9dc8f8839ed0259f5a1027983617dbdabb4eabed (patch)
tree5264318380b08e4f0008cd817fd1e0829df56d7d
parent267a763a55799a73453d90fc61d5fcf1ee7697d1 (diff)
downloadffmpeg-9dc8f8839ed0259f5a1027983617dbdabb4eabed.tar.gz
avcodec/pthread_frame: Add API to share RefStruct refs just once
This is useful when the lifetime of the object to be shared is the whole decoding process as it allows to avoid having to sync them every time in update_thread_context. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
-rw-r--r--libavcodec/decode.c7
-rw-r--r--libavcodec/pthread_frame.c20
-rw-r--r--libavcodec/thread.h30
3 files changed, 57 insertions, 0 deletions
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 495614f29f..d031b1ca17 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -1747,6 +1747,13 @@ void ff_progress_frame_await(const ProgressFrame *f, int n)
ff_thread_progress_await(&f->progress->progress, n);
}
+#if !HAVE_THREADS
+enum ThreadingStatus ff_thread_sync_ref(AVCodecContext *avctx, size_t offset)
+{
+ return FF_THREAD_NO_FRAME_THREADING;
+}
+#endif /* !HAVE_THREADS */
+
static av_cold int progress_frame_pool_init_cb(FFRefStructOpaque opaque, void *obj)
{
const AVCodecContext *avctx = opaque.nc;
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 0da9db1f57..7028fe422d 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -1013,3 +1013,23 @@ void ff_thread_release_ext_buffer(ThreadFrame *f)
if (f->f)
av_frame_unref(f->f);
}
+
+enum ThreadingStatus ff_thread_sync_ref(AVCodecContext *avctx, size_t offset)
+{
+ PerThreadContext *p;
+ const void *ref;
+
+ if (!avctx->internal->is_copy)
+ return avctx->active_thread_type & FF_THREAD_FRAME ?
+ FF_THREAD_IS_FIRST_THREAD : FF_THREAD_NO_FRAME_THREADING;
+
+ p = avctx->internal->thread_ctx;
+
+ av_assert1(memcpy(&ref, (char*)avctx->priv_data + offset, sizeof(ref)) && ref == NULL);
+
+ memcpy(&ref, (const char*)p->parent->threads[0].avctx->priv_data + offset, sizeof(ref));
+ av_assert1(ref);
+ ff_refstruct_replace((char*)avctx->priv_data + offset, ref);
+
+ return FF_THREAD_IS_COPY;
+}
diff --git a/libavcodec/thread.h b/libavcodec/thread.h
index f772d7ff18..5ab12848b4 100644
--- a/libavcodec/thread.h
+++ b/libavcodec/thread.h
@@ -84,4 +84,34 @@ int ff_slice_thread_init_progress(AVCodecContext *avctx);
void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n);
void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift);
+enum ThreadingStatus {
+ FF_THREAD_IS_COPY,
+ FF_THREAD_IS_FIRST_THREAD,
+ FF_THREAD_NO_FRAME_THREADING,
+};
+
+/**
+ * Allows to synchronize objects whose lifetime is the whole decoding
+ * process among all frame threads.
+ *
+ * When called from a non-copy thread, do nothing.
+ * When called from another thread, place a new RefStruct reference
+ * at the given offset in the calling thread's private data from
+ * the RefStruct reference in the private data of the first decoding thread.
+ * The first thread must have a valid RefStruct reference at the given
+ * offset in its private data; the calling thread must not have
+ * a reference at this offset in its private data (must be NULL).
+ *
+ * @param avctx an AVCodecContext
+ * @param offset offset of the RefStruct reference in avctx's private data
+ *
+ * @retval FF_THREAD_IS_COPY if frame-threading is in use and the
+ * calling thread is a copy; in this case, the RefStruct reference
+ * will be set.
+ * @retval FF_THREAD_IS_MAIN_THREAD if frame-threading is in use
+ * and the calling thread is the main thread.
+ * @retval FF_THREAD_NO_FRAME_THREADING if frame-threading is not in use.
+ */
+enum ThreadingStatus ff_thread_sync_ref(AVCodecContext *avctx, size_t offset);
+
#endif /* AVCODEC_THREAD_H */