On 2016-12-14 09:56:23 +0100, Anton Khirnov wrote: > --- > libavcodec/h263dec.c | 2 +- > libavcodec/h264dec.c | 2 +- > libavcodec/pthread_frame.c | 35 +++++++++++++++++++++++++++++++++++ > 3 files changed, 37 insertions(+), 2 deletions(-) > > diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c > index e4a7227..921ff5f 100644 > --- a/libavcodec/h263dec.c > +++ b/libavcodec/h263dec.c > @@ -558,7 +558,7 @@ int ff_h263_decode_frame(AVCodecContext *avctx, void > *data, int *got_frame, > if ((ret = ff_mpv_frame_start(s, avctx)) < 0) > return ret; > > - if (!s->divx_packed && !avctx->hwaccel) > + if (!s->divx_packed) > ff_thread_finish_setup(avctx); > > if (avctx->hwaccel) { > diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c > index 330a74d..83b3ab3 100644 > --- a/libavcodec/h264dec.c > +++ b/libavcodec/h264dec.c > @@ -573,7 +573,7 @@ static int decode_nal_units(H264Context *h, const uint8_t > *buf, int buf_size) > if ((err = ff_h264_queue_decode_slice(h, nal))) > break; > > - if (avctx->active_thread_type & FF_THREAD_FRAME && > !h->avctx->hwaccel && > + if (avctx->active_thread_type & FF_THREAD_FRAME && > i >= nals_needed && !h->setup_finished && h->cur_pic_ptr) { > ff_thread_finish_setup(avctx); > h->setup_finished = 1; > diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c > index 75f4ff4..364a998 100644 > --- a/libavcodec/pthread_frame.c > +++ b/libavcodec/pthread_frame.c > @@ -99,6 +99,8 @@ typedef struct PerThreadContext { > int requested_flags; ///< flags passed to get_buffer() for > requested_frame > > int die; ///< Set when the thread should exit. > + > + int hwaccel_serializing; > } PerThreadContext; > > /** > @@ -109,6 +111,11 @@ typedef struct FrameThreadContext { > PerThreadContext *prev_thread; ///< The last thread submit_packet() was > called on. > > pthread_mutex_t buffer_mutex; ///< Mutex used to protect > get/release_buffer(). > + /** > + * This lock is used for ensuring threads run in serial when hwaccel > + * is used. > + */ > + pthread_mutex_t hwaccel_mutex; > > int next_decoding; ///< The next context to submit a packet > to. > int next_finished; ///< The next context to return output > from. > @@ -149,6 +156,22 @@ static attribute_align_arg void > *frame_worker_thread(void *arg) > ff_thread_finish_setup(avctx); > > pthread_mutex_lock(&p->mutex); > + > + /* If a decoder supports hwaccel, then it must call ff_get_format(). > + * Since that call must happen before ff_thread_finish_setup(), the > + * decoder is required to implement update_thread_context() and call > + * ff_thread_finish_setup() manually. Therefore the above > + * ff_thread_finish_setup() call did not happen and > hwaccel_serializing > + * cannot be true here. */ > + av_assert0(!p->hwaccel_serializing); > + > + /* if the previous thread uses hwaccel then we take the lock to > ensure > + * the threads don't run concurrently */ > + if (avctx->hwaccel) { > + pthread_mutex_lock(&p->parent->hwaccel_mutex); > + p->hwaccel_serializing = 1; > + } > + > av_frame_unref(p->frame); > p->got_frame = 0; > p->result = codec->decode(avctx, p->frame, &p->got_frame, &p->avpkt); > @@ -163,6 +186,11 @@ static attribute_align_arg void > *frame_worker_thread(void *arg) > if (atomic_load(&p->state) == STATE_SETTING_UP) > ff_thread_finish_setup(avctx); > > + if (p->hwaccel_serializing) { > + p->hwaccel_serializing = 0; > + pthread_mutex_unlock(&p->parent->hwaccel_mutex); > + } > + > atomic_store(&p->state, STATE_INPUT_READY); > > pthread_mutex_lock(&p->progress_mutex); > @@ -499,6 +527,11 @@ void ff_thread_finish_setup(AVCodecContext *avctx) { > > if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return; > > + if (avctx->hwaccel && !p->hwaccel_serializing) { > + pthread_mutex_lock(&p->parent->hwaccel_mutex); > + p->hwaccel_serializing = 1; > + } > + > pthread_mutex_lock(&p->progress_mutex); > > atomic_store(&p->state, STATE_SETUP_FINISHED); > @@ -579,6 +612,7 @@ void ff_frame_thread_free(AVCodecContext *avctx, int > thread_count) > > av_freep(&fctx->threads); > pthread_mutex_destroy(&fctx->buffer_mutex); > + pthread_mutex_destroy(&fctx->hwaccel_mutex); > av_freep(&avctx->internal->thread_ctx); > } > > @@ -620,6 +654,7 @@ int ff_frame_thread_init(AVCodecContext *avctx) > } > > pthread_mutex_init(&fctx->buffer_mutex, NULL); > + pthread_mutex_init(&fctx->hwaccel_mutex, NULL); > fctx->delaying = 1; > > for (i = 0; i < thread_count; i++) {
ok, thanks for the verbose comment Janne _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel