/** * Codec worker thread. * * Automatically calls ff_thread_finish_setup() if the codec does * not provide an update_thread_context method, or if the codec returns * before calling it. */ static attribute_align_arg void *frame_worker_thread(void *arg) { PerThreadContext *p = arg; FrameThreadContext *fctx = p->parent; AVCodecContext *avctx = p->avctx; const AVCodec *codec = avctx->codec; pthread_mutex_lock(&p->mutex); while (1) { while (p->state == STATE_INPUT_READY && !fctx->die) pthread_cond_wait(&p->input_cond, &p->mutex); if (fctx->die) break; if (!codec->update_thread_context && THREAD_SAFE_CALLBACKS(avctx)) ff_thread_finish_setup(avctx); av_frame_unref(p->frame); p->got_frame = 0; p->result = codec->decode(avctx, p->frame, &p->got_frame, &p->avpkt); if ((p->result < 0 || !p->got_frame) && p->frame->buf[0]) { if (avctx->internal->allocate_progress) av_log(avctx, AV_LOG_ERROR, "A frame threaded decoder did not " "free the frame on failure. This is a bug, please report it.\n"); av_frame_unref(p->frame); } if (p->state == STATE_SETTING_UP) ff_thread_finish_setup(avctx); pthread_mutex_lock(&p->progress_mutex); #if 0 //BUFREF-FIXME for (i = 0; i < MAX_BUFFERS; i++) if (p->progress_used[i] && (p->got_frame || p->result<0 || avctx->codec_id != AV_CODEC_ID_H264)) { p->progress[i][0] = INT_MAX; p->progress[i][1] = INT_MAX; } #endif p->state = STATE_INPUT_READY; pthread_cond_broadcast(&p->progress_cond); pthread_cond_signal(&p->output_cond); pthread_mutex_unlock(&p->progress_mutex); } pthread_mutex_unlock(&p->mutex); return NULL; }
/** * Codec worker thread. * * Automatically calls ff_thread_finish_setup() if the codec does * not provide an update_thread_context method, or if the codec returns * before calling it. */ static attribute_align_arg void *frame_worker_thread(void *arg) { PerThreadContext *p = arg; FrameThreadContext *fctx = p->parent; AVCodecContext *avctx = p->avctx; const AVCodec *codec = avctx->codec; pthread_mutex_lock(&p->mutex); while (1) { while (p->state == STATE_INPUT_READY && !fctx->die) pthread_cond_wait(&p->input_cond, &p->mutex); if (fctx->die) break; if (!codec->update_thread_context && THREAD_SAFE_CALLBACKS(avctx)) ff_thread_finish_setup(avctx); avcodec_get_frame_defaults(&p->frame); p->got_frame = 0; p->result = codec->decode(avctx, &p->frame, &p->got_frame, &p->avpkt); /* many decoders assign whole AVFrames, thus overwriting extended_data; * make sure it's set correctly */ p->frame.extended_data = p->frame.data; if (p->state == STATE_SETTING_UP) ff_thread_finish_setup(avctx); pthread_mutex_lock(&p->progress_mutex); #if 0 //BUFREF-FIXME for (i = 0; i < MAX_BUFFERS; i++) if (p->progress_used[i] && (p->got_frame || p->result<0 || avctx->codec_id != AV_CODEC_ID_H264)) { p->progress[i][0] = INT_MAX; p->progress[i][1] = INT_MAX; } #endif p->state = STATE_INPUT_READY; pthread_cond_broadcast(&p->progress_cond); pthread_cond_signal(&p->output_cond); pthread_mutex_unlock(&p->progress_mutex); } pthread_mutex_unlock(&p->mutex); return NULL; }
/** * Codec worker thread. * * Automatically calls ff_thread_finish_setup() if the codec does * not provide an update_thread_context method, or if the codec returns * before calling it. */ static attribute_align_arg void *frame_worker_thread(void *arg) { PerThreadContext *p = arg; AVCodecContext *avctx = p->avctx; const AVCodec *codec = avctx->codec; pthread_mutex_lock(&p->mutex); while (1) { while (atomic_load(&p->state) == STATE_INPUT_READY && !p->die) pthread_cond_wait(&p->input_cond, &p->mutex); if (p->die) break; if (!codec->update_thread_context && THREAD_SAFE_CALLBACKS(avctx)) ff_thread_finish_setup(avctx); /* 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); if ((p->result < 0 || !p->got_frame) && p->frame->buf[0]) { if (avctx->internal->allocate_progress) av_log(avctx, AV_LOG_ERROR, "A frame threaded decoder did not " "free the frame on failure. This is a bug, please report it.\n"); av_frame_unref(p->frame); } 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); } if (p->async_serializing) { p->async_serializing = 0; async_unlock(p->parent); } pthread_mutex_lock(&p->progress_mutex); atomic_store(&p->state, STATE_INPUT_READY); pthread_cond_broadcast(&p->progress_cond); pthread_cond_signal(&p->output_cond); pthread_mutex_unlock(&p->progress_mutex); } pthread_mutex_unlock(&p->mutex); return NULL; }