multiqueue: Optimize multiqueue sizes based on interleave
Multiqueue should only be used to cope with:
* decoupling upstream and dowstream threading (i.e. having separate threads
for elementary streams).
* Ensuring individual queues have enough space to cope with upstream interleave
(distance in stream time between co-located samples). This is to guarantee
that we have enough room in each individual queues to provide new data in
each, without being blocked.
* Limit the queue sizes to that interleave distance (and an extra minimal
buffering size). This is to ensure we don't consume too much memory.
Based on that, multiqueue now continuously calculates the input interleave
(per incoming streaming thread). Based on that, it calculates a target
interleave (currently 1.5 x real_interleave + 250ms padding).
If the target interleave is greater than the current max_size.time, it will
update it accordingly (to allow enough margin to not block).
If the target interleave goes down by more than 50%, we re-adjust it once
we know we have gone past a safe distance (2 x current max_size.time).
This mode can only be used for incoming streams that are guaranteed to be
properly timestamped.
Furthermore, we ignore sparse streams when calculating interleave and maximum
size of queues.
For the simplest of use-cases (single stream), multiqueue acts as a single
queue with a time limit of 250ms.
If there are multiple inputs, but each come from a different streaming thread,
the maximum time limit will also end up being 250ms.
On regular files (more than one input stream from the same upstream streaming
thread), it can reduce the total memory used as much as 10x, ending up with
max_size.time around 500ms.
Due to the adaptive nature, it can also cope with changing interleave (which
can happen commonly on some files at startup/pre-roll time)