public class RocSender
extends java.lang.Object
Sender gets an audio stream from the user, encodes it into network packets, and transmits them to a remote receiver.
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.
RocSender().setOutgoingAddress(Slot, Interface, String) function.bind(),
allowing receivers connecting to them, or itself connects to remote receiver endpoints
using connect(). What approach to use is up to the user.write().
The sender encodes the stream into packets and send to connected receiver(s).close().
RocSender class implements AutoCloseable so if it is used in a
try-with-resources statement the object is closed automatically at the end of the statement.
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 Slot.DEFAULT.
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:
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.connect(Slot, Interface, Endpoint) 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:
Interface.CONSOLIDATED to a remote endpoint (e.g. be an RTSP client).Interface.CONSOLIDATED to a local endpoint (e.g. be an RTSP server).Interface.AUDIO_SOURCE, Interface.AUDIO_REPAIR (optionally, for FEC),
and Interface.AUDIO_CONTROL (optionally, for control messages) to remote endpoints
(e.g. be an RTP/FECFRAME/RTCP sender).
If Interface.CONSOLIDATED is used, it automatically creates all necessary
transport interfaces and the user should not bother about them.
Otherwise, the user should manually configure Interface.AUDIO_SOURCE and
Interface.AUDIO_REPAIR interfaces:
FecEncoding.DISABLE, only Interface.AUDIO_SOURCE
should be configured. It will be used to transmit audio packets.Interface.AUDIO_SOURCE and Interface.AUDIO_REPAIR
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 FecEncoding.RS8M is used, the protocols should be
Protocol.RTP_RS8M_SOURCE and Protocol.RS8M_REPAIR.
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.
Sender should encode samples at a constant rate that is configured when the sender is created. There are two ways to accomplish this:
ClockSource.INTERNAL, 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.
ClockSource.EXTERNAL, 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.
Can be used concurrently
RocSenderConfig config = RocSenderConfig.builder()
.frameSampleRate(SAMPLE_RATE)
.frameChannels(ChannelSet.STEREO)
.frameEncoding(FrameEncoding.PCM_FLOAT)
.resamplerProfile(ResamplerProfile.DISABLE)
.fecEncoding(FecEncoding.RS8M)
.build();
try (
RocContext context = new RocContext();
RocSender sender = new RocSender(context, config);
) {
sender.connect(Slot.DEFAULT, Interface.AUDIO_SOURCE, new Endpoint("rtp+rs8m://0.0.0.0:10001"));
sender.connect(Slot.DEFAULT, Interface.AUDIO_REPAIR, new Endpoint("rs8m://0.0.0.0:10002"));
float[] samples = new float[] {2.0f, -2.0f};
sender.write(samples);
}
RocContext,
RocSenderConfig,
AutoCloseable| Constructor and Description |
|---|
RocSender(RocContext context,
RocSenderConfig config)
Open a new sender.
|
| Modifier and Type | Method and Description |
|---|---|
void |
bind(Endpoint endpoint) |
void |
close()
Close the native object and unregister it from the
NativeObjectCleaner. |
void |
connect(Slot slot,
Interface iface,
Endpoint endpoint)
Connect the sender interface to a remote receiver endpoint.
|
void |
setOutgoingAddress(Slot slot,
Interface iface,
java.lang.String ip)
Set sender interface outgoing address.
|
void |
write(float[] samples)
Encode samples to packets and transmit them to the receiver.
|
public RocSender(RocContext context, RocSenderConfig config) throws java.lang.IllegalArgumentException, java.lang.Exception
context - should point to an opened context.config - should point to an initialized config.java.lang.IllegalArgumentException - if the arguments are invalid.java.lang.Exception - if an error occurred when creating the sender.public void setOutgoingAddress(Slot slot, Interface iface, java.lang.String ip) throws java.lang.Exception
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 connect() for this slot and interface. It should not be
called when calling bind() for the interface.
Automatically initializes slot with given index if it's used first time.
**Parameters**
slot - specifies the sender slotiface - specifies the sender interfaceip - should be IPv4 or IPv6 addressjava.lang.Exception - if an error occurredpublic void bind(Endpoint endpoint) throws java.lang.IllegalArgumentException, java.io.IOException
java.lang.IllegalArgumentExceptionjava.io.IOExceptionpublic void connect(Slot slot, Interface iface, Endpoint endpoint) throws java.lang.IllegalArgumentException, java.io.IOException
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.
slot - slot specifies the sender slotiface - iface specifies the sender interfaceendpoint - endpoint specifies the receiver endpointjava.lang.IllegalArgumentException - if the arguments are invalid.java.io.IOException - if was error during connectpublic void write(float[] samples)
throws java.lang.IllegalArgumentException,
java.io.IOException
Encodes samples to packets and enqueues them for transmission by the network worker thread of the context.
If ClockSource.INTERNAL 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.
samples - array of samples to send.java.lang.IllegalArgumentException - if the arguments are invalid.java.io.IOException - if the sender if there are not enough resources.public void close()
throws java.lang.Exception
NativeObjectCleaner.close in interface java.lang.AutoCloseablejava.lang.Exception - if the underlying roc native object cannot be closed.