diff mbox series

[FFmpeg-devel,v2,10/27] avcodec/pthread_frame: Add API to share RefStruct refs just once

Message ID GV1P250MB07370AEC1BC2D09E877523078F002@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM
State Accepted
Commit 9dc8f8839ed0259f5a1027983617dbdabb4eabed
Headers show
Series [FFmpeg-devel,v2,01/27] avcodec/threadprogress: Add new API for frame-threaded progress | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Andreas Rheinhardt April 8, 2024, 8:13 p.m. UTC
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>
---
 libavcodec/decode.c        |  7 +++++++
 libavcodec/pthread_frame.c | 20 ++++++++++++++++++++
 libavcodec/thread.h        | 30 ++++++++++++++++++++++++++++++
 3 files changed, 57 insertions(+)
diff mbox series

Patch

diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index f18f85c33c..e196c05f11 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 6b2c4312e0..ee571be610 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -1001,3 +1001,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 */