From 2ad0b8e0ea36115595f16bca203a5fdaabafb4ab Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 14 Dec 2023 20:15:02 +0100 Subject: [PATCH] fftools/ffmpeg: use a mutex for enc_stats_write() It may be called concurrently from different threads to write into the same file. --- fftools/ffmpeg.h | 3 +++ fftools/ffmpeg_enc.c | 4 ++++ fftools/ffmpeg_mux.c | 4 ++++ fftools/ffmpeg_mux_init.c | 5 +++++ 4 files changed, 16 insertions(+) diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 03dbb528c0..33a29b316f 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -480,6 +480,9 @@ typedef struct EncStats { int nb_components; AVIOContext *io; + + pthread_mutex_t lock; + int lock_initialized; } EncStats; extern const char *const forced_keyframes_const_names[]; diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index d774a7e008..57590a43a3 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -491,6 +491,8 @@ void enc_stats_write(OutputStream *ost, EncStats *es, ptsi = fd->dec.pts; } + pthread_mutex_lock(&es->lock); + for (size_t i = 0; i < es->nb_components; i++) { const EncStatsComponent *c = &es->components[i]; @@ -538,6 +540,8 @@ void enc_stats_write(OutputStream *ost, EncStats *es, } avio_w8(io, '\n'); avio_flush(io); + + pthread_mutex_unlock(&es->lock); } static inline double psnr(double d) diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 357f34172f..ab86abee14 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -778,6 +778,10 @@ static void enc_stats_uninit(EncStats *es) for (int i = 0; i < es->nb_components; i++) av_freep(&es->components[i].str); av_freep(&es->components); + + if (es->lock_initialized) + pthread_mutex_destroy(&es->lock); + es->lock_initialized = 0; } static void ost_free(OutputStream **post) diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index 0203701d78..52eca9f9d5 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -402,6 +402,11 @@ fail: return ret; } + ret = pthread_mutex_init(&es->lock, NULL); + if (ret) + return AVERROR(ret); + es->lock_initialized = 1; + ret = enc_stats_get_file(&es->io, path); if (ret < 0) return ret;