defmodule Membrane.RTC.Engine.Endpoint.WebRTC.ConnectionAllocator do
@moduledoc """
Behavior defining a set of functions for managing connection allocations for TrackReceivers.
It is responsible for allocating connection bandwidth for track receivers and probing the connection.
# Message protocol
In addition to implementing the behavior, Each implementation of ConnectionAllocator should be aware of the
following message protocol.
`Membrane.RTC.Engine.Endpoint.WebRTC.TrackReceiver` already implements proper handling of this message protocol.
## Granting an allocation
`t:#{inspect(__MODULE__)}.AllocationGrantedNotification.t/0` message is sent to TrackReceiver when ConnectionAllocator
wants to grant an allocation. TrackReceiver is obligated to comply. This message can also be used to
force-lower the allocation of a particular TrackReceiver, skipping the negotiation flow.
## Negotiating lower allocation
Whenever it is deemed necessary, ConnectionAllocator can send `t:decrease_allocation_request/0` to
selected TrackReceiver, to request that it lowers its allocation by unspecified amount.
Usually, this will mean that TrackReceiver selects a lower variant (if possible).
In response, TrackReceiver sends `t:decrease_allocation_request_response/0` to ConnectionAllocator.
If the request was accepted, TrackReceiver is obligated to request lower allocation
immediately after sending a reply.
### Example of decrease allocation request message flow
```
CA - Connection Allocator
TR - Track Receiver
CA -> TR: :decrease_your_allocation
TR -> CA: {:decrease_allocation_request, :accept}
TR calls `request_allocation/2` with lowered allocation
CA -> AllocationGrantedNotification
```
"""
alias Membrane.Buffer
alias Membrane.RTC.Engine.Track
@type allocator_ref() :: any()
@typedoc """
Type describing a message sent by ConnectionAllocator to `Membrane.RTC.Engine.Endpoint.WebRTC.TrackReceiver`
to request that they lower their allocation.
"""
@type decrease_allocation_request() :: :decrease_your_allocation
@typedoc """
Type describing a message sent by `Membrane.RTC.Engine.Endpoint.WebRTC.TrackReceiver` to ConnectionAllocator
in response to `t:decrease_allocation_request/0`, in order to either accept or reject the request.
"""
@type decrease_allocation_request_response() ::
{:decrease_allocation_request, :accept | :reject}
# Lifecycle callbacks
@doc """
A function that should be used by the WebRTC Endpoint to create an instance of ConnectionAllocator
"""
@callback create() :: {:ok, allocator_ref()} | {:error, reason :: any()}
@doc """
A function that should be used by the endpoint to destroy an instance of ConnectionAllocator
"""
@callback destroy(allocator_ref()) :: :ok
# API
@doc """
Function invoked by the TrackReceiver whenever a buffer is sent
"""
@callback buffer_sent(allocator_ref(), Buffer.t()) :: :ok
@doc """
Function called by the TrackReceiver to register itself in the allocator
"""
@callback register_track_receiver(allocator_ref(), number(), Track.t(), Keyword.t()) :: :ok
@doc """
A function called by the endpoint, to update the bandwidth estimation in the allocator
"""
@callback update_bandwidth_estimation(allocator_ref(), number()) :: :ok
@doc """
A function used by the VariantSelector to request a different bandwidth allocation.
In response, the Allocator sends `Membrane.RTC.Engine.Endpoint.WebRTC.ConnectionAllocator.AllocationGrantedNotification`
to the track receiver that gets new allocation.
"""
@callback request_allocation(allocator_ref(), number()) :: :ok
@doc """
Function used to change the negotiability status of the TrackReceiver.
TrackReceiver is considered negotiable if it is both capable of decreasing its bandwidth usage and, in principal, allowed to do so.
"""
@callback set_negotiability_status(allocator_ref(), boolean()) :: :ok
end