@@ -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;
@@ -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;
+}
@@ -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 */
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(+)