diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index fa1e9ae829..d4d31ccb00 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1423,14 +1423,14 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl, * We have to do that before the "dummy" in-between frame allocation, * since that can modify h->cur_pic_ptr. */ if (h->first_field) { + int last_field = last_pic_structure == PICT_BOTTOM_FIELD; av_assert0(h->cur_pic_ptr); av_assert0(h->cur_pic_ptr->f->buf[0]); assert(h->cur_pic_ptr->reference != DELAYED_PIC_REF); /* Mark old field/frame as completed */ - if (h->cur_pic_ptr->tf.owner == h->avctx) { - ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, - last_pic_structure == PICT_BOTTOM_FIELD); + if (h->cur_pic_ptr->tf.owner[last_field] == h->avctx) { + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, last_field); } /* figure out if we have a complementary field pair */ @@ -1568,7 +1568,9 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl, return AVERROR_INVALIDDATA; } } else { + int field = h->picture_structure == PICT_BOTTOM_FIELD; release_unused_pictures(h, 0); + h->cur_pic_ptr->tf.owner[field] = h->avctx; } /* Some macroblocks can be accessed before they're available in case * of lost slices, MBAFF or threading. */ diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 9a6b83ac45..c246c2fded 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -564,10 +564,11 @@ void ff_thread_report_progress(ThreadFrame *f, int n, int field) atomic_load_explicit(&progress[field], memory_order_relaxed) >= n) return; - p = f->owner->internal->thread_ctx; + p = f->owner[field]->internal->thread_ctx; - if (f->owner->debug&FF_DEBUG_THREADS) - av_log(f->owner, AV_LOG_DEBUG, "%p finished %d field %d\n", progress, n, field); + if (f->owner[field]->debug&FF_DEBUG_THREADS) + av_log(f->owner[field], AV_LOG_DEBUG, + "%p finished %d field %d\n", progress, n, field); pthread_mutex_lock(&p->progress_mutex); @@ -586,10 +587,11 @@ void ff_thread_await_progress(ThreadFrame *f, int n, int field) atomic_load_explicit(&progress[field], memory_order_acquire) >= n) return; - p = f->owner->internal->thread_ctx; + p = f->owner[field]->internal->thread_ctx; - if (f->owner->debug&FF_DEBUG_THREADS) - av_log(f->owner, AV_LOG_DEBUG, "thread awaiting %d field %d from %p\n", n, field, progress); + if (f->owner[field]->debug&FF_DEBUG_THREADS) + av_log(f->owner[field], AV_LOG_DEBUG, + "thread awaiting %d field %d from %p\n", n, field, progress); pthread_mutex_lock(&p->progress_mutex); while (atomic_load_explicit(&progress[field], memory_order_relaxed) < n) @@ -882,7 +884,7 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int PerThreadContext *p = avctx->internal->thread_ctx; int err; - f->owner = avctx; + f->owner[0] = f->owner[1] = avctx; ff_init_buffer_info(avctx, f->f); @@ -986,7 +988,7 @@ void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) av_log(avctx, AV_LOG_DEBUG, "thread_release_buffer called on pic %p\n", f); av_buffer_unref(&f->progress); - f->owner = NULL; + f->owner[0] = f->owner[1] = NULL; if (can_direct_free) { av_frame_unref(f->f); diff --git a/libavcodec/thread.h b/libavcodec/thread.h index c848d7ae8b..90864b59d9 100644 --- a/libavcodec/thread.h +++ b/libavcodec/thread.h @@ -34,7 +34,7 @@ typedef struct ThreadFrame { AVFrame *f; - AVCodecContext *owner; + AVCodecContext *owner[2]; // progress->data is an array of 2 ints holding progress for top/bottom // fields AVBufferRef *progress; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 3e8677d0f4..0c6883686e 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -3971,7 +3971,8 @@ int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src) { int ret; - dst->owner = src->owner; + dst->owner[0] = src->owner[0]; + dst->owner[1] = src->owner[1]; ret = av_frame_ref(dst->f, src->f); if (ret < 0) @@ -3981,7 +3982,7 @@ int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src) if (src->progress && !(dst->progress = av_buffer_ref(src->progress))) { - ff_thread_release_buffer(dst->owner, dst); + ff_thread_release_buffer(dst->owner[0], dst); return AVERROR(ENOMEM); } @@ -3997,7 +3998,7 @@ enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixe int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) { - f->owner = avctx; + f->owner[0] = f->owner[1] = avctx; return ff_get_buffer(avctx, f->f, flags); }