Documentation
¶
Index ¶
- func SetLogLevel(level LogLevel)
- func SetLogger(logger Logger)
- func SetLoggerFunc(logFn LoggerFunc)
- type ChannelLayout
- type ClockSource
- type Context
- type ContextConfig
- type Endpoint
- type FecEncoding
- type Format
- type Interface
- type InterfaceConfig
- type LatencyTunerBackend
- type LatencyTunerProfile
- type LogLevel
- type LogMessage
- type Logger
- type LoggerFunc
- type MediaEncoding
- type PacketEncoding
- type Protocol
- type Receiver
- func (r *Receiver) Bind(slot Slot, iface Interface, endpoint *Endpoint) (err error)
- func (r *Receiver) Close() (err error)
- func (r *Receiver) Configure(slot Slot, iface Interface, config InterfaceConfig) (err error)
- func (r *Receiver) ReadFloats(frame []float32) (err error)
- func (r *Receiver) Unlink(slot Slot) (err error)
- type ReceiverConfig
- type ResamplerBackend
- type ResamplerProfile
- type SemanticVersion
- type Sender
- func (s *Sender) Close() (err error)
- func (s *Sender) Configure(slot Slot, iface Interface, config InterfaceConfig) (err error)
- func (s *Sender) Connect(slot Slot, iface Interface, endpoint *Endpoint) (err error)
- func (s *Sender) Unlink(slot Slot) (err error)
- func (s *Sender) WriteFloats(frame []float32) (err error)
- type SenderConfig
- type Slot
- type VersionInfo
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func SetLogLevel ¶
func SetLogLevel(level LogLevel)
SetLogLevel changes the logging level.
Messages with higher verbosity than the given level will be dropped. Default log level is LogError.
This function is thread-safe.
func SetLogger ¶
func SetLogger(logger Logger)
SetLogger is like SetLoggerFunc, but uses Logger interface instead of LoggerFunc.
If a nil Logger is passed, default logger is used, which passes all messages to the standard logger using log.Print.
This function is thread-safe.
func SetLoggerFunc ¶
func SetLoggerFunc(logFn LoggerFunc)
SetLoggerFunc sets the handler for log messages.
Starting from this call, all log messages produced by the library, will be passed to the given function. It may be called from different threads, but the calls will be always serialized, so it doesn't need to be thread-safe.
If a nil function is passed, default logger is used, which passes all messages to the standard logger using log.Print.
This function is thread-safe.
Types ¶
type ChannelLayout ¶
type ChannelLayout int
Channel layout.
Defines number of channels and meaning of each channel.
const ( // Multi-track audio. // // In multitrack layout, stream contains multiple channels which represent // independent "tracks" without any special meaning (unlike stereo or surround) // and hence without any special processing or mapping. // // The number of channels is arbitrary and is defined by Tracks field of // MediaEncoding struct. ChannelLayoutMultitrack ChannelLayout = 1 // Mono. // // One channel with monophonic sound. ChannelLayoutMono ChannelLayout = 2 // Stereo. // // Two channels: left, right. ChannelLayoutStereo ChannelLayout = 3 )
func (ChannelLayout) String ¶
func (i ChannelLayout) String() string
type ClockSource ¶
type ClockSource int
Clock source for sender or receiver.
Defines wo is responsible to invoke read or write in proper time.
const ( // Default clock source. // // Current default is ClockSourceExternal. ClockSourceDefault ClockSource = 0 // Sender or receiver is clocked by external user-defined clock. // // Write and read operations are non-blocking. The user is responsible to call // them in time, according to the external clock. // // Use when samples source (from where you read them to pass to receiver) or // destination (to where you write them after obtaining from sender) is active // and has its own clock, e.g. it is a sound card. ClockSourceExternal ClockSource = 1 // Sender or receiver is clocked by an internal pipeline clock. // // Write and read operations are blocking. They automatically wait until it's // time to process the next bunch of samples according to the configured sample // rate, based on a CPU timer. // // Use when samples source (from where you read them to pass to receiver) or // destination (to where you write them after obtaining from sender) is passive // and does now have clock, e.g. it is a file on disk. ClockSourceInternal ClockSource = 2 )
func (ClockSource) String ¶
func (i ClockSource) String() string
type Context ¶
type Context struct {
// contains filtered or unexported fields
}
Shared context.
Context contains memory pools and network worker threads, shared among objects attached to the context. It is allowed both to create a separate context for every object, or to create a single context shared between multiple objects.
Life cycle ¶
A context is created using OpenContext() and destroyed using 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 also ¶
See also Sender, Receiver
func OpenContext ¶
func OpenContext(config ContextConfig) (ctx *Context, err error)
Open a new context.
Allocates and initializes a new context. May start some background threads. Overrides the provided Result pointer with the newly created context.
func (*Context) Close ¶
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.
func (*Context) RegisterEncoding ¶
func (c *Context) RegisterEncoding(encodingID int, encoding MediaEncoding) (err error)
Register custom encoding.
Registers Encoding with given EncodingId. Registered encodings complement built-in encodings defined by PacketEncoding enum. Whenever you need to specify packet encoding, you can use both built-in and registered encodings.
On sender, you should register custom encoding and set to PacketEncoding field of SenderConfig, if you need to force specific encoding of packets, but built-in set of encodings is not enough.
On receiver, you should register custom encoding with same id and specification, if you did so on sender, and you're not using any signaling protocol (like RTSP) that is capable of automatic exchange of encoding information.
In case of RTP, encoding id is mapped directly to payload type field (PT).
type ContextConfig ¶
type ContextConfig struct {
// 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.
MaxPacketSize uint32
// 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.
MaxFrameSize uint32
}
Context configuration. You can zero-initialize this struct to get a default config. See also Context.
type Endpoint ¶
type Endpoint struct {
// Protocol of the endpoint (URI scheme).
// Should be set.
Protocol Protocol
// Host IP address or domain.
// Should be set.
// To bind to all interfaces, use "0.0.0.0" or "[::]".
Host string
// TCP or UDP port number.
// To bind to random port, use 0.
// To use default port for specified protocol, use -1.
// Some protocols don't have default port.
Port int
// Resource path.
// Can be empty.
// Some protocols don't have default resource component.
Resource string
}
Network endpoint.
Endpoint is a network entry point of a peer. The definition includes the protocol being used, network host and port, and, for some protocols, a resource. All these parts together are unambiguously represented by a URI. The user may set or get the entire URI or its individual parts.
Endpoint URI ¶
Endpoint URI syntax is a subset of the syntax defined in RFC 3986:
protocol://host[:port][/path][?query]
Examples:
rtsp://localhost:123/path?query rtp+rs8m://localhost:123 rtp://127.0.0.1:123 rtp://[::1]:123
The following protocols (schemes) are supported:
rtp:// (ProtoRtp) rtp+rs8m:// (ProtoRtpRs8mSource) rs8m:// (ProtoRs8mRepair) rtp+ldpc:// (ProtoRtpLdpcSource) ldpc:// (ProtoLdpcRepair)
The host field should be either FQDN (domain name), or IPv4 address, or IPv6 address in square brackets.
The port field can be omitted if the protocol defines standard port. Otherwise, the port can not be omitted. For example, RTSP defines standard port, but RTP doesn't.
The path and query fields are allowed only for protocols that support them. For example, they're supported by RTSP, but not by RTP.
Thread safety ¶
Should not be used concurrently.
func ParseEndpoint ¶
ParseEndpoint decomposes URI string into Endpoint instance.
type FecEncoding ¶
type FecEncoding int
Forward Error Correction encoding.
Each FEC encoding is compatible with specific protocols.
const ( // No FEC encoding. // // Compatible with ProtoRtp protocol. // // Pros: // - compatible with third-party software that does not support FECFRAME // // Cons: // - no packet recovery FecEncodingDisable FecEncoding = -1 // Default FEC encoding. // // Current default is FecEncodingRs8m. FecEncodingDefault FecEncoding = 0 // Reed-Solomon FEC encoding (RFC 6865) with m=8. // // Good for small block sizes (below 256 packets). Compatible with // ProtoRtpRs8mSource and ProtoRs8mRepair protocols for source and repair // endpoints. // // Pros: // - good repair capabilities even on small block sizes // // Cons: // - high CPU usage on large block sizes FecEncodingRs8m FecEncoding = 1 // LDPC-Staircase FEC encoding (RFC 6816). // // Good for large block sizes (above 1024 packets). Compatible with // ProtoRtpLdpcSource and ProtoLdpcRepair protocols for source and repair // endpoints. // // Pros: // - low CPU usage even on large block sizes // // Cons: // - low repair capabilities on small block sizes FecEncodingLdpcStaircase FecEncoding = 2 )
func (FecEncoding) String ¶
func (i FecEncoding) String() string
type Format ¶
type Format int
Sample format.
Defines how each sample is represented. Does not define channels layout and sample rate.
const ( // PCM floats. // // Uncompressed samples coded as 32-bit native-endian floats in range [-1; 1]. // Channels are interleaved, e.g. two channels are encoded as "L R L R...". FormatPcmFloat32 Format = 1 )
type Interface ¶
type Interface int
Network interface.
Interface is a way to access the peer (sender or receiver) via network.
Each slot of a peer (see Slot) has multiple interfaces, one for each of the interface types. The user interconnects peers by binding an interface of one peer to an URI, and then connecting the corresponding interface of another peer to that URI.
A URI is represented by Endpoint object.
The interface defines the type of the communication with the remote peer and the set of protocols (URI schemes) that can be used with this particular interface.
InterfaceConsolidated is an interface for high-level protocols which automatically manage all necessary communication: transport streams, control messages, parameter negotiation, etc. When a consolidated connection is established, peers may automatically setup lower-level interfaces like InterfaceAudioSource, InterfaceAudioRepair, and InterfaceAudioControl.
InterfaceConsolidated is mutually exclusive with lower-level interfaces. In most cases, the user needs only InterfaceConsolidated. However, the lower-level interfaces may be useful if an external signaling mechanism is used or for compatibility with third-party software.
InterfaceAudioSource and InterfaceAudioRepair are lower-level unidirectional transport-only interfaces. The first is used to transmit audio stream, and the second is used to transmit redundant repair stream, if FEC is enabled.
InterfaceAudioControl is a lower-level bidirectional interface for control streams. If you use InterfaceAudioSource and InterfaceAudioRepair, you usually also need to use InterfaceAudioControl to enable carrying additional non-transport information.
const ( // Interface that consolidates all types of streams (source, repair, control). // // Allowed operations: // - bind (sender, receiver) // - connect (sender, receiver) // // Allowed protocols: // - ProtoRtsp InterfaceConsolidated Interface = 1 // Interface for audio stream source data. // // Allowed operations: // - bind (receiver) // - connect (sender) // // Allowed protocols: // - ProtoRtp // - ProtoRtpRs8mSource // - ProtoRtpLdpcSource InterfaceAudioSource Interface = 11 // Interface for audio stream repair data. // // Allowed operations: // - bind (receiver) // - connect (sender) // // Allowed protocols: // - ProtoRs8mRepair // - ProtoLdpcRepair InterfaceAudioRepair Interface = 12 // Interface for audio control messages. // // Allowed operations: // - bind (sender, receiver) // - connect (sender, receiver) // // Allowed protocols: // - ProtoRtcp InterfaceAudioControl Interface = 13 )
type InterfaceConfig ¶
type InterfaceConfig struct {
// Outgoing IP address.
//
// If non-empty, explicitly identifies the OS network interface, by its IP
// address, from which to send outgoing packets. If NULL, the network interface
// is selected automatically by the OS, depending on the address of remote
// endpoint.
//
// For example, if eth0 has IP address "192.168.0.1", then setting outgoing
// address to "192.168.0.1" will force usage of eth0 interface.
//
// Setting it to 0.0.0.0 (for IPv4) or to :: (for IPv6) gives the same effect
// as if it was NULL.
//
// By default, empty.
OutgoingAddress string
// Multicast group IP address.
//
// Multicast group should be set only when binding or connecting interface to
// an endpoint with multicast IP address. If present, it defines an IP address
// of the OS network interface on which to join the multicast group. If not
// present, no multicast group is joined.
//
// It's allowed to receive multicast traffic from only those OS network
// interfaces, on which the process has joined the multicast group. When using
// multicast, the user should either set this field, or join multicast group
// manually using OS-specific APIs.
//
// It is allowed to set multicast group to 0.0.0.0 (for IPv4) or to :: (for
// IPv6), to be able to receive multicast traffic from all available
// interfaces. However, this may not be desirable for security reasons.
//
// By default, empty.
MulticastGroup string
// Socket address reuse flag.
//
// When true (non-zero), SO_REUSEADDR is enabled for socket, regardless of
// socket type, unless binding to ephemeral port (when port is set to zero).
//
// When false (zero), SO_REUSEADDR is enabled for socket only if it has
// multicast type, unless binding to ephemeral port (when port is set to zero).
//
// For TCP-based protocols, SO_REUSEADDR allows immediate reuse of recently
// closed socket in TIME_WAIT state, which may be useful you want to be able to
// restart server quickly.
//
// For UDP-based protocols, SO_REUSEADDR allows multiple processes to bind to
// the same address, which may be useful if you're using socket activation
// mechanism.
//
// By default, false.
ReuseAddress bool
}
Interface configuration.
Sender and receiver can have multiple slots (Slot), and each slot can be bound or connected to multiple interfaces (Interface).
Each such interface has its own configuration, defined by this struct.
For all fields, zero value means "use default". If you want to set all options to default values, you can memset() this struct with zeros.
See Sender.Configure(), Receiver.Configure().
type LatencyTunerBackend ¶
type LatencyTunerBackend int
Latency tuner backend.
Defines which latency is monitored and tuned by latency tuner.
const ( // Default backend. // // Current default is LatencyTunerBackendNiq. LatencyTunerBackendDefault LatencyTunerBackend = 0 // Latency tuning is based on network incoming queue length. // // In this mode, latency is defined as incoming queue length (in nanoseconds). // Latency tuner monitors queue length and and adjusts playback clock speed to // keep queue length close to configured target latency. // // Keeping constant queue length allows to match playback clock speed with the // capture clock speed and to keep the overall latency constant (yet unknown). // // On receiver, this backend is always available, without any protocol help. On // sender, this backend works only if RTCP is enabled and both sender and // receiver are implemented with roc-toolkit, as it relies on a non-standard // RTCP extension to report receiver queue length to sender. // // Pros: // - works with any protocol if used on receiver (does not require RTCP or // NTP) // // Cons: // - synchronizes only clock speed, but not position; different receivers will // have different (constant) delays // - affected by network jitter; spikes in packet delivery will cause slow // oscillations in clock speed LatencyTunerBackendNiq LatencyTunerBackend = 2 )
func (LatencyTunerBackend) String ¶
func (i LatencyTunerBackend) String() string
type LatencyTunerProfile ¶
type LatencyTunerProfile int
Latency tuner profile.
Defines whether latency tuning is enabled and which algorithm is used.
const ( // Default profile. // // On receiver, when LatencyTunerBackendNiq is used, selects // LatencyTunerProfileResponsive if target latency is low, and // LatencyTunerProfileGradual if target latency is high. // // On sender, selects LatencyTunerProfileIntact. LatencyTunerProfileDefault LatencyTunerProfile = 0 // No latency tuning. // // In this mode, clock speed is not adjusted. Default on sender. // // You can set this mode on receiver, and set some other mode on sender, to do // latency tuning on sender side instead of recever side. It's useful when // receiver is CPU-constrained and sender is not, because latency tuner relies // on resampling, which is CPU-demanding. // // You can also set this mode on both sender and receiver if you don't need // latency tuning at all. However, if sender and receiver have independent // clocks (which is typically the case), clock drift will lead to periodic // playback disruptions caused by underruns and overruns. LatencyTunerProfileIntact LatencyTunerProfile = 1 // Responsive latency tuning. // // Clock speed is adjusted quickly and accurately. // // Requires high precision clock adjustment, hence recommended for use with // ResamplerBackendBuiltin. // // Pros: // - allows very low latency and synchronization error // // Cons: // - does not work well with some resampler backends // - does not work well with LatencyTunerBackendNiq if network jitter is high LatencyTunerProfileResponsive LatencyTunerProfile = 2 // Gradual latency tuning. // // Clock speed is adjusted slowly and smoothly. // // Pros: // - works well even with high network jitter // - works well with any resampler backend // // Cons: // - does not allow very low latency and synchronization error LatencyTunerProfileGradual LatencyTunerProfile = 3 )
func (LatencyTunerProfile) String ¶
func (i LatencyTunerProfile) String() string
type LogLevel ¶
type LogLevel int
LogLevel defines the logging verbosity.
const ( // LogNone disables logging completely. LogNone LogLevel = 0 // LogError enables only error messages. LogError LogLevel = 1 // LogInfo enables informational messages and above. LogInfo LogLevel = 2 // LogDebug enables debugging messages and above. LogDebug LogLevel = 3 // LogTrace enables extra verbose logging, which may hurt performance // and should not be used in production. LogTrace LogLevel = 4 )
type LogMessage ¶
type LogMessage struct {
// Message log level.
Level LogLevel
// Name of the module that originated the message.
Module string
// Name of the source code file.
// May be empty.
File string
// Line number in the source code file.
Line int
// Message timestamp, unix time at which message was logged
Time time.Time
// Platform-specific process ID.
Pid uint64
// Platform-specific thread ID.
Tid uint64
// Message text.
Text string
}
LogMessage defines message written to log.
type Logger ¶
type Logger interface {
Print(v ...interface{})
}
Logger interface is an alternative way to handle log messages. It is used like LoggerFunc, but receives a single string with formatted message. This interface is compatible with log.Logger from standard library.
type LoggerFunc ¶
type LoggerFunc func(LogMessage)
LogFunc is a handler for log messages. It is called for every message, if the corresponding log level is enabled. Its calls are serialized, so it doesn't need to be thread-safe.
type MediaEncoding ¶
type MediaEncoding struct {
// Sample frequency.
//
// Defines number of samples per channel per second (e.g. 44100).
Rate uint32
// Sample format.
//
// Defines sample precision and encoding.
Format Format
// Channel layout.
//
// Defines number of channels and meaning of each channel.
Channels ChannelLayout
// Multi-track channel count.
//
// If Channels is ChannelLayoutMultitrack, defines number of channels (which
// represent independent "tracks"). For other channel layouts should be zero.
//
// Should be in range [1; 1024].
Tracks uint32
}
Media encoding.
Defines format and parameters of samples encoded in frames or packets.
type PacketEncoding ¶
type PacketEncoding int
Packet encoding.
Each packet encoding defines sample format, channel layout, and rate. Each packet encoding is compatible with specific protocols.
const ( // PCM signed 16-bit, 1 channel, 44100 rate. // // Represents 1-channel L16 stereo encoding from RTP A/V Profile (RFC 3551). // Uses uncompressed samples coded as interleaved 16-bit signed big-endian // integers in two's complement notation. // // Supported by protocols: // - ProtoRtp // - ProtoRtpRs8mSource // - ProtoRtpLdpcSource PacketEncodingAvpL16Mono PacketEncoding = 11 // PCM signed 16-bit, 2 channels, 44100 rate. // // Represents 2-channel L16 stereo encoding from RTP A/V Profile (RFC 3551). // Uses uncompressed samples coded as interleaved 16-bit signed big-endian // integers in two's complement notation. // // Supported by protocols: // - ProtoRtp // - ProtoRtpRs8mSource // - ProtoRtpLdpcSource PacketEncodingAvpL16Stereo PacketEncoding = 10 )
func (PacketEncoding) String ¶
func (i PacketEncoding) String() string
type Protocol ¶
type Protocol int
Network protocol.
Defines URI scheme of Endpoint.
const ( // RTSP 1.0 (RFC 2326) or RTSP 2.0 (RFC 7826). // // Interfaces: // - InterfaceConsolidated // // Transports: // - for signaling: TCP // - for media: RTP and RTCP over UDP or TCP ProtoRtsp Protocol = 10 // RTP over UDP (RFC 3550). // // Interfaces: // - InterfaceAudioSource // // Transports: // - UDP // // Audio encodings: // - PacketEncodingAvpL16Mono // - PacketEncodingAvpL16Stereo // - encodings registered using ContextRegisterEncoding() // // FEC encodings: // - none ProtoRtp Protocol = 20 // RTP source packet (RFC 3550) + FECFRAME Reed-Solomon footer (RFC 6865) with // m=8. // // Interfaces: // - InterfaceAudioSource // // Transports: // - UDP // // Audio encodings: // - similar to ProtoRtp // // FEC encodings: // - FecEncodingRs8m ProtoRtpRs8mSource Protocol = 30 // FEC repair packet + FECFRAME Reed-Solomon header (RFC 6865) with m=8. // // Interfaces: // - InterfaceAudioRepair // // Transports: // - UDP // // FEC encodings: // - FecEncodingRs8m ProtoRs8mRepair Protocol = 31 // RTP source packet (RFC 3550) + FECFRAME LDPC-Staircase footer (RFC 6816). // // Interfaces: // - InterfaceAudioSource // // Transports: // - UDP // // Audio encodings: // - similar to ProtoRtp // // FEC encodings: // - FecEncodingLdpcStaircase ProtoRtpLdpcSource Protocol = 32 // FEC repair packet + FECFRAME LDPC-Staircase header (RFC 6816). // // Interfaces: // - InterfaceAudioRepair // // Transports: // - UDP // // FEC encodings: // - FecEncodingLdpcStaircase ProtoLdpcRepair Protocol = 33 // RTCP over UDP (RFC 3550). // // Interfaces: // - InterfaceAudioControl // // Transports: // - UDP ProtoRtcp Protocol = 70 )
type Receiver ¶
type Receiver struct {
// contains filtered or unexported fields
}
Receiver peer.
Receiver gets 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 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 threads.
Life cycle ¶
- A receiver is created using OpenReceiver().
- Optionally, the receiver parameters may be fine-tuned using Receiver.Configure().
- The receiver either binds local endpoints using Receiver.Bind(), allowing senders connecting to them, or itself connects to remote sender endpoints using Receiver.Connect(). What approach to use is up to the user.
- The audio stream is iteratively read from the receiver using Receiver.ReadFloats(). Receiver returns the mixed stream from all connected senders.
- The receiver is destroyed using Receiver.Close().
Slots, interfaces, and endpoints ¶
Receiver has one or multiple slots, which may be independently bound or connected. Slots may be used to bind receiver to multiple addresses. Slots are numbered from zero and are created automatically. In simple cases just use SlotDefault.
Each slot has its own set of interfaces, one per each type defined in Interface. The interface defines the type of the communication with the remote peer and the set of the protocols supported by it.
Supported actions with the interface:
- Call Receiver.Bind() to bind the interface to a local Endpoint. In this case the receiver accepts connections from senders mixes their streams into the single output stream.
- Call Receiver.Connect() to connect the interface to a remote Endpoint. In this case the receiver initiates connection to the sender and requests it to start sending media stream to the receiver.
Supported interface configurations:
- Bind InterfaceConsolidated to a local endpoint (e.g. be an RTSP server).
- Connect InterfaceConsolidated to a remote endpoint (e.g. be an RTSP client).
- Bind InterfaceAudioSource, InterfaceAudioRepair (optionally, for FEC), and InterfaceAudioControl (optionally, for control messages) to local endpoints (e.g. be an RTP/FECFRAME/RTCP receiver).
Slots can be removed using Receiver.Unlink(). Removing a slot also removes all its interfaces and terminates all associated connections.
Slots can be added and removed at any time on fly and from any thread. It is safe to do it from another thread concurrently with reading frames. Operations with slots won't block concurrent reads.
FEC schemes ¶
If InterfaceConsolidated is used, it automatically creates all necessary transport interfaces and the user should not bother about them.
Otherwise, the user should manually configure InterfaceAudioSource and InterfaceAudioRepair interfaces:
- If FEC is disabled (FecEncodingDisable), only InterfaceAudioSource should be configured. It will be used to transmit audio packets.
- If FEC is enabled, both InterfaceAudioSource and InterfaceAudioRepair interfaces should be configured. The second interface will be used to transmit redundant repair data.
The protocols for the two interfaces should correspond to each other and to the FEC scheme. For example, if FecEncodingRs8m is used, the protocols should be ProtoRtpRs8mSource and ProtoRs8mRepair.
Connections ¶
Receiver creates a connection object for every sender connected to it. Connections can appear and disappear at any time. Multiple connections can be active at the same time.
A connection may contain multiple streams sent to different receiver ports. If the sender employs FEC, connection usually has source, repair, and control streams. Otherwise, connection usually has source and control streams.
Connection is created automatically on the reception of the first packet from a new sender, and terminated when there are no packets during a timeout. Connection can also be terminated on other events like a large latency underrun or overrun or continuous stuttering, but if the sender continues to send packets, connection will be created again shortly.
Mixing ¶
Receiver mixes audio streams from all currently active connections into a single output stream.
The output stream continues no matter how much active connections there are at the moment. In particular, if there are no connections, the receiver produces a stream with all zeros.
Connections can be added and removed from the output stream at any time, probably in the middle of a frame.
Transcoding ¶
Every connection may have a different sample rate, channel layout, and encoding.
Before mixing, receiver automatically transcodes all incoming streams to the format of receiver frames.
Latency tuning and bounding ¶
If latency tuning is enabled (which is by default enabled on receiver), receiver monitors latency of each connection and adjusts per-connection clock to keep latency close to the target value. The user can configure how the latency is measured, how smooth is the tuning, and the target value.
If latency bounding is enabled (which is also by default enabled on receiver), receiver also ensures that latency lies within allowed boundaries, and terminates connection otherwise. The user can configure those boundaries.
To adjust connection clock, receiver uses resampling with a scaling factor slightly above or below 1.0. Since resampling may be a quite time-consuming operation, the user can choose between several resampler backends and profiles providing different compromises between CPU consumption, quality, and precision.
Clock source ¶
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 internal clock (ClockSourceInternal), 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.
- If the user enabled external clock (ClockSourceExternal), the samples read from the receiver are decoded immediately and hence the user is responsible to call read operation according to the sample rate. This mode is useful when the user passes samples to a realtime destination with its own clock, e.g. to an audio device. Internal clock 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.
func OpenReceiver ¶
func OpenReceiver(context *Context, config ReceiverConfig) (receiver *Receiver, err error)
Open a new receiver.
Allocates and initializes a new receiver, and attaches it to the context.
func (*Receiver) Bind ¶
Bind the receiver interface to a local endpoint.
Checks that the endpoint is valid and supported by the interface, allocates a new ingoing port, and binds it to the local endpoint.
Each slot's interface can be bound or connected only once. May be called multiple times for different slots or interfaces.
Automatically initializes slot with given index if it's used first time.
If an error happens during bind, the whole slot is disabled and marked broken. The slot index remains reserved. The user is responsible for removing the slot using Receiver.Unlink(), after which slot index can be reused.
If Endpoint has explicitly set 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 to Endpoint.
func (*Receiver) Close ¶
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.
func (*Receiver) Configure ¶
func (r *Receiver) Configure(slot Slot, iface Interface, config InterfaceConfig) (err error)
Set receiver interface configuration.
Updates configuration of specified interface of specified slot. If called, the call should be done before calling Receiver.Bind() or Receiver.Connect() for the same interface.
Automatically initializes slot with given index if it's used first time.
If an error happens during configure, the whole slot is disabled and marked broken. The slot index remains reserved. The user is responsible for removing the slot using Receiver.Unlink(), after which slot index can be reused.
func (*Receiver) ReadFloats ¶
Read samples from the receiver.
Reads retrieved network packets, decodes packets, repairs losses, extracts samples, adjusts sample rate and channel layout, compensates clock drift, mixes samples from all connections, and finally stores samples into the provided frame.
If ClockSourceInternal is used, the function blocks until it's time to decode the samples according to the configured sample rate.
Until the receiver is connected to at least one sender, it produces silence. If the receiver is connected to multiple senders, it mixes their streams into one.
type ReceiverConfig ¶
type ReceiverConfig struct {
// The encoding used in frames returned by receiver.
//
// Frame encoding defines sample format, channel layout, and sample rate in
// local frames returned by receiver to user.
//
// Should be set (zero value is invalid).
FrameEncoding MediaEncoding
// Clock source.
//
// Defines whether read operation is blocking or non-blocking.
//
// If zero, default value is used (ClockSourceDefault).
ClockSource ClockSource
// Latency tuner backend.
//
// Defines which latency is monitored and controlled by latency tuner. Defines
// semantics of TargetLatency, MinLatency, and MaxLatency fields.
//
// If zero, default backend is used (LatencyTunerBackendDefault).
LatencyTunerBackend LatencyTunerBackend
// Latency tuner profile.
//
// Defines whether latency tuning is enabled and which algorithm is used.
//
// If zero, default profile is used (LatencyTunerProfileDefault).
//
// By default, latency tuning is enabled on receiver. If you disable it on
// receiver, you usually need to enable it on sender. In that case you also
// need to set TargetLatency to the same value on both sides.
LatencyTunerProfile LatencyTunerProfile
// Resampler backend.
//
// Affects CPU usage, quality, and clock synchronization precision (if latency
// tuning is enabled).
//
// If zero, default backend is used (ResamplerBackendDefault).
ResamplerBackend ResamplerBackend
// Resampler profile.
//
// Affects CPU usage and quality.
//
// If zero, default profile is used (ResamplerProfileDefault).
ResamplerProfile ResamplerProfile
// Target latency, in nanoseconds.
//
// How latency is calculated depends on LatencyTunerBackend field.
//
// If latency tuning is enabled on receiver (if LatencyTunerProfile is not
// LatencyTunerProfileIntact), receiver adjusts its clock to keep actual
// latency as close as possible to the target.
//
// By default, latency tuning is enabled on receiver. If you disable it on
// receiver, you likely want to enable it on sender. In this case you also need
// to set TargetLatency to the exact same value on both sides.
//
// If zero, default value is used.
TargetLatency time.Duration
// Maximum allowed delta between current and target latency, in nanoseconds.
//
// How latency is calculated depends on LatencyTunerBackend field.
//
// If latency tuning is enabled on receiver (if LatencyTunerProfile is not
// LatencyTunerProfileIntact), receiver monitors current latency, and if it
// differs from TargetLatency more than by LatencyTolerance, receiver
// terminates connection to sender (but it then restarts if sender continues
// streaming).
//
// By default, latency bounding is enabled on receiver. If you disable it on
// receiver, you likely want to enable it on sender.
//
// If zero, default value is used (if latency tuning is enabled on receiver).
LatencyTolerance time.Duration
// Timeout for the lack of playback, in nanoseconds.
//
// If there is no playback during this period, receiver terminates connection
// to to sender (but it then restarts if sender continues streaming).
//
// This mechanism allows to detect dead, hanging, or incompatible clients that
// generate unparseable packets.
//
// If zero, default value is used. If negative, the check is disabled.
NoPlaybackTimeout time.Duration
// Timeout for choppy playback, in nanoseconds.
//
// If there is constant stuttering during this period, receiver terminates
// connection to sender (but it then restarts if sender continues streaming).
//
// This mechanism allows to detect situations when playback continues but there
// are frequent glitches, for example because there is a high ratio of late
// packets.
//
// If zero, default value is used. If negative, the check is disabled.
ChoppyPlaybackTimeout time.Duration
}
Receiver configuration. You can zero-initialize this struct to get a default config. See also Receiver.
type ResamplerBackend ¶
type ResamplerBackend int
Resampler backend.
Affects CPU usage, quality, and clock synchronization precision. Some backends may be disabled at build time.
const ( // Default backend. // // Selects ResamplerBackendBuiltin when using LatencyTunerProfileResponsive, or // when SpeexDSP is disabled. // // Otherwise, selects ResamplerBackendSpeex. ResamplerBackendDefault ResamplerBackend = 0 // CPU-intensive good-quality high-precision built-in resampler. // // This backend controls clock speed with very high precision, and hence is // useful when latency or synchronization error should be very low. // // This backend has higher CPU usage, especially on high resampling quality and // on CPUs with small L3 caches. // // The implementation is based on bandlimited interpolation algorithm. // // This backend is always available. // // Recommended for LatencyTunerProfileResponsive and on good CPUs. ResamplerBackendBuiltin ResamplerBackend = 1 // Fast good-quality low-precision resampler based on SpeexDSP. // // This backend has low CPU usage even on high resampler quality and cheap // CPUs. // // This backend controls clock speed with lower precision, and is not so good // when latency or synchronization error should be very low. // // This backend is available only when SpeexDSP was enabled at build time. // // Recommended for LatencyTunerProfileGradual and on cheap CPUs. ResamplerBackendSpeex ResamplerBackend = 2 // Fast medium-quality and medium-precision resampler combining SpeexDSP with // decimation. // // This backend uses SpeexDSP for converting between base rates (e.g. 44100 vs // 48000) and decimation/expansion (dropping or duplicating samples) for clock // drift compensation. // // Typical decimation rate needed to compensate clock drift is below // 0.5ms/second (20 samples/second on 48Khz), which gives tolerable quality // despite usage of decimation, especially for speech. // // When frame and packet sample rates are equal (e.g. both are 44100), only // decimation stage is needed, and this becomes fastest possible backend // working almost as fast as memcpy(). // // When frame and packet rates are different, usage of this backend compared to // ResamplerBackendSpeex allows to sacrify some quality, but somewhat improve // scaling precision and CPU usage in return. // // This backend is available only when SpeexDSP was enabled at build time. // // Recommended when CPU resources are extremely limited. ResamplerBackendSpeexdec ResamplerBackend = 3 )
func (ResamplerBackend) String ¶
func (i ResamplerBackend) String() string
type ResamplerProfile ¶
type ResamplerProfile int
Resampler profile.
Affects CPU usage and quality. Each resampler backend treats profile in its own way.
const ( // Default profile. // // Current default is ResamplerProfileMedium. ResamplerProfileDefault ResamplerProfile = 0 // High quality, higher CPU usage. ResamplerProfileHigh ResamplerProfile = 1 // Medium quality, medium CPU usage. ResamplerProfileMedium ResamplerProfile = 2 // Low quality, lower CPU usage. ResamplerProfileLow ResamplerProfile = 3 )
func (ResamplerProfile) String ¶
func (i ResamplerProfile) String() string
type SemanticVersion ¶
Semantic version components.
func (SemanticVersion) String ¶
func (sv SemanticVersion) String() string
Return string format of semantic version.
type Sender ¶
type Sender struct {
// contains filtered or unexported fields
}
Sender peer.
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 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 threads.
Life cycle ¶
- A sender is created using OpenSender().
- Optionally, the sender parameters may be fine-tuned using Sender.Configure().
- The sender either binds local endpoints using Sender.Bind(), allowing receivers connecting to them, or itself connects to remote receiver endpoints using Sender.Connect(). What approach to use is up to the user.
- The audio stream is iteratively written to the sender using Sender.WriteFloats(). The sender encodes the stream into packets and send to connected receiver(s).
- The sender is destroyed using Sender.Close().
Slots, interfaces, and endpoints ¶
Sender has one or multiple slots, which may be independently bound or connected. Slots may be used to connect sender to multiple receivers. Slots are numbered from zero and are created automatically. In simple cases just use SlotDefault.
Each slot has its own set of interfaces, one per each type defined in Interface. The interface defines the type of the communication with the remote peer and the set of the protocols supported by it.
Supported actions with the interface:
- Call Sender.Bind() to bind the interface to a local Endpoint. In this case the sender accepts connections from receivers and sends media stream to all connected receivers.
- Call Sender.Connect() to connect the interface to a remote Endpoint. In this case the sender initiates connection to the receiver and starts sending media stream to it.
Supported interface configurations:
- Connect InterfaceConsolidated to a remote endpoint (e.g. be an RTSP client).
- Bind InterfaceConsolidated to a local endpoint (e.g. be an RTSP server).
- Connect InterfaceAudioSource, InterfaceAudioRepair (optionally, for FEC), and InterfaceAudioControl (optionally, for control messages) to remote endpoints (e.g. be an RTP/FECFRAME/RTCP sender).
Slots can be removed using Sender.Unlink(). Removing a slot also removes all its interfaces and terminates all associated connections.
Slots can be added and removed at any time on fly and from any thread. It is safe to do it from another thread concurrently with writing frames. Operations with slots won't block concurrent writes.
FEC schemes ¶
If InterfaceConsolidated is used, it automatically creates all necessary transport interfaces and the user should not bother about them.
Otherwise, the user should manually configure InterfaceAudioSource and InterfaceAudioRepair interfaces:
- If FEC is disabled (FecEncodingDisable), only InterfaceAudioSource should be configured. It will be used to transmit audio packets.
- If FEC is enabled, both InterfaceAudioSource and InterfaceAudioRepair interfaces should be configured. The second interface will be used to transmit redundant repair data.
The protocols for the two interfaces should correspond to each other and to the FEC scheme. For example, if FecEncodingRs8m is used, the protocols should be ProtoRtpRs8mSource and ProtoRs8mRepair.
Transcoding ¶
If encoding of sender frames and network packets are different, sender automatically performs all necessary transcoding.
Latency tuning and bounding ¶
Usually latency tuning and bounding is done on receiver side, but it's possible to disable it on receiver and enable on sender. It is useful if receiver is does not support it or does not have enough CPU to do it with good quality. This feature requires use of ProtoRtcp to deliver necessary latency metrics from receiver to sender.
If latency tuning is enabled (which is by default disabled on sender), sender monitors latency and adjusts connection clock to keep latency close to the target value. The user can configure how the latency is measured, how smooth is the tuning, and the target value.
If latency bounding is enabled (which is also by default disabled on sender), sender also ensures that latency lies within allowed boundaries, and restarts connection otherwise. The user can configure those boundaries.
To adjust connection clock, sender uses resampling with a scaling factor slightly above or below 1.0. Since resampling may be a quite time-consuming operation, the user can choose between several resampler backends and profiles providing different compromises between CPU consumption, quality, and precision.
Clock source ¶
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 internal clock (ClockSourceInternal), 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.
- If the user enabled external clock (ClockSourceExternal), the samples written to the sender are encoded and sent immediately, and hence the user is responsible to call write operation according to the sample rate. This mode is useful when the user gets samples from a realtime source with its own clock, e.g. from an audio device. Internal clock 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.
func OpenSender ¶
func OpenSender(context *Context, config SenderConfig) (sender *Sender, err error)
Open a new sender.
Allocates and initializes a new sender, and attaches it to the context.
func (*Sender) Close ¶
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.
func (*Sender) Configure ¶
func (s *Sender) Configure(slot Slot, iface Interface, config InterfaceConfig) (err error)
Set sender interface configuration.
Updates configuration of specified interface of specified slot. If called, the call should be done before calling Sender.Bind() or Sender.Connect() for the same interface.
Automatically initializes slot with given index if it's used first time.
If an error happens during configure, the whole slot is disabled and marked broken. The slot index remains reserved. The user is responsible for removing the slot using Sender.Unlink(), after which slot index can be reused.
func (*Sender) Connect ¶
Connect the sender interface to a remote receiver endpoint.
Checks that the endpoint is valid and supported by the interface, allocates a new outgoing port, and connects it to the remote endpoint.
Each slot's interface can be bound or connected only once. May be called multiple times for different slots or interfaces.
Automatically initializes slot with given index if it's used first time.
If an error happens during connect, the whole slot is disabled and marked broken. The slot index remains reserved. The user is responsible for removing the slot using Sender.Unlink(), after which slot index can be reused.
func (*Sender) Unlink ¶
Delete sender slot.
Disconnects, unbinds, and removes all slot interfaces and removes the slot. All associated connections to remote peers are properly terminated.
After unlinking the slot, it can be re-created again by re-using slot index.
func (*Sender) WriteFloats ¶
Encode samples to packets and transmit them to the receiver.
Encodes samples to packets and enqueues them for transmission by the network worker thread of the context.
If ClockSourceInternal is used, the function blocks until it's time to transmit 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.
Until the sender is connected to at least one receiver, the stream is just dropped. If the sender is connected to multiple receivers, the stream is duplicated to each of them.
type SenderConfig ¶
type SenderConfig struct {
// The encoding used in frames passed to sender.
//
// Frame encoding defines sample format, channel layout, and sample rate in
// local frames created by user and passed to sender.
//
// Should be set explicitly (zero value is invalid).
FrameEncoding MediaEncoding
// The encoding used for packets produced by sender.
//
// Packet encoding defines sample format, channel layout, and sample rate in
// network packets. If packet encoding differs from frame encoding, conversion
// is performed automatically.
//
// If zero, sender selects packet encoding automatically based on
// FrameEncoding. This automatic selection matches only encodings that have
// exact same sample rate and channel layout, and hence don't require
// conversions. If you need conversions, you should set packet encoding
// explicitly.
//
// If you want to force specific packet encoding, and built-in set of encodings
// is not enough, you can use ContextRegisterEncoding() to register custom
// encoding, and set PacketEncoding to registered identifier. If you use
// signaling protocol like RTSP, it's enough to register in just on sender;
// otherwise, you need to do the same on receiver as well.
PacketEncoding PacketEncoding
// 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 does not allow
// smaller latency.
//
// If zero, default value is used.
PacketLength time.Duration
// Enable packet interleaving.
//
// If non-zero, the sender shuffles packets before sending them. This may
// increase robustness but also increases latency.
PacketInterleaving bool
// FEC encoding to use.
//
// If FEC is enabled, the sender employs a FEC encoding to generate redundant
// packet which may be used on receiver to restore lost packets. This requires
// both sender and receiver to use two separate source and repair endpoints.
//
// If zero, default encoding is used (FecEncodingDefault).
FecEncoding FecEncoding
// Number of source packets per FEC block.
//
// Used if some FEC encoding is selected.
//
// Sender divides stream into blocks of N source (media) packets, and adds M
// repair (redundancy) packets to each block, where N is FecBlockSourcePackets
// and M is FecBlockRepairPackets.
//
// Larger number of source packets in block increases robustness (repair
// ratio), but also increases latency.
//
// If zero, default value is used.
FecBlockSourcePackets uint32
// Number of repair packets per FEC block.
//
// Used if some FEC encoding is selected.
//
// Sender divides stream into blocks of N source (media) packets, and adds M
// repair (redundancy) packets to each block, where N is FecBlockSourcePackets
// and M is FecBlockRepairPackets.
//
// Larger number of repair packets in block increases robustness (repair
// ratio), but also increases traffic. Number of repair packets usually should
// be 1/2 or 2/3 of the number of source packets.
//
// If zero, default value is used.
FecBlockRepairPackets uint32
// Clock source to use.
//
// Defines whether write operation is blocking or non-blocking.
//
// If zero, default value is used (ClockSourceDefault).
ClockSource ClockSource
// Latency tuner backend.
//
// Defines which latency is monitored and controlled by latency tuner. Defines
// semantics of TargetLatency, MinLatency, and MaxLatency fields.
//
// If zero, default backend is used (LatencyTunerBackendDefault).
LatencyTunerBackend LatencyTunerBackend
// Latency tuner profile.
//
// Defines whether latency tuning is enabled and which algorithm is used.
//
// If zero, default profile is used (LatencyTunerProfileDefault).
//
// By default, latency tuning is disabled on sender. If you enable it on
// sender, you need to disable it on receiver. You also need to set
// TargetLatency to the exact same value on both sides.
LatencyTunerProfile LatencyTunerProfile
// Resampler backend.
//
// Affects CPU usage, quality, and clock synchronization precision (if latency
// tuning is enabled).
//
// If zero, default backend is used (ResamplerBackendDefault).
ResamplerBackend ResamplerBackend
// Resampler profile.
//
// Affects CPU usage and quality.
//
// If zero, default profile is used (ResamplerProfileDefault).
ResamplerProfile ResamplerProfile
// Target latency, in nanoseconds.
//
// How latency is calculated depends on LatencyTunerBackend field.
//
// If latency tuning is enabled on sender (if LatencyTunerProfile is not
// LatencyTunerProfileIntact), sender adjusts its clock to keep actual latency
// as close as possible to the target.
//
// By default, latency tuning is disabled on sender. If you enable it on
// sender, you need to disable it on receiver. You also need to set
// TargetLatency to the exact same value on both sides.
//
// If latency tuning is enabled, TargetLatency should be non-zero.
TargetLatency time.Duration
// Maximum allowed delta between current and target latency, in nanoseconds.
//
// How latency is calculated depends on LatencyTunerBackend field.
//
// If latency tuning is enabled on sender (if LatencyTunerProfile is not
// LatencyTunerProfileIntact), sender monitors current latency, and if it
// differs from TargetLatency more than by LatencyTolerance, sender restarts
// connection to receiver.
//
// By default, latency bounding is disabled on sender. If you enable it on
// sender, you likely want to disable it on receiver.
//
// If zero, default value is used (if latency tuning is enabled on sender).
LatencyTolerance time.Duration
}
Sender configuration. You can zero-initialize this struct to get a default config. See also Sender.
type Slot ¶
type Slot int
Network slot.
A peer (sender or receiver) may have multiple slots, which may be independently bound or connected. You can use multiple slots on sender to connect it to multiple receiver addresses, and you can use multiple slots on receiver to bind it to multiple receiver address.
Slots are numbered from zero and are created implicitly. Just specify slot index when binding or connecting endpoint, and slot will be automatically created if it was not created yet.
In simple cases, just use SlotDefault.
Each slot has its own set of interfaces, dedicated to different kinds of endpoints. See Interface for details.
const ( // Alias for the slot with index zero. SlotDefault Slot = 0 )
type VersionInfo ¶
type VersionInfo struct {
Native SemanticVersion // Version of native library (libroc).
Bindings SemanticVersion // Version of Go bindings.
}
Version components.
func Version ¶
func Version() VersionInfo
Retrieve version numbers. This function can be used to retrieve actual run-time version of the library. It may be different from the compile-time version when using shared library.
func (VersionInfo) Validate ¶
func (vi VersionInfo) Validate() error
Check compatibility of versions of native library (libroc) and Go bindings. If versions are incompatible, then error describing the problem is returned, otherwise returns nil. When Go bindings are used first time, they automatically run this check and panic if it fails. You can run it manually before using bindings.
Source Files
¶
- channel_layout.go
- channel_layout_string.go
- clock_source.go
- clock_source_string.go
- context.go
- context_config.go
- convert.go
- endpoint.go
- errors.go
- fec_encoding.go
- fec_encoding_string.go
- flags_nix.go
- format.go
- format_string.go
- interface.go
- interface_config.go
- interface_string.go
- latency_tuner_backend.go
- latency_tuner_backend_string.go
- latency_tuner_profile.go
- latency_tuner_profile_string.go
- log.go
- loglevel_string.go
- media_encoding.go
- packet_encoding.go
- packet_encoding_string.go
- protocol.go
- protocol_string.go
- receiver.go
- receiver_config.go
- resampler_backend.go
- resampler_backend_string.go
- resampler_profile.go
- resampler_profile_string.go
- sender.go
- sender_config.go
- slot.go
- version.go