roc

package module
v0.0.0-...-6e5d59c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2023 License: MIT Imports: 12 Imported by: 0

Documentation

Index

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 ChannelSet

type ChannelSet int

Channel set.

const (
	// Stereo.
	//
	// Two channels: left and right.
	ChannelSetStereo ChannelSet = 0x3
)

func (ChannelSet) String

func (i ChannelSet) String() string

type ClockSource

type ClockSource int

Clock source for sender or receiver.

const (
	// 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.
	ClockExternal ClockSource = 0

	// Sender or receiver is clocked by an internal 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.
	ClockInternal ClockSource = 1
)

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.

The user is responsible for closing any opened context before exiting the program.

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. User is responsible to call Context.Close to free context resources.

func (*Context) Close

func (c *Context) Close() (err error)

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.

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

func ParseEndpoint(uri string) (*Endpoint, error)

ParseEndpoint decomposes URI string into Endpoint instance.

func (*Endpoint) URI

func (endp *Endpoint) URI() (string, error)

URI composes Endpoint instance into URI string.

type FecEncoding

type FecEncoding int

Forward Error Correction encoding.

const (
	// No FEC encoding.
	//
	// Compatible with ProtoRtp protocol.
	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.
	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.
	FecEncodingLdpcStaircase FecEncoding = 2
)

func (FecEncoding) String

func (i FecEncoding) String() string

type FrameEncoding

type FrameEncoding int

Frame encoding.

const (
	// 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...".
	FrameEncodingPcmFloat FrameEncoding = 1
)

func (FrameEncoding) String

func (i FrameEncoding) String() string

type Interface

type Interface int

Network interface.

Interface is a way to access the peer (sender or receiver) via network.

Each peer slot has multiple interfaces, one of each type. The user interconnects peers by binding one of the first peer's interfaces to an URI and then connecting the corresponding second peer's interface 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 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
)

func (Interface) String

func (i Interface) 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
)

func (LogLevel) String

func (i LogLevel) String() string

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 PacketEncoding

type PacketEncoding int

Packet encoding.

const (
	// 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.
	PacketEncodingAvpL16 PacketEncoding = 2
)

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:
	//  - PacketEncodingAvpL16
	//
	// 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
)

func (Protocol) String

func (i Protocol) String() string

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.Set*() functions.

  • 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.Read*(). Receiver returns the mixed stream from all connected senders.

- The receiver is destroyed using Receiver.Close().

The user is responsible for closing any opened receiver before exiting the program.

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 type. 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).

FEC scheme

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.

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.

Sample rate

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.

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 (ClockInternal), 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 (ClockExternal), 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

func (r *Receiver) Bind(slot Slot, iface Interface, endpoint *Endpoint) (err error)

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 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

func (r *Receiver) Close() (err error)

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) ReadFloats

func (r *Receiver) ReadFloats(frame []float32) (err error)

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 ClockInternal 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.

func (*Receiver) SetMulticastGroup

func (r *Receiver) SetMulticastGroup(slot Slot, iface Interface, ip string) (err error)

Set receiver interface multicast group.

Optional.

Multicast group should be set only when binding receiver 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 possible 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 call this function, or join multicast group manually using OS-specific API.

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.

Each slot's interface can have only one multicast group. The function should be called before calling roc_receiver_bind() for the interface. It should not be called when calling Receiver.Connect() for the interface.

Automatically initializes slot with given index if it's used first time.

func (*Receiver) SetReuseaddr

func (r *Receiver) SetReuseaddr(slot Slot, iface Interface, enabled bool) (err error)

Set receiver interface address reuse option.

Optional.

When set to true, SO_REUSEADDR is enabled for interface socket, regardless of socket type, unless binding to ephemeral port (port explicitly set to zero).

When set to false, SO_REUSEADDR is enabled only for multicast sockets, unless binding to ephemeral port (port explicitly set to zero).

By default set to false.

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.

Automatically initializes slot with given index if it's used first time.

type ReceiverConfig

type ReceiverConfig struct {
	// The rate of the samples in the frames returned to the user.
	// Number of samples per channel per second.
	// Should be set.
	FrameSampleRate uint32

	// The channel set in the frames returned to the user.
	// Should be set.
	FrameChannels ChannelSet

	// The sample encoding in the frames returned to the user.
	// Should be set.
	FrameEncoding FrameEncoding

	// Clock source to use.
	// Defines whether read operation will be blocking or non-blocking.
	// If zero, default value is used.
	ClockSource ClockSource

	// Resampler backend to use.
	ResamplerBackend ResamplerBackend

	// 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
	ResamplerProfile ResamplerProfile

	// 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 possible to the target latency.
	// If zero, default value is used. Should not be negative, otherwise an error is returned.
	TargetLatency time.Duration

	// 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. Should not be negative, otherwise an error is returned.
	MaxLatencyOverrun time.Duration

	// 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.  Should not be negative, otherwise an error is returned.
	MaxLatencyUnderrun time.Duration

	// 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.
	NoPlaybackTimeout time.Duration

	// 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
	// BreakageDetectionWindow during BrokenPlaybackTimeout.
	// 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.
	BrokenPlaybackTimeout time.Duration

	// Breakage detection window, in nanoseconds.
	// If zero, default value is used. Should not be negative, otherwise an error is returned.
	// See BrokenPlaybackTimeout.
	BreakageDetectionWindow 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 speed and quality. Some backends may be disabled at build time.

const (
	// Default backend.
	//
	// Depends on what was enabled at build time.
	ResamplerBackendDefault ResamplerBackend = 0

	// Slow built-in resampler.
	//
	// Always available.
	ResamplerBackendBuiltin ResamplerBackend = 1

	// Fast good-quality resampler from SpeexDSP.
	//
	// May be disabled at build time.
	ResamplerBackendSpeex ResamplerBackend = 2
)

func (ResamplerBackend) String

func (i ResamplerBackend) String() string

type ResamplerProfile

type ResamplerProfile int

Resampler profile.

Affects speed and quality. Each resampler backend treats profile in its own way.

const (
	// Do not perform resampling.
	//
	// Clock drift compensation will be disabled in this case. If in doubt, do not
	// disable resampling.
	ResamplerProfileDisable ResamplerProfile = -1

	// Default profile.
	//
	// Current default is ResamplerProfileMedium.
	ResamplerProfileDefault ResamplerProfile = 0

	// High quality, low speed.
	ResamplerProfileHigh ResamplerProfile = 1

	// Medium quality, medium speed.
	ResamplerProfileMedium ResamplerProfile = 2

	// Low quality, high speed.
	ResamplerProfileLow ResamplerProfile = 3
)

func (ResamplerProfile) String

func (i ResamplerProfile) String() string

type SemanticVersion

type SemanticVersion struct {
	Major uint64
	Minor uint64
	Patch uint64
}

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.Set(). functions.

  • 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.Write*(). The sender encodes the stream into packets and send to connected receiver(s).

- The sender is destroyed using Sender.Close().

The user is responsible for closing any opened sender before exiting the program.

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 type. 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).

FEC scheme

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.

Sample rate

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.

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 (ClockInternal), 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 (ClockExternal), 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

func (s *Sender) Close() (err error)

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) Connect

func (s *Sender) Connect(slot Slot, iface Interface, endpoint *Endpoint) (err error)

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.

func (*Sender) SetOutgoingAddress

func (s *Sender) SetOutgoingAddress(slot Slot, iface Interface, ip string) (err error)

Set sender interface outgoing address.

Optional. Should be used only when connecting an interface to a remote endpoint.

If set, explicitly defines the IP address of the OS network interface from which to send the outgoing packets. If not set, the outgoing interface is selected automatically by the OS, depending on the remote endpoint address.

It is allowed to set outgoing address to `0.0.0.0` (for IPv4) or to `::` (for IPv6), to achieve the same behavior as if it wasn't set, i.e. to let the OS to select the outgoing interface automatically.

By default, the outgoing address is not set.

Each slot's interface can have only one outgoing address. The function should be called before calling Sender.Connect() for this slot and interface. It should not be called when calling Sender.Bind() for the interface.

Automatically initializes slot with given index if it's used first time.

func (*Sender) SetReuseaddr

func (s *Sender) SetReuseaddr(slot Slot, iface Interface, enabled bool) (err error)

Set sender interface address reuse option.

Optional.

When set to true, SO_REUSEADDR is enabled for interface socket, regardless of socket type, unless binding to ephemeral port (port explicitly set to zero).

When set to false, SO_REUSEADDR is enabled only for multicast sockets, unless binding to ephemeral port (port explicitly set to zero).

By default set to false.

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.

Automatically initializes slot with given index if it's used first time.

func (*Sender) WriteFloats

func (s *Sender) WriteFloats(frame []float32) (err error)

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 ClockInternal 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 rate of the samples in the frames passed to sender.
	// Number of samples per channel per second.
	// If FrameSampleRate and PacketSampleRate are different,
	// resampler should be enabled.
	// Should be set.
	FrameSampleRate uint32

	// The channel set in the frames passed to sender.
	// Should be set.
	FrameChannels ChannelSet

	// The sample encoding in the frames passed to sender.
	// Should be set.
	FrameEncoding FrameEncoding

	// The rate of the samples in the packets generated by sender.
	// Number of samples per channel per second.
	// If zero, default value is used.
	PacketSampleRate uint32

	// The channel set in the packets generated by sender.
	// If zero, default value is used.
	PacketChannels ChannelSet

	// The sample encoding in the packets generated by sender.
	// If zero, default value is used.
	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 increases latency.
	// If zero, default value is used. Should not be negative, otherwise an error is returned.
	PacketLength time.Duration

	// Enable packet interleaving.
	// If true, the sender shuffles packets before sending them. This
	// may increase robustness but also increases latency.
	PacketInterleaving bool

	// Clock source to use.
	// Defines whether write operation will be blocking or non-blocking.
	// If zero, default value is used.
	ClockSource ClockSource

	// Resampler backend to use.
	ResamplerBackend ResamplerBackend

	// Resampler profile to use.
	// If non-zero, the sender employs resampler if the frame sample rate differs
	// from the packet sample rate.
	ResamplerProfile ResamplerProfile

	// FEC encoding 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.
	FecEncoding FecEncoding

	// 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.
	FecBlockSourcePackets uint32

	// 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.
	FecBlockRepairPackets uint32
}

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL