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
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel