blob: 6f938be45bf33461ec76bbe5fcbea92a865ed52f [file] [log] [blame] [view]
Artem Titov3ab7a552021-04-14 14:23:101<?% config.freshness.reviewed = '2021-04-12' %?>
2<?% config.freshness.owner = 'sprang' %?>
Erik Språng32347b52021-04-13 16:18:553
4# Paced Sending
5
Artem Titov3ab7a552021-04-14 14:23:106The paced sender, often referred to as just the "pacer", is a part of the WebRTC
7RTP stack used primarily to smooth the flow of packets sent onto the network.
Erik Språng32347b52021-04-13 16:18:558
9## Background
Erik Språng32347b52021-04-13 16:18:5510
Artem Titov3ab7a552021-04-14 14:23:1011Consider a video stream at 5Mbps and 30fps. This would in an ideal world result
12in each frame being ~21kB large and packetized into 18 RTP packets. While the
13average bitrate over say a one second sliding window would be a correct 5Mbps,
14on a shorter time scale it can be seen as a burst of 167Mbps every 33ms, each
15followed by a 32ms silent period. Further, it is quite common that video
16encoders overshoot the target frame size in case of sudden movement especially
17dealing with screensharing. Frames being 10x or even 100x larger than the ideal
18size is an all too real scenario. These packet bursts can cause several issues,
19such as congesting networks and causing buffer bloat or even packet loss. Most
20sessions have more than one media stream, e.g. a video and an audio track. If
21you put a frame on the wire in one go, and those packets take 100ms to reach the
22other side - that means you have now blocked any audio packets from reaching the
23remote end in time as well.
Erik Språng32347b52021-04-13 16:18:5524
Artem Titov3ab7a552021-04-14 14:23:1025The paced sender solves this by having a buffer in which media is queued, and
26then using a _leaky bucket_ algorithm to pace them onto the network. The buffer
27contains separate fifo streams for all media tracks so that e.g. audio can be
28prioritized over video - and equal prio streams can be sent in a round-robin
29fashion to avoid any one stream blocking others.
30
31Since the pacer is in control of the bitrate sent on the wire, it is also used
32to generate padding in cases where a minimum send rate is required - and to
33generate packet trains if bitrate probing is used.
Erik Språng32347b52021-04-13 16:18:5534
35## Life of a Packet
36
Artem Titov3ab7a552021-04-14 14:23:1037The typical path for media packets when using the paced sender looks something
38like this:
Erik Språng32347b52021-04-13 16:18:5539
Artem Titov3ab7a552021-04-14 14:23:10401. `RTPSenderVideo` or `RTPSenderAudio` packetizes media into RTP packets.
412. The packets are sent to the [RTPSender] class for transmission.
423. The pacer is called via [RtpPacketSender] interface to enqueue the packet
43 batch.
444. The packets are put into a queue within the pacer awaiting opportune moments
45 to send them.
465. At a calculated time, the pacer calls the `PacingController::PacketSender()`
47 callback method, normally implemented by the [PacketRouter] class.
486. The router forwards the packet to the correct RTP module based on the
49 packet's SSRC, and in which the `RTPSenderEgress` class makes final time
50 stamping, potentially records it for retransmissions etc.
517. The packet is sent to the low-level `Transport` interface, after which it is
52 now out of scope.
Erik Språng32347b52021-04-13 16:18:5553
Artem Titov3ab7a552021-04-14 14:23:1054Asynchronously to this, the estimated available send bandwidth is determined -
55and the target send rate is set on the `RtpPacketPacker` via the `void
56SetPacingRates(DataRate pacing_rate, DataRate padding_rate)` method.
Erik Språng32347b52021-04-13 16:18:5557
58## Packet Prioritization
59
60The pacer prioritized packets based on two criteria:
61
Artem Titov3ab7a552021-04-14 14:23:1062* Packet type, with most to least prioritized:
63 1. Audio
64 2. Retransmissions
65 3. Video and FEC
66 4. Padding
67* Enqueue order
Erik Språng32347b52021-04-13 16:18:5568
Artem Titov3ab7a552021-04-14 14:23:1069The enqueue order is enforced on a per stream (SSRC) basis. Given equal
70priority, the [RoundRobinPacketQueue] alternates between media streams to ensure
71no stream needlessly blocks others.
Erik Språng32347b52021-04-13 16:18:5572
73## Implementations
74
Artem Titov3ab7a552021-04-14 14:23:1075There are currently two implementations of the paced sender (although they share
76a large amount of logic via the `PacingController` class). The legacy
77[PacedSender] uses a dedicated thread to poll the pacing controller at 5ms
78intervals, and has a lock to protect internal state. The newer
79[TaskQueuePacedSender] as the name implies uses a TaskQueue to both protect
80state and schedule packet processing, the latter is dynamic based on actual send
81rates and constraints. Avoid using the legacy PacedSender in new applications as
82we are planning to remove it.
Erik Språng32347b52021-04-13 16:18:5583
84## The Packet Router
85
Artem Titov3ab7a552021-04-14 14:23:1086An adjacent component called [PacketRouter] is used to route packets coming out
87of the pacer and into the correct RTP module. It has the following functions:
Erik Språng32347b52021-04-13 16:18:5588
Artem Titov3ab7a552021-04-14 14:23:1089* The `SendPacket` method looks up an RTP module with an SSRC corresponding to
90 the packet for further routing to the network.
91* If send-side bandwidth estimation is used, it populates the transport-wide
92 sequence number extension.
93* Generate padding. Modules supporting payload-based padding are prioritized,
94 with the last module to have sent media always being the first choice.
95* Returns any generated FEC after having sent media.
96* Forwards REMB and/or TransportFeedback messages to suitable RTP modules.
Erik Språng32347b52021-04-13 16:18:5597
Artem Titov3ab7a552021-04-14 14:23:1098At present the FEC is generated on a per SSRC basis, so is always returned from
99an RTP module after sending media. Hopefully one day we will support covering
100multiple streams with a single FlexFEC stream - and the packet router is the
101likely place for that FEC generator to live. It may even be used for FEC padding
102as an alternative to RTX.
Erik Språng32347b52021-04-13 16:18:55103
104## The API
105
Artem Titov3ab7a552021-04-14 14:23:10106The section outlines the classes and methods relevant to a few different use
107cases of the pacer.
Erik Språng32347b52021-04-13 16:18:55108
109### Packet sending
110
Artem Titov3ab7a552021-04-14 14:23:10111For sending packets, use
112`RtpPacketSender::EnqueuePackets(std::vector<std::unique_ptr<RtpPacketToSend>>
113packets)` The pacer takes a `PacingController::PacketSender` as constructor
114argument, this callback is used when it's time to actually send packets.
Erik Språng32347b52021-04-13 16:18:55115
116### Send rates
117
Artem Titov3ab7a552021-04-14 14:23:10118To control the send rate, use `void SetPacingRates(DataRate pacing_rate,
119DataRate padding_rate)` If the packet queue becomes empty and the send rate
120drops below `padding_rate`, the pacer will request padding packets from the
121`PacketRouter`.
Erik Språng32347b52021-04-13 16:18:55122
Artem Titov3ab7a552021-04-14 14:23:10123In order to completely suspend/resume sending data (e.g. due to network
124availability), use the `Pause()` and `Resume()` methods.
Erik Språng32347b52021-04-13 16:18:55125
Artem Titov3ab7a552021-04-14 14:23:10126The specified pacing rate may be overriden in some cases, e.g. due to extreme
127encoder overshoot. Use `void SetQueueTimeLimit(TimeDelta limit)` to specify the
128longest time you want packets to spend waiting in the pacer queue (pausing
129excluded). The actual send rate may then be increased past the pacing_rate to
130try to make the _average_ queue time less than that requested limit. The
131rationale for this is that if the send queue is say longer than three seconds,
132it's better to risk packet loss and then try to recover using a key-frame rather
133than cause severe delays.
Erik Språng32347b52021-04-13 16:18:55134
135### Bandwidth estimation
136
Artem Titov3ab7a552021-04-14 14:23:10137If the bandwidth estimator supports bandwidth probing, it may request a cluster
138of packets to be sent at a specified rate in order to gauge if this causes
Per Kjellander88af2032022-05-16 17:58:40139increased delay/loss on the network. Use the `void CreateProbeCluster(...)`
140method - packets sent via this `PacketRouter` will be marked with the
141corresponding cluster_id in the attached `PacedPacketInfo` struct.
Erik Språng32347b52021-04-13 16:18:55142
Artem Titov3ab7a552021-04-14 14:23:10143If congestion window pushback is used, the state can be updated using
144`SetCongestionWindow()` and `UpdateOutstandingData()`.
Erik Språng32347b52021-04-13 16:18:55145
Artem Titov3ab7a552021-04-14 14:23:10146A few more methods control how we pace: * `SetAccountForAudioPackets()`
147determines if audio packets count into bandwidth consumed. *
148`SetIncludeOverhead()` determines if the entire RTP packet size counts into
149bandwidth used (otherwise just media payload). * `SetTransportOverhead()` sets
150an additional data size consumed per packet, representing e.g. UDP/IP headers.
Erik Språng32347b52021-04-13 16:18:55151
152### Stats
153
154Several methods are used to gather statistics in pacer state:
Erik Språng32347b52021-04-13 16:18:55155
Artem Titov3ab7a552021-04-14 14:23:10156* `OldestPacketWaitTime()` time since the oldest packet in the queue was
157 added.
158* `QueueSizeData()` total bytes currently in the queue.
159* `FirstSentPacketTime()` absolute time the first packet was sent.
160* `ExpectedQueueTime()` total bytes in the queue divided by the send rate.
Erik Språng32347b52021-04-13 16:18:55161
Tony Herreb0ed1202021-07-22 15:40:44162[RTPSender]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/rtp_rtcp/source/rtp_sender.h;drc=77ee8542dd35d5143b5788ddf47fb7cdb96eb08e
163[RtpPacketSender]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/rtp_rtcp/include/rtp_packet_sender.h;drc=ea55b0872f14faab23a4e5dbcb6956369c8ed5dc
164[RtpPacketPacer]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/pacing/rtp_packet_pacer.h;drc=e7bc3a347760023dd4840cf6ebdd1e6c8592f4d7
165[PacketRouter]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/pacing/packet_router.h;drc=3d2210876e31d0bb5c7de88b27fd02ceb1f4e03e
166[PacedSender]: https://source.chromium.org/chromium/chromium/src/+/main:media/cast/net/pacing/paced_sender.h;drc=df00acf8f3cea9a947e11dc687aa1147971a1883
167[TaskQueuePacedSender]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/pacing/task_queue_paced_sender.h;drc=5051693ada61bc7b78855c6fb3fa87a0394fa813
168[RoundRobinPacketQueue]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/pacing/round_robin_packet_queue.h;drc=b571ff48f8fe07678da5a854cd6c3f5dde02855f