[FFmpeg-cvslog] avcodec/pthread_frame: Add API to share RefStruct refs just once

Andreas Rheinhardt git at videolan.org
Fri Apr 19 14:53:37 EEST 2024


ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinhardt at outlook.com> | Mon Oct  9 01:30:00 2023 +0200| [9dc8f8839ed0259f5a1027983617dbdabb4eabed] | committer: Andreas Rheinhardt

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 at outlook.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=9dc8f8839ed0259f5a1027983617dbdabb4eabed
---

 libavcodec/decode.c        |  7 +++++++
 libavcodec/pthread_frame.c | 20 ++++++++++++++++++++
 libavcodec/thread.h        | 30 ++++++++++++++++++++++++++++++
 3 files changed, 57 insertions(+)

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 */



More information about the ffmpeg-cvslog mailing list