+static av_cold int init_thread(PerThreadContext *p, int *threads_to_free,
+ FrameThreadContext *fctx, AVCodecContext *avctx,
+ AVCodecContext *src, const AVCodec *codec, int first)
+{
+ AVCodecContext *copy;
+ int err;
+
+ atomic_init(&p->state, STATE_INPUT_READY);
+
+ copy = av_memdup(src, sizeof(*src));
+ if (!copy)
+ return AVERROR(ENOMEM);
+ copy->priv_data = NULL;
+
+ /* From now on, this PerThreadContext will be cleaned up by
+ * ff_frame_thread_free in case of errors. */
+ (*threads_to_free)++;
+
+ p->parent = fctx;
+ p->avctx = copy;
+
+ copy->internal = av_memdup(src->internal, sizeof(*src->internal));
+ if (!copy->internal)
+ return AVERROR(ENOMEM);
+ copy->internal->thread_ctx = p;
+
+ copy->delay = avctx->delay;
+
+ if (codec->priv_data_size) {
+ copy->priv_data = av_mallocz(codec->priv_data_size);
+ if (!copy->priv_data)
+ return AVERROR(ENOMEM);
+
+ if (codec->priv_class) {
+ *(const AVClass **)copy->priv_data = codec->priv_class;
+ err = av_opt_copy(copy->priv_data, src->priv_data);
+ if (err < 0)
+ return err;
+ }
+ }
+
+ err = init_pthread(p, per_thread_offsets);
+ if (err < 0)
+ return err;
+
+ if (!(p->frame = av_frame_alloc()) ||
+ !(p->avpkt = av_packet_alloc()))
+ return AVERROR(ENOMEM);
+ copy->internal->last_pkt_props = p->avpkt;
+
+ if (!first)
+ copy->internal->is_copy = 1;
+
+ if (codec->init) {
+ err = codec->init(copy);
+ if (err < 0) {
+ if (codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP)
+ p->thread_init = NEEDS_CLOSE;
+ return err;
+ }
+ }
+ p->thread_init = NEEDS_CLOSE;
+
+ if (first)
+ update_context_from_thread(avctx, copy, 1);
+
+ atomic_init(&p->debug_threads, (copy->debug & FF_DEBUG_THREADS) != 0);
+
+ err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p));
+ if (err < 0)
+ return err;
+ p->thread_init = INITIALIZED;
+
+ return 0;
+}
+