Skip to content

Ring buffer for packets without session #217

@gavv

Description

@gavv

Last revised: Oct 2023

Problem

Currently, when we receive a packet, we first try to find an existing session and route the packet to it, then try to create a new session from the packet, and if both of these failed, we drop the packet.

We create sessions only when a source packet arrives and thus drop repair packets preceding the first delivered source packet. This may decrease the service quality at the session start a bit.

When we'll add RTCP and RTSP support, we might want to be able to disable session auto-creation at all and allow only explicitly announced sessions. In this case we will drop data packets until negotiation completes.

When we'll also add support for multiple sender ports, allowing different streams of the same session to have different source addresses, we will not be able to match the streams of the same session until we receive instructions from RTCP or RTSP. So in this case we will also drop data packets until negotiation completes.

When we'll add support for dynamic payload type, we also will not be able to handle and will drop packets until session negotiation completes.

In other words, there are numerous reasons why we will drop packets until session negotiation completes or, if it is disabled, until the first source packet arrives.

On the other hand, session negotiation may take time (RTSP connection establishment requires a few round-trips; RTCP packets may be lost and are not retried immediately).

In view of the above, this means that we will always drop some packets at the beginning of the session and so increase the "cold" (startup) latency.

Solution

The following simple solution is suggested, which solves all these problems:

  • when a packet can't be routed, don't drop it, but instead place it into a ring buffer
  • when a session is created, fetch all matching packets from the ring buffer and pass to the session

The ring buffer capacity should be enough to hold packets for max_latency * max_sessions samples.

Implementation

  • Add a ring buffer to pipeline::ReceiverSessionGroup; we can use core::List<packet::Packet> as a container because we don't need random access.

  • Find the place where ReceiverSessionGroup::route_packet() drops packets, and make it store the packet inside the ring buffer instead (add the packet to the end of the buffer; if the buffer capacity exceeds the limit, remove the very first packet from it).

  • Find the place where ReceiverSessionGroup creates a new session and, after creating the session, iterate over the ring buffer and try to pass every packet to the newly created session (sess->handle(packet)); if the session accepts the packet, remove it from the ring buffer.

Tests

We should cover this feature in receiver unit tests: https://github.com/roc-streaming/roc-toolkit/blob/master/src/tests/roc_pipeline/test_receiver_source.cpp

The following cases come into my mind:

  • N repair packets (N = ring_buffer_size) for the session A arrive before source packets and then a source packet arrives and the session is created; the newly created session should receive all the N repair packets

  • N repair packets (N > ring_buffer_size) for the session A arrive before source packets and then a source packet arrives and the session is created; the new session should receive only ring_buffer_size repair packets

  • N repair packets (N = ring_buffer_size) for the session A arrive before source packets, then K repair packets (K < ring_buffer_size) for the session B arrive, then source packets arrive for sessions A and B; the session B should receive all the K repair packets, and the session A should not receive any repair packets

Metadata

Metadata

Labels

C-networkingcategory: Network and streamingeasy hacksSolution requires minimal project contexthelp wantedLooking for contributorsmost wantedNeeded most among other help-wanted issues

Projects

Status

Help wanted

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions