|
|
The actual number of calls to libRIST are relatively few in number. You may find that much of your effort consists in getting and setting the configuration, optionally initiating a tunnel, moving the packets, and handling the reporting of all the above via callbacks. In addition to definitions, we have emphasized the usage via examples from the ristsender and ristreceiver "example" applications. In fact, we use them as production code behind a GUI providing configuration options and some fancy scripting to parameterize what may sometimes be complicated configurations. We encourage you to make the most of ristsender and ristreceiver, whether for study in preparation for writing your own libRIST utilities, or to modify them further for your production purposes.
|
|
|
|
|
|
**Receiver Only**
|
|
|
|
|
|
##### int rist_receiver_create(struct rist_ctx **ctx, enum rist_profile profile, struct rist_logging_settings *logging_settings);
|
|
|
|
|
|
Parameters:
|
|
|
- [out] ctx a context representing the receiver instance
|
|
|
- profile RIST profile
|
|
|
- logging_settings Optional struct containing the logging settings.
|
|
|
|
|
|
Returns: 0 on success,-1 on error
|
|
|
|
|
|
Notes: Create a RIST receiver instance.
|
|
|
|
|
|
Example: The code below (from ristreceiver.c) allocates a rist context structure and pointer to it, then calls the function with a reference to the pointer.
|
|
|
|
|
|
```
|
|
|
static struct rist_logging_settings *logging_settings;
|
|
|
...
|
|
|
enum rist_profile profile = RIST_PROFILE_MAIN;
|
|
|
...
|
|
|
struct rist_ctx *ctx;
|
|
|
if (rist_receiver_create(&ctx, profile, logging_settings) != 0) {
|
|
|
rist_log(logging_settings, RIST_LOG_ERROR, "Could not create rist receiver context\n");
|
|
|
exit(1);
|
|
|
}
|
|
|
```
|
|
|
___
|
|
|
##### int rist_receiver_nack_type_set(struct rist_ctx *ctx, enum rist_nack_type nacks_type);
|
|
|
|
|
|
Parameters:
|
|
|
- ctx RIST receiver context
|
|
|
- nack_type 0 for range (default), 1 for bitmask
|
|
|
|
|
|
Returns: 0 on success, -1 on error
|
|
|
|
|
|
Notes: Choose the nack type used by the receiver.
|
|
|
___
|
|
|
##### int rist_receiver_nack_type_set(struct rist_ctx *ctx, enum rist_nack_type nacks_type);
|
|
|
|
|
|
Parameters:
|
|
|
- ctx RIST receiver context
|
|
|
- [out] data_block a pointer to the rist_data_block structure
|
|
|
- timeout How long to wait for queue data (ms), 0 for no wait
|
|
|
|
|
|
Returns: num buffers remaining on queue +1 (0 if no buffer returned), -1 on error
|
|
|
|
|
|
Notes: Reads rist datal use this to read data from an internal fifo queue instead of the callback
|
|
|
|
|
|
Example: The code below (from ristreceiver.c) calls rist_receiver_data_read with the receiver context, a pointer to a rist data block structure, and the timeout. In the snippet, it only checks the size of the queue and logs an error, if any
|
|
|
|
|
|
```
|
|
|
// Master loop
|
|
|
while (!signalReceived)
|
|
|
{
|
|
|
const struct rist_data_block *b;
|
|
|
int queue_size = rist_receiver_data_read(ctx, &b, 5);
|
|
|
if (queue_size && queue_size % 10 == 0)
|
|
|
rist_log(logging_settings, RIST_LOG_WARN, "Falling behind on rist_receiver_data_read: %d\n", queue_size);
|
|
|
...
|
|
|
}
|
|
|
```
|
|
|
___
|
|
|
##### int rist_receiver_data_read(struct rist_ctx *ctx, const struct rist_data_block **data_block, int timeout);
|
|
|
|
|
|
Parameters:
|
|
|
- ctx RIST receiver context
|
|
|
- [out] data_block a pointer to the rist_data_block structure
|
|
|
- timeout How long to wait for queue data (ms), 0 for no wait
|
|
|
|
|
|
Returns: num buffers remaining on queue +1 (0 if no buffer returned), -1 on error
|
|
|
|
|
|
Notes: Reads rist datal use this to read data from an internal fifo queue instead of the callback
|
|
|
|
|
|
Example: The code below (from ristreceiver.c) calls rist_receiver_data_read with the receiver context, a pointer to a rist data block structure, and the timeout. In the snippet, it only checks the size of the queue and logs an error, if any
|
|
|
|
|
|
```
|
|
|
// Master loop
|
|
|
while (!signalReceived)
|
|
|
{
|
|
|
const struct rist_data_block *b;
|
|
|
int queue_size = rist_receiver_data_read(ctx, &b, 5);
|
|
|
if (queue_size && queue_size % 10 == 0)
|
|
|
rist_log(logging_settings, RIST_LOG_WARN, "Falling behind on rist_receiver_data_read: %d\n", queue_size);
|
|
|
...
|
|
|
}
|
|
|
```
|
|
|
___
|
|
|
##### int rist_receiver_data_callback_set(struct rist_ctx *ctx, int (*data_callback)(void *arg, const struct rist_data_block *data_block), void *arg);
|
|
|
|
|
|
Parameters:
|
|
|
- ctx RIST receiver context
|
|
|
- data_callback The function that will be called when a data frame is - received from a sender.
|
|
|
- arg the extra argument passed to the "data_callback"
|
|
|
|
|
|
Returns: return 0 on success, -1 on error
|
|
|
|
|
|
Notes: Enable data callback channel; call to enable data callback channel.
|
|
|
|
|
|
Example: The code below (from ristreceiver.c) shows the process of setting up the callback and testing its validity.
|
|
|
|
|
|
```
|
|
|
struct rist_callback_object {
|
|
|
int mpeg[MAX_OUTPUT_COUNT];
|
|
|
uint16_t virt_src_port[MAX_OUTPUT_COUNT];
|
|
|
};
|
|
|
...
|
|
|
struct rist_callback_object callback_object;
|
|
|
...
|
|
|
|
|
|
if (enable_data_callback == 1) {
|
|
|
if (rist_receiver_data_callback_set(ctx, cb_recv, &callback_object))
|
|
|
{
|
|
|
rist_log(logging_settings, RIST_LOG_ERROR, "Could not set data_callback pointer");
|
|
|
exit(1);
|
|
|
}
|
|
|
```
|
|
|
___
|
|
|
|
|
|
**Sender Only**
|
|
|
___
|
|
|
|
|
|
##### int rist_sender_create(struct rist_ctx **ctx, enum rist_profile profile, uint32_t flow_id, struct rist_logging_settings *logging_settings);
|
|
|
|
|
|
Parameters:
|
|
|
- [out] ctx a context representing the sender instance
|
|
|
- profile RIST profile
|
|
|
- flow_id Flow ID use 0 to delegate creation of flow_id to lib
|
|
|
- logging_settings Struct containing logging settings
|
|
|
|
|
|
Returns: return 0 on success, -1 in case of error.
|
|
|
|
|
|
Notes: Create a RIST sender instance
|
|
|
|
|
|
Example: The code below (from ristsender.c) shows the sender being created, after having declared the context structure, logging options and the configuration profile.
|
|
|
|
|
|
```
|
|
|
static struct rist_logging_settings *logging_settings;
|
|
|
...
|
|
|
struct rist_ctx *ctx;
|
|
|
...
|
|
|
enum rist_profile profile = RIST_PROFILE_MAIN;
|
|
|
...
|
|
|
|
|
|
if (rist_sender_create(&ctx, profile, 0, logging_settings) != 0) {
|
|
|
rist_log(logging_settings, RIST_LOG_ERROR, "Could not create rist sender context\n");
|
|
|
exit(1);
|
|
|
}
|
|
|
```
|
|
|
___
|
|
|
##### int rist_sender_flow_id_get(struct rist_ctx *ctx, uint32_t *flow_id);
|
|
|
|
|
|
Parameters:
|
|
|
- ctx RIST sender context
|
|
|
- flow_id pointer to your flow_id variable
|
|
|
|
|
|
Returns: return 0 on success, -1 on error
|
|
|
|
|
|
Notes: Retrieve the current flow_id value
|
|
|
___
|
|
|
##### int rist_sender_flow_id_set(struct rist_ctx *ctx, uint32_t flow_id);
|
|
|
|
|
|
Parameters:
|
|
|
- ctx RIST sender context
|
|
|
- flow_id new flow_id
|
|
|
|
|
|
Returns: return 0 on success, -1 on error
|
|
|
|
|
|
Notes: Change the flow_id value
|
|
|
___
|
|
|
##### int rist_sender_data_write(struct rist_ctx *ctx, const struct rist_data_block *data_block);
|
|
|
|
|
|
Parameters:
|
|
|
- ctx RIST sender context
|
|
|
- data_block pointer to the rist_data_block structure; ts_ntp will be populated by the lib if a value of 0 is passed
|
|
|
|
|
|
Returns: return number of written bytes on success, -1 in case of error.
|
|
|
|
|
|
Notes: Write data into a librist packet. One sender can send write data into a librist packet.
|
|
|
|
|
|
Example: The code below (from ristsender.c) shows the callback object and the data block being declared, then writing to the data block, which in this case is the packet payload.
|
|
|
|
|
|
```
|
|
|
struct rist_callback_object *callback_object = (void *) arg;
|
|
|
...
|
|
|
struct rist_data_block data_block;
|
|
|
...
|
|
|
int w = rist_sender_data_write(callback_object->ctx, &data_block);
|
|
|
```
|
|
|
___
|
|
|
**OOB Specific functions**
|
|
|
|
|
|
**Send and receive IP traffic inband in RIST Main Profile**
|
|
|
|
|
|
##### int rist_oob_write(struct rist_ctx *ctx, const struct rist_oob_block *oob_block);
|
|
|
|
|
|
Parameters:
|
|
|
- ctx RIST context
|
|
|
- oob_block a pointer to the struct rist_oob_block
|
|
|
|
|
|
Returns: number of written bytes on success, -1 in case of error.
|
|
|
|
|
|
Notes: Write data directly to a remote receiver peer; this API is used to transmit out-of-band data to a remote receiver peer
|
|
|
|
|
|
Example: The code below (from ristsender.c) shows part of the authorization exchange. In this case the sender creates a message for the receiver and sends it. It is distinct from the normal rtcp messages such as data regarding packets sent or re-requested, and is therefore considered out-of-band.
|
|
|
|
|
|
```
|
|
|
static int cb_auth_connect(void *arg, const char* connecting_ip, uint16_t connecting_port, const char* local_ip, uint16_t local_port, struct rist_peer *peer)
|
|
|
{
|
|
|
struct rist_ctx *ctx = (struct rist_ctx *)arg;
|
|
|
char message[500];
|
|
|
int ret = snprintf(message, 500, "auth,%s:%d,%s:%d", connecting_ip, connecting_port, local_ip, local_port);
|
|
|
rist_log(logging_settings, RIST_LOG_INFO,"Peer has been authenticated, sending auth message: %s\n", message);
|
|
|
struct rist_oob_block oob_block;
|
|
|
oob_block.peer = peer;
|
|
|
oob_block.payload = message;
|
|
|
oob_block.payload_len = ret;
|
|
|
rist_oob_write(ctx, &oob_block);
|
|
|
return 0;
|
|
|
}
|
|
|
```
|
|
|
___ |