<html><head></head><body bgcolor="#ffffff" text="#4c4c4c" link="#007aa6" vlink="#007aa6"><div>From a114dd5f9491d1ce9e1171d95e7fa2083ad16ec9 Mon Sep 17 00:00:00 2001</div><div>From: Sergio Ammirata <<a href="mailto:sergio@ammirata.net">sergio@ammirata.net</a>></div><div>Date: Sun, 22 Mar 2020 11:26:08 -0400</div><div>Subject: [PATCH] access_output: rist: refactor to use the librist library (we now support simple and main profiles)</div><div><br></div><div>---</div><div> modules/access_output/Makefile.am |   5 +-</div><div> modules/access_output/rist.c      | 815 ++++++------------------------</div><div> 2 files changed, 159 insertions(+), 661 deletions(-)</div><div><br></div><div>diff --git a/modules/access_output/Makefile.am b/modules/access_output/Makefile.am</div><div>index f6f78c0b73..5e54eae8ff 100644</div><div>--- a/modules/access_output/Makefile.am</div><div>+++ b/modules/access_output/Makefile.am</div><div>@@ -36,9 +36,10 @@ access_out_LTLIBRARIES += $(LTLIBaccess_output_srt)</div><div> EXTRA_LTLIBRARIES += libaccess_output_srt_plugin.la</div><div> </div><div> ### RIST ###</div><div>-libaccess_output_rist_plugin_la_SOURCES = access_output/rist.c access/rist.h</div><div>-libaccess_output_rist_plugin_la_CFLAGS = $(AM_CFLAGS) $(BITSTREAM_CFLAGS)</div><div>+libaccess_output_rist_plugin_la_SOURCES = access_output/rist.c</div><div>+libaccess_output_rist_plugin_la_CFLAGS = $(AM_CFLAGS)</div><div> libaccess_output_rist_plugin_la_LIBADD = $(SOCKET_LIBS)</div><div>+libaccess_output_rist_plugin_la_LDFLAGS = $(AM_LDFLAGS) -lrist</div><div> if HAVE_BITSTREAM</div><div> access_out_LTLIBRARIES += libaccess_output_rist_plugin.la</div><div> endif</div><div>diff --git a/modules/access_output/rist.c b/modules/access_output/rist.c</div><div>index 3f2f3901bd..8d044df7f0 100644</div><div>--- a/modules/access_output/rist.c</div><div>+++ b/modules/access_output/rist.c</div><div>@@ -2,7 +2,7 @@</div><div>  *  * rist.c: RIST (Reliable Internet Stream Transport) output module</div><div>  *****************************************************************************</div><div>  * Copyright (C) 2018, DVEO, the Broadcast Division of Computer Modules, Inc.</div><div>- * Copyright (C) 2018, SipRadius LLC</div><div>+ * Copyright (C) 2018-2020, SipRadius LLC</div><div>  *</div><div>  * Authors: Sergio Ammirata <<a href="mailto:sergio@ammirata.net">sergio@ammirata.net</a>></div><div>  *          Daniele Lacamera <<a href="mailto:root@danielinux.net">root@danielinux.net</a>></div><div>@@ -28,571 +28,63 @@</div><div> </div><div> #include <vlc_common.h></div><div> #include <vlc_interrupt.h></div><div>-#include <vlc_fs.h></div><div> #include <vlc_plugin.h></div><div> #include <vlc_sout.h></div><div> #include <vlc_block.h></div><div>-#include <vlc_network.h></div><div>-#include <vlc_threads.h></div><div> #include <vlc_rand.h></div><div>-#ifdef HAVE_POLL</div><div>-#include <poll.h></div><div>-#endif</div><div> #include <sys/time.h></div><div>-#ifdef HAVE_SYS_SOCKET_H</div><div>-#include <sys/socket.h></div><div>-#endif</div><div>-#include <bitstream/ietf/rtcp_rr.h></div><div>-#include <bitstream/ietf/rtcp_sr.h></div><div>-#include <bitstream/ietf/rtcp_fb.h></div><div>-#include <bitstream/ietf/rtcp_sdes.h></div><div>-#include <bitstream/ietf/rtp.h></div><div>-</div><div>-#include "../access/rist.h"</div><div>-</div><div>-/* Uncomment the following to introduce induced packet loss for TESTING purposes only */</div><div>-/*#define TEST_PACKET_LOSS*/</div><div>+#include <librist.h></div><div> </div><div> /* The default target packet size */</div><div>-#define RIST_TARGET_PACKET_SIZE 1328</div><div>-/* The default caching delay for output data */</div><div>-#define DEFAULT_CACHING_DELAY 50</div><div>-/* The default buffer size in ms */</div><div>-#define DEFAULT_BUFFER_SIZE 0</div><div>-/* Calculate and print stats once per second */</div><div>-#define STATS_INTERVAL 1000 /*ms*/</div><div>+#define RIST_TARGET_PACKET_SIZE 1316</div><div> </div><div>-#define MPEG_II_TRANSPORT_STREAM (0x21)</div><div>-#define RIST_DEFAULT_PORT 1968</div><div>+/* The default max bitrate in Kbps */</div><div>+#define DEFAULT_MAX_BITRATE 100000</div><div>+/* The default buffer size in ms */</div><div>+#define DEFAULT_BUFFER_SIZE 1000</div><div>+/* Default ports for main profile mode */</div><div>+#define RIST_DEFAULT_SRC_PORT 1971</div><div>+#define RIST_DEFAULT_DST_PORT 1968</div><div>+/* Default profile */</div><div>+#define RIST_DEFAULT_PROFILE RIST_PROFILE_MAIN</div><div> </div><div> #define SOUT_CFG_PREFIX "sout-rist-"</div><div> </div><div> static const char *const ppsz_sout_options[] = {</div><div>     "packet-size",</div><div>-    "caching",</div><div>     "buffer-size",</div><div>-    "ssrc",</div><div>     "stream-name",</div><div>+    "profile",</div><div>+    "gre-src-port",</div><div>+    "gre-dst-port",</div><div>+    "max-bitrate",</div><div>+    "encryption-type",</div><div>+    "shared-secret",</div><div>     NULL</div><div> };</div><div> </div><div> typedef struct</div><div> {</div><div>-    struct       rist_flow *flow;</div><div>-    uint16_t     rtp_counter;</div><div>-    char         receiver_name[MAX_CNAME];</div><div>-    uint64_t     last_rtcp_tx;</div><div>-    vlc_thread_t ristthread;</div><div>-    vlc_thread_t senderthread;</div><div>-    size_t       i_packet_size;</div><div>-    bool         b_mtu_warning;</div><div>-    bool         b_ismulticast;</div><div>-    vlc_mutex_t  lock;</div><div>-    vlc_mutex_t  fd_lock;</div><div>-    block_t      *p_pktbuffer;</div><div>-    uint64_t     i_ticks_caching;</div><div>-    uint32_t     ssrc;</div><div>-    block_fifo_t *p_fifo;</div><div>-    /* stats variables */</div><div>-    uint64_t     i_last_stat;</div><div>-    uint32_t     i_retransmit_packets;</div><div>-    uint32_t     i_total_packets;</div><div>+    struct rist_client *client_ctx;</div><div>+    block_t            *p_pktbuffer;</div><div>+    int                gre_src_port;</div><div>+    int                gre_dst_port;</div><div>+    int                rist_profile;</div><div>+    bool               b_mtu_warning;</div><div>+    size_t             i_packet_size;</div><div> } sout_access_out_sys_t;</div><div> </div><div>-static struct rist_flow *rist_init_tx()</div><div>-{</div><div>-    struct rist_flow *flow = calloc(1, sizeof(struct rist_flow));</div><div>-    if (!flow)</div><div>-        return NULL;</div><div>-</div><div>-    flow->reset = 1;</div><div>-    flow->buffer = calloc(RIST_QUEUE_SIZE, sizeof(struct rtp_pkt));</div><div>-    if ( unlikely( flow->buffer == NULL ) )</div><div>-    {</div><div>-        free(flow);</div><div>-        return NULL;</div><div>-    }</div><div>-    flow->fd_out = -1;</div><div>-    flow->fd_rtcp = -1;</div><div>-    flow->fd_rtcp_m = -1;</div><div>-</div><div>-    return flow;</div><div>-}</div><div>-</div><div>-static struct rist_flow *rist_udp_transmitter(sout_access_out_t *p_access, char *psz_dst_server, </div><div>-    int i_dst_port, bool b_ismulticast)</div><div>-{</div><div>-    struct rist_flow *flow;</div><div>-    flow = rist_init_tx();</div><div>-    if (!flow)</div><div>-        return NULL;</div><div>-</div><div>-    flow->fd_out = net_ConnectDgram(p_access, psz_dst_server, i_dst_port, -1, IPPROTO_UDP );</div><div>-    if (flow->fd_out < 0)</div><div>-    {</div><div>-        msg_Err( p_access, "cannot open output socket" );</div><div>-        goto fail;</div><div>-    }</div><div>-</div><div>-    if (b_ismulticast) {</div><div>-        flow->fd_rtcp_m = net_OpenDgram(p_access, psz_dst_server, i_dst_port + 1,</div><div>-            NULL, 0, IPPROTO_UDP);</div><div>-        if (flow->fd_rtcp_m < 0)</div><div>-        {</div><div>-            msg_Err( p_access, "cannot open multicast nack socket" );</div><div>-            goto fail;</div><div>-        }</div><div>-    }</div><div>-</div><div>-    flow->fd_rtcp = net_ConnectDgram(p_access, psz_dst_server, i_dst_port + 1, -1, IPPROTO_UDP );</div><div>-    if (flow->fd_rtcp < 0)</div><div>-    {</div><div>-        msg_Err( p_access, "cannot open nack socket" );</div><div>-        goto fail;</div><div>-    }</div><div>-</div><div>-    char *psz_streamname = NULL;</div><div>-    psz_streamname = var_InheritString( p_access, SOUT_CFG_PREFIX "stream-name" );</div><div>-    if ( psz_streamname != NULL && psz_streamname[0] != '\0')</div><div>-    {</div><div>-        int name_length = snprintf(flow->cname, MAX_CNAME, "%s", psz_streamname);</div><div>-        if (name_length >= MAX_CNAME)</div><div>-            flow->cname[MAX_CNAME-1] = 0;</div><div>-        free( psz_streamname );</div><div>-    }</div><div>-    else</div><div>-        populate_cname(flow->fd_rtcp, flow->cname);</div><div>-</div><div>-    msg_Info(p_access, "our cname is %s", flow->cname);</div><div>-</div><div>-    return flow;</div><div>-</div><div>-fail:</div><div>-    if (flow->fd_out != -1)</div><div>-        vlc_close(flow->fd_out);</div><div>-    if (flow->fd_rtcp != -1)</div><div>-        vlc_close(flow->fd_rtcp);</div><div>-    if (flow->fd_rtcp_m != -1)</div><div>-        vlc_close(flow->fd_rtcp_m);</div><div>-    free(flow->buffer);</div><div>-    free(flow);</div><div>-    return NULL;</div><div>-}</div><div>-</div><div>-static void rist_retransmit(sout_access_out_t *p_access, struct rist_flow *flow, uint16_t seq)</div><div>-{</div><div>-    sout_access_out_sys_t *p_sys = p_access->p_sys;</div><div>-    struct rtp_pkt *pkt = &(flow->buffer[seq]);</div><div>-    if (pkt->buffer == NULL)</div><div>-    {</div><div>-        msg_Err(p_access, "RIST recovery: missing requested packet %d, buffer not yet full", seq);</div><div>-        return;</div><div>-    }</div><div>-</div><div>-    /* Mark SSID for retransmission (change the last bit of the ssrc to 1) */</div><div>-    pkt->buffer->p_buffer[11] |= (1 << 0);</div><div>-#ifdef TEST_PACKET_LOSS</div><div>-#   warning COMPILED WITH SELF INFLICTED PACKET LOSS</div><div>-        if ((flow->packets_count % 14) == 0) {</div><div>-            return;</div><div>-        }</div><div>-#endif</div><div>-    uint32_t rtp_age = flow->hi_timestamp - pkt->rtp_ts;</div><div>-    uint64_t age = ts_get_from_rtp(rtp_age)/1000;</div><div>-    if (flow->rtp_latency > 0 && rtp_age > flow->rtp_latency)</div><div>-    {</div><div>-        msg_Err(p_access, "   Not Sending Nack #%d, too old (age %"PRId64" ms), current seq is:" \</div><div>-            " [%d]. Perhaps you should increase the buffer-size ...", seq, age, flow->wi);</div><div>-    }</div><div>-    else</div><div>-    {</div><div>-        msg_Dbg(p_access, "   Sending Nack #%d (age %"PRId64" ms), current seq is: [%d]", </div><div>-            seq, age, flow->wi);</div><div>-        p_sys->i_retransmit_packets++;</div><div>-        vlc_mutex_lock( &p_sys->fd_lock );</div><div>-        if (rist_Write(flow->fd_out, pkt->buffer->p_buffer, pkt->buffer->i_buffer) </div><div>-                != (ssize_t)pkt->buffer->i_buffer) {</div><div>-            msg_Err(p_access, "Error sending retransmitted packet after 2 tries ...");</div><div>-        }</div><div>-</div><div>-        vlc_mutex_unlock( &p_sys->fd_lock );</div><div>-    }</div><div>-}</div><div>-</div><div>-static void process_nack(sout_access_out_t *p_access, uint8_t  ptype, uint16_t nrecords, </div><div>-    struct rist_flow *flow, uint8_t *pkt)</div><div>-{</div><div>-    sout_access_out_sys_t *p_sys = p_access->p_sys;</div><div>-    int i,j;</div><div>-</div><div>-    /*msg_Info(p_access, "   Nack (BbRR), %d record(s), Window: [%d:%d-->%d]", nrecords, </div><div>-        flow->ri, flow->wi, flow->wi-flow->ri);*/</div><div>-</div><div>-    if (ptype == RTCP_PT_RTPFR)</div><div>-    {</div><div>-        uint8_t pi_ssrc[4];</div><div>-        rtcp_fb_get_ssrc_media_src(pkt, pi_ssrc);</div><div>-        if (memcmp(pi_ssrc, "RIST", 4) != 0)</div><div>-        {</div><div>-            msg_Info(p_access, "   Ignoring Nack with name %s", pi_ssrc);</div><div>-            return; /* Ignore app-type not RIST */</div><div>-        }</div><div>-</div><div>-        for (i = 0; i < (nrecords-2); i++) {</div><div>-            uint16_t missing;</div><div>-            uint16_t additional;</div><div>-            uint8_t *rtp_nack_record = (pkt + 12 + i * 4);</div><div>-            missing = rtcp_fb_nack_get_range_start(rtp_nack_record);</div><div>-            additional = rtcp_fb_nack_get_range_extra(rtp_nack_record);</div><div>-            /*msg_Info(p_access, "   Nack (Range), %d, current seq is: [%d]", missing, flow->wi);*/</div><div>-            vlc_mutex_lock( &p_sys->lock );</div><div>-            rist_retransmit(p_access, flow, missing);</div><div>-            for (j = 0; j < additional; j++) {</div><div>-                rist_retransmit(p_access, flow, missing + j + 1);</div><div>-            }</div><div>-            vlc_mutex_unlock( &p_sys->lock );</div><div>-        }</div><div>-    }</div><div>-    else if (ptype == RTCP_PT_RTPFB)</div><div>-    {</div><div>-        for (i = 0; i < (nrecords-2); i++) {</div><div>-            uint16_t missing;</div><div>-            uint16_t bitmask;</div><div>-            uint8_t *rtp_nack_record = (pkt + 12 + i * 4);</div><div>-            missing = rtcp_fb_nack_get_packet_id(rtp_nack_record);</div><div>-            bitmask = rtcp_fb_nack_get_bitmask_lost(rtp_nack_record);</div><div>-            /*msg_Info(p_access, "  Nack (Bitmask), %d, current seq is: [%d]", missing, flow->wi);*/</div><div>-            vlc_mutex_lock( &p_sys->lock );</div><div>-            rist_retransmit(p_access, flow, missing);</div><div>-            for (j = 0; j < 16; j++) {</div><div>-                if ((bitmask & (1 << j)) == (1 << j)) {</div><div>-                    rist_retransmit(p_access, flow, missing + j + 1);</div><div>-                }</div><div>-            }</div><div>-            vlc_mutex_unlock( &p_sys->lock );</div><div>-        }</div><div>-    }</div><div>-    else</div><div>-    {</div><div>-        msg_Err(p_access, "   !!! Wrong feedback. Ptype is %02x!=%02x, FMT: %02x", ptype, </div><div>-            RTCP_PT_RTPFR, rtcp_fb_get_fmt(pkt));</div><div>-    }</div><div>-}</div><div>-</div><div>-static void rist_rtcp_recv(sout_access_out_t *p_access, struct rist_flow *flow, uint8_t *pkt_raw, </div><div>-    size_t len)</div><div>-{</div><div>-    sout_access_out_sys_t *p_sys = p_access->p_sys;</div><div>-    uint8_t *pkt = pkt_raw;</div><div>-    uint8_t  ptype;</div><div>-    uint16_t processed_bytes = 0;</div><div>-    uint16_t records;</div><div>-</div><div>-    while (processed_bytes < len) {</div><div>-        pkt = pkt_raw + processed_bytes;</div><div>-        /* safety checks */</div><div>-        uint16_t bytes_left = len - processed_bytes + 1;</div><div>-        if ( bytes_left < 4 )</div><div>-        {</div><div>-            /* we must have at least 4 bytes */</div><div>-            msg_Err(p_access, "Rist rtcp packet must have at least 4 bytes, we have %d", </div><div>-                bytes_left);</div><div>-            return; </div><div>-        }</div><div>-        else if (!rtp_check_hdr(pkt))</div><div>-        {</div><div>-            /* check for a valid rtp header */</div><div>-            msg_Err(p_access, "Malformed feedback packet starting with %02x, ignoring.", pkt[0]);</div><div>-            return;</div><div>-        }</div><div>-</div><div>-        ptype =  rtcp_get_pt(pkt);</div><div>-        records = rtcp_get_length(pkt);</div><div>-        uint16_t bytes = (uint16_t)(4 * (1 + records));</div><div>-        if (bytes > bytes_left)</div><div>-        {</div><div>-            /* check for a sane number of bytes */</div><div>-            msg_Err(p_access, "Malformed feedback packet, wrong len %d, expecting %u bytes in the" \</div><div>-                " packet, got a buffer of %u bytes. ptype = %d", rtcp_get_length(pkt), bytes, </div><div>-                bytes_left, ptype);</div><div>-            return;</div><div>-        }</div><div>-</div><div>-        switch(ptype) {</div><div>-            case RTCP_PT_RTPFR:</div><div>-            case RTCP_PT_RTPFB:</div><div>-                process_nack(p_access, ptype, records, flow, pkt);</div><div>-                break;</div><div>-</div><div>-            case RTCP_PT_RR:</div><div>-                /*</div><div>-                if (p_sys->b_ismulticast == false)</div><div>-                    process_rr(f, pkt, len);</div><div>-                */</div><div>-                break;</div><div>-</div><div>-            case RTCP_PT_SDES:</div><div>-                {</div><div>-                    if (p_sys->b_ismulticast == false)</div><div>-                    {</div><div>-                        int8_t name_length = rtcp_sdes_get_name_length(pkt);</div><div>-                        if (name_length > bytes_left)</div><div>-                        {</div><div>-                            /* check for a sane number of bytes */</div><div>-                            msg_Err(p_access, "Malformed SDES packet, wrong cname len %u, got a " \</div><div>-                                "buffer of %u bytes.", name_length, bytes_left);</div><div>-                            return;</div><div>-                        }</div><div>-                        if (memcmp(pkt + RTCP_SDES_SIZE, p_sys->receiver_name, name_length) != 0)</div><div>-                        {</div><div>-                            memcpy(p_sys->receiver_name, pkt + RTCP_SDES_SIZE, name_length);</div><div>-                            msg_Info(p_access, "Receiver name: %s", p_sys->receiver_name);</div><div>-                        }</div><div>-                    }</div><div>-                }</div><div>-                break;</div><div>-</div><div>-            case RTCP_PT_SR:</div><div>-                break;</div><div>-</div><div>-            default:</div><div>-                msg_Err(p_access, "   Unrecognized RTCP packet with PTYPE=%02x!!", ptype);</div><div>-        }</div><div>-        processed_bytes += bytes;</div><div>-    }</div><div>-}</div><div>-</div><div>-static void rist_rtcp_send(sout_access_out_t *p_access)</div><div>-{</div><div>-    sout_access_out_sys_t *p_sys = p_access->p_sys;</div><div>-    struct rist_flow *flow = p_sys->flow;</div><div>-    uint8_t rtcp_buf[RTCP_SR_SIZE + RTCP_SDES_SIZE + MAX_CNAME] = { };</div><div>-    struct timeval tv;</div><div>-    int r;</div><div>-    uint64_t fractions;</div><div>-    uint16_t namelen = strlen(flow->cname) + 1;</div><div>-    gettimeofday(&tv, NULL);</div><div>-</div><div>-    /* Populate SR for sender report */</div><div>-    uint8_t *p_sr = rtcp_buf;</div><div>-    rtp_set_hdr(p_sr);</div><div>-    rtcp_sr_set_pt(p_sr);</div><div>-    rtcp_sr_set_length(p_sr, 6);</div><div>-    rtcp_fb_set_int_ssrc_pkt_sender(p_sr, p_sys->ssrc);</div><div>-    rtcp_sr_set_ntp_time_msw(p_sr, tv.tv_sec + SEVENTY_YEARS_OFFSET);</div><div>-    fractions = (uint64_t)tv.tv_usec;</div><div>-    fractions <<= 32ULL;</div><div>-    fractions /= 1000000ULL;</div><div>-    rtcp_sr_set_ntp_time_lsw(p_sr, (uint32_t)fractions);</div><div>-    rtcp_sr_set_rtp_time(p_sr, rtp_get_ts(vlc_tick_now()));</div><div>-    vlc_mutex_lock( &p_sys->lock );</div><div>-    rtcp_sr_set_packet_count(p_sr, flow->packets_count);</div><div>-    rtcp_sr_set_octet_count(p_sr, flow->bytes_count);</div><div>-    vlc_mutex_unlock( &p_sys->lock );</div><div>-</div><div>-    /* Populate SDES for sender description */</div><div>-    uint8_t *p_sdes = (rtcp_buf + RTCP_SR_SIZE);</div><div>-    /* we need to make sure it is a multiple of 4, pad if necessary */</div><div>-    if ((namelen - 2) & 0x3)</div><div>-        namelen = ((((namelen - 2) >> 2) + 1) << 2) + 2;</div><div>-    rtp_set_hdr(p_sdes);</div><div>-    rtp_set_cc(p_sdes, 1); /* Actually it is source count in this case */</div><div>-    rtcp_sdes_set_pt(p_sdes);</div><div>-    rtcp_set_length(p_sdes, (namelen >> 2) + 2);</div><div>-    rtcp_sdes_set_cname(p_sdes, 1);</div><div>-    rtcp_sdes_set_name_length(p_sdes, strlen(flow->cname));</div><div>-    p_sdes += RTCP_SDES_SIZE;</div><div>-    strlcpy((char *)p_sdes, flow->cname, namelen);</div><div>-</div><div>-    /* Send the rtcp message */</div><div>-    r = send(flow->fd_rtcp, rtcp_buf, RTCP_SR_SIZE + RTCP_SDES_SIZE + namelen, 0);</div><div>-    (void)r;</div><div>-}</div><div>-</div><div>-static void *rist_thread(void *data)</div><div>-{</div><div>-    sout_access_out_t *p_access = data;</div><div>-    sout_access_out_sys_t *p_sys = p_access->p_sys;</div><div>-    uint64_t now;</div><div>-    uint8_t pkt[RTP_PKT_SIZE];</div><div>-    struct pollfd pfd[2];</div><div>-    int ret;</div><div>-    ssize_t r;</div><div>-</div><div>-    int poll_sockets = 1;</div><div>-    pfd[0].fd = p_sys->flow->fd_rtcp;</div><div>-    pfd[0].events = POLLIN;</div><div>-    if (p_sys->b_ismulticast)</div><div>-    {</div><div>-        pfd[1].fd = p_sys->flow->fd_rtcp_m;</div><div>-        pfd[1].events = POLLIN;</div><div>-        poll_sockets++;</div><div>-    }</div><div>-</div><div>-    for (;;) {</div><div>-        ret = poll(pfd, poll_sockets, RTCP_INTERVAL >> 1);</div><div>-        int canc = vlc_savecancel();</div><div>-        if (ret > 0)</div><div>-        {</div><div>-            if (pfd[0].revents & POLLIN)</div><div>-            {</div><div>-                r = rist_Read(p_sys->flow->fd_rtcp, pkt, RTP_PKT_SIZE);</div><div>-                if (r == RTP_PKT_SIZE) {</div><div>-                    msg_Err(p_access, "Rist RTCP messsage is too big (%zd bytes) and was probably " \</div><div>-                        "cut, please keep it under %d bytes", r, RTP_PKT_SIZE);</div><div>-                }</div><div>-                if (unlikely(r == -1)) {</div><div>-                    msg_Err(p_access, "socket %d error: %s\n", p_sys->flow->fd_rtcp, </div><div>-                        gai_strerror(errno));</div><div>-                }</div><div>-                else {</div><div>-                    rist_rtcp_recv(p_access, p_sys->flow, pkt, r);</div><div>-                }</div><div>-            }</div><div>-            if (p_sys->b_ismulticast && (pfd[1].revents & POLLIN))</div><div>-            {</div><div>-                r = rist_Read(p_sys->flow->fd_rtcp_m, pkt, RTP_PKT_SIZE);</div><div>-                if (r == RTP_PKT_SIZE) {</div><div>-                    msg_Err(p_access, "Rist RTCP messsage is too big (%zd bytes) and was " \</div><div>-                        "probably cut, please keep it under %d bytes", r, RTP_PKT_SIZE);</div><div>-                }</div><div>-                if (unlikely(r == -1)) {</div><div>-                    msg_Err(p_access, "mcast socket %d error: %s\n", p_sys->flow->fd_rtcp_m,</div><div>-                        gai_strerror(errno));</div><div>-                }</div><div>-                else {</div><div>-                    rist_rtcp_recv(p_access, p_sys->flow, pkt, r);</div><div>-                }</div><div>-            }</div><div>-        }</div><div>-</div><div>-        /* And, in any case: */</div><div>-        now = vlc_tick_now();</div><div>-        if ((now - p_sys->last_rtcp_tx) > VLC_TICK_FROM_MS(RTCP_INTERVAL))</div><div>-        {</div><div>-            rist_rtcp_send(p_access);</div><div>-            p_sys->last_rtcp_tx = now;</div><div>-        }</div><div>-        vlc_restorecancel (canc);</div><div>-    }</div><div>-</div><div>-    return NULL;</div><div>-}</div><div>-</div><div>-/****************************************************************************</div><div>- * RTP send</div><div>- ****************************************************************************/</div><div>-static void* ThreadSend( void *data )</div><div>-{</div><div>-    sout_access_out_t *p_access = data;</div><div>-    sout_access_out_sys_t *p_sys = p_access->p_sys;</div><div>-    vlc_tick_t i_caching = p_sys->i_ticks_caching;</div><div>-    struct rist_flow *flow = p_sys->flow;</div><div>-</div><div>-    for (;;)</div><div>-    {</div><div>-        ssize_t len = 0;</div><div>-        uint16_t seq = 0;</div><div>-        uint32_t pkt_ts = 0;</div><div>-        block_t *out = block_FifoGet( p_sys->p_fifo );</div><div>-</div><div>-        block_cleanup_push( out );</div><div>-        vlc_tick_wait (out->i_dts + i_caching);</div><div>-        vlc_cleanup_pop();</div><div>-</div><div>-        len = out->i_buffer;</div><div>-        int canc = vlc_savecancel();</div><div>-</div><div>-        seq = rtp_get_seqnum(out->p_buffer);</div><div>-        pkt_ts = rtp_get_timestamp(out->p_buffer);</div><div>-</div><div>-        vlc_mutex_lock( &p_sys->fd_lock );</div><div>-#ifdef TEST_PACKET_LOSS</div><div>-#   warning COMPILED WITH SELF INFLICTED PACKET LOSS</div><div>-        if ((seq % 14) == 0) {</div><div>-            /*msg_Err(p_access, "Dropped packet with seq number %d ...", seq);*/</div><div>-        }</div><div>-        else</div><div>-        {</div><div>-            if (rist_Write(flow->fd_out, out->p_buffer, len) != len) {</div><div>-                msg_Err(p_access, "Error sending data packet after 2 tries ...");</div><div>-            }</div><div>-        }</div><div>-#else</div><div>-        if (rist_Write(flow->fd_out, out->p_buffer, len) != len) {</div><div>-            msg_Err(p_access, "Error sending data packet after 2 tries ...");</div><div>-        }</div><div>-#endif</div><div>-        vlc_mutex_unlock( &p_sys->fd_lock );</div><div>-</div><div>-        /* Insert Into Queue */</div><div>-        vlc_mutex_lock( &p_sys->lock );</div><div>-        /* Always replace the existing one with the new one */</div><div>-        struct rtp_pkt *pkt;</div><div>-        pkt = &(flow->buffer[seq]);</div><div>-        if (pkt->buffer)</div><div>-        {</div><div>-            block_Release(pkt->buffer);</div><div>-            pkt->buffer = NULL;</div><div>-        }</div><div>-        pkt->rtp_ts = pkt_ts;</div><div>-        pkt->buffer = out;</div><div>-</div><div>-        if (flow->reset == 1)</div><div>-        {</div><div>-            msg_Info(p_access, "Traffic detected");</div><div>-            /* First packet in the queue */</div><div>-            flow->reset = 0;</div><div>-        }</div><div>-        flow->wi = seq;</div><div>-        flow->hi_timestamp = pkt_ts;</div><div>-        /* Stats for RTCP feedback packets */</div><div>-        flow->packets_count++;</div><div>-        flow->bytes_count += len;</div><div>-        flow->last_out = seq;</div><div>-        vlc_mutex_unlock( &p_sys->lock );</div><div>-</div><div>-        /* We print out the stats once per second */</div><div>-        uint64_t now = vlc_tick_now();</div><div>-        uint64_t interval = (now - p_sys->i_last_stat);</div><div>-        if ( interval > VLC_TICK_FROM_MS(STATS_INTERVAL) )</div><div>-        {</div><div>-            if (p_sys->i_retransmit_packets > 0)</div><div>-            {</div><div>-                float quality = 100;</div><div>-                if (p_sys->i_total_packets > 0)</div><div>-                    quality = (float)100 - (float)100*(float)(p_sys->i_retransmit_packets)</div><div>-                        /(float)p_sys->i_total_packets;</div><div>-                msg_Info(p_access, "STATS: Total %u, Retransmitted %u, Link Quality %.2f%%", </div><div>-                    p_sys->i_total_packets, p_sys->i_retransmit_packets, quality);</div><div>-            }</div><div>-            p_sys->i_last_stat = now;</div><div>-            p_sys->i_retransmit_packets = 0;</div><div>-            p_sys->i_total_packets = 0;</div><div>-        }</div><div>-        p_sys->i_total_packets++;</div><div>-</div><div>-        vlc_restorecancel (canc);</div><div>-    }</div><div>-    return NULL;</div><div>-}</div><div>-</div><div>-static void SendtoFIFO( sout_access_out_t *p_access, block_t *buffer )</div><div>+static uint64_t i_dts_to_ntp64( vlc_tick_t i_dts )</div><div> {</div><div>-    sout_access_out_sys_t *p_sys = p_access->p_sys;</div><div>-    uint16_t seq = p_sys->rtp_counter++;</div><div>-</div><div>-    /* Set fresh rtp header data */</div><div>-    uint8_t *bufhdr = buffer->p_buffer;</div><div>-    rtp_set_hdr(bufhdr);</div><div>-    rtp_set_type(bufhdr, MPEG_II_TRANSPORT_STREAM);</div><div>-    rtp_set_seqnum(bufhdr, seq);</div><div>-    rtp_set_int_ssrc(bufhdr, p_sys->ssrc);</div><div>-    uint32_t pkt_ts = rtp_get_ts(buffer->i_dts);</div><div>-    rtp_set_timestamp(bufhdr, pkt_ts);</div><div>-</div><div>-    block_t *pkt = block_Duplicate(buffer);</div><div>-    block_FifoPut( p_sys->p_fifo, pkt );</div><div>+    lldiv_t d = lldiv (i_dts, CLOCK_FREQ);</div><div>+    struct timespec ts = { d.quot, NS_FROM_VLC_TICK( d.rem ) };</div><div>+    // Convert nanoseconds to 32-bits fraction (232 picosecond units)</div><div>+    uint64_t t = (uint64_t)(ts.tv_nsec) << 32;</div><div>+    t /= 1000000000;</div><div>+    // There is 70 years (incl. 17 leap ones) offset to the Unix Epoch.</div><div>+    // No leap seconds during that period since they were not invented yet.</div><div>+    t |= ((70LL * 365 + 17) * 24 * 60 * 60 + ts.tv_sec) << 32;</div><div>+    return t; // nanoseconds (technically, 232.831 picosecond units)</div><div> }</div><div> </div><div> static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer )</div><div>@@ -616,8 +108,9 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer )</div><div>         /* Temp buffer is already too large, flush */</div><div>         if( p_sys->p_pktbuffer->i_buffer + p_buffer->i_buffer > p_sys->i_packet_size )</div><div>         {</div><div>-            SendtoFIFO(p_access, p_sys->p_pktbuffer);</div><div>-            p_sys->p_pktbuffer->i_buffer = RTP_HEADER_SIZE;</div><div>+            rist_client_write_timed(p_sys->client_ctx, p_sys->p_pktbuffer->p_buffer, p_sys->p_pktbuffer->i_buffer,</div><div>+                                    p_sys->gre_src_port, p_sys->gre_dst_port, i_dts_to_ntp64(p_sys->p_pktbuffer->i_dts));</div><div>+            p_sys->p_pktbuffer->i_buffer = 0;</div><div>         }</div><div> </div><div>         i_len += p_buffer->i_buffer;</div><div>@@ -629,7 +122,7 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer )</div><div> </div><div>             i_block_split++;</div><div> </div><div>-            if( p_sys->p_pktbuffer->i_buffer == RTP_HEADER_SIZE )</div><div>+            if( p_sys->p_pktbuffer->i_buffer == 0 )</div><div>             {</div><div>                 p_sys->p_pktbuffer->i_dts = p_buffer->i_dts;</div><div>             }</div><div>@@ -646,8 +139,9 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer )</div><div>              *  larger than the packet-size because we need to continue the inner loop */</div><div>             if( p_sys->p_pktbuffer->i_buffer == p_sys->i_packet_size || i_block_split > 1 )</div><div>             {</div><div>-                SendtoFIFO(p_access, p_sys->p_pktbuffer);</div><div>-                p_sys->p_pktbuffer->i_buffer = RTP_HEADER_SIZE;</div><div>+                rist_client_write_timed(p_sys->client_ctx, p_sys->p_pktbuffer->p_buffer, p_sys->p_pktbuffer->i_buffer,</div><div>+                                        p_sys->gre_src_port, p_sys->gre_dst_port, i_dts_to_ntp64(p_sys->p_pktbuffer->i_dts));</div><div>+                p_sys->p_pktbuffer->i_buffer = 0;</div><div>             }</div><div> </div><div>         }</div><div>@@ -684,54 +178,16 @@ static int Control( sout_access_out_t *p_access, int i_query, va_list args )</div><div>     return i_ret;</div><div> }</div><div> </div><div>-static void Clean( sout_access_out_t *p_access )</div><div>-{</div><div>-    sout_access_out_sys_t *p_sys = p_access->p_sys;</div><div>-</div><div>-    if( likely(p_sys->p_fifo != NULL) )</div><div>-        block_FifoRelease( p_sys->p_fifo );</div><div>-</div><div>-    if ( p_sys->flow )</div><div>-    {</div><div>-        if (p_sys->flow->fd_out >= 0) {</div><div>-            net_Close (p_sys->flow->fd_out);</div><div>-        }</div><div>-        if (p_sys->flow->fd_rtcp >= 0) {</div><div>-            net_Close (p_sys->flow->fd_rtcp);</div><div>-        }</div><div>-        if (p_sys->flow->fd_rtcp_m >= 0) {</div><div>-            net_Close (p_sys->flow->fd_rtcp_m);</div><div>-        }</div><div>-        for (int i=0; i<RIST_QUEUE_SIZE; i++) {</div><div>-            struct rtp_pkt *pkt = &(p_sys->flow->buffer[i]);</div><div>-            if (pkt->buffer)</div><div>-            {</div><div>-                block_Release(pkt->buffer);</div><div>-                pkt->buffer = NULL;</div><div>-            }</div><div>-        }</div><div>-        free(p_sys->flow->buffer);</div><div>-        free(p_sys->flow);</div><div>-    }</div><div>-</div><div>-    vlc_mutex_destroy( &p_sys->lock );</div><div>-    vlc_mutex_destroy( &p_sys->fd_lock );</div><div>-    if (p_sys->p_pktbuffer)</div><div>-        block_Release(p_sys->p_pktbuffer);</div><div>-}</div><div>-</div><div> static void Close( vlc_object_t * p_this )</div><div> {</div><div>     sout_access_out_t     *p_access = (sout_access_out_t*)p_this;</div><div>     sout_access_out_sys_t *p_sys = p_access->p_sys;</div><div> </div><div>-    vlc_cancel(p_sys->ristthread);</div><div>-    vlc_cancel(p_sys->senderthread);</div><div>-</div><div>-    vlc_join(p_sys->ristthread, NULL);</div><div>-    vlc_join(p_sys->senderthread, NULL);</div><div>+    if (p_sys->p_pktbuffer)</div><div>+        block_Release(p_sys->p_pktbuffer);</div><div> </div><div>-    Clean( p_access );</div><div>+    rist_client_destroy(p_sys->client_ctx);</div><div>+    p_sys->client_ctx = NULL;</div><div> }</div><div> </div><div> static int Open( vlc_object_t *p_this )</div><div>@@ -754,105 +210,139 @@ static int Open( vlc_object_t *p_this )</div><div>     if( unlikely( p_sys == NULL ) )</div><div>         return VLC_ENOMEM;</div><div> </div><div>-    int i_dst_port = RIST_DEFAULT_PORT;</div><div>-    char *psz_dst_addr;</div><div>-    char *psz_parser = psz_dst_addr = strdup( p_access->psz_path );</div><div>-    if( !psz_dst_addr )</div><div>+    p_sys->gre_src_port = var_InheritInteger(p_access, SOUT_CFG_PREFIX "gre-src-port");</div><div>+    p_sys->gre_dst_port = var_InheritInteger(p_access, SOUT_CFG_PREFIX "gre-dst-port");</div><div>+    if (p_sys->gre_dst_port % 2 != 0) {</div><div>+        msg_Err( p_access, "GRE destination port must be an even number." );</div><div>         return VLC_ENOMEM;</div><div>-</div><div>-    if ( psz_parser[0] == '[' )</div><div>-        psz_parser = strchr( psz_parser, ']' );</div><div>-</div><div>-    psz_parser = strchr( psz_parser ? psz_parser : psz_dst_addr, ':' );</div><div>-    if ( psz_parser != NULL )</div><div>-    {</div><div>-        *psz_parser++ = '\0';</div><div>-        i_dst_port = atoi( psz_parser );</div><div>     }</div><div> </div><div>-    vlc_mutex_init( &p_sys->lock );</div><div>-    vlc_mutex_init( &p_sys->fd_lock );</div><div>+    p_sys->i_packet_size = var_InheritInteger(p_access, SOUT_CFG_PREFIX "packet-size" );</div><div>+    p_sys->p_pktbuffer = block_Alloc( p_sys->i_packet_size );</div><div>+    if( unlikely(p_sys->p_pktbuffer == NULL) )</div><div>+        goto failed;</div><div> </div><div>-    msg_Info(p_access, "Connecting RIST output to %s:%d and %s:%d", psz_dst_addr, i_dst_port, </div><div>-        psz_dst_addr, i_dst_port+1);</div><div>-    p_sys->b_ismulticast = is_multicast_address(psz_dst_addr);</div><div>-    struct rist_flow *flow = rist_udp_transmitter(p_access, psz_dst_addr, i_dst_port,</div><div>-        p_sys->b_ismulticast);</div><div>-    free (psz_dst_addr);</div><div>-    if (!flow)</div><div>+    p_sys->rist_profile = var_InheritInteger(p_access, SOUT_CFG_PREFIX "profile");</div><div>+    if (rist_client_create(&p_sys->client_ctx, p_sys->rist_profile) != 0) {</div><div>+        msg_Err( p_access, "Could not create rist client context\n");</div><div>         goto failed;</div><div>+    }</div><div> </div><div>-    p_sys->flow = flow;</div><div>-    flow->latency = var_InheritInteger(p_access, SOUT_CFG_PREFIX "buffer-size");</div><div>-    flow->rtp_latency = rtp_get_ts(VLC_TICK_FROM_MS(flow->latency));</div><div>-    p_sys->ssrc = var_InheritInteger(p_access, SOUT_CFG_PREFIX "ssrc");</div><div>-    if (p_sys->ssrc == 0) {</div><div>-        vlc_rand_bytes(&p_sys->ssrc, 4);</div><div>+    char *psz_streamname = NULL;</div><div>+    psz_streamname = var_InheritString( p_access, SOUT_CFG_PREFIX "stream-name" );</div><div>+    if ( psz_streamname != NULL && psz_streamname[0] != '\0')</div><div>+    {</div><div>+        if (rist_client_set_cname(p_sys->client_ctx, psz_streamname, strlen(psz_streamname)) != 0) {</div><div>+            msg_Err( p_access, "Could not set the cname\n");</div><div>+            goto failed;</div><div>+        }</div><div>+        free( psz_streamname );</div><div>     }</div><div>-    /* Last bit of ssrc must be 0 for normal data and 1 for retries */</div><div>-    p_sys->ssrc &= ~(1 << 0);</div><div> </div><div>-    msg_Info(p_access, "SSRC: 0x%08X", p_sys->ssrc);</div><div>-    p_sys->i_ticks_caching = VLC_TICK_FROM_MS(var_InheritInteger( p_access, </div><div>-        SOUT_CFG_PREFIX "caching"));</div><div>-    p_sys->i_packet_size = var_InheritInteger(p_access, SOUT_CFG_PREFIX "packet-size" );</div><div>-    p_sys->p_fifo = block_FifoNew();</div><div>-    if( unlikely(p_sys->p_fifo == NULL) )</div><div>-        goto failed;</div><div>-    p_sys->p_pktbuffer = block_Alloc( p_sys->i_packet_size );</div><div>-    if( unlikely(p_sys->p_pktbuffer == NULL) )</div><div>+    uint64_t now;</div><div>+    struct timeval time;</div><div>+    gettimeofday(&time, NULL);</div><div>+    now = time.tv_sec * 1000000;</div><div>+    now += time.tv_usec;</div><div>+    uint32_t adv_flow_id = (uint32_t)(now >> 16);</div><div>+    // It must me an even number</div><div>+    adv_flow_id &= ~(1UL << 0);</div><div>+</div><div>+    if(rist_client_init(p_sys->client_ctx, adv_flow_id, RIST_LOG_WARN, NULL, NULL, NULL) < 0) {</div><div>+        msg_Err( p_access, "Could not initialize rist client\n");</div><div>         goto failed;</div><div>+    }</div><div> </div><div>-    p_sys->p_pktbuffer->i_buffer = RTP_HEADER_SIZE;</div><div>-</div><div>-    p_access->p_sys = p_sys;</div><div>+    int i_encryption_type = var_InheritInteger(p_access, SOUT_CFG_PREFIX "encryption-type");</div><div>+    char *psz_shared_secret = NULL;</div><div>+    psz_shared_secret = var_InheritString( p_access, SOUT_CFG_PREFIX "stream-name" );</div><div>+    if (psz_shared_secret != NULL && psz_shared_secret[0] != '\0') {</div><div>+        if (i_encryption_type) {</div><div>+            int keysize =  i_encryption_type == 1 ? 128 : 256;</div><div>+            if (rist_client_encrypt_enable(p_sys->client_ctx, psz_shared_secret, keysize) == -1) {</div><div>+                msg_Err( p_access, "Could not enable encryption\n");</div><div>+                free(psz_shared_secret);</div><div>+                goto failed;</div><div>+            }</div><div>+        }</div><div>+        free(psz_shared_secret);</div><div>+    }</div><div> </div><div>-    if( vlc_clone(&p_sys->senderthread, ThreadSend, p_access, VLC_THREAD_PRIORITY_HIGHEST ) )</div><div>-    {</div><div>-        msg_Err(p_access, "Failed to create sender thread.");</div><div>+    const struct rist_peer_config peer_config = {</div><div>+        .address = p_access->psz_path,</div><div>+        .recovery_mode = RIST_RECOVERY_MODE_TIME,</div><div>+        .recovery_maxbitrate = var_InheritInteger(p_access, SOUT_CFG_PREFIX "max-bitrate"),</div><div>+        .recovery_maxbitrate_return = 0,</div><div>+        .recovery_length_min = var_InheritInteger(p_access, SOUT_CFG_PREFIX "buffer-size"),</div><div>+        .recovery_length_max = var_InheritInteger(p_access, SOUT_CFG_PREFIX "buffer-size"),</div><div>+        .recover_reorder_buffer = 70,</div><div>+        .recovery_rtt_min = 50,</div><div>+        .recovery_rtt_max = 500,</div><div>+        .weight = 5,</div><div>+        .bufferbloat_mode = RIST_BUFFER_BLOAT_MODE_NORMAL,</div><div>+        .bufferbloat_limit = 7,</div><div>+        .bufferbloat_hard_limit = 20</div><div>+    };</div><div>+</div><div>+    struct rist_peer *peer;</div><div>+    if (rist_client_add_peer(p_sys->client_ctx, &peer_config, &peer) == -1) {</div><div>+        msg_Err( p_access, "Could not add peer connector to client\n");</div><div>         goto failed;</div><div>     }</div><div> </div><div>-    if (vlc_clone(&p_sys->ristthread, rist_thread, p_access, VLC_THREAD_PRIORITY_INPUT))</div><div>-    {</div><div>-        msg_Err(p_access, "Failed to create worker thread.");</div><div>-        vlc_cancel(p_sys->senderthread);</div><div>-        vlc_join(p_sys->senderthread, NULL);</div><div>+    if (rist_client_start(p_sys->client_ctx) == -1) {</div><div>+        msg_Err( p_access, "Could not start rist client\n");</div><div>         goto failed;</div><div>     }</div><div> </div><div>+    p_access->p_sys = p_sys;</div><div>     p_access->pf_write = Write;</div><div>     p_access->pf_control = Control;</div><div> </div><div>     return VLC_SUCCESS;</div><div> </div><div> failed:</div><div>-    Clean( p_access );</div><div>+    rist_client_destroy(p_sys->client_ctx);</div><div>+    p_sys->client_ctx = NULL;</div><div>     return VLC_EGENERIC;</div><div> }</div><div> </div><div>-#define CACHING_TEXT N_("RIST data output caching size (ms)")</div><div>-#define CACHING_LONGTEXT N_( \</div><div>-    "Having this cache will guarantee that the packets going out are " \</div><div>-    "delivered at a spacing determined by the chain timestamps thus ensuring " \</div><div>-    "a near jitter free output. Be aware that this setting will also add to " \</div><div>-    "the overall latency of the stream." )</div><div>-</div><div> #define BUFFER_TEXT N_("RIST retry-buffer queue size (ms)")</div><div> #define BUFFER_LONGTEXT N_( \</div><div>-    "This must match the buffer size (latency) configured on the server side. If you " \</div><div>-    "are not sure, leave the default of 0 which will set it the maximum " \</div><div>-    "value and will use about 100MB of RAM" )</div><div>+    "This must match the buffer size (latency) configured on the receiver side. If you " \</div><div>+    "are not sure, leave it blank and it will use 1000ms" )</div><div> </div><div>-#define SSRC_TEXT N_("SSRC used in RTP output (default is random, i.e. 0)")</div><div>-#define SSRC_LONGTEXT N_( \</div><div>-    "Use this setting to specify a known SSRC for the RTP header. This is only useful " \</div><div>-    "if your receiver acts on it. When using VLC as receiver, it is not." )</div><div>+#define MAX_BITRATE_TEXT N_("Max bitrate in Kbps")</div><div>+#define MAX_BITRATE_LONGTEXT N_( \</div><div>+    "Use this value to guarantee that data+retries bitrate never exceeds your pipe size. " \</div><div>+    "Default value is 100000 Kbps (100 Mbps)" )</div><div> </div><div> #define NAME_TEXT N_("Stream name")</div><div> #define NAME_LONGTEXT N_( \</div><div>     "This Stream name will be sent to the receiver using the rist RTCP channel" )</div><div> </div><div>+#define PROFILE_TEXT N_("Rist Profile")</div><div>+#define PROFILE_LONGTEXT N_( \</div><div>+    "Select the rist profile to use, 0 is simple, 1 is main. Default is main (1)" )</div><div>+</div><div>+#define SRC_PORT_TEXT N_("GRE Source Port")</div><div>+#define SRC_PORT_LONGTEXT N_( \</div><div>+    "Source port to be used inside the reduced-mode of the main profile" )</div><div>+</div><div>+#define DST_PORT_TEXT N_("GRE Destination Port")</div><div>+#define DST_PORT_LONGTEXT N_( \</div><div>+    "Destination port to be used inside the reduced-mode of the main profile" )</div><div>+</div><div>+#define ENCRYPTION_TYPE_TEXT N_("Encryption Type")</div><div>+#define ENCRYPTION_TYPE_LONGTEXT N_( \</div><div>+    "Type of encryption to use: 0 = disabled, 1 = AES 128, 2 = AES 256, default is " \</div><div>+    "disabled" )</div><div>+</div><div>+#define SHARED_SECRET_TEXT N_("Shared Secret")</div><div>+#define SHARED_SECRET_LONGTEXT N_( \</div><div>+    "This shared secret is a passphare shared between sender and receiver. The AES key " \</div><div>+    "is derived from it" )</div><div>+</div><div> /* Module descriptor */</div><div> vlc_module_begin()</div><div> </div><div>@@ -863,13 +353,20 @@ vlc_module_begin()</div><div> </div><div>     add_integer( SOUT_CFG_PREFIX "packet-size", RIST_TARGET_PACKET_SIZE,</div><div>             N_("RIST target packet size (bytes)"), NULL, true )</div><div>-    add_integer( SOUT_CFG_PREFIX "caching", DEFAULT_CACHING_DELAY,</div><div>-            CACHING_TEXT, CACHING_LONGTEXT, true )</div><div>     add_integer( SOUT_CFG_PREFIX "buffer-size", DEFAULT_BUFFER_SIZE,</div><div>             BUFFER_TEXT, BUFFER_LONGTEXT, true )</div><div>-    add_integer( SOUT_CFG_PREFIX "ssrc", 0,</div><div>-            SSRC_TEXT, SSRC_LONGTEXT, true )</div><div>+    add_integer( SOUT_CFG_PREFIX "max-bitrate", DEFAULT_MAX_BITRATE,</div><div>+            MAX_BITRATE_TEXT, MAX_BITRATE_LONGTEXT, true )</div><div>+    add_integer( SOUT_CFG_PREFIX "profile", RIST_DEFAULT_PROFILE,</div><div>+            PROFILE_TEXT, PROFILE_LONGTEXT, true )</div><div>+    add_integer( SOUT_CFG_PREFIX "gre-src-port", RIST_DEFAULT_SRC_PORT,</div><div>+            SRC_PORT_TEXT, SRC_PORT_LONGTEXT, true )</div><div>+    add_integer( SOUT_CFG_PREFIX "gre-dst-port", RIST_DEFAULT_DST_PORT,</div><div>+            DST_PORT_TEXT, DST_PORT_LONGTEXT, true )</div><div>+    add_integer( SOUT_CFG_PREFIX "encryption-type", 0,</div><div>+            ENCRYPTION_TYPE_TEXT, ENCRYPTION_TYPE_LONGTEXT, true )</div><div>     add_string( SOUT_CFG_PREFIX "stream-name", NULL, NAME_TEXT, NAME_LONGTEXT, true )</div><div>+    add_string( SOUT_CFG_PREFIX "shared-secret", NULL, SHARED_SECRET_TEXT, SHARED_SECRET_LONGTEXT, true )</div><div> </div><div>     set_capability( "sout access", 0 )</div><div>     add_shortcut( "rist", "tr06" )</div><div>-- </div><div>2.17.1</div><div><br></div><div></div><div><br></div></body></html>