[vlc-commits] [Git][videolan/vlc][master] 4 commits: sout/udp: add module for TS over raw UDP

Rémi Denis-Courmont (@Courmisch) gitlab at videolan.org
Wed Dec 1 21:41:17 UTC 2021



Rémi Denis-Courmont pushed to branch master at VideoLAN / VLC


Commits:
9dec8f3b by Rémi Denis-Courmont at 2021-12-01T20:01:08+00:00
sout/udp: add module for TS over raw UDP

This module does not pretend that UDP output is a regular access that
should be handled with the "standard" stream output.
This takes handles SAP much more cleanly and supports vector I/O to
avoid unnecessary memory copies.

Also fixes #26058.

- - - - -
3d0da8e9 by Rémi Denis-Courmont at 2021-12-01T20:01:08+00:00
sout/udp: add backward compability

- - - - -
1315eb16 by Rémi Denis-Courmont at 2021-12-01T20:01:08+00:00
standard: remove udp handling

- - - - -
c142d02b by Rémi Denis-Courmont at 2021-12-01T20:01:08+00:00
udp access out: remove no longer used module

- - - - -


7 changed files:

- NEWS
- modules/access_output/Makefile.am
- − modules/access_output/udp.c
- modules/stream_out/Makefile.am
- modules/stream_out/standard.c
- + modules/stream_out/udp.c
- po/POTFILES.in


Changes:

=====================================
NEWS
=====================================
@@ -92,6 +92,10 @@ Stream output:
  * New SDI output with improved audio and ancillary support.
    Candidate for deprecation of decklink vout/aout modules.
  * Support for DLNA/UPNP renderers
+ * The "udp" access output module has been removed.
+   Please use the UDP stream output instead, e.g.:
+     Old: '#std{access=udp,mux=ts,dst=239.255.1.2:1234,sap}'
+     New: '#udp{dst=239.255.1.2:1234,sap}'
 
 Muxers:
  * MP4 files are no longer faststart by default


=====================================
modules/access_output/Makefile.am
=====================================
@@ -3,14 +3,11 @@ access_outdir = $(pluginsdir)/access_output
 libaccess_output_dummy_plugin_la_SOURCES = access_output/dummy.c
 libaccess_output_file_plugin_la_SOURCES = access_output/file.c
 libaccess_output_http_plugin_la_SOURCES = access_output/http.c
-libaccess_output_udp_plugin_la_SOURCES = access_output/udp.c
-libaccess_output_udp_plugin_la_LIBADD = $(SOCKET_LIBS)
 
 access_out_LTLIBRARIES = \
 	libaccess_output_dummy_plugin.la \
 	libaccess_output_file_plugin.la \
-	libaccess_output_http_plugin.la \
-	libaccess_output_udp_plugin.la
+	libaccess_output_http_plugin.la
 
 libaccess_output_livehttp_plugin_la_SOURCES = access_output/livehttp.c
 libaccess_output_livehttp_plugin_la_CFLAGS = $(AM_CFLAGS) $(GCRYPT_CFLAGS)


=====================================
modules/access_output/udp.c deleted
=====================================
@@ -1,420 +0,0 @@
-/*****************************************************************************
- * udp.c
- *****************************************************************************
- * Copyright (C) 2001-2007 VLC authors and VideoLAN
- *
- * Authors: Laurent Aimar <fenrir at via.ecp.fr>
- *          Eric Petit <titer at videolan.org>
- *
- * 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.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <vlc_common.h>
-#include <vlc_plugin.h>
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <vlc_queue.h>
-#include <vlc_sout.h>
-#include <vlc_block.h>
-
-#ifdef _WIN32
-#   include <winsock2.h>
-#   include <ws2tcpip.h>
-#elif defined (HAVE_SYS_SOCKET_H)
-#   include <sys/socket.h>
-#endif
-
-#include <vlc_network.h>
-
-#define MAX_EMPTY_BLOCKS 200
-
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
-static int  Open ( vlc_object_t * );
-static void Close( vlc_object_t * );
-
-#define SOUT_CFG_PREFIX "sout-udp-"
-
-#define CACHING_TEXT N_("Caching value (ms)")
-#define CACHING_LONGTEXT N_( \
-    "Default caching value for outbound UDP streams. This " \
-    "value should be set in milliseconds." )
-
-#define GROUP_TEXT N_("Group packets")
-#define GROUP_LONGTEXT N_("Packets can be sent one by one at the right time " \
-                          "or by groups. You can choose the number " \
-                          "of packets that will be sent at a time. It " \
-                          "helps reducing the scheduling load on " \
-                          "heavily-loaded systems." )
-
-vlc_module_begin ()
-    set_description( N_("UDP stream output") )
-    set_shortname( "UDP" )
-    set_category( CAT_SOUT )
-    set_subcategory( SUBCAT_SOUT_ACO )
-    add_integer( SOUT_CFG_PREFIX "caching", DEFAULT_PTS_DELAY / 1000, CACHING_TEXT, CACHING_LONGTEXT )
-    add_integer( SOUT_CFG_PREFIX "group", 1, GROUP_TEXT, GROUP_LONGTEXT )
-
-    set_capability( "sout access", 0 )
-    add_shortcut( "udp" )
-    set_callbacks( Open, Close )
-vlc_module_end ()
-
-/*****************************************************************************
- * Exported prototypes
- *****************************************************************************/
-
-static const char *const ppsz_sout_options[] = {
-    "caching",
-    "group",
-    NULL
-};
-
-/* Options handled by the libvlc network core */
-static const char *const ppsz_core_options[] = {
-    "dscp",
-    "ttl",
-    "miface",
-    NULL
-};
-
-static ssize_t Write   ( sout_access_out_t *, block_t * );
-static int Control( sout_access_out_t *, int, va_list );
-
-static void* ThreadWrite( void * );
-
-typedef struct
-{
-    vlc_tick_t    i_caching;
-    int           i_handle;
-    bool          b_mtu_warning;
-    bool          dead;
-    size_t        i_mtu;
-
-    vlc_queue_t   queue;
-    block_t      *p_buffer;
-
-    vlc_thread_t  thread;
-} sout_access_out_sys_t;
-
-#define DEFAULT_PORT 1234
-
-/*****************************************************************************
- * Open: open the file
- *****************************************************************************/
-static int Open( vlc_object_t *p_this )
-{
-    sout_access_out_t       *p_access = (sout_access_out_t*)p_this;
-    sout_access_out_sys_t   *p_sys;
-
-    char                *psz_dst_addr = NULL;
-    int                 i_dst_port;
-
-    int                 i_handle;
-
-    config_ChainParse( p_access, SOUT_CFG_PREFIX,
-                       ppsz_sout_options, p_access->p_cfg );
-    config_ChainParse( p_access, "",
-                       ppsz_core_options, p_access->p_cfg );
-
-    if (var_Create (p_access, "dst-port", VLC_VAR_INTEGER)
-     || var_Create (p_access, "src-port", VLC_VAR_INTEGER)
-     || var_Create (p_access, "dst-addr", VLC_VAR_STRING)
-     || var_Create (p_access, "src-addr", VLC_VAR_STRING))
-    {
-        return VLC_ENOMEM;
-    }
-
-    if( !( p_sys = malloc ( sizeof( *p_sys ) ) ) )
-        return VLC_ENOMEM;
-    p_access->p_sys = p_sys;
-
-    i_dst_port = DEFAULT_PORT;
-    char *psz_parser = psz_dst_addr = strdup( p_access->psz_path );
-    if( !psz_dst_addr )
-    {
-        free( p_sys );
-        return VLC_ENOMEM;
-    }
-
-    if (psz_parser[0] == '[')
-        psz_parser = strchr (psz_parser, ']');
-
-    psz_parser = strchr (psz_parser ? psz_parser : psz_dst_addr, ':');
-    if (psz_parser != NULL)
-    {
-        *psz_parser++ = '\0';
-        i_dst_port = atoi (psz_parser);
-    }
-
-    i_handle = net_ConnectDgram( p_this, psz_dst_addr, i_dst_port, -1,
-                                 IPPROTO_UDP );
-    free (psz_dst_addr);
-
-    if( i_handle == -1 )
-    {
-         msg_Err( p_access, "failed to create raw UDP socket" );
-         free (p_sys);
-         return VLC_EGENERIC;
-    }
-    else
-    {
-        char addr[NI_MAXNUMERICHOST];
-        int port;
-
-        if (net_GetSockAddress (i_handle, addr, &port) == 0)
-        {
-            msg_Dbg (p_access, "source: %s port %d", addr, port);
-            var_SetString (p_access, "src-addr", addr);
-            var_SetInteger (p_access, "src-port", port);
-        }
-
-        if (net_GetPeerAddress (i_handle, addr, &port) == 0)
-        {
-            msg_Dbg (p_access, "destination: %s port %d", addr, port);
-            var_SetString (p_access, "dst-addr", addr);
-            var_SetInteger (p_access, "dst-port", port);
-        }
-    }
-    shutdown( i_handle, SHUT_RD );
-
-    p_sys->i_caching = VLC_TICK_FROM_MS(
-                     var_GetInteger( p_access, SOUT_CFG_PREFIX "caching") );
-    p_sys->i_handle = i_handle;
-    p_sys->i_mtu = var_CreateGetInteger( p_this, "mtu" );
-    p_sys->b_mtu_warning = false;
-    p_sys->dead = false;
-    vlc_queue_Init(&p_sys->queue, offsetof (block_t, p_next));
-    p_sys->p_buffer = NULL;
-
-    if( vlc_clone( &p_sys->thread, ThreadWrite, p_access,
-                           VLC_THREAD_PRIORITY_HIGHEST ) )
-    {
-        msg_Err( p_access, "cannot spawn sout access thread" );
-        net_Close (i_handle);
-        free (p_sys);
-        return VLC_EGENERIC;
-    }
-
-    p_access->pf_write = Write;
-    p_access->pf_control = Control;
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Close: close the target
- *****************************************************************************/
-static void Close( vlc_object_t * p_this )
-{
-    sout_access_out_t     *p_access = (sout_access_out_t*)p_this;
-    sout_access_out_sys_t *p_sys = p_access->p_sys;
-
-    vlc_queue_Kill(&p_sys->queue, &p_sys->dead);
-    vlc_join( p_sys->thread, NULL );
-
-    if( p_sys->p_buffer ) block_Release( p_sys->p_buffer );
-
-    net_Close( p_sys->i_handle );
-    free( p_sys );
-}
-
-static int Control( sout_access_out_t *p_access, int i_query, va_list args )
-{
-    (void)p_access;
-
-    switch( i_query )
-    {
-        case ACCESS_OUT_CONTROLS_PACE:
-            *va_arg( args, bool * ) = false;
-            break;
-
-        default:
-            return VLC_EGENERIC;
-    }
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Write: standard write on a file descriptor.
- *****************************************************************************/
-static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer )
-{
-    sout_access_out_sys_t *p_sys = p_access->p_sys;
-    int i_len = 0;
-
-    while( p_buffer )
-    {
-        block_t *p_next;
-        int i_packets = 0;
-        vlc_tick_t now = vlc_tick_now();
-
-        if( !p_sys->b_mtu_warning && p_buffer->i_buffer > p_sys->i_mtu )
-        {
-            msg_Warn( p_access, "packet size > MTU, you should probably "
-                      "increase the MTU" );
-            p_sys->b_mtu_warning = true;
-        }
-
-        /* Check if there is enough space in the buffer */
-        if( p_sys->p_buffer &&
-            p_sys->p_buffer->i_buffer + p_buffer->i_buffer > p_sys->i_mtu )
-        {
-            if( p_sys->p_buffer->i_dts + p_sys->i_caching < now )
-            {
-                msg_Dbg( p_access, "late packet for UDP input (%"PRId64 ")",
-                         now - p_sys->p_buffer->i_dts
-                          - p_sys->i_caching );
-            }
-            vlc_queue_Enqueue(&p_sys->queue, p_sys->p_buffer);
-            p_sys->p_buffer = NULL;
-        }
-
-        i_len += p_buffer->i_buffer;
-        while( p_buffer->i_buffer )
-        {
-            size_t i_payload_size = p_sys->i_mtu;
-            size_t i_write = __MIN( p_buffer->i_buffer, i_payload_size );
-
-            i_packets++;
-
-            if( !p_sys->p_buffer )
-            {
-                p_sys->p_buffer = block_Alloc( p_sys->i_mtu );
-                if( !p_sys->p_buffer ) break;
-                p_sys->p_buffer->i_dts = p_buffer->i_dts;
-                p_sys->p_buffer->i_buffer = 0;
-            }
-
-            memcpy( p_sys->p_buffer->p_buffer + p_sys->p_buffer->i_buffer,
-                    p_buffer->p_buffer, i_write );
-
-            p_sys->p_buffer->i_buffer += i_write;
-            p_buffer->p_buffer += i_write;
-            p_buffer->i_buffer -= i_write;
-            if ( p_buffer->i_flags & BLOCK_FLAG_CLOCK )
-            {
-                if ( p_sys->p_buffer->i_flags & BLOCK_FLAG_CLOCK )
-                    msg_Warn( p_access, "putting two PCRs at once" );
-                p_sys->p_buffer->i_flags |= BLOCK_FLAG_CLOCK;
-            }
-
-            if( p_sys->p_buffer->i_buffer == p_sys->i_mtu || i_packets > 1 )
-            {
-                /* Flush */
-                if( p_sys->p_buffer->i_dts + p_sys->i_caching < now )
-                {
-                    msg_Dbg( p_access, "late packet for udp input (%"PRId64 ")",
-                             vlc_tick_now() - p_sys->p_buffer->i_dts
-                              - p_sys->i_caching );
-                }
-                vlc_queue_Enqueue(&p_sys->queue, p_sys->p_buffer);
-                p_sys->p_buffer = NULL;
-            }
-        }
-
-        p_next = p_buffer->p_next;
-        block_Release( p_buffer );
-        p_buffer = p_next;
-    }
-
-    return i_len;
-}
-
-/*****************************************************************************
- * ThreadWrite: Write a packet on the network at the good time.
- *****************************************************************************/
-static void* ThreadWrite( void *data )
-{
-    sout_access_out_t *p_access = data;
-    sout_access_out_sys_t *p_sys = p_access->p_sys;
-    vlc_tick_t i_date_last = -1;
-    const unsigned i_group = var_GetInteger( p_access,
-                                             SOUT_CFG_PREFIX "group" );
-    int i_to_send = i_group;
-    unsigned i_dropped_packets = 0;
-    block_t *p_pk;
-
-    while ((p_pk = vlc_queue_DequeueKillable(&p_sys->queue,
-                                             &p_sys->dead)) != NULL)
-    {
-        vlc_tick_t    i_date;
-
-        i_date = p_sys->i_caching + p_pk->i_dts;
-        if( i_date_last > 0 )
-        {
-            if( i_date - i_date_last > VLC_TICK_FROM_SEC(2) )
-            {
-                if( !i_dropped_packets )
-                    msg_Dbg( p_access, "mmh, hole (%"PRId64" > 2s) -> drop",
-                             i_date - i_date_last );
-
-                block_Release( p_pk );
-
-                i_date_last = i_date;
-                i_dropped_packets++;
-                continue;
-            }
-            else if( i_date - i_date_last < VLC_TICK_FROM_MS(-1) )
-            {
-                if( !i_dropped_packets )
-                    msg_Dbg( p_access, "mmh, packets in the past (%"PRId64")",
-                             i_date_last - i_date );
-            }
-        }
-
-        i_to_send--;
-        if( !i_to_send || (p_pk->i_flags & BLOCK_FLAG_CLOCK) )
-        {
-            vlc_tick_wait( i_date );
-            i_to_send = i_group;
-        }
-        if ( send( p_sys->i_handle, p_pk->p_buffer, p_pk->i_buffer, 0 ) == -1 )
-            msg_Warn( p_access, "send error: %s", vlc_strerror_c(errno) );
-
-        if( i_dropped_packets )
-        {
-            msg_Dbg( p_access, "dropped %i packets", i_dropped_packets );
-            i_dropped_packets = 0;
-        }
-
-        i_date_last = i_date;
-
-#if 1
-        i_date = vlc_tick_now() - i_date;
-        if ( i_date > VLC_TICK_FROM_MS(20) )
-        {
-            msg_Dbg( p_access, "packet has been sent too late (%"PRId64 ")",
-                     i_date );
-        }
-#endif
-
-        block_Release( p_pk );
-
-    }
-    return NULL;
-}


=====================================
modules/stream_out/Makefile.am
=====================================
@@ -4,10 +4,8 @@ libstream_out_dummy_plugin_la_SOURCES = stream_out/dummy.c
 libstream_out_cycle_plugin_la_SOURCES = stream_out/cycle.c
 libstream_out_delay_plugin_la_SOURCES = stream_out/delay.c
 libstream_out_stats_plugin_la_SOURCES = stream_out/stats.c
-libstream_out_standard_plugin_la_SOURCES = stream_out/standard.c \
-	stream_out/sdp_helper.c stream_out/sdp_helper.h
+libstream_out_standard_plugin_la_SOURCES = stream_out/standard.c
 libstream_out_standard_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS_access_output_srt)
-libstream_out_standard_plugin_la_LIBADD = $(SOCKET_LIBS)
 libstream_out_duplicate_plugin_la_SOURCES = stream_out/duplicate.c
 libstream_out_es_plugin_la_SOURCES = stream_out/es.c
 libstream_out_display_plugin_la_SOURCES = stream_out/display.c
@@ -30,6 +28,10 @@ libstream_out_transcode_plugin_la_SOURCES = \
 	stream_out/transcode/audio.c stream_out/transcode/video.c
 libstream_out_transcode_plugin_la_CFLAGS = $(AM_CFLAGS)
 libstream_out_transcode_plugin_la_LIBADD = $(LIBM)
+libstream_out_udp_plugin_la_SOURCES = \
+	stream_out/sdp_helper.c stream_out/sdp_helper.h \
+	stream_out/udp.c
+libstream_out_udp_plugin_la_LIBADD = $(SOCKET_LIBS)
 
 sout_LTLIBRARIES = \
 	libstream_out_dummy_plugin.la \
@@ -47,7 +49,8 @@ sout_LTLIBRARIES = \
 	libstream_out_record_plugin.la \
 	libstream_out_smem_plugin.la \
 	libstream_out_setid_plugin.la \
-	libstream_out_transcode_plugin.la
+	libstream_out_transcode_plugin.la \
+	libstream_out_udp_plugin.la
 
 if HAVE_DECKLINK
 libstream_out_sdi_plugin_la_CXXFLAGS = $(AM_CXXFLAGS) $(CPPFLAGS_decklinkoutput)


=====================================
modules/stream_out/standard.c
=====================================
@@ -33,8 +33,6 @@
 
 #include <vlc_network.h>
 #include <vlc_url.h>
-#include <vlc_memstream.h>
-#include "sdp_helper.h"
 
 /*****************************************************************************
  * Module descriptor
@@ -56,16 +54,6 @@
 #define PATH_LONGTEXT N_( \
   "Filename for stream. "\
   "Helper setting for dst, dst=bind+'/'+path. dst-parameter overrides this." )
-#define NAME_TEXT N_("Session name")
-#define NAME_LONGTEXT N_( \
-    "This is the name of the session that will be announced in the SDP " \
-    "(Session Descriptor)." )
-#define DESC_TEXT N_("Session description")
-#define DESC_LONGTEXT N_( \
-    "This allows you to give a short description with details about the stream, " \
-    "that will be announced in the SDP (Session Descriptor)." )
-#define SAP_TEXT N_("SAP announcing")
-#define SAP_LONGTEXT N_("Announce this session with SAP.")
 
 static int      Open    ( vlc_object_t * );
 static void     Close   ( vlc_object_t * );
@@ -82,7 +70,7 @@ vlc_module_begin ()
     set_shortname( N_("Standard"))
     set_description( N_("Standard stream output") )
     set_capability( "sout output", 50 )
-    add_shortcut( "standard", "std", "file", "http", "udp", SRT_SHORTCUT )
+    add_shortcut( "standard", "std", "file", "http", SRT_SHORTCUT )
     set_category( CAT_SOUT )
     set_subcategory( SUBCAT_SOUT_STREAM )
 
@@ -91,9 +79,9 @@ vlc_module_begin ()
     add_string( SOUT_CFG_PREFIX "dst", "", DEST_TEXT, DEST_LONGTEXT )
     add_string( SOUT_CFG_PREFIX "bind", "", BIND_TEXT, BIND_LONGTEXT )
     add_string( SOUT_CFG_PREFIX "path", "", PATH_TEXT, PATH_LONGTEXT )
-    add_bool(   SOUT_CFG_PREFIX "sap", false, SAP_TEXT, SAP_LONGTEXT )
-    add_string( SOUT_CFG_PREFIX "name", "", NAME_TEXT, NAME_LONGTEXT )
-    add_string( SOUT_CFG_PREFIX "description", "", DESC_TEXT, DESC_LONGTEXT )
+    add_obsolete_bool( SOUT_CFG_PREFIX "sap" ) /* since 4.0.0 */
+    add_obsolete_string( SOUT_CFG_PREFIX "name" ) /* since 4.0.0 */
+    add_obsolete_string( SOUT_CFG_PREFIX "description" ) /* since 4.0.0 */
     add_obsolete_string( SOUT_CFG_PREFIX "url" ) /* since 4.0.0 */
     add_obsolete_string( SOUT_CFG_PREFIX "email" ) /* since 4.0.0 */
     add_obsolete_string( SOUT_CFG_PREFIX "phone" ) /* since 3.0.0 */
@@ -107,12 +95,9 @@ vlc_module_end ()
  *****************************************************************************/
 static const char *const ppsz_sout_options[] = {
     "access", "mux", "url", "dst",
-    "sap", "name", "description",
     "bind", "path", NULL
 };
 
-#define DEFAULT_PORT 1234
-
 typedef struct
 {
     sout_mux_t           *p_mux;
@@ -144,57 +129,6 @@ static void Flush( sout_stream_t *p_stream, void *id )
     sout_MuxFlush( p_sys->p_mux, (sout_input_t*)id );
 }
 
-static void create_SDP(sout_stream_t *p_stream, sout_access_out_t *p_access)
-{
-    sout_stream_sys_t   *p_sys = p_stream->p_sys;
-
-    static const struct addrinfo hints = {
-        .ai_family = AF_UNSPEC,
-        .ai_socktype = SOCK_DGRAM,
-        .ai_protocol = 0,
-        .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_IDN,
-    };
-    char *shost = var_GetNonEmptyString (p_access, "src-addr");
-    char *dhost = var_GetNonEmptyString (p_access, "dst-addr");
-    int sport = var_GetInteger (p_access, "src-port");
-    int dport = var_GetInteger (p_access, "dst-port");
-    struct sockaddr_storage src, dst;
-    socklen_t srclen = 0, dstlen = 0;
-    struct addrinfo *res;
-
-    if (!vlc_getaddrinfo (dhost, dport, &hints, &res))
-    {
-        memcpy (&dst, res->ai_addr, dstlen = res->ai_addrlen);
-        freeaddrinfo (res);
-    }
-
-    if (!vlc_getaddrinfo (shost, sport, &hints, &res))
-    {
-        memcpy (&src, res->ai_addr, srclen = res->ai_addrlen);
-        freeaddrinfo (res);
-    }
-
-    struct vlc_memstream sdp;
-
-    if (vlc_sdp_Start(&sdp, VLC_OBJECT (p_stream), SOUT_CFG_PREFIX,
-                      (struct sockaddr *)&src, srclen,
-                      (struct sockaddr *)&dst, dstlen) == 0)
-    {
-        vlc_memstream_printf(&sdp, "m=video %d udp mpeg\r\n", dport);
-
-        /* Register the SDP with the SAP thread */
-        if (vlc_memstream_close(&sdp) == 0)
-        {
-            msg_Dbg(p_stream, "Generated SDP:\n%s", sdp.ptr);
-            p_sys->p_session =
-                sout_AnnounceRegisterSDP(p_stream, sdp.ptr, dhost);
-            free(sdp.ptr);
-        }
-    }
-    free(shost);
-    free(dhost);
-}
-
 static const char *getMuxFromAlias( const char *psz_alias )
 {
     static struct { const char alias[6]; const char mux[32]; } mux_alias[] =
@@ -263,8 +197,6 @@ static int fixAccessMux( sout_stream_t *p_stream, char **ppsz_mux,
         {
             if( !strncmp( psz_access, "mmsh", 4 ) )
                 *ppsz_mux = strdup("asfh");
-            else if (!strcmp (psz_access, "udp"))
-                *ppsz_mux = strdup("ts");
             else if( psz_mux_byext )
                 *ppsz_mux = strdup(psz_mux_byext);
             else
@@ -301,18 +233,6 @@ static void checkAccessMux( sout_stream_t *p_stream, char *psz_access,
     else if( !exactMatch( psz_access, "file", 4 ) &&
              ( exactMatch( psz_mux, "mov", 3 ) || exactMatch( psz_mux, "mp4", 3 ) ) )
         msg_Err( p_stream, "mov and mp4 mux are only valid with file output" );
-    else if( exactMatch( psz_access, "udp", 3 ) )
-    {
-        if( exactMatch( psz_mux, "ffmpeg", 6 ) || exactMatch( psz_mux, "avformat", 8 ) )
-        {   /* why would you use ffmpeg's ts muxer ? YOU DON'T LOVE VLC ??? */
-            char *psz_ffmpeg_mux = var_CreateGetString( p_stream, "sout-avformat-mux" );
-            if( !psz_ffmpeg_mux || strncmp( psz_ffmpeg_mux, "mpegts", 6 ) )
-                msg_Err( p_stream, "UDP output is only valid with TS mux" );
-            free( psz_ffmpeg_mux );
-        }
-        else if( !exactMatch( psz_mux, "ts", 2 ) )
-            msg_Err( p_stream, "UDP output is only valid with TS mux" );
-    }
 }
 
 static int Control(sout_stream_t *stream, int query, va_list args)
@@ -418,9 +338,6 @@ static int Open( vlc_object_t *p_this )
         }
     }
 
-    if( var_GetBool( p_stream, SOUT_CFG_PREFIX"sap" ) )
-        create_SDP( p_stream, p_access );
-
     p_stream->ops = &ops;
     ret = VLC_SUCCESS;
     msg_Dbg( p_this, "using `%s/%s://%s'", psz_access, psz_mux, psz_url );


=====================================
modules/stream_out/udp.c
=====================================
@@ -0,0 +1,365 @@
+/*****************************************************************************
+ * udp.c: standard stream output module
+ *****************************************************************************
+ * Copyright (C) 2003-2011 VLC authors and VideoLAN
+ *
+ * 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.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include <vlc_common.h>
+#include <vlc_block.h>
+#include <vlc_plugin.h>
+#include <vlc_sout.h>
+
+#include <vlc_network.h>
+#include <vlc_memstream.h>
+#include "sdp_helper.h"
+
+struct sout_stream_udp
+{
+    sout_access_out_t *access;
+    sout_mux_t *mux;
+    session_descriptor_t *sap;
+    int fd;
+    uint_fast16_t mtu;
+};
+
+static void *Add(sout_stream_t *stream, const es_format_t *fmt)
+{
+    struct sout_stream_udp *sys = stream->p_sys;
+
+    return sout_MuxAddStream(sys->mux, fmt);
+}
+
+static void Del(sout_stream_t *stream, void *id)
+{
+    struct sout_stream_udp *sys = stream->p_sys;
+
+    sout_MuxDeleteStream(sys->mux, id);
+}
+
+static int Send(sout_stream_t *stream, void *id, block_t *block)
+{
+    struct sout_stream_udp *sys = stream->p_sys;
+
+    return sout_MuxSendBuffer(sys->mux, id, block);
+}
+
+static void Flush(sout_stream_t *stream, void *id)
+{
+    struct sout_stream_udp *sys = stream->p_sys;
+
+    sout_MuxFlush(sys->mux, id);
+}
+
+#define SOUT_CFG_PREFIX "sout-udp-"
+
+static session_descriptor_t *CreateSDP(vlc_object_t *obj, int fd)
+{
+    union {
+        struct sockaddr addr;
+        struct sockaddr_in in;
+        struct sockaddr_in6 in6;
+    } src, dst;
+    socklen_t srclen = sizeof (srclen), dstlen = sizeof (dst);
+    char dhost[INET6_ADDRSTRLEN];
+    unsigned short dport;
+
+    if (getsockname(fd, &src.addr, &srclen)
+     || getpeername(fd, &dst.addr, &dstlen)) {
+        int val = errno;
+
+        msg_Err(obj, "cannot format SDP: %s", vlc_strerror_c(val));
+        return NULL;
+    }
+
+    switch (dst.addr.sa_family) {
+        case AF_INET:
+            inet_ntop(AF_INET, &dst.in.sin_addr, dhost, sizeof (dhost));
+            dport = dst.in.sin_port;
+            break;
+        case AF_INET6:
+            inet_ntop(AF_INET6, &dst.in6.sin6_addr, dhost, sizeof (dhost));
+            dport = dst.in6.sin6_port;
+            break;
+        default:
+            return NULL;
+    }
+
+    struct vlc_memstream sdp;
+
+    if (vlc_sdp_Start(&sdp, obj, SOUT_CFG_PREFIX,
+                      &src.addr, srclen, &dst.addr, dstlen))
+        return NULL;
+
+    vlc_memstream_printf(&sdp, "m=video %d udp mpeg\r\n", ntohs(dport));
+
+    if (vlc_memstream_close(&sdp) != 0)
+        return NULL;
+
+    /* Register the SDP with the SAP thread */
+    session_descriptor_t *session;
+
+    msg_Dbg(obj, "Generated SDP:\n%s", sdp.ptr);
+    session = sout_AnnounceRegisterSDP(obj, sdp.ptr, dhost);
+    free(sdp.ptr);
+    return session;
+}
+
+static int Control(sout_stream_t *stream, int query, va_list args)
+{
+    switch (query) {
+        case SOUT_STREAM_IS_SYNCHRONOUS:
+            *va_arg(args, bool *) = true;
+            break;
+
+        default:
+            return VLC_EGENERIC;
+    }
+
+    (void) stream;
+    return VLC_SUCCESS;
+}
+
+static ssize_t AccessOutWrite(sout_access_out_t *access, block_t *block)
+{
+    struct sout_stream_udp *sys = access->p_sys;
+    ssize_t total = 0;
+
+    while (block != NULL) {
+        struct iovec iov[16];
+        block_t *unsent = block;
+        unsigned iovlen = 0;
+        size_t tosend = 0;
+
+        /* Count how many blocks to gather */
+        do {
+            if (iovlen >= ARRAY_SIZE(iov))
+                break;
+            if (unsent->i_buffer + tosend > sys->mtu && likely(iovlen > 0))
+                break;
+
+            iov[iovlen].iov_base = unsent->p_buffer;
+            iov[iovlen].iov_len = unsent->i_buffer;
+            iovlen++;
+            tosend += unsent->i_buffer;
+            unsent = unsent->p_next;
+        } while (unsent != NULL);
+
+        /* Send */
+        struct msghdr hdr = { .msg_iov = iov, .msg_iovlen = iovlen };
+        int val = sendmsg(sys->fd, &hdr, 0);
+
+        if (val < 0)
+            msg_Err(access, "send error: %s", vlc_strerror_c(errno));
+        else
+            total += val;
+
+        /* Free */
+        do {
+            block_t *next = block->p_next;
+
+            block_Release(block);
+            block = next;
+        } while (block != unsent);
+    }
+
+    return total;
+}
+
+static void Close(vlc_object_t *obj)
+{
+    sout_stream_t *stream = (sout_stream_t *)obj;
+    struct sout_stream_udp *sys = stream->p_sys;
+
+    if (sys->sap != NULL)
+        sout_AnnounceUnRegister(stream, sys->sap);
+
+    sout_MuxDelete(sys->mux);
+    sout_AccessOutDelete(sys->access);
+    net_Close(sys->fd);
+    free(sys);
+}
+
+static const struct sout_stream_operations ops = {
+    Add, Del, Send, Control, Flush,
+};
+
+static const char *const chain_options[] = {
+    "avformat", "dst", "sap", "name", "description", NULL
+};
+
+#define DEFAULT_PORT 1234
+
+static int Open(vlc_object_t *obj)
+{
+    sout_stream_t *stream = (sout_stream_t *)obj;
+    sout_access_out_t *access = NULL;
+    const char *muxmod = "ts";
+    int ret;
+
+    /* --sout '#std{...}' option backward compatibility */
+    if (strcmp(stream->psz_name, "std") == 0
+     || strcmp(stream->psz_name, "standard") == 0) {
+        config_chain_t *c = NULL;
+
+        for (c = stream->p_cfg; c != NULL; c = c->p_next)
+             if (strcmp(c->psz_name, "access") == 0)
+                 break;
+
+        if (c == NULL) /* default is file, not for us */
+            return VLC_ENOTSUP;
+        if (strcmp(c->psz_value, "udp"))
+            return VLC_ENOTSUP;
+
+        msg_Info(stream, "\"#standard{access=udp,mux=ts,...}\" is deprecated. "
+                 "Use \"#udp{...}\" instead.");
+    }
+
+    config_ChainParse(stream, SOUT_CFG_PREFIX, chain_options, stream->p_cfg);
+
+    char *dst = var_GetNonEmptyString(stream, SOUT_CFG_PREFIX "dst");
+    if (dst == NULL) {
+        msg_Err(stream, "missing required destination");
+        return VLC_EINVAL;
+    }
+
+    const char *dhost;
+    char *end;
+    int dport = DEFAULT_PORT;
+
+    if (dst[0] == '[') {
+        dhost = dst;
+        end = strchr(dst, ']');
+
+        if (end != NULL)
+            *(end++) = '\0';
+    } else {
+        dhost = dst;
+        end = strchr(dst, ':');
+    }
+
+    if (end != NULL && *end == ':') {
+        *(end++) = '\0';
+        dport = atoi(&end[1]);
+    }
+
+    int fd = net_ConnectDgram(stream, dhost, dport, -1, IPPROTO_UDP);
+    free(dst);
+    if (fd == -1) {
+        int val = errno;
+
+        msg_Err(stream, "cannot reach destination: %s", vlc_strerror_c(val));
+        return val ? -val : VLC_EGENERIC;
+    }
+
+    if (var_GetBool(stream, SOUT_CFG_PREFIX "avformat")
+     && var_Create(stream, "sout-avformat-mux",
+                   VLC_VAR_STRING) == VLC_SUCCESS) {
+        var_SetString(stream, "sout-avformat-mux", "mpegts");
+        muxmod = "avformat";
+    }
+
+    struct sout_stream_udp *sys = malloc(sizeof (*sys));
+    if (unlikely(sys == NULL)) {
+        ret = VLC_ENOMEM;
+        goto error;
+    }
+
+    access = vlc_object_create(stream, sizeof (*access));
+    if (unlikely(access == NULL)) {
+        ret = VLC_ENOMEM;
+        goto error;
+    }
+
+    access->p_module = NULL;
+    access->psz_access = strdup("udp");
+    access->psz_path = NULL;
+    access->p_sys = sys;
+    access->pf_seek = NULL;
+    access->pf_read = NULL;
+    access->pf_write = AccessOutWrite;
+    access->pf_control = NULL;
+    access->p_cfg = NULL;
+    sys->access = access;
+    sys->fd = fd;
+    sys->mtu = var_InheritInteger(stream, "mtu");
+
+    sout_mux_t *mux = sout_MuxNew(access, muxmod);
+    if (mux == NULL) {
+        ret = VLC_ENOTSUP;
+        goto error;
+    }
+    sys->mux = mux;
+
+    if (var_GetBool(stream, SOUT_CFG_PREFIX "sap"))
+        sys->sap = CreateSDP(VLC_OBJECT(stream), fd);
+    else
+        sys->sap = NULL;
+
+    stream->p_sys = sys;
+    stream->ops = &ops;
+    return VLC_SUCCESS;
+
+error:
+    if (access != NULL)
+        sout_AccessOutDelete(access);
+    free(sys);
+    net_Close(fd);
+    return ret;
+}
+
+#define AVF_TEXT N_("Use libavformat")
+#define AVF_LONGTEXT N_("Use libavformat instead of dvbpsi to mux MPEG TS.")
+#define DEST_TEXT N_("Destination")
+#define DEST_LONGTEXT N_( \
+    "Destination address and port (colon-separated) for the stream.")
+#define SAP_TEXT N_("SAP announcement")
+#define SAP_LONGTEXT N_("Announce this stream as a session with SAP.")
+#define NAME_TEXT N_("SAP name")
+#define NAME_LONGTEXT N_( \
+    "Name of the stream that will be announced with SAP.")
+#define DESC_TEXT N_("SAP description")
+#define DESC_LONGTEXT N_( \
+    "Short description of the stream that will be announced with SAP.")
+
+vlc_module_begin()
+    set_shortname(N_("UDP"))
+    set_description(N_("UDP stream output"))
+    set_capability("sout output", 40)
+    add_shortcut("standard", "std", "udp")
+    set_category(CAT_SOUT)
+    set_subcategory(SUBCAT_SOUT_STREAM)
+
+    add_bool(SOUT_CFG_PREFIX "avformat", false, AVF_TEXT, AVF_LONGTEXT)
+    add_string(SOUT_CFG_PREFIX "dst", "", DEST_TEXT, DEST_LONGTEXT)
+    add_bool(SOUT_CFG_PREFIX "sap", false, SAP_TEXT, SAP_LONGTEXT)
+    add_string(SOUT_CFG_PREFIX "name", "", NAME_TEXT, NAME_LONGTEXT)
+    add_string(SOUT_CFG_PREFIX "description", "", DESC_TEXT, DESC_LONGTEXT)
+
+    set_callbacks(Open, Close)
+vlc_module_end()


=====================================
po/POTFILES.in
=====================================
@@ -221,7 +221,6 @@ modules/access_output/livehttp.c
 modules/access_output/rist.c
 modules/access_output/shout.c
 modules/access_output/srt.c
-modules/access_output/udp.c
 modules/arm_neon/chroma_yuv.c
 modules/arm_neon/volume.c
 modules/arm_neon/yuv_rgb.c
@@ -1257,6 +1256,7 @@ modules/stream_out/smem.c
 modules/stream_out/stats.c
 modules/stream_out/standard.c
 modules/stream_out/transcode/transcode.c
+modules/stream_out/udp.c
 modules/text_renderer/freetype/fonts/fontconfig.c
 modules/text_renderer/freetype/freetype.c
 modules/text_renderer/nsspeechsynthesizer.m



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/82347d93d526df00c1ebf73805534b7f4081859a...c142d02bb4e37c58e07bda80fb4edd720c2b85e6

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/82347d93d526df00c1ebf73805534b7f4081859a...c142d02bb4e37c58e07bda80fb4edd720c2b85e6
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list