@ -45,6 +45,7 @@
# include "rtpdec_formats.h"
# include "rtpdec_formats.h"
# include "rtpenc_chain.h"
# include "rtpenc_chain.h"
# include "url.h"
# include "url.h"
# include "rtpenc.h"
//#define DEBUG
//#define DEBUG
@ -56,6 +57,36 @@
# define SDP_MAX_SIZE 16384
# define SDP_MAX_SIZE 16384
# define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH
# define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH
# define OFFSET(x) offsetof(RTSPState, x)
# define DEC AV_OPT_FLAG_DECODING_PARAM
# define ENC AV_OPT_FLAG_ENCODING_PARAM
# define RTSP_FLAG_OPTS(name, longname) \
{ name , longname , OFFSET ( rtsp_flags ) , AV_OPT_TYPE_FLAGS , { 0 } , INT_MIN , INT_MAX , DEC , " rtsp_flags " } , \
{ " filter_src " , " Only receive packets from the negotiated peer IP " , 0 , AV_OPT_TYPE_CONST , { RTSP_FLAG_FILTER_SRC } , 0 , 0 , DEC , " rtsp_flags " }
const AVOption ff_rtsp_options [ ] = {
{ " initial_pause " , " Don't start playing the stream immediately " , OFFSET ( initial_pause ) , AV_OPT_TYPE_INT , { 0 } , 0 , 1 , DEC } ,
FF_RTP_FLAG_OPTS ( RTSPState , rtp_muxer_flags ) ,
{ " rtsp_transport " , " RTSP transport protocols " , OFFSET ( lower_transport_mask ) , AV_OPT_TYPE_FLAGS , { 0 } , INT_MIN , INT_MAX , DEC | ENC , " rtsp_transport " } , \
{ " udp " , " UDP " , 0 , AV_OPT_TYPE_CONST , { 1 < < RTSP_LOWER_TRANSPORT_UDP } , 0 , 0 , DEC | ENC , " rtsp_transport " } , \
{ " tcp " , " TCP " , 0 , AV_OPT_TYPE_CONST , { 1 < < RTSP_LOWER_TRANSPORT_TCP } , 0 , 0 , DEC | ENC , " rtsp_transport " } , \
{ " udp_multicast " , " UDP multicast " , 0 , AV_OPT_TYPE_CONST , { 1 < < RTSP_LOWER_TRANSPORT_UDP_MULTICAST } , 0 , 0 , DEC , " rtsp_transport " } ,
{ " http " , " HTTP tunneling " , 0 , AV_OPT_TYPE_CONST , { ( 1 < < RTSP_LOWER_TRANSPORT_HTTP ) } , 0 , 0 , DEC , " rtsp_transport " } ,
RTSP_FLAG_OPTS ( " rtsp_flags " , " RTSP flags " ) ,
{ NULL } ,
} ;
static const AVOption sdp_options [ ] = {
RTSP_FLAG_OPTS ( " sdp_flags " , " SDP flags " ) ,
{ NULL } ,
} ;
static const AVOption rtp_options [ ] = {
RTSP_FLAG_OPTS ( " rtp_flags " , " RTP flags " ) ,
{ NULL } ,
} ;
static void get_word_until_chars ( char * buf , int buf_size ,
static void get_word_until_chars ( char * buf , int buf_size ,
const char * sep , const char * * pp )
const char * sep , const char * * pp )
{
{
@ -1218,7 +1249,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
case RTSP_LOWER_TRANSPORT_UDP : {
case RTSP_LOWER_TRANSPORT_UDP : {
char url [ 1024 ] , options [ 30 ] = " " ;
char url [ 1024 ] , options [ 30 ] = " " ;
if ( rt - > filter_source )
if ( rt - > rtsp_flags & RTSP_FLAG_FILTER_SRC )
av_strlcpy ( options , " ?connect=1 " , sizeof ( options ) ) ;
av_strlcpy ( options , " ?connect=1 " , sizeof ( options ) ) ;
/* Use source address if specified */
/* Use source address if specified */
if ( reply - > transports [ 0 ] . source [ 0 ] ) {
if ( reply - > transports [ 0 ] . source [ 0 ] ) {
@ -1308,8 +1339,17 @@ int ff_rtsp_connect(AVFormatContext *s)
if ( ! ff_network_init ( ) )
if ( ! ff_network_init ( ) )
return AVERROR ( EIO ) ;
return AVERROR ( EIO ) ;
redirect :
rt - > control_transport = RTSP_MODE_PLAIN ;
rt - > control_transport = RTSP_MODE_PLAIN ;
if ( rt - > lower_transport_mask & ( 1 < < RTSP_LOWER_TRANSPORT_HTTP ) ) {
rt - > lower_transport_mask = 1 < < RTSP_LOWER_TRANSPORT_TCP ;
rt - > control_transport = RTSP_MODE_TUNNEL ;
}
/* Only pass through valid flags from here */
rt - > lower_transport_mask & = ( 1 < < RTSP_LOWER_TRANSPORT_NB ) - 1 ;
redirect :
lower_transport_mask = rt - > lower_transport_mask ;
/* extract hostname and port */
/* extract hostname and port */
av_url_split ( NULL , 0 , auth , sizeof ( auth ) ,
av_url_split ( NULL , 0 , auth , sizeof ( auth ) ,
host , sizeof ( host ) , & port , path , sizeof ( path ) , s - > filename ) ;
host , sizeof ( host ) , & port , path , sizeof ( path ) , s - > filename ) ;
@ -1319,6 +1359,7 @@ redirect:
if ( port < 0 )
if ( port < 0 )
port = RTSP_DEFAULT_PORT ;
port = RTSP_DEFAULT_PORT ;
# if FF_API_RTSP_URL_OPTIONS
/* search for options */
/* search for options */
option_list = strrchr ( path , ' ? ' ) ;
option_list = strrchr ( path , ' ? ' ) ;
if ( option_list ) {
if ( option_list ) {
@ -1326,6 +1367,7 @@ redirect:
* the options back into the same string . */
* the options back into the same string . */
filename = option_list ;
filename = option_list ;
while ( option_list ) {
while ( option_list ) {
int handled = 1 ;
/* move the option pointer */
/* move the option pointer */
option = + + option_list ;
option = + + option_list ;
option_list = strchr ( option_list , ' & ' ) ;
option_list = strchr ( option_list , ' & ' ) ;
@ -1343,7 +1385,7 @@ redirect:
lower_transport_mask | = ( 1 < < RTSP_LOWER_TRANSPORT_TCP ) ;
lower_transport_mask | = ( 1 < < RTSP_LOWER_TRANSPORT_TCP ) ;
rt - > control_transport = RTSP_MODE_TUNNEL ;
rt - > control_transport = RTSP_MODE_TUNNEL ;
} else if ( ! strcmp ( option , " filter_src " ) ) {
} else if ( ! strcmp ( option , " filter_src " ) ) {
rt - > filter_source = 1 ;
rt - > rtsp_flags | = RTSP_FLAG_FILTER_SRC ;
} else {
} else {
/* Write options back into the buffer, using memmove instead
/* Write options back into the buffer, using memmove instead
* of strcpy since the strings may overlap . */
* of strcpy since the strings may overlap . */
@ -1351,10 +1393,16 @@ redirect:
memmove ( + + filename , option , len ) ;
memmove ( + + filename , option , len ) ;
filename + = len ;
filename + = len ;
if ( option_list ) * filename = ' & ' ;
if ( option_list ) * filename = ' & ' ;
handled = 0 ;
}
}
if ( handled )
av_log ( s , AV_LOG_WARNING , " Options passed via URL are "
" deprecated, use -rtsp_transport "
" and -rtsp_flags instead. \n " ) ;
}
}
* filename = 0 ;
* filename = 0 ;
}
}
# endif
if ( ! lower_transport_mask )
if ( ! lower_transport_mask )
lower_transport_mask = ( 1 < < RTSP_LOWER_TRANSPORT_NB ) - 1 ;
lower_transport_mask = ( 1 < < RTSP_LOWER_TRANSPORT_NB ) - 1 ;
@ -1797,8 +1845,9 @@ static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap)
namebuf , sizeof ( namebuf ) , NULL , 0 , NI_NUMERICHOST ) ;
namebuf , sizeof ( namebuf ) , NULL , 0 , NI_NUMERICHOST ) ;
ff_url_join ( url , sizeof ( url ) , " rtp " , NULL ,
ff_url_join ( url , sizeof ( url ) , " rtp " , NULL ,
namebuf , rtsp_st - > sdp_port ,
namebuf , rtsp_st - > sdp_port ,
" ?localport=%d&ttl=%d " , rtsp_st - > sdp_port ,
" ?localport=%d&ttl=%d&connect=%d " , rtsp_st - > sdp_port ,
rtsp_st - > sdp_ttl ) ;
rtsp_st - > sdp_ttl ,
rt - > rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0 ) ;
if ( ffurl_open ( & rtsp_st - > rtp_handle , url , AVIO_FLAG_READ_WRITE ) < 0 ) {
if ( ffurl_open ( & rtsp_st - > rtp_handle , url , AVIO_FLAG_READ_WRITE ) < 0 ) {
err = AVERROR_INVALIDDATA ;
err = AVERROR_INVALIDDATA ;
goto fail ;
goto fail ;
@ -1820,6 +1869,13 @@ static int sdp_read_close(AVFormatContext *s)
return 0 ;
return 0 ;
}
}
static const AVClass sdp_demuxer_class = {
. class_name = " SDP demuxer " ,
. item_name = av_default_item_name ,
. option = sdp_options ,
. version = LIBAVUTIL_VERSION_INT ,
} ;
AVInputFormat ff_sdp_demuxer = {
AVInputFormat ff_sdp_demuxer = {
. name = " sdp " ,
. name = " sdp " ,
. long_name = NULL_IF_CONFIG_SMALL ( " SDP " ) ,
. long_name = NULL_IF_CONFIG_SMALL ( " SDP " ) ,
@ -1828,6 +1884,7 @@ AVInputFormat ff_sdp_demuxer = {
. read_header = sdp_read_header ,
. read_header = sdp_read_header ,
. read_packet = ff_rtsp_fetch_packet ,
. read_packet = ff_rtsp_fetch_packet ,
. read_close = sdp_read_close ,
. read_close = sdp_read_close ,
. priv_class = & sdp_demuxer_class
} ;
} ;
# endif /* CONFIG_SDP_DEMUXER */
# endif /* CONFIG_SDP_DEMUXER */
@ -1924,6 +1981,13 @@ fail:
return ret ;
return ret ;
}
}
static const AVClass rtp_demuxer_class = {
. class_name = " RTP demuxer " ,
. item_name = av_default_item_name ,
. option = rtp_options ,
. version = LIBAVUTIL_VERSION_INT ,
} ;
AVInputFormat ff_rtp_demuxer = {
AVInputFormat ff_rtp_demuxer = {
. name = " rtp " ,
. name = " rtp " ,
. long_name = NULL_IF_CONFIG_SMALL ( " RTP input format " ) ,
. long_name = NULL_IF_CONFIG_SMALL ( " RTP input format " ) ,
@ -1933,6 +1997,7 @@ AVInputFormat ff_rtp_demuxer = {
. read_packet = ff_rtsp_fetch_packet ,
. read_packet = ff_rtsp_fetch_packet ,
. read_close = sdp_read_close ,
. read_close = sdp_read_close ,
. flags = AVFMT_NOFILE ,
. flags = AVFMT_NOFILE ,
. priv_class = & rtp_demuxer_class
} ;
} ;
# endif /* CONFIG_RTP_DEMUXER */
# endif /* CONFIG_RTP_DEMUXER */