#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_TEXT N_("Session descriptipn")
#define DESC_LONGTEXT N_( \
- "This allows you to give a broader description of the stream, that will " \
- "be announced in the SDP (Session Descriptor)." )
+ "This allows you to give a short description with details about 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 " \
"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)." )
+ "This allows you to give a contact mail address for the stream, that will " \
+ "be announced in the SDP (Session Descriptor)." )
+#define PHONE_TEXT N_("Session phone number")
+#define PHONE_LONGTEXT N_( \
+ "This allows you to give a contact telephone number 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." )
URL_LONGTEXT, VLC_TRUE );
add_string( SOUT_CFG_PREFIX "email", "", NULL, EMAIL_TEXT,
EMAIL_LONGTEXT, VLC_TRUE );
+ add_string( SOUT_CFG_PREFIX "phone", "", NULL, PHONE_TEXT,
+ PHONE_LONGTEXT, VLC_TRUE );
add_integer( SOUT_CFG_PREFIX "port", 1234, NULL, PORT_TEXT,
PORT_LONGTEXT, VLC_TRUE );
*****************************************************************************/
static const char *ppsz_sout_options[] = {
"dst", "name", "port", "port-audio", "port-video", "*sdp", "ttl", "mux",
- "description", "url", "email",
+ "description", "url", "email", "phone",
"dccp", "tcp", "udplite",
"mp4a-latm", NULL
};
char *psz_sdp;
vlc_mutex_t lock_sdp;
- char *psz_session_name;
- char *psz_session_description;
- char *psz_session_url;
- char *psz_session_email;
-
/* SDP to disk */
vlc_bool_t b_export_sdp_file;
char *psz_sdp_file;
return VLC_ENOMEM;
p_sys->psz_destination = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "dst" );
- p_sys->psz_session_name = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "name" );
- p_sys->psz_session_description = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "description" );
- p_sys->psz_session_url = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "url" );
- p_sys->psz_session_email = var_GetNonEmptyString( 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 = 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_sys->p_httpd_host )
httpd_HostDelete( p_sys->p_httpd_host );
- free( p_sys->psz_session_name );
- free( p_sys->psz_session_description );
- free( p_sys->psz_session_url );
- free( p_sys->psz_session_email );
free( p_sys->psz_sdp );
if( p_sys->b_export_sdp_file )
/*****************************************************************************
* SDPGenerate
*****************************************************************************/
- /* FIXME http://www.faqs.org/rfcs/rfc2327.html
- All text fields should be UTF-8 encoded. Use global a:charset to announce this.
- o= - should be local username (no spaces allowed)
- o= time should be hashed with some other value to garantue uniqueness
- o= we need IP6 support?
- o= don't use the localhost address. use fully qualified domain name or IP4 address
- p= international phone number (pass via vars?)
- c= IP6 support
- a= recvonly (missing)
- a= type:broadcast (missing)
- a= charset: (normally charset should be UTF-8, this can be used to override s= and i=)
- a= x-plgroup: (missing)
- RTP packets need to get the correct src IP address */
/*static*/
char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url )
{
dstlen = sizeof( struct sockaddr_in );
}
- psz_sdp = sdp_Start( p_sys->psz_session_name,
- p_sys->psz_session_description,
- p_sys->psz_session_url, p_sys->psz_session_email,
- NULL, NULL, 0, (struct sockaddr *)&dst, dstlen );
+ psz_sdp = vlc_sdp_Start( VLC_OBJECT( p_stream ), SOUT_CFG_PREFIX,
+ NULL, 0, (struct sockaddr *)&dst, dstlen );
if( psz_sdp == NULL )
return NULL;
/* TODO: a=source-filter */
+ if( rtsp_url != NULL )
+ sdp_AddAttribute ( &psz_sdp, "control", "%s", rtsp_url );
+
/* FIXME: locking?! */
for( i = 0; i < p_sys->i_es; i++ )
{
sout_stream_id_t *id = p_sys->es[i];
const char *mime_major; /* major MIME type */
- if( id->i_cat == AUDIO_ES )
- mime_major = "audio";
- else
- if( id->i_cat == VIDEO_ES )
- mime_major = "video";
- else
- continue;
+ switch( id->i_cat )
+ {
+ case VIDEO_ES:
+ mime_major = "video";
+ break;
+ case AUDIO_ES:
+ mime_major = "audio";
+ break;
+ case SPU_ES:
+ mime_major = "text";
+ break;
+ default:
+ continue;
+ }
sdp_AddMedia( &psz_sdp, mime_major, "RTP/AVP", inclport * id->i_port,
id->i_payload_type, VLC_FALSE, id->i_bitrate,
id->psz_rtpmap, id->psz_fmtp);
if( rtsp_url != NULL )
- sdp_AddAttribute ( &psz_sdp, "control", "/trackID=%d", i );
+ {
+ assert( strlen( rtsp_url ) > 0 );
+ vlc_bool_t addslash = ( rtsp_url[strlen( rtsp_url ) - 1] != '/' );
+ sdp_AddAttribute ( &psz_sdp, "control",
+ addslash ? "%s/trackID=%u" : "%strackID=%u",
+ rtsp_url, i );
+ }
}
return psz_sdp;
static int rtp_packetize_h263 ( sout_stream_t *, sout_stream_id_t *, block_t * );
static int rtp_packetize_h264 ( sout_stream_t *, sout_stream_id_t *, block_t * );
static int rtp_packetize_amr ( sout_stream_t *, sout_stream_id_t *, block_t * );
+static int rtp_packetize_t140 ( sout_stream_t *, sout_stream_id_t *, block_t * );
static void sprintf_hexa( char *s, uint8_t *p_data, int i_data )
{
id->i_clock_rate = p_fmt->audio.i_rate;
id->pf_packetize = rtp_packetize_amr;
break;
+ case VLC_FOURCC( 't', '1', '4', '0' ):
+ id->psz_rtpmap = strdup( "t140/1000" );
+ id->i_clock_rate = 1000;
+ id->pf_packetize = rtp_packetize_t140;
+ break;
default:
msg_Err( p_stream, "cannot add this stream (unsupported "
sout_stream_sys_t *p_sys = p_stream->p_sys;
vlc_object_kill( id );
+ block_FifoWake( id->p_fifo );
vlc_mutex_lock( &p_sys->lock_es );
TAB_REMOVE( p_sys->i_es, p_sys->es, id );
{
sout_stream_sys_t *p_sys = p_stream->p_sys;
sout_instance_t *p_sout = p_stream->p_sout;
- announce_method_t *p_method = sout_SAPMethod();
/* Remove the previous session */
if( p_sys->p_session != NULL)
{
sout_AnnounceUnRegister( p_sout, p_sys->p_session);
- sout_AnnounceSessionDestroy( p_sys->p_session );
p_sys->p_session = NULL;
}
if( ( p_sys->i_es > 0 || p_sys->p_mux ) && p_sys->psz_sdp && *p_sys->psz_sdp )
{
+ announce_method_t *p_method = sout_SAPMethod();
p_sys->p_session = sout_AnnounceRegisterSDP( p_sout, SOUT_CFG_PREFIX,
p_sys->psz_sdp,
p_sys->psz_destination,
p_method );
+ sout_MethodRelease( p_method );
}
- sout_MethodRelease( p_method );
return VLC_SUCCESS;
}
if( ( f = utf8_fopen( p_sys->psz_sdp_file, "wt" ) ) == NULL )
{
- msg_Err( p_stream, "cannot open file '%s' (%s)",
- p_sys->psz_sdp_file, strerror(errno) );
+ msg_Err( p_stream, "cannot open file '%s' (%m)",
+ p_sys->psz_sdp_file );
return VLC_EGENERIC;
}
while( !id->b_die )
{
block_t *out = block_FifoGet( id->p_fifo );
+ if( out == NULL )
+ continue; /* Forced wakeup */
+
mtime_t i_date = out->i_dts + i_caching;
ssize_t len = out->i_buffer;
return VLC_SUCCESS;
}
+static int rtp_packetize_t140( sout_stream_t *p_stream, sout_stream_id_t *id,
+ block_t *in )
+{
+ const size_t i_max = id->i_mtu - 12;
+ const uint8_t *p_data = in->p_buffer;
+ size_t i_data = in->i_buffer;
+
+ for( unsigned i_packet = 0; i_data > 0; i_packet++ )
+ {
+ size_t i_payload = i_data;
+
+ /* Make sure we stop on an UTF-8 character boundary
+ * (assuming the input is valid UTF-8) */
+ if( i_data > i_max )
+ {
+ i_payload = i_max;
+
+ while( ( p_data[i_payload] & 0xC0 ) == 0x80 )
+ {
+ if( i_payload == 0 )
+ return VLC_SUCCESS; /* fishy input! */
+
+ i_payload--;
+ }
+ }
+
+ block_t *out = block_New( p_stream, 12 + i_payload );
+ if( out == NULL )
+ return VLC_SUCCESS;
+
+ rtp_packetize_common( id, out, 0, in->i_pts + i_packet );
+ memcpy( out->p_buffer + 12, p_data, i_payload );
+
+ out->i_buffer = 12 + i_payload;
+ out->i_dts = out->i_pts;
+ out->i_length = 0;
+
+ rtp_packetize_send( id, out );
+
+ p_data += i_payload;
+ i_data -= i_payload;
+ }
+
+ return VLC_SUCCESS;
+}
+
/*****************************************************************************
* Non-RTP mux
*****************************************************************************/