You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
242 lines
10 KiB
242 lines
10 KiB
/*****************************************************************************
|
|
* rist.h: RIST (Reliable Internet Stream Transport) helper
|
|
*****************************************************************************
|
|
* Copyright (C) 2020, SipRadius LLC
|
|
*
|
|
* Authors: Sergio Ammirata <sergio@ammirata.net>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2.1 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
|
*****************************************************************************/
|
|
|
|
#ifndef RIST_VLC_COMMON_H
|
|
#define RIST_VLC_COMMON_H 1
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <vlc_common.h>
|
|
#include <librist/librist.h>
|
|
|
|
/* RIST max fifo count (private RIST_DATAOUT_QUEUE_BUFFERS in librist) */
|
|
#define RIST_MAX_QUEUE_BUFFERS (1024)
|
|
|
|
/* RIST parameter names */
|
|
#define RIST_CFG_MAX_PACKET_SIZE "packet-size"
|
|
#define RIST_CFG_URL2 "peer-url2"
|
|
#define RIST_CFG_URL3 "peer-url3"
|
|
#define RIST_CFG_URL4 "peer-url4"
|
|
#define RIST_CFG_RETRY_INTERVAL "retry-interval"
|
|
#define RIST_CFG_MAX_RETRIES "max-retries"
|
|
#define RIST_CFG_LATENCY "latency"
|
|
|
|
static const char *rist_log_label[9] = {"DISABLED", "", "", "ERROR", "WARN", "", "INFO", "DEBUG", "SIMULATE"};
|
|
|
|
/* RIST parameter descriptions */
|
|
#define RIST_URL2_TEXT N_("Second peer URL")
|
|
#define RIST_URL3_TEXT N_("Third peer URL")
|
|
#define RIST_URL4_TEXT N_("Fourth peer URL")
|
|
#define RIST_MAX_BITRATE_TEXT N_("Max bitrate in Kbps")
|
|
#define RIST_MAX_BITRATE_LONGTEXT N_( \
|
|
"Use this value to guarantee that data+retries bitrate never exceeds your pipe size. " \
|
|
"Default value is 100000 Kbps (100 Mbps)" )
|
|
#define RIST_RETRY_INTERVAL_TEXT N_("RIST nack minimum retry interval (ms)")
|
|
#define RIST_REORDER_BUFFER_TEXT N_("RIST reorder buffer size (ms)")
|
|
#define RIST_MAX_RETRIES_TEXT N_("RIST maximum retry count")
|
|
#define BUFFER_TEXT N_("RIST retry-buffer queue size (ms)")
|
|
#define BUFFER_LONGTEXT N_( \
|
|
"This must match the buffer size (latency) configured on the other side. If you " \
|
|
"are not sure, leave it blank and it will use 1000ms" )
|
|
#define RIST_SHARED_SECRET_TEXT N_("Shared Secret")
|
|
#define RIST_SHARED_SECRET_LONGTEXT N_( \
|
|
"This shared secret is a passphare shared between sender and receiver. The AES key " \
|
|
"is derived from it" )
|
|
#define RIST_CNAME_TEXT N_("Peer cname")
|
|
#define RIST_CNAME_LONGTEXT N_( \
|
|
"This name will be sent using the rist RTCP channel and uniquely identifies us" )
|
|
#define RIST_PACKET_SIZE_TEXT N_("RIST maximum packet size (bytes)")
|
|
#define RIST_SRP_USERNAME_TEXT N_("Username used for stream authentication")
|
|
#define RIST_SRP_PASSWORD_TEXT N_("Password used for stream authentication")
|
|
/* Profile selection */
|
|
#define RIST_PROFILE_TEXT N_("Rist Profile")
|
|
#define RIST_PROFILE_LONGTEXT N_( "Select the rist profile to use" )
|
|
static const int rist_profile[] = { 0, 1, 2 };
|
|
static const char *const rist_profile_names[] = {
|
|
N_("Simple Profile"), N_("Main Profile"), N_("Advanced Profile"),
|
|
};
|
|
/* Encryption type */
|
|
#define RIST_ENCRYPTION_TYPE_TEXT N_("Encryption type")
|
|
#define RIST_DEFAULT_ENCRYPTION_TPE 128
|
|
static const int rist_encryption_type[] = { 0, 128, 256, };
|
|
static const char *const rist_encryption_type_names[] = {
|
|
N_("Disabled"), N_("AES 128 bits"), N_("AES 256 bits"),
|
|
};
|
|
/* Timing Mode */
|
|
#define RIST_TIMING_MODE_TEXT N_("Timing mode")
|
|
static const int rist_timing_mode_type[] = { 0, 1, 2, };
|
|
static const char *const rist_timing_mode_names[] = {
|
|
N_("Use Source Time"), N_("Use Arrival Time"), N_("Use RTC"),
|
|
};
|
|
/* Verbose level */
|
|
#define RIST_VERBOSE_LEVEL_TEXT N_("Verbose level")
|
|
#define RIST_VERBOSE_LEVEL_LONGTEXT N_("This controls how much log data the library will output over stderr")
|
|
static const int verbose_level_type[] = { RIST_LOG_DISABLE, RIST_LOG_ERROR, RIST_LOG_WARN, RIST_LOG_INFO, RIST_LOG_DEBUG, RIST_LOG_SIMULATE };
|
|
static const char *const verbose_level_type_names[] = {
|
|
N_("Quiet"), N_("Errors"), N_("Warnings"), N_("Info"), N_("Debug"), N_("Simulate-Loss"),
|
|
};
|
|
|
|
/* Max number of peers */
|
|
// This will restrict the use of the library to the configured maximum packet size
|
|
#define RIST_MAX_PACKET_SIZE (10000)
|
|
|
|
#define RIST_MAX_LOG_BUFFER 512
|
|
|
|
|
|
static inline int log_cb(void *arg, enum rist_log_level log_level, const char *msg)
|
|
{
|
|
vlc_object_t *p_access = (vlc_object_t *)arg;
|
|
int label_index = 0;
|
|
if (log_level > 8)
|
|
label_index = 8;
|
|
else if (log_level > 0)
|
|
label_index = log_level;
|
|
|
|
if (log_level == RIST_LOG_ERROR)
|
|
msg_Err(p_access, "[RIST-%s]: %.*s", rist_log_label[label_index], (int)strlen(msg) - 1, msg);
|
|
else if (log_level == RIST_LOG_WARN)
|
|
msg_Warn(p_access, "[RIST-%s]: %.*s", rist_log_label[label_index], (int)strlen(msg) - 1, msg);
|
|
else if (log_level == RIST_LOG_INFO)
|
|
//libRIST follows Syslog log priorities and assigns INFO a low prio, VLC gives Info the highest
|
|
//so make it warn (debug would be too verbose)
|
|
msg_Warn(p_access, "[RIST-%s]: %.*s", rist_log_label[label_index], (int)strlen(msg) - 1, msg);
|
|
else if (log_level > RIST_LOG_DEBUG)
|
|
msg_Dbg(p_access, "[RIST-%s]: %.*s", rist_log_label[label_index], (int)strlen(msg) - 1, msg);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline int rist_get_max_packet_size(vlc_object_t *p_this)
|
|
{
|
|
int i_max_packet_size = var_InheritInteger( p_this, RIST_CFG_PREFIX RIST_CFG_MAX_PACKET_SIZE );
|
|
if (i_max_packet_size > RIST_MAX_PACKET_SIZE)
|
|
{
|
|
msg_Err(p_this, "The maximum packet size configured is bigger than what the library allows %d > %d, using %d instead",
|
|
i_max_packet_size, RIST_MAX_PACKET_SIZE, RIST_MAX_PACKET_SIZE);
|
|
i_max_packet_size = RIST_MAX_PACKET_SIZE;
|
|
}
|
|
return i_max_packet_size;
|
|
}
|
|
|
|
static inline bool rist_add_peers(vlc_object_t *p_this, struct rist_ctx *ctx, char *psz_url, int i_multipeer_mode, int virt_dst_port, int i_recovery_length)
|
|
{
|
|
|
|
|
|
int i_rist_reorder_buffer = var_InheritInteger( p_this, RIST_CFG_PREFIX RIST_URL_PARAM_REORDER_BUFFER );
|
|
int i_rist_retry_interval = var_InheritInteger( p_this, RIST_CFG_PREFIX RIST_CFG_RETRY_INTERVAL );
|
|
int i_rist_max_retries = var_InheritInteger( p_this, RIST_CFG_PREFIX RIST_CFG_MAX_RETRIES );
|
|
int i_rist_max_bitrate = var_InheritInteger(p_this, RIST_CFG_PREFIX RIST_URL_PARAM_BANDWIDTH);
|
|
|
|
char *psz_stream_name = NULL;
|
|
psz_stream_name = var_InheritString( p_this, RIST_CFG_PREFIX RIST_URL_PARAM_CNAME );
|
|
|
|
char *psz_shared_secret = NULL;
|
|
psz_shared_secret = var_InheritString( p_this, RIST_CFG_PREFIX RIST_URL_PARAM_SECRET );
|
|
|
|
int i_key_size = var_InheritInteger(p_this, RIST_CFG_PREFIX RIST_URL_PARAM_AES_TYPE);
|
|
|
|
char *psz_srp_username = NULL;
|
|
psz_srp_username = var_InheritString( p_this, RIST_CFG_PREFIX RIST_URL_PARAM_SRP_USERNAME );
|
|
char *psz_srp_password = NULL;
|
|
psz_srp_password = var_InheritString( p_this, RIST_CFG_PREFIX RIST_URL_PARAM_SRP_PASSWORD );
|
|
|
|
int recovery_mode = RIST_RECOVERY_MODE_TIME;
|
|
|
|
msg_Info( p_this, "Setting retry buffer to %d ms", i_recovery_length );
|
|
|
|
char *addr[] = {
|
|
strdup(psz_url),
|
|
var_InheritString( p_this, RIST_CFG_PREFIX RIST_CFG_URL2 ),
|
|
var_InheritString( p_this, RIST_CFG_PREFIX RIST_CFG_URL3 ),
|
|
var_InheritString( p_this, RIST_CFG_PREFIX RIST_CFG_URL4 )
|
|
};
|
|
|
|
bool b_peer_alive = false;
|
|
for (size_t i = 0; i < ARRAY_SIZE(addr); i++) {
|
|
if (addr[i] == NULL) {
|
|
continue;
|
|
}
|
|
else if (addr[i][0] == '\0') {
|
|
free(addr[i]);
|
|
continue;
|
|
}
|
|
|
|
struct rist_peer_config app_peer_config = {
|
|
.version = RIST_PEER_CONFIG_VERSION,
|
|
.virt_dst_port = virt_dst_port,
|
|
.recovery_mode = recovery_mode,
|
|
.recovery_maxbitrate = (uint32_t)i_rist_max_bitrate,
|
|
.recovery_maxbitrate_return = 0,
|
|
.recovery_length_min = (uint32_t)i_recovery_length,
|
|
.recovery_length_max = (uint32_t)i_recovery_length,
|
|
.recovery_reorder_buffer = (uint32_t)i_rist_reorder_buffer,
|
|
.recovery_rtt_min = (uint32_t)i_rist_retry_interval,
|
|
.recovery_rtt_max = (uint32_t)10*i_rist_retry_interval,
|
|
.weight = (uint32_t)i_multipeer_mode,
|
|
.congestion_control_mode = RIST_CONGESTION_CONTROL_MODE_NORMAL,
|
|
.min_retries = 6,
|
|
.max_retries = (uint32_t)i_rist_max_retries,
|
|
.key_size = i_key_size
|
|
};
|
|
|
|
if (psz_shared_secret != NULL && psz_shared_secret[0] != '\0') {
|
|
strlcpy(app_peer_config.secret, psz_shared_secret, sizeof(app_peer_config.secret));
|
|
}
|
|
|
|
if ( psz_stream_name != NULL && psz_stream_name[0] != '\0') {
|
|
strlcpy(app_peer_config.cname, psz_stream_name, sizeof(app_peer_config.cname));
|
|
}
|
|
|
|
// URL overrides (also cleans up the URL)
|
|
struct rist_peer_config *peer_config = &app_peer_config;
|
|
if (rist_parse_address2(addr[i], &peer_config))
|
|
{
|
|
msg_Err( p_this, "Could not parse peer options for sender #%d\n", (int)(i + 1));
|
|
free(addr[i]);
|
|
continue;
|
|
}
|
|
|
|
struct rist_peer *peer;
|
|
if (rist_peer_create(ctx, &peer, peer_config)) {
|
|
msg_Err( p_this, "Could not init rist sender #%i at %s",(int)(i + 1), addr[i] );
|
|
free(addr[i]);
|
|
continue;
|
|
}
|
|
else {
|
|
b_peer_alive = true;
|
|
}
|
|
free(addr[i]);
|
|
}
|
|
|
|
free(psz_shared_secret);
|
|
free(psz_stream_name);
|
|
free(psz_srp_username);
|
|
free(psz_srp_password);
|
|
|
|
return b_peer_alive;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|