rtp.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:68k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * rtp.c: rtp stream output module
  3.  *****************************************************************************
  4.  * Copyright (C) 2003-2004 VideoLAN
  5.  * $Id: rtp.c 8412 2004-08-10 15:02:11Z hartman $
  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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <stdlib.h>
  27. #include <errno.h>
  28. #include <vlc/vlc.h>
  29. #include <vlc/input.h>
  30. #include <vlc/sout.h>
  31. #include "vlc_httpd.h"
  32. #include "network.h"
  33. /*****************************************************************************
  34.  * Module descriptor
  35.  *****************************************************************************/
  36. #define DST_TEXT N_("Destination")
  37. #define DST_LONGTEXT N_( 
  38.     "Allows you to specify the output URL used for the streaming output." )
  39. #define SDP_TEXT N_("SDP")
  40. #define SDP_LONGTEXT N_( 
  41.     "Allows you to specify the SDP used for the streaming output. " 
  42.     "You must use an url: http://location to access the SDP via HTTP, " 
  43.     "rtsp://location for RTSP access, and sap:// for the SDP to be " 
  44.     "announced via SAP." )
  45. #define MUX_TEXT N_("Muxer")
  46. #define MUX_LONGTEXT N_( 
  47.     "Allows you to specify the muxer used for the streaming output." )
  48. #define NAME_TEXT N_("Session name")
  49. #define NAME_LONGTEXT N_( 
  50.     "Allows you to specify the session name used for the streaming output." )
  51. #define DESC_TEXT N_("Session description")
  52. #define DESC_LONGTEXT N_( 
  53.     "Allows you to give a broader description of the stream." )
  54. #define URL_TEXT N_("Session URL")
  55. #define URL_LONGTEXT N_( 
  56.     "Allows you to specify a URL with additional information on the stream." )
  57. #define EMAIL_TEXT N_("Session email")
  58. #define EMAIL_LONGTEXT N_( 
  59.     "Allows you to specify contact e-mail address for this session." )
  60. #define PORT_TEXT N_("Port")
  61. #define PORT_LONGTEXT N_( 
  62.     "Allows you to specify the base port used for the RTP streaming." )
  63. #define PORT_AUDIO_TEXT N_("Audio port")
  64. #define PORT_AUDIO_LONGTEXT N_( 
  65.     "Allows you to specify the default audio port used for the RTP streaming." )
  66. #define PORT_VIDEO_TEXT N_("Video port")
  67. #define PORT_VIDEO_LONGTEXT N_( 
  68.     "Allows you to specify the default video port used for the RTP streaming." )
  69. #define TTL_TEXT N_("Time to live")
  70. #define TTL_LONGTEXT N_( 
  71.     "Allows you to specify the time to live for the output stream." )
  72. static int  Open ( vlc_object_t * );
  73. static void Close( vlc_object_t * );
  74. #define SOUT_CFG_PREFIX "sout-rtp-"
  75. vlc_module_begin();
  76.     set_description( _("RTP stream output") );
  77.     set_capability( "sout stream", 0 );
  78.     add_shortcut( "rtp" );
  79.     add_string( SOUT_CFG_PREFIX "dst", "", NULL, DST_TEXT,
  80.                 DST_LONGTEXT, VLC_TRUE );
  81.     add_string( SOUT_CFG_PREFIX "sdp", "", NULL, SDP_TEXT,
  82.                 SDP_LONGTEXT, VLC_TRUE );
  83.     add_string( SOUT_CFG_PREFIX "mux", "", NULL, MUX_TEXT,
  84.                 MUX_LONGTEXT, VLC_TRUE );
  85.     add_string( SOUT_CFG_PREFIX "name", "NONE", NULL, NAME_TEXT,
  86.                 NAME_LONGTEXT, VLC_TRUE );
  87.     add_string( SOUT_CFG_PREFIX "description", "", NULL, DESC_TEXT,
  88.                 DESC_LONGTEXT, VLC_TRUE );
  89.     add_string( SOUT_CFG_PREFIX "url", "", NULL, URL_TEXT,
  90.                 URL_LONGTEXT, VLC_TRUE );
  91.     add_string( SOUT_CFG_PREFIX "email", "", NULL, EMAIL_TEXT,
  92.                 EMAIL_LONGTEXT, VLC_TRUE );
  93.     add_integer( SOUT_CFG_PREFIX "port-audio", 1234, NULL, PORT_AUDIO_TEXT,
  94.                  PORT_LONGTEXT, VLC_TRUE );
  95.     add_integer( SOUT_CFG_PREFIX "port-video", 1236, NULL, PORT_VIDEO_TEXT,
  96.                  PORT_LONGTEXT, VLC_TRUE );
  97.     add_integer( SOUT_CFG_PREFIX "port", 1238, NULL, PORT_TEXT,
  98.                  PORT_LONGTEXT, VLC_TRUE );
  99.     add_integer( SOUT_CFG_PREFIX "ttl", 0, NULL, TTL_TEXT,
  100.                  TTL_LONGTEXT, VLC_TRUE );
  101.     set_callbacks( Open, Close );
  102. vlc_module_end();
  103. /*****************************************************************************
  104.  * Exported prototypes
  105.  *****************************************************************************/
  106. static const char *ppsz_sout_options[] = {
  107.     "dst", "name", "port", "port-audio", "port-video", "*sdp", "ttl", "mux",
  108.     "description", "url","email", NULL
  109. };
  110. static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
  111. static int               Del ( sout_stream_t *, sout_stream_id_t * );
  112. static int               Send( sout_stream_t *, sout_stream_id_t *,
  113.                                block_t* );
  114. /* For unicast/interleaved streaming */
  115. typedef struct
  116. {
  117.     char    *psz_session;
  118.     int64_t i_last; /* for timeout */
  119.     /* is it in "play" state */
  120.     vlc_bool_t b_playing;
  121.     /* output (id-access) */
  122.     int               i_id;
  123.     sout_stream_id_t  **id;
  124.     int               i_access;
  125.     sout_access_out_t **access;
  126. } rtsp_client_t;
  127. struct sout_stream_sys_t
  128. {
  129.     /* sdp */
  130.     int64_t i_sdp_id;
  131.     int     i_sdp_version;
  132.     char    *psz_sdp;
  133.     vlc_mutex_t  lock_sdp;
  134.     char        *psz_session_name;
  135.     char        *psz_session_description;
  136.     char        *psz_session_url;
  137.     char        *psz_session_email;
  138.     /* */
  139.     vlc_bool_t b_export_sdp_file;
  140.     char *psz_sdp_file;
  141.     /* sap */
  142.     vlc_bool_t b_export_sap;
  143.     session_descriptor_t *p_session;
  144.     httpd_host_t *p_httpd_host;
  145.     httpd_file_t *p_httpd_file;
  146.     httpd_host_t *p_rtsp_host;
  147.     httpd_url_t  *p_rtsp_url;
  148.     char         *psz_rtsp_control;
  149.     char         *psz_rtsp_path;
  150.     /* */
  151.     char *psz_destination;
  152.     int  i_port;
  153.     int  i_port_audio;
  154.     int  i_port_video;
  155.     int  i_ttl;
  156.     /* when need to use a private one or when using muxer */
  157.     int i_payload_type;
  158.     /* in case we do TS/PS over rtp */
  159.     sout_mux_t        *p_mux;
  160.     sout_access_out_t *p_access;
  161.     int               i_mtu;
  162.     sout_access_out_t *p_grab;
  163.     uint16_t          i_sequence;
  164.     uint32_t          i_timestamp_start;
  165.     uint8_t           ssrc[4];
  166.     block_t           *packet;
  167.     /* */
  168.     vlc_mutex_t      lock_es;
  169.     int              i_es;
  170.     sout_stream_id_t **es;
  171.     /* */
  172.     int              i_rtsp;
  173.     rtsp_client_t    **rtsp;
  174. };
  175. typedef int (*pf_rtp_packetizer_t)( sout_stream_t *, sout_stream_id_t *,
  176.                                     block_t * );
  177. struct sout_stream_id_t
  178. {
  179.     sout_stream_t *p_stream;
  180.     /* rtp field */
  181.     uint8_t     i_payload_type;
  182.     uint16_t    i_sequence;
  183.     uint32_t    i_timestamp_start;
  184.     uint8_t     ssrc[4];
  185.     /* for sdp */
  186.     int         i_clock_rate;
  187.     char        *psz_rtpmap;
  188.     char        *psz_fmtp;
  189.     char        *psz_destination;
  190.     int         i_port;
  191.     int         i_cat;
  192.     /* Packetizer specific fields */
  193.     pf_rtp_packetizer_t pf_packetize;
  194.     int           i_mtu;
  195.     /* for sending the packets */
  196.     sout_access_out_t *p_access;
  197.     vlc_mutex_t       lock_rtsp;
  198.     int               i_rtsp_access;
  199.     sout_access_out_t **rtsp_access;
  200.     /* */
  201.     sout_input_t      *p_input;
  202.     /* RTSP url control */
  203.     httpd_url_t  *p_rtsp_url;
  204. };
  205. static int AccessOutGrabberWrite( sout_access_out_t *, block_t * );
  206. static void SDPHandleUrl( sout_stream_t *, char * );
  207. static int SapSetup( sout_stream_t *p_stream );
  208. static int FileSetup( sout_stream_t *p_stream );
  209. static int HttpSetup( sout_stream_t *p_stream, vlc_url_t * );
  210. static int RtspSetup( sout_stream_t *p_stream, vlc_url_t * );
  211. static int  RtspCallback( httpd_callback_sys_t *, httpd_client_t *,
  212.                           httpd_message_t *, httpd_message_t * );
  213. static int  RtspCallbackId( httpd_callback_sys_t *, httpd_client_t *,
  214.                             httpd_message_t *, httpd_message_t * );
  215. static rtsp_client_t *RtspClientNew( sout_stream_t *, char *psz_session );
  216. static rtsp_client_t *RtspClientGet( sout_stream_t *, char *psz_session );
  217. static void           RtspClientDel( sout_stream_t *, rtsp_client_t * );
  218. /*****************************************************************************
  219.  * Open:
  220.  *****************************************************************************/
  221. static int Open( vlc_object_t *p_this )
  222. {
  223.     sout_stream_t       *p_stream = (sout_stream_t*)p_this;
  224.     sout_instance_t     *p_sout = p_stream->p_sout;
  225.     sout_stream_sys_t   *p_sys;
  226.     vlc_value_t         val;
  227.     sout_CfgParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options, p_stream->p_cfg );
  228.     p_sys = malloc( sizeof( sout_stream_sys_t ) );
  229.     p_sys->psz_destination = var_GetString( p_stream, SOUT_CFG_PREFIX "dst" );
  230.     if( *p_sys->psz_destination == '' )
  231.     {
  232.         free( p_sys->psz_destination );
  233.         p_sys->psz_destination = NULL;
  234.     }
  235.     p_sys->psz_session_name = var_GetString( p_stream, SOUT_CFG_PREFIX "name" );
  236.     p_sys->psz_session_description = var_GetString( p_stream, SOUT_CFG_PREFIX "description" );
  237.     p_sys->psz_session_url = var_GetString( p_stream, SOUT_CFG_PREFIX "url" );
  238.     p_sys->psz_session_email = var_GetString( p_stream, SOUT_CFG_PREFIX "email" );
  239.     p_sys->i_port       = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port" );
  240.     p_sys->i_port_audio = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-audio" );
  241.     p_sys->i_port_video = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-video" );
  242.     p_sys->psz_sdp_file = NULL;
  243.     if( p_sys->i_port_audio == p_sys->i_port_video )
  244.     {
  245.         msg_Err( p_stream, "audio and video port cannot be the same" );
  246.         p_sys->i_port_audio = 0;
  247.         p_sys->i_port_video = 0;
  248.     }
  249.     if( !p_sys->psz_session_name )
  250.     {
  251.         if( p_sys->psz_destination )
  252.             p_sys->psz_session_name = strdup( p_sys->psz_destination );
  253.         else
  254.            p_sys->psz_session_name = strdup( "NONE" );
  255.     }
  256.     if( !p_sys->psz_destination || *p_sys->psz_destination == '' )
  257.     {
  258.         sout_cfg_t *p_cfg;
  259.         vlc_bool_t b_ok = VLC_FALSE;
  260.         for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
  261.         {
  262.             if( !strcmp( p_cfg->psz_name, "sdp" ) )
  263.             {
  264.                 if( p_cfg->psz_value && !strncasecmp( p_cfg->psz_value, "rtsp", 4 ) )
  265.                 {
  266.                     b_ok = VLC_TRUE;
  267.                     break;
  268.                 }
  269.             }
  270.         }
  271.         if( !b_ok )
  272.         {
  273.             vlc_value_t val2;
  274.             var_Get( p_stream, SOUT_CFG_PREFIX "sdp", &val2 );
  275.             if( !strncasecmp( val2.psz_string, "rtsp", 4 ) )
  276.                 b_ok = VLC_TRUE;
  277.             free( val2.psz_string );
  278.         }
  279.         if( !b_ok )
  280.         {
  281.             msg_Err( p_stream, "missing destination and not in rtsp mode" );
  282.             free( p_sys );
  283.             return VLC_EGENERIC;
  284.         }
  285.         p_sys->psz_destination = NULL;
  286.     }
  287.     else if( p_sys->i_port <= 0 )
  288.     {
  289.         msg_Err( p_stream, "invalid port" );
  290.         free( p_sys );
  291.         return VLC_EGENERIC;
  292.     }
  293.     var_Get( p_stream, SOUT_CFG_PREFIX "ttl", &val );
  294.     p_sys->i_ttl = val.i_int;
  295.     p_sys->i_payload_type = 96;
  296.     p_sys->i_es = 0;
  297.     p_sys->es   = NULL;
  298.     p_sys->i_rtsp = 0;
  299.     p_sys->rtsp   = NULL;
  300.     p_sys->psz_sdp = NULL;
  301.     p_sys->i_sdp_id = mdate();
  302.     p_sys->i_sdp_version = 1;
  303.     p_sys->psz_sdp = NULL;
  304.     p_sys->b_export_sap = VLC_FALSE;
  305.     p_sys->b_export_sdp_file = VLC_FALSE;
  306.     p_sys->p_session = NULL;
  307.     p_sys->p_httpd_host = NULL;
  308.     p_sys->p_httpd_file = NULL;
  309.     p_sys->p_rtsp_host  = NULL;
  310.     p_sys->p_rtsp_url   = NULL;
  311.     p_sys->psz_rtsp_control = NULL;
  312.     p_sys->psz_rtsp_path = NULL;
  313.     vlc_mutex_init( p_stream, &p_sys->lock_sdp );
  314.     vlc_mutex_init( p_stream, &p_sys->lock_es );
  315.     p_stream->pf_add    = Add;
  316.     p_stream->pf_del    = Del;
  317.     p_stream->pf_send   = Send;
  318.     p_stream->p_sys     = p_sys;
  319.     var_Get( p_stream, SOUT_CFG_PREFIX "mux", &val );
  320.     if( *val.psz_string )
  321.     {
  322.         sout_access_out_t *p_grab;
  323.         char *psz_rtpmap;
  324.         char access[100];
  325.         char url[strlen( p_sys->psz_destination ) + 1 + 12 + 1];
  326.         /* Check muxer type */
  327.         if( !strncasecmp( val.psz_string, "ps", 2 ) || !strncasecmp( val.psz_string, "mpeg1", 5 ) )
  328.         {
  329.             psz_rtpmap = "MP2P/90000";
  330.         }
  331.         else if( !strncasecmp( val.psz_string, "ts", 2 ) )
  332.         {
  333.             psz_rtpmap = "MP2T/90000";
  334.             p_sys->i_payload_type = 33;
  335.         }
  336.         else
  337.         {
  338.             msg_Err( p_stream, "unsupported muxer type with rtp (only ts/ps)" );
  339.             return VLC_EGENERIC;
  340.         }
  341.         /* create the access out */
  342.         if( p_sys->i_ttl > 0 )
  343.         {
  344.             sprintf( access, "udp{raw,ttl=%d}", p_sys->i_ttl );
  345.         }
  346.         else
  347.         {
  348.             sprintf( access, "udp{raw}" );
  349.         }
  350.         sprintf( url, "%s:%d", p_sys->psz_destination, p_sys->i_port );
  351.         if( !( p_sys->p_access = sout_AccessOutNew( p_sout, access, url ) ) )
  352.         {
  353.             msg_Err( p_stream, "cannot create the access out for %s://%s",
  354.                      access, url );
  355.             free( p_sys );
  356.             return VLC_EGENERIC;
  357.         }
  358.         p_sys->i_mtu = config_GetInt( p_stream, "mtu" );  /* XXX beurk */
  359.         if( p_sys->i_mtu <= 16 )
  360.         {
  361.             /* better than nothing */
  362.             p_sys->i_mtu = 1500;
  363.         }
  364.         /* the access out grabber TODO export it as sout_AccessOutGrabberNew */
  365.         p_grab = p_sys->p_grab =
  366.             vlc_object_create( p_sout, sizeof( sout_access_out_t ) );
  367.         p_grab->p_module    = NULL;
  368.         p_grab->p_sout      = p_sout;
  369.         p_grab->psz_access  = strdup( "grab" );
  370.         p_grab->p_cfg       = NULL;
  371.         p_grab->psz_name    = strdup( "" );
  372.         p_grab->p_sys       = (sout_access_out_sys_t*)p_stream;
  373.         p_grab->pf_seek     = NULL;
  374.         p_grab->pf_write    = AccessOutGrabberWrite;
  375.         /* the muxer */
  376.         if( !( p_sys->p_mux = sout_MuxNew( p_sout, val.psz_string, p_sys->p_grab ) ) )
  377.         {
  378.             msg_Err( p_stream, "cannot create the muxer (%s)", val.psz_string );
  379.             sout_AccessOutDelete( p_sys->p_grab );
  380.             sout_AccessOutDelete( p_sys->p_access );
  381.             free( p_sys );
  382.             return VLC_EGENERIC;
  383.         }
  384.         /* create the SDP for a muxed stream (only once) */
  385.         /* FIXME  http://www.faqs.org/rfcs/rfc2327.html
  386.            All text fields should be UTF-8 encoded. Use global a:charset to announce this.
  387.            o= - should be local username (no spaces allowed)
  388.            o= time should be hashed with some other value to garantue uniqueness
  389.            o= we need IP6 support?
  390.            o= don't use the localhost address. use fully qualified domain name or IP4 address
  391.            p= international phone number (pass via vars?)
  392.            c= IP6 support
  393.            c= /ttl should only be added in case of multicast
  394.            a= recvonly (missing)
  395.            a= type:broadcast (missing)
  396.            a= charset: (normally charset should be UTF-8, this can be used to override s= and i=)
  397.            a= x-plgroup: (missing)
  398.            RTP packets need to get the correct src IP address  */
  399.         p_sys->psz_sdp =
  400.             malloc( 10 + 30 + 10 + strlen( p_sys->psz_session_name ) +
  401.                     10 + strlen( p_sys->psz_session_description ) + 10 + strlen( p_sys->psz_session_url ) +
  402.                     10 + strlen( p_sys->psz_session_email ) + 10 + strlen( p_sys->psz_destination ) +
  403.                     10 + 10 + strlen( PACKAGE_STRING ) +
  404.                     20 + 10 + 20 + 10 + strlen( psz_rtpmap ) );
  405.         sprintf( p_sys->psz_sdp,
  406.                  "v=0rn"
  407.                  "o=- "I64Fd" %d IN IP4 127.0.0.1rn"
  408.                  "s=%srn"
  409.                  "i=%srn"
  410.                  "u=%srn"
  411.                  "e=%srn"
  412.                  "t=0 0rn" /* permanent stream */ /* when scheduled from vlm, we should set this info correctly */
  413.                  "a=tool:"PACKAGE_STRING"rn"
  414.                  "c=IN IP4 %s/%drn"
  415.                  "m=video %d RTP/AVP %drn"
  416.                  "a=rtpmap:%d %srn",
  417.                  p_sys->i_sdp_id, p_sys->i_sdp_version,
  418.                  p_sys->psz_session_name,
  419.                  p_sys->psz_session_description,
  420.                  p_sys->psz_session_url,
  421.                  p_sys->psz_session_email,
  422.                  p_sys->psz_destination, p_sys->i_ttl,
  423.                  p_sys->i_port, p_sys->i_payload_type,
  424.                  p_sys->i_payload_type, psz_rtpmap );
  425.         fprintf( stderr, "sdp=%s", p_sys->psz_sdp );
  426.         /* create the rtp context */
  427.         p_sys->ssrc[0] = rand()&0xff;
  428.         p_sys->ssrc[1] = rand()&0xff;
  429.         p_sys->ssrc[2] = rand()&0xff;
  430.         p_sys->ssrc[3] = rand()&0xff;
  431.         p_sys->i_sequence = rand()&0xffff;
  432.         p_sys->i_timestamp_start = rand()&0xffffffff;
  433.         p_sys->packet = NULL;
  434.     }
  435.     else
  436.     {
  437.         p_sys->p_mux    = NULL;
  438.         p_sys->p_access = NULL;
  439.         p_sys->p_grab   = NULL;
  440.     }
  441.     free( val.psz_string );
  442.     var_Get( p_stream, SOUT_CFG_PREFIX "sdp", &val );
  443.     if( *val.psz_string )
  444.     {
  445.         sout_cfg_t *p_cfg;
  446.         SDPHandleUrl( p_stream, val.psz_string );
  447.         for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
  448.         {
  449.             if( !strcmp( p_cfg->psz_name, "sdp" ) )
  450.             {
  451.                 if( p_cfg->psz_value == NULL || *p_cfg->psz_value == '' )
  452.                     continue;
  453.                 if( !strcmp( p_cfg->psz_value, val.psz_string ) )   /* needed both :sout-rtp-sdp= and rtp{sdp=} can be used */
  454.                     continue;
  455.                 SDPHandleUrl( p_stream, p_cfg->psz_value );
  456.             }
  457.         }
  458.     }
  459.     free( val.psz_string );
  460.     /* update p_sout->i_out_pace_nocontrol */
  461.     p_stream->p_sout->i_out_pace_nocontrol++;
  462.     return VLC_SUCCESS;
  463. }
  464. /*****************************************************************************
  465.  * Close:
  466.  *****************************************************************************/
  467. static void Close( vlc_object_t * p_this )
  468. {
  469.     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
  470.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  471.     /* update p_sout->i_out_pace_nocontrol */
  472.     p_stream->p_sout->i_out_pace_nocontrol--;
  473.     if( p_sys->p_mux )
  474.     {
  475.         sout_MuxDelete( p_sys->p_mux );
  476.         sout_AccessOutDelete( p_sys->p_access );
  477.         sout_AccessOutDelete( p_sys->p_grab );
  478.         if( p_sys->packet )
  479.         {
  480.             block_Release( p_sys->packet );
  481.         }
  482.     }
  483.     while( p_sys->i_rtsp > 0 )
  484.     {
  485.         RtspClientDel( p_stream, p_sys->rtsp[0] );
  486.     }
  487.     vlc_mutex_destroy( &p_sys->lock_sdp );
  488.     if( p_sys->p_httpd_file )
  489.     {
  490.         httpd_FileDelete( p_sys->p_httpd_file );
  491.     }
  492.     if( p_sys->p_httpd_host )
  493.     {
  494.         httpd_HostDelete( p_sys->p_httpd_host );
  495.     }
  496.     if( p_sys->p_rtsp_url )
  497.     {
  498.         httpd_UrlDelete( p_sys->p_rtsp_url );
  499.     }
  500.     if( p_sys->p_rtsp_host )
  501.     {
  502.         httpd_HostDelete( p_sys->p_rtsp_host );
  503.     }
  504. #if 0
  505.     /* why? is this disabled? */
  506.     if( p_sys->psz_session_name )
  507.     {
  508.         free( p_sys->psz_session_name );
  509.         p_sys->psz_session_name = NULL;
  510.     }
  511.     if( p_sys->psz_session_description )
  512.     {
  513.         free( p_sys->psz_session_description );
  514.         p_sys->psz_session_description = NULL;
  515.     }
  516.     if( p_sys->psz_session_url )
  517.     {
  518.         free( p_sys->psz_session_url );
  519.         p_sys->psz_session_url = NULL;
  520.     }
  521.     if( p_sys->psz_session_email )
  522.     {
  523.         free( p_sys->psz_session_email );
  524.         p_sys->psz_session_email = NULL;
  525.     }
  526. #endif
  527.     if( p_sys->psz_sdp )
  528.     {
  529.         free( p_sys->psz_sdp );
  530.     }
  531.     free( p_sys );
  532. }
  533. /*****************************************************************************
  534.  * SDPHandleUrl:
  535.  *****************************************************************************/
  536. static void SDPHandleUrl( sout_stream_t *p_stream, char *psz_url )
  537. {
  538.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  539.     vlc_url_t url;
  540.     vlc_UrlParse( &url, psz_url, 0 );
  541.     if( url.psz_protocol && !strcasecmp( url.psz_protocol, "http" ) )
  542.     {
  543.         if( p_sys->p_httpd_file )
  544.         {
  545.             msg_Err( p_stream, "You can used sdp=http:// only once" );
  546.             return;
  547.         }
  548.         if( HttpSetup( p_stream, &url ) )
  549.         {
  550.             msg_Err( p_stream, "cannot export sdp as http" );
  551.         }
  552.     }
  553.     else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "rtsp" ) )
  554.     {
  555.         if( p_sys->p_rtsp_url )
  556.         {
  557.             msg_Err( p_stream, "You can used sdp=rtsp:// only once" );
  558.             return;
  559.         }
  560.         /* FIXME test if destination is multicast or no destination at all FIXME */
  561.         if( RtspSetup( p_stream, &url ) )
  562.         {
  563.             msg_Err( p_stream, "cannot export sdp as rtsp" );
  564.         }
  565.     }
  566.     else if( ( url.psz_protocol && !strcasecmp( url.psz_protocol, "sap" ) ) || 
  567.              ( url.psz_host && !strcasecmp( url.psz_host, "sap" ) ) )
  568.     {
  569.         p_sys->b_export_sap = VLC_TRUE;
  570.         SapSetup( p_stream );
  571.     }
  572.     else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "file" ) )
  573.     {
  574.         if( p_sys->b_export_sdp_file )
  575.         {
  576.             msg_Err( p_stream, "You can used sdp=file:// only once" );
  577.             return;
  578.         }
  579.         p_sys->b_export_sdp_file = VLC_TRUE;
  580.         psz_url = &psz_url[5];
  581.         if( psz_url[0] == '/' && psz_url[1] == '/' )
  582.             psz_url += 2;
  583.         p_sys->psz_sdp_file = strdup( psz_url );
  584.     }
  585.     else
  586.     {
  587.         msg_Warn( p_stream, "unknown protocol for SDP (%s)",
  588.                   url.psz_protocol );
  589.     }
  590.     vlc_UrlClean( &url );
  591. }
  592. /*****************************************************************************
  593.  * SDPGenerate
  594.  *****************************************************************************/
  595.         /* FIXME  http://www.faqs.org/rfcs/rfc2327.html
  596.            All text fields should be UTF-8 encoded. Use global a:charset to announce this.
  597.            o= - should be local username (no spaces allowed)
  598.            o= time should be hashed with some other value to garantue uniqueness
  599.            o= we need IP6 support?
  600.            o= don't use the localhost address. use fully qualified domain name or IP4 address
  601.            p= international phone number (pass via vars?)
  602.            c= IP6 support
  603.            c= /ttl should only be added in case of multicast
  604.            a= recvonly (missing)
  605.            a= type:broadcast (missing)
  606.            a= charset: (normally charset should be UTF-8, this can be used to override s= and i=)
  607.            a= x-plgroup: (missing)
  608.            RTP packets need to get the correct src IP address  */
  609. static char *SDPGenerate( sout_stream_t *p_stream, char *psz_destination, vlc_bool_t b_rtsp )
  610. {
  611.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  612.     int i_size;
  613.     char *psz_sdp, *p;
  614.     int i;
  615.     i_size = strlen( "v=0rn" ) +
  616.              strlen( "o=- * * IN IP4 127.0.0.1rn" ) + 10 + 10 +
  617.              strlen( "s=*rn" ) + strlen( p_sys->psz_session_name ) +
  618.              strlen( "i=*rn" ) + strlen( p_sys->psz_session_description ) +
  619.              strlen( "u=*rn" ) + strlen( p_sys->psz_session_url ) +
  620.              strlen( "e=*rn" ) + strlen( p_sys->psz_session_email ) +
  621.              strlen( "t=0 0rn" ) + /* permanent stream */ /* when scheduled from vlm, we should set this info correctly */
  622.              strlen( "a=tool:"PACKAGE_STRING"rn" ) +
  623.              strlen( "c=IN IP4 */*rn" ) + 20 + 10 +
  624.              strlen( psz_destination ? psz_destination : "0.0.0.0") ;
  625.     for( i = 0; i < p_sys->i_es; i++ )
  626.     {
  627.         sout_stream_id_t *id = p_sys->es[i];
  628.         i_size += strlen( "m=**d*o * RTP/AVP *rn" ) + 10 + 10;
  629.         if( id->psz_rtpmap )
  630.         {
  631.             i_size += strlen( "a=rtpmap:* *rn" ) + strlen( id->psz_rtpmap )+10;
  632.         }
  633.         if( id->psz_fmtp )
  634.         {
  635.             i_size += strlen( "a=fmtp:* *rn" ) + strlen( id->psz_fmtp ) + 10;
  636.         }
  637.         if( b_rtsp )
  638.         {
  639.             i_size += strlen( "a=control:*/trackid=*rn" ) + strlen( p_sys->psz_rtsp_control ) + 10;
  640.         }
  641.     }
  642.     p = psz_sdp = malloc( i_size );
  643.     p += sprintf( p, "v=0rn" );
  644.     p += sprintf( p, "o=- "I64Fd" %d IN IP4 127.0.0.1rn",
  645.                   p_sys->i_sdp_id, p_sys->i_sdp_version );
  646.     if( *p_sys->psz_session_name )
  647.         p += sprintf( p, "s=%srn", p_sys->psz_session_name );
  648.     if( *p_sys->psz_session_description )
  649.         p += sprintf( p, "i=%srn", p_sys->psz_session_description );
  650.     if( *p_sys->psz_session_url )
  651.         p += sprintf( p, "u=%srn", p_sys->psz_session_url );
  652.     if( *p_sys->psz_session_email )
  653.         p += sprintf( p, "e=%srn", p_sys->psz_session_email );
  654.     p += sprintf( p, "t=0 0rn" ); /* permanent stream */ /* when scheduled from vlm, we should set this info correctly */
  655.     p += sprintf( p, "a=tool:"PACKAGE_STRING"rn" );
  656.     p += sprintf( p, "c=IN IP4 %s/%drn", psz_destination ? psz_destination : "0.0.0.0",
  657.                   p_sys->i_ttl );
  658.     for( i = 0; i < p_sys->i_es; i++ )
  659.     {
  660.         sout_stream_id_t *id = p_sys->es[i];
  661.         if( id->i_cat == AUDIO_ES )
  662.         {
  663.             p += sprintf( p, "m=audio %d RTP/AVP %drn",
  664.                           id->i_port, id->i_payload_type );
  665.         }
  666.         else if( id->i_cat == VIDEO_ES )
  667.         {
  668.             p += sprintf( p, "m=video %d RTP/AVP %drn",
  669.                           id->i_port, id->i_payload_type );
  670.         }
  671.         else
  672.         {
  673.             continue;
  674.         }
  675.         if( id->psz_rtpmap )
  676.         {
  677.             p += sprintf( p, "a=rtpmap:%d %srn", id->i_payload_type,
  678.                           id->psz_rtpmap );
  679.         }
  680.         if( id->psz_fmtp )
  681.         {
  682.             p += sprintf( p, "a=fmtp:%d %srn", id->i_payload_type,
  683.                           id->psz_fmtp );
  684.         }
  685.         if( b_rtsp )
  686.         {
  687.             p += sprintf( p, "a=control:%s/trackid=%drn", p_sys->psz_rtsp_control, i );
  688.         }
  689.     }
  690.     return psz_sdp;
  691. }
  692. /*****************************************************************************
  693.  *
  694.  *****************************************************************************/
  695. static int rtp_packetize_l16  ( sout_stream_t *, sout_stream_id_t *, block_t * );
  696. static int rtp_packetize_l8   ( sout_stream_t *, sout_stream_id_t *, block_t * );
  697. static int rtp_packetize_mpa  ( sout_stream_t *, sout_stream_id_t *, block_t * );
  698. static int rtp_packetize_mpv  ( sout_stream_t *, sout_stream_id_t *, block_t * );
  699. static int rtp_packetize_ac3  ( sout_stream_t *, sout_stream_id_t *, block_t * );
  700. static int rtp_packetize_split( sout_stream_t *, sout_stream_id_t *, block_t * );
  701. static int rtp_packetize_mp4a ( sout_stream_t *, sout_stream_id_t *, block_t * );
  702. static int rtp_packetize_h263 ( sout_stream_t *, sout_stream_id_t *, block_t * );
  703. static void sprintf_hexa( char *s, uint8_t *p_data, int i_data )
  704. {
  705.     static const char hex[16] = "0123456789abcdef";
  706.     int i;
  707.     for( i = 0; i < i_data; i++ )
  708.     {
  709.         s[2*i+0] = hex[(p_data[i]>>4)&0xf];
  710.         s[2*i+1] = hex[(p_data[i]   )&0xf];
  711.     }
  712.     s[2*i_data] = '';
  713. }
  714. static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
  715. {
  716.     sout_instance_t   *p_sout = p_stream->p_sout;
  717.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  718.     sout_stream_id_t  *id;
  719.     sout_access_out_t *p_access = NULL;
  720.     int               i_port;
  721.     char              *psz_sdp;
  722.     if( p_sys->p_mux != NULL )
  723.     {
  724.         sout_input_t      *p_input  = NULL;
  725.         if( ( p_input = sout_MuxAddStream( p_sys->p_mux, p_fmt ) ) == NULL )
  726.         {
  727.             msg_Err( p_stream, "cannot add this stream to the muxer" );
  728.             return NULL;
  729.         }
  730.         id = malloc( sizeof( sout_stream_id_t ) );
  731.         memset( id, 0, sizeof( sout_stream_id_t ) );
  732.         id->p_access    = NULL;
  733.         id->p_input     = p_input;
  734.         id->pf_packetize= NULL;
  735.         id->p_rtsp_url  = NULL;
  736.         id->i_port      = 0;
  737.         return id;
  738.     }
  739.     /* Choose the port */
  740.     i_port = 0;
  741.     if( p_fmt->i_cat == AUDIO_ES && p_sys->i_port_audio > 0 )
  742.     {
  743.         i_port = p_sys->i_port_audio;
  744.         p_sys->i_port_audio = 0;
  745.     }
  746.     else if( p_fmt->i_cat == VIDEO_ES && p_sys->i_port_video > 0 )
  747.     {
  748.         i_port = p_sys->i_port_video;
  749.         p_sys->i_port_video = 0;
  750.     }
  751.     while( i_port == 0 )
  752.     {
  753.         if( p_sys->i_port != p_sys->i_port_audio && p_sys->i_port != p_sys->i_port_video )
  754.         {
  755.             i_port = p_sys->i_port;
  756.             p_sys->i_port += 2;
  757.             break;
  758.         }
  759.         p_sys->i_port += 2;
  760.     }
  761.     if( p_sys->psz_destination )
  762.     {
  763.         char access[100];
  764.         char url[strlen( p_sys->psz_destination ) + 1 + 12 + 1];
  765.         /* first try to create the access out */
  766.         if( p_sys->i_ttl > 0 )
  767.         {
  768.             sprintf( access, "udp{raw,ttl=%d}", p_sys->i_ttl );
  769.         }
  770.         else
  771.         {
  772.             sprintf( access, "udp{raw}" );
  773.         }
  774.         sprintf( url, "%s:%d", p_sys->psz_destination, i_port );
  775.         if( ( p_access = sout_AccessOutNew( p_sout, access, url ) ) == NULL )
  776.         {
  777.             msg_Err( p_stream, "cannot create the access out for %s://%s",
  778.                      access, url );
  779.             return NULL;
  780.         }
  781.         msg_Dbg( p_stream, "access out %s:%s", access, url );
  782.     }
  783.     /* not create the rtp specific stuff */
  784.     id = malloc( sizeof( sout_stream_id_t ) );
  785.     memset( id, 0, sizeof( sout_stream_id_t ) );
  786.     id->p_stream   = p_stream;
  787.     id->p_access   = p_access;
  788.     id->p_input    = NULL;
  789.     id->psz_rtpmap = NULL;
  790.     id->psz_fmtp   = NULL;
  791.     id->psz_destination = p_sys->psz_destination ? strdup( p_sys->psz_destination ) : NULL;
  792.     id->i_port = i_port;
  793.     id->p_rtsp_url = NULL;
  794.     vlc_mutex_init( p_stream, &id->lock_rtsp );
  795.     id->i_rtsp_access = 0;
  796.     id->rtsp_access = NULL;
  797.     switch( p_fmt->i_codec )
  798.     {
  799.         case VLC_FOURCC( 's', '1', '6', 'b' ):
  800.             if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 44100 )
  801.             {
  802.                 id->i_payload_type = 11;
  803.             }
  804.             else if( p_fmt->audio.i_channels == 2 &&
  805.                      p_fmt->audio.i_rate == 44100 )
  806.             {
  807.                 id->i_payload_type = 10;
  808.             }
  809.             else
  810.             {
  811.                 id->i_payload_type = p_sys->i_payload_type++;
  812.             }
  813.             id->psz_rtpmap = malloc( strlen( "L16/*/*" ) + 20+1 );
  814.             sprintf( id->psz_rtpmap, "L16/%d/%d", p_fmt->audio.i_rate,
  815.                      p_fmt->audio.i_channels );
  816.             id->i_clock_rate = p_fmt->audio.i_rate;
  817.             id->pf_packetize = rtp_packetize_l16;
  818.             break;
  819.         case VLC_FOURCC( 'u', '8', ' ', ' ' ):
  820.             id->i_payload_type = p_sys->i_payload_type++;
  821.             id->psz_rtpmap = malloc( strlen( "L8/*/*" ) + 20+1 );
  822.             sprintf( id->psz_rtpmap, "L8/%d/%d", p_fmt->audio.i_rate,
  823.                      p_fmt->audio.i_channels );
  824.             id->i_clock_rate = p_fmt->audio.i_rate;
  825.             id->pf_packetize = rtp_packetize_l8;
  826.             break;
  827.         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
  828.             id->i_payload_type = 14;
  829.             id->i_clock_rate = 90000;
  830.             id->psz_rtpmap = strdup( "MPA/90000" );
  831.             id->pf_packetize = rtp_packetize_mpa;
  832.             break;
  833.         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
  834.             id->i_payload_type = 32;
  835.             id->i_clock_rate = 90000;
  836.             id->psz_rtpmap = strdup( "MPV/90000" );
  837.             id->pf_packetize = rtp_packetize_mpv;
  838.             break;
  839.         case VLC_FOURCC( 'a', '5', '2', ' ' ):
  840.             id->i_payload_type = p_sys->i_payload_type++;
  841.             id->i_clock_rate = 90000;
  842.             id->psz_rtpmap = strdup( "ac3/90000" );
  843.             id->pf_packetize = rtp_packetize_ac3;
  844.             break;
  845.         case VLC_FOURCC( 'H', '2', '6', '3' ):
  846.             id->i_payload_type = p_sys->i_payload_type++;
  847.             id->i_clock_rate = 90000;
  848.             id->psz_rtpmap = strdup( "H263-1998/90000" );
  849.             id->pf_packetize = rtp_packetize_h263;
  850.             break;
  851.         case VLC_FOURCC( 'm', 'p', '4', 'v' ):
  852.         {
  853.             char hexa[2*p_fmt->i_extra +1];
  854.             id->i_payload_type = p_sys->i_payload_type++;
  855.             id->i_clock_rate = 90000;
  856.             id->psz_rtpmap = strdup( "MP4V-ES/90000" );
  857.             id->pf_packetize = rtp_packetize_split;
  858.             if( p_fmt->i_extra > 0 )
  859.             {
  860.                 id->psz_fmtp = malloc( 100 + 2 * p_fmt->i_extra );
  861.                 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
  862.                 sprintf( id->psz_fmtp,
  863.                          "profile-level-id=3; config=%s;", hexa );
  864.             }
  865.             break;
  866.         }
  867.         case VLC_FOURCC( 'm', 'p', '4', 'a' ):
  868.         {
  869.             char hexa[2*p_fmt->i_extra +1];
  870.             id->i_payload_type = p_sys->i_payload_type++;
  871.             id->i_clock_rate = p_fmt->audio.i_rate;
  872.             id->psz_rtpmap = malloc( strlen( "mpeg4-generic/" ) + 12 );
  873.             sprintf( id->psz_rtpmap, "mpeg4-generic/%d", p_fmt->audio.i_rate );
  874.             id->pf_packetize = rtp_packetize_mp4a;
  875.             id->psz_fmtp = malloc( 200 + 2 * p_fmt->i_extra );
  876.             sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
  877.             sprintf( id->psz_fmtp,
  878.                      "streamtype=5; profile-level-id=15; mode=AAC-hbr; "
  879.                      "config=%s; SizeLength=13;IndexLength=3; "
  880.                      "IndexDeltaLength=3; Profile=1;", hexa );
  881.             break;
  882.         }
  883.         default:
  884.             msg_Err( p_stream, "cannot add this stream (unsupported "
  885.                      "codec:%4.4s)", (char*)&p_fmt->i_codec );
  886.             free( id );
  887.             return NULL;
  888.     }
  889.     id->i_cat = p_fmt->i_cat;
  890.     id->ssrc[0] = rand()&0xff;
  891.     id->ssrc[1] = rand()&0xff;
  892.     id->ssrc[2] = rand()&0xff;
  893.     id->ssrc[3] = rand()&0xff;
  894.     id->i_sequence = rand()&0xffff;
  895.     id->i_timestamp_start = rand()&0xffffffff;
  896.     id->i_mtu    = config_GetInt( p_stream, "mtu" );  /* XXX beuk */
  897.     if( id->i_mtu <= 16 )
  898.     {
  899.         /* better than nothing */
  900.         id->i_mtu = 1500;
  901.     }
  902.     msg_Dbg( p_stream, "using mtu=%d", id->i_mtu );
  903.     if( p_sys->p_rtsp_url )
  904.     {
  905.         char psz_urlc[strlen( p_sys->psz_rtsp_control ) + 1 + 10];
  906.         sprintf( psz_urlc, "%s/trackid=%d", p_sys->psz_rtsp_path, p_sys->i_es );
  907.         fprintf( stderr, "rtsp: adding %sn", psz_urlc );
  908.         id->p_rtsp_url = httpd_UrlNewUnique( p_sys->p_rtsp_host, psz_urlc, NULL, NULL );
  909.         if( id->p_rtsp_url )
  910.         {
  911.             httpd_UrlCatch( id->p_rtsp_url, HTTPD_MSG_SETUP,    RtspCallbackId, (void*)id );
  912.             //httpd_UrlCatch( id->p_rtsp_url, HTTPD_MSG_PLAY,     RtspCallback, (void*)p_stream );
  913.             //httpd_UrlCatch( id->p_rtsp_url, HTTPD_MSG_PAUSE,    RtspCallback, (void*)p_stream );
  914.         }
  915.     }
  916.     /* Update p_sys context */
  917.     vlc_mutex_lock( &p_sys->lock_es );
  918.     TAB_APPEND( p_sys->i_es, p_sys->es, id );
  919.     vlc_mutex_unlock( &p_sys->lock_es );
  920.     psz_sdp = SDPGenerate( p_stream, p_sys->psz_destination, VLC_FALSE );
  921.     vlc_mutex_lock( &p_sys->lock_sdp );
  922.     free( p_sys->psz_sdp );
  923.     p_sys->psz_sdp = psz_sdp;
  924.     vlc_mutex_unlock( &p_sys->lock_sdp );
  925.     p_sys->i_sdp_version++;
  926.     fprintf( stderr, "sdp=%s", p_sys->psz_sdp );
  927.     /* Update SDP (sap/file) */
  928.     if( p_sys->b_export_sap ) SapSetup( p_stream );
  929.     if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
  930.     return id;
  931. }
  932. static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
  933. {
  934.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  935.     vlc_mutex_lock( &p_sys->lock_es );
  936.     TAB_REMOVE( p_sys->i_es, p_sys->es, id );
  937.     vlc_mutex_unlock( &p_sys->lock_es );
  938.     /* Release port */
  939.     if( id->i_port > 0 )
  940.     {
  941.         if( id->i_cat == AUDIO_ES && p_sys->i_port_audio == 0 )
  942.             p_sys->i_port_audio = id->i_port;
  943.         else if( id->i_cat == VIDEO_ES && p_sys->i_port_video == 0 )
  944.             p_sys->i_port_video = id->i_port;
  945.     }
  946.     if( id->p_access )
  947.     {
  948.         if( id->psz_rtpmap )
  949.         {
  950.             free( id->psz_rtpmap );
  951.         }
  952.         if( id->psz_fmtp )
  953.         {
  954.             free( id->psz_fmtp );
  955.         }
  956.         if( id->psz_destination )
  957.             free( id->psz_destination );
  958.         sout_AccessOutDelete( id->p_access );
  959.     }
  960.     else if( id->p_input )
  961.     {
  962.         sout_MuxDeleteStream( p_sys->p_mux, id->p_input );
  963.     }
  964.     if( id->p_rtsp_url )
  965.     {
  966.         httpd_UrlDelete( id->p_rtsp_url );
  967.     }
  968.     vlc_mutex_destroy( &id->lock_rtsp );
  969.     if( id->rtsp_access ) free( id->rtsp_access );
  970.     /* Update SDP (sap/file) */
  971.     if( p_sys->b_export_sap ) SapSetup( p_stream );
  972.     if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
  973.     free( id );
  974.     return VLC_SUCCESS;
  975. }
  976. static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
  977.                  block_t *p_buffer )
  978. {
  979.     block_t *p_next;
  980.     if( p_stream->p_sys->p_mux )
  981.     {
  982.         sout_MuxSendBuffer( p_stream->p_sys->p_mux, id->p_input, p_buffer );
  983.     }
  984.     else
  985.     {
  986.         while( p_buffer )
  987.         {
  988.             p_next = p_buffer->p_next;
  989.             if( id->pf_packetize( p_stream, id, p_buffer ) )
  990.             {
  991.                 break;
  992.             }
  993.             block_Release( p_buffer );
  994.             p_buffer = p_next;
  995.         }
  996.     }
  997.     return VLC_SUCCESS;
  998. }
  999. static int AccessOutGrabberWriteBuffer( sout_stream_t *p_stream,
  1000.                                         block_t *p_buffer )
  1001. {
  1002.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  1003.     int64_t  i_dts = p_buffer->i_dts;
  1004.     uint32_t i_timestamp = i_dts * 9 / 100;
  1005.     uint8_t         *p_data = p_buffer->p_buffer;
  1006.     unsigned int    i_data  = p_buffer->i_buffer;
  1007.     unsigned int    i_max   = p_sys->i_mtu - 12;
  1008.     int i_packet = ( p_buffer->i_buffer + i_max - 1 ) / i_max;
  1009.     while( i_data > 0 )
  1010.     {
  1011.         unsigned int i_size;
  1012.         /* output complete packet */
  1013.         if( p_sys->packet &&
  1014.             p_sys->packet->i_buffer + i_data > i_max )
  1015.         {
  1016.             sout_AccessOutWrite( p_sys->p_access, p_sys->packet );
  1017.             p_sys->packet = NULL;
  1018.         }
  1019.         if( p_sys->packet == NULL )
  1020.         {
  1021.             /* allocate a new packet */
  1022.             p_sys->packet = block_New( p_stream, p_sys->i_mtu );
  1023.             p_sys->packet->p_buffer[ 0] = 0x80;
  1024.             p_sys->packet->p_buffer[ 1] = 0x80|p_sys->i_payload_type;
  1025.             p_sys->packet->p_buffer[ 2] = ( p_sys->i_sequence >> 8)&0xff;
  1026.             p_sys->packet->p_buffer[ 3] = ( p_sys->i_sequence     )&0xff;
  1027.             p_sys->packet->p_buffer[ 4] = ( i_timestamp >> 24 )&0xff;
  1028.             p_sys->packet->p_buffer[ 5] = ( i_timestamp >> 16 )&0xff;
  1029.             p_sys->packet->p_buffer[ 6] = ( i_timestamp >>  8 )&0xff;
  1030.             p_sys->packet->p_buffer[ 7] = ( i_timestamp       )&0xff;
  1031.             p_sys->packet->p_buffer[ 8] = p_sys->ssrc[0];
  1032.             p_sys->packet->p_buffer[ 9] = p_sys->ssrc[1];
  1033.             p_sys->packet->p_buffer[10] = p_sys->ssrc[2];
  1034.             p_sys->packet->p_buffer[11] = p_sys->ssrc[3];
  1035.             p_sys->packet->i_buffer = 12;
  1036.             p_sys->packet->i_dts = i_dts;
  1037.             p_sys->packet->i_length = p_buffer->i_length / i_packet;
  1038.             i_dts += p_sys->packet->i_length;
  1039.             p_sys->i_sequence++;
  1040.         }
  1041.         i_size = __MIN( i_data, p_sys->i_mtu - p_sys->packet->i_buffer );
  1042.         memcpy( &p_sys->packet->p_buffer[p_sys->packet->i_buffer],
  1043.                 p_data, i_size );
  1044.         p_sys->packet->i_buffer += i_size;
  1045.         p_data += i_size;
  1046.         i_data -= i_size;
  1047.     }
  1048.     return VLC_SUCCESS;
  1049. }
  1050. static int AccessOutGrabberWrite( sout_access_out_t *p_access,
  1051.                                   block_t *p_buffer )
  1052. {
  1053.     sout_stream_t *p_stream = (sout_stream_t*)p_access->p_sys;
  1054.     //fprintf( stderr, "received buffer size=%dn", p_buffer->i_buffer );
  1055.     //
  1056.     while( p_buffer )
  1057.     {
  1058.         block_t *p_next;
  1059.         AccessOutGrabberWriteBuffer( p_stream, p_buffer );
  1060.         p_next = p_buffer->p_next;
  1061.         block_Release( p_buffer );
  1062.         p_buffer = p_next;
  1063.     }
  1064.     return VLC_SUCCESS;
  1065. }
  1066. /****************************************************************************
  1067.  * SAP:
  1068.  ****************************************************************************/
  1069. static int SapSetup( sout_stream_t *p_stream )
  1070. {
  1071.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  1072.     sout_instance_t   *p_sout = p_stream->p_sout;
  1073.     announce_method_t *p_method = (announce_method_t *)
  1074.                                   malloc(sizeof(announce_method_t));
  1075.     /* Remove the previous session */
  1076.     if( p_sys->p_session != NULL)
  1077.     {
  1078.         sout_AnnounceUnRegister( p_sout, p_sys->p_session);
  1079.         sout_AnnounceSessionDestroy( p_sys->p_session );
  1080.         p_sys->p_session = NULL;
  1081.     }
  1082.     p_method->i_type = METHOD_TYPE_SAP;
  1083.     p_method->psz_address = NULL; /* FIXME */
  1084.     p_method->i_ip_version = 4; /* FIXME ! */
  1085.     if( p_sys->i_es > 0 && p_sys->psz_sdp && *p_sys->psz_sdp )
  1086.     {
  1087.         p_sys->p_session = sout_AnnounceRegisterSDP( p_sout, p_sys->psz_sdp,
  1088.                                                      p_method );
  1089.     }
  1090.     free( p_method );
  1091.     return VLC_SUCCESS;
  1092. }
  1093. /****************************************************************************
  1094. * File:
  1095. ****************************************************************************/
  1096. static int FileSetup( sout_stream_t *p_stream )
  1097. {
  1098.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  1099.     FILE            *f;
  1100.     if( ( f = fopen( p_sys->psz_sdp_file, "wt" ) ) == NULL )
  1101.     {
  1102.         msg_Err( p_stream, "cannot open file '%s' (%s)",
  1103.                  p_sys->psz_sdp_file, strerror(errno) );
  1104.         return VLC_EGENERIC;
  1105.     }
  1106.     fprintf( f, "%s", p_sys->psz_sdp );
  1107.     fclose( f );
  1108.     return VLC_SUCCESS;
  1109. }
  1110. /****************************************************************************
  1111.  * HTTP:
  1112.  ****************************************************************************/
  1113. static int  HttpCallback( httpd_file_sys_t *p_args,
  1114.                           httpd_file_t *, uint8_t *p_request,
  1115.                           uint8_t **pp_data, int *pi_data );
  1116. static int HttpSetup( sout_stream_t *p_stream, vlc_url_t *url)
  1117. {
  1118.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  1119.     p_sys->p_httpd_host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host, url->i_port );
  1120.     if( p_sys->p_httpd_host )
  1121.     {
  1122.         p_sys->p_httpd_file = httpd_FileNew( p_sys->p_httpd_host,
  1123.                                              url->psz_path ? url->psz_path : "/",
  1124.                                              "application/sdp",
  1125.                                              NULL, NULL,
  1126.                                              HttpCallback, (void*)p_sys );
  1127.     }
  1128.     if( p_sys->p_httpd_file == NULL )
  1129.     {
  1130.         return VLC_EGENERIC;
  1131.     }
  1132.     return VLC_SUCCESS;
  1133. }
  1134. static int  HttpCallback( httpd_file_sys_t *p_args,
  1135.                           httpd_file_t *f, uint8_t *p_request,
  1136.                           uint8_t **pp_data, int *pi_data )
  1137. {
  1138.     sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_args;
  1139.     vlc_mutex_lock( &p_sys->lock_sdp );
  1140.     if( p_sys->psz_sdp && *p_sys->psz_sdp )
  1141.     {
  1142.         *pi_data = strlen( p_sys->psz_sdp );
  1143.         *pp_data = malloc( *pi_data );
  1144.         memcpy( *pp_data, p_sys->psz_sdp, *pi_data );
  1145.     }
  1146.     else
  1147.     {
  1148.         *pp_data = NULL;
  1149.         *pi_data = 0;
  1150.     }
  1151.     vlc_mutex_unlock( &p_sys->lock_sdp );
  1152.     return VLC_SUCCESS;
  1153. }
  1154. /****************************************************************************
  1155.  * RTSP:
  1156.  ****************************************************************************/
  1157. static rtsp_client_t *RtspClientNew( sout_stream_t *p_stream, char *psz_session )
  1158. {
  1159.     rtsp_client_t *rtsp = malloc( sizeof( rtsp_client_t ));
  1160.     rtsp->psz_session = psz_session;
  1161.     rtsp->i_last = 0;
  1162.     rtsp->b_playing = VLC_FALSE;
  1163.     rtsp->i_id = 0;
  1164.     rtsp->id = NULL;
  1165.     rtsp->i_access = 0;
  1166.     rtsp->access = NULL;
  1167.     TAB_APPEND( p_stream->p_sys->i_rtsp, p_stream->p_sys->rtsp, rtsp );
  1168.     return rtsp;
  1169. }
  1170. static rtsp_client_t *RtspClientGet( sout_stream_t *p_stream, char *psz_session )
  1171. {
  1172.     int i;
  1173.     for( i = 0; i < p_stream->p_sys->i_rtsp; i++ )
  1174.     {
  1175.         if( !strcmp( p_stream->p_sys->rtsp[i]->psz_session, psz_session ) )
  1176.         {
  1177.             return p_stream->p_sys->rtsp[i];
  1178.         }
  1179.     }
  1180.     return NULL;
  1181. }
  1182. static void RtspClientDel( sout_stream_t *p_stream, rtsp_client_t *rtsp )
  1183. {
  1184.     int i;
  1185.     TAB_REMOVE( p_stream->p_sys->i_rtsp, p_stream->p_sys->rtsp, rtsp );
  1186.     for( i = 0; i < rtsp->i_access; i++ )
  1187.     {
  1188.         sout_AccessOutDelete( rtsp->access[i] );
  1189.     }
  1190.     if( rtsp->id )     free( rtsp->id );
  1191.     if( rtsp->access ) free( rtsp->access );
  1192.     free( rtsp->psz_session );
  1193.     free( rtsp );
  1194. }
  1195. static int RtspSetup( sout_stream_t *p_stream, vlc_url_t *url )
  1196. {
  1197.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  1198.     fprintf( stderr, "rtsp setup: %s : %d / %sn", url->psz_host, url->i_port, url->psz_path );
  1199.     p_sys->p_rtsp_host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host, url->i_port > 0 ? url->i_port : 554 );
  1200.     if( p_sys->p_rtsp_host == NULL )
  1201.     {
  1202.         return VLC_EGENERIC;
  1203.     }
  1204.     p_sys->psz_rtsp_path = strdup( url->psz_path ? url->psz_path : "/" );
  1205.     p_sys->psz_rtsp_control = malloc (strlen( url->psz_host ) + 20 + strlen( p_sys->psz_rtsp_path ) + 1 );
  1206.     sprintf( p_sys->psz_rtsp_control, "rtsp://%s:%d%s",
  1207.              url->psz_host,  url->i_port > 0 ? url->i_port : 554, p_sys->psz_rtsp_path );
  1208.     p_sys->p_rtsp_url = httpd_UrlNewUnique( p_sys->p_rtsp_host, p_sys->psz_rtsp_path, NULL, NULL );
  1209.     if( p_sys->p_rtsp_url == 0 )
  1210.     {
  1211.         return VLC_EGENERIC;
  1212.     }
  1213.     httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_DESCRIBE, RtspCallback, (void*)p_stream );
  1214.     httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_PLAY,     RtspCallback, (void*)p_stream );
  1215.     httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_PAUSE,    RtspCallback, (void*)p_stream );
  1216.     httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_TEARDOWN, RtspCallback, (void*)p_stream );
  1217.     return VLC_SUCCESS;
  1218. }
  1219. static int  RtspCallback( httpd_callback_sys_t *p_args,
  1220.                           httpd_client_t *cl,
  1221.                           httpd_message_t *answer, httpd_message_t *query )
  1222. {
  1223.     sout_stream_t *p_stream = (sout_stream_t*)p_args;
  1224.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  1225.     char          *psz_destination = p_sys->psz_destination;
  1226.     char          *psz_session = NULL;
  1227.     if( answer == NULL || query == NULL )
  1228.     {
  1229.         return VLC_SUCCESS;
  1230.     }
  1231.     fprintf( stderr, "RtspCallback query: type=%dn", query->i_type );
  1232.     answer->i_proto = HTTPD_PROTO_RTSP;
  1233.     answer->i_version= query->i_version;
  1234.     answer->i_type   = HTTPD_MSG_ANSWER;
  1235.     switch( query->i_type )
  1236.     {
  1237.         case HTTPD_MSG_DESCRIBE:
  1238.         {
  1239.             char *psz_sdp = SDPGenerate( p_stream, psz_destination ? psz_destination : "0.0.0.0", VLC_TRUE );
  1240.             answer->i_status = 200;
  1241.             answer->psz_status = strdup( "OK" );
  1242.             httpd_MsgAdd( answer, "Content-type",  "%s", "application/sdp" );
  1243.             answer->p_body = psz_sdp;
  1244.             answer->i_body = strlen( psz_sdp );
  1245.             break;
  1246.         }
  1247.         case HTTPD_MSG_PLAY:
  1248.         {
  1249.             rtsp_client_t *rtsp;
  1250.             /* for now only multicast so easy */
  1251.             answer->i_status = 200;
  1252.             answer->psz_status = strdup( "OK" );
  1253.             answer->i_body = 0;
  1254.             answer->p_body = NULL;
  1255.             psz_session = httpd_MsgGet( query, "Session" );
  1256.             rtsp = RtspClientGet( p_stream, psz_session );
  1257.             if( rtsp && !rtsp->b_playing )
  1258.             {
  1259.                 int i_id;
  1260.                 /* FIXME */
  1261.                 rtsp->b_playing = VLC_TRUE;
  1262.                 vlc_mutex_lock( &p_sys->lock_es );
  1263.                 for( i_id = 0; i_id < rtsp->i_id; i_id++ )
  1264.                 {
  1265.                     sout_stream_id_t *id = rtsp->id[i_id];
  1266.                     int i;
  1267.                     for( i = 0; i < p_sys->i_es; i++ )
  1268.                     {
  1269.                         if( id == p_sys->es[i] )
  1270.                             break;
  1271.                     }
  1272.                     if( i >= p_sys->i_es ) continue;
  1273.                     vlc_mutex_lock( &id->lock_rtsp );
  1274.                     TAB_APPEND( id->i_rtsp_access, id->rtsp_access, rtsp->access[i_id] );
  1275.                     vlc_mutex_unlock( &id->lock_rtsp );
  1276.                 }
  1277.                 vlc_mutex_unlock( &p_sys->lock_es );
  1278.             }
  1279.             break;
  1280.         }
  1281.         case HTTPD_MSG_PAUSE:
  1282.             /* FIXME */
  1283.             return VLC_EGENERIC;
  1284.         case HTTPD_MSG_TEARDOWN:
  1285.         {
  1286.             rtsp_client_t *rtsp;
  1287.             /* for now only multicast so easy again */
  1288.             answer->i_status = 200;
  1289.             answer->psz_status = strdup( "OK" );
  1290.             answer->i_body = 0;
  1291.             answer->p_body = NULL;
  1292.             psz_session = httpd_MsgGet( query, "Session" );
  1293.             rtsp = RtspClientGet( p_stream, psz_session );
  1294.             if( rtsp )
  1295.             {
  1296.                 int i_id;
  1297.                 vlc_mutex_lock( &p_sys->lock_es );
  1298.                 for( i_id = 0; i_id < rtsp->i_id; i_id++ )
  1299.                 {
  1300.                     sout_stream_id_t *id = rtsp->id[i_id];
  1301.                     int i;
  1302.                     for( i = 0; i < p_sys->i_es; i++ )
  1303.                     {
  1304.                         if( id == p_sys->es[i] )
  1305.                             break;
  1306.                     }
  1307.                     if( i >= p_sys->i_es ) continue;
  1308.                     vlc_mutex_lock( &id->lock_rtsp );
  1309.                     TAB_REMOVE( id->i_rtsp_access, id->rtsp_access, rtsp->access[i_id] );
  1310.                     vlc_mutex_unlock( &id->lock_rtsp );
  1311.                 }
  1312.                 vlc_mutex_unlock( &p_sys->lock_es );
  1313.                 RtspClientDel( p_stream, rtsp );
  1314.             }
  1315.             break;
  1316.         }
  1317.         default:
  1318.             return VLC_EGENERIC;
  1319.     }
  1320.     httpd_MsgAdd( answer, "Server", "VLC Server" );
  1321.     httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );
  1322.     httpd_MsgAdd( answer, "Cseq", "%d", atoi( httpd_MsgGet( query, "Cseq" ) ) );
  1323.     httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" );
  1324.     if( psz_session )
  1325.     {
  1326.         httpd_MsgAdd( answer, "Session", "%s;timeout=5", psz_session );
  1327.     }
  1328.     return VLC_SUCCESS;
  1329. }
  1330. static int  RtspCallbackId( httpd_callback_sys_t *p_args,
  1331.                           httpd_client_t *cl,
  1332.                           httpd_message_t *answer, httpd_message_t *query )
  1333. {
  1334.     sout_stream_id_t *id = (sout_stream_id_t*)p_args;
  1335.     sout_stream_t    *p_stream = id->p_stream;
  1336.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  1337.     char          *psz_session = NULL;
  1338.     if( answer == NULL || query == NULL )
  1339.     {
  1340.         return VLC_SUCCESS;
  1341.     }
  1342.     fprintf( stderr, "RtspCallback query: type=%dn", query->i_type );
  1343.     answer->i_proto = HTTPD_PROTO_RTSP;
  1344.     answer->i_version= query->i_version;
  1345.     answer->i_type   = HTTPD_MSG_ANSWER;
  1346.     switch( query->i_type )
  1347.     {
  1348.         case HTTPD_MSG_SETUP:
  1349.         {
  1350.             char *psz_transport = httpd_MsgGet( query, "Transport" );
  1351.             fprintf( stderr, "HTTPD_MSG_SETUP: transport=%sn", psz_transport );
  1352.             if( strstr( psz_transport, "multicast" ) && id->psz_destination )
  1353.             {
  1354.                 fprintf( stderr, "HTTPD_MSG_SETUP: multicastn" );
  1355.                 answer->i_status = 200;
  1356.                 answer->psz_status = strdup( "OK" );
  1357.                 answer->i_body = 0;
  1358.                 answer->p_body = NULL;
  1359.                 psz_session = httpd_MsgGet( query, "Session" );
  1360.                 if( *psz_session == 0 )
  1361.                 {
  1362.                     psz_session = malloc( 100 );
  1363.                     sprintf( psz_session, "%d", rand() );
  1364.                 }
  1365.                 httpd_MsgAdd( answer, "Transport",
  1366.                               "RTP/AVP/UDP;destination=%s;port=%d-%d;ttl=%d",
  1367.                               id->psz_destination, id->i_port,id->i_port+1, p_sys->i_ttl );
  1368.             }
  1369.             else if( strstr( psz_transport, "unicast" ) && strstr( psz_transport, "client_port=" ) )
  1370.             {
  1371.                 int  i_port = atoi( strstr( psz_transport, "client_port=" ) + strlen("client_port=") );
  1372.                 char *ip    = httpd_ClientIP( cl );
  1373.                 char psz_access[100];
  1374.                 char psz_url[100];
  1375.                 sout_access_out_t *p_access;
  1376.                 rtsp_client_t *rtsp = NULL;
  1377.                 if( ip == NULL )
  1378.                 {
  1379.                     answer->i_status = 400;
  1380.                     answer->psz_status = strdup( "Internal server error" );
  1381.                     answer->i_body = 0;
  1382.                     answer->p_body = NULL;
  1383.                     break;
  1384.                 }
  1385.                 fprintf( stderr, "HTTPD_MSG_SETUP: unicast ip=%s port=%dn",
  1386.                          ip, i_port );
  1387.                 psz_session = httpd_MsgGet( query, "Session" );
  1388.                 if( *psz_session == 0 )
  1389.                 {
  1390.                     psz_session = malloc( 100 );
  1391.                     sprintf( psz_session, "%d", rand() );
  1392.                     rtsp = RtspClientNew( p_stream, psz_session );
  1393.                 }
  1394.                 else
  1395.                 {
  1396.                     rtsp = RtspClientGet( p_stream, psz_session );
  1397.                     if( rtsp == NULL )
  1398.                     {
  1399.                         /* FIXME right error code */
  1400.                         answer->i_status = 400;
  1401.                         answer->psz_status = strdup( "Unknown session id" );
  1402.                         answer->i_body = 0;
  1403.                         answer->p_body = NULL;
  1404.                         free( ip );
  1405.                         break;
  1406.                     }
  1407.                 }
  1408.                 /* first try to create the access out */
  1409.                 if( p_sys->i_ttl > 0 )
  1410.                     sprintf( psz_access, "udp{raw,ttl=%d}", p_sys->i_ttl );
  1411.                 else
  1412.                     sprintf( psz_access, "udp{raw}" );
  1413.                 sprintf( psz_url, "%s:%d", ip, i_port );
  1414.                 free( ip );
  1415.                 
  1416.                 if( ( p_access = sout_AccessOutNew( p_stream->p_sout, psz_access, psz_url ) ) == NULL )
  1417.                 {
  1418.                     msg_Err( p_stream, "cannot create the access out for %s://%s",
  1419.                              psz_access, psz_url );
  1420.                     answer->i_status = 400;
  1421.                     answer->psz_status = strdup( "Server internal error" );
  1422.                     answer->i_body = 0;
  1423.                     answer->p_body = NULL;
  1424.                     break;
  1425.                 }
  1426.                 TAB_APPEND( rtsp->i_id, rtsp->id, id );
  1427.                 TAB_APPEND( rtsp->i_access, rtsp->access, p_access );
  1428.                 answer->i_status = 200;
  1429.                 answer->psz_status = strdup( "OK" );
  1430.                 answer->i_body = 0;
  1431.                 answer->p_body = NULL;
  1432.                 httpd_MsgAdd( answer, "Transport",
  1433.                               "RTP/AVP/UDP;client_port=%d-%d", i_port, i_port + 1 );
  1434.             }
  1435.             else /* TODO  strstr( psz_transport, "interleaved" ) ) */
  1436.             {
  1437.                 answer->i_status = 400;
  1438.                 answer->psz_status = strdup( "Bad Request" );
  1439.                 answer->i_body = 0;
  1440.                 answer->p_body = NULL;
  1441.             }
  1442.             break;
  1443.         }
  1444.         default:
  1445.             return VLC_EGENERIC;
  1446.     }
  1447.     httpd_MsgAdd( answer, "Server", "VLC Server" );
  1448.     httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );
  1449.     httpd_MsgAdd( answer, "Cseq", "%d", atoi( httpd_MsgGet( query, "Cseq" ) ) );
  1450.     httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" );
  1451.     if( psz_session )
  1452.     {
  1453.         httpd_MsgAdd( answer, "Session", "%s"/*;timeout=5*/, psz_session );
  1454.     }
  1455.     return VLC_SUCCESS;
  1456. }
  1457. /****************************************************************************
  1458.  * rtp_packetize_*:
  1459.  ****************************************************************************/
  1460. static void rtp_packetize_common( sout_stream_id_t *id, block_t *out,
  1461.                                   int b_marker, int64_t i_pts )
  1462. {
  1463.     uint32_t i_timestamp = i_pts * (int64_t)id->i_clock_rate / I64C(1000000);
  1464.     out->p_buffer[0] = 0x80;
  1465.     out->p_buffer[1] = (b_marker?0x80:0x00)|id->i_payload_type;
  1466.     out->p_buffer[2] = ( id->i_sequence >> 8)&0xff;
  1467.     out->p_buffer[3] = ( id->i_sequence     )&0xff;
  1468.     out->p_buffer[4] = ( i_timestamp >> 24 )&0xff;
  1469.     out->p_buffer[5] = ( i_timestamp >> 16 )&0xff;
  1470.     out->p_buffer[6] = ( i_timestamp >>  8 )&0xff;
  1471.     out->p_buffer[7] = ( i_timestamp       )&0xff;
  1472.     out->p_buffer[ 8] = id->ssrc[0];
  1473.     out->p_buffer[ 9] = id->ssrc[1];
  1474.     out->p_buffer[10] = id->ssrc[2];
  1475.     out->p_buffer[11] = id->ssrc[3];
  1476.     out->i_buffer = 12;
  1477.     id->i_sequence++;
  1478. }
  1479. static void rtp_packetize_send( sout_stream_id_t *id, block_t *out )
  1480. {
  1481.     int i;
  1482.     vlc_mutex_lock( &id->lock_rtsp );
  1483.     for( i = 0; i < id->i_rtsp_access; i++ )
  1484.     {
  1485.         sout_AccessOutWrite( id->rtsp_access[i], block_Duplicate( out ) );
  1486.     }
  1487.     vlc_mutex_unlock( &id->lock_rtsp );
  1488.     if( id->p_access )
  1489.     {
  1490.         sout_AccessOutWrite( id->p_access, out );
  1491.     }
  1492.     else
  1493.     {
  1494.         block_Release( out );
  1495.     }
  1496. }
  1497. static int rtp_packetize_mpa( sout_stream_t *p_stream, sout_stream_id_t *id,
  1498.                               block_t *in )
  1499. {
  1500.     int     i_max   = id->i_mtu - 12 - 4; /* payload max in one packet */
  1501.     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
  1502.     uint8_t *p_data = in->p_buffer;
  1503.     int     i_data  = in->i_buffer;
  1504.     int     i;
  1505.     for( i = 0; i < i_count; i++ )
  1506.     {
  1507.         int           i_payload = __MIN( i_max, i_data );
  1508.         block_t *out = block_New( p_stream, 16 + i_payload );
  1509.         /* rtp common header */
  1510.         rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
  1511.         /* mbz set to 0 */
  1512.         out->p_buffer[12] = 0;
  1513.         out->p_buffer[13] = 0;
  1514.         /* fragment offset in the current frame */
  1515.         out->p_buffer[14] = ( (i*i_max) >> 8 )&0xff;
  1516.         out->p_buffer[15] = ( (i*i_max)      )&0xff;
  1517.         memcpy( &out->p_buffer[16], p_data, i_payload );
  1518.         out->i_buffer   = 16 + i_payload;
  1519.         out->i_dts    = in->i_dts + i * in->i_length / i_count;
  1520.         out->i_length = in->i_length / i_count;
  1521.         rtp_packetize_send( id, out );
  1522.         p_data += i_payload;
  1523.         i_data -= i_payload;
  1524.     }
  1525.     return VLC_SUCCESS;
  1526. }
  1527. /* rfc2250 */
  1528. static int rtp_packetize_mpv( sout_stream_t *p_stream, sout_stream_id_t *id,
  1529.                               block_t *in )
  1530. {
  1531.     int     i_max   = id->i_mtu - 12 - 4; /* payload max in one packet */
  1532.     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
  1533.     uint8_t *p_data = in->p_buffer;
  1534.     int     i_data  = in->i_buffer;
  1535.     int     i;
  1536.     int     b_sequence_start = 0;
  1537.     int     i_temporal_ref = 0;
  1538.     int     i_picture_coding_type = 0;
  1539.     int     i_fbv = 0, i_bfc = 0, i_ffv = 0, i_ffc = 0;
  1540.     int     b_start_slice = 0;
  1541.     /* preparse this packet to get some info */
  1542.     if( in->i_buffer > 4 )
  1543.     {
  1544.         uint8_t *p = p_data;
  1545.         int      i_rest = in->i_buffer;
  1546.         for( ;; )
  1547.         {
  1548.             while( i_rest > 4 &&
  1549.                    ( p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x01 ) )
  1550.             {
  1551.                 p++;
  1552.                 i_rest--;
  1553.             }
  1554.             if( i_rest <= 4 )
  1555.             {
  1556.                 break;
  1557.             }
  1558.             p += 3;
  1559.             i_rest -= 4;
  1560.             if( *p == 0xb3 )
  1561.             {
  1562.                 /* sequence start code */
  1563.                 b_sequence_start = 1;
  1564.             }
  1565.             else if( *p == 0x00 && i_rest >= 4 )
  1566.             {
  1567.                 /* picture */
  1568.                 i_temporal_ref = ( p[1] << 2) |((p[2]>>6)&0x03);
  1569.                 i_picture_coding_type = (p[2] >> 3)&0x07;
  1570.                 if( i_rest >= 4 && ( i_picture_coding_type == 2 ||
  1571.                                     i_picture_coding_type == 3 ) )
  1572.                 {
  1573.                     i_ffv = (p[3] >> 2)&0x01;
  1574.                     i_ffc = ((p[3]&0x03) << 1)|((p[4]>>7)&0x01);
  1575.                     if( i_rest > 4 && i_picture_coding_type == 3 )
  1576.                     {
  1577.                         i_fbv = (p[4]>>6)&0x01;
  1578.                         i_bfc = (p[4]>>3)&0x07;
  1579.                     }
  1580.                 }
  1581.             }
  1582.             else if( *p <= 0xaf )
  1583.             {
  1584.                 b_start_slice = 1;
  1585.             }
  1586.         }
  1587.     }
  1588.     for( i = 0; i < i_count; i++ )
  1589.     {
  1590.         int           i_payload = __MIN( i_max, i_data );
  1591.         block_t *out = block_New( p_stream,
  1592.                                              16 + i_payload );
  1593.         uint32_t      h = ( i_temporal_ref << 16 )|
  1594.                           ( b_sequence_start << 13 )|
  1595.                           ( b_start_slice << 12 )|
  1596.                           ( i == i_count - 1 ? 1 << 11 : 0 )|
  1597.                           ( i_picture_coding_type << 8 )|
  1598.                           ( i_fbv << 7 )|( i_bfc << 4 )|( i_ffv << 3 )|i_ffc;
  1599.         /* rtp common header */
  1600.         rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
  1601.                               in->i_pts > 0 ? in->i_pts : in->i_dts );
  1602.         /* MBZ:5 T:1 TR:10 AN:1 N:1 S:1 B:1 E:1 P:3 FBV:1 BFC:3 FFV:1 FFC:3 */
  1603.         out->p_buffer[12] = ( h >> 24 )&0xff;
  1604.         out->p_buffer[13] = ( h >> 16 )&0xff;
  1605.         out->p_buffer[14] = ( h >>  8 )&0xff;
  1606.         out->p_buffer[15] = ( h       )&0xff;
  1607.         memcpy( &out->p_buffer[16], p_data, i_payload );
  1608.         out->i_buffer   = 16 + i_payload;
  1609.         out->i_dts    = in->i_dts + i * in->i_length / i_count;
  1610.         out->i_length = in->i_length / i_count;
  1611.         rtp_packetize_send( id, out );
  1612.         p_data += i_payload;
  1613.         i_data -= i_payload;
  1614.     }
  1615.     return VLC_SUCCESS;
  1616. }
  1617. static int rtp_packetize_ac3( sout_stream_t *p_stream, sout_stream_id_t *id,
  1618.                               block_t *in )
  1619. {
  1620.     int     i_max   = id->i_mtu - 12 - 2; /* payload max in one packet */
  1621.     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
  1622.     uint8_t *p_data = in->p_buffer;
  1623.     int     i_data  = in->i_buffer;
  1624.     int     i;
  1625.     for( i = 0; i < i_count; i++ )
  1626.     {
  1627.         int           i_payload = __MIN( i_max, i_data );
  1628.         block_t *out = block_New( p_stream, 14 + i_payload );
  1629.         /* rtp common header */
  1630.         rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
  1631.         /* unit count */
  1632.         out->p_buffer[12] = 1;
  1633.         /* unit header */
  1634.         out->p_buffer[13] = 0x00;
  1635.         /* data */
  1636.         memcpy( &out->p_buffer[14], p_data, i_payload );
  1637.         out->i_buffer   = 14 + i_payload;
  1638.         out->i_dts    = in->i_dts + i * in->i_length / i_count;
  1639.         out->i_length = in->i_length / i_count;
  1640.         rtp_packetize_send( id, out );
  1641.         p_data += i_payload;
  1642.         i_data -= i_payload;
  1643.     }
  1644.     return VLC_SUCCESS;
  1645. }
  1646. static int rtp_packetize_split( sout_stream_t *p_stream, sout_stream_id_t *id,
  1647.                                 block_t *in )
  1648. {
  1649.     int     i_max   = id->i_mtu - 12; /* payload max in one packet */
  1650.     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
  1651.     uint8_t *p_data = in->p_buffer;
  1652.     int     i_data  = in->i_buffer;
  1653.     int     i;
  1654.     for( i = 0; i < i_count; i++ )
  1655.     {
  1656.         int           i_payload = __MIN( i_max, i_data );
  1657.         block_t *out = block_New( p_stream, 12 + i_payload );
  1658.         /* rtp common header */
  1659.         rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
  1660.                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
  1661.         memcpy( &out->p_buffer[12], p_data, i_payload );
  1662.         out->i_buffer   = 12 + i_payload;
  1663.         out->i_dts    = in->i_dts + i * in->i_length / i_count;
  1664.         out->i_length = in->i_length / i_count;
  1665.         rtp_packetize_send( id, out );
  1666.         p_data += i_payload;
  1667.         i_data -= i_payload;
  1668.     }
  1669.     return VLC_SUCCESS;
  1670. }
  1671. static int rtp_packetize_l16( sout_stream_t *p_stream, sout_stream_id_t *id,
  1672.                               block_t *in )
  1673. {
  1674.     int     i_max   = id->i_mtu - 12; /* payload max in one packet */
  1675.     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
  1676.     uint8_t *p_data = in->p_buffer;
  1677.     int     i_data  = in->i_buffer;
  1678.     int     i_packet = 0;
  1679.     while( i_data > 0 )
  1680.     {
  1681.         int           i_payload = (__MIN( i_max, i_data )/4)*4;
  1682.         block_t *out = block_New( p_stream, 12 + i_payload );
  1683.         /* rtp common header */
  1684.         rtp_packetize_common( id, out, 0,
  1685.                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
  1686.         memcpy( &out->p_buffer[12], p_data, i_payload );
  1687.         out->i_buffer   = 12 + i_payload;
  1688.         out->i_dts    = in->i_dts + i_packet * in->i_length / i_count;
  1689.         out->i_length = in->i_length / i_count;
  1690.         rtp_packetize_send( id, out );
  1691.         p_data += i_payload;
  1692.         i_data -= i_payload;
  1693.         i_packet++;
  1694.     }
  1695.     return VLC_SUCCESS;
  1696. }
  1697. static int rtp_packetize_l8( sout_stream_t *p_stream, sout_stream_id_t *id,
  1698.                              block_t *in )
  1699. {
  1700.     int     i_max   = id->i_mtu - 12; /* payload max in one packet */
  1701.     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
  1702.     uint8_t *p_data = in->p_buffer;
  1703.     int     i_data  = in->i_buffer;
  1704.     int     i_packet = 0;
  1705.     while( i_data > 0 )
  1706.     {
  1707.         int           i_payload = (__MIN( i_max, i_data )/2)*2;
  1708.         block_t *out = block_New( p_stream, 12 + i_payload );
  1709.         /* rtp common header */
  1710.         rtp_packetize_common( id, out, 0,
  1711.                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
  1712.         memcpy( &out->p_buffer[12], p_data, i_payload );
  1713.         out->i_buffer   = 12 + i_payload;
  1714.         out->i_dts    = in->i_dts + i_packet * in->i_length / i_count;
  1715.         out->i_length = in->i_length / i_count;
  1716.         rtp_packetize_send( id, out );
  1717.         p_data += i_payload;
  1718.         i_data -= i_payload;
  1719.         i_packet++;
  1720.     }
  1721.     return VLC_SUCCESS;
  1722. }
  1723. static int rtp_packetize_mp4a( sout_stream_t *p_stream, sout_stream_id_t *id,
  1724.                                block_t *in )
  1725. {
  1726.     int     i_max   = id->i_mtu - 16; /* payload max in one packet */
  1727.     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
  1728.     uint8_t *p_data = in->p_buffer;
  1729.     int     i_data  = in->i_buffer;
  1730.     int     i;
  1731.     for( i = 0; i < i_count; i++ )
  1732.     {
  1733.         int           i_payload = __MIN( i_max, i_data );
  1734.         block_t *out = block_New( p_stream, 16 + i_payload );
  1735.         /* rtp common header */
  1736.         rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
  1737.                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
  1738.         /* AU headers */
  1739.         /* AU headers length (bits) */
  1740.         out->p_buffer[12] = 0;
  1741.         out->p_buffer[13] = 2*8;
  1742.         /* for each AU length 13 bits + idx 3bits, */
  1743.         out->p_buffer[14] = ( in->i_buffer >> 5 )&0xff;
  1744.         out->p_buffer[15] = ( (in->i_buffer&0xff)<<3 )|0;
  1745.         memcpy( &out->p_buffer[16], p_data, i_payload );
  1746.         out->i_buffer   = 16 + i_payload;
  1747.         out->i_dts    = in->i_dts + i * in->i_length / i_count;
  1748.         out->i_length = in->i_length / i_count;
  1749.         rtp_packetize_send( id, out );
  1750.         p_data += i_payload;
  1751.         i_data -= i_payload;
  1752.     }
  1753.     return VLC_SUCCESS;
  1754. }
  1755. /* rfc2429 */
  1756. #define RTP_H263_HEADER_SIZE (2)  // plen = 0
  1757. #define RTP_H263_PAYLOAD_START (14)  // plen = 0
  1758. static int rtp_packetize_h263( sout_stream_t *p_stream, sout_stream_id_t *id,
  1759.                                block_t *in )
  1760. {
  1761.     uint8_t *p_data = in->p_buffer;
  1762.     int     i_data  = in->i_buffer;
  1763.     int     i;
  1764.     int     i_max   = id->i_mtu - 12 - RTP_H263_HEADER_SIZE; /* payload max in one packet */
  1765.     int     i_count;
  1766.     int     b_p_bit;
  1767.     int     b_v_bit = 0; // no pesky error resilience
  1768.     int     i_plen = 0; // normally plen=0 for PSC packet
  1769.     int     i_pebit = 0; // because plen=0
  1770.     uint16_t h;
  1771.     if( i_data < 2 )
  1772.     {
  1773.         return VLC_EGENERIC;
  1774.     }
  1775.     if( p_data[0] || p_data[1] )
  1776.     {
  1777.         return VLC_EGENERIC;
  1778.     }
  1779.     /* remove 2 leading 0 bytes */
  1780.     p_data += 2;
  1781.     i_data -= 2;
  1782.     i_count = ( i_data + i_max - 1 ) / i_max;
  1783.     for( i = 0; i < i_count; i++ )
  1784.     {
  1785.         int      i_payload = __MIN( i_max, i_data );
  1786.         block_t *out = block_New( p_stream,
  1787.                                   RTP_H263_PAYLOAD_START + i_payload );
  1788.         b_p_bit = (i == 0) ? 1 : 0;
  1789.         h = ( b_p_bit << 10 )|
  1790.             ( b_v_bit << 9  )|
  1791.             ( i_plen  << 3  )|
  1792.               i_pebit;
  1793.         /* rtp common header */
  1794.         //b_m_bit = 1; // always contains end of frame
  1795.         rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
  1796.                               in->i_pts > 0 ? in->i_pts : in->i_dts );
  1797.         /* h263 header */
  1798.         out->p_buffer[12] = ( h >>  8 )&0xff;
  1799.         out->p_buffer[13] = ( h       )&0xff;
  1800.         memcpy( &out->p_buffer[RTP_H263_PAYLOAD_START], p_data, i_payload );
  1801.         out->i_buffer = RTP_H263_PAYLOAD_START + i_payload;
  1802.         out->i_dts    = in->i_dts + i * in->i_length / i_count;
  1803.         out->i_length = in->i_length / i_count;
  1804.         rtp_packetize_send( id, out );
  1805.         p_data += i_payload;
  1806.         i_data -= i_payload;
  1807.     }
  1808.     return VLC_SUCCESS;
  1809. }