pub struct Allocator { /* private fields */ }Expand description
Divides one connection’s bandwidth estimate among the tracks sharing it.
Every sender on a connection reads the same estimate, so N senders each
targeting all of it oversubscribe the uplink N times over. Register a track
here and it gets a Consumer reporting only its own slice, so the slices
sum to the estimate instead of each matching it.
Advisory, not enforced. A track that ignores its slice, or can’t follow it at all (PCM audio has a fixed bitrate), still sends what it sends; the transport sheds the excess by dropping groups. Rate estimation isn’t exact enough for the difference to be worth policing.
Clones share one registry, so hand a clone to each sender.
Implementations§
Source§impl Allocator
impl Allocator
Sourcepub fn new(estimate: Consumer) -> Self
pub fn new(estimate: Consumer) -> Self
Divide estimate, normally a connection’s
Session::send_bandwidth.
Sourcepub fn unlimited() -> Self
pub fn unlimited() -> Self
An allocator with nothing to divide, so every reservation reports None.
None already means “no opinion, hold your rate” to a sender, so this is what
a transport with no congestion estimate, a local file, or a test harness wants,
and it saves every config struct on the way down from being an Option. It is
also Default, so a config that never sets one encodes at its configured rate.
Sourcepub fn reserve(&self, track: &Demand, max: Rate) -> Reservation
pub fn reserve(&self, track: &Demand, max: Rate) -> Reservation
Reserve up to max for track, returning the reservation.
max is a ceiling, not a measurement: reserve the most the track can ever
send, not what it happens to be sending. A VBR encoder sitting on a black
screen at 1 Mbps can jump to 6 Mbps between one frame and the next, and a
reservation that had followed it down would have already handed that room
to somebody else.
Priority comes from the track (track::Info::priority, higher served
first). A tier is filled to its reservations before the next one sees a
bit; within a tier the split is max-min fair, so a share asking for less
than an even cut takes all of it and leaves the difference to the others.
That is the publisher’s priority, which is not what orders the local send queue: that ranks by each subscription’s own priority, so a subscriber asking for video ahead of audio is served that way whatever this decides. The publisher’s is still the right one to divide by, since allocation is a decision about what to produce, and there is no single subscriber priority to read when several are watching one track.
That last part carries a publisher that leaves priority at its default:
one tier of audio and video still serves audio’s small reservation in full
before video takes the remainder.
The reservation lasts as long as the returned Reservation: hold it for as
long as the sender is publishing, change the ceiling with
update, and drop it to hand the room back. It is
released when the track closes either way, since a track::Demand is a weak
handle and reserving never keeps a track alive.
Read the current slice through Reservation::consumer, which reports None
while nothing is subscribed to the track or the connection has no estimate.
That tells a sender to hold its current rate rather than encode at zero.