Commit a4930fc6a6 for ffmpeg
commit a4930fc6a65ae6f268fec234bb442c0bd395dd13
Author: Romain Beauxis <romain.beauxis@gmail.com>
Date: Sat Oct 31 09:21:58 2026 -0500
avcodec/flacdec: hand the stream parameters on to the next frame thread
A STREAMINFO from packet side data only reaches the frame thread
decoding that packet.
Copy the stream parameters to the next frame thread when a new
STREAMINFO has arrived, finishing setup once the output buffer is
allocated so that the subframes still decode in parallel.
With frame threads, a packet must then hold a single frame, as every
FLAC mapping defines it.
diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c
index c712c372f4..9bab61d4a3 100644
--- a/libavcodec/flacdec.c
+++ b/libavcodec/flacdec.c
@@ -59,6 +59,7 @@ typedef struct FLACContext {
int sample_shift; ///< shift required to make output samples 16-bit or 32-bit
int ch_mode; ///< channel decorrelation type in the current frame
int got_streaminfo; ///< indicates if the STREAMINFO has been read
+ unsigned streaminfo_serial; ///< counts the STREAMINFOs taken from packet side data
int32_t *decoded[FLAC_MAX_CHANNELS]; ///< decoded samples
uint8_t *decoded_buffer;
@@ -95,13 +96,14 @@ static void flac_set_bps(FLACContext *s)
}
}
-static int apply_streaminfo(FLACContext *s, const uint8_t *streaminfo)
+/**
+ * Set the decoder up for s->stream_info, which it cannot decode with until the
+ * buffers are allocated.
+ */
+static int setup_streaminfo(FLACContext *s)
{
- FLACStreaminfo stream_info;
- int ret = ff_flac_parse_streaminfo(s->avctx, &stream_info, streaminfo);
- if (ret < 0)
- return ret;
- s->stream_info = stream_info;
+ int ret;
+
s->got_streaminfo = 0;
ret = allocate_buffers(s);
if (ret < 0)
@@ -114,6 +116,17 @@ static int apply_streaminfo(FLACContext *s, const uint8_t *streaminfo)
return 0;
}
+static int apply_streaminfo(FLACContext *s, const uint8_t *streaminfo)
+{
+ FLACStreaminfo stream_info;
+ int ret = ff_flac_parse_streaminfo(s->avctx, &stream_info, streaminfo);
+ if (ret < 0)
+ return ret;
+ s->stream_info = stream_info;
+
+ return setup_streaminfo(s);
+}
+
static av_cold int flac_decode_init(AVCodecContext *avctx)
{
uint8_t *streaminfo;
@@ -728,6 +741,11 @@ static int flac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
*got_frame_ptr = 0;
+ if (!ff_thread_can_start_frame(avctx)) {
+ av_log(avctx, AV_LOG_ERROR, "frame threads need one FLAC frame per packet\n");
+ return AVERROR_PATCHWELCOME;
+ }
+
streaminfo = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA,
&streaminfo_size);
if (streaminfo) {
@@ -738,6 +756,7 @@ static int flac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
return AVERROR_INVALIDDATA;
if ((ret = apply_streaminfo(s, streaminfo)) < 0)
return ret;
+ s->streaminfo_serial++;
}
if (buf_size > 5 && !memcmp(buf, "\177FLAC", 5)) {
@@ -778,6 +797,8 @@ static int flac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0)
return ret;
+ ff_thread_finish_setup(avctx);
+
if ((ret = decode_subframes(s)) < 0) {
av_log(s->avctx, AV_LOG_ERROR, "decode_frame() failed\n");
return ret;
@@ -816,6 +837,27 @@ static int flac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
return bytes_read;
}
+#if HAVE_THREADS
+/**
+ * Hand the stream parameters on to the next frame thread, so that a STREAMINFO
+ * taken from packet side data holds for the frames after the one carrying it.
+ */
+static int flac_update_thread_context(AVCodecContext *dst,
+ const AVCodecContext *src)
+{
+ FLACContext *s = dst->priv_data;
+ const FLACContext *s1 = src->priv_data;
+
+ if (s == s1 || s->streaminfo_serial == s1->streaminfo_serial)
+ return 0;
+
+ s->streaminfo_serial = s1->streaminfo_serial;
+ s->stream_info = s1->stream_info;
+
+ return setup_streaminfo(s);
+}
+#endif
+
static av_cold int flac_decode_close(AVCodecContext *avctx)
{
FLACContext *s = avctx->priv_data;
@@ -847,6 +889,7 @@ const FFCodec ff_flac_decoder = {
.init = flac_decode_init,
.close = flac_decode_close,
FF_CODEC_DECODE_CB(flac_decode_frame),
+ UPDATE_THREAD_CONTEXT(flac_update_thread_context),
.p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
AV_CODEC_CAP_DR1 |
AV_CODEC_CAP_FRAME_THREADS,