[FFmpeg-devel] [PATCH 2/3] lavc/pthread_frame: allow ff_thread_finish_setup() to return errors
Anton Khirnov
anton at khirnov.net
Wed Nov 13 15:06:57 EET 2024
Will be useful in following commits.
---
libavcodec/cfhd.c | 4 +++-
libavcodec/ffv1dec.c | 4 +++-
libavcodec/h263dec.c | 14 ++++++++++----
libavcodec/h264dec.c | 5 ++++-
libavcodec/hevc/hevcdec.c | 7 +++++--
libavcodec/mimic.c | 4 +++-
libavcodec/mpeg12dec.c | 7 +++++--
libavcodec/pngdec.c | 9 ++++++---
libavcodec/proresdec.c | 5 ++++-
libavcodec/pthread_frame.c | 26 ++++++++++++++++++++------
libavcodec/rv34.c | 5 ++++-
libavcodec/takdec.c | 5 ++++-
libavcodec/thread.h | 2 +-
libavcodec/utils.c | 3 ++-
libavcodec/vp3.c | 4 +++-
libavcodec/vp8.c | 7 +++++--
libavcodec/vp9.c | 16 ++++++++++++----
libavcodec/wavpack.c | 4 +++-
18 files changed, 97 insertions(+), 34 deletions(-)
diff --git a/libavcodec/cfhd.c b/libavcodec/cfhd.c
index 6f1d960058..0886f8d9da 100644
--- a/libavcodec/cfhd.c
+++ b/libavcodec/cfhd.c
@@ -910,7 +910,9 @@ finish:
s->planes = 4;
}
- ff_thread_finish_setup(avctx);
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ goto end;
if (!s->a_width || !s->a_height || s->a_format == AV_PIX_FMT_NONE ||
s->a_transform_type == INT_MIN ||
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index ac8cc8a31d..5690a38074 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -928,7 +928,9 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
av_log(avctx, AV_LOG_DEBUG, "ver:%d keyframe:%d coder:%d ec:%d slices:%d bps:%d\n",
f->version, !!(p->flags & AV_FRAME_FLAG_KEY), f->ac, f->ec, f->slice_count, f->avctx->bits_per_raw_sample);
- ff_thread_finish_setup(avctx);
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ return ret;
buf_p = buf + buf_size;
for (int i = f->slice_count - 1; i >= 0; i--) {
diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index 0c23012584..7a9abccbe0 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -584,8 +584,11 @@ retry:
if ((ret = ff_mpv_frame_start(s, avctx)) < 0)
return ret;
- if (!s->divx_packed && !avctx->hwaccel)
- ff_thread_finish_setup(avctx);
+ if (!s->divx_packed && !avctx->hwaccel) {
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ return ret;
+ }
if (avctx->hwaccel) {
ret = FF_HW_CALL(avctx, start_frame,
@@ -656,8 +659,11 @@ frame_end:
if (CONFIG_MPEG4_DECODER && avctx->codec_id == AV_CODEC_ID_MPEG4)
ff_mpeg4_frame_end(avctx, buf, buf_size);
- if (!s->divx_packed && avctx->hwaccel)
- ff_thread_finish_setup(avctx);
+ if (!s->divx_packed && avctx->hwaccel) {
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ return ret;
+ }
av_assert1(s->pict_type == s->cur_pic.ptr->f->pict_type);
if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) {
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index af0913ca2c..0cc24d15a9 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -665,7 +665,10 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
if (h->current_slice == 1) {
if (avctx->active_thread_type & FF_THREAD_FRAME &&
i >= nals_needed && !h->setup_finished && h->cur_pic_ptr) {
- ff_thread_finish_setup(avctx);
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ goto end;
+
h->setup_finished = 1;
}
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 1ea8df0fa0..ea1b4c6218 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -3318,8 +3318,11 @@ static int hevc_frame_start(HEVCContext *s, HEVCLayerContext *l,
if (l == &s->layers[0])
s->finish_setup_nal_idx = find_finish_setup_nal(s);
- if (nal_idx >= s->finish_setup_nal_idx)
- ff_thread_finish_setup(s->avctx);
+ if (nal_idx >= s->finish_setup_nal_idx) {
+ ret = ff_thread_finish_setup(s->avctx);
+ if (ret < 0)
+ goto fail;
+ }
return 0;
diff --git a/libavcodec/mimic.c b/libavcodec/mimic.c
index 2925aa50f7..054ecf54be 100644
--- a/libavcodec/mimic.c
+++ b/libavcodec/mimic.c
@@ -390,7 +390,9 @@ static int mimic_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
ctx->next_prev_index = ctx->cur_index;
ctx->next_cur_index = (ctx->cur_index - 1) & 15;
- ff_thread_finish_setup(avctx);
+ res = ff_thread_finish_setup(avctx);
+ if (res < 0)
+ return res;
av_fast_padded_malloc(&ctx->swap_buf, &ctx->swap_buf_size, swap_buf_size);
if (!ctx->swap_buf)
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index c0ed6a9d5b..4503f3edfe 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -1332,8 +1332,11 @@ static int mpeg_field_start(Mpeg1Context *s1, const uint8_t *buf, int buf_size)
s1->has_afd = 0;
}
- if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_FRAME))
- ff_thread_finish_setup(avctx);
+ if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_FRAME)) {
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ return ret;
+ }
} else { // second field
second_field = 1;
if (!s->cur_pic.ptr) {
diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c
index c5b32c166d..a805bf8eb8 100644
--- a/libavcodec/pngdec.c
+++ b/libavcodec/pngdec.c
@@ -656,8 +656,8 @@ static int decode_phys_chunk(AVCodecContext *avctx, PNGDecContext *s,
/*
* This populates AVCodecContext fields so it must be called before
- * ff_thread_finish_setup() to avoid a race condition with respect to the
- * generic copying of avctx fields.
+ * ff_thread_finish_setup() to propagate them correctly to following
+ * threads.
*/
static int populate_avctx_color_fields(AVCodecContext *avctx, AVFrame *frame)
{
@@ -908,7 +908,10 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
if ((ret = populate_avctx_color_fields(avctx, p)) < 0)
return ret;
- ff_thread_finish_setup(avctx);
+
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ return ret;
/* compute the compressed row size */
if (!s->interlace_type) {
diff --git a/libavcodec/proresdec.c b/libavcodec/proresdec.c
index 6a256107b4..bddc70b2e7 100644
--- a/libavcodec/proresdec.c
+++ b/libavcodec/proresdec.c
@@ -801,7 +801,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0)
return ret;
- ff_thread_finish_setup(avctx);
+
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ return ret;
if (avctx->hwaccel) {
const FFHWAccel *hwaccel = ffhwaccel(avctx->hwaccel);
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 78e6cf668b..8a52e418ad 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -273,8 +273,13 @@ static attribute_align_arg void *frame_worker_thread(void *arg)
if (p->die) break;
- if (!codec->update_thread_context)
- ff_thread_finish_setup(avctx);
+ if (!codec->update_thread_context) {
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0) {
+ p->result = ret;
+ goto alloc_fail;
+ }
+ }
/* If a decoder supports hwaccel, then it must call ff_get_format().
* Since that call must happen before ff_thread_finish_setup(), the
@@ -312,8 +317,13 @@ static attribute_align_arg void *frame_worker_thread(void *arg)
p->result = (ret == AVERROR(EAGAIN)) ? 0 : ret;
}
- if (atomic_load(&p->state) == STATE_SETTING_UP)
- ff_thread_finish_setup(avctx);
+ if (atomic_load(&p->state) == STATE_SETTING_UP) {
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0) {
+ p->result = ret;
+ goto alloc_fail;
+ }
+ }
alloc_fail:
if (p->hwaccel_serializing) {
@@ -684,11 +694,13 @@ void ff_thread_await_progress(const ThreadFrame *f, int n, int field)
pthread_mutex_unlock(&p->progress_mutex);
}
-void ff_thread_finish_setup(AVCodecContext *avctx) {
+int ff_thread_finish_setup(AVCodecContext *avctx)
+{
ChildDecoder *cd;
PerThreadContext *p;
- if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return;
+ if (!(avctx->active_thread_type & FF_THREAD_FRAME))
+ return 0;
cd = avctx->internal->thread_ctx;
p = cd->thread;
@@ -729,6 +741,8 @@ void ff_thread_finish_setup(AVCodecContext *avctx) {
pthread_cond_broadcast(&p->progress_cond);
pthread_mutex_unlock(&p->progress_mutex);
+
+ return 0;
}
/// Waits for all threads to finish.
diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c
index d94285431e..2627e9bdb0 100644
--- a/libavcodec/rv34.c
+++ b/libavcodec/rv34.c
@@ -1750,7 +1750,10 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict,
}
}
s->mb_x = s->mb_y = 0;
- ff_thread_finish_setup(s->avctx);
+
+ ret = ff_thread_finish_setup(s->avctx);
+ if (ret < 0)
+ return ret;
} else if (s->context_reinit) {
av_log(s->avctx, AV_LOG_ERROR, "Decoder needs full frames to "
"reinitialize (start MB is %d).\n", si.start);
diff --git a/libavcodec/takdec.c b/libavcodec/takdec.c
index cfa69f4217..c1bf697f55 100644
--- a/libavcodec/takdec.c
+++ b/libavcodec/takdec.c
@@ -745,7 +745,10 @@ static int tak_decode_frame(AVCodecContext *avctx, AVFrame *frame,
frame->nb_samples = s->nb_samples;
if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0)
return ret;
- ff_thread_finish_setup(avctx);
+
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ return ret;
if (avctx->bits_per_raw_sample <= 16) {
int buf_size = av_samples_get_buffer_size(NULL, avctx->ch_layout.nb_channels,
diff --git a/libavcodec/thread.h b/libavcodec/thread.h
index 7df5839ed0..12f4cbff24 100644
--- a/libavcodec/thread.h
+++ b/libavcodec/thread.h
@@ -41,7 +41,7 @@ int ff_thread_can_start_frame(AVCodecContext *avctx);
*
* @param avctx The context.
*/
-void ff_thread_finish_setup(AVCodecContext *avctx);
+int ff_thread_finish_setup(AVCodecContext *avctx);
/**
* Wrapper around get_buffer() for frame-multithreaded codecs.
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 28023a4a4d..5f04cb8c78 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -897,8 +897,9 @@ void ff_thread_release_ext_buffer(ThreadFrame *f)
av_frame_unref(f->f);
}
-void ff_thread_finish_setup(AVCodecContext *avctx)
+int ff_thread_finish_setup(AVCodecContext *avctx)
{
+ return 0;
}
void ff_thread_report_progress(ThreadFrame *f, int progress, int field)
diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c
index d03a1c9dbc..a0d3d878b4 100644
--- a/libavcodec/vp3.c
+++ b/libavcodec/vp3.c
@@ -2733,7 +2733,9 @@ static int vp3_decode_frame(AVCodecContext *avctx, AVFrame *frame,
ff_progress_frame_report(&s->golden_frame, INT_MAX);
}
}
- ff_thread_finish_setup(avctx);
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ goto error;
memset(s->all_fragments, 0, s->fragment_count * sizeof(Vp3Fragment));
diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
index d6df018655..3d3039c9d4 100644
--- a/libavcodec/vp8.c
+++ b/libavcodec/vp8.c
@@ -2748,8 +2748,11 @@ int vp78_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame,
s->next_framep[VP8_FRAME_CURRENT] = curframe;
- if (!is_vp7 && !s->actually_webp)
- ff_thread_finish_setup(avctx);
+ if (!is_vp7 && !s->actually_webp) {
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ goto err;
+ }
if (avctx->hwaccel) {
const FFHWAccel *hwaccel = ffhwaccel(avctx->hwaccel);
diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c
index 8ede2e2eb3..acf325fa21 100644
--- a/libavcodec/vp9.c
+++ b/libavcodec/vp9.c
@@ -1566,7 +1566,9 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
}
for (int i = 0; i < 8; i++)
ff_progress_frame_replace(&s->next_refs[i], &s->s.refs[i]);
- ff_thread_finish_setup(avctx);
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ return ret;
ff_progress_frame_await(&s->s.refs[ref], INT_MAX);
if ((ret = av_frame_ref(frame, s->s.refs[ref].f)) < 0)
@@ -1655,9 +1657,13 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
break;
}
s->prob_ctx[s->s.h.framectxid].p = s->prob.p;
- ff_thread_finish_setup(avctx);
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ return ret;
} else if (!s->s.h.refreshctx) {
- ff_thread_finish_setup(avctx);
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ return ret;
}
#if HAVE_THREADS
@@ -1726,7 +1732,9 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
if (s->pass < 2 && s->s.h.refreshctx && !s->s.h.parallelmode) {
ff_vp9_adapt_probs(s);
- ff_thread_finish_setup(avctx);
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ goto fail;
}
} while (s->pass++ == 1);
diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c
index bf9aa0cdce..a850cd155d 100644
--- a/libavcodec/wavpack.c
+++ b/libavcodec/wavpack.c
@@ -1560,7 +1560,9 @@ static int wavpack_decode_block(AVCodecContext *avctx, AVFrame *frame, int block
*new_progress = 1;
}
av_assert1(!!wc->dsdctx == !!wc->curr_progress);
- ff_thread_finish_setup(avctx);
+ ret = ff_thread_finish_setup(avctx);
+ if (ret < 0)
+ return ret;
}
}
--
2.43.0
More information about the ffmpeg-devel
mailing list