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>
release/7.1
Andreas Rheinhardt 1 year ago
parent 267a763a55
commit 9dc8f8839e
  1. 7
      libavcodec/decode.c
  2. 20
      libavcodec/pthread_frame.c
  3. 30
      libavcodec/thread.h

@ -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;

@ -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;
}

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

Loading…
Cancel
Save