RTCP support
RFC 3550 requires conforming implementations to provide RTCP support. In fact, roc can function without it, though RTCP provides some benefits:
- without RTCP, sender has no feedback from receiver; it even doesn't know, if receiver was able to receive traffic, if receiver was able to process the traffic and didn't reject it for some reason, and if quality of service is acceptable;
- RTCP allows receiver to detect associated streams from single sender in a standard-conforming way, e.g. audio stream and FEC stream (we're now using an ad-hoc implementation that conforms to no standard);
- RTCP provides timing synchronisation for sender and receiver and for several streams of single sender (e.g. audio and video);
- RTCP can be used to implement dynamic adjustment of latency and FEC code rate (using RFC 5725);
- RTCP can be used to implement retransmission using RFC 4588 and RFC 4585;
- RTCP allows multiple senders to share the same source transport address (e.g. in case of RTP translator);
- RTCP allows seamless sender restart or address change (this also allows sender roaming);
- RTCP allows receiver to terminate sender's session immediately without waiting for timeout;
- RTCP is used in RTSP, which we may want to support in future;
- with RTCP, receiver sends to sender various statistics that may be useful for troubleshooting, especially when receiver is some embedded device which is harder to debug;
- some senders may reject connection if there is no RTCP feedback from receiver (I'm not aware of such senders however);
- finally, RTCP also allows to exchange arbitrary application-specific data.
RTCP consists of the following message types:
SR(sender report): statistics sent from sender to receiver;RR(receiver report): statistics and feedback send from receiver to sender;SDES(source description items): sender identification sent from sender to receiver;BYE: session termination, initiated by sender or receiver;APP: arbitrary application-specific data.
Overview
RTCP support will consist of three parts:
- RTCP packet, composer and parser
- RTCP support for roc_ctl (#214), for sender and for receiver
- RTCP control ports support in the API and command-line tools
Implementation
Packet format
-
[ ] Add RTCP support to roc::packet::Packet.
-
[ ] Implement RTCP parser and composer. We also need regression tests for RTCP packets, like we have for RTP and FECFRAME, including real-world samples captured with wireshark or other tools.
Integration
-
[ ] Send
SRandRRmessages. Fill them correctly on the sending side. For now, just log them on the receiving side. -
[ ] Send
SDESmessage from the sender and handle them on the receiver. Sender should send multipleSSRCidentifiers for singleCNAMEelement to associate source and repair streams belonging to the same session. Receiver should useCNAMEto allow streams of the same sessions to have different source ports. -
[ ] Send
BYEfrom receiver when session is rejected (can't be created or is killed) and from sender when session is terminated. Handle it on the other side. -
[ ] Respect congestion constraints dictated by RTCP and don't send RTCP packets more frequently than allowed.
API and tools
-
[ ] Extend the public API. Add control port type and RTCP protocol. Allow to bind and connect receiver and sender to control ports. Allow to bind sender to different source and repair ports.
-
[ ] Also, add RTCP port to command-line tools and PulseAudio modules.
Related RFCs
RTCP and SDP:
- https://tools.ietf.org/html/rfc3605
- https://tools.ietf.org/html/rfc3556
- https://tools.ietf.org/html/rfc3890
Multiplexing RTP and RTCP:
- https://www.rfc-editor.org/rfc/rfc5761
- https://www.rfc-editor.org/rfc/rfc8035
RTP/AVPF and XRs:
- https://tools.ietf.org/html/rfc4585
- https://tools.ietf.org/html/rfc5725
RTCP and security / encryption:
- https://tools.ietf.org/html/rfc7022
- https://tools.ietf.org/html/rfc5124
Steps
Implement components
- [x] rtcp::Parser
- [x] rtcp::Composer
- [x] rtcp::Builder
- [x] rtcp::Traverser
- [x] rtcp::XrTraverser
- [x] rtcp::SdesTraverser
- [x] rtcp::ByeTraverser
- [x] rtcp::IStreamController
- [x] rtcp::Reporter
- [x] rtcp::Communicator (process and generates packets)
- [x] rtcp::RttEstimator (estimates RTT based on XR)
Refine error handling
- [x] instead of INVALID state, keep only END state and add bool error() getter to check if there were errors; this will make user code less bug prone - the last state is always END
- [x] if we skip some packet/chunk/block, we should set error flag so that the user can check it with bool error() getter; this should be done in all traverser
- [x] when we skip something, we should allow to continue to next item, don't fail instantly, so that the user could parse everything that is parsable
Support padding
- [x] RTCP traverser: remove padding
- [x] RTCP builder: pad last packet in compound
Refine test coverage
- [x] unknown RTCP packet type
- [x] unknown XR blocks
- [x] zero blocks (RR, SR, XR)
- [x] zero sub-blocks (XR DLRR)
- [x] zero chunks, zero items (SDES)
- [x] zero sources (BYE)
- [x] empty strings (SDES item, BYE reason)
- [x] multiple SDES chunks
- [x] test for various invalid packets
- [x] tests for padding
Integration into pipeline
- [x] teach receiver to send packets
- [x] teach sender to receive packets
- [x] teach netio to share port for receiving and sending
- [x] receiver: implement rtcp::IStreamController
- [x] receiver: query reports from sessions (multiple streams per each session)
- [x] receiver: pass reports to sessions
- [x] receiver: session routing based on RTCP
- [x] receiver: associate streams based on SDES CNAME messages
- [x] receiver: terminate sessions based on BYE messages
- [x] sender: implement rtcp::IStreamController
- [x] sender: query report from pipeline
- [x] sender: pass report to pipeline
Reports checklist
- [x] receiver: fully fill RR/XR
- [x] receiver: fully handle SR/XR
- [x] sender: fully fill SR/XR
- [x] sender: fully handle RR/XR
Packet handling checklist
- [x] SDES: generate (on sender and receiver)
- [x] SDES: process (on sender and receiver)
- [x] BYE: generate (on sender and receiver)
- [x] BYE: process (on sender and receiver)
- [x] SR, DLRR: generate (on sender)
- [x] SR, DLRR: process (on receiver)
- [x] RR, RRTR: generate (on receiver)
- [x] RR, RRTR: process (on sender)
API and CLI
- [x] Extend the public API. Add control port type and RTCP protocol. Allow to bind and connect receiver and sender to control ports. Allow to bind sender to different source and repair ports.
- [x] Add RTCP port to command-line tools.
- [x] Support two-way control packet exchange in roc_sender_encoder & roc_receiver_decoder
High-level tests
- [x] rtcp communicator
- [x] pipeline
- [x] public_api
Done.