Reference¶
Warning
There is no compatibility promise until 1.0.0 is released. Small breaking changes are possible.
roc_context¶
#include <roc/context.h>
-
typedef struct roc_context
roc_context
¶ Roc context.
Context contains memory pools and network worker thread(s). Other objects that work with memory and network should be attached to a context. It is allowed both to create a separate context for every object, or to create a single context shared between multiple objects.
A context is created using roc_context_open() and destroyed using roc_context_close(). Objects can be attached and detached to an opened context at any moment from any thread. However, the user should ensure that the context is not closed until there are no objects attached to the context.
Thread-safety
- can be used concurrently
- See
- roc_sender, roc_receiver
-
roc_context*
roc_context_open
(const roc_context_config * config)¶ Open a new context.
Allocates and initializes a new context. May start some background threads.
Parameters
config
should point to an initialized config
Returns
- returns a new context if it was successfully created
- returns NULL if the arguments are invalid
- returns NULL if there are not enough resources
-
int
roc_context_close
(roc_context * context)¶ Close the context.
Stops any started background threads, deinitializes and deallocates the context. The user should ensure that nobody uses the context during and after this call.
If this function fails, the context is kept opened.
Parameters
context
should point to an opened context
Returns
- returns zero if the context was successfully closed
- returns a negative value if the arguments are invalid
- returns a negative value if there are objects attached to the context
roc_sender¶
#include <roc/sender.h>
-
typedef struct roc_sender
roc_sender
¶ Roc sender.
Sender gets an audio stream from the user, encodes it into network packets, and transmits them to a remote receiver.
Context
Sender is automatically attached to a context when opened and detached from it when closed. The user should not close the context until the sender is not closed.
Sender work consists of two parts: stream encoding and packet transmission. The encoding part is performed in the sender itself, and the transmission part is performed in the context network worker thread(s).
Lifecycle
A sender is created using roc_sender_open(). Then it should be bound to a local port using roc_sender_bind() and connected to a single or multiple remote receiver ports using roc_sender_connect(). After that, the audio stream is iteratively written to the sender using roc_sender_write(). When the sender is not needed anymore, it is destroyed using roc_sender_close().
Ports
The user is responsible for connecting the sender to all necessary receiver ports and selecting the same port types and protocols as at the receiver side.
Currently, two configurations are possible:
- If FEC is disabled, a single port of type
ROC_PORT_AUDIO_SOURCE
should be connected. The only supported protocol in this case isROC_PROTO_RTP
. This port will be used to send audio packets. - If FEC is enabled, two ports of types
ROC_PORT_AUDIO_SOURCE
andROC_PORT_AUDIO_REPAIR
should be connected. These ports will be used to send audio packets and redundant data for audio packets, respectively. The supported protocols in this case depend on the selected FEC code. For example, ifROC_FEC_RS8M
is used, the corresponding protocols would beROC_PROTO_RTP_RSM8_SOURCE
andROC_PROTO_RSM8_REPAIR
.
Resampling
If the sample rate of the user frames and the sample rate of the network packets are different, the sender employs resampler to convert one rate to another.
Resampling is a quite time-consuming operation. The user can choose between completely disabling resampling (and so use the same rate for frames and packets) or several resampler profiles providing different compromises between CPU consumption and quality.
Timing
Sender should encode samples at a constant rate that is configured when the sender is created. There are two ways to accomplish this:
- If the user enabled the automatic timing feature, the sender employs a CPU timer to block writes until it's time to encode the next bunch of samples according to the configured sample rate. This mode is useful when the user gets samples from a non-realtime source, e.g. from an audio file.
- Otherwise, the samples written to the sender are encoded immediately and the user is responsible to write samples in time. This mode is useful when the user gets samples from a realtime source with its own clock, e.g. from an audio device. Automatic clocking should not be used in this case because the audio device and the CPU might have slightly different clocks, and the difference will eventually lead to an underrun or an overrun.
Thread-safety
- can be used concurrently
- If FEC is disabled, a single port of type
-
roc_sender*
roc_sender_open
(roc_context * context, const roc_sender_config * config)¶ Open a new sender.
Allocates and initializes a new sender, and attaches it to the context.
Parameters
context
should point to an opened contextconfig
should point to an initialized config
Returns
- returns a new sender if it was successfully created
- returns NULL if the arguments are invalid
- returns NULL if there are not enough resources
-
int
roc_sender_bind
(roc_sender * sender, roc_address * address)¶ Bind the sender to a local port.
Binds the sender to a local port. Should be called exactly once before calling roc_sender_write() first time.
If
address
has zero port, the sender is bound to a randomly chosen ephemeral port. If the function succeeds, the actual port to which the sender was bound is written back toaddress
.Parameters
sender
should point to an opened senderaddress
should point to a properly initialized address
Returns
- returns zero if the sender was successfully bound to a port
- returns a negative value if the arguments are invalid
- returns a negative value if the sender is already bound
- returns a negative value if the address can't be bound
- returns a negative value if there are not enough resources
-
int
roc_sender_connect
(roc_sender * sender, roc_port_type type, roc_protocol proto, const roc_address * address)¶ Connect the sender to a remote receiver port.
Connects the sender to a receiver port. Should be called one or multiple times before calling roc_sender_write() first time. The
type
andproto
should be the same as they are set at the receiver for this port.Parameters
sender
should point to an opened sendertype
specifies the receiver port typeproto
specifies the receiver port protocoladdress
should point to a properly initialized address
Returns
- returns zero if the sender was successfully connected to a port
- returns a negative value if the arguments are invalid
- returns a negative value if roc_sender_write() was already called
-
int
roc_sender_write
(roc_sender * sender, const roc_frame * frame)¶ Encode samples to packets and transmit them to the receiver.
Encodes samples to packets and enqueues them for transmission by the context network worker thread. Should be called after roc_sender_bind() and roc_sender_connect().
If the automatic timing is enabled, the function blocks until it's time to encode the samples according to the configured sample rate. The function returns after encoding and enqueuing the packets, without waiting when the packets are actually transmitted.
Parameters
sender
should point to an opened, bound, and connected senderframe
should point to a valid frame with an array of samples to send
Returns
- returns zero if all samples were successfully encoded and enqueued
- returns a negative value if the arguments are invalid
- returns a negative value if the sender is not bound or connected
- returns a negative value if there are not enough resources
-
int
roc_sender_close
(roc_sender * sender)¶ Close the sender.
Deinitializes and deallocates the sender, and detaches it from the context. The user should ensure that nobody uses the sender during and after this call. If this function fails, the sender is kept opened and attached to the context.
Parameters
sender
should point to an opened sender
Returns
- returns zero if the sender was successfully closed
- returns a negative value if the arguments are invalid
roc_receiver¶
#include <roc/receiver.h>
-
typedef struct roc_receiver
roc_receiver
¶ Roc receiver.
Receiver receives the network packets from multiple senders, decodes audio streams from them, mixes multiple streams into a single stream, and returns it to the user.
Context
Receiver is automatically attached to a context when opened and detached from it when closed. The user should not close the context until the receiver is not closed.
Receiver work consists of two parts: packet reception and stream decoding. The decoding part is performed in the receiver itself, and the reception part is performed in the context network worker thread(s).
Lifecycle
A receiver is created using roc_receiver_open(). Then it should be bound to a single or multiple local ports using roc_receiver_bind(). After that, the audio stream is iteratively read from the receiver using roc_receiver_read(). When the receiver is not needed anymore, it is destroyed using roc_receiver_close().
Ports
Receiver can be bound to multiple network ports of several types. Every port handles packets of the specific protocol selected when the port is bound. It is allowed to bind multiple ports of the same type, typically handling different protocols.
Senders can then be connected to some or all receiver ports to transmit one or several packet streams. If a sender employs FEC, it needs to be connected to a pair of
ROC_PORT_AUDIO_SOURCE
andROC_PORT_AUDIO_REPAIR
ports which protocols correspond to the employed FEC code. Otherwise, the sender needs to be connected to a singleROC_PORT_AUDIO_SOURCE
port.Sessions
Receiver creates a session object for every sender connected to it. Sessions can appear and disappear at any time. Multiple sessions can be active at the same time.
A session is identified by the sender address. A session may contain multiple packet streams sent to different receiver ports. If the sender employs FEC, the session will contain source and repair packet streams. Otherwise, the session will contain a single source packet stream.
A session is created automatically on the reception of the first packet from a new address and destroyed when there are no packets during a timeout. A session is also destroyed on other events like a large latency underrun or overrun or broken playback, but if the sender continues to send packets, it will be created again shortly.
Mixing
Receiver mixes audio streams from all currently active sessions into a single output stream. The output stream continues no matter how much active sessions there are at the moment. In particular, if there are no sessions, the receiver produces a stream with all zeros. Sessions can be added and removed from the output stream at any time, probably in the middle of a frame.
Resampling
Every session may have a different sample rate. And even if nominally all of them are of the same rate, device frequencies usually differ by a few tens of Hertz.
Receiver compensates these differences by adjusting the rate of every session stream to the rate of the receiver output stream using a per-session resampler. The frequencies factor between the sender and the receiver clocks is calculated dynamically for every session based on the session incoming packet queue size.
Resampling is a quite time-consuming operation. The user can choose between completely disabling resampling (at the cost of occasional underruns or overruns) or several resampler profiles providing different compromises between CPU consumption and quality.
Timing
Receiver should decode samples at a constant rate that is configured when the receiver is created. There are two ways to accomplish this:
- If the user enabled the automatic timing feature, the receiver employs a CPU timer to block reads until it's time to decode the next bunch of samples according to the configured sample rate. This mode is useful when the user passes samples to a non-realtime destination, e.g. to an audio file.
- Otherwise, the samples read from the receiver are decoded immediately and the user is responsible to read samples in time. This mode is useful when the user passes samples to a realtime destination with its own clock, e.g. to an audio device. Automatic clocking should not be used in this case because the audio device and the CPU might have slightly different clocks, and the difference will eventually lead to an underrun or an overrun.
Thread-safety
- can be used concurrently
-
roc_receiver*
roc_receiver_open
(roc_context * context, const roc_receiver_config * config)¶ Open a new receiver.
Allocates and initializes a new receiver, and attaches it to the context.
Parameters
context
should point to an opened contextconfig
should point to an initialized config
Returns
- returns a new receiver if it was successfully created
- returns NULL if the arguments are invalid
- returns NULL if there are not enough resources
-
int
roc_receiver_bind
(roc_receiver * receiver, roc_port_type type, roc_protocol proto, roc_address * address)¶ Bind the receiver to a local port.
Binds the receiver to a local port. May be called multiple times to bind multiple port. May be called at any time.
If
address
has zero port, the receiver is bound to a randomly chosen ephemeral port. If the function succeeds, the actual port to which the receiver was bound is written back toaddress
.Parameters
receiver
should point to an opened receivertype
specifies the port typeproto
specifies the port protocoladdress
should point to a properly initialized address
Returns
- returns zero if the receiver was successfully bound to a port
- returns a negative value if the arguments are invalid
- returns a negative value if the address can't be bound
- returns a negative value if there are not enough resources
-
int
roc_receiver_read
(roc_receiver * receiver, roc_frame * frame)¶ Read samples from the receiver.
Reads network packets received on bound ports, routes packets to sessions, repairs lost packets, decodes samples, resamples and mixes them, and finally stores samples into the provided frame.
If the automatic timing is enabled, the function blocks until it's time to decode the samples according to the configured sample rate.
Parameters
receiver
should point to an opened receiverframe
should point to an initialized frame which will be filled with samples; the number of samples is defined by the frame size
Returns
- returns zero if all samples were successfully decoded
- returns a negative value if the arguments are invalid
- returns a negative value if there are not enough resources
-
int
roc_receiver_close
(roc_receiver * receiver)¶ Close the receiver.
Deinitializes and deallocates the receiver, and detaches it from the context. The user should ensure that nobody uses the receiver during and after this call. If this function fails, the receiver is kept opened and attached to the context.
Parameters
receiver
should point to an opened receiver
Returns
- returns zero if the receiver was successfully closed
- returns a negative value if the arguments are invalid
roc_frame¶
#include <roc/frame.h>
-
struct
roc_frame
Audio frame.
Represents a multichannel sequence of audio samples. The user is responsible for allocating and deallocating the frame and the data it is pointing to.
Thread-safety
- should not be used concurrently
roc_address¶
#include <roc/address.h>
-
typedef enum roc_family
roc_family
¶
-
roc_family
Network address family.
Values:
-
1
¶ Invalid address.
-
0
¶ Automatically detect address family from string format.
-
1
IPv4 address.
-
2
¶ IPv6 address.
-
-
typedef struct roc_address
roc_address
¶
-
struct
roc_address
Network address.
Represents an Internet address, i.e. and IP address plus UDP or TCP port. Similar to struct sockaddr.
Thread-safety
- should not be used concurrently
-
int
roc_address_init
(roc_address * address, roc_family family, const char * ip, int port)¶ Initialize address.
Parses an IP address from a string representation and initializes
address
. Iffamily
isROC_AF_AUTO
, the address family is auto-detected from theip
format. Otherwise, theip
format should correspond to thefamily
specified.When
address
is used to bind a sender or receiver port, the "0.0.0.0"ip
may be used to bind the port to all network interfaces, and the zeroport
may be used to bind the port to a randomly chosen ephemeral port.The user is responsible for allocating and deallocating
address
. An address doesn't contain any dynamically allocated data, so no special deinitialization is required.Parameters
address
should point to a probably uninitialized struct allocated by userfamily
should beROC_AF_AUTO
,ROC_AF_IPv4
, orROC_AF_IPv6
ip
should point to a zero-terminated string with a valid IPv4 or IPv6 addressport
should be a port number in range [0; 65536)
Returns
- returns zero if
address
was successfully initialized - returns a negative value if the arguments are invalid
-
roc_family
roc_address_family
(const roc_address * address)¶ Get address family.
Parameters
address
should point to a properly initialized address struct
Returns
- returns the address family if no error occurred
- returns
ROC_AF_INVALID
if the arguments are invalid
-
const char*
roc_address_ip
(const roc_address * address, char * buf, size_t bufsz)¶ Get IP address.
Formats the zero-terminated string representation of the IP address to the given buffer. The function fails if the buffer is not large enough to store the string plus the terminating zero.
Parameters
address
should point to a properly initialized address structbuf
should point to a probably uninitialized buffer allocated by user at least of thebufsz
sizebufsz
defines thebuf
size
Returns
- returns
buf
if the IP address was successfully stored into thebuf
- returns NULL if the buffer is too small to store the formatted IP address
- returns NULL if the arguments are invalid
-
int
roc_address_port
(const roc_address * address)¶ Get address port.
Parameters
address
should point to a properly initialized address struct
Returns
- returns a non-negative port number if no error occurred
- returns a negative value if the arguments are invalid
roc_config¶
#include <roc/config.h>
-
typedef enum roc_port_type
roc_port_type
¶
-
roc_port_type
Network port type.
Values:
-
1
Network port for audio source packets.
If FEC is not used, this type of port is used to send or receive audio packets. If FEC is used, this type of port is used to send or receive FEC source packets containing audio data plus some FEC headers.
-
2
Network port for audio repair packets.
If FEC is used, this type of port is used to send or receive FEC repair packets containing redundant data for audio plus some FEC headers.
-
-
typedef enum roc_protocol
roc_protocol
¶
-
roc_protocol
Network protocol.
Values:
-
1
Bare RTP (RFC 3550).
-
2
RTP source packet (RFC 3550) + FECFRAME Reed-Solomon footer (RFC 6865) with m=8.
-
3
¶ FEC repair packet + FECFRAME Reed-Solomon header (RFC 6865) with m=8.
-
4
¶ RTP source packet (RFC 3550) + FECFRAME LDPC-Staircase footer (RFC 6816).
-
5
¶ FEC repair packet + FECFRAME LDPC-Staircase header (RFC 6816).
-
-
typedef enum roc_fec_code
roc_fec_code
¶
-
roc_fec_code
Forward Error Correction code.
Values:
-
1
No FEC code.
Compatible with
ROC_PROTO_RTP
protocol.
-
0
Default FEC code.
Current default is
ROC_FEC_RS8M
.
-
1
Reed-Solomon FEC code (RFC 6865) with m=8.
Good for small block sizes (below 256 packets). Compatible with
ROC_PROTO_RTP_RS8M_SOURCE
andROC_PROTO_RS8M_REPAIR
protocols for source and repair ports.
-
2
LDPC-Staircase FEC code (RFC 6816).
Good for large block sizes (above 1024 packets). Compatible with
ROC_PROTO_RTP_LDPC_SOURCE
andROC_PROTO_LDPC_REPAIR
protocols for source and repair ports.
-
-
typedef enum roc_packet_encoding
roc_packet_encoding
¶
-
roc_packet_encoding
Packet encoding.
Values:
-
2
PCM signed 16-bit.
"L16" encoding from RTP A/V Profile (RFC 3551). Uncompressed samples coded as interleaved 16-bit signed big-endian integers in two's complement notation.
-
-
typedef enum roc_frame_encoding
roc_frame_encoding
¶
-
roc_frame_encoding
Frame encoding.
Values:
-
1
PCM floats.
Uncompressed samples coded as floats in range [-1; 1]. Channels are interleaved, e.g. two channels are encoded as "L R L R ...".
-
-
typedef enum roc_channel_set
roc_channel_set
¶
-
roc_channel_set
Channel set.
Values:
-
2
Stereo.
Two channels: left and right.
-
-
typedef enum roc_resampler_profile
roc_resampler_profile
¶
-
roc_resampler_profile
Resampler profile.
Values:
-
1
No resampling.
-
0
Default profile.
Current default is
ROC_RESAMPLER_MEDIUM
.
-
1
High quality, low speed.
-
2
Medium quality, medium speed.
-
3
Low quality, high speed.
-
-
typedef struct roc_context_config
roc_context_config
¶
-
struct
roc_context_config
Context configuration.
- See
- roc_context
Public Members
-
unsigned int
max_packet_size
¶ Maximum size in bytes of a network packet.
Defines the amount of bytes allocated per network packet. Sender and receiver won't handle packets larger than this. If zero, default value is used.
-
unsigned int
max_frame_size
¶ Maximum size in bytes of an audio frame.
Defines the amount of bytes allocated per intermediate internal frame in the pipeline. Does not limit the size of the frames provided by user. If zero, default value is used.
-
typedef struct roc_sender_config
roc_sender_config
¶
-
struct
roc_sender_config
Sender configuration.
- See
- roc_sender
Public Members
-
unsigned int
frame_sample_rate
¶ The rate of the samples in the frames passed to sender.
Number of samples per channel per second. If
frame_sample_rate
andpacket_sample_rate
are different, resampler should be enabled. Should be set.
-
roc_channel_set
frame_channels
¶ The channel set in the frames passed to sender.
Should be set.
-
roc_frame_encoding
frame_encoding
¶ The sample encoding in the frames passed to sender.
Should be set.
-
unsigned int
packet_sample_rate
¶ The rate of the samples in the packets generated by sender.
Number of samples per channel per second. If zero, default value is used.
-
roc_channel_set
packet_channels
¶ The channel set in the packets generated by sender.
If zero, default value is used.
-
roc_packet_encoding
packet_encoding
¶ The sample encoding in the packets generated by sender.
If zero, default value is used.
-
unsigned long long
packet_length
¶ The length of the packets produced by sender, in nanoseconds.
Number of nanoseconds encoded per packet. The samples written to the sender are buffered until the full packet is accumulated or the sender is flushed or closed. Larger number reduces packet overhead but also increases latency. If zero, default value is used.
-
unsigned int
packet_interleaving
¶ Enable packet interleaving.
If non-zero, the sender shuffles packets before sending them. This may increase robustness but also increases latency.
-
unsigned int
automatic_timing
¶ Enable automatic timing.
If non-zero, the sender write operation restricts the write rate according to the frame_sample_rate parameter. If zero, no restrictions are applied.
-
roc_resampler_profile
resampler_profile
¶ Resampler profile to use.
If non-zero, the sender employs resampler if the frame sample rate differs from the packet sample rate.
-
roc_fec_code
fec_code
¶ FEC code to use.
If non-zero, the sender employs a FEC codec to generate redundant packets which may be used on receiver to restore lost packets. This requires both sender and receiver to use two separate source and repair ports.
-
unsigned int
fec_block_source_packets
¶ Number of source packets per FEC block.
Used if some FEC code is selected. Larger number increases robustness but also increases latency. If zero, default value is used.
-
unsigned int
fec_block_repair_packets
¶ Number of repair packets per FEC block.
Used if some FEC code is selected. Larger number increases robustness but also increases traffic. If zero, default value is used.
-
typedef struct roc_receiver_config
roc_receiver_config
¶
-
struct
roc_receiver_config
Receiver configuration.
- See
- roc_receiver
Public Members
-
unsigned int
frame_sample_rate
¶ The rate of the samples in the frames returned to the user.
Number of samples per channel per second. Should be set.
-
roc_channel_set
frame_channels
¶ The channel set in the frames returned to the user.
Should be set.
-
roc_frame_encoding
frame_encoding
¶ The sample encoding in the frames returned to the user.
Should be set.
-
unsigned int
automatic_timing
¶ Enable automatic timing.
If non-zero, the receiver read operation restricts the read rate according to the
frame_sample_rate
parameter. If zero, no restrictions are applied.
-
roc_resampler_profile
resampler_profile
¶ Resampler profile to use.
If non-zero, the receiver employs resampler for two purposes:
- adjust the sender clock to the receiver clock, which may differ a bit
- convert the packet sample rate to the frame sample rate if they are different
-
unsigned long long
target_latency
¶ Target latency, in nanoseconds.
The session will not start playing until it accumulates the requested latency. Then, if resampler is enabled, the session will adjust its clock to keep actual latency as close as close as possible to the target latency. If zero, default value is used.
-
unsigned long long
max_latency_overrun
¶ Maximum delta between current and target latency, in nanoseconds.
If current latency becomes larger than the target latency plus this value, the session is terminated. If zero, default value is used.
-
unsigned long long
max_latency_underrun
¶ Maximum delta between target and current latency, in nanoseconds.
If current latency becomes smaller than the target latency minus this value, the session is terminated. May be larger than the target latency because current latency may be negative, which means that the playback run ahead of the last packet received from network. If zero, default value is used.
-
long long
no_playback_timeout
¶ Timeout for the lack of playback, in nanoseconds.
If there is no playback during this period, the session is terminated. This mechanism allows to detect dead, hanging, or broken clients generating invalid packets. If zero, default value is used. If negative, the timeout is disabled.
-
long long
broken_playback_timeout
¶ Timeout for broken playback, in nanoseconds.
If there the playback is considered broken during this period, the session is terminated. The playback is broken if there is a breakage detected at every
breakage_detection_window
duringbroken_playback_timeout
. This mechanism allows to detect vicious circles like when all client packets are a bit late and receiver constantly drops them producing unpleasant noise. If zero, default value is used. If negative, the timeout is disabled.
-
unsigned long long
breakage_detection_window
¶ Breakage detection window, in nanoseconds.
If zero, default value is used.
roc_log¶
#include <roc/log.h>
-
typedef enum roc_log_level
roc_log_level
¶
-
roc_log_level
Log level.
Values:
-
0
No messages.
Setting this level disables logging completely.
-
1
Error messages.
Setting this level enables logging only when something goes wrong, e.g. a user operation can't be completed, or there is not enough memory for a new session.
-
2
Informational messages.
Setting this level enables logging of important high-level events, like binding a new port or creating a new session.
-
3
Debug messages.
Setting this level enables logging of debug messages. Doesn't affect performance.
-
4
Debug messages (extra verbosity).
Setting this level enables verbose tracing. May cause significant slow down.
-
-
typedef void
(* roc_log_handler)
(roc_log_level level, const char *component, const char *message)¶ Log handler.
Parameters
level
defines the message levelcomponent
defines the component that produces the messagemessage
defines the message text
-
void
roc_log_set_level
(roc_log_level level)¶ Set maximum log level.
Messages with log levels higher than
level
will be dropped. By default the log level is set toROC_LOG_ERROR
.Thread-safety
- can be used concurrently
-
void
roc_log_set_handler
(roc_log_handler handler)¶ Set log handler.
If
handler
is not NULL, messages are passed to the handler. Otherwise, messages are printed to stderr. By default the log handler is set to NULL.It's guaranteed that the previously set handler, if any, will not be used after this function returns.
Thread-safety
- can be used concurrently
- handler calls are serialized, so the handler itself doesn't need to be thread-safe