📄 rtp.c
字号:
/***************************************************************************** * rtp.c: rtp stream output module ***************************************************************************** * Copyright (C) 2003-2004 the VideoLAN team * $Id: rtp.c 19750 2007-04-09 15:15:59Z courmisch $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h>#include <vlc/vlc.h>#include <vlc/input.h>#include <vlc/sout.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#include <errno.h>#include "vlc_httpd.h"#include "vlc_url.h"#include "network.h"#include "charset.h"/***************************************************************************** * Module descriptor *****************************************************************************/#define MTU_REDUCE 50#define DST_TEXT N_("Destination")#define DST_LONGTEXT N_( \ "This is the output URL that will be used." )#define SDP_TEXT N_("SDP")#define SDP_LONGTEXT N_( \ "This allows you to specify how the SDP (Session Descriptor) for this RTP "\ "session will be made available. You must use an url: http://location to " \ "access the SDP via HTTP, rtsp://location for RTSP access, and sap:// " \ "for the SDP to be announced via SAP." )#define MUX_TEXT N_("Muxer")#define MUX_LONGTEXT N_( \ "This allows you to specify the muxer used for the streaming output. " \ "Default is to use no muxer (standard RTP stream)." )#define NAME_TEXT N_("Session name")#define NAME_LONGTEXT N_( \ "This is the name of the session that will be announced in the SDP " \ "(Session Descriptor)." )#define DESC_TEXT N_("Session description")#define DESC_LONGTEXT N_( \ "This allows you to give a broader description of the stream, that will " \ "be announced in the SDP (Session Descriptor)." )#define URL_TEXT N_("Session URL")#define URL_LONGTEXT N_( \ "This allows you to give an URL with more details about the stream " \ "(often the website of the streaming organization), that will " \ "be announced in the SDP (Session Descriptor)." )#define EMAIL_TEXT N_("Session email")#define EMAIL_LONGTEXT N_( \ "This allows you to give a contact mail address for the stream, that will " \ "be announced in the SDP (Session Descriptor)." )#define PORT_TEXT N_("Port")#define PORT_LONGTEXT N_( \ "This allows you to specify the base port for the RTP streaming." )#define PORT_AUDIO_TEXT N_("Audio port")#define PORT_AUDIO_LONGTEXT N_( \ "This allows you to specify the default audio port for the RTP streaming." )#define PORT_VIDEO_TEXT N_("Video port")#define PORT_VIDEO_LONGTEXT N_( \ "This allows you to specify the default video port for the RTP streaming." )#define TTL_TEXT N_("Time-To-Live (TTL)")#define TTL_LONGTEXT N_( \ "This allows you to specify the Time-To-Live for the output stream." )#define RFC3016_TEXT N_("MP4A LATM")#define RFC3016_LONGTEXT N_( \ "This allows you to stream MPEG4 LATM audio streams (see RFC3016)." )static int Open ( vlc_object_t * );static void Close( vlc_object_t * );#define SOUT_CFG_PREFIX "sout-rtp-"vlc_module_begin(); set_shortname( _("RTP")); set_description( _("RTP stream output") ); set_capability( "sout stream", 0 ); add_shortcut( "rtp" ); set_category( CAT_SOUT ); set_subcategory( SUBCAT_SOUT_STREAM ); add_string( SOUT_CFG_PREFIX "dst", "", NULL, DST_TEXT, DST_LONGTEXT, VLC_TRUE ); add_string( SOUT_CFG_PREFIX "sdp", "", NULL, SDP_TEXT, SDP_LONGTEXT, VLC_TRUE ); add_string( SOUT_CFG_PREFIX "mux", "", NULL, MUX_TEXT, MUX_LONGTEXT, VLC_TRUE ); add_string( SOUT_CFG_PREFIX "name", "NONE", NULL, NAME_TEXT, NAME_LONGTEXT, VLC_TRUE ); add_string( SOUT_CFG_PREFIX "description", "", NULL, DESC_TEXT, DESC_LONGTEXT, VLC_TRUE ); add_string( SOUT_CFG_PREFIX "url", "", NULL, URL_TEXT, URL_LONGTEXT, VLC_TRUE ); add_string( SOUT_CFG_PREFIX "email", "", NULL, EMAIL_TEXT, EMAIL_LONGTEXT, VLC_TRUE ); add_integer( SOUT_CFG_PREFIX "port", 1234, NULL, PORT_TEXT, PORT_LONGTEXT, VLC_TRUE ); add_integer( SOUT_CFG_PREFIX "port-audio", 1230, NULL, PORT_AUDIO_TEXT, PORT_AUDIO_LONGTEXT, VLC_TRUE ); add_integer( SOUT_CFG_PREFIX "port-video", 1232, NULL, PORT_VIDEO_TEXT, PORT_VIDEO_LONGTEXT, VLC_TRUE ); add_integer( SOUT_CFG_PREFIX "ttl", 0, NULL, TTL_TEXT, TTL_LONGTEXT, VLC_TRUE ); add_bool( SOUT_CFG_PREFIX "mp4a-latm", 0, NULL, RFC3016_TEXT, RFC3016_LONGTEXT, VLC_FALSE ); set_callbacks( Open, Close );vlc_module_end();/***************************************************************************** * Exported prototypes *****************************************************************************/static const char *ppsz_sout_options[] = { "dst", "name", "port", "port-audio", "port-video", "*sdp", "ttl", "mux", "description", "url","email", "mp4a-latm", NULL};static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );static int Del ( sout_stream_t *, sout_stream_id_t * );static int Send( sout_stream_t *, sout_stream_id_t *, block_t* );/* For unicast/interleaved streaming */typedef struct{ char *psz_session; int64_t i_last; /* for timeout */ /* is it in "play" state */ vlc_bool_t b_playing; /* output (id-access) */ int i_id; sout_stream_id_t **id; int i_access; sout_access_out_t **access;} rtsp_client_t;struct sout_stream_sys_t{ /* sdp */ int64_t i_sdp_id; int i_sdp_version; char *psz_sdp; vlc_mutex_t lock_sdp; char *psz_session_name; char *psz_session_description; char *psz_session_url; char *psz_session_email; /* */ vlc_bool_t b_export_sdp_file; char *psz_sdp_file; /* sap */ vlc_bool_t b_export_sap; session_descriptor_t *p_session; httpd_host_t *p_httpd_host; httpd_file_t *p_httpd_file; httpd_host_t *p_rtsp_host; httpd_url_t *p_rtsp_url; char *psz_rtsp_control; char *psz_rtsp_path; /* */ char *psz_destination; int i_port; int i_port_audio; int i_port_video; int i_ttl; vlc_bool_t b_latm; /* when need to use a private one or when using muxer */ int i_payload_type; /* in case we do TS/PS over rtp */ sout_mux_t *p_mux; sout_access_out_t *p_access; int i_mtu; sout_access_out_t *p_grab; uint16_t i_sequence; uint32_t i_timestamp_start; uint8_t ssrc[4]; block_t *packet; /* */ vlc_mutex_t lock_es; int i_es; sout_stream_id_t **es; /* */ int i_rtsp; rtsp_client_t **rtsp;};typedef int (*pf_rtp_packetizer_t)( sout_stream_t *, sout_stream_id_t *, block_t * );struct sout_stream_id_t{ sout_stream_t *p_stream; /* rtp field */ uint8_t i_payload_type; uint16_t i_sequence; uint32_t i_timestamp_start; uint8_t ssrc[4]; /* for sdp */ int i_clock_rate; char *psz_rtpmap; char *psz_fmtp; char *psz_destination; int i_port; int i_cat; int i_bitrate; /* Packetizer specific fields */ pf_rtp_packetizer_t pf_packetize; int i_mtu; /* for sending the packets */ sout_access_out_t *p_access; vlc_mutex_t lock_rtsp; int i_rtsp_access; sout_access_out_t **rtsp_access; /* */ sout_input_t *p_input; /* RTSP url control */ httpd_url_t *p_rtsp_url;};static int AccessOutGrabberWrite( sout_access_out_t *, block_t * );static void SDPHandleUrl( sout_stream_t *, char * );static int SapSetup( sout_stream_t *p_stream );static int FileSetup( sout_stream_t *p_stream );static int HttpSetup( sout_stream_t *p_stream, vlc_url_t * );static int RtspSetup( sout_stream_t *p_stream, vlc_url_t * );static int RtspCallback( httpd_callback_sys_t *, httpd_client_t *, httpd_message_t *, httpd_message_t * );static int RtspCallbackId( httpd_callback_sys_t *, httpd_client_t *, httpd_message_t *, httpd_message_t * );static rtsp_client_t *RtspClientNew( sout_stream_t *, char *psz_session );static rtsp_client_t *RtspClientGet( sout_stream_t *, char *psz_session );static void RtspClientDel( sout_stream_t *, rtsp_client_t * );/***************************************************************************** * Open: *****************************************************************************/static int Open( vlc_object_t *p_this ){ sout_stream_t *p_stream = (sout_stream_t*)p_this; sout_instance_t *p_sout = p_stream->p_sout; sout_stream_sys_t *p_sys = NULL; sout_cfg_t *p_cfg = NULL; vlc_value_t val; vlc_bool_t b_rtsp = VLC_FALSE; sout_CfgParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options, p_stream->p_cfg ); p_sys = malloc( sizeof( sout_stream_sys_t ) ); p_sys->psz_destination = var_GetString( p_stream, SOUT_CFG_PREFIX "dst" ); if( *p_sys->psz_destination == '\0' ) { free( p_sys->psz_destination ); p_sys->psz_destination = NULL; } p_sys->psz_session_name = var_GetString( p_stream, SOUT_CFG_PREFIX "name" ); p_sys->psz_session_description = var_GetString( p_stream, SOUT_CFG_PREFIX "description" ); p_sys->psz_session_url = var_GetString( p_stream, SOUT_CFG_PREFIX "url" ); p_sys->psz_session_email = var_GetString( p_stream, SOUT_CFG_PREFIX "email" ); p_sys->i_port = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port" ); p_sys->i_port_audio = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-audio" ); p_sys->i_port_video = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-video" ); p_sys->psz_sdp_file = NULL; if( p_sys->i_port_audio == p_sys->i_port_video ) { msg_Err( p_stream, "audio and video port cannot be the same" ); p_sys->i_port_audio = 0; p_sys->i_port_video = 0; } if( !p_sys->psz_session_name ) { if( p_sys->psz_destination ) p_sys->psz_session_name = strdup( p_sys->psz_destination ); else p_sys->psz_session_name = strdup( "NONE" ); } for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next ) { if( !strcmp( p_cfg->psz_name, "sdp" ) ) { if( p_cfg->psz_value && !strncasecmp( p_cfg->psz_value, "rtsp", 4 ) ) { b_rtsp = VLC_TRUE; break; } } } if( !b_rtsp ) { vlc_value_t val2; var_Get( p_stream, SOUT_CFG_PREFIX "sdp", &val2 ); if( !strncasecmp( val2.psz_string, "rtsp", 4 ) ) b_rtsp = VLC_TRUE; free( val2.psz_string ); } if( !p_sys->psz_destination || *p_sys->psz_destination == '\0' ) { if( !b_rtsp ) { msg_Err( p_stream, "missing destination and not in rtsp mode" ); free( p_sys ); return VLC_EGENERIC; } p_sys->psz_destination = NULL; } else if( p_sys->i_port <= 0 ) { msg_Err( p_stream, "invalid port" ); free( p_sys ); return VLC_EGENERIC; } var_Get( p_stream, SOUT_CFG_PREFIX "ttl", &val ); if( val.i_int == 0 ) { /* Normally, we should let the default hop limit up to the core, * but we have to know it to build our SDP properly, which is why * we ask the core. FIXME: broken when neither sout-rtp-ttl nor * ttl are set. */ val.i_int = config_GetInt( p_stream, "ttl" ); } if( val.i_int > 255 ) val.i_int = 255; /* must not exceed 999 once formatted */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -