@ -378,6 +378,27 @@ static int udp_get_file_handle(URLContext *h)
return s - > udp_fd ;
}
static int parse_source_list ( char * buf , char * * sources , int * num_sources ,
int max_sources )
{
char * source_start ;
source_start = buf ;
while ( 1 ) {
char * next = strchr ( source_start , ' , ' ) ;
if ( next )
* next = ' \0 ' ;
sources [ * num_sources ] = av_strdup ( source_start ) ;
if ( ! sources [ * num_sources ] )
return AVERROR ( ENOMEM ) ;
source_start = next + 1 ;
( * num_sources ) + + ;
if ( * num_sources > = max_sources | | ! next )
break ;
}
return 0 ;
}
/* put it in UDP context */
/* return non zero if error */
static int udp_open ( URLContext * h , const char * uri , int flags )
@ -391,8 +412,8 @@ static int udp_open(URLContext *h, const char *uri, int flags)
struct sockaddr_storage my_addr ;
socklen_t len ;
int reuse_specified = 0 ;
int i , include = 0 , num_sources = 0 ;
char * sources [ 32 ] ;
int i , num_ include_sources = 0 , num_exclude _sources = 0 ;
char * include_sources [ 32 ] , * exclude_ sources[ 32 ] ;
h - > is_streamed = 1 ;
h - > max_packet_size = 1472 ;
@ -430,24 +451,15 @@ static int udp_open(URLContext *h, const char *uri, int flags)
if ( av_find_info_tag ( buf , sizeof ( buf ) , " localaddr " , p ) ) {
av_strlcpy ( localaddr , buf , sizeof ( localaddr ) ) ;
}
if ( av_find_info_tag ( buf , sizeof ( buf ) , " sources " , p ) )
include = 1 ;
if ( include | | av_find_info_tag ( buf , sizeof ( buf ) , " block " , p ) ) {
char * source_start ;
source_start = buf ;
while ( 1 ) {
char * next = strchr ( source_start , ' , ' ) ;
if ( next )
* next = ' \0 ' ;
sources [ num_sources ] = av_strdup ( source_start ) ;
if ( ! sources [ num_sources ] )
goto fail ;
source_start = next + 1 ;
num_sources + + ;
if ( num_sources > = FF_ARRAY_ELEMS ( sources ) | | ! next )
break ;
}
if ( av_find_info_tag ( buf , sizeof ( buf ) , " sources " , p ) ) {
if ( parse_source_list ( buf , include_sources , & num_include_sources ,
FF_ARRAY_ELEMS ( include_sources ) ) )
goto fail ;
}
if ( av_find_info_tag ( buf , sizeof ( buf ) , " block " , p ) ) {
if ( parse_source_list ( buf , exclude_sources , & num_exclude_sources ,
FF_ARRAY_ELEMS ( exclude_sources ) ) )
goto fail ;
}
}
@ -506,20 +518,20 @@ static int udp_open(URLContext *h, const char *uri, int flags)
}
if ( h - > flags & AVIO_FLAG_READ ) {
/* input */
if ( num_sources = = 0 | | ! include ) {
if ( num_include_sources & & num_exclude_sources ) {
av_log ( h , AV_LOG_ERROR , " Simultaneously including and excluding multicast sources is not supported \n " ) ;
goto fail ;
}
if ( num_include_sources ) {
if ( udp_set_multicast_sources ( udp_fd , ( struct sockaddr * ) & s - > dest_addr , s - > dest_addr_len , include_sources , num_include_sources , 1 ) < 0 )
goto fail ;
} else {
if ( udp_join_multicast_group ( udp_fd , ( struct sockaddr * ) & s - > dest_addr ) < 0 )
goto fail ;
if ( num_sources ) {
if ( udp_set_multicast_sources ( udp_fd , ( struct sockaddr * ) & s - > dest_addr , s - > dest_addr_len , sources , num_sources , 0 ) < 0 )
goto fail ;
}
} else if ( include & & num_sources ) {
if ( udp_set_multicast_sources ( udp_fd , ( struct sockaddr * ) & s - > dest_addr , s - > dest_addr_len , sources , num_sources , 1 ) < 0 )
}
if ( num_exclude_sources ) {
if ( udp_set_multicast_sources ( udp_fd , ( struct sockaddr * ) & s - > dest_addr , s - > dest_addr_len , exclude_sources , num_exclude_sources , 0 ) < 0 )
goto fail ;
} else {
av_log ( NULL , AV_LOG_ERROR , " invalid udp settings: inclusive multicast but no sources given \n " ) ;
goto fail ;
}
}
}
@ -548,16 +560,20 @@ static int udp_open(URLContext *h, const char *uri, int flags)
}
}
for ( i = 0 ; i < num_sources ; i + + )
av_free ( sources [ i ] ) ;
for ( i = 0 ; i < num_include_sources ; i + + )
av_freep ( & include_sources [ i ] ) ;
for ( i = 0 ; i < num_exclude_sources ; i + + )
av_freep ( & exclude_sources [ i ] ) ;
s - > udp_fd = udp_fd ;
return 0 ;
fail :
if ( udp_fd > = 0 )
closesocket ( udp_fd ) ;
for ( i = 0 ; i < num_sources ; i + + )
av_free ( sources [ i ] ) ;
for ( i = 0 ; i < num_include_sources ; i + + )
av_freep ( & include_sources [ i ] ) ;
for ( i = 0 ; i < num_exclude_sources ; i + + )
av_freep ( & exclude_sources [ i ] ) ;
return AVERROR ( EIO ) ;
}