ffmpeg/fftools
Niklas Haas 03dfac5630 fftools/ffmpeg_sched: allow throttling decoder outputs
This is a departure from the conventional idea of decoders always outputting
data as fast as possible. Instead, this allows decoders to be throttled in the
same way filter graphs can be.

This comes into play when e.g. a demuxer is feeding into two decoders, but
only one of the two decoders is actually currently needed (e.g. due to
A/V misalignment). In that case, what typically happens is that the unneeded
decoder alse decodes all frames, and then piles them up on the "buffersrc"
filter's downstream link (growing indefinitely).

Another issue this solves manifests when e.g. a single demuxer is feeding many
decoders that all try to feed frames to the same filter graph. In this case,
all decoders run as fast as posssible, leading to lock contention on the
filter graph input queue; resulting in (again) many frames piling up on the
buffersrc (or downstream filters) for the unneeded inputs that are not actually
the bottleneck, while the input that's actually undersatisfied can end up
starved for CPU time, possibly for long enough to exhaust memory limits. The
normal rate limiting fails to apply in this scenario because all decoders share
a single demuxer, and are hence rate-limited only by the demuxer speed; whereas
the demuxer is not choked because from the PoV of the scheduler, the filter
graph is simply not getting enough frames.

In a more general sense, there's a philosophical argument to be made here.
Since a decoder is typically also a decompressor, it produces more data than
it consumes. So, it a sense, it's acting like a type of producer also - in
the same way that a filter graph can produce more input that outputs.

Solve all of these issues by allowing decoders to be output-choked, which
gives the scheduler control over when decoders are allowed to output frames.
This does mean we have to add some sort of internal packet queue, because the
decoder thread may need to continue *accepting* upstream packets from the
demuxer (or else we risk stalling the demuxer), but defer the actual decoding
by placing them inside an internal "overflow" queue.

This effectively simulates a sort of "filter graph"-type semantics but
for the decoder queue.

This overflow logic is fairly self-contained inside `sch_dec_receive`, though
it is quite nontrivial. I have added as much documentation as is hopefully
needed to understand the logic.

Importantly, we cannot simply unlimit the decoder input thread queue because
the demuxer relies on backpressure from the decoder to rate limit itself. (Note
that demuxers may only be active if there is at least one downstream decoder
that is alse active, so we always have at least one decoder providing
backpressure)

Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-05-23 08:41:12 +00:00
..
graph fftools/graph: Add missing include "libavutil/mem.h" for fftools/graph/graphprint.c 2026-05-07 22:00:38 +00:00
resources fftools/resources: Update .gitignore 2025-08-13 17:39:49 +00:00
textformat fftools: replace fall-through comments 2026-04-28 12:29:37 +00:00
cmdutils.c fftools: replace fall-through comments 2026-04-28 12:29:37 +00:00
cmdutils.h ffplay: print new metadata 2025-11-22 18:38:40 +00:00
ffmpeg.c fftools/ffmpeg: fix read_key() always return 255 when there was no input 2026-03-09 16:13:18 +00:00
ffmpeg.h fftools/ffmpeg_demux: add options to override mastering display and content light level metadata 2026-03-15 17:52:05 -03:00
ffmpeg_dec.c avcodec: rename avcodec_receive_frame2 to avcodec_receive_frame_flags 2025-12-07 12:47:46 -03:00
ffmpeg_demux.c fftools/ffmpeg_demux: properly unnitialize the side_data_prefer_packet AVBprint buffer 2026-03-18 13:29:23 -03:00
ffmpeg_enc.c fftools:/ffmpeg_enc: honor the user request for fixed size frames 2026-05-16 13:55:22 -03:00
ffmpeg_filter.c fftools/ffmpeg_filter: rate control all filter graphs 2026-05-23 08:41:12 +00:00
ffmpeg_hw.c avutil/common: Don't auto-include mem.h 2024-03-31 00:08:43 +01:00
ffmpeg_mux.c fftools/ffmpeg_mux: move OutputStream.enc_ctx to Encoder 2024-09-30 09:29:18 +02:00
ffmpeg_mux.h fftools/ffmpeg_mux: Make ms_from_ost() inline 2025-05-15 23:08:05 +02:00
ffmpeg_mux_init.c avformat/avformat: add a Track Reference Stream Group 2026-05-17 11:16:51 -03:00
ffmpeg_opt.c fftools/ffmpeg_opt: fix mismatching negative maps 2026-05-03 13:19:18 +00:00
ffmpeg_sched.c fftools/ffmpeg_sched: allow throttling decoder outputs 2026-05-23 08:41:12 +00:00
ffmpeg_sched.h fftools/ffmpeg_sched: add a function to remove a filtergraph from the scheduler 2025-10-30 11:02:01 -03:00
ffmpeg_utils.h fftools/ffmpeg: propagate decoded_side_data from decoded streams to the filterchain 2025-01-25 21:56:49 -03:00
ffplay.c fftools/ffplay.c: Also print demuxer-level metadata updates. 2026-03-12 02:45:13 +00:00
ffplay_renderer.c hwcontext_vulkan: deprecate AVVulkanDeviceContext.lock/unlock_queue 2026-03-14 17:05:06 +00:00
ffplay_renderer.h fftools/ffplay: add support for rendering without alpha 2026-01-21 22:02:50 +00:00
ffprobe.c ffprobe: implement printing IAMF frame side data 2026-05-13 15:19:11 +02:00
fftools.manifest fftools: add DPI awareness manifest 2022-08-13 14:42:52 +02:00
fftoolsres.rc fftools: add DPI awareness manifest 2022-08-13 14:42:52 +02:00
fopen_utf8.h avutil/common: Don't auto-include mem.h 2024-03-31 00:08:43 +01:00
Makefile fftools: Fix MediaCodec on Android15+ 2025-11-23 12:53:43 +00:00
opt_common.c fftools/opt_common: Use enum for encoder/decoder selection 2026-05-01 23:37:55 +00:00
opt_common.h fftools/opt_common: Make -sources/-sinks options work without arguments 2026-02-03 23:22:03 +00:00
sync_queue.c fftools/sync_queue: switch from AVFifo+ObjPool to AVContainerFifo 2024-12-15 14:05:34 +01:00
sync_queue.h fftools/sync_queue: add debug logging 2023-05-28 10:47:59 +02:00
thread_queue.c fftools/thread_queue: add THREAD_QUEUE_FLAG_NO_BLOCK 2026-05-23 08:41:12 +00:00
thread_queue.h fftools/thread_queue: add THREAD_QUEUE_FLAG_NO_BLOCK 2026-05-23 08:41:12 +00:00