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.rheinha...@outlook.com>
---
 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 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 */
-- 
2.40.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to