rtp.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:57k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * rtp.c: rtp stream output module
  3.  *****************************************************************************
  4.  * Copyright (C) 2003-2004 the VideoLAN team
  5.  * Copyright © 2007-2008 Rémi Denis-Courmont
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <vlc_plugin.h>
  31. #include <vlc_sout.h>
  32. #include <vlc_block.h>
  33. #include <vlc_httpd.h>
  34. #include <vlc_url.h>
  35. #include <vlc_network.h>
  36. #include <vlc_charset.h>
  37. #include <vlc_strings.h>
  38. #include <vlc_rand.h>
  39. #include <srtp.h>
  40. #include "rtp.h"
  41. #ifdef HAVE_UNISTD_H
  42. #   include <sys/types.h>
  43. #   include <unistd.h>
  44. #   include <fcntl.h>
  45. #   include <sys/stat.h>
  46. #endif
  47. #ifdef HAVE_LINUX_DCCP_H
  48. #   include <linux/dccp.h>
  49. #endif
  50. #ifndef IPPROTO_DCCP
  51. # define IPPROTO_DCCP 33
  52. #endif
  53. #ifndef IPPROTO_UDPLITE
  54. # define IPPROTO_UDPLITE 136
  55. #endif
  56. #include <errno.h>
  57. #include <assert.h>
  58. /*****************************************************************************
  59.  * Module descriptor
  60.  *****************************************************************************/
  61. #define DEST_TEXT N_("Destination")
  62. #define DEST_LONGTEXT N_( 
  63.     "This is the output URL that will be used." )
  64. #define SDP_TEXT N_("SDP")
  65. #define SDP_LONGTEXT N_( 
  66.     "This allows you to specify how the SDP (Session Descriptor) for this RTP "
  67.     "session will be made available. You must use an url: http://location to " 
  68.     "access the SDP via HTTP, rtsp://location for RTSP access, and sap:// " 
  69.     "for the SDP to be announced via SAP." )
  70. #define SAP_TEXT N_("SAP announcing")
  71. #define SAP_LONGTEXT N_("Announce this session with SAP.")
  72. #define MUX_TEXT N_("Muxer")
  73. #define MUX_LONGTEXT N_( 
  74.     "This allows you to specify the muxer used for the streaming output. " 
  75.     "Default is to use no muxer (standard RTP stream)." )
  76. #define NAME_TEXT N_("Session name")
  77. #define NAME_LONGTEXT N_( 
  78.     "This is the name of the session that will be announced in the SDP " 
  79.     "(Session Descriptor)." )
  80. #define DESC_TEXT N_("Session description")
  81. #define DESC_LONGTEXT N_( 
  82.     "This allows you to give a short description with details about the stream, " 
  83.     "that will be announced in the SDP (Session Descriptor)." )
  84. #define URL_TEXT N_("Session URL")
  85. #define URL_LONGTEXT N_( 
  86.     "This allows you to give an URL with more details about the stream " 
  87.     "(often the website of the streaming organization), that will " 
  88.     "be announced in the SDP (Session Descriptor)." )
  89. #define EMAIL_TEXT N_("Session email")
  90. #define EMAIL_LONGTEXT N_( 
  91.     "This allows you to give a contact mail address for the stream, that will " 
  92.     "be announced in the SDP (Session Descriptor)." )
  93. #define PHONE_TEXT N_("Session phone number")
  94. #define PHONE_LONGTEXT N_( 
  95.     "This allows you to give a contact telephone number for the stream, that will " 
  96.     "be announced in the SDP (Session Descriptor)." )
  97. #define PORT_TEXT N_("Port")
  98. #define PORT_LONGTEXT N_( 
  99.     "This allows you to specify the base port for the RTP streaming." )
  100. #define PORT_AUDIO_TEXT N_("Audio port")
  101. #define PORT_AUDIO_LONGTEXT N_( 
  102.     "This allows you to specify the default audio port for the RTP streaming." )
  103. #define PORT_VIDEO_TEXT N_("Video port")
  104. #define PORT_VIDEO_LONGTEXT N_( 
  105.     "This allows you to specify the default video port for the RTP streaming." )
  106. #define TTL_TEXT N_("Hop limit (TTL)")
  107. #define TTL_LONGTEXT N_( 
  108.     "This is the hop limit (also known as "Time-To-Live" or TTL) of " 
  109.     "the multicast packets sent by the stream output (-1 = use operating " 
  110.     "system built-in default).")
  111. #define RTCP_MUX_TEXT N_("RTP/RTCP multiplexing")
  112. #define RTCP_MUX_LONGTEXT N_( 
  113.     "This sends and receives RTCP packet multiplexed over the same port " 
  114.     "as RTP packets." )
  115. #define PROTO_TEXT N_("Transport protocol")
  116. #define PROTO_LONGTEXT N_( 
  117.     "This selects which transport protocol to use for RTP." )
  118. #define SRTP_KEY_TEXT N_("SRTP key (hexadecimal)")
  119. #define SRTP_KEY_LONGTEXT N_( 
  120.     "RTP packets will be integrity-protected and ciphered "
  121.     "with this Secure RTP master shared secret key.")
  122. #define SRTP_SALT_TEXT N_("SRTP salt (hexadecimal)")
  123. #define SRTP_SALT_LONGTEXT N_( 
  124.     "Secure RTP requires a (non-secret) master salt value.")
  125. static const char *const ppsz_protos[] = {
  126.     "dccp", "sctp", "tcp", "udp", "udplite",
  127. };
  128. static const char *const ppsz_protocols[] = {
  129.     "DCCP", "SCTP", "TCP", "UDP", "UDP-Lite",
  130. };
  131. #define RFC3016_TEXT N_("MP4A LATM")
  132. #define RFC3016_LONGTEXT N_( 
  133.     "This allows you to stream MPEG4 LATM audio streams (see RFC3016)." )
  134. static int  Open ( vlc_object_t * );
  135. static void Close( vlc_object_t * );
  136. #define SOUT_CFG_PREFIX "sout-rtp-"
  137. #define MAX_EMPTY_BLOCKS 200
  138. vlc_module_begin ()
  139.     set_shortname( N_("RTP"))
  140.     set_description( N_("RTP stream output") )
  141.     set_capability( "sout stream", 0 )
  142.     add_shortcut( "rtp" )
  143.     set_category( CAT_SOUT )
  144.     set_subcategory( SUBCAT_SOUT_STREAM )
  145.     add_string( SOUT_CFG_PREFIX "dst", "", NULL, DEST_TEXT,
  146.                 DEST_LONGTEXT, true )
  147.     add_string( SOUT_CFG_PREFIX "sdp", "", NULL, SDP_TEXT,
  148.                 SDP_LONGTEXT, true )
  149.     add_string( SOUT_CFG_PREFIX "mux", "", NULL, MUX_TEXT,
  150.                 MUX_LONGTEXT, true )
  151.     add_bool( SOUT_CFG_PREFIX "sap", false, NULL, SAP_TEXT, SAP_LONGTEXT,
  152.               true )
  153.     add_string( SOUT_CFG_PREFIX "name", "", NULL, NAME_TEXT,
  154.                 NAME_LONGTEXT, true )
  155.     add_string( SOUT_CFG_PREFIX "description", "", NULL, DESC_TEXT,
  156.                 DESC_LONGTEXT, true )
  157.     add_string( SOUT_CFG_PREFIX "url", "", NULL, URL_TEXT,
  158.                 URL_LONGTEXT, true )
  159.     add_string( SOUT_CFG_PREFIX "email", "", NULL, EMAIL_TEXT,
  160.                 EMAIL_LONGTEXT, true )
  161.     add_string( SOUT_CFG_PREFIX "phone", "", NULL, PHONE_TEXT,
  162.                 PHONE_LONGTEXT, true )
  163.     add_string( SOUT_CFG_PREFIX "proto", "udp", NULL, PROTO_TEXT,
  164.                 PROTO_LONGTEXT, false )
  165.         change_string_list( ppsz_protos, ppsz_protocols, NULL )
  166.     add_integer( SOUT_CFG_PREFIX "port", 5004, NULL, PORT_TEXT,
  167.                  PORT_LONGTEXT, true )
  168.     add_integer( SOUT_CFG_PREFIX "port-audio", 0, NULL, PORT_AUDIO_TEXT,
  169.                  PORT_AUDIO_LONGTEXT, true )
  170.     add_integer( SOUT_CFG_PREFIX "port-video", 0, NULL, PORT_VIDEO_TEXT,
  171.                  PORT_VIDEO_LONGTEXT, true )
  172.     add_integer( SOUT_CFG_PREFIX "ttl", -1, NULL, TTL_TEXT,
  173.                  TTL_LONGTEXT, true )
  174.     add_bool( SOUT_CFG_PREFIX "rtcp-mux", false, NULL,
  175.               RTCP_MUX_TEXT, RTCP_MUX_LONGTEXT, false )
  176.     add_string( SOUT_CFG_PREFIX "key", "", NULL,
  177.                 SRTP_KEY_TEXT, SRTP_KEY_LONGTEXT, false )
  178.     add_string( SOUT_CFG_PREFIX "salt", "", NULL,
  179.                 SRTP_SALT_TEXT, SRTP_SALT_LONGTEXT, false )
  180.     add_bool( SOUT_CFG_PREFIX "mp4a-latm", 0, NULL, RFC3016_TEXT,
  181.                  RFC3016_LONGTEXT, false )
  182.     set_callbacks( Open, Close )
  183. vlc_module_end ()
  184. /*****************************************************************************
  185.  * Exported prototypes
  186.  *****************************************************************************/
  187. static const char *const ppsz_sout_options[] = {
  188.     "dst", "name", "port", "port-audio", "port-video", "*sdp", "ttl", "mux",
  189.     "sap", "description", "url", "email", "phone",
  190.     "proto", "rtcp-mux", "key", "salt",
  191.     "mp4a-latm", NULL
  192. };
  193. static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
  194. static int               Del ( sout_stream_t *, sout_stream_id_t * );
  195. static int               Send( sout_stream_t *, sout_stream_id_t *,
  196.                                block_t* );
  197. static sout_stream_id_t *MuxAdd ( sout_stream_t *, es_format_t * );
  198. static int               MuxDel ( sout_stream_t *, sout_stream_id_t * );
  199. static int               MuxSend( sout_stream_t *, sout_stream_id_t *,
  200.                                   block_t* );
  201. static sout_access_out_t *GrabberCreate( sout_stream_t *p_sout );
  202. static void* ThreadSend( vlc_object_t *p_this );
  203. static void SDPHandleUrl( sout_stream_t *, const char * );
  204. static int SapSetup( sout_stream_t *p_stream );
  205. static int FileSetup( sout_stream_t *p_stream );
  206. static int HttpSetup( sout_stream_t *p_stream, const vlc_url_t * );
  207. struct sout_stream_sys_t
  208. {
  209.     /* SDP */
  210.     char    *psz_sdp;
  211.     vlc_mutex_t  lock_sdp;
  212.     /* SDP to disk */
  213.     bool b_export_sdp_file;
  214.     char *psz_sdp_file;
  215.     /* SDP via SAP */
  216.     bool b_export_sap;
  217.     session_descriptor_t *p_session;
  218.     /* SDP via HTTP */
  219.     httpd_host_t *p_httpd_host;
  220.     httpd_file_t *p_httpd_file;
  221.     /* RTSP */
  222.     rtsp_stream_t *rtsp;
  223.     /* */
  224.     char     *psz_destination;
  225.     uint32_t  payload_bitmap;
  226.     uint16_t  i_port;
  227.     uint16_t  i_port_audio;
  228.     uint16_t  i_port_video;
  229.     uint8_t   proto;
  230.     bool      rtcp_mux;
  231.     int       i_ttl:9;
  232.     bool      b_latm;
  233.     /* in case we do TS/PS over rtp */
  234.     sout_mux_t        *p_mux;
  235.     sout_access_out_t *p_grab;
  236.     block_t           *packet;
  237.     /* */
  238.     vlc_mutex_t      lock_es;
  239.     int              i_es;
  240.     sout_stream_id_t **es;
  241. };
  242. typedef int (*pf_rtp_packetizer_t)( sout_stream_id_t *, block_t * );
  243. typedef struct rtp_sink_t
  244. {
  245.     int rtp_fd;
  246.     rtcp_sender_t *rtcp;
  247. } rtp_sink_t;
  248. struct sout_stream_id_t
  249. {
  250.     VLC_COMMON_MEMBERS
  251.     sout_stream_t *p_stream;
  252.     /* rtp field */
  253.     uint32_t    i_timestamp;
  254.     uint16_t    i_sequence;
  255.     uint8_t     i_payload_type;
  256.     uint8_t     ssrc[4];
  257.     /* for sdp */
  258.     const char  *psz_enc;
  259.     char        *psz_fmtp;
  260.     int          i_clock_rate;
  261.     int          i_port;
  262.     int          i_cat;
  263.     int          i_channels;
  264.     int          i_bitrate;
  265.     /* Packetizer specific fields */
  266.     int                 i_mtu;
  267.     srtp_session_t     *srtp;
  268.     pf_rtp_packetizer_t pf_packetize;
  269.     /* Packets sinks */
  270.     vlc_mutex_t       lock_sink;
  271.     int               sinkc;
  272.     rtp_sink_t       *sinkv;
  273.     rtsp_stream_id_t *rtsp_id;
  274.     int              *listen_fd;
  275.     block_fifo_t     *p_fifo;
  276.     int64_t           i_caching;
  277. };
  278. /*****************************************************************************
  279.  * Open:
  280.  *****************************************************************************/
  281. static int Open( vlc_object_t *p_this )
  282. {
  283.     sout_stream_t       *p_stream = (sout_stream_t*)p_this;
  284.     sout_instance_t     *p_sout = p_stream->p_sout;
  285.     sout_stream_sys_t   *p_sys = NULL;
  286.     config_chain_t      *p_cfg = NULL;
  287.     char                *psz;
  288.     bool          b_rtsp = false;
  289.     config_ChainParse( p_stream, SOUT_CFG_PREFIX,
  290.                        ppsz_sout_options, p_stream->p_cfg );
  291.     p_sys = malloc( sizeof( sout_stream_sys_t ) );
  292.     if( p_sys == NULL )
  293.         return VLC_ENOMEM;
  294.     p_sys->psz_destination = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "dst" );
  295.     p_sys->i_port       = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port" );
  296.     p_sys->i_port_audio = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-audio" );
  297.     p_sys->i_port_video = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-video" );
  298.     p_sys->rtcp_mux     = var_GetBool( p_stream, SOUT_CFG_PREFIX "rtcp-mux" );
  299.     p_sys->psz_sdp_file = NULL;
  300.     if( p_sys->i_port_audio && p_sys->i_port_video == p_sys->i_port_audio )
  301.     {
  302.         msg_Err( p_stream, "audio and video RTP port must be distinct" );
  303.         free( p_sys->psz_destination );
  304.         free( p_sys );
  305.         return VLC_EGENERIC;
  306.     }
  307.     for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
  308.     {
  309.         if( !strcmp( p_cfg->psz_name, "sdp" )
  310.          && ( p_cfg->psz_value != NULL )
  311.          && !strncasecmp( p_cfg->psz_value, "rtsp:", 5 ) )
  312.         {
  313.             b_rtsp = true;
  314.             break;
  315.         }
  316.     }
  317.     if( !b_rtsp )
  318.     {
  319.         psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "sdp" );
  320.         if( psz != NULL )
  321.         {
  322.             if( !strncasecmp( psz, "rtsp:", 5 ) )
  323.                 b_rtsp = true;
  324.             free( psz );
  325.         }
  326.     }
  327.     /* Transport protocol */
  328.     p_sys->proto = IPPROTO_UDP;
  329.     psz = var_GetNonEmptyString (p_stream, SOUT_CFG_PREFIX"proto");
  330.     if ((psz == NULL) || !strcasecmp (psz, "udp"))
  331.         (void)0; /* default */
  332.     else
  333.     if (!strcasecmp (psz, "dccp"))
  334.     {
  335.         p_sys->proto = IPPROTO_DCCP;
  336.         p_sys->rtcp_mux = true; /* Force RTP/RTCP mux */
  337.     }
  338. #if 0
  339.     else
  340.     if (!strcasecmp (psz, "sctp"))
  341.     {
  342.         p_sys->proto = IPPROTO_TCP;
  343.         p_sys->rtcp_mux = true; /* Force RTP/RTCP mux */
  344.     }
  345. #endif
  346. #if 0
  347.     else
  348.     if (!strcasecmp (psz, "tcp"))
  349.     {
  350.         p_sys->proto = IPPROTO_TCP;
  351.         p_sys->rtcp_mux = true; /* Force RTP/RTCP mux */
  352.     }
  353. #endif
  354.     else
  355.     if (!strcasecmp (psz, "udplite") || !strcasecmp (psz, "udp-lite"))
  356.         p_sys->proto = IPPROTO_UDPLITE;
  357.     else
  358.         msg_Warn (p_this, "unknown or unsupported transport protocol "%s"",
  359.                   psz);
  360.     free (psz);
  361.     var_Create (p_this, "dccp-service", VLC_VAR_STRING);
  362.     if( ( p_sys->psz_destination == NULL ) && !b_rtsp )
  363.     {
  364.         msg_Err( p_stream, "missing destination and not in RTSP mode" );
  365.         free( p_sys );
  366.         return VLC_EGENERIC;
  367.     }
  368.     p_sys->i_ttl = var_GetInteger( p_stream, SOUT_CFG_PREFIX "ttl" );
  369.     if( p_sys->i_ttl == -1 )
  370.     {
  371.         /* Normally, we should let the default hop limit up to the core,
  372.          * but we have to know it to build our SDP properly, which is why
  373.          * we ask the core. FIXME: broken when neither sout-rtp-ttl nor
  374.          * ttl are set. */
  375.         p_sys->i_ttl = config_GetInt( p_stream, "ttl" );
  376.     }
  377.     p_sys->b_latm = var_GetBool( p_stream, SOUT_CFG_PREFIX "mp4a-latm" );
  378.     p_sys->payload_bitmap = 0;
  379.     p_sys->i_es = 0;
  380.     p_sys->es   = NULL;
  381.     p_sys->rtsp = NULL;
  382.     p_sys->psz_sdp = NULL;
  383.     p_sys->b_export_sap = false;
  384.     p_sys->b_export_sdp_file = false;
  385.     p_sys->p_session = NULL;
  386.     p_sys->p_httpd_host = NULL;
  387.     p_sys->p_httpd_file = NULL;
  388.     p_stream->p_sys     = p_sys;
  389.     vlc_mutex_init( &p_sys->lock_sdp );
  390.     vlc_mutex_init( &p_sys->lock_es );
  391.     psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );
  392.     if( psz != NULL )
  393.     {
  394.         sout_stream_id_t *id;
  395.         /* Check muxer type */
  396.         if( strncasecmp( psz, "ps", 2 )
  397.          && strncasecmp( psz, "mpeg1", 5 )
  398.          && strncasecmp( psz, "ts", 2 ) )
  399.         {
  400.             msg_Err( p_stream, "unsupported muxer type for RTP (only TS/PS)" );
  401.             free( psz );
  402.             vlc_mutex_destroy( &p_sys->lock_sdp );
  403.             vlc_mutex_destroy( &p_sys->lock_es );
  404.             free( p_sys->psz_destination );
  405.             free( p_sys );
  406.             return VLC_EGENERIC;
  407.         }
  408.         p_sys->p_grab = GrabberCreate( p_stream );
  409.         p_sys->p_mux = sout_MuxNew( p_sout, psz, p_sys->p_grab );
  410.         free( psz );
  411.         if( p_sys->p_mux == NULL )
  412.         {
  413.             msg_Err( p_stream, "cannot create muxer" );
  414.             sout_AccessOutDelete( p_sys->p_grab );
  415.             vlc_mutex_destroy( &p_sys->lock_sdp );
  416.             vlc_mutex_destroy( &p_sys->lock_es );
  417.             free( p_sys->psz_destination );
  418.             free( p_sys );
  419.             return VLC_EGENERIC;
  420.         }
  421.         id = Add( p_stream, NULL );
  422.         if( id == NULL )
  423.         {
  424.             sout_MuxDelete( p_sys->p_mux );
  425.             sout_AccessOutDelete( p_sys->p_grab );
  426.             vlc_mutex_destroy( &p_sys->lock_sdp );
  427.             vlc_mutex_destroy( &p_sys->lock_es );
  428.             free( p_sys->psz_destination );
  429.             free( p_sys );
  430.             return VLC_EGENERIC;
  431.         }
  432.         p_sys->packet = NULL;
  433.         p_stream->pf_add  = MuxAdd;
  434.         p_stream->pf_del  = MuxDel;
  435.         p_stream->pf_send = MuxSend;
  436.     }
  437.     else
  438.     {
  439.         p_sys->p_mux    = NULL;
  440.         p_sys->p_grab   = NULL;
  441.         p_stream->pf_add    = Add;
  442.         p_stream->pf_del    = Del;
  443.         p_stream->pf_send   = Send;
  444.     }
  445.     if( var_GetBool( p_stream, SOUT_CFG_PREFIX"sap" ) )
  446.         SDPHandleUrl( p_stream, "sap" );
  447.     psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "sdp" );
  448.     if( psz != NULL )
  449.     {
  450.         config_chain_t *p_cfg;
  451.         SDPHandleUrl( p_stream, psz );
  452.         for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
  453.         {
  454.             if( !strcmp( p_cfg->psz_name, "sdp" ) )
  455.             {
  456.                 if( p_cfg->psz_value == NULL || *p_cfg->psz_value == '' )
  457.                     continue;
  458.                 /* needed both :sout-rtp-sdp= and rtp{sdp=} can be used */
  459.                 if( !strcmp( p_cfg->psz_value, psz ) )
  460.                     continue;
  461.                 SDPHandleUrl( p_stream, p_cfg->psz_value );
  462.             }
  463.         }
  464.         free( psz );
  465.     }
  466.     /* update p_sout->i_out_pace_nocontrol */
  467.     p_stream->p_sout->i_out_pace_nocontrol++;
  468.     return VLC_SUCCESS;
  469. }
  470. /*****************************************************************************
  471.  * Close:
  472.  *****************************************************************************/
  473. static void Close( vlc_object_t * p_this )
  474. {
  475.     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
  476.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  477.     /* update p_sout->i_out_pace_nocontrol */
  478.     p_stream->p_sout->i_out_pace_nocontrol--;
  479.     if( p_sys->p_mux )
  480.     {
  481.         assert( p_sys->i_es == 1 );
  482.         sout_MuxDelete( p_sys->p_mux );
  483.         Del( p_stream, p_sys->es[0] );
  484.         sout_AccessOutDelete( p_sys->p_grab );
  485.         if( p_sys->packet )
  486.         {
  487.             block_Release( p_sys->packet );
  488.         }
  489.         if( p_sys->b_export_sap )
  490.         {
  491.             p_sys->p_mux = NULL;
  492.             SapSetup( p_stream );
  493.         }
  494.     }
  495.     if( p_sys->rtsp != NULL )
  496.         RtspUnsetup( p_sys->rtsp );
  497.     vlc_mutex_destroy( &p_sys->lock_sdp );
  498.     vlc_mutex_destroy( &p_sys->lock_es );
  499.     if( p_sys->p_httpd_file )
  500.         httpd_FileDelete( p_sys->p_httpd_file );
  501.     if( p_sys->p_httpd_host )
  502.         httpd_HostDelete( p_sys->p_httpd_host );
  503.     free( p_sys->psz_sdp );
  504.     if( p_sys->b_export_sdp_file )
  505.     {
  506. #ifdef HAVE_UNISTD_H
  507.         unlink( p_sys->psz_sdp_file );
  508. #endif
  509.         free( p_sys->psz_sdp_file );
  510.     }
  511.     free( p_sys->psz_destination );
  512.     free( p_sys );
  513. }
  514. /*****************************************************************************
  515.  * SDPHandleUrl:
  516.  *****************************************************************************/
  517. static void SDPHandleUrl( sout_stream_t *p_stream, const char *psz_url )
  518. {
  519.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  520.     vlc_url_t url;
  521.     vlc_UrlParse( &url, psz_url, 0 );
  522.     if( url.psz_protocol && !strcasecmp( url.psz_protocol, "http" ) )
  523.     {
  524.         if( p_sys->p_httpd_file )
  525.         {
  526.             msg_Err( p_stream, "you can use sdp=http:// only once" );
  527.             goto out;
  528.         }
  529.         if( HttpSetup( p_stream, &url ) )
  530.         {
  531.             msg_Err( p_stream, "cannot export SDP as HTTP" );
  532.         }
  533.     }
  534.     else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "rtsp" ) )
  535.     {
  536.         if( p_sys->rtsp != NULL )
  537.         {
  538.             msg_Err( p_stream, "you can use sdp=rtsp:// only once" );
  539.             goto out;
  540.         }
  541.         /* FIXME test if destination is multicast or no destination at all */
  542.         p_sys->rtsp = RtspSetup( p_stream, &url );
  543.         if( p_sys->rtsp == NULL )
  544.             msg_Err( p_stream, "cannot export SDP as RTSP" );
  545.         else
  546.         if( p_sys->p_mux != NULL )
  547.         {
  548.             sout_stream_id_t *id = p_sys->es[0];
  549.             id->rtsp_id = RtspAddId( p_sys->rtsp, id, 0, GetDWBE( id->ssrc ),
  550.                                      p_sys->psz_destination, p_sys->i_ttl,
  551.                                      id->i_port, id->i_port + 1 );
  552.         }
  553.     }
  554.     else if( ( url.psz_protocol && !strcasecmp( url.psz_protocol, "sap" ) ) ||
  555.              ( url.psz_host && !strcasecmp( url.psz_host, "sap" ) ) )
  556.     {
  557.         p_sys->b_export_sap = true;
  558.         SapSetup( p_stream );
  559.     }
  560.     else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "file" ) )
  561.     {
  562.         if( p_sys->b_export_sdp_file )
  563.         {
  564.             msg_Err( p_stream, "you can use sdp=file:// only once" );
  565.             goto out;
  566.         }
  567.         p_sys->b_export_sdp_file = true;
  568.         psz_url = &psz_url[5];
  569.         if( psz_url[0] == '/' && psz_url[1] == '/' )
  570.             psz_url += 2;
  571.         p_sys->psz_sdp_file = strdup( psz_url );
  572.         decode_URI( p_sys->psz_sdp_file ); /* FIXME? */
  573.         FileSetup( p_stream );
  574.     }
  575.     else
  576.     {
  577.         msg_Warn( p_stream, "unknown protocol for SDP (%s)",
  578.                   url.psz_protocol );
  579.     }
  580. out:
  581.     vlc_UrlClean( &url );
  582. }
  583. /*****************************************************************************
  584.  * SDPGenerate
  585.  *****************************************************************************/
  586. /*static*/
  587. char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url )
  588. {
  589.     const sout_stream_sys_t *p_sys = p_stream->p_sys;
  590.     char *psz_sdp;
  591.     struct sockaddr_storage dst;
  592.     socklen_t dstlen;
  593.     int i;
  594.     /*
  595.      * When we have a fixed destination (typically when we do multicast),
  596.      * we need to put the actual port numbers in the SDP.
  597.      * When there is no fixed destination, we only support RTSP unicast
  598.      * on-demand setup, so we should rather let the clients decide which ports
  599.      * to use.
  600.      * When there is both a fixed destination and RTSP unicast, we need to
  601.      * put port numbers used by the fixed destination, otherwise the SDP would
  602.      * become totally incorrect for multicast use. It should be noted that
  603.      * port numbers from SDP with RTSP are only "recommendation" from the
  604.      * server to the clients (per RFC2326), so only broken clients will fail
  605.      * to handle this properly. There is no solution but to use two differents
  606.      * output chain with two different RTSP URLs if you need to handle this
  607.      * scenario.
  608.      */
  609.     int inclport;
  610.     if( p_sys->psz_destination != NULL )
  611.     {
  612.         inclport = 1;
  613.         /* Oh boy, this is really ugly! (+ race condition on lock_es) */
  614.         dstlen = sizeof( dst );
  615.         if( p_sys->es[0]->listen_fd != NULL )
  616.             getsockname( p_sys->es[0]->listen_fd[0],
  617.                          (struct sockaddr *)&dst, &dstlen );
  618.         else
  619.             getpeername( p_sys->es[0]->sinkv[0].rtp_fd,
  620.                          (struct sockaddr *)&dst, &dstlen );
  621.     }
  622.     else
  623.     {
  624.         inclport = 0;
  625.         /* Dummy destination address for RTSP */
  626.         memset (&dst, 0, sizeof( struct sockaddr_in ) );
  627.         dst.ss_family = AF_INET;
  628. #ifdef HAVE_SA_LEN
  629.         dst.ss_len =
  630. #endif
  631.         dstlen = sizeof( struct sockaddr_in );
  632.     }
  633.     psz_sdp = vlc_sdp_Start( VLC_OBJECT( p_stream ), SOUT_CFG_PREFIX,
  634.                              NULL, 0, (struct sockaddr *)&dst, dstlen );
  635.     if( psz_sdp == NULL )
  636.         return NULL;
  637.     /* TODO: a=source-filter */
  638.     if( p_sys->rtcp_mux )
  639.         sdp_AddAttribute( &psz_sdp, "rtcp-mux", NULL );
  640.     if( rtsp_url != NULL )
  641.         sdp_AddAttribute ( &psz_sdp, "control", "%s", rtsp_url );
  642.     /* FIXME: locking?! */
  643.     for( i = 0; i < p_sys->i_es; i++ )
  644.     {
  645.         sout_stream_id_t *id = p_sys->es[i];
  646.         const char *mime_major; /* major MIME type */
  647.         const char *proto = "RTP/AVP"; /* protocol */
  648.         switch( id->i_cat )
  649.         {
  650.             case VIDEO_ES:
  651.                 mime_major = "video";
  652.                 break;
  653.             case AUDIO_ES:
  654.                 mime_major = "audio";
  655.                 break;
  656.             case SPU_ES:
  657.                 mime_major = "text";
  658.                 break;
  659.             default:
  660.                 continue;
  661.         }
  662.         if( rtsp_url == NULL )
  663.         {
  664.             switch( p_sys->proto )
  665.             {
  666.                 case IPPROTO_UDP:
  667.                     break;
  668.                 case IPPROTO_TCP:
  669.                     proto = "TCP/RTP/AVP";
  670.                     break;
  671.                 case IPPROTO_DCCP:
  672.                     proto = "DCCP/RTP/AVP";
  673.                     break;
  674.                 case IPPROTO_UDPLITE:
  675.                     continue;
  676.             }
  677.         }
  678.         sdp_AddMedia( &psz_sdp, mime_major, proto, inclport * id->i_port,
  679.                       id->i_payload_type, false, id->i_bitrate,
  680.                       id->psz_enc, id->i_clock_rate, id->i_channels,
  681.                       id->psz_fmtp);
  682.         if( !p_sys->rtcp_mux && (id->i_port & 1) ) /* cf RFC4566 §5.14 */
  683.             sdp_AddAttribute ( &psz_sdp, "rtcp", "%u", id->i_port + 1 );
  684.         if( rtsp_url != NULL )
  685.         {
  686.             assert( strlen( rtsp_url ) > 0 );
  687.             bool addslash = ( rtsp_url[strlen( rtsp_url ) - 1] != '/' );
  688.             sdp_AddAttribute ( &psz_sdp, "control",
  689.                                addslash ? "%s/trackID=%u" : "%strackID=%u",
  690.                                rtsp_url, i );
  691.         }
  692.         else
  693.         {
  694.             if( id->listen_fd != NULL )
  695.                 sdp_AddAttribute( &psz_sdp, "setup", "passive" );
  696.             if( p_sys->proto == IPPROTO_DCCP )
  697.                 sdp_AddAttribute( &psz_sdp, "dccp-service-code",
  698.                                   "SC:RTP%c", toupper( mime_major[0] ) );
  699.         }
  700.     }
  701.     return psz_sdp;
  702. }
  703. /*****************************************************************************
  704.  * RTP mux
  705.  *****************************************************************************/
  706. static void sprintf_hexa( char *s, uint8_t *p_data, int i_data )
  707. {
  708.     static const char hex[16] = "0123456789abcdef";
  709.     int i;
  710.     for( i = 0; i < i_data; i++ )
  711.     {
  712.         s[2*i+0] = hex[(p_data[i]>>4)&0xf];
  713.         s[2*i+1] = hex[(p_data[i]   )&0xf];
  714.     }
  715.     s[2*i_data] = '';
  716. }
  717. /**
  718.  * Shrink the MTU down to a fixed packetization time (for audio).
  719.  */
  720. static void
  721. rtp_set_ptime (sout_stream_id_t *id, unsigned ptime_ms, size_t bytes)
  722. {
  723.     /* Samples per second */
  724.     size_t spl = (id->i_clock_rate - 1) * ptime_ms / 1000 + 1;
  725.     bytes *= id->i_channels;
  726.     spl *= bytes;
  727.     if (spl < rtp_mtu (id)) /* MTU is big enough for ptime */
  728.         id->i_mtu = 12 + spl;
  729.     else /* MTU is too small for ptime, align to a sample boundary */
  730.         id->i_mtu = 12 + (((id->i_mtu - 12) / bytes) * bytes);
  731. }
  732. /** Add an ES as a new RTP stream */
  733. static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
  734. {
  735.     /* NOTE: As a special case, if we use a non-RTP
  736.      * mux (TS/PS), then p_fmt is NULL. */
  737.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  738.     sout_stream_id_t  *id;
  739.     int               cscov = -1;
  740.     char              *psz_sdp;
  741.     if (0xffffffff == p_sys->payload_bitmap)
  742.     {
  743.         msg_Err (p_stream, "too many RTP elementary streams");
  744.         return NULL;
  745.     }
  746.     /* Choose the port */
  747.     uint16_t i_port = 0;
  748.     if( p_fmt == NULL )
  749.         ;
  750.     else
  751.     if( p_fmt->i_cat == AUDIO_ES && p_sys->i_port_audio > 0 )
  752.         i_port = p_sys->i_port_audio;
  753.     else
  754.     if( p_fmt->i_cat == VIDEO_ES && p_sys->i_port_video > 0 )
  755.         i_port = p_sys->i_port_video;
  756.     /* We do not need the ES lock (p_sys->lock_es) here, because this is the
  757.      * only one thread that can *modify* the ES table. The ES lock protects
  758.      * the other threads from our modifications (TAB_APPEND, TAB_REMOVE). */
  759.     for (int i = 0; i_port && (i < p_sys->i_es); i++)
  760.          if (i_port == p_sys->es[i]->i_port)
  761.              i_port = 0; /* Port already in use! */
  762.     for (uint16_t p = p_sys->i_port; i_port == 0; p += 2)
  763.     {
  764.         if (p == 0)
  765.         {
  766.             msg_Err (p_stream, "too many RTP elementary streams");
  767.             return NULL;
  768.         }
  769.         i_port = p;
  770.         for (int i = 0; i_port && (i < p_sys->i_es); i++)
  771.              if (p == p_sys->es[i]->i_port)
  772.                  i_port = 0;
  773.     }
  774.     id = vlc_object_create( p_stream, sizeof( sout_stream_id_t ) );
  775.     if( id == NULL )
  776.         return NULL;
  777.     vlc_object_attach( id, p_stream );
  778.     id->p_stream   = p_stream;
  779.     id->i_timestamp = 0; /* It will be filled when the first packet is sent */
  780.     /* Look for free dymanic payload type */
  781.     id->i_payload_type = 96;
  782.     while (p_sys->payload_bitmap & (1 << (id->i_payload_type - 96)))
  783.         id->i_payload_type++;
  784.     assert (id->i_payload_type < 128);
  785.     vlc_rand_bytes (&id->i_sequence, sizeof (id->i_sequence));
  786.     vlc_rand_bytes (id->ssrc, sizeof (id->ssrc));
  787.     id->psz_enc    = NULL;
  788.     id->psz_fmtp   = NULL;
  789.     id->i_clock_rate = 90000; /* most common case for video */
  790.     id->i_channels = 0;
  791.     id->i_port     = i_port;
  792.     if( p_fmt != NULL )
  793.     {
  794.         id->i_cat  = p_fmt->i_cat;
  795.         if( p_fmt->i_cat == AUDIO_ES )
  796.         {
  797.             id->i_clock_rate = p_fmt->audio.i_rate;
  798.             id->i_channels = p_fmt->audio.i_channels;
  799.         }
  800.         id->i_bitrate = p_fmt->i_bitrate/1000; /* Stream bitrate in kbps */
  801.     }
  802.     else
  803.     {
  804.         id->i_cat  = VIDEO_ES;
  805.         id->i_bitrate = 0;
  806.     }
  807.     id->i_mtu = config_GetInt( p_stream, "mtu" );
  808.     if( id->i_mtu <= 12 + 16 )
  809.         id->i_mtu = 576 - 20 - 8; /* pessimistic */
  810.     msg_Dbg( p_stream, "maximum RTP packet size: %d bytes", id->i_mtu );
  811.     id->srtp = NULL;
  812.     id->pf_packetize = NULL;
  813.     char *key = var_CreateGetNonEmptyString (p_stream, SOUT_CFG_PREFIX"key");
  814.     if (key)
  815.     {
  816.         id->srtp = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 10,
  817.                                    SRTP_PRF_AES_CM, SRTP_RCC_MODE1);
  818.         if (id->srtp == NULL)
  819.         {
  820.             free (key);
  821.             goto error;
  822.         }
  823.         char *salt = var_CreateGetNonEmptyString (p_stream, SOUT_CFG_PREFIX"salt");
  824.         errno = srtp_setkeystring (id->srtp, key, salt ? salt : "");
  825.         free (salt);
  826.         free (key);
  827.         if (errno)
  828.         {
  829.             msg_Err (p_stream, "bad SRTP key/salt combination (%m)");
  830.             goto error;
  831.         }
  832.         id->i_sequence = 0; /* FIXME: awful hack for libvlc_srtp */
  833.     }
  834.     vlc_mutex_init( &id->lock_sink );
  835.     id->sinkc = 0;
  836.     id->sinkv = NULL;
  837.     id->rtsp_id = NULL;
  838.     id->p_fifo = NULL;
  839.     id->listen_fd = NULL;
  840.     id->i_caching =
  841.         (int64_t)1000 * var_GetInteger( p_stream, SOUT_CFG_PREFIX "caching");
  842.     if( p_sys->psz_destination != NULL )
  843.         switch( p_sys->proto )
  844.         {
  845.             case IPPROTO_DCCP:
  846.             {
  847.                 const char *code;
  848.                 switch (id->i_cat)
  849.                 {
  850.                     case VIDEO_ES: code = "RTPV";     break;
  851.                     case AUDIO_ES: code = "RTPARTPV"; break;
  852.                     case SPU_ES:   code = "RTPTRTPV"; break;
  853.                     default:       code = "RTPORTPV"; break;
  854.                 }
  855.                 var_SetString (p_stream, "dccp-service", code);
  856.             }   /* fall through */
  857.             case IPPROTO_TCP:
  858.                 id->listen_fd = net_Listen( VLC_OBJECT(p_stream),
  859.                                             p_sys->psz_destination, i_port,
  860.                                             p_sys->proto );
  861.                 if( id->listen_fd == NULL )
  862.                 {
  863.                     msg_Err( p_stream, "passive COMEDIA RTP socket failed" );
  864.                     goto error;
  865.                 }
  866.                 break;
  867.             default:
  868.             {
  869.                 int ttl = (p_sys->i_ttl >= 0) ? p_sys->i_ttl : -1;
  870.                 int fd = net_ConnectDgram( p_stream, p_sys->psz_destination,
  871.                                            i_port, ttl, p_sys->proto );
  872.                 if( fd == -1 )
  873.                 {
  874.                     msg_Err( p_stream, "cannot create RTP socket" );
  875.                     goto error;
  876.                 }
  877.                 rtp_add_sink( id, fd, p_sys->rtcp_mux );
  878.             }
  879.         }
  880.     if( p_fmt == NULL )
  881.     {
  882.         char *psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );
  883.         if( psz == NULL ) /* Uho! */
  884.             ;
  885.         else
  886.         if( strncmp( psz, "ts", 2 ) == 0 )
  887.         {
  888.             id->i_payload_type = 33;
  889.             id->psz_enc = "MP2T";
  890.         }
  891.         else
  892.         {
  893.             id->psz_enc = "MP2P";
  894.         }
  895.         free( psz );
  896.     }
  897.     else
  898.     switch( p_fmt->i_codec )
  899.     {
  900.         case VLC_FOURCC( 'u', 'l', 'a', 'w' ):
  901.             if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 )
  902.                 id->i_payload_type = 0;
  903.             id->psz_enc = "PCMU";
  904.             id->pf_packetize = rtp_packetize_split;
  905.             rtp_set_ptime (id, 20, 1);
  906.             break;
  907.         case VLC_FOURCC( 'a', 'l', 'a', 'w' ):
  908.             if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 )
  909.                 id->i_payload_type = 8;
  910.             id->psz_enc = "PCMA";
  911.             id->pf_packetize = rtp_packetize_split;
  912.             rtp_set_ptime (id, 20, 1);
  913.             break;
  914.         case VLC_FOURCC( 's', '1', '6', 'b' ):
  915.             if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 44100 )
  916.             {
  917.                 id->i_payload_type = 11;
  918.             }
  919.             else if( p_fmt->audio.i_channels == 2 &&
  920.                      p_fmt->audio.i_rate == 44100 )
  921.             {
  922.                 id->i_payload_type = 10;
  923.             }
  924.             id->psz_enc = "L16";
  925.             id->pf_packetize = rtp_packetize_split;
  926.             rtp_set_ptime (id, 20, 2);
  927.             break;
  928.         case VLC_FOURCC( 'u', '8', ' ', ' ' ):
  929.             id->psz_enc = "L8";
  930.             id->pf_packetize = rtp_packetize_split;
  931.             rtp_set_ptime (id, 20, 1);
  932.             break;
  933.         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
  934.         case VLC_FOURCC( 'm', 'p', '3', ' ' ):
  935.             id->i_payload_type = 14;
  936.             id->psz_enc = "MPA";
  937.             id->i_clock_rate = 90000; /* not 44100 */
  938.             id->pf_packetize = rtp_packetize_mpa;
  939.             break;
  940.         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
  941.             id->i_payload_type = 32;
  942.             id->psz_enc = "MPV";
  943.             id->pf_packetize = rtp_packetize_mpv;
  944.             break;
  945.         case VLC_FOURCC( 'G', '7', '2', '6' ):
  946.         case VLC_FOURCC( 'g', '7', '2', '6' ):
  947.             switch( p_fmt->i_bitrate / 1000 )
  948.             {
  949.             case 16:
  950.                 id->psz_enc = "G726-16";
  951.                 id->pf_packetize = rtp_packetize_g726_16;
  952.                 break;
  953.             case 24:
  954.                 id->psz_enc = "G726-24";
  955.                 id->pf_packetize = rtp_packetize_g726_24;
  956.                 break;
  957.             case 32:
  958.                 id->psz_enc = "G726-32";
  959.                 id->pf_packetize = rtp_packetize_g726_32;
  960.                 break;
  961.             case 40:
  962.                 id->psz_enc = "G726-40";
  963.                 id->pf_packetize = rtp_packetize_g726_40;
  964.                 break;
  965.             default:
  966.                 msg_Err( p_stream, "cannot add this stream (unsupported "
  967.                          "G.726 bit rate: %u)", p_fmt->i_bitrate );
  968.                 goto error;
  969.             }
  970.             break;
  971.         case VLC_FOURCC( 'a', '5', '2', ' ' ):
  972.             id->psz_enc = "ac3";
  973.             id->pf_packetize = rtp_packetize_ac3;
  974.             break;
  975.         case VLC_FOURCC( 'H', '2', '6', '3' ):
  976.             id->psz_enc = "H263-1998";
  977.             id->pf_packetize = rtp_packetize_h263;
  978.             break;
  979.         case VLC_FOURCC( 'h', '2', '6', '4' ):
  980.             id->psz_enc = "H264";
  981.             id->pf_packetize = rtp_packetize_h264;
  982.             id->psz_fmtp = NULL;
  983.             if( p_fmt->i_extra > 0 )
  984.             {
  985.                 uint8_t *p_buffer = p_fmt->p_extra;
  986.                 int     i_buffer = p_fmt->i_extra;
  987.                 char    *p_64_sps = NULL;
  988.                 char    *p_64_pps = NULL;
  989.                 char    hexa[6+1];
  990.                 while( i_buffer > 4 &&
  991.                        p_buffer[0] == 0 && p_buffer[1] == 0 &&
  992.                        p_buffer[2] == 0 && p_buffer[3] == 1 )
  993.                 {
  994.                     const int i_nal_type = p_buffer[4]&0x1f;
  995.                     int i_offset;
  996.                     int i_size      = 0;
  997.                     msg_Dbg( p_stream, "we found a startcode for NAL with TYPE:%d", i_nal_type );
  998.                     i_size = i_buffer;
  999.                     for( i_offset = 4; i_offset+3 < i_buffer ; i_offset++)
  1000.                     {
  1001.                         if( !memcmp (p_buffer + i_offset, "x00x00x00x01", 4 ) )
  1002.                         {
  1003.                             /* we found another startcode */
  1004.                             i_size = i_offset;
  1005.                             break;
  1006.                         }
  1007.                     }
  1008.                     if( i_nal_type == 7 )
  1009.                     {
  1010.                         p_64_sps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
  1011.                         sprintf_hexa( hexa, &p_buffer[5], 3 );
  1012.                     }
  1013.                     else if( i_nal_type == 8 )
  1014.                     {
  1015.                         p_64_pps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
  1016.                     }
  1017.                     i_buffer -= i_size;
  1018.                     p_buffer += i_size;
  1019.                 }
  1020.                 /* */
  1021.                 if( p_64_sps && p_64_pps &&
  1022.                     ( asprintf( &id->psz_fmtp,
  1023.                                 "packetization-mode=1;profile-level-id=%s;"
  1024.                                 "sprop-parameter-sets=%s,%s;", hexa, p_64_sps,
  1025.                                 p_64_pps ) == -1 ) )
  1026.                     id->psz_fmtp = NULL;
  1027.                 free( p_64_sps );
  1028.                 free( p_64_pps );
  1029.             }
  1030.             if( !id->psz_fmtp )
  1031.                 id->psz_fmtp = strdup( "packetization-mode=1" );
  1032.             break;
  1033.         case VLC_FOURCC( 'm', 'p', '4', 'v' ):
  1034.         {
  1035.             char hexa[2*p_fmt->i_extra +1];
  1036.             id->psz_enc = "MP4V-ES";
  1037.             id->pf_packetize = rtp_packetize_split;
  1038.             if( p_fmt->i_extra > 0 )
  1039.             {
  1040.                 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
  1041.                 if( asprintf( &id->psz_fmtp,
  1042.                               "profile-level-id=3; config=%s;", hexa ) == -1 )
  1043.                     id->psz_fmtp = NULL;
  1044.             }
  1045.             break;
  1046.         }
  1047.         case VLC_FOURCC( 'm', 'p', '4', 'a' ):
  1048.         {
  1049.             if(!p_sys->b_latm)
  1050.             {
  1051.                 char hexa[2*p_fmt->i_extra +1];
  1052.                 id->psz_enc = "mpeg4-generic";
  1053.                 id->pf_packetize = rtp_packetize_mp4a;
  1054.                 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
  1055.                 if( asprintf( &id->psz_fmtp,
  1056.                               "streamtype=5; profile-level-id=15; "
  1057.                               "mode=AAC-hbr; config=%s; SizeLength=13; "
  1058.                               "IndexLength=3; IndexDeltaLength=3; Profile=1;",
  1059.                               hexa ) == -1 )
  1060.                     id->psz_fmtp = NULL;
  1061.             }
  1062.             else
  1063.             {
  1064.                 char hexa[13];
  1065.                 int i;
  1066.                 unsigned char config[6];
  1067.                 unsigned int aacsrates[15] = {
  1068.                     96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
  1069.                     16000, 12000, 11025, 8000, 7350, 0, 0 };
  1070.                 for( i = 0; i < 15; i++ )
  1071.                     if( p_fmt->audio.i_rate == aacsrates[i] )
  1072.                         break;
  1073.                 config[0]=0x40;
  1074.                 config[1]=0;
  1075.                 config[2]=0x20|i;
  1076.                 config[3]=p_fmt->audio.i_channels<<4;
  1077.                 config[4]=0x3f;
  1078.                 config[5]=0xc0;
  1079.                 id->psz_enc = "MP4A-LATM";
  1080.                 id->pf_packetize = rtp_packetize_mp4a_latm;
  1081.                 sprintf_hexa( hexa, config, 6 );
  1082.                 if( asprintf( &id->psz_fmtp, "profile-level-id=15; "
  1083.                               "object=2; cpresent=0; config=%s", hexa ) == -1 )
  1084.                     id->psz_fmtp = NULL;
  1085.             }
  1086.             break;
  1087.         }
  1088.         case VLC_FOURCC( 's', 'a', 'm', 'r' ):
  1089.             id->psz_enc = "AMR";
  1090.             id->psz_fmtp = strdup( "octet-align=1" );
  1091.             id->pf_packetize = rtp_packetize_amr;
  1092.             break;
  1093.         case VLC_FOURCC( 's', 'a', 'w', 'b' ):
  1094.             id->psz_enc = "AMR-WB";
  1095.             id->psz_fmtp = strdup( "octet-align=1" );
  1096.             id->pf_packetize = rtp_packetize_amr;
  1097.             break;
  1098.         case VLC_FOURCC( 's', 'p', 'x', ' ' ):
  1099.             id->psz_enc = "SPEEX";
  1100.             id->pf_packetize = rtp_packetize_spx;
  1101.             break;
  1102.         case VLC_FOURCC( 't', '1', '4', '0' ):
  1103.             id->psz_enc = "t140" ;
  1104.             id->i_clock_rate = 1000;
  1105.             id->pf_packetize = rtp_packetize_t140;
  1106.             break;
  1107.         default:
  1108.             msg_Err( p_stream, "cannot add this stream (unsupported "
  1109.                      "codec: %4.4s)", (char*)&p_fmt->i_codec );
  1110.             goto error;
  1111.     }
  1112.     if (id->i_payload_type >= 96)
  1113.         /* Mark dynamic payload type in use */
  1114.         p_sys->payload_bitmap |= 1 << (id->i_payload_type - 96);
  1115. #if 0 /* No payload formats sets this at the moment */
  1116.     if( cscov != -1 )
  1117.         cscov += 8 /* UDP */ + 12 /* RTP */;
  1118.     if( id->sinkc > 0 )
  1119.         net_SetCSCov( id->sinkv[0].rtp_fd, cscov, -1 );
  1120. #endif
  1121.     if( p_sys->rtsp != NULL )
  1122.         id->rtsp_id = RtspAddId( p_sys->rtsp, id, p_sys->i_es,
  1123.                                  GetDWBE( id->ssrc ),
  1124.                                  p_sys->psz_destination,
  1125.                                  p_sys->i_ttl, id->i_port, id->i_port + 1 );
  1126.     id->p_fifo = block_FifoNew();
  1127.     if( vlc_thread_create( id, "RTP send thread", ThreadSend,
  1128.                            VLC_THREAD_PRIORITY_HIGHEST ) )
  1129.         goto error;
  1130.     /* Update p_sys context */
  1131.     vlc_mutex_lock( &p_sys->lock_es );
  1132.     TAB_APPEND( p_sys->i_es, p_sys->es, id );
  1133.     vlc_mutex_unlock( &p_sys->lock_es );
  1134.     psz_sdp = SDPGenerate( p_stream, NULL );
  1135.     vlc_mutex_lock( &p_sys->lock_sdp );
  1136.     free( p_sys->psz_sdp );
  1137.     p_sys->psz_sdp = psz_sdp;
  1138.     vlc_mutex_unlock( &p_sys->lock_sdp );
  1139.     msg_Dbg( p_stream, "sdp=n%s", p_sys->psz_sdp );
  1140.     /* Update SDP (sap/file) */
  1141.     if( p_sys->b_export_sap ) SapSetup( p_stream );
  1142.     if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
  1143.     return id;
  1144. error:
  1145.     Del( p_stream, id );
  1146.     return NULL;
  1147. }
  1148. static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
  1149. {
  1150.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  1151.     if( id->p_fifo != NULL )
  1152.     {
  1153.         vlc_object_kill( id );
  1154.         vlc_thread_join( id );
  1155.         block_FifoRelease( id->p_fifo );
  1156.     }
  1157.     vlc_mutex_lock( &p_sys->lock_es );
  1158.     TAB_REMOVE( p_sys->i_es, p_sys->es, id );
  1159.     vlc_mutex_unlock( &p_sys->lock_es );
  1160.     /* Release dynamic payload type */
  1161.     if (id->i_payload_type >= 96)
  1162.         p_sys->payload_bitmap &= ~(1 << (id->i_payload_type - 96));
  1163.     free( id->psz_fmtp );
  1164.     if( id->rtsp_id )
  1165.         RtspDelId( p_sys->rtsp, id->rtsp_id );
  1166.     if( id->sinkc > 0 )
  1167.         rtp_del_sink( id, id->sinkv[0].rtp_fd ); /* sink for explicit dst= */
  1168.     if( id->listen_fd != NULL )
  1169.         net_ListenClose( id->listen_fd );
  1170.     if( id->srtp != NULL )
  1171.         srtp_destroy( id->srtp );
  1172.     vlc_mutex_destroy( &id->lock_sink );
  1173.     /* Update SDP (sap/file) */
  1174.     if( p_sys->b_export_sap && !p_sys->p_mux ) SapSetup( p_stream );
  1175.     if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
  1176.     vlc_object_detach( id );
  1177.     vlc_object_release( id );
  1178.     return VLC_SUCCESS;
  1179. }
  1180. static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
  1181.                  block_t *p_buffer )
  1182. {
  1183.     block_t *p_next;
  1184.     assert( p_stream->p_sys->p_mux == NULL );
  1185.     (void)p_stream;
  1186.     while( p_buffer != NULL )
  1187.     {
  1188.         p_next = p_buffer->p_next;
  1189.         if( id->pf_packetize( id, p_buffer ) )
  1190.             break;
  1191.         block_Release( p_buffer );
  1192.         p_buffer = p_next;
  1193.     }
  1194.     return VLC_SUCCESS;
  1195. }
  1196. /****************************************************************************
  1197.  * SAP:
  1198.  ****************************************************************************/
  1199. static int SapSetup( sout_stream_t *p_stream )
  1200. {
  1201.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  1202.     sout_instance_t   *p_sout = p_stream->p_sout;
  1203.     /* Remove the previous session */
  1204.     if( p_sys->p_session != NULL)
  1205.     {
  1206.         sout_AnnounceUnRegister( p_sout, p_sys->p_session);
  1207.         p_sys->p_session = NULL;
  1208.     }
  1209.     if( ( p_sys->i_es > 0 || p_sys->p_mux ) && p_sys->psz_sdp && *p_sys->psz_sdp )
  1210.     {
  1211.         announce_method_t *p_method = sout_SAPMethod();
  1212.         p_sys->p_session = sout_AnnounceRegisterSDP( p_sout,
  1213.                                                      p_sys->psz_sdp,
  1214.                                                      p_sys->psz_destination,
  1215.                                                      p_method );
  1216.         sout_MethodRelease( p_method );
  1217.     }
  1218.     return VLC_SUCCESS;
  1219. }
  1220. /****************************************************************************
  1221. * File:
  1222. ****************************************************************************/
  1223. static int FileSetup( sout_stream_t *p_stream )
  1224. {
  1225.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  1226.     FILE            *f;
  1227.     if( p_sys->psz_sdp == NULL )
  1228.         return VLC_EGENERIC; /* too early */
  1229.     if( ( f = utf8_fopen( p_sys->psz_sdp_file, "wt" ) ) == NULL )
  1230.     {
  1231.         msg_Err( p_stream, "cannot open file '%s' (%m)",
  1232.                  p_sys->psz_sdp_file );
  1233.         return VLC_EGENERIC;
  1234.     }
  1235.     fputs( p_sys->psz_sdp, f );
  1236.     fclose( f );
  1237.     return VLC_SUCCESS;
  1238. }
  1239. /****************************************************************************
  1240.  * HTTP:
  1241.  ****************************************************************************/
  1242. static int  HttpCallback( httpd_file_sys_t *p_args,
  1243.                           httpd_file_t *, uint8_t *p_request,
  1244.                           uint8_t **pp_data, int *pi_data );
  1245. static int HttpSetup( sout_stream_t *p_stream, const vlc_url_t *url)
  1246. {
  1247.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  1248.     p_sys->p_httpd_host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host,
  1249.                                          url->i_port > 0 ? url->i_port : 80 );
  1250.     if( p_sys->p_httpd_host )
  1251.     {
  1252.         p_sys->p_httpd_file = httpd_FileNew( p_sys->p_httpd_host,
  1253.                                              url->psz_path ? url->psz_path : "/",
  1254.                                              "application/sdp",
  1255.                                              NULL, NULL, NULL,
  1256.                                              HttpCallback, (void*)p_sys );
  1257.     }
  1258.     if( p_sys->p_httpd_file == NULL )
  1259.     {
  1260.         return VLC_EGENERIC;
  1261.     }
  1262.     return VLC_SUCCESS;
  1263. }
  1264. static int  HttpCallback( httpd_file_sys_t *p_args,
  1265.                           httpd_file_t *f, uint8_t *p_request,
  1266.                           uint8_t **pp_data, int *pi_data )
  1267. {
  1268.     VLC_UNUSED(f); VLC_UNUSED(p_request);
  1269.     sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_args;
  1270.     vlc_mutex_lock( &p_sys->lock_sdp );
  1271.     if( p_sys->psz_sdp && *p_sys->psz_sdp )
  1272.     {
  1273.         *pi_data = strlen( p_sys->psz_sdp );
  1274.         *pp_data = malloc( *pi_data );
  1275.         memcpy( *pp_data, p_sys->psz_sdp, *pi_data );
  1276.     }
  1277.     else
  1278.     {
  1279.         *pp_data = NULL;
  1280.         *pi_data = 0;
  1281.     }
  1282.     vlc_mutex_unlock( &p_sys->lock_sdp );
  1283.     return VLC_SUCCESS;
  1284. }
  1285. /****************************************************************************
  1286.  * RTP send
  1287.  ****************************************************************************/
  1288. static void* ThreadSend( vlc_object_t *p_this )
  1289. {
  1290. #ifdef WIN32
  1291. # define ECONNREFUSED WSAECONNREFUSED
  1292. # define ENOPROTOOPT  WSAENOPROTOOPT
  1293. # define EHOSTUNREACH WSAEHOSTUNREACH
  1294. # define ENETUNREACH  WSAENETUNREACH
  1295. # define ENETDOWN     WSAENETDOWN
  1296. # define ENOBUFS      WSAENOBUFS
  1297. # define EAGAIN       WSAEWOULDBLOCK
  1298. # define EWOULDBLOCK  WSAEWOULDBLOCK
  1299. #endif
  1300.     sout_stream_id_t *id = (sout_stream_id_t *)p_this;
  1301.     unsigned i_caching = id->i_caching;
  1302.     for (;;)
  1303.     {
  1304.         block_t *out = block_FifoGet( id->p_fifo );
  1305.         block_cleanup_push (out);
  1306.         if( id->srtp )
  1307.         {   /* FIXME: this is awfully inefficient */
  1308.             size_t len = out->i_buffer;
  1309.             out = block_Realloc( out, 0, len + 10 );
  1310.             out->i_buffer = len;
  1311.             int canc = vlc_savecancel ();
  1312.             int val = srtp_send( id->srtp, out->p_buffer, &len, len + 10 );
  1313.             vlc_restorecancel (canc);
  1314.             if( val )
  1315.             {
  1316.                 errno = val;
  1317.                 msg_Dbg( id, "SRTP sending error: %m" );
  1318.                 block_Release( out );
  1319.                 out = NULL;
  1320.             }
  1321.             else
  1322.                 out->i_buffer = len;
  1323.         }
  1324.         if (out)
  1325.             mwait (out->i_dts + i_caching);
  1326.         vlc_cleanup_pop ();
  1327.         if (out == NULL)
  1328.             continue;
  1329.         ssize_t len = out->i_buffer;
  1330.         int canc = vlc_savecancel ();
  1331.         vlc_mutex_lock( &id->lock_sink );
  1332.         unsigned deadc = 0; /* How many dead sockets? */
  1333.         int deadv[id->sinkc]; /* Dead sockets list */
  1334.         for( int i = 0; i < id->sinkc; i++ )
  1335.         {
  1336.             if( !id->srtp ) /* FIXME: SRTCP support */
  1337.                 SendRTCP( id->sinkv[i].rtcp, out );
  1338.             if( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) >= 0 )
  1339.                 continue;
  1340.             switch( net_errno )
  1341.             {
  1342.                 /* Soft errors (e.g. ICMP): */
  1343.                 case ECONNREFUSED: /* Port unreachable */
  1344.                 case ENOPROTOOPT:
  1345. #ifdef EPROTO
  1346.                 case EPROTO:       /* Protocol unreachable */
  1347. #endif
  1348.                 case EHOSTUNREACH: /* Host unreachable */
  1349.                 case ENETUNREACH:  /* Network unreachable */
  1350.                 case ENETDOWN:     /* Entire network down */
  1351.                     send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 );
  1352.                 /* Transient congestion: */
  1353.                 case ENOMEM: /* out of socket buffers */
  1354.                 case ENOBUFS:
  1355.                 case EAGAIN:
  1356. #if (EAGAIN != EWOULDBLOCK)
  1357.                 case EWOULDBLOCK:
  1358. #endif
  1359.                     continue;
  1360.             }
  1361.             deadv[deadc++] = id->sinkv[i].rtp_fd;
  1362.         }
  1363.         vlc_mutex_unlock( &id->lock_sink );
  1364.         block_Release( out );
  1365.         for( unsigned i = 0; i < deadc; i++ )
  1366.         {
  1367.             msg_Dbg( id, "removing socket %d", deadv[i] );
  1368.             rtp_del_sink( id, deadv[i] );
  1369.         }
  1370.         /* Hopefully we won't overflow the SO_MAXCONN accept queue */
  1371.         while( id->listen_fd != NULL )
  1372.         {
  1373.             int fd = net_Accept( id, id->listen_fd, 0 );
  1374.             if( fd == -1 )
  1375.                 break;
  1376.             msg_Dbg( id, "adding socket %d", fd );
  1377.             rtp_add_sink( id, fd, true );
  1378.         }
  1379.         vlc_restorecancel (canc);
  1380.     }
  1381.     return NULL;
  1382. }
  1383. int rtp_add_sink( sout_stream_id_t *id, int fd, bool rtcp_mux )
  1384. {
  1385.     rtp_sink_t sink = { fd, NULL };
  1386.     sink.rtcp = OpenRTCP( VLC_OBJECT( id->p_stream ), fd, IPPROTO_UDP,
  1387.                           rtcp_mux );
  1388.     if( sink.rtcp == NULL )
  1389.         msg_Err( id, "RTCP failed!" );
  1390.     vlc_mutex_lock( &id->lock_sink );
  1391.     INSERT_ELEM( id->sinkv, id->sinkc, id->sinkc, sink );
  1392.     vlc_mutex_unlock( &id->lock_sink );
  1393.     return VLC_SUCCESS;
  1394. }
  1395. void rtp_del_sink( sout_stream_id_t *id, int fd )
  1396. {
  1397.     rtp_sink_t sink = { fd, NULL };
  1398.     /* NOTE: must be safe to use if fd is not included */
  1399.     vlc_mutex_lock( &id->lock_sink );
  1400.     for( int i = 0; i < id->sinkc; i++ )
  1401.     {
  1402.         if (id->sinkv[i].rtp_fd == fd)
  1403.         {
  1404.             sink = id->sinkv[i];
  1405.             REMOVE_ELEM( id->sinkv, id->sinkc, i );
  1406.             break;
  1407.         }
  1408.     }
  1409.     vlc_mutex_unlock( &id->lock_sink );
  1410.     CloseRTCP( sink.rtcp );
  1411.     net_Close( sink.rtp_fd );
  1412. }
  1413. uint16_t rtp_get_seq( const sout_stream_id_t *id )
  1414. {
  1415.     /* This will return values for the next packet.
  1416.      * Accounting for caching would not be totally trivial. */
  1417.     return id->i_sequence;
  1418. }
  1419. uint32_t rtp_get_ts( const sout_stream_id_t *id )
  1420. {
  1421.     /* ... and this will return the value for the last packet.
  1422.      * Lame, but close enough. */
  1423.     return id->i_timestamp;
  1424. }
  1425. /* FIXME: this is pretty bad - if we remove and then insert an ES
  1426.  * the number will get unsynched from inside RTSP */
  1427. unsigned rtp_get_num( const sout_stream_id_t *id )
  1428. {
  1429.     sout_stream_sys_t *p_sys = id->p_stream->p_sys;
  1430.     int i;
  1431.     vlc_mutex_lock( &p_sys->lock_es );
  1432.     for( i = 0; i < p_sys->i_es; i++ )
  1433.     {
  1434.         if( id == p_sys->es[i] )
  1435.             break;
  1436.     }
  1437.     vlc_mutex_unlock( &p_sys->lock_es );
  1438.     return i;
  1439. }
  1440. void rtp_packetize_common( sout_stream_id_t *id, block_t *out,
  1441.                            int b_marker, int64_t i_pts )
  1442. {
  1443.     uint32_t i_timestamp = i_pts * (int64_t)id->i_clock_rate / INT64_C(1000000);
  1444.     out->p_buffer[0] = 0x80;
  1445.     out->p_buffer[1] = (b_marker?0x80:0x00)|id->i_payload_type;
  1446.     out->p_buffer[2] = ( id->i_sequence >> 8)&0xff;
  1447.     out->p_buffer[3] = ( id->i_sequence     )&0xff;
  1448.     out->p_buffer[4] = ( i_timestamp >> 24 )&0xff;
  1449.     out->p_buffer[5] = ( i_timestamp >> 16 )&0xff;
  1450.     out->p_buffer[6] = ( i_timestamp >>  8 )&0xff;
  1451.     out->p_buffer[7] = ( i_timestamp       )&0xff;
  1452.     memcpy( out->p_buffer + 8, id->ssrc, 4 );
  1453.     out->i_buffer = 12;
  1454.     id->i_timestamp = i_timestamp;
  1455.     id->i_sequence++;
  1456. }
  1457. void rtp_packetize_send( sout_stream_id_t *id, block_t *out )
  1458. {
  1459.     block_FifoPut( id->p_fifo, out );
  1460. }
  1461. /**
  1462.  * @return configured max RTP payload size (including payload type-specific
  1463.  * headers, excluding RTP and transport headers)
  1464.  */
  1465. size_t rtp_mtu (const sout_stream_id_t *id)
  1466. {
  1467.     return id->i_mtu - 12;
  1468. }
  1469. /*****************************************************************************
  1470.  * Non-RTP mux
  1471.  *****************************************************************************/
  1472. /** Add an ES to a non-RTP muxed stream */
  1473. static sout_stream_id_t *MuxAdd( sout_stream_t *p_stream, es_format_t *p_fmt )
  1474. {
  1475.     sout_input_t      *p_input;
  1476.     sout_mux_t *p_mux = p_stream->p_sys->p_mux;
  1477.     assert( p_mux != NULL );
  1478.     p_input = sout_MuxAddStream( p_mux, p_fmt );
  1479.     if( p_input == NULL )
  1480.     {
  1481.         msg_Err( p_stream, "cannot add this stream to the muxer" );
  1482.         return NULL;
  1483.     }
  1484.     return (sout_stream_id_t *)p_input;
  1485. }
  1486. static int MuxSend( sout_stream_t *p_stream, sout_stream_id_t *id,
  1487.                     block_t *p_buffer )
  1488. {
  1489.     sout_mux_t *p_mux = p_stream->p_sys->p_mux;
  1490.     assert( p_mux != NULL );
  1491.     sout_MuxSendBuffer( p_mux, (sout_input_t *)id, p_buffer );
  1492.     return VLC_SUCCESS;
  1493. }
  1494. /** Remove an ES from a non-RTP muxed stream */
  1495. static int MuxDel( sout_stream_t *p_stream, sout_stream_id_t *id )
  1496. {
  1497.     sout_mux_t *p_mux = p_stream->p_sys->p_mux;
  1498.     assert( p_mux != NULL );
  1499.     sout_MuxDeleteStream( p_mux, (sout_input_t *)id );
  1500.     return VLC_SUCCESS;
  1501. }
  1502. static ssize_t AccessOutGrabberWriteBuffer( sout_stream_t *p_stream,
  1503.                                             const block_t *p_buffer )
  1504. {
  1505.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  1506.     sout_stream_id_t *id = p_sys->es[0];
  1507.     int64_t  i_dts = p_buffer->i_dts;
  1508.     uint8_t         *p_data = p_buffer->p_buffer;
  1509.     size_t          i_data  = p_buffer->i_buffer;
  1510.     size_t          i_max   = id->i_mtu - 12;
  1511.     size_t i_packet = ( p_buffer->i_buffer + i_max - 1 ) / i_max;
  1512.     while( i_data > 0 )
  1513.     {
  1514.         size_t i_size;
  1515.         /* output complete packet */
  1516.         if( p_sys->packet &&
  1517.             p_sys->packet->i_buffer + i_data > i_max )
  1518.         {
  1519.             rtp_packetize_send( id, p_sys->packet );
  1520.             p_sys->packet = NULL;
  1521.         }
  1522.         if( p_sys->packet == NULL )
  1523.         {
  1524.             /* allocate a new packet */
  1525.             p_sys->packet = block_New( p_stream, id->i_mtu );
  1526.             rtp_packetize_common( id, p_sys->packet, 1, i_dts );
  1527.             p_sys->packet->i_dts = i_dts;
  1528.             p_sys->packet->i_length = p_buffer->i_length / i_packet;
  1529.             i_dts += p_sys->packet->i_length;
  1530.         }
  1531.         i_size = __MIN( i_data,
  1532.                         (unsigned)(id->i_mtu - p_sys->packet->i_buffer) );
  1533.         memcpy( &p_sys->packet->p_buffer[p_sys->packet->i_buffer],
  1534.                 p_data, i_size );
  1535.         p_sys->packet->i_buffer += i_size;
  1536.         p_data += i_size;
  1537.         i_data -= i_size;
  1538.     }
  1539.     return VLC_SUCCESS;
  1540. }
  1541. static ssize_t AccessOutGrabberWrite( sout_access_out_t *p_access,
  1542.                                       block_t *p_buffer )
  1543. {
  1544.     sout_stream_t *p_stream = (sout_stream_t*)p_access->p_sys;
  1545.     while( p_buffer )
  1546.     {
  1547.         block_t *p_next;
  1548.         AccessOutGrabberWriteBuffer( p_stream, p_buffer );
  1549.         p_next = p_buffer->p_next;
  1550.         block_Release( p_buffer );
  1551.         p_buffer = p_next;
  1552.     }
  1553.     return VLC_SUCCESS;
  1554. }
  1555. static sout_access_out_t *GrabberCreate( sout_stream_t *p_stream )
  1556. {
  1557.     sout_access_out_t *p_grab;
  1558.     p_grab = vlc_object_create( p_stream->p_sout, sizeof( *p_grab ) );
  1559.     if( p_grab == NULL )
  1560.         return NULL;
  1561.     p_grab->p_module    = NULL;
  1562.     p_grab->psz_access  = strdup( "grab" );
  1563.     p_grab->p_cfg       = NULL;
  1564.     p_grab->psz_path    = strdup( "" );
  1565.     p_grab->p_sys       = (sout_access_out_sys_t *)p_stream;
  1566.     p_grab->pf_seek     = NULL;
  1567.     p_grab->pf_write    = AccessOutGrabberWrite;
  1568.     vlc_object_attach( p_grab, p_stream );
  1569.     return p_grab;
  1570. }